Create separate taskqueue to call zfs_unlinked_drain().
r334810 introduced zfs_unlinked_drain() dispatch to taskqueue on every deletion of a file with extended attributes. Using system_taskq for that with its multiple threads in case of multiple files deletion caused all available CPU threads to uselessly spin on busy locks, completely blocking the system. Use of single dedicated taskqueue is the only easy solution I've found, while in would be great if we could specify that some task should be executed only once at a time, but never in parallel, while many tasks could use different threads same time. Sponsored by: iXsystems, Inc.
This commit is contained in:
parent
b5d8388764
commit
c1c7ce6e54
@ -402,6 +402,10 @@ zfs_purgedir(znode_t *dzp)
|
|||||||
return (skipped);
|
return (skipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__FreeBSD__)
|
||||||
|
extern taskq_t *zfsvfs_taskq;
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
zfs_rmnode(znode_t *zp)
|
zfs_rmnode(znode_t *zp)
|
||||||
{
|
{
|
||||||
@ -520,15 +524,17 @@ zfs_rmnode(znode_t *zp)
|
|||||||
|
|
||||||
dmu_tx_commit(tx);
|
dmu_tx_commit(tx);
|
||||||
|
|
||||||
|
#if defined(__FreeBSD__)
|
||||||
if (xattr_obj) {
|
if (xattr_obj) {
|
||||||
/*
|
/*
|
||||||
* We're using the FreeBSD taskqueue API here instead of
|
* We're using the FreeBSD taskqueue API here instead of
|
||||||
* the Solaris taskq API since the FreeBSD API allows for a
|
* the Solaris taskq API since the FreeBSD API allows for a
|
||||||
* task to be enqueued multiple times but executed once.
|
* task to be enqueued multiple times but executed once.
|
||||||
*/
|
*/
|
||||||
taskqueue_enqueue(system_taskq->tq_queue,
|
taskqueue_enqueue(zfsvfs_taskq->tq_queue,
|
||||||
&zfsvfs->z_unlinked_drain_task);
|
&zfsvfs->z_unlinked_drain_task);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t
|
static uint64_t
|
||||||
|
@ -1130,6 +1130,8 @@ zfsvfs_init(zfsvfs_t *zfsvfs, objset_t *os)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__FreeBSD__)
|
#if defined(__FreeBSD__)
|
||||||
|
taskq_t *zfsvfs_taskq;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
zfsvfs_task_unlinked_drain(void *context, int pending __unused)
|
zfsvfs_task_unlinked_drain(void *context, int pending __unused)
|
||||||
{
|
{
|
||||||
@ -2185,9 +2187,9 @@ zfs_umount(vfs_t *vfsp, int fflag)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (taskqueue_cancel(system_taskq->tq_queue,
|
while (taskqueue_cancel(zfsvfs_taskq->tq_queue,
|
||||||
&zfsvfs->z_unlinked_drain_task, NULL) != 0)
|
&zfsvfs->z_unlinked_drain_task, NULL) != 0)
|
||||||
taskqueue_drain(system_taskq->tq_queue,
|
taskqueue_drain(zfsvfs_taskq->tq_queue,
|
||||||
&zfsvfs->z_unlinked_drain_task);
|
&zfsvfs->z_unlinked_drain_task);
|
||||||
|
|
||||||
VERIFY(zfsvfs_teardown(zfsvfs, B_TRUE) == 0);
|
VERIFY(zfsvfs_teardown(zfsvfs, B_TRUE) == 0);
|
||||||
@ -2554,11 +2556,17 @@ zfs_init(void)
|
|||||||
zfs_vnodes_adjust();
|
zfs_vnodes_adjust();
|
||||||
|
|
||||||
dmu_objset_register_type(DMU_OST_ZFS, zfs_space_delta_cb);
|
dmu_objset_register_type(DMU_OST_ZFS, zfs_space_delta_cb);
|
||||||
|
#if defined(__FreeBSD__)
|
||||||
|
zfsvfs_taskq = taskq_create("zfsvfs", 1, minclsyspri, 0, 0, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
zfs_fini(void)
|
zfs_fini(void)
|
||||||
{
|
{
|
||||||
|
#if defined(__FreeBSD__)
|
||||||
|
taskq_destroy(zfsvfs_taskq);
|
||||||
|
#endif
|
||||||
zfsctl_fini();
|
zfsctl_fini();
|
||||||
zfs_znode_fini();
|
zfs_znode_fini();
|
||||||
zfs_vnodes_adjust_back();
|
zfs_vnodes_adjust_back();
|
||||||
|
Loading…
Reference in New Issue
Block a user