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)
_______________________________________________
svn-src-stable-9@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-stable-9
To unsubscribe, send any mail to "svn-src-stable-9-unsubscr...@freebsd.org"

Reply via email to