From 7ba31c89c30fa2061bb449c97e1576a8f54fe02a Mon Sep 17 00:00:00 2001 From: Venkatesh Srinivas Date: Thu, 16 Feb 2012 07:53:22 -0800 Subject: [PATCH] kernel: mfs -- Fix unmount panic for MFS filesystems. mfs_start() is active for the life of an MFS mount, handling copyin/out requests. It is directed to exit when an MFS filesystem is unmounted. The VFS accounting code and VFS MPLOCK code assumed that the mountpoint structure was stable on return of mfs_start, which was not the case. To work around that, don't call acinit if the vfs_start vfsop returns EMOUNTEXIT, a kernel-specific pseudo-errno. Also allow marking vfs_start MPSAFE and mark mfs vfs_start MPSAFE, to avoid accessing a per-mount token field. A future commit will rework MFS's locking so that critical sections are not used to protect the MFS bioq. This is a hack for MFS; future work should either rework the filesystem or replace it outright with tmpfs. Closes: Bug 2276 --- sys/kern/vfs_vfsops.c | 4 +++- sys/sys/errno.h | 1 + sys/sys/mount.h | 4 +++- sys/vfs/mfs/mfs_vfsops.c | 8 +++++++- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/sys/kern/vfs_vfsops.c b/sys/kern/vfs_vfsops.c index c21f333369..f5b0937d1f 100644 --- a/sys/kern/vfs_vfsops.c +++ b/sys/kern/vfs_vfsops.c @@ -110,13 +110,15 @@ vfs_start(struct mount *mp, int flags) VFS_MPLOCK_DECLARE; int error; - VFS_MPLOCK1(mp); + VFS_MPLOCK_FLAG(mp, MNTK_ST_MPSAFE); error = (mp->mnt_op->vfs_start)(mp, flags); if (error == 0) /* do not call vfs_acinit on mount updates */ if ((mp->mnt_flag & MNT_UPDATE) == 0) error = (mp->mnt_op->vfs_acinit)(mp); VFS_MPUNLOCK(mp); + if (error == EMOUNTEXIT) + error = 0; return (error); } diff --git a/sys/sys/errno.h b/sys/sys/errno.h index 15ea63696d..b6e7b70a7d 100644 --- a/sys/sys/errno.h +++ b/sys/sys/errno.h @@ -195,6 +195,7 @@ static __inline int *__error(void) #define ERESTART (-1) /* restart syscall */ #define EJUSTRETURN (-2) /* don't modify regs, just return */ #define ENOIOCTL (-3) /* ioctl not handled by this layer */ +#define EMOUNTEXIT (-4) /* mfs: mountpoint released via vfs_start */ #endif #endif diff --git a/sys/sys/mount.h b/sys/sys/mount.h index f4bd4c1c9b..30c076042b 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -343,9 +343,11 @@ struct mount { #define MNTK_NOSTKMNT 0x10000000 /* no stacked mount point allowed */ #define MNTK_NOMSYNC 0x20000000 /* used by tmpfs */ #define MNTK_THR_SYNC 0x40000000 /* fs sync thread requested */ +#define MNTK_ST_MPSAFE 0x80000000 /* (mfs) vfs_start is MPSAFE */ #define MNTK_ALL_MPSAFE (MNTK_MPSAFE | MNTK_RD_MPSAFE | MNTK_WR_MPSAFE | \ - MNTK_GA_MPSAFE | MNTK_IN_MPSAFE | MNTK_SG_MPSAFE) + MNTK_GA_MPSAFE | MNTK_IN_MPSAFE | MNTK_SG_MPSAFE | \ + MNTK_ST_MPSAFE) /* * mountlist_*() defines diff --git a/sys/vfs/mfs/mfs_vfsops.c b/sys/vfs/mfs/mfs_vfsops.c index 4c95554922..dbd36b7fce 100644 --- a/sys/vfs/mfs/mfs_vfsops.c +++ b/sys/vfs/mfs/mfs_vfsops.c @@ -396,6 +396,12 @@ mfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred) */ VFS_STATFS(mp, &mp->mnt_stat, cred); + /* + * Mark VFS_START MPSAFE; this is to avoid accessing + * per-mount token after VFS_START exits + */ + mp->mnt_kern_flag |= MNTK_ST_MPSAFE; + goto success; error_2: /* error with devvp held*/ @@ -491,7 +497,7 @@ mfs_start(struct mount *mp, int flags) mfsp->mfs_dev = NULL; } kfree(mfsp, M_MFSNODE); - return (0); + return (EMOUNTEXIT); } /* -- 2.41.0