Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102901060
D30263.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D30263.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D30263: nullfs: busy the lower mount before calling VFS_* operations on it
Attached
Detach File
Event Timeline
Log In to Comment