svn commit: r244652 - in stable/9/sys: kern sys
Konstantin Belousov
kib at FreeBSD.org
Mon Dec 24 13:01:08 UTC 2012
Author: kib
Date: Mon Dec 24 13:01:07 2012
New Revision: 244652
URL: http://svnweb.freebsd.org/changeset/base/244652
Log:
MFC r240284:
Add a facility for vgone() to inform the set of subscribed mounts
about vnode reclamation. Typical use is for the bypass mounts like
nullfs to get a notification about lower vnode going away.
MFC r241225 (by avg):
mount.h: MNTK_VGONE_UPPER and MNTK_VGONE_WAITER were supposed to be different
Modified:
stable/9/sys/kern/vfs_mount.c
stable/9/sys/kern/vfs_subr.c
stable/9/sys/sys/mount.h
Directory Properties:
stable/9/sys/ (props changed)
Modified: stable/9/sys/kern/vfs_mount.c
==============================================================================
--- stable/9/sys/kern/vfs_mount.c Mon Dec 24 12:54:12 2012 (r244651)
+++ stable/9/sys/kern/vfs_mount.c Mon Dec 24 13:01:07 2012 (r244652)
@@ -479,6 +479,7 @@ vfs_mount_alloc(struct vnode *vp, struct
mac_mount_create(cred, mp);
#endif
arc4rand(&mp->mnt_hashseed, sizeof mp->mnt_hashseed, 0);
+ TAILQ_INIT(&mp->mnt_uppers);
return (mp);
}
@@ -512,6 +513,7 @@ vfs_mount_destroy(struct mount *mp)
vprint("", vp);
panic("unmount: dangling vnode");
}
+ KASSERT(TAILQ_EMPTY(&mp->mnt_uppers), ("mnt_uppers"));
if (mp->mnt_nvnodelistsize != 0)
panic("vfs_mount_destroy: nonzero nvnodelistsize");
if (mp->mnt_activevnodelistsize != 0)
@@ -1259,7 +1261,8 @@ dounmount(mp, flags, td)
}
MNT_ILOCK(mp);
- if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
+ if ((mp->mnt_kern_flag & MNTK_UNMOUNT) != 0 ||
+ !TAILQ_EMPTY(&mp->mnt_uppers)) {
MNT_IUNLOCK(mp);
if (coveredvp)
VOP_UNLOCK(coveredvp, 0);
Modified: stable/9/sys/kern/vfs_subr.c
==============================================================================
--- stable/9/sys/kern/vfs_subr.c Mon Dec 24 12:54:12 2012 (r244651)
+++ stable/9/sys/kern/vfs_subr.c Mon Dec 24 13:01:07 2012 (r244652)
@@ -2741,6 +2741,58 @@ vgone(struct vnode *vp)
VI_UNLOCK(vp);
}
+static void
+vgonel_reclaim_lowervp_vfs(struct mount *mp __unused,
+ struct vnode *lowervp __unused)
+{
+}
+
+/*
+ * Notify upper mounts about reclaimed vnode.
+ */
+static void
+vgonel_reclaim_lowervp(struct vnode *vp)
+{
+ static struct vfsops vgonel_vfsops = {
+ .vfs_reclaim_lowervp = vgonel_reclaim_lowervp_vfs
+ };
+ struct mount *mp, *ump, *mmp;
+
+ mp = vp->v_mount;
+ if (mp == NULL)
+ return;
+
+ MNT_ILOCK(mp);
+ if (TAILQ_EMPTY(&mp->mnt_uppers))
+ goto unlock;
+ MNT_IUNLOCK(mp);
+ mmp = malloc(sizeof(struct mount), M_TEMP, M_WAITOK | M_ZERO);
+ mmp->mnt_op = &vgonel_vfsops;
+ mmp->mnt_kern_flag |= MNTK_MARKER;
+ MNT_ILOCK(mp);
+ mp->mnt_kern_flag |= MNTK_VGONE_UPPER;
+ for (ump = TAILQ_FIRST(&mp->mnt_uppers); ump != NULL;) {
+ if ((ump->mnt_kern_flag & MNTK_MARKER) != 0) {
+ ump = TAILQ_NEXT(ump, mnt_upper_link);
+ continue;
+ }
+ TAILQ_INSERT_AFTER(&mp->mnt_uppers, ump, mmp, mnt_upper_link);
+ MNT_IUNLOCK(mp);
+ VFS_RECLAIM_LOWERVP(ump, vp);
+ MNT_ILOCK(mp);
+ ump = TAILQ_NEXT(mmp, mnt_upper_link);
+ TAILQ_REMOVE(&mp->mnt_uppers, mmp, mnt_upper_link);
+ }
+ free(mmp, M_TEMP);
+ mp->mnt_kern_flag &= ~MNTK_VGONE_UPPER;
+ if ((mp->mnt_kern_flag & MNTK_VGONE_WAITER) != 0) {
+ mp->mnt_kern_flag &= ~MNTK_VGONE_WAITER;
+ wakeup(&mp->mnt_uppers);
+ }
+unlock:
+ MNT_IUNLOCK(mp);
+}
+
/*
* vgone, with the vp interlock held.
*/
@@ -2765,6 +2817,7 @@ vgonel(struct vnode *vp)
if (vp->v_iflag & VI_DOOMED)
return;
vp->v_iflag |= VI_DOOMED;
+
/*
* Check to see if the vnode is in use. If so, we have to call
* VOP_CLOSE() and VOP_INACTIVE().
@@ -2772,6 +2825,8 @@ vgonel(struct vnode *vp)
active = vp->v_usecount;
oweinact = (vp->v_iflag & VI_OWEINACT);
VI_UNLOCK(vp);
+ vgonel_reclaim_lowervp(vp);
+
/*
* Clean out any buffers associated with the vnode.
* If the flush fails, just toss the buffers.
Modified: stable/9/sys/sys/mount.h
==============================================================================
--- stable/9/sys/sys/mount.h Mon Dec 24 12:54:12 2012 (r244651)
+++ stable/9/sys/sys/mount.h Mon Dec 24 13:01:07 2012 (r244652)
@@ -189,6 +189,8 @@ struct mount {
#define mnt_endzero mnt_gjprovider
char *mnt_gjprovider; /* gjournal provider name */
struct lock mnt_explock; /* vfs_export walkers lock */
+ TAILQ_ENTRY(mount) mnt_upper_link; /* (m) we in the all uppers */
+ TAILQ_HEAD(, mount) mnt_uppers; /* (m) upper mounts over us*/
};
/*
@@ -369,7 +371,10 @@ void __mnt_vnode_markerfree(str
#define MNTK_NO_IOPF 0x00000100 /* Disallow page faults during reads
and writes. Filesystem shall properly
handle i/o state on EFAULT. */
+#define MNTK_VGONE_UPPER 0x00000200
+#define MNTK_VGONE_WAITER 0x00000400
#define MNTK_LOOKUP_EXCL_DOTDOT 0x00000800
+#define MNTK_MARKER 0x00001000
#define MNTK_NOASYNC 0x00800000 /* disable async */
#define MNTK_UNMOUNT 0x01000000 /* unmount in progress */
#define MNTK_MWAIT 0x02000000 /* waiting for unmount to finish */
@@ -625,6 +630,7 @@ typedef int vfs_mount_t(struct mount *mp
typedef int vfs_sysctl_t(struct mount *mp, fsctlop_t op,
struct sysctl_req *req);
typedef void vfs_susp_clean_t(struct mount *mp);
+typedef void vfs_reclaim_lowervp_t(struct mount *mp, struct vnode *lowervp);
struct vfsops {
vfs_mount_t *vfs_mount;
@@ -642,6 +648,7 @@ struct vfsops {
vfs_extattrctl_t *vfs_extattrctl;
vfs_sysctl_t *vfs_sysctl;
vfs_susp_clean_t *vfs_susp_clean;
+ vfs_reclaim_lowervp_t *vfs_reclaim_lowervp;
};
vfs_statfs_t __vfs_statfs;
@@ -667,6 +674,9 @@ vfs_statfs_t __vfs_statfs;
#define VFS_SUSP_CLEAN(MP) \
({if (*(MP)->mnt_op->vfs_susp_clean != NULL) \
(*(MP)->mnt_op->vfs_susp_clean)(MP); })
+#define VFS_RECLAIM_LOWERVP(MP, VP) \
+ ({if (*(MP)->mnt_op->vfs_reclaim_lowervp != NULL) \
+ (*(MP)->mnt_op->vfs_reclaim_lowervp)((MP), (VP)); })
#define VFS_NEEDSGIANT_(MP) \
((MP) != NULL && ((MP)->mnt_kern_flag & MNTK_MPSAFE) == 0)
More information about the svn-src-stable-9
mailing list