Skip to content

Commit e022864

Browse files
ahrensbehlendorf
authored andcommitted
Illumos 5176 - lock contention on godfather zio
5176 lock contention on godfather zio Reviewed by: Adam Leventhal <ahl@delphix.com> Reviewed by: Alex Reece <alex.reece@delphix.com> Reviewed by: Christopher Siden <christopher.siden@delphix.com> Reviewed by: George Wilson <george.wilson@delphix.com> Reviewed by: Richard Elling <richard.elling@gmail.com> Reviewed by: Bayard Bell <Bayard.Bell@nexenta.com> Approved by: Garrett D'Amore <garrett@damore.org> References: https://www.illumos.org/issues/5176 illumos/illumos-gate@6f834bc Porting notes: Under Linux max_ncpus is defined as num_possible_cpus(). This is largest number of cpu ids which might be available during the life time of the system boot. This value can be larger than the number of present cpus if CONFIG_HOTPLUG_CPU is defined. Ported by: Turbo Fredriksson <turbo@bayour.com> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #2711
1 parent 07a3312 commit e022864

File tree

4 files changed

+29
-14
lines changed

4 files changed

+29
-14
lines changed

cmd/zdb/zdb.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2565,7 +2565,7 @@ dump_block_stats(spa_t *spa)
25652565
uint64_t norm_alloc, norm_space, total_alloc, total_found;
25662566
int flags = TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA | TRAVERSE_HARD;
25672567
boolean_t leaks = B_FALSE;
2568-
int e;
2568+
int e, c;
25692569
bp_embedded_type_t i;
25702570

25712571
(void) printf("\nTraversing all blocks %s%s%s%s%s...\n\n",
@@ -2614,10 +2614,12 @@ dump_block_stats(spa_t *spa)
26142614
* all async I/Os to complete.
26152615
*/
26162616
if (dump_opt['c']) {
2617-
(void) zio_wait(spa->spa_async_zio_root);
2618-
spa->spa_async_zio_root = zio_root(spa, NULL, NULL,
2619-
ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE |
2620-
ZIO_FLAG_GODFATHER);
2617+
for (c = 0; c < max_ncpus; c++) {
2618+
(void) zio_wait(spa->spa_async_zio_root[c]);
2619+
spa->spa_async_zio_root[c] = zio_root(spa, NULL, NULL,
2620+
ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE |
2621+
ZIO_FLAG_GODFATHER);
2622+
}
26212623
}
26222624

26232625
if (zcb.zcb_haderrors) {

include/sys/spa_impl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,8 @@ struct spa {
204204
uint64_t spa_failmode; /* failure mode for the pool */
205205
uint64_t spa_delegation; /* delegation on/off */
206206
list_t spa_config_list; /* previous cache file(s) */
207-
zio_t *spa_async_zio_root; /* root of all async I/O */
207+
/* per-CPU array of root of async I/O: */
208+
zio_t **spa_async_zio_root;
208209
zio_t *spa_suspend_zio_root; /* root of all suspended I/O */
209210
kmutex_t spa_suspend_lock; /* protects suspend_zio_root */
210211
kcondvar_t spa_suspend_cv; /* notification of resume */

module/zfs/spa.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,7 +1252,9 @@ spa_unload(spa_t *spa)
12521252
* Wait for any outstanding async I/O to complete.
12531253
*/
12541254
if (spa->spa_async_zio_root != NULL) {
1255-
(void) zio_wait(spa->spa_async_zio_root);
1255+
for (i = 0; i < max_ncpus; i++)
1256+
(void) zio_wait(spa->spa_async_zio_root[i]);
1257+
kmem_free(spa->spa_async_zio_root, max_ncpus * sizeof (void *));
12561258
spa->spa_async_zio_root = NULL;
12571259
}
12581260

@@ -2165,7 +2167,7 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
21652167
uberblock_t *ub = &spa->spa_uberblock;
21662168
uint64_t children, config_cache_txg = spa->spa_config_txg;
21672169
int orig_mode = spa->spa_mode;
2168-
int parse;
2170+
int parse, i;
21692171
uint64_t obj;
21702172
boolean_t missing_feat_write = B_FALSE;
21712173

@@ -2189,8 +2191,13 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
21892191
/*
21902192
* Create "The Godfather" zio to hold all async IOs
21912193
*/
2192-
spa->spa_async_zio_root = zio_root(spa, NULL, NULL,
2193-
ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE | ZIO_FLAG_GODFATHER);
2194+
spa->spa_async_zio_root = kmem_alloc(max_ncpus * sizeof (void *),
2195+
KM_SLEEP);
2196+
for (i = 0; i < max_ncpus; i++) {
2197+
spa->spa_async_zio_root[i] = zio_root(spa, NULL, NULL,
2198+
ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE |
2199+
ZIO_FLAG_GODFATHER);
2200+
}
21942201

21952202
/*
21962203
* Parse the configuration into a vdev tree. We explicitly set the
@@ -3495,7 +3502,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
34953502
uint64_t version, obj;
34963503
boolean_t has_features;
34973504
nvpair_t *elem;
3498-
int c;
3505+
int c, i;
34993506
char *poolname;
35003507
nvlist_t *nvl;
35013508

@@ -3556,8 +3563,13 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
35563563
/*
35573564
* Create "The Godfather" zio to hold all async IOs
35583565
*/
3559-
spa->spa_async_zio_root = zio_root(spa, NULL, NULL,
3560-
ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE | ZIO_FLAG_GODFATHER);
3566+
spa->spa_async_zio_root = kmem_alloc(max_ncpus * sizeof (void *),
3567+
KM_SLEEP);
3568+
for (i = 0; i < max_ncpus; i++) {
3569+
spa->spa_async_zio_root[i] = zio_root(spa, NULL, NULL,
3570+
ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE |
3571+
ZIO_FLAG_GODFATHER);
3572+
}
35613573

35623574
/*
35633575
* Create the root vdev.

module/zfs/zio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1474,7 +1474,7 @@ zio_nowait(zio_t *zio)
14741474
*/
14751475
spa_t *spa = zio->io_spa;
14761476

1477-
zio_add_child(spa->spa_async_zio_root, zio);
1477+
zio_add_child(spa->spa_async_zio_root[CPU_SEQID], zio);
14781478
}
14791479

14801480
__zio_execute(zio);

0 commit comments

Comments
 (0)