diff options
author | Matthew Ahrens <[email protected]> | 2017-03-20 18:36:00 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2017-03-20 18:36:00 -0700 |
commit | 64fc776208ad14b0078b89317b0f3b24338e10c1 (patch) | |
tree | b8c229ca8b052f3aa718a27b97c759a564c8fd78 /module/zfs/zio.c | |
parent | a3478c074752610814f894375c3d947ece4938fe (diff) |
OpenZFS 7968 - multi-threaded spa_sync()
Reviewed by: Pavel Zakharov <[email protected]>
Reviewed by: Brad Lewis <[email protected]>
Reviewed by: Saso Kiselkov <[email protected]>
Reviewed by: Brian Behlendorf <[email protected]>
Ported-by: Matthew Ahrens <[email protected]>
spa_sync() iterates over all the dirty dnodes and processes each of them
by calling dnode_sync(). If there are many dirty dnodes (e.g. because we
created or removed a lot of files), the single thread of spa_sync()
calling dnode_sync() can become a bottleneck. Additionally, if many
dnodes are dirtied concurrently in open context (e.g. due to concurrent
file creation), the os_lock will experience lock contention via
dnode_setdirty().
The solution is to track dirty dnodes on a multilist_t, and for
spa_sync() to use separate threads to process each of the sublists in
the multilist.
OpenZFS-issue: https://www.illumos.org/issues/7968
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/4a2a54c
Closes #5752
Diffstat (limited to 'module/zfs/zio.c')
-rw-r--r-- | module/zfs/zio.c | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/module/zfs/zio.c b/module/zfs/zio.c index 8a3b3066a..8c0543cf9 100644 --- a/module/zfs/zio.c +++ b/module/zfs/zio.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2016 by Delphix. All rights reserved. + * Copyright (c) 2011, 2017 by Delphix. All rights reserved. * Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved. */ @@ -544,21 +544,37 @@ zio_inherit_child_errors(zio_t *zio, enum zio_child c) } int -zio_timestamp_compare(const void *x1, const void *x2) +zio_bookmark_compare(const void *x1, const void *x2) { const zio_t *z1 = x1; const zio_t *z2 = x2; - int cmp; - cmp = AVL_CMP(z1->io_queued_timestamp, z2->io_queued_timestamp); - if (likely(cmp)) - return (cmp); + if (z1->io_bookmark.zb_objset < z2->io_bookmark.zb_objset) + return (-1); + if (z1->io_bookmark.zb_objset > z2->io_bookmark.zb_objset) + return (1); - cmp = AVL_CMP(z1->io_offset, z2->io_offset); - if (likely(cmp)) - return (cmp); + if (z1->io_bookmark.zb_object < z2->io_bookmark.zb_object) + return (-1); + if (z1->io_bookmark.zb_object > z2->io_bookmark.zb_object) + return (1); - return (AVL_PCMP(z1, z2)); + if (z1->io_bookmark.zb_level < z2->io_bookmark.zb_level) + return (-1); + if (z1->io_bookmark.zb_level > z2->io_bookmark.zb_level) + return (1); + + if (z1->io_bookmark.zb_blkid < z2->io_bookmark.zb_blkid) + return (-1); + if (z1->io_bookmark.zb_blkid > z2->io_bookmark.zb_blkid) + return (1); + + if (z1 < z2) + return (-1); + if (z1 > z2) + return (1); + + return (0); } /* @@ -2953,8 +2969,6 @@ zio_dva_throttle(zio_t *zio) return (ZIO_PIPELINE_CONTINUE); if (nio != NULL) { - ASSERT3U(nio->io_queued_timestamp, <=, - zio->io_queued_timestamp); ASSERT(nio->io_stage == ZIO_STAGE_DVA_THROTTLE); /* * We are passing control to a new zio so make sure that |