Repository navigation
DAOS-17321 ddb: Report inconsistent csum metadata in dump_csum - #19177
Conversation
ddb is a recovery tool: the checksum metadata it reads from a pool may be damaged and must be neither trusted nor asserted on. dv_dump_csum() handed the checksum infos returned by VOS straight to its callback, which asserted that the checksum-info count matches the extent count and that every checksum info is valid, and dereferenced the checksum type through daos_mhash_type2algo() without checking it. Validate the fetched metadata in dv_dump_csum() before any callback is invoked: the checksum-info count must be zero or match the stored extents (recx list present), every checksum info must pass ci_is_valid(), its type must be known to the checksum library and its chunk count must cover exactly its extent. Any inconsistency is logged and returned as -DER_CSUM; the callback contract is documented in ddb_vos.h. Add the DDB_CSUM_NR_INJECT, DDB_CSUM_CHUNK_NR_INJECT and DDB_CSUM_TYPE_INJECT fault injection points, ddb_tests fixtures with partially overwritten extents, and the corresponding dump_csum tests (dv_dump_csum() and the print/write csum_dump callbacks). Split off from #18941, which keeps the dv_check_csum() API. Features: recovery Signed-off-by: Cedric Koch-Hofer <cedric.koch-hofer@hpe.com>
e40577c to
85dc692
Compare
|
Ticket title is 'Checksum management with ddb' |
|
Test stage Functional Hardware Medium MD on SSD completed with status FAILURE. https://jenkins-3.daos.hpc.amslabs.hpecorp.net//job/daos-stack/job/daos/view/change-requests/job/PR-19177/2/execution/node/1892/log |
…/daos-17321/patch-009 Features: recovery
…/daos-17321/patch-009 Features: recovery
janekmi
left a comment
There was a problem hiding this comment.
Have you considered simply mocking VOS interfaces and test just the DDB logic here? It looks like a lot of effort is actually put in testing the VOS logic here.
I understand if you decide to leave it as it is. In this PR you are only improving already existing tests. Re-writing all of this will be probably a significant effort but with a potential to also significantly simplify all of this test code.
@janekmi thanks for the suggestion. I actually tried mocking the VOS interfaces while the work was still in the original PR #18941, before splitting it (short summary in #18941 (comment)). It worked, but needed a lot of plumbing, which is why I settled on fault injection. In more detail: the count mismatch cannot be built through the VOS API (a "mixed" akey, with one extent written with a checksum and one without, still gets a checksum info for every extent), so I prototyped two mock variants: a single |
…/daos-17321/patch-009
…/daos-17321/patch-009 Features: recovery Signed-off-by: Cedric Koch-Hofer <cedric.koch-hofer@hpe.com>
Follow-up of the review of #19177: - ddb_vos.h: document when dv_dump_csum() invokes its callback, list its return values and reword the contract of the checksum info list. - ddb_vos.c: log the object, dkey and akey in the checksum metadata error messages and log a callback failure with D_ERROR. - ddb tests: drop the redundant fault injection setup, name the akeys of the checksum fixtures (DVT_FAKE_CSUM_AKEY_*), take uint64_t in the injection helpers, pass no cb_arg when there is no callback, use DAOS_EPOCH_MAX in the comments, and let the checksum fixture helpers assert instead of handling errors (write_maybe_corrupt() and csum_test_*_setup() return void, ddb_test_csum_setup() no longer unwinds). Features: recovery Signed-off-by: Cedric Koch-Hofer <cedric.koch-hofer@hpe.com>
Follow-up of the review of #19177: - Write the macro name DAOS_EPOCH_MAX instead of EPOCH_MAX in the comments of print_csum_sv_tests() and write_csum_sv_tests(). - In the extent-layout comments of print_csum_recx_tests() and write_csum_recx_tests(), label the object "oid", the name of the argument of csum_test_recx_path_init(), instead of "g_oid", which is not an identifier. Comments only, no functional change. Features: recovery Signed-off-by: Cedric Koch-Hofer <cedric.koch-hofer@hpe.com>
|
Test stage Functional on EL 9 completed with status FAILURE. https://jenkins-3.daos.hpc.amslabs.hpecorp.net//job/daos-stack/job/daos/view/change-requests/job/PR-19177/6/execution/node/1373/log |
|
Test stage Functional Hardware Medium MD on SSD completed with status FAILURE. https://jenkins-3.daos.hpc.amslabs.hpecorp.net//job/daos-stack/job/daos/view/change-requests/job/PR-19177/8/execution/node/621/log |
|
Test stage Functional Hardware Medium MD on SSD completed with status UNSTABLE. https://jenkins-3.daos.hpc.amslabs.hpecorp.net/job/daos-stack/job/daos//view/change-requests/job/PR-19177/7/testReport/ |
…/daos-17321/patch-009 Features: recovery
|
Test stage Functional Hardware Medium Provider MD on SSD completed with status FAILURE. https://jenkins-3.daos.hpc.amslabs.hpecorp.net//job/daos-stack/job/daos/view/change-requests/job/PR-19177/9/execution/node/2028/log |
…/daos-17321/patch-009 Features: recovery
|
Test stage Functional on EL 9 completed with status FAILURE. https://jenkins-3.daos.hpc.amslabs.hpecorp.net//job/daos-stack/job/daos/view/change-requests/job/PR-19177/10/execution/node/1372/log |
…/daos-17321/patch-009 Features: recovery
|
Test stage Functional Hardware Medium Provider MD on SSD completed with status FAILURE. https://jenkins-3.daos.hpc.amslabs.hpecorp.net//job/daos-stack/job/daos/view/change-requests/job/PR-19177/10/execution/node/1876/log |
|
Test stage Functional Hardware Medium MD on SSD completed with status FAILURE. https://jenkins-3.daos.hpc.amslabs.hpecorp.net//job/daos-stack/job/daos/view/change-requests/job/PR-19177/10/execution/node/1819/log |
|
@daos-stack/daos-gatekeeper could you lend this PR with the following message:
|
This patch is split off from the PR #18941 , which had grown too large to review as a single PR. It carries the hardening of the existing
csum_dumppath, while #18941 keeps the newdv_check_csum()API. Once this patch has landed, master will be merged into #18941 so that only the check part remains there.The principle behind the change was raised during the review of #18941: ddb is a recovery tool, so the checksum metadata it reads from a possibly damaged pool must be neither trusted nor asserted on.
dv_dump_csum()handed the checksum infos returned by VOS straight to its callback. Thecsum_dumpcallbacks ofddb_commands.cthen asserted that the checksum-info count matches the extent count and that every checksum info is valid, and dereferenced the checksum type throughdaos_mhash_type2algo()without checking it. A pool with corrupted checksum metadata could therefore crash ddb instead of getting an error.validate the fetched checksum metadata (
ddb_vos.c,ddb_vos.h)dump_csum_sv()anddump_csum_recx()now check what theVOS_OF_FETCH_CSUMfetch returned before invoking the callback:evt_entry_csum_fill()reports a checksum info for every non-hole extent whileakey_fetch_recx()records one recx per such extent. A count that does not match denotes corrupted metadata or a broken VOS invariant.csum_info_check()). Every entry must passci_is_valid()(sizes, count, buffer), and its checksum type must be known to the checksum library (daos_mhash_type2algo()), since the callbacks rely on that lookup to print the type name.csum_recx_check_chunks()). The number of checksums of a recx entry must be the number of chunks of its extent (daos_recx_calc_chunks()). Since DAOS-19629 (DAOS-19629 vos: Do not trim checksums fetched with VOS_OF_FETCH_CSUM #19057) VOS no longer trims the checksums fetched withVOS_OF_FETCH_CSUM, so every recx-list entry is reported with its whole physical extent and its checksum info covers all of its chunks; a mismatch used to be printed silently as aRecord Indexesline paired with too few checksum values.Every inconsistency is logged with
D_ERRORand returned as-DER_CSUMwithout invoking the callback, the way a data mismatch is reported. The callback contract is exhaustively documented inddb_vos.h.For the existing
csum_dumpcallbacks ofddb_commands.c(untouched here), theD_ASSERT()s on the count and onci_is_valid()and thedaos_mhash_type2algo()dereference are now guaranteed by the API contract. On a pool with inconsistent checksum metadata, theddbCLI reportsDER_CSUM(-1032): Checksum errorand the details go to the DAOS log, instead of an abort.Fault injection (
common.h)Three new fail-locs in the DDB group make the error paths testable on a real pool, since VOS cannot produce such metadata:
DDB_CSUM_NR_INJECTforges the checksum-info count,DDB_CSUM_CHUNK_NR_INJECTthe chunk count of a checksum info andDDB_CSUM_TYPE_INJECTan unknown checksum type. The corresponding tests skip on builds withoutFAULT_INJECTION.Test fixtures (
tests/ddb_test_driver.c,tests/ddb_test_driver.h)The checksum fixtures now name their objects and the data bytes they write with the
DVT_FAKE_CSUM_OID_*andDVT_FAKE_PART_*constants, so that the tests refer to the fixture objects by role instead of by index.csum_test_partial_recx_setup()adds an object with an older extent A = [0, S)@1 whose leading chunk is overwritten by a newer extent B = [0, S/2)@2, and keeps their checksum infos indct_part_icsso that the tests can check that A is reported with the checksums of both its visible and its hidden chunk.Tests (
tests/ddb_vos_tests.c,tests/ddb_commands_tests.c,tests/ddb_cmocka.h)dump_csum_error_testsvos_cont_openfailure propagationdump_csum_sv_testsDAOS_EPOCH_MAX(latest version); no-callback no-op; callback-error propagationdump_csum_recx_testsrecx_rel == NULLand an empty list); no-callback no-op; callback-error propagationdump_csum_sv_inconsistent_tests(FI)dcs_csum_info_get()returns NULL); unknown checksum type →-DER_CSUM, callback not invoked; control step with the consistent countdump_csum_recx_inconsistent_tests(FI)-DER_CSUM, callback not invoked; control steps with the consistent countsprint_csum_recx_tests,write_csum_recx_testscsum_dumpoutput for the partially overwritten fixture: oneRecord Indexesline per stored extent, in extent order, with every chunk checksum (printed_count(),assert_strings_in_order())ddb_cmocka.hgains theassert_string_contains()andassert_strings_in_order()helpers used by the command tests.Local Validation
ddb_tests76/76 on a fault-injection build, including the checksum cases ofddb_vos_testsandddb_commands_tests, also clean under valgrind;ddb_ut22/22.cksum:crc16container and a container without checksums: 420csum_dumpinvocations over everyakey_sv_*andakey_array_*path of the pool, all exiting 0 with the expectedcrc16values orNo checksum atlines.Steps for the author:
After all prior steps are complete: