Index: zfs_vfsops.c =================================================================== RCS file: /zoo/pjd/repo/src/sys/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c,v retrieving revision 1.12 diff -u -p -r1.12 zfs_vfsops.c --- zfs_vfsops.c 10 Sep 2007 19:58:14 -0000 1.12 +++ zfs_vfsops.c 7 Nov 2007 12:39:14 -0000 @@ -988,6 +988,8 @@ zfs_init(void) printf("ZFS filesystem version " ZFS_VERSION_STRING "\n"); + zgd_done_init(); + /* * Initialize .zfs directory structures */ @@ -1012,6 +1014,7 @@ zfs_fini(void) zfsctl_fini(); zfs_znode_fini(); zfs_vnodes_adjust_back(); + zgd_done_fini(); } int Index: zfs_vnops.c =================================================================== RCS file: /zoo/pjd/repo/src/sys/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c,v retrieving revision 1.24 diff -u -p -r1.24 zfs_vnops.c --- zfs_vnops.c 24 Jul 2007 15:00:43 -0000 1.24 +++ zfs_vnops.c 9 Nov 2007 22:20:26 -0000 @@ -856,21 +860,79 @@ zfs_write(vnode_t *vp, uio_t *uio, int i return (0); } +static TAILQ_HEAD(, zgd) zgd_done = TAILQ_HEAD_INITIALIZER(zgd_done); +static struct mtx zgd_done_mtx; +static int zgd_done_exit = 0; +MTX_SYSINIT(zgd_done, &zgd_done_mtx, "zgd", MTX_DEF); +static int zfs_done_count = 0; +SYSCTL_DECL(_vfs_zfs); +SYSCTL_INT(_vfs_zfs, OID_AUTO, zgd_done_count, CTLFLAG_RW, &zfs_done_count, 0, ""); + +static void +zgd_done_worker(void *arg) +{ + zgd_t *zgd; + vnode_t *vp; + int vfslocked; + + for (;;) { + mtx_lock(&zgd_done_mtx); + zgd = TAILQ_FIRST(&zgd_done); + if (zgd == NULL) { + if (zgd_done_exit) { + zgd_done_exit = 2; + mtx_unlock(&zgd_done_mtx); + wakeup(&zgd_done_exit); + kproc_exit(0); + } + msleep(&zgd_done, &zgd_done_mtx, PRIBIO | PDROP, "zgd", 0); + continue; + } + TAILQ_REMOVE(&zgd_done, zgd, zgd_next); + zfs_done_count++; + mtx_unlock(&zgd_done_mtx); + vp = zgd->zgd_vnode; + vfslocked = VFS_LOCK_GIANT(vp->v_vfsp); + VN_RELE(vp); + VFS_UNLOCK_GIANT(vfslocked); + kmem_free(zgd, sizeof (zgd_t)); + } +} + +void +zgd_done_init(void) +{ + + kproc_create(zgd_done_worker, NULL, NULL, 0, 0, "zgd_done"); +} + +void +zgd_done_fini(void) +{ + + mtx_lock(&zgd_done_mtx); + zgd_done_exit = 1; + wakeup(&zgd_done); + while (zgd_done_exit != 2) + msleep(&zgd_done_exit, &zgd_done_mtx, PRIBIO, "zgd_fini", 0); + mtx_unlock(&zgd_done_mtx); +} + void 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); - int vfslocked; - vfslocked = VFS_LOCK_GIANT(vp->v_vfsp); dmu_buf_rele(db, vzgd); zfs_range_unlock(rl); - VN_RELE(vp); + zgd->zgd_vnode = vp; zil_add_vdev(zgd->zgd_zilog, DVA_GET_VDEV(BP_IDENTITY(zgd->zgd_bp))); - kmem_free(zgd, sizeof (zgd_t)); - VFS_UNLOCK_GIANT(vfslocked); + mtx_lock(&zgd_done_mtx); + TAILQ_INSERT_TAIL(&zgd_done, zgd, zgd_next); + mtx_unlock(&zgd_done_mtx); + wakeup(&zgd_done); } /* Index: sys/zil.h =================================================================== RCS file: /zoo/pjd/repo/src/sys/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h,v retrieving revision 1.1 diff -u -p -r1.1 zil.h --- sys/zil.h 6 Apr 2007 01:09:03 -0000 1.1 +++ sys/zil.h 7 Nov 2007 12:45:00 -0000 @@ -222,10 +222,12 @@ typedef struct itx { * zgd_t is passed through dmu_sync() to the callback routine zfs_get_done() * to handle the cleanup of the dmu_sync() buffer write */ -typedef struct { +typedef struct zgd { zilog_t *zgd_zilog; /* zilog */ blkptr_t *zgd_bp; /* block pointer */ struct rl *zgd_rl; /* range lock */ + vnode_t *zgd_vnode; + TAILQ_ENTRY(zgd) zgd_next; } zgd_t; @@ -267,6 +269,9 @@ extern void zil_resume(zilog_t *zilog); extern void zil_add_vdev(zilog_t *zilog, uint64_t vdev); +extern void zgd_done_init(void); +extern void zgd_done_fini(void); + extern int zil_disable; #ifdef __cplusplus