Add mnt_noasync counter to better handle interleaved calls to nmount(),
sync() and sync_fsync() without losing MNT_ASYNC. Add MNTK_ASYNC flag which is set only when MNT_ASYNC is set and mnt_noasync is zero, and check that flag instead of MNT_ASYNC before initiating async io.
This commit is contained in:
parent
cea9d840d8
commit
a1e363f256
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=162649
@ -147,7 +147,7 @@ struct indir {
|
||||
|
||||
/* Determine if soft dependencies are being done */
|
||||
#define DOINGSOFTDEP(vp) ((vp)->v_mount->mnt_flag & MNT_SOFTDEP)
|
||||
#define DOINGASYNC(vp) ((vp)->v_mount->mnt_flag & MNT_ASYNC)
|
||||
#define DOINGASYNC(vp) ((vp)->v_mount->mnt_kern_flag & MNTK_ASYNC)
|
||||
|
||||
/* This overlays the fid structure (see mount.h). */
|
||||
struct ufid {
|
||||
|
@ -92,7 +92,7 @@ ext2_update(vp, waitfor)
|
||||
}
|
||||
ext2_i2ei(ip, (struct ext2_inode *)((char *)bp->b_data +
|
||||
EXT2_INODE_SIZE * ino_to_fsbo(fs, ip->i_number)));
|
||||
if (waitfor && (vp->v_mount->mnt_flag & MNT_ASYNC) == 0)
|
||||
if (waitfor && (vp->v_mount->mnt_kern_flag & MNTK_ASYNC) == 0)
|
||||
return (bwrite(bp));
|
||||
else {
|
||||
bdwrite(bp);
|
||||
|
@ -595,7 +595,7 @@ cluster_write(struct vnode *vp, struct buf *bp, u_quad_t filesize, int seqcount)
|
||||
int async;
|
||||
|
||||
if (vp->v_type == VREG) {
|
||||
async = vp->v_mount->mnt_flag & MNT_ASYNC;
|
||||
async = vp->v_mount->mnt_kern_flag & MNTK_ASYNC;
|
||||
lblocksize = vp->v_mount->mnt_stat.f_iosize;
|
||||
} else {
|
||||
async = 0;
|
||||
|
@ -122,7 +122,6 @@ sync(td, uap)
|
||||
{
|
||||
struct mount *mp, *nmp;
|
||||
int vfslocked;
|
||||
int asyncflag;
|
||||
|
||||
mtx_lock(&mountlist_mtx);
|
||||
for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
|
||||
@ -134,13 +133,16 @@ sync(td, uap)
|
||||
if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
|
||||
vn_start_write(NULL, &mp, V_NOWAIT) == 0) {
|
||||
MNT_ILOCK(mp);
|
||||
asyncflag = mp->mnt_flag & MNT_ASYNC;
|
||||
mp->mnt_flag &= ~MNT_ASYNC;
|
||||
mp->mnt_noasync++;
|
||||
mp->mnt_kern_flag &= ~MNTK_ASYNC;
|
||||
MNT_IUNLOCK(mp);
|
||||
vfs_msync(mp, MNT_NOWAIT);
|
||||
VFS_SYNC(mp, MNT_NOWAIT, td);
|
||||
MNT_ILOCK(mp);
|
||||
mp->mnt_flag |= asyncflag;
|
||||
mp->mnt_noasync--;
|
||||
if ((mp->mnt_flag & MNT_ASYNC) != 0 &&
|
||||
mp->mnt_noasync == 0)
|
||||
mp->mnt_kern_flag |= MNTK_ASYNC;
|
||||
MNT_IUNLOCK(mp);
|
||||
vn_finished_write(mp);
|
||||
}
|
||||
|
@ -946,6 +946,8 @@ vfs_domount(
|
||||
mp->mnt_flag |= MNT_RDONLY;
|
||||
mp->mnt_flag &=~ MNT_UPDATEMASK;
|
||||
mp->mnt_flag |= fsflags & (MNT_UPDATEMASK | MNT_FORCE | MNT_ROOTFS);
|
||||
if ((mp->mnt_flag & MNT_ASYNC) == 0)
|
||||
mp->mnt_kern_flag &= ~MNTK_ASYNC;
|
||||
MNT_IUNLOCK(mp);
|
||||
/*
|
||||
* Mount the filesystem.
|
||||
@ -981,6 +983,10 @@ vfs_domount(
|
||||
~(MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_SNAPSHOT);
|
||||
if (error)
|
||||
mp->mnt_flag = flag;
|
||||
if ((mp->mnt_flag & MNT_ASYNC) != 0 && mp->mnt_noasync == 0)
|
||||
mp->mnt_kern_flag |= MNTK_ASYNC;
|
||||
else
|
||||
mp->mnt_kern_flag &= ~MNTK_ASYNC;
|
||||
MNT_IUNLOCK(mp);
|
||||
if ((mp->mnt_flag & MNT_RDONLY) == 0) {
|
||||
if (mp->mnt_syncer == NULL)
|
||||
@ -997,6 +1003,12 @@ vfs_domount(
|
||||
vrele(vp);
|
||||
return (error);
|
||||
}
|
||||
MNT_ILOCK(mp);
|
||||
if ((mp->mnt_flag & MNT_ASYNC) != 0 && mp->mnt_noasync == 0)
|
||||
mp->mnt_kern_flag |= MNTK_ASYNC;
|
||||
else
|
||||
mp->mnt_kern_flag &= ~MNTK_ASYNC;
|
||||
MNT_IUNLOCK(mp);
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
|
||||
/*
|
||||
* Put the new filesystem on the mount list after root.
|
||||
@ -1196,6 +1208,7 @@ dounmount(mp, flags, td)
|
||||
MNT_ILOCK(mp);
|
||||
async_flag = mp->mnt_flag & MNT_ASYNC;
|
||||
mp->mnt_flag &= ~MNT_ASYNC;
|
||||
mp->mnt_kern_flag &= ~MNTK_ASYNC;
|
||||
MNT_IUNLOCK(mp);
|
||||
cache_purgevfs(mp); /* remove cache entries for this file sys */
|
||||
if (mp->mnt_syncer != NULL)
|
||||
@ -1238,6 +1251,8 @@ dounmount(mp, flags, td)
|
||||
MNT_ILOCK(mp);
|
||||
mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
|
||||
mp->mnt_flag |= async_flag;
|
||||
if ((mp->mnt_flag & MNT_ASYNC) != 0 && mp->mnt_noasync == 0)
|
||||
mp->mnt_kern_flag |= MNTK_ASYNC;
|
||||
lockmgr(&mp->mnt_lock, LK_RELEASE, NULL, td);
|
||||
if (mp->mnt_kern_flag & MNTK_MWAIT)
|
||||
wakeup(mp);
|
||||
|
@ -3051,7 +3051,7 @@ sync_fsync(struct vop_fsync_args *ap)
|
||||
struct vnode *syncvp = ap->a_vp;
|
||||
struct mount *mp = syncvp->v_mount;
|
||||
struct thread *td = ap->a_td;
|
||||
int error, asyncflag;
|
||||
int error;
|
||||
struct bufobj *bo;
|
||||
|
||||
/*
|
||||
@ -3082,14 +3082,15 @@ sync_fsync(struct vop_fsync_args *ap)
|
||||
return (0);
|
||||
}
|
||||
MNT_ILOCK(mp);
|
||||
asyncflag = mp->mnt_flag & MNT_ASYNC;
|
||||
mp->mnt_flag &= ~MNT_ASYNC;
|
||||
mp->mnt_noasync++;
|
||||
mp->mnt_kern_flag &= ~MNTK_ASYNC;
|
||||
MNT_IUNLOCK(mp);
|
||||
vfs_msync(mp, MNT_NOWAIT);
|
||||
error = VFS_SYNC(mp, MNT_LAZY, td);
|
||||
MNT_ILOCK(mp);
|
||||
if (asyncflag)
|
||||
mp->mnt_flag |= MNT_ASYNC;
|
||||
mp->mnt_noasync--;
|
||||
if ((mp->mnt_flag & MNT_ASYNC) != 0 && mp->mnt_noasync == 0)
|
||||
mp->mnt_kern_flag |= MNTK_ASYNC;
|
||||
MNT_IUNLOCK(mp);
|
||||
vn_finished_write(mp);
|
||||
vfs_unbusy(mp, td);
|
||||
|
@ -122,7 +122,6 @@ sync(td, uap)
|
||||
{
|
||||
struct mount *mp, *nmp;
|
||||
int vfslocked;
|
||||
int asyncflag;
|
||||
|
||||
mtx_lock(&mountlist_mtx);
|
||||
for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
|
||||
@ -134,13 +133,16 @@ sync(td, uap)
|
||||
if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
|
||||
vn_start_write(NULL, &mp, V_NOWAIT) == 0) {
|
||||
MNT_ILOCK(mp);
|
||||
asyncflag = mp->mnt_flag & MNT_ASYNC;
|
||||
mp->mnt_flag &= ~MNT_ASYNC;
|
||||
mp->mnt_noasync++;
|
||||
mp->mnt_kern_flag &= ~MNTK_ASYNC;
|
||||
MNT_IUNLOCK(mp);
|
||||
vfs_msync(mp, MNT_NOWAIT);
|
||||
VFS_SYNC(mp, MNT_NOWAIT, td);
|
||||
MNT_ILOCK(mp);
|
||||
mp->mnt_flag |= asyncflag;
|
||||
mp->mnt_noasync--;
|
||||
if ((mp->mnt_flag & MNT_ASYNC) != 0 &&
|
||||
mp->mnt_noasync == 0)
|
||||
mp->mnt_kern_flag |= MNTK_ASYNC;
|
||||
MNT_IUNLOCK(mp);
|
||||
vn_finished_write(mp);
|
||||
}
|
||||
|
@ -1223,7 +1223,7 @@ nfs_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
|
||||
tsiz -= len;
|
||||
}
|
||||
nfsmout:
|
||||
if (vp->v_mount->mnt_flag & MNT_ASYNC)
|
||||
if (vp->v_mount->mnt_kern_flag & MNTK_ASYNC)
|
||||
committed = NFSV3WRITE_FILESYNC;
|
||||
*iomode = committed;
|
||||
if (error)
|
||||
|
@ -157,6 +157,7 @@ struct mount {
|
||||
int mnt_writeopcount; /* (i) write syscalls pending */
|
||||
int mnt_kern_flag; /* (i) kernel only flags */
|
||||
u_int mnt_flag; /* (i) flags shared with user */
|
||||
u_int mnt_noasync; /* (i) # noasync overrides */
|
||||
struct vfsoptlist *mnt_opt; /* current mount options */
|
||||
struct vfsoptlist *mnt_optnew; /* new options passed to fs */
|
||||
int mnt_maxsymlinklen; /* max size of short symlink */
|
||||
@ -303,6 +304,7 @@ void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp);
|
||||
* with the unmount attempt (used by NFS).
|
||||
*/
|
||||
#define MNTK_UNMOUNTF 0x00000001 /* forced unmount in progress */
|
||||
#define MNTK_ASYNC 0x00000002 /* filtered async flag */
|
||||
#define MNTK_UNMOUNT 0x01000000 /* unmount in progress */
|
||||
#define MNTK_MWAIT 0x02000000 /* waiting for unmount to finish */
|
||||
#define MNTK_SUSPEND 0x08000000 /* request write suspension */
|
||||
|
@ -166,7 +166,7 @@ struct indir {
|
||||
|
||||
/* Determine if soft dependencies are being done */
|
||||
#define DOINGSOFTDEP(vp) ((vp)->v_mount->mnt_flag & MNT_SOFTDEP)
|
||||
#define DOINGASYNC(vp) ((vp)->v_mount->mnt_flag & MNT_ASYNC)
|
||||
#define DOINGASYNC(vp) ((vp)->v_mount->mnt_kern_flag & MNTK_ASYNC)
|
||||
|
||||
/* This overlays the fid structure (see mount.h). */
|
||||
struct ufid {
|
||||
|
Loading…
Reference in New Issue
Block a user