-
Notifications
You must be signed in to change notification settings - Fork 2k
dsl_scan: detect 'unencrypted block in encrypted objset' during scrub #18587
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2380,6 +2380,43 @@ dsl_scan_visitbp(const blkptr_t *bp, const zbookmark_phys_t *zb, | |
| return; | ||
| } | ||
|
|
||
| /* | ||
| * Detect "unencrypted block in encrypted object set" corruption. | ||
| * On an encrypted dataset every BP — leaf data block or indirect — | ||
| * must have BP_USES_CRYPT set. The read path in dbuf.c converts | ||
| * a missing flag to EIO, and the create path historically panicked | ||
| * in zfs_mknode. | ||
| * | ||
| * Log each occurrence so it appears in 'zpool status -v', and | ||
| * count it for the scan's permanent-error tally. Both leaf and | ||
| * indirect levels are checked: leaf BPs store data MAC in blk_cksum | ||
| * directly, while indirect BPs store a MAC-of-MAC computed over | ||
| * their children's MACs (see zio_crypt_do_indirect_mac_checksum_abd | ||
| * in zio_crypt.c). Both forms are corrupted equally when the flag | ||
| * is lost during write, so neither read nor scrub can verify them. | ||
| * | ||
| * Embedded BPs (BP_IS_EMBEDDED) inline their data into the BP | ||
| * itself and never carry the encryption flag — skip them. | ||
| * | ||
| * Refs: #14330 #15275 #16065 #14709 #18186 | ||
| */ | ||
| if (ds != NULL && !BP_IS_EMBEDDED(bp) && !BP_USES_CRYPT(bp)) { | ||
| objset_t *bp_os; | ||
| if (dmu_objset_from_ds(ds, &bp_os) == 0 && | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. openning objset for every unencrypted BP is probably too expensive (several locks in there)? I wonder if we can get away with ds->ds_dir->dd_crypto_obj != 0 here instead? |
||
| bp_os->os_encrypted) { | ||
| scn->scn_phys.scn_errors++; | ||
| spa_log_error(dp->dp_spa, zb, | ||
| BP_GET_PHYSICAL_BIRTH(bp)); | ||
| zfs_dbgmsg("scrub: encrypted objset %llu has BP " | ||
| "without BP_USES_CRYPT (object %llu, " | ||
| "level %u, blkid %llu)", | ||
| (u_longlong_t)zb->zb_objset, | ||
| (u_longlong_t)zb->zb_object, | ||
| (uint_t)zb->zb_level, | ||
| (u_longlong_t)zb->zb_blkid); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there any value to continue scrubbing this BP or should we just |
||
| } | ||
| } | ||
|
|
||
| /* | ||
| * Check if this block contradicts any filesystem flags. | ||
| */ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's mention the read path will also add these blocks to the error log.