Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 17 Aug 2009 09:48:34 +0000 (UTC)
From:      Pawel Jakub Dawidek <pjd@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r196307 - in head/sys/cddl: compat/opensolaris/sys contrib/opensolaris/uts/common/fs contrib/opensolaris/uts/common/fs/zfs contrib/opensolaris/uts/common/fs/zfs/sys contrib/opensolaris/...
Message-ID:  <200908170948.n7H9mY9H057685@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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.
  */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200908170948.n7H9mY9H057685>