scrub: RAID10 repair writes to wrong device offsets (data corruption); devices[j+j] typo; RAID56 MDL double free; stale rewrite flag
Audit findings against master @ a0648190 (v1.10), src/scrub.c.
- RAID10 repair writes to the wrong device offset (data corruption) — ~1187-1189 (and 1351-1353):
Status = write_data_phys(c->devices[j + k]->devobj, c->devices[j + k]->fileobj,
c->chunk_item->stripe[j + k].offset + offset - c->offset,
context->stripes[j + goodstripe].buf, context->stripes[j + goodstripe].length);The data was read using the device-relative offset from get_raid0_offset (.start, scrub.c ~1422-1440 / ~1542), but the repair writes at stripe.offset + (chunk-relative logical offset). On a 4-disk RAID10 those differ (logical 0x30000 -> .start 0x10000), so the repair lands 0x20000 off — corrupting an unrelated stripe while leaving the bad one broken. The DUP path sets .start = offset - c->offset explicitly (~1467-1468); the RAID10 branch looks like that formula was copied over. The write offset should be stripe[j + k].offset + context->stripes[j + goodstripe].start.
c->devices[j + j]typo in the all-mirrors-bad branch — ~1291-1295: the inner loop variable isk, soj + jreads past thedevicesarray (1 element on 4 disks, 2 on 6) and dereferences whatever is there;log_errorthen charges the wrong device.RAID56 MDL double free — ~2714-2718: after
MmProbeAndLockPagesthrows, the handler callsIoFreeMdl(...->MdlAddress)without clearing the pointer; the cleanup atend4(~2791-2794) then doesMmUnlockPages+IoFreeMdlon it again. The non-raid56 path (~1532-1537) clears the pointer; this one is missing the= NULL.rewriteflag never reset between batches — initialized once at ~2647, checked at ~2798-2807 inside the per-batch loop: once a stripe was repaired, every later batch rewrites it even if the re-read failed (the ~2765goto end4happens before any verification) — writing back unverified/partial data.missingis reset per batch (~2728/2736) butrewriteis not.
Source: maharmstone/btrfs