Page MenuHomeFreeBSD

D30263.diff
No OneTemporary

D30263.diff

Index: sys/fs/nullfs/null.h
===================================================================
--- sys/fs/nullfs/null.h
+++ sys/fs/nullfs/null.h
@@ -42,7 +42,6 @@
#define NULLM_CACHE 0x0001
struct null_mount {
- struct mount *nullm_vfs;
struct vnode *nullm_lowerrootvp; /* Ref to lower root vnode */
uint64_t nullm_flags;
};
@@ -79,6 +78,9 @@
#define NULLVPTOLOWERVP(vp) (VTONULL(vp)->null_lowervp)
#endif
+struct mount *nullfs_mount_trybusy(struct vnode *vp);
+void nullfs_mount_unbusy(struct mount *mp);
+
extern struct vop_vector null_vnodeops;
#ifdef MALLOC_DECLARE
Index: sys/fs/nullfs/null_subr.c
===================================================================
--- sys/fs/nullfs/null_subr.c
+++ sys/fs/nullfs/null_subr.c
@@ -46,6 +46,8 @@
#include <sys/proc.h>
#include <sys/vnode.h>
+#include <machine/atomic.h>
+
#include <fs/nullfs/null.h>
/*
@@ -343,3 +345,31 @@
return (a->null_lowervp);
}
#endif
+
+/*
+ * Attempt to mark the underlying mount for a vnode busy so that nullfs
+ * can safely access it or issue VFS_* operations against it.
+ * Returns NULL on failure.
+ */
+struct mount *
+nullfs_mount_trybusy(struct vnode *vp)
+{
+ struct mount *mp;
+ int error;
+
+ mp = atomic_load_ptr(&vp->v_mount);
+ if (mp == NULL)
+ return (NULL);
+ error = vfs_busy(mp, MBF_NOWAIT);
+ if (error != 0)
+ return (NULL);
+
+ return (mp);
+}
+
+void
+nullfs_mount_unbusy(struct mount *mp)
+{
+ if (mp != NULL)
+ vfs_unbusy(mp);
+}
Index: sys/fs/nullfs/null_vfsops.c
===================================================================
--- sys/fs/nullfs/null_vfsops.c
+++ sys/fs/nullfs/null_vfsops.c
@@ -74,6 +74,7 @@
static int
nullfs_mount(struct mount *mp)
{
+ struct mount *lowermp;
struct vnode *lowerrootvp;
struct vnode *nullm_rootvp;
struct null_mount *xmp;
@@ -160,19 +161,22 @@
M_NULLFSMNT, M_WAITOK | M_ZERO);
/*
- * Save pointer to underlying FS and the reference to the
- * lower root vnode.
+ * Save the reference to the lower root vnode.
*/
- xmp->nullm_vfs = lowerrootvp->v_mount;
vref(lowerrootvp);
+ lowermp = nullfs_mount_trybusy(lowerrootvp);
xmp->nullm_lowerrootvp = lowerrootvp;
mp->mnt_data = xmp;
/*
* Make sure the node alias worked.
*/
- error = null_nodeget(mp, lowerrootvp, &nullm_rootvp);
+ if (lowermp == NULL)
+ error = ENOENT;
+ else
+ error = null_nodeget(mp, lowerrootvp, &nullm_rootvp);
if (error != 0) {
+ nullfs_mount_unbusy(lowermp);
vrele(lowerrootvp);
free(xmp, M_NULLFSMNT);
return (error);
@@ -186,7 +190,7 @@
xmp->nullm_flags |= NULLM_CACHE;
if (vfs_getopt(mp->mnt_optnew, "nocache", NULL, NULL) == 0 ||
- (xmp->nullm_vfs->mnt_kern_flag & MNTK_NULL_NOCACHE) != 0)
+ (lowermp->mnt_kern_flag & MNTK_NULL_NOCACHE) != 0)
xmp->nullm_flags &= ~NULLM_CACHE;
MNT_ILOCK(mp);
@@ -201,12 +205,13 @@
MNT_IUNLOCK(mp);
vfs_getnewfsid(mp);
if ((xmp->nullm_flags & NULLM_CACHE) != 0) {
- MNT_ILOCK(xmp->nullm_vfs);
- TAILQ_INSERT_TAIL(&xmp->nullm_vfs->mnt_uppers, mp,
+ MNT_ILOCK(lowermp);
+ TAILQ_INSERT_TAIL(&lowermp->mnt_uppers, mp,
mnt_upper_link);
- MNT_IUNLOCK(xmp->nullm_vfs);
+ MNT_IUNLOCK(lowermp);
}
+ nullfs_mount_unbusy(lowermp);
vfs_mountedfrom(mp, target);
vput(nullm_rootvp);
@@ -253,8 +258,13 @@
* Finally, throw away the null_mount structure
*/
mntdata = mp->mnt_data;
- ump = mntdata->nullm_vfs;
if ((mntdata->nullm_flags & NULLM_CACHE) != 0) {
+ ump = mntdata->nullm_lowerrootvp->v_mount;
+ /*
+ * Registration as upper should prevent even forced
+ * unmount of lower FS.
+ */
+ KASSERT(ump != NULL, ("nullfs: lower mount gone"));
MNT_ILOCK(ump);
while ((ump->mnt_kern_flag & MNTK_VGONE_UPPER) != 0) {
ump->mnt_kern_flag |= MNTK_VGONE_WAITER;
@@ -294,13 +304,34 @@
}
static int
-nullfs_quotactl(mp, cmd, uid, arg)
+nullfs_quotactl(mp, cmd, uid, arg, mp_busy)
struct mount *mp;
int cmd;
uid_t uid;
void *arg;
+ bool *mp_busy;
{
- return VFS_QUOTACTL(MOUNTTONULLMOUNT(mp)->nullm_vfs, cmd, uid, arg);
+ struct mount *lowermp;
+ struct null_mount *mntdata;
+ int error;
+ bool unbusy;
+
+ unbusy = true;
+
+ mntdata = MOUNTTONULLMOUNT(mp);
+ NULLFSDEBUG("nullfs_quotactl(mp = %p, vp = %p)\n", mp,
+ mntdata->nullm_lowerrootvp);
+ lowermp = nullfs_mount_trybusy(mntdata->nullm_lowerrootvp);
+
+ if (lowermp == NULL)
+ return (ENOENT);
+
+ error = VFS_QUOTACTL(lowermp, cmd, uid, arg, &unbusy);
+
+ if (unbusy)
+ nullfs_mount_unbusy(lowermp);
+
+ return (error);
}
static int
@@ -308,16 +339,24 @@
struct mount *mp;
struct statfs *sbp;
{
+ struct mount *lowermp;
+ struct null_mount *mntdata;
int error;
struct statfs *mstat;
- NULLFSDEBUG("nullfs_statfs(mp = %p, vp = %p->%p)\n", (void *)mp,
- (void *)MOUNTTONULLMOUNT(mp)->nullm_rootvp,
- (void *)NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp));
+ mntdata = MOUNTTONULLMOUNT(mp);
+ NULLFSDEBUG("nullfs_statfs(mp = %p, vp = %p->%p)\n", mp,
+ mntdata->nullm_rootvp, NULLVPTOLOWERVP(mntdata->nullm_rootvp));
mstat = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK | M_ZERO);
- error = VFS_STATFS(MOUNTTONULLMOUNT(mp)->nullm_vfs, mstat);
+ lowermp = nullfs_mount_trybusy(mntdata->nullm_lowerrootvp);
+ if (lowermp == NULL)
+ error = ENOENT;
+ else
+ error = VFS_STATFS(lowermp, mstat);
+
+ nullfs_mount_unbusy(lowermp);
if (error) {
free(mstat, M_STATFS);
return (error);
@@ -358,12 +397,21 @@
int flags;
struct vnode **vpp;
{
+ struct mount *lowermp;
+ struct null_mount *mntdata;
int error;
+ mntdata = MOUNTTONULLMOUNT(mp);
+
KASSERT((flags & LK_TYPE_MASK) != 0,
("nullfs_vget: no lock requested"));
- error = VFS_VGET(MOUNTTONULLMOUNT(mp)->nullm_vfs, ino, flags, vpp);
+ lowermp = nullfs_mount_trybusy(mntdata->nullm_lowerrootvp);
+ if (lowermp == NULL)
+ return (ENOENT);
+
+ error = VFS_VGET(lowermp, ino, flags, vpp);
+ nullfs_mount_unbusy(lowermp);
if (error != 0)
return (error);
return (null_nodeget(mp, *vpp, vpp));
@@ -376,10 +424,19 @@
int flags;
struct vnode **vpp;
{
+ struct mount *lowermp;
+ struct null_mount *mntdata;
int error;
- error = VFS_FHTOVP(MOUNTTONULLMOUNT(mp)->nullm_vfs, fidp, flags,
+ mntdata = MOUNTTONULLMOUNT(mp);
+
+ lowermp = nullfs_mount_trybusy(mntdata->nullm_lowerrootvp);
+ if (lowermp == NULL)
+ return (ENOENT);
+
+ error = VFS_FHTOVP(lowermp, fidp, flags,
vpp);
+ nullfs_mount_unbusy(lowermp);
if (error != 0)
return (error);
return (null_nodeget(mp, *vpp, vpp));
@@ -393,9 +450,21 @@
int namespace;
const char *attrname;
{
+ struct mount *lowermp;
+ struct null_mount *mntdata;
+ int error;
+
+ mntdata = MOUNTTONULLMOUNT(mp);
+
+ lowermp = nullfs_mount_trybusy(mntdata->nullm_lowerrootvp);
+ if (lowermp == NULL)
+ return (ENOENT);
- return (VFS_EXTATTRCTL(MOUNTTONULLMOUNT(mp)->nullm_vfs, cmd,
- filename_vp, namespace, attrname));
+ error = VFS_EXTATTRCTL(lowermp, cmd,
+ filename_vp, namespace, attrname);
+
+ nullfs_mount_unbusy(lowermp);
+ return (error);
}
static void

File Metadata

Mime Type
text/plain
Expires
Tue, Nov 19, 12:33 PM (21 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14716544
Default Alt Text
D30263.diff (6 KB)

Event Timeline