aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChunwei Chen <[email protected]>2018-02-01 15:42:41 -0800
committerBrian Behlendorf <[email protected]>2018-02-09 10:08:40 -0800
commit0c0b0ad48addf342fcff29253a40282c00d5ce65 (patch)
treeac347dacf08245fea391f19894dc41cd97c58fe8
parentf108a49236ee21bab807c0c6750409b6912ef05e (diff)
Fix racy assignment of zcb.zcb_haderrors
zcb_haderrors will be modified in zdb_blkptr_done, which is asynchronous. So we must move this assignment after zio_wait. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: loli10K <[email protected]> Signed-off-by: Chunwei Chen <[email protected]> Closes #7099
-rw-r--r--cmd/zdb/zdb.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c
index 3719d22e1..c381d02a3 100644
--- a/cmd/zdb/zdb.c
+++ b/cmd/zdb/zdb.c
@@ -3388,7 +3388,7 @@ dump_block_stats(spa_t *spa)
int flags = TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA |
TRAVERSE_NO_DECRYPT | TRAVERSE_HARD;
boolean_t leaks = B_FALSE;
- int e, c;
+ int e, c, err;
bp_embedded_type_t i;
bzero(&zcb, sizeof (zcb));
@@ -3430,7 +3430,7 @@ dump_block_stats(spa_t *spa)
zcb.zcb_totalasize = metaslab_class_get_alloc(spa_normal_class(spa));
zcb.zcb_start = zcb.zcb_lastprint = gethrtime();
- zcb.zcb_haderrors |= traverse_pool(spa, 0, flags, zdb_blkptr_cb, &zcb);
+ err = traverse_pool(spa, 0, flags, zdb_blkptr_cb, &zcb);
/*
* If we've traversed the data blocks then we need to wait for those
@@ -3446,6 +3446,12 @@ dump_block_stats(spa_t *spa)
}
}
+ /*
+ * Done after zio_wait() since zcb_haderrors is modified in
+ * zdb_blkptr_done()
+ */
+ zcb.zcb_haderrors |= err;
+
if (zcb.zcb_haderrors) {
(void) printf("\nError counts:\n\n");
(void) printf("\t%5s %s\n", "errno", "count");