summaryrefslogtreecommitdiffstats
path: root/sys/cddl
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2009-08-17 09:48:34 +0000
committerpjd <pjd@FreeBSD.org>2009-08-17 09:48:34 +0000
commit131066d515bbb9cbb5a4fe078b182d438544ade5 (patch)
treec4b69636b0708c9d82be00202fcf3d749895d775 /sys/cddl
parent2a9e26ee0b5f26db25a9616883cd50fbf3d04d18 (diff)
downloadFreeBSD-src-131066d515bbb9cbb5a4fe078b182d438544ade5.zip
FreeBSD-src-131066d515bbb9cbb5a4fe078b182d438544ade5.tar.gz
Manage asynchronous vnode release just like Solaris.
Discussed with: kmacy Approved by: re (kib)
Diffstat (limited to 'sys/cddl')
-rw-r--r--sys/cddl/compat/opensolaris/sys/vnode.h1
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/vnode.c134
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c3
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c10
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h3
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c9
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h22
7 files changed, 50 insertions, 132 deletions
diff --git a/sys/cddl/compat/opensolaris/sys/vnode.h b/sys/cddl/compat/opensolaris/sys/vnode.h
index bf11e67..7611a3f 100644
--- a/sys/cddl/compat/opensolaris/sys/vnode.h
+++ b/sys/cddl/compat/opensolaris/sys/vnode.h
@@ -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)
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/vnode.c b/sys/cddl/contrib/opensolaris/uts/common/fs/vnode.c
index bf613e5..f4e2449 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/vnode.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/vnode.c
@@ -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;
+static void
+vn_rele_inactive(vnode_t *vp)
+{
-typedef struct {
- struct vnode *stqe_next;
-} vnode_link_t;
+ 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;
+ vp->v_usecount--;
+ vdropl(vp);
}
-
-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();
-}
-
-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);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
index 842677b..377efb9 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
@@ -1199,9 +1199,6 @@ dmu_init(void)
void
dmu_fini(void)
{
-#ifdef _KERNEL
- vn_rele_async_fini();
-#endif
arc_fini();
dnode_fini();
dbuf_fini();
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
index 4585dc8..03af3d1 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
@@ -91,6 +91,9 @@ dsl_pool_open_impl(spa_t *spa, uint64_t txg)
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, dmu_tx_t *tx)
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);
+}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h
index 4dd88fe..dcf5a44 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h
@@ -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
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
index b2a3a16..de7c293 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
@@ -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, char *buf, zio_t *zio)
* 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);
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h b/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h
index a166315..a46b711 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h
@@ -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.
*/
OpenPOWER on IntegriCloud