From 131066d515bbb9cbb5a4fe078b182d438544ade5 Mon Sep 17 00:00:00 2001 From: pjd Date: Mon, 17 Aug 2009 09:48:34 +0000 Subject: Manage asynchronous vnode release just like Solaris. Discussed with: kmacy Approved by: re (kib) --- sys/cddl/compat/opensolaris/sys/vnode.h | 1 - sys/cddl/contrib/opensolaris/uts/common/fs/vnode.c | 134 +++------------------ .../contrib/opensolaris/uts/common/fs/zfs/dmu.c | 3 - .../opensolaris/uts/common/fs/zfs/dsl_pool.c | 10 ++ .../opensolaris/uts/common/fs/zfs/sys/dsl_pool.h | 3 + .../opensolaris/uts/common/fs/zfs/zfs_vnops.c | 9 +- .../contrib/opensolaris/uts/common/sys/vnode.h | 22 +++- 7 files changed, 50 insertions(+), 132 deletions(-) (limited to 'sys') 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 #include #include +#include #include /* 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. */ -- cgit v1.1