Handle races when remounting UFS volume from ro to rw.

In particular, ensure that writers are not unleashed before SU
structures are initialized.  Also, correctly handle MNT_ASYNC before
this.

Reported and tested by:	pho
Reviewed by:	mckusick
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2019-04-08 15:20:05 +00:00
parent 9274fb3599
commit 5ffc99e2e4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=346031

View File

@ -154,7 +154,7 @@ ffs_mount(struct mount *mp)
struct fs *fs; struct fs *fs;
pid_t fsckpid = 0; pid_t fsckpid = 0;
int error, error1, flags; int error, error1, flags;
uint64_t mntorflags; uint64_t mntorflags, saved_mnt_flag;
accmode_t accmode; accmode_t accmode;
struct nameidata ndp; struct nameidata ndp;
char *fspec; char *fspec;
@ -371,25 +371,40 @@ ffs_mount(struct mount *mp)
return (error); return (error);
if ((error = vn_start_write(NULL, &mp, V_WAIT)) != 0) if ((error = vn_start_write(NULL, &mp, V_WAIT)) != 0)
return (error); return (error);
error = vfs_write_suspend_umnt(mp);
if (error != 0)
return (error);
fs->fs_ronly = 0; fs->fs_ronly = 0;
MNT_ILOCK(mp); MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_RDONLY; saved_mnt_flag = MNT_RDONLY;
if (MOUNTEDSOFTDEP(mp) && (mp->mnt_flag &
MNT_ASYNC) != 0)
saved_mnt_flag |= MNT_ASYNC;
mp->mnt_flag &= ~saved_mnt_flag;
MNT_IUNLOCK(mp); MNT_IUNLOCK(mp);
fs->fs_mtime = time_second; fs->fs_mtime = time_second;
/* check to see if we need to start softdep */ /* check to see if we need to start softdep */
if ((fs->fs_flags & FS_DOSOFTDEP) && if ((fs->fs_flags & FS_DOSOFTDEP) &&
(error = softdep_mount(devvp, mp, fs, td->td_ucred))){ (error = softdep_mount(devvp, mp, fs, td->td_ucred))){
vn_finished_write(mp); fs->fs_ronly = 1;
MNT_ILOCK(mp);
mp->mnt_flag |= saved_mnt_flag;
MNT_IUNLOCK(mp);
vfs_write_resume(mp, 0);
return (error); return (error);
} }
fs->fs_clean = 0; fs->fs_clean = 0;
if ((error = ffs_sbupdate(ump, MNT_WAIT, 0)) != 0) { if ((error = ffs_sbupdate(ump, MNT_WAIT, 0)) != 0) {
vn_finished_write(mp); fs->fs_ronly = 1;
MNT_ILOCK(mp);
mp->mnt_flag |= saved_mnt_flag;
MNT_IUNLOCK(mp);
vfs_write_resume(mp, 0);
return (error); return (error);
} }
if (fs->fs_snapinum[0] != 0) if (fs->fs_snapinum[0] != 0)
ffs_snapshot_mount(mp); ffs_snapshot_mount(mp);
vn_finished_write(mp); vfs_write_resume(mp, 0);
} }
/* /*
* Soft updates is incompatible with "async", * Soft updates is incompatible with "async",