From 83154f853d9ca39deb1add01e032aff1f0678514 Mon Sep 17 00:00:00 2001 From: tegge Date: Tue, 26 Sep 2006 04:12:49 +0000 Subject: 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(). --- sys/fs/cd9660/cd9660_vfsops.c | 6 ++++ sys/fs/devfs/devfs_vfsops.c | 2 ++ sys/fs/hpfs/hpfs_vfsops.c | 4 +++ sys/fs/msdosfs/msdosfs_vfsops.c | 4 +++ sys/fs/ntfs/ntfs_vfsops.c | 4 +++ sys/fs/nullfs/null_vfsops.c | 7 ++++- sys/fs/nwfs/nwfs_vfsops.c | 2 ++ sys/fs/portalfs/portal_vfsops.c | 2 ++ sys/fs/smbfs/smbfs_vfsops.c | 2 ++ sys/fs/udf/udf_vfsops.c | 6 ++++ sys/fs/umapfs/umap_vfsops.c | 5 +++- sys/fs/unionfs/union_vfsops.c | 9 +++++- sys/gnu/fs/ext2fs/ext2_vfsops.c | 6 ++++ sys/gnu/fs/reiserfs/reiserfs_vfsops.c | 4 +++ sys/isofs/cd9660/cd9660_vfsops.c | 6 ++++ sys/kern/uipc_mqueue.c | 2 ++ sys/kern/vfs_export.c | 10 +++++++ sys/kern/vfs_extattr.c | 4 +++ sys/kern/vfs_mount.c | 13 ++++++++ sys/kern/vfs_subr.c | 4 +++ sys/kern/vfs_syscalls.c | 4 +++ sys/nfsclient/nfs_vfsops.c | 16 ++++++++-- sys/sys/mount.h | 2 +- sys/ufs/ffs/ffs_snapshot.c | 7 ++++- sys/ufs/ffs/ffs_softdep.c | 2 ++ sys/ufs/ffs/ffs_vfsops.c | 56 +++++++++++++++++++++++++++-------- sys/ufs/ufs/ufs_quota.c | 7 ++++- 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); } -- cgit v1.1