diff options
author | Matthew Ahrens <[email protected]> | 2020-07-14 17:51:05 -0700 |
---|---|---|
committer | GitHub <[email protected]> | 2020-07-14 17:51:05 -0700 |
commit | 6774931dfa9e90a88d77d54108eccc26cc2af893 (patch) | |
tree | 12c26da757773da0e5377ba0a1af5af0369fe677 /include | |
parent | 38e2e9ce8327284b2d516874308300aa96102fe9 (diff) |
Extend zdb to print inconsistencies in livelists and metaslabs
Livelists and spacemaps are data structures that are logs of allocations
and frees. Livelists entries are block pointers (blkptr_t). Spacemaps
entries are ranges of numbers, most often used as to track
allocated/freed regions of metaslabs/vdevs.
These data structures can become self-inconsistent, for example if a
block or range can be "double allocated" (two allocation records without
an intervening free) or "double freed" (two free records without an
intervening allocation).
ZDB (as well as zfs running in the kernel) can detect these
inconsistencies when loading livelists and metaslab. However, it
generally halts processing when the error is detected.
When analyzing an on-disk problem, we often want to know the entire set
of inconsistencies, which is not possible with the current behavior.
This commit adds a new flag, `zdb -y`, which analyzes the livelist and
metaslab data structures and displays all of their inconsistencies.
Note that this is different from the leak detection performed by
`zdb -b`, which checks for inconsistencies between the spacemaps and the
tree of block pointers, but assumes the spacemaps are self-consistent.
The specific checks added are:
Verify livelists by iterating through each sublivelists and:
- report leftover FREEs
- report double ALLOCs and double FREEs
- record leftover ALLOCs together with their TXG [see Cross Check]
Verify spacemaps by iterating over each metaslab and:
- iterate over spacemap and then the metaslab's entries in the
spacemap log, then report any double FREEs and double ALLOCs
Verify that livelists are consistenet with spacemaps. The space
referenced by livelists (after using the FREE's to cancel out
corresponding ALLOCs) should be allocated, according to the spacemaps.
Reviewed-by: Serapheim Dimitropoulos <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Co-authored-by: Sara Hartse <[email protected]>
Signed-off-by: Matthew Ahrens <[email protected]>
External-issue: DLPX-66031
Closes #10515
Diffstat (limited to 'include')
-rw-r--r-- | include/sys/metaslab.h | 3 | ||||
-rw-r--r-- | include/sys/space_map.h | 9 |
2 files changed, 12 insertions, 0 deletions
diff --git a/include/sys/metaslab.h b/include/sys/metaslab.h index f8d9c6a82..b3b7f8655 100644 --- a/include/sys/metaslab.h +++ b/include/sys/metaslab.h @@ -137,6 +137,9 @@ void metaslab_set_selected_txg(metaslab_t *, uint64_t); extern int metaslab_debug_load; +range_seg_type_t metaslab_calculate_range_tree_type(vdev_t *vdev, + metaslab_t *msp, uint64_t *start, uint64_t *shift); + #ifdef __cplusplus } #endif diff --git a/include/sys/space_map.h b/include/sys/space_map.h index 81f56076a..cb81e710b 100644 --- a/include/sys/space_map.h +++ b/include/sys/space_map.h @@ -148,6 +148,15 @@ typedef struct space_map_entry { uint32_t sme_vdev; /* max is 2^24-1; SM_NO_VDEVID if not present */ uint64_t sme_offset; /* max is 2^63-1; units of sm_shift */ uint64_t sme_run; /* max is 2^36; units of sm_shift */ + + /* + * The following fields are not part of the actual space map entry + * on-disk and they are populated with the values from the debug + * entry most recently visited starting from the beginning to the + * end of the space map. + */ + uint64_t sme_txg; + uint64_t sme_sync_pass; } space_map_entry_t; #define SM_NO_VDEVID (1 << SPA_VDEVBITS) |