Author: pjd
Date: Mon Aug 17 09:48:34 2009
New Revision: 196307
URL: http://svn.freebsd.org/changeset/base/196307

Log:
  Manage asynchronous vnode release just like Solaris.
  
  Discussed with:       kmacy
  Approved by:  re (kib)

Modified:
  head/sys/cddl/compat/opensolaris/sys/vnode.h
  head/sys/cddl/contrib/opensolaris/uts/common/fs/vnode.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
  head/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h

Modified: head/sys/cddl/compat/opensolaris/sys/vnode.h
==============================================================================
--- head/sys/cddl/compat/opensolaris/sys/vnode.h        Mon Aug 17 09:42:34 
2009        (r196306)
+++ head/sys/cddl/compat/opensolaris/sys/vnode.h        Mon Aug 17 09:48:34 
2009        (r196307)
@@ -75,7 +75,6 @@ vn_is_readonly(vnode_t *vp)
 #define        VN_HOLD(v)      vref(v)
 #define        VN_RELE(v)      vrele(v)
 #define        VN_URELE(v)     vput(v)
-#define        VN_RELE_ASYNC(v, tq)    vn_rele_async(v, tq); 
 
 #define        VOP_REALVP(vp, vpp, ct) (*(vpp) = (vp), 0)
 

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/vnode.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/vnode.c     Mon Aug 17 
09:42:34 2009        (r196306)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/vnode.c     Mon Aug 17 
09:48:34 2009        (r196307)
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -36,12 +36,10 @@
  * contributors.
  */
 
-
-#pragma ident  "%Z%%M% %I%     %E% SMI"
-
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/proc.h>
+#include <sys/taskq.h>
 #include <sys/vnode.h>
 
 /* Extensible attribute (xva) routines. */
@@ -74,15 +72,12 @@ xva_getxoptattr(xvattr_t *xvap)
        return (xoap);
 }
 
-static STAILQ_HEAD(, vnode) vn_rele_async_list;
-static struct mtx vn_rele_async_lock;
-static struct cv vn_rele_async_cv;
-static int vn_rele_list_length;
-static int vn_rele_async_thread_exit;
-
-typedef struct  {
-       struct vnode *stqe_next;
-} vnode_link_t;
+static void
+vn_rele_inactive(vnode_t *vp)
+{
+
+       vrele(vp);
+}
 
 /*
  * Like vn_rele() except if we are going to call VOP_INACTIVE() then do it
@@ -95,117 +90,16 @@ typedef struct  {
  * This is because taskqs throttle back allocation if too many are created.
  */
 void
-vn_rele_async(vnode_t *vp, taskq_t *taskq /* unused */)
+vn_rele_async(vnode_t *vp, taskq_t *taskq)
 {
-       
-       KASSERT(vp != NULL, ("vrele: null vp"));
-       VFS_ASSERT_GIANT(vp->v_mount);
+       VERIFY(vp->v_count > 0);
        VI_LOCK(vp);
-
-       if (vp->v_usecount > 1 || ((vp->v_iflag & VI_DOINGINACT) &&
-           vp->v_usecount == 1)) {
-               vp->v_usecount--;
-               vdropl(vp);
-               return;
-       }       
-       if (vp->v_usecount != 1) {
-#ifdef DIAGNOSTIC
-               vprint("vrele: negative ref count", vp);
-#endif
+       if (vp->v_count == 1 && !(vp->v_iflag & VI_DOINGINACT)) {
                VI_UNLOCK(vp);
-               panic("vrele: negative ref cnt");
-       }
-       /*
-        * We are exiting
-        */
-       if (vn_rele_async_thread_exit != 0) {
-               vrele(vp);
+               VERIFY(taskq_dispatch((taskq_t *)taskq,
+                   (task_func_t *)vn_rele_inactive, vp, TQ_SLEEP) != 0);
                return;
        }
-       
-       mtx_lock(&vn_rele_async_lock);
-
-       /*  STAILQ_INSERT_TAIL                  */
-       (*(vnode_link_t *)&vp->v_cstart).stqe_next = NULL;
-       *vn_rele_async_list.stqh_last = vp;
-       vn_rele_async_list.stqh_last =
-           &((vnode_link_t *)&vp->v_cstart)->stqe_next;
-
-       /****************************************/
-       vn_rele_list_length++;
-       if ((vn_rele_list_length % 100) == 0)
-               cv_signal(&vn_rele_async_cv);
-       mtx_unlock(&vn_rele_async_lock);
-       VI_UNLOCK(vp);
-}
-
-static void
-vn_rele_async_init(void *arg)
-{
-
-       mtx_init(&vn_rele_async_lock, "valock", NULL, MTX_DEF);
-       STAILQ_INIT(&vn_rele_async_list);
-
-       /* cv_init(&vn_rele_async_cv, "vacv"); */
-       vn_rele_async_cv.cv_description = "vacv";
-       vn_rele_async_cv.cv_waiters = 0;
-}
-
-void
-vn_rele_async_fini(void)
-{
-
-       mtx_lock(&vn_rele_async_lock);
-       vn_rele_async_thread_exit = 1;
-       cv_signal(&vn_rele_async_cv);
-       while (vn_rele_async_thread_exit != 0)
-               cv_wait(&vn_rele_async_cv, &vn_rele_async_lock);
-       mtx_unlock(&vn_rele_async_lock);
-       mtx_destroy(&vn_rele_async_lock);
-}
-
-
-static void
-vn_rele_async_cleaner(void)
-{
-       STAILQ_HEAD(, vnode) vn_tmp_list;
-       struct vnode *curvnode;
-
-       STAILQ_INIT(&vn_tmp_list);
-       mtx_lock(&vn_rele_async_lock);
-       while (vn_rele_async_thread_exit == 0) {
-               STAILQ_CONCAT(&vn_tmp_list, &vn_rele_async_list);
-               vn_rele_list_length = 0;
-               mtx_unlock(&vn_rele_async_lock);
-               
-               while (!STAILQ_EMPTY(&vn_tmp_list)) {
-                       curvnode = STAILQ_FIRST(&vn_tmp_list);
-
-                       /*   STAILQ_REMOVE_HEAD */
-                       STAILQ_FIRST(&vn_tmp_list) =
-                           ((vnode_link_t *)&curvnode->v_cstart)->stqe_next;
-                       if (STAILQ_FIRST(&vn_tmp_list) == NULL)
-                                        vn_tmp_list.stqh_last = 
&STAILQ_FIRST(&vn_tmp_list);
-                       /***********************/
-                       vrele(curvnode);
-               }
-               mtx_lock(&vn_rele_async_lock);
-               if (vn_rele_list_length == 0)
-                       cv_timedwait(&vn_rele_async_cv, &vn_rele_async_lock,
-                           hz/10);
-       }
-
-       vn_rele_async_thread_exit = 0;
-       cv_broadcast(&vn_rele_async_cv);
-       mtx_unlock(&vn_rele_async_lock);
-       thread_exit();
+       vp->v_usecount--;
+       vdropl(vp);
 }
-
-static struct proc *vn_rele_async_proc;
-static struct kproc_desc up_kp = {
-       "vaclean",
-       vn_rele_async_cleaner,
-       &vn_rele_async_proc
-};
-SYSINIT(vaclean, SI_SUB_KTHREAD_UPDATE, SI_ORDER_FIRST, kproc_start, &up_kp);
-SYSINIT(vn_rele_async_setup, SI_SUB_VFS, SI_ORDER_FIRST, vn_rele_async_init, 
NULL);

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c   Mon Aug 17 
09:42:34 2009        (r196306)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c   Mon Aug 17 
09:48:34 2009        (r196307)
@@ -1199,9 +1199,6 @@ dmu_init(void)
 void
 dmu_fini(void)
 {
-#ifdef _KERNEL
-       vn_rele_async_fini();
-#endif
        arc_fini();
        dnode_fini();
        dbuf_fini();

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c      Mon Aug 
17 09:42:34 2009        (r196306)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c      Mon Aug 
17 09:48:34 2009        (r196307)
@@ -91,6 +91,9 @@ dsl_pool_open_impl(spa_t *spa, uint64_t 
        mutex_init(&dp->dp_lock, NULL, MUTEX_DEFAULT, NULL);
        mutex_init(&dp->dp_scrub_cancel_lock, NULL, MUTEX_DEFAULT, NULL);
 
+       dp->dp_vnrele_taskq = taskq_create("zfs_vn_rele_taskq", 1, minclsyspri,
+           1, 4, 0);
+
        return (dp);
 }
 
@@ -228,6 +231,7 @@ dsl_pool_close(dsl_pool_t *dp)
        rw_destroy(&dp->dp_config_rwlock);
        mutex_destroy(&dp->dp_lock);
        mutex_destroy(&dp->dp_scrub_cancel_lock);
+       taskq_destroy(dp->dp_vnrele_taskq);
        kmem_free(dp, sizeof (dsl_pool_t));
 }
 
@@ -611,3 +615,9 @@ dsl_pool_create_origin(dsl_pool_t *dp, d
        dsl_dataset_rele(ds, FTAG);
        rw_exit(&dp->dp_config_rwlock);
 }
+
+taskq_t *
+dsl_pool_vnrele_taskq(dsl_pool_t *dp)
+{
+       return (dp->dp_vnrele_taskq);
+}

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h  Mon Aug 
17 09:42:34 2009        (r196306)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h  Mon Aug 
17 09:48:34 2009        (r196307)
@@ -57,6 +57,7 @@ typedef struct dsl_pool {
        struct dsl_dir *dp_mos_dir;
        struct dsl_dataset *dp_origin_snap;
        uint64_t dp_root_dir_obj;
+       struct taskq *dp_vnrele_taskq;
 
        /* No lock needed - sync context only */
        blkptr_t dp_meta_rootbp;
@@ -119,6 +120,8 @@ int dsl_pool_scrub_clean(dsl_pool_t *dp)
 void dsl_pool_scrub_sync(dsl_pool_t *dp, dmu_tx_t *tx);
 void dsl_pool_scrub_restart(dsl_pool_t *dp);
 
+taskq_t *dsl_pool_vnrele_taskq(dsl_pool_t *dp);
+
 #ifdef __cplusplus
 }
 #endif

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c     Mon Aug 
17 09:42:34 2009        (r196306)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c     Mon Aug 
17 09:48:34 2009        (r196307)
@@ -924,6 +924,7 @@ zfs_get_done(dmu_buf_t *db, void *vzgd)
        zgd_t *zgd = (zgd_t *)vzgd;
        rl_t *rl = zgd->zgd_rl;
        vnode_t *vp = ZTOV(rl->r_zp);
+       objset_t *os = rl->r_zp->z_zfsvfs->z_os;
        int vfslocked;
 
        vfslocked = VFS_LOCK_GIANT(vp->v_vfsp);
@@ -933,7 +934,7 @@ zfs_get_done(dmu_buf_t *db, void *vzgd)
         * Release the vnode asynchronously as we currently have the
         * txg stopped from syncing.
         */
-       VN_RELE_ASYNC(vp, NULL);
+       VN_RELE_ASYNC(vp, dsl_pool_vnrele_taskq(dmu_objset_pool(os)));
        zil_add_block(zgd->zgd_zilog, zgd->zgd_bp);
        kmem_free(zgd, sizeof (zgd_t));
        VFS_UNLOCK_GIANT(vfslocked);
@@ -968,8 +969,8 @@ zfs_get_data(void *arg, lr_write_t *lr, 
                 * Release the vnode asynchronously as we currently have the
                 * txg stopped from syncing.
                 */
-               VN_RELE_ASYNC(ZTOV(zp), NULL);
-
+               VN_RELE_ASYNC(ZTOV(zp),
+                   dsl_pool_vnrele_taskq(dmu_objset_pool(os)));
                return (ENOENT);
        }
 
@@ -1045,7 +1046,7 @@ out:
         * Release the vnode asynchronously as we currently have the
         * txg stopped from syncing.
         */
-       VN_RELE_ASYNC(ZTOV(zp), NULL);
+       VN_RELE_ASYNC(ZTOV(zp), dsl_pool_vnrele_taskq(dmu_objset_pool(os)));
        return (error);
 }
 

Modified: head/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h    Mon Aug 17 
09:42:34 2009        (r196306)
+++ head/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h    Mon Aug 17 
09:48:34 2009        (r196307)
@@ -354,6 +354,11 @@ typedef struct caller_context {
 } caller_context_t;
 
 /*
+ * Structure tags for function prototypes, defined elsewhere.
+ */
+struct taskq;
+
+/*
  * Flags for VOP_LOOKUP
  *
  * Defined in file.h, but also possible, FIGNORECASE
@@ -370,6 +375,13 @@ typedef struct caller_context {
 #define        V_RDDIR_ENTFLAGS        0x01    /* request dirent flags */
 
 /*
+ * Public vnode manipulation functions.
+ */
+#ifdef _KERNEL
+
+void   vn_rele_async(struct vnode *vp, struct taskq *taskq);
+
+/*
  * Extensible vnode attribute (xva) routines:
  * xva_init() initializes an xvattr_t (zero struct, init mapsize, set AT_XATTR)
  * xva_getxoptattr() returns a ponter to the xoptattr_t section of xvattr_t
@@ -377,10 +389,12 @@ typedef struct caller_context {
 void           xva_init(xvattr_t *);
 xoptattr_t     *xva_getxoptattr(xvattr_t *);   /* Get ptr to xoptattr_t */
 
-struct taskq;
-void   vn_rele_async(struct vnode *vp, struct taskq *taskq);
-void   vn_rele_async_fini(void);
-       
+#define        VN_RELE_ASYNC(vp, taskq)        { \
+       vn_rele_async(vp, taskq); \
+}
+
+#endif /* _KERNEL */
+
 /*
  * Flags to VOP_SETATTR/VOP_GETATTR.
  */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to