summaryrefslogtreecommitdiffstats
path: root/sys/ufs/ffs
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/ufs/ffs
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/ufs/ffs')
-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
3 files changed, 51 insertions, 14 deletions
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);
}
OpenPOWER on IntegriCloud