summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authortegge <tegge@FreeBSD.org>2006-09-26 04:12:49 +0000
committertegge <tegge@FreeBSD.org>2006-09-26 04:12:49 +0000
commit83154f853d9ca39deb1add01e032aff1f0678514 (patch)
treeac46e0b5a80f88127d3d14dc940a5f2746573c00 /sys
parentd7fe3e736512a1dd37a985037184eecf7df1f26d (diff)
downloadFreeBSD-src-83154f853d9ca39deb1add01e032aff1f0678514.zip
FreeBSD-src-83154f853d9ca39deb1add01e032aff1f0678514.tar.gz
Use mount interlock to protect all changes to mnt_flag and mnt_kern_flag.
This eliminates a race where MNT_UPDATE flag could be lost when nmount() raced against sync(), sync_fsync() or quotactl().
Diffstat (limited to 'sys')
-rw-r--r--sys/fs/cd9660/cd9660_vfsops.c6
-rw-r--r--sys/fs/devfs/devfs_vfsops.c2
-rw-r--r--sys/fs/hpfs/hpfs_vfsops.c4
-rw-r--r--sys/fs/msdosfs/msdosfs_vfsops.c4
-rw-r--r--sys/fs/ntfs/ntfs_vfsops.c4
-rw-r--r--sys/fs/nullfs/null_vfsops.c7
-rw-r--r--sys/fs/nwfs/nwfs_vfsops.c2
-rw-r--r--sys/fs/portalfs/portal_vfsops.c2
-rw-r--r--sys/fs/smbfs/smbfs_vfsops.c2
-rw-r--r--sys/fs/udf/udf_vfsops.c6
-rw-r--r--sys/fs/umapfs/umap_vfsops.c5
-rw-r--r--sys/fs/unionfs/union_vfsops.c9
-rw-r--r--sys/gnu/fs/ext2fs/ext2_vfsops.c6
-rw-r--r--sys/gnu/fs/reiserfs/reiserfs_vfsops.c4
-rw-r--r--sys/isofs/cd9660/cd9660_vfsops.c6
-rw-r--r--sys/kern/uipc_mqueue.c2
-rw-r--r--sys/kern/vfs_export.c10
-rw-r--r--sys/kern/vfs_extattr.c4
-rw-r--r--sys/kern/vfs_mount.c13
-rw-r--r--sys/kern/vfs_subr.c4
-rw-r--r--sys/kern/vfs_syscalls.c4
-rw-r--r--sys/nfsclient/nfs_vfsops.c16
-rw-r--r--sys/sys/mount.h2
-rw-r--r--sys/ufs/ffs/ffs_snapshot.c7
-rw-r--r--sys/ufs/ffs/ffs_softdep.c2
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c56
-rw-r--r--sys/ufs/ufs/ufs_quota.c7
27 files changed, 174 insertions, 22 deletions
diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c
index 30aba51..9a5e836 100644
--- a/sys/fs/cd9660/cd9660_vfsops.c
+++ b/sys/fs/cd9660/cd9660_vfsops.c
@@ -137,7 +137,9 @@ cd9660_mount(struct mount *mp, struct thread *td)
/*
* Unconditionally mount as read-only.
*/
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_RDONLY;
+ MNT_IUNLOCK(mp);
fspec = vfs_getopts(mp->mnt_optnew, "from", &error);
if (error)
@@ -378,7 +380,9 @@ iso_mountfs(devvp, mp, td)
mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
mp->mnt_maxsymlinklen = 0;
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
+ MNT_IUNLOCK(mp);
isomp->im_mountp = mp;
isomp->im_dev = dev;
isomp->im_devvp = devvp;
@@ -528,7 +532,9 @@ cd9660_unmount(mp, mntflags, td)
vrele(isomp->im_devvp);
free((caddr_t)isomp, M_ISOFSMNT);
mp->mnt_data = (qaddr_t)0;
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_LOCAL;
+ MNT_IUNLOCK(mp);
return (error);
}
diff --git a/sys/fs/devfs/devfs_vfsops.c b/sys/fs/devfs/devfs_vfsops.c
index 8c1069a..f3a364b 100644
--- a/sys/fs/devfs/devfs_vfsops.c
+++ b/sys/fs/devfs/devfs_vfsops.c
@@ -79,11 +79,13 @@ devfs_mount(struct mount *mp, struct thread *td)
sx_init(&fmp->dm_lock, "devfsmount");
fmp->dm_holdcnt = 1;
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_kern_flag |= MNTK_MPSAFE;
#ifdef MAC
mp->mnt_flag |= MNT_MULTILABEL;
#endif
+ MNT_IUNLOCK(mp);
fmp->dm_mount = mp;
mp->mnt_data = (void *) fmp;
vfs_getnewfsid(mp);
diff --git a/sys/fs/hpfs/hpfs_vfsops.c b/sys/fs/hpfs/hpfs_vfsops.c
index cc43fe6..92735ec 100644
--- a/sys/fs/hpfs/hpfs_vfsops.c
+++ b/sys/fs/hpfs/hpfs_vfsops.c
@@ -315,7 +315,9 @@ hpfs_mountfs(devvp, mp, td)
mp->mnt_stat.f_fsid.val[0] = (long)dev2udev(dev);
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
mp->mnt_maxsymlinklen = 0;
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
+ MNT_IUNLOCK(mp);
return (0);
failed:
@@ -359,7 +361,9 @@ hpfs_unmount(
hpfs_cpdeinit(hpmp);
hpfs_bmdeinit(hpmp);
mp->mnt_data = (qaddr_t)0;
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_LOCAL;
+ MNT_IUNLOCK(mp);
FREE(hpmp, M_HPFSMNT);
return (0);
diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c
index a485632..c0963cb 100644
--- a/sys/fs/msdosfs/msdosfs_vfsops.c
+++ b/sys/fs/msdosfs/msdosfs_vfsops.c
@@ -706,7 +706,9 @@ mountmsdosfs(devvp, mp, td)
mp->mnt_data = (qaddr_t) pmp;
mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
+ MNT_IUNLOCK(mp);
#ifdef MSDOSFS_LARGE
msdosfs_fileno_init(mp);
@@ -798,7 +800,9 @@ msdosfs_unmount(mp, mntflags, td)
#endif
free(pmp, M_MSDOSFSMNT);
mp->mnt_data = (qaddr_t)0;
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_LOCAL;
+ MNT_IUNLOCK(mp);
return (error);
}
diff --git a/sys/fs/ntfs/ntfs_vfsops.c b/sys/fs/ntfs/ntfs_vfsops.c
index 31f1a0b..1f46d01 100644
--- a/sys/fs/ntfs/ntfs_vfsops.c
+++ b/sys/fs/ntfs/ntfs_vfsops.c
@@ -430,7 +430,9 @@ ntfs_mountfs(devvp, mp, td)
mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
mp->mnt_maxsymlinklen = 0;
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
+ MNT_IUNLOCK(mp);
return (0);
out1:
@@ -507,7 +509,9 @@ ntfs_unmount(
ntfs_u28_uninit(ntmp);
ntfs_82u_uninit(ntmp);
mp->mnt_data = (qaddr_t)0;
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_LOCAL;
+ MNT_IUNLOCK(mp);
FREE(ntmp->ntm_ad, M_NTFSMNT);
FREE(ntmp, M_NTFSMNT);
return (error);
diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c
index 505576b..125c67a 100644
--- a/sys/fs/nullfs/null_vfsops.c
+++ b/sys/fs/nullfs/null_vfsops.c
@@ -179,9 +179,14 @@ nullfs_mount(struct mount *mp, struct thread *td)
*/
VOP_UNLOCK(vp, 0, td);
- if (NULLVPTOLOWERVP(nullm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
+ if (NULLVPTOLOWERVP(nullm_rootvp)->v_mount->mnt_flag & MNT_LOCAL) {
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
+ MNT_IUNLOCK(mp);
+ }
+ MNT_ILOCK(mp);
mp->mnt_kern_flag |= lowerrootvp->v_mount->mnt_kern_flag & MNTK_MPSAFE;
+ MNT_IUNLOCK(mp);
mp->mnt_data = (qaddr_t) xmp;
vfs_getnewfsid(mp);
diff --git a/sys/fs/nwfs/nwfs_vfsops.c b/sys/fs/nwfs/nwfs_vfsops.c
index e1e4997..aad0b99 100644
--- a/sys/fs/nwfs/nwfs_vfsops.c
+++ b/sys/fs/nwfs/nwfs_vfsops.c
@@ -267,7 +267,9 @@ nwfs_unmount(struct mount *mp, int mntflags, struct thread *td)
if (nmp->m.flags & NWFS_MOUNT_HAVE_NLS)
free(nmp->m.nls.to_lower, M_NWFSDATA);
free(nmp, M_NWFSDATA);
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_LOCAL;
+ MNT_IUNLOCK(mp);
return (error);
}
diff --git a/sys/fs/portalfs/portal_vfsops.c b/sys/fs/portalfs/portal_vfsops.c
index ed2022e..db73ef0 100644
--- a/sys/fs/portalfs/portal_vfsops.c
+++ b/sys/fs/portalfs/portal_vfsops.c
@@ -146,7 +146,9 @@ portal_mount(struct mount *mp, struct thread *td)
fhold(fp);
fmp->pm_server = fp;
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
+ MNT_IUNLOCK(mp);
mp->mnt_data = (qaddr_t) fmp;
vfs_getnewfsid(mp);
diff --git a/sys/fs/smbfs/smbfs_vfsops.c b/sys/fs/smbfs/smbfs_vfsops.c
index 904835c..182ba2b 100644
--- a/sys/fs/smbfs/smbfs_vfsops.c
+++ b/sys/fs/smbfs/smbfs_vfsops.c
@@ -318,7 +318,9 @@ smbfs_unmount(struct mount *mp, int mntflags, struct thread *td)
#else
free(smp, M_SMBFSDATA);
#endif
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_LOCAL;
+ MNT_IUNLOCK(mp);
return error;
}
diff --git a/sys/fs/udf/udf_vfsops.c b/sys/fs/udf/udf_vfsops.c
index 706816e..672bdeb 100644
--- a/sys/fs/udf/udf_vfsops.c
+++ b/sys/fs/udf/udf_vfsops.c
@@ -201,7 +201,9 @@ udf_mount(struct mount *mp, struct thread *td)
/*
* Unconditionally mount as read-only.
*/
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_RDONLY;
+ MNT_IUNLOCK(mp);
/*
* No root filesystem support. Probably not a big deal, since the
@@ -341,7 +343,9 @@ udf_mountfs(struct vnode *devvp, struct mount *mp, struct thread *td) {
mp->mnt_data = (qaddr_t)udfmp;
mp->mnt_stat.f_fsid.val[0] = dev2udev(devvp->v_rdev);
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
+ MNT_IUNLOCK(mp);
udfmp->im_mountp = mp;
udfmp->im_dev = devvp->v_rdev;
udfmp->im_devvp = devvp;
@@ -532,7 +536,9 @@ udf_unmount(struct mount *mp, int mntflags, struct thread *td)
FREE(udfmp, M_UDFMOUNT);
mp->mnt_data = (qaddr_t)0;
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_LOCAL;
+ MNT_IUNLOCK(mp);
return (0);
}
diff --git a/sys/fs/umapfs/umap_vfsops.c b/sys/fs/umapfs/umap_vfsops.c
index 7d4d40c..a692998 100644
--- a/sys/fs/umapfs/umap_vfsops.c
+++ b/sys/fs/umapfs/umap_vfsops.c
@@ -216,8 +216,11 @@ umapfs_omount(mp, path, data, ndp, td)
umapm_rootvp = vp;
umapm_rootvp->v_vflag |= VV_ROOT;
amp->umapm_rootvp = umapm_rootvp;
- if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
+ if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL) {
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
+ MNT_IUNLOCK(mp);
+ }
mp->mnt_data = (qaddr_t) amp;
vfs_getnewfsid(mp);
diff --git a/sys/fs/unionfs/union_vfsops.c b/sys/fs/unionfs/union_vfsops.c
index 0a65ea7..1d0d58e 100644
--- a/sys/fs/unionfs/union_vfsops.c
+++ b/sys/fs/unionfs/union_vfsops.c
@@ -86,7 +86,9 @@ union_mount(mp, td)
/*
* Disable clustered write, otherwise system becomes unstable.
*/
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_NOCLUSTERW;
+ MNT_IUNLOCK(mp);
if (mp->mnt_flag & MNT_ROOTFS)
return (EOPNOTSUPP);
@@ -246,8 +248,11 @@ union_mount(mp, td)
if (um->um_op == UNMNT_ABOVE) {
if (((um->um_lowervp == NULLVP) ||
(um->um_lowervp->v_mount->mnt_flag & MNT_LOCAL)) &&
- (um->um_uppervp->v_mount->mnt_flag & MNT_LOCAL))
+ (um->um_uppervp->v_mount->mnt_flag & MNT_LOCAL)) {
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
+ MNT_IUNLOCK(mp);
+ }
}
/*
@@ -257,7 +262,9 @@ union_mount(mp, td)
* mount of the underlying filesystem to go from rdonly to rdwr
* will leave the unioned view as read-only.
*/
+ MNT_ILOCK(mp);
mp->mnt_flag |= (um->um_uppervp->v_mount->mnt_flag & MNT_RDONLY);
+ MNT_IUNLOCK(mp);
mp->mnt_data = (qaddr_t) um;
vfs_getnewfsid(mp);
diff --git a/sys/gnu/fs/ext2fs/ext2_vfsops.c b/sys/gnu/fs/ext2fs/ext2_vfsops.c
index 38f9e25..4fdc727 100644
--- a/sys/gnu/fs/ext2fs/ext2_vfsops.c
+++ b/sys/gnu/fs/ext2fs/ext2_vfsops.c
@@ -230,7 +230,9 @@ ext2_mount(mp, td)
fs->s_es->s_state &= ~EXT2_VALID_FS;
ext2_sbupdate(ump, MNT_WAIT);
fs->s_rd_only = 0;
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_RDONLY;
+ MNT_IUNLOCK(mp);
}
if (vfs_flagopt(opts, "export", NULL, 0)) {
/* Process export requests in vfs_mount.c. */
@@ -683,7 +685,9 @@ ext2_mountfs(devvp, mp, td)
mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
mp->mnt_maxsymlinklen = EXT2_MAXSYMLINKLEN;
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
+ MNT_IUNLOCK(mp);
ump->um_mountp = mp;
ump->um_dev = dev;
ump->um_devvp = devvp;
@@ -771,7 +775,9 @@ ext2_unmount(mp, mntflags, td)
bsd_free(fs, M_EXT2MNT);
bsd_free(ump, M_EXT2MNT);
mp->mnt_data = (qaddr_t)0;
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_LOCAL;
+ MNT_IUNLOCK(mp);
return (error);
}
diff --git a/sys/gnu/fs/reiserfs/reiserfs_vfsops.c b/sys/gnu/fs/reiserfs/reiserfs_vfsops.c
index b6436ae..066d5b2 100644
--- a/sys/gnu/fs/reiserfs/reiserfs_vfsops.c
+++ b/sys/gnu/fs/reiserfs/reiserfs_vfsops.c
@@ -241,7 +241,9 @@ reiserfs_unmount(struct mount *mp, int mntflags, struct thread *td)
}
mp->mnt_data = (qaddr_t)0;
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_LOCAL;
+ MNT_IUNLOCK(mp);
reiserfs_log(LOG_DEBUG, "done\n");
return (error);
@@ -624,7 +626,9 @@ reiserfs_mountfs(struct vnode *devvp, struct mount *mp, struct thread *td)
mp->mnt_data = (qaddr_t)rmp;
mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
+ MNT_IUNLOCK(mp);
#if defined(si_mountpoint)
devvp->v_rdev->si_mountpoint = mp;
#endif
diff --git a/sys/isofs/cd9660/cd9660_vfsops.c b/sys/isofs/cd9660/cd9660_vfsops.c
index 30aba51..9a5e836 100644
--- a/sys/isofs/cd9660/cd9660_vfsops.c
+++ b/sys/isofs/cd9660/cd9660_vfsops.c
@@ -137,7 +137,9 @@ cd9660_mount(struct mount *mp, struct thread *td)
/*
* Unconditionally mount as read-only.
*/
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_RDONLY;
+ MNT_IUNLOCK(mp);
fspec = vfs_getopts(mp->mnt_optnew, "from", &error);
if (error)
@@ -378,7 +380,9 @@ iso_mountfs(devvp, mp, td)
mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
mp->mnt_maxsymlinklen = 0;
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
+ MNT_IUNLOCK(mp);
isomp->im_mountp = mp;
isomp->im_dev = dev;
isomp->im_devvp = devvp;
@@ -528,7 +532,9 @@ cd9660_unmount(mp, mntflags, td)
vrele(isomp->im_devvp);
free((caddr_t)isomp, M_ISOFSMNT);
mp->mnt_data = (qaddr_t)0;
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_LOCAL;
+ MNT_IUNLOCK(mp);
return (error);
}
diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c
index e95f800..d6cf2e5 100644
--- a/sys/kern/uipc_mqueue.c
+++ b/sys/kern/uipc_mqueue.c
@@ -561,8 +561,10 @@ mqfs_mount(struct mount *mp, struct thread *td)
return (EOPNOTSUPP);
mp->mnt_data = &mqfs_data;
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_kern_flag |= MNTK_MPSAFE;
+ MNT_IUNLOCK(mp);
vfs_getnewfsid(mp);
sbp = &mp->mnt_stat;
diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c
index 5552845..00237b6 100644
--- a/sys/kern/vfs_export.c
+++ b/sys/kern/vfs_export.c
@@ -117,7 +117,9 @@ vfs_hang_addrlist(mp, nep, argp)
bcopy(argp->ex_anon.cr_groups, np->netc_anon.cr_groups,
sizeof(np->netc_anon.cr_groups));
refcount_init(&np->netc_anon.cr_ref, 1);
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_DEFEXPORTED;
+ MNT_IUNLOCK(mp);
return (0);
}
@@ -236,13 +238,17 @@ vfs_export(mp, argp)
return (ENOENT);
if (mp->mnt_flag & MNT_EXPUBLIC) {
vfs_setpublicfs(NULL, NULL, NULL);
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_EXPUBLIC;
+ MNT_IUNLOCK(mp);
}
vfs_free_addrlist(nep);
mp->mnt_export = NULL;
free(nep, M_MOUNT);
nep = NULL;
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~(MNT_EXPORTED | MNT_DEFEXPORTED);
+ MNT_IUNLOCK(mp);
}
if (argp->ex_flags & MNT_EXPORTED) {
if (nep == NULL) {
@@ -252,11 +258,15 @@ vfs_export(mp, argp)
if (argp->ex_flags & MNT_EXPUBLIC) {
if ((error = vfs_setpublicfs(mp, nep, argp)) != 0)
return (error);
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_EXPUBLIC;
+ MNT_IUNLOCK(mp);
}
if ((error = vfs_hang_addrlist(mp, nep, argp)))
return (error);
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_EXPORTED;
+ MNT_IUNLOCK(mp);
}
return (0);
}
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index cbef350..147b31e 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -133,11 +133,15 @@ sync(td, uap)
vfslocked = VFS_LOCK_GIANT(mp);
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;
+ MNT_IUNLOCK(mp);
vfs_msync(mp, MNT_NOWAIT);
VFS_SYNC(mp, MNT_NOWAIT, td);
+ MNT_ILOCK(mp);
mp->mnt_flag |= asyncflag;
+ MNT_IUNLOCK(mp);
vn_finished_write(mp);
}
VFS_UNLOCK_GIANT(vfslocked);
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 64c64c9..1e4cf6d 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -471,7 +471,9 @@ vfs_mount_alloc(struct vnode *vp, struct vfsconf *vfsp,
mp->mnt_vfc = vfsp;
vfsp->vfc_refcount++; /* XXX Unlocked */
mp->mnt_stat.f_type = vfsp->vfc_typenum;
+ MNT_ILOCK(mp);
mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
+ MNT_IUNLOCK(mp);
strlcpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
mp->mnt_vnodecovered = vp;
mp->mnt_cred = crdup(td->td_ucred);
@@ -848,6 +850,7 @@ vfs_domount(
return (EINVAL);
}
mp = vp->v_mount;
+ MNT_ILOCK(mp);
flag = mp->mnt_flag;
kern_flag = mp->mnt_kern_flag;
/*
@@ -856,9 +859,11 @@ vfs_domount(
*/
if ((fsflags & MNT_RELOAD) &&
((mp->mnt_flag & MNT_RDONLY) == 0)) {
+ MNT_IUNLOCK(mp);
vput(vp);
return (EOPNOTSUPP); /* Needs translation */
}
+ MNT_IUNLOCK(mp);
/*
* Only privileged root, or (if MNT_USER is set) the user that
* did the original mount is permitted to update it.
@@ -882,8 +887,10 @@ vfs_domount(
}
vp->v_iflag |= VI_MOUNT;
VI_UNLOCK(vp);
+ MNT_ILOCK(mp);
mp->mnt_flag |= fsflags &
(MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_SNAPSHOT | MNT_ROOTFS);
+ MNT_IUNLOCK(mp);
VOP_UNLOCK(vp, 0, td);
mp->mnt_optnew = fsdata;
vfs_mergeopts(mp->mnt_optnew, mp->mnt_opt);
@@ -935,10 +942,12 @@ vfs_domount(
/*
* Set the mount level flags.
*/
+ MNT_ILOCK(mp);
if (fsflags & MNT_RDONLY)
mp->mnt_flag |= MNT_RDONLY;
mp->mnt_flag &=~ MNT_UPDATEMASK;
mp->mnt_flag |= fsflags & (MNT_UPDATEMASK | MNT_FORCE | MNT_ROOTFS);
+ MNT_IUNLOCK(mp);
/*
* Mount the filesystem.
* XXX The final recipients of VFS_MOUNT just overwrite the ndp they
@@ -968,12 +977,14 @@ vfs_domount(
*/
mp->mnt_optnew = NULL;
if (mp->mnt_flag & MNT_UPDATE) {
+ MNT_ILOCK(mp);
mp->mnt_flag &=
~(MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_SNAPSHOT);
if (error) {
mp->mnt_flag = flag;
mp->mnt_kern_flag = kern_flag;
}
+ MNT_IUNLOCK(mp);
if ((mp->mnt_flag & MNT_RDONLY) == 0) {
if (mp->mnt_syncer == NULL)
error = vfs_allocate_syncvnode(mp);
@@ -1185,8 +1196,10 @@ dounmount(mp, flags, td)
vfs_setpublicfs(NULL, NULL, NULL);
vfs_msync(mp, MNT_WAIT);
+ MNT_ILOCK(mp);
async_flag = mp->mnt_flag & MNT_ASYNC;
mp->mnt_flag &= ~MNT_ASYNC;
+ MNT_IUNLOCK(mp);
cache_purgevfs(mp); /* remove cache entries for this file sys */
if (mp->mnt_syncer != NULL)
vrele(mp->mnt_syncer);
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 2903e7d..72c4b5c 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -3081,12 +3081,16 @@ sync_fsync(struct vop_fsync_args *ap)
vfs_unbusy(mp, td);
return (0);
}
+ MNT_ILOCK(mp);
asyncflag = mp->mnt_flag & MNT_ASYNC;
mp->mnt_flag &= ~MNT_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;
+ MNT_IUNLOCK(mp);
vn_finished_write(mp);
vfs_unbusy(mp, td);
return (error);
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index cbef350..147b31e 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -133,11 +133,15 @@ sync(td, uap)
vfslocked = VFS_LOCK_GIANT(mp);
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;
+ MNT_IUNLOCK(mp);
vfs_msync(mp, MNT_NOWAIT);
VFS_SYNC(mp, MNT_NOWAIT, td);
+ MNT_ILOCK(mp);
mp->mnt_flag |= asyncflag;
+ MNT_IUNLOCK(mp);
vn_finished_write(mp);
}
VFS_UNLOCK_GIANT(vfslocked);
diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c
index 480a5d6..69476bc 100644
--- a/sys/nfsclient/nfs_vfsops.c
+++ b/sys/nfsclient/nfs_vfsops.c
@@ -522,8 +522,10 @@ nfs_mountdiskless(char *path, int mountflag,
struct sockaddr *nam;
int error;
+ MNT_ILOCK(mp);
mp->mnt_kern_flag = 0;
mp->mnt_flag = mountflag;
+ MNT_IUNLOCK(mp);
nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
if ((error = mountnfs(args, mp, nam, path, vpp,
td->td_ucred)) != 0) {
@@ -548,10 +550,15 @@ nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp)
* flag is already clear, or this is a root mount and it was set
* intentionally at some previous point.
*/
- if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0)
+ if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_RDONLY;
- else if (mp->mnt_flag & MNT_UPDATE)
+ MNT_IUNLOCK(mp);
+ } else if (mp->mnt_flag & MNT_UPDATE) {
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_RDONLY;
+ MNT_IUNLOCK(mp);
+ }
/*
* Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
@@ -784,8 +791,11 @@ nfs_mount(struct mount *mp, struct thread *td)
args.fh = nfh;
error = mountnfs(&args, mp, nam, hst, &vp, td->td_ucred);
out:
- if (!error)
+ if (!error) {
+ MNT_ILOCK(mp);
mp->mnt_kern_flag |= (MNTK_MPSAFE|MNTK_LOOKUP_SHARED);
+ MNT_IUNLOCK(mp);
+ }
return (error);
}
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index 66e3ea6..c7e0db3 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -156,7 +156,7 @@ struct mount {
int mnt_nvnodelistsize; /* (i) # of vnodes */
int mnt_writeopcount; /* (i) write syscalls pending */
int mnt_kern_flag; /* (i) kernel only flags */
- u_int mnt_flag; /* flags shared with user */
+ u_int mnt_flag; /* (i) flags shared with user */
struct vfsoptlist *mnt_opt; /* current mount options */
struct vfsoptlist *mnt_optnew; /* new options passed to fs */
int mnt_maxsymlinklen; /* max size of short symlink */
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index b183569..f23f098 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -194,7 +194,7 @@ ffs_snapshot(mp, snapfile)
ufs2_daddr_t numblks, blkno, *blkp, *snapblklist;
int error, cg, snaploc;
int i, size, len, loc;
- int flag = mp->mnt_flag;
+ int flag;
struct timespec starttime = {0, 0}, endtime;
char saved_nice = 0;
long redo = 0, snaplistsize = 0;
@@ -216,6 +216,9 @@ ffs_snapshot(mp, snapfile)
ump = VFSTOUFS(mp);
fs = ump->um_fs;
sn = NULL;
+ MNT_ILOCK(mp);
+ flag = mp->mnt_flag;
+ MNT_IUNLOCK(mp);
/*
* Need to serialize access to snapshot code per filesystem.
@@ -828,7 +831,9 @@ out:
fs->fs_active = 0;
}
UFS_UNLOCK(ump);
+ MNT_ILOCK(mp);
mp->mnt_flag = flag;
+ MNT_IUNLOCK(mp);
if (error)
(void) ffs_truncate(vp, (off_t)0, 0, NOCRED, td);
(void) ffs_syncvnode(vp, MNT_WAIT);
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index d2f6015..6805563 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -1423,8 +1423,10 @@ softdep_mount(devvp, mp, fs, cred)
struct buf *bp;
int error, cyl;
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_ASYNC;
mp->mnt_flag |= MNT_SOFTDEP;
+ MNT_IUNLOCK(mp);
ump = VFSTOUFS(mp);
LIST_INIT(&ump->softdep_workitem_pending);
ump->softdep_worklist_tail = NULL;
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 0c12305..1c8c4d3 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -129,6 +129,7 @@ ffs_mount(struct mount *mp, struct thread *td)
struct ufsmount *ump = 0;
struct fs *fs;
int error, flags;
+ u_int mntorflags, mntandnotflags;
mode_t accessmode;
struct nameidata ndp;
char *fspec;
@@ -151,33 +152,38 @@ ffs_mount(struct mount *mp, struct thread *td)
if (error)
return (error);
+ mntorflags = 0;
+ mntandnotflags = 0;
if (vfs_getopt(mp->mnt_optnew, "acls", NULL, NULL) == 0)
- mp->mnt_flag |= MNT_ACLS;
+ mntorflags |= MNT_ACLS;
if (vfs_getopt(mp->mnt_optnew, "async", NULL, NULL) == 0)
- mp->mnt_flag |= MNT_ASYNC;
+ mntorflags |= MNT_ASYNC;
if (vfs_getopt(mp->mnt_optnew, "force", NULL, NULL) == 0)
- mp->mnt_flag |= MNT_FORCE;
+ mntorflags |= MNT_FORCE;
if (vfs_getopt(mp->mnt_optnew, "multilabel", NULL, NULL) == 0)
- mp->mnt_flag |= MNT_MULTILABEL;
+ mntorflags |= MNT_MULTILABEL;
if (vfs_getopt(mp->mnt_optnew, "noasync", NULL, NULL) == 0)
- mp->mnt_flag &= ~MNT_ASYNC;
+ mntandnotflags |= MNT_ASYNC;
if (vfs_getopt(mp->mnt_optnew, "noatime", NULL, NULL) == 0)
- mp->mnt_flag |= MNT_NOATIME;
+ mntorflags |= MNT_NOATIME;
if (vfs_getopt(mp->mnt_optnew, "noclusterr", NULL, NULL) == 0)
- mp->mnt_flag |= MNT_NOCLUSTERR;
+ mntorflags |= MNT_NOCLUSTERR;
if (vfs_getopt(mp->mnt_optnew, "noclusterw", NULL, NULL) == 0)
- mp->mnt_flag |= MNT_NOCLUSTERW;
+ mntorflags |= MNT_NOCLUSTERW;
if (vfs_getopt(mp->mnt_optnew, "snapshot", NULL, NULL) == 0)
- mp->mnt_flag |= MNT_SNAPSHOT;
+ mntorflags |= MNT_SNAPSHOT;
+ MNT_ILOCK(mp);
+ mp->mnt_flag = (mp->mnt_flag | mntorflags) & ~mntandnotflags;
+ MNT_IUNLOCK(mp);
/*
* If updating, check whether changing from read-only to
* read/write; if there is no device name, that's all we do.
@@ -237,7 +243,9 @@ ffs_mount(struct mount *mp, struct thread *td)
g_topology_unlock();
PICKUP_GIANT();
fs->fs_ronly = 1;
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_RDONLY;
+ MNT_IUNLOCK(mp);
}
if ((mp->mnt_flag & MNT_RELOAD) &&
(error = ffs_reload(mp, td)) != 0)
@@ -289,7 +297,9 @@ ffs_mount(struct mount *mp, struct thread *td)
if ((error = vn_start_write(NULL, &mp, V_WAIT)) != 0)
return (error);
fs->fs_ronly = 0;
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_RDONLY;
+ MNT_IUNLOCK(mp);
fs->fs_clean = 0;
if ((error = ffs_sbupdate(ump, MNT_WAIT, 0)) != 0) {
vn_finished_write(mp);
@@ -312,13 +322,21 @@ ffs_mount(struct mount *mp, struct thread *td)
* Softdep_mount() clears it in an initial mount
* or ro->rw remount.
*/
- if (mp->mnt_flag & MNT_SOFTDEP)
+ if (mp->mnt_flag & MNT_SOFTDEP) {
+ /* XXX: Reset too late ? */
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_ASYNC;
+ MNT_IUNLOCK(mp);
+ }
/*
* Keep MNT_ACLS flag if it is stored in superblock.
*/
- if ((fs->fs_flags & FS_ACLS) != 0)
+ if ((fs->fs_flags & FS_ACLS) != 0) {
+ /* XXX: Set too late ? */
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_ACLS;
+ MNT_IUNLOCK(mp);
+ }
/*
* If this is a snapshot request, take the snapshot.
@@ -745,23 +763,31 @@ ffs_mountfs(devvp, mp, td)
vfs_getnewfsid(mp);
}
mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
- if ((fs->fs_flags & FS_MULTILABEL) != 0)
+ MNT_IUNLOCK(mp);
+ if ((fs->fs_flags & FS_MULTILABEL) != 0) {
#ifdef MAC
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_MULTILABEL;
+ MNT_IUNLOCK(mp);
#else
printf(
"WARNING: %s: multilabel flag on fs but no MAC support\n",
mp->mnt_stat.f_mntonname);
#endif
- if ((fs->fs_flags & FS_ACLS) != 0)
+ }
+ if ((fs->fs_flags & FS_ACLS) != 0) {
#ifdef UFS_ACL
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_ACLS;
+ MNT_IUNLOCK(mp);
#else
printf(
"WARNING: %s: ACLs flag on fs but no ACLs support\n",
mp->mnt_stat.f_mntonname);
#endif
+ }
ump->um_mountp = mp;
ump->um_dev = dev;
ump->um_devvp = devvp;
@@ -825,7 +851,9 @@ ffs_mountfs(devvp, mp, td)
*/
devvp->v_bufobj.bo_flag |= BO_NEEDSGIANT;
#else
+ MNT_ILOCK(mp);
mp->mnt_kern_flag |= MNTK_MPSAFE;
+ MNT_IUNLOCK(mp);
#endif
return (0);
out:
@@ -1003,7 +1031,9 @@ ffs_unmount(mp, mntflags, td)
free(fs, M_UFSMNT);
free(ump, M_UFSMNT);
mp->mnt_data = (qaddr_t)0;
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_LOCAL;
+ MNT_IUNLOCK(mp);
return (error);
}
diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c
index 976fa71..81a1d0d 100644
--- a/sys/ufs/ufs/ufs_quota.c
+++ b/sys/ufs/ufs/ufs_quota.c
@@ -443,7 +443,9 @@ quotaon(td, mp, type, fname)
if (*vpp != vp)
quotaoff(td, mp, type);
ump->um_qflags[type] |= QTF_OPENING;
+ MNT_ILOCK(mp);
mp->mnt_flag |= MNT_QUOTA;
+ MNT_IUNLOCK(mp);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
vp->v_vflag |= VV_SYSTEM;
VOP_UNLOCK(vp, 0, td);
@@ -562,8 +564,11 @@ again:
for (type = 0; type < MAXQUOTAS; type++)
if (ump->um_quotas[type] != NULLVP)
break;
- if (type == MAXQUOTAS)
+ if (type == MAXQUOTAS) {
+ MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_QUOTA;
+ MNT_IUNLOCK(mp);
+ }
return (error);
}
OpenPOWER on IntegriCloud