20#define SCRUB_UNIT 0x100000
53 bool orig_subvol =
true, not_in_tree =
false;
59 le =
Vcb->roots.Flink;
60 while (le != &
Vcb->roots) {
63 if (
r2->id == subvol) {
72 ERR(
"could not find subvol %I64x\n", subvol);
81 if (
dir ==
r->root_item.objid) {
82 if (
r ==
Vcb->root_fileref->fcb->subvol)
87 searchkey.
offset = 0xffffffffffffffff;
91 ERR(
"find_item returned %08lx\n",
Status);
112 ERR(
"out of memory\n");
116 pp->name.Buffer = rr->
name;
117 pp->name.Length = pp->name.MaximumLength = rr->
n;
118 pp->orig_subvol =
false;
124 le =
Vcb->roots.Flink;
125 while (le != &
Vcb->roots) {
150 searchkey.
offset = 0xffffffffffffffff;
154 ERR(
"find_item returned %08lx\n",
Status);
175 ERR(
"out of memory\n");
179 pp->name.Buffer = ir->
name;
180 pp->name.Length = pp->name.MaximumLength = ir->
n;
181 pp->orig_subvol = orig_subvol;
207 ERR(
"out of memory\n");
211 pp->name.Buffer = ier->
name;
212 pp->name.Length = pp->name.MaximumLength = ier->
n;
213 pp->orig_subvol = orig_subvol;
222 ERR(
"could not find INODE_REF for inode %I64x in subvol %I64x\n",
dir,
r->id);
228 fn.MaximumLength = 0;
232 while (le != &
parts) {
247 while (le != &
parts) {
257 ERR(
"out of memory\n");
264 while (le != &
parts) {
267 fn.Buffer[
fn.Length] =
'\\';
277 ERR(
"subvol %I64x, %.*s, offset %I64x\n", subvol,
fn.Length,
fn.Buffer,
offset);
283 ERR(
"utf8_to_utf16 1 returned %08lx\n",
Status);
290 ERR(
"out of memory\n");
297 err->recovered =
false;
298 err->is_metadata =
false;
301 err->data.subvol = not_in_tree ? subvol : 0;
307 ERR(
"utf8_to_utf16 2 returned %08lx\n",
Status);
315 Vcb->scrub.num_errors++;
338 ERR(
"out of memory\n");
342 Status =
read_data(
Vcb, treeaddr,
Vcb->superblock.node_size,
NULL,
true, (
uint8_t*)
tree,
NULL,
NULL,
NULL, 0,
false,
NormalPagePriority);
344 ERR(
"read_data returned %08lx\n",
Status);
348 if (
tree->level != 0) {
349 ERR(
"tree level was %x, expected 0\n",
tree->level);
355 for (
i = 0;
i <
tree->num_items;
i++) {
374 ERR(
"out of memory\n");
380 err->recovered =
false;
381 err->is_metadata =
true;
388 ERR(
"root %I64x, level %u, first item (%I64x,%x,%I64x)\n",
root,
level, firstitem->
obj_id,
391 err->metadata.firstitem = *firstitem;
400 Vcb->scrub.num_errors++;
414 ERR(
"out of memory\n");
418 Status =
read_data(
Vcb,
offset,
Vcb->superblock.node_size,
NULL,
true, (
uint8_t*)
tree,
NULL,
NULL,
NULL, 0,
false,
NormalPagePriority);
420 ERR(
"read_data returned %08lx\n",
Status);
424 if (
tree->level == 0) {
425 ERR(
"tree level was 0\n");
431 for (
i = 0;
i <
tree->num_items;
i++) {
456 searchkey.
offset = 0xffffffffffffffff;
460 ERR(
"find_item returned %08lx\n",
Status);
505 ERR(
"TREE_BLOCK_REF takes up %Iu bytes, but only %lu remaining\n",
sizeof(
TREE_BLOCK_REF),
len);
566 ERR(
"unknown extent type %x\n",
type);
571 if (rc < ei->refcount) {
610 ERR(
"recovering from parity error at %I64x on device %I64x\n",
addr, devid);
613 ERR(
"recovering from metadata checksum error at %I64x on device %I64x\n",
addr, devid);
615 ERR(
"recovering from data checksum error at %I64x on device %I64x\n",
addr, devid);
620 ERR(
"out of memory\n");
626 err->recovered =
true;
628 err->parity = parity;
637 Vcb->scrub.num_errors++;
643 ERR(
"unrecoverable metadata checksum error at %I64x\n",
addr);
645 ERR(
"unrecoverable data checksum error at %I64x\n",
addr);
669 bool csum_error =
false;
675 ULONG good_stripe = 0xffffffff;
677 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
678 if (
c->devices[
i]->devobj) {
682 if (good_stripe != 0xffffffff) {
685 context->stripes[
i].csum_error =
true;
692 context->stripes[
i].csum_error =
true;
696 ERR(
"check_csum returned %08lx\n",
Status);
704 ULONG good_stripe = 0xffffffff;
706 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
709 if (
c->devices[
i]->devobj) {
711 if (good_stripe != 0xffffffff) {
714 context->stripes[
i].csum_error =
true;
719 for (
j = 0;
j <
context->stripes[
i].length /
Vcb->superblock.node_size;
j++) {
723 context->stripes[
i].csum_error =
true;
729 if (!
context->stripes[
i].csum_error)
741 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
742 if (
context->stripes[
i].csum_error) {
745 if (!
context->stripes[
i].bad_csums) {
746 ERR(
"out of memory\n");
755 if (!
context->stripes[
i].bad_csums) {
756 ERR(
"out of memory\n");
760 for (
j = 0;
j <
context->stripes[
i].length /
Vcb->superblock.node_size;
j++) {
769 if (present_devices > 1) {
770 ULONG good_stripe = 0xffffffff;
772 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
773 if (
c->devices[
i]->devobj && !
context->stripes[
i].csum_error) {
779 if (good_stripe != 0xffffffff) {
782 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
783 if (
context->stripes[
i].csum_error) {
787 for (
j = 0;
j <
context->stripes[
i].length >>
Vcb->sector_shift;
j++) {
796 for (
j = 0;
j <
context->stripes[
i].length /
Vcb->superblock.node_size;
j++) {
811 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
812 if (
context->stripes[
i].csum_error && !
c->devices[
i]->readonly) {
817 ERR(
"write_data_phys returned %08lx\n",
Status);
829 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
830 if (
c->devices[
i]->devobj) {
836 bool recovered =
false;
838 for (
k = 0;
k <
c->chunk_item->num_stripes;
k++) {
839 if (
i !=
k &&
c->devices[
k]->devobj &&
846 context->stripes[
k].buf + (
j <<
Vcb->sector_shift),
Vcb->superblock.sector_size);
866 bool recovered =
false;
868 for (
k = 0;
k <
c->chunk_item->num_stripes;
k++) {
869 if (
i !=
k &&
c->devices[
k]->devobj) {
896 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
897 if (
c->devices[
i]->devobj && !
c->devices[
i]->readonly) {
901 ERR(
"write_data_phys returned %08lx\n",
Status);
911 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
912 if (
c->devices[
i]->devobj) {
916 for (
j = 0;
j <
context->stripes[
i].length >>
Vcb->sector_shift;
j++) {
924 for (
j = 0;
j <
context->stripes[
i].length /
Vcb->superblock.node_size;
j++) {
946 ERR(
"out of memory\n");
962 for (
j = 0;
j < readlen;
j +=
Vcb->superblock.sector_size) {
970 pos +=
Vcb->superblock.sector_size;
971 stripeoff[
stripe] +=
Vcb->superblock.sector_size;
974 for (
j = 0;
j < readlen;
j +=
Vcb->superblock.node_size) {
983 pos +=
Vcb->superblock.node_size;
984 stripeoff[
stripe] +=
Vcb->superblock.node_size;
1000 bool csum_error =
false;
1006 ERR(
"out of memory\n");
1018 c->chunk_item->stripe_length - (
context->stripes[
stripe * sub_stripes].start %
c->chunk_item->stripe_length));
1023 ULONG good_stripe = 0xffffffff;
1026 for (
k = 0;
k < sub_stripes;
k++) {
1027 if (
c->devices[(
stripe * sub_stripes) +
k]->devobj) {
1029 if (good_stripe != 0xffffffff) {
1032 readlen) != readlen) {
1038 for (
j = 0;
j < readlen;
j +=
Vcb->superblock.sector_size) {
1055 stripeoff[
stripe] += readlen;
1057 ULONG good_stripe = 0xffffffff;
1060 for (
k = 0;
k < sub_stripes;
k++) {
1061 if (
c->devices[(
stripe * sub_stripes) +
k]->devobj) {
1063 if (good_stripe != 0xffffffff) {
1066 readlen) != readlen) {
1072 for (
j = 0;
j < readlen;
j +=
Vcb->superblock.node_size) {
1091 stripeoff[
stripe] += readlen;
1094 stripe = (
stripe + 1) % (
c->chunk_item->num_stripes / sub_stripes);
1102 for (
j = 0;
j <
c->chunk_item->num_stripes;
j += sub_stripes) {
1103 ULONG goodstripe = 0xffffffff;
1105 bool hasbadstripe =
false;
1107 if (
context->stripes[
j].length == 0)
1110 for (
k = 0;
k < sub_stripes;
k++) {
1111 if (
c->devices[
j +
k]->devobj) {
1112 if (!
context->stripes[
j +
k].csum_error)
1115 hasbadstripe =
true;
1120 if (goodstripe != 0xffffffff) {
1121 for (
k = 0;
k < sub_stripes;
k++) {
1122 if (
c->devices[
j +
k]->devobj &&
context->stripes[
j +
k].csum_error) {
1124 bool recovered =
false;
1134 c->chunk_item->stripe_length - (
context->stripes[
stripe * sub_stripes].start %
c->chunk_item->stripe_length));
1138 if (
stripe ==
j / sub_stripes) {
1142 for (
l = 0;
l < readlen;
l +=
Vcb->superblock.sector_size) {
1144 context->stripes[
j + goodstripe].buf + so,
1145 Vcb->superblock.sector_size) !=
Vcb->superblock.sector_size) {
1153 pos +=
Vcb->superblock.sector_size;
1154 so +=
Vcb->superblock.sector_size;
1159 for (
l = 0;
l < readlen;
l +=
Vcb->superblock.node_size) {
1161 context->stripes[
j + goodstripe].buf + so,
1162 Vcb->superblock.node_size) !=
Vcb->superblock.node_size) {
1170 pos +=
Vcb->superblock.node_size;
1171 so +=
Vcb->superblock.node_size;
1177 stripe = (
stripe + 1) % (
c->chunk_item->num_stripes / sub_stripes);
1183 if (!
c->devices[
j +
k]->readonly) {
1187 context->stripes[
j + goodstripe].buf,
context->stripes[
j + goodstripe].length);
1190 ERR(
"write_data_phys returned %08lx\n",
Status);
1200 bool recovered =
false;
1203 for (
k = 0;
k < sub_stripes;
k++) {
1204 if (
c->devices[
j +
k]->devobj) {
1207 if (!
context->stripes[
j +
k].bad_csums) {
1208 ERR(
"out of memory\n");
1217 for (
k = 0;
k < sub_stripes;
k++) {
1218 if (
c->devices[
j +
k]->devobj) {
1223 if (!
context->stripes[
j +
k].bad_csums) {
1224 ERR(
"out of memory\n");
1229 for (
l = 0;
l <
context->stripes[
j +
k].length /
Vcb->superblock.node_size;
l++) {
1246 c->chunk_item->stripe_length - (
context->stripes[
stripe * sub_stripes].start %
c->chunk_item->stripe_length));
1250 if (
stripe ==
j / sub_stripes) {
1254 for (
l = 0;
l < readlen;
l +=
Vcb->superblock.sector_size) {
1255 bool has_error =
false;
1257 goodstripe = 0xffffffff;
1258 for (
k = 0;
k < sub_stripes;
k++) {
1259 if (
c->devices[
j +
k]->devobj) {
1262 Vcb->csum_size) !=
Vcb->csum_size) {
1270 if (goodstripe != 0xffffffff) {
1271 for (
k = 0;
k < sub_stripes;
k++) {
1272 if (
c->devices[
j +
k]->devobj &&
1275 Vcb->csum_size) !=
Vcb->csum_size) {
1283 Vcb->superblock.sector_size);
1289 for (
k = 0;
k < sub_stripes;
k++) {
1290 if (
c->devices[
j +
j]->devobj) {
1298 pos +=
Vcb->superblock.sector_size;
1299 so +=
Vcb->superblock.sector_size;
1302 for (
l = 0;
l < readlen;
l +=
Vcb->superblock.node_size) {
1303 for (
k = 0;
k < sub_stripes;
k++) {
1304 if (
c->devices[
j +
k]->devobj) {
1313 for (
m = 0;
m < sub_stripes;
m++) {
1335 pos +=
Vcb->superblock.node_size;
1336 so +=
Vcb->superblock.node_size;
1342 stripe = (
stripe + 1) % (
c->chunk_item->num_stripes / sub_stripes);
1348 for (
k = 0;
k < sub_stripes;
k++) {
1349 if (
c->devices[
j +
k]->devobj && !
c->devices[
j +
k]->readonly) {
1356 ERR(
"write_data_phys returned %08lx\n",
Status);
1380 uint16_t startoffstripe = 0, num_missing, allowed_missing;
1382 TRACE(
"(%p, %p, %lx, %I64x, %x, %p)\n",
Vcb,
c,
type,
offset,
size,
csum);
1386 ERR(
"out of memory\n");
1401 get_raid0_offset(
offset -
c->offset,
c->chunk_item->stripe_length,
c->chunk_item->num_stripes, &startoff, &startoffstripe);
1404 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
1405 if (startoffstripe >
i)
1406 context.stripes[
i].start = startoff - (startoff %
c->chunk_item->stripe_length) +
c->chunk_item->stripe_length;
1407 else if (startoffstripe ==
i)
1408 context.stripes[
i].start = startoff;
1410 context.stripes[
i].start = startoff - (startoff %
c->chunk_item->stripe_length);
1412 if (endoffstripe >
i)
1413 context.stripes[
i].length = (
uint32_t)(endoff - (endoff %
c->chunk_item->stripe_length) +
c->chunk_item->stripe_length -
context.stripes[
i].start);
1414 else if (endoffstripe ==
i)
1420 allowed_missing = 0;
1423 uint16_t endoffstripe,
j, sub_stripes =
max(
c->chunk_item->sub_stripes, 1);
1425 get_raid0_offset(
offset -
c->offset,
c->chunk_item->stripe_length,
c->chunk_item->num_stripes / sub_stripes, &startoff, &startoffstripe);
1426 get_raid0_offset(
offset +
size -
c->offset - 1,
c->chunk_item->stripe_length,
c->chunk_item->num_stripes / sub_stripes, &endoff, &endoffstripe);
1428 if ((
c->chunk_item->num_stripes % sub_stripes) != 0) {
1429 ERR(
"chunk %I64x: num_stripes %x was not a multiple of sub_stripes %x!\n",
c->offset,
c->chunk_item->num_stripes, sub_stripes);
1434 startoffstripe *= sub_stripes;
1435 endoffstripe *= sub_stripes;
1437 for (
i = 0;
i <
c->chunk_item->num_stripes;
i += sub_stripes) {
1438 if (startoffstripe >
i)
1439 context.stripes[
i].start = startoff - (startoff %
c->chunk_item->stripe_length) +
c->chunk_item->stripe_length;
1440 else if (startoffstripe ==
i)
1441 context.stripes[
i].start = startoff;
1443 context.stripes[
i].start = startoff - (startoff %
c->chunk_item->stripe_length);
1445 if (endoffstripe >
i)
1446 context.stripes[
i].length = (
uint32_t)(endoff - (endoff %
c->chunk_item->stripe_length) +
c->chunk_item->stripe_length -
context.stripes[
i].start);
1447 else if (endoffstripe ==
i)
1452 for (
j = 1;
j < sub_stripes;
j++) {
1458 startoffstripe /= sub_stripes;
1459 allowed_missing = 1;
1461 allowed_missing =
c->chunk_item->num_stripes - 1;
1465 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
1474 ERR(
"unexpected chunk type %lx\n",
type);
1479 if (!
c->devices[
i]->devobj) {
1482 if (num_missing > allowed_missing) {
1483 ERR(
"too many missing devices (at least %u, maximum allowed %u)\n", num_missing, allowed_missing);
1487 }
else if (
context.stripes[
i].length > 0) {
1491 ERR(
"out of memory\n");
1499 ERR(
"IoAllocateIrp failed\n");
1510 if (!
context.stripes[
i].Irp->AssociatedIrp.SystemBuffer) {
1511 ERR(
"out of memory\n");
1521 if (!
context.stripes[
i].Irp->MdlAddress) {
1522 ERR(
"IoAllocateMdl failed\n");
1536 ERR(
"MmProbeAndLockPages threw exception %08lx\n",
Status);
1553 Vcb->scrub.data_scrubbed +=
context.stripes[
i].length;
1557 if (
context.stripes_left == 0) {
1558 ERR(
"error - not reading any stripes\n");
1565 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
1566 if (
c->devices[
i]->devobj &&
context.stripes[
i].length > 0)
1573 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
1584 ERR(
"scrub_extent_dup returned %08lx\n",
Status);
1590 ERR(
"scrub_extent_raid0 returned %08lx\n",
Status);
1596 ERR(
"scrub_extent_raid10 returned %08lx\n",
Status);
1603 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
1631 while (runlength != 0) {
1632 if (
index >= bmplen)
1635 if (
index + runlength >= bmplen) {
1636 runlength = bmplen -
index;
1653 ERR(
"scrub_data_extent_dup returned %08lx\n",
Status);
1659 }
while (runlength > 0);
1708 ULONG sectors_per_stripe = (
ULONG)(
c->chunk_item->stripe_length >>
Vcb->sector_shift), off;
1709 uint16_t stripe, parity = (bit_start +
num +
c->chunk_item->num_stripes - 1) %
c->chunk_item->num_stripes;
1712 stripe = (parity + 1) %
c->chunk_item->num_stripes;
1713 off = (
ULONG)(bit_start +
num - stripe_start) * sectors_per_stripe * (
c->chunk_item->num_stripes - 1);
1714 stripeoff =
num * sectors_per_stripe;
1716 if (missing_devices == 0)
1719 while (
stripe != parity) {
1722 for (
ULONG i = 0;
i < sectors_per_stripe;
i++) {
1726 uint64_t addr =
c->offset + (stripe_start * (
c->chunk_item->num_stripes - 1) *
c->chunk_item->stripe_length) + (off <<
Vcb->sector_shift);
1732 if (missing_devices > 0)
1736 off +=
Vcb->superblock.node_size >>
Vcb->sector_shift;
1737 stripeoff +=
Vcb->superblock.node_size >>
Vcb->sector_shift;
1738 i += (
Vcb->superblock.node_size >>
Vcb->sector_shift) - 1;
1746 if (missing_devices > 0) {
1747 uint64_t addr =
c->offset + (stripe_start * (
c->chunk_item->num_stripes - 1) *
c->chunk_item->stripe_length) + (off <<
Vcb->sector_shift);
1759 if (missing_devices == 0)
1763 stripeoff =
num * sectors_per_stripe;
1768 if (missing_devices == 0) {
1771 for (
ULONG i = 0;
i < sectors_per_stripe;
i++) {
1774 o =
i <<
Vcb->sector_shift;
1775 for (
j = 0;
j <
Vcb->superblock.sector_size;
j++) {
1776 if (
context->parity_scratch[o] != 0) {
1787 if (missing_devices > 0)
1790 for (
ULONG i = 0;
i < sectors_per_stripe;
i++) {
1795 stripe = (parity + 1) %
c->chunk_item->num_stripes;
1796 off = (
ULONG)((bit_start +
num - stripe_start) * sectors_per_stripe * (
c->chunk_item->num_stripes - 1)) +
i;
1798 while (
stripe != parity) {
1809 off += sectors_per_stripe;
1822 do_xor(&
context->stripes[parity].buf[(
num *
c->chunk_item->stripe_length) + (
i <<
Vcb->sector_shift)],
1824 Vcb->superblock.sector_size);
1826 bad_off = (
ULONG)((bit_start +
num - stripe_start) * sectors_per_stripe * (
c->chunk_item->num_stripes - 1)) +
i;
1827 addr =
c->offset + (stripe_start * (
c->chunk_item->num_stripes - 1) *
c->chunk_item->stripe_length) + (bad_off <<
Vcb->sector_shift);
1829 context->stripes[parity].rewrite =
true;
1834 uint64_t addr =
c->offset + (stripe_start * (
c->chunk_item->num_stripes - 1) *
c->chunk_item->stripe_length) + (bad_off <<
Vcb->sector_shift);
1840 &
context->stripes[bad_stripe].buf[(
num *
c->chunk_item->stripe_length) + (
i <<
Vcb->sector_shift)],
1841 Vcb->superblock.node_size);
1847 &
context->parity_scratch[
i <<
Vcb->sector_shift],
Vcb->superblock.node_size);
1849 context->stripes[bad_stripe].rewrite =
true;
1853 log_error(
Vcb,
addr,
c->devices[bad_stripe]->devitem.dev_id,
true,
true,
false);
1855 log_error(
Vcb,
addr,
c->devices[bad_stripe]->devitem.dev_id,
true,
false,
false);
1860 &
context->stripes[bad_stripe].buf[(
num *
c->chunk_item->stripe_length) + (
i <<
Vcb->sector_shift)],
1861 Vcb->superblock.sector_size);
1867 &
context->parity_scratch[
i <<
Vcb->sector_shift],
Vcb->superblock.sector_size);
1869 context->stripes[bad_stripe].rewrite =
true;
1871 log_error(
Vcb,
addr,
c->devices[bad_stripe]->devitem.dev_id,
false,
true,
false);
1873 log_error(
Vcb,
addr,
c->devices[bad_stripe]->devitem.dev_id,
false,
false,
false);
1876 stripe = (parity + 1) %
c->chunk_item->num_stripes;
1877 off = (
ULONG)((bit_start +
num - stripe_start) * sectors_per_stripe * (
c->chunk_item->num_stripes - 1)) +
i;
1879 while (
stripe != parity) {
1882 uint64_t addr =
c->offset + (stripe_start * (
c->chunk_item->num_stripes - 1) *
c->chunk_item->stripe_length) + (off <<
Vcb->sector_shift);
1888 off += sectors_per_stripe;
1897 ULONG sectors_per_stripe = (
ULONG)(
c->chunk_item->stripe_length >>
Vcb->sector_shift), off;
1898 uint16_t stripe, parity1 = (bit_start +
num +
c->chunk_item->num_stripes - 2) %
c->chunk_item->num_stripes;
1899 uint16_t parity2 = (parity1 + 1) %
c->chunk_item->num_stripes;
1902 stripe = (parity1 + 2) %
c->chunk_item->num_stripes;
1903 off = (
ULONG)(bit_start +
num - stripe_start) * sectors_per_stripe * (
c->chunk_item->num_stripes - 2);
1904 stripeoff =
num * sectors_per_stripe;
1906 if (
c->devices[parity1]->devobj)
1909 if (
c->devices[parity2]->devobj)
1912 while (
stripe != parity1) {
1915 for (
ULONG i = 0;
i < sectors_per_stripe;
i++) {
1919 uint64_t addr =
c->offset + (stripe_start * (
c->chunk_item->num_stripes - 2) *
c->chunk_item->stripe_length) + (off <<
Vcb->sector_shift);
1925 if (missing_devices == 2)
1929 off +=
Vcb->superblock.node_size >>
Vcb->sector_shift;
1930 stripeoff +=
Vcb->superblock.node_size >>
Vcb->sector_shift;
1931 i += (
Vcb->superblock.node_size >>
Vcb->sector_shift) - 1;
1940 uint64_t addr =
c->offset + (stripe_start * (
c->chunk_item->num_stripes - 2) *
c->chunk_item->stripe_length) + (off <<
Vcb->sector_shift);
1945 if (missing_devices == 2)
1955 if (
c->devices[parity1]->devobj)
1959 stripeoff =
num * sectors_per_stripe;
1964 if (missing_devices == 0 || (missing_devices == 1 && !
c->devices[parity2]->devobj)) {
1967 for (
ULONG i = 0;
i < sectors_per_stripe;
i++) {
1970 o =
i <<
Vcb->sector_shift;
1971 for (
j = 0;
j <
Vcb->superblock.sector_size;
j++) {
1972 if (
context->parity_scratch[o] != 0) {
1983 if (missing_devices == 0 || (missing_devices == 1 && !
c->devices[parity1]->devobj)) {
1986 stripe = parity1 == 0 ? (
c->chunk_item->num_stripes - 1) : (parity1 - 1);
1988 while (
stripe != parity2) {
1995 for (
ULONG i = 0;
i < sectors_per_stripe;
i++) {
1997 &
context->parity_scratch2[
i <<
Vcb->sector_shift],
Vcb->superblock.sector_size) !=
Vcb->superblock.sector_size)
2002 if (missing_devices == 2)
2007 for (
ULONG i = 0;
i < sectors_per_stripe;
i++) {
2009 uint64_t bad_stripe1 = 0, bad_stripe2 = 0;
2010 ULONG bad_off1 = 0, bad_off2 = 0;
2013 stripe = (parity1 + 2) %
c->chunk_item->num_stripes;
2014 off = (
ULONG)((bit_start +
num - stripe_start) * sectors_per_stripe * (
c->chunk_item->num_stripes - 2)) +
i;
2016 while (
stripe != parity1) {
2032 off += sectors_per_stripe;
2046 do_xor(&
context->stripes[parity1].buf[(
num *
c->chunk_item->stripe_length) + (
i <<
Vcb->sector_shift)],
2048 Vcb->superblock.sector_size);
2050 bad_off1 = (
ULONG)((bit_start +
num - stripe_start) * sectors_per_stripe * (
c->chunk_item->num_stripes - 2)) +
i;
2051 addr =
c->offset + (stripe_start * (
c->chunk_item->num_stripes - 2) *
c->chunk_item->stripe_length) + (bad_off1 <<
Vcb->sector_shift);
2053 context->stripes[parity1].rewrite =
true;
2061 &
context->parity_scratch2[
i <<
Vcb->sector_shift],
2062 Vcb->superblock.sector_size);
2064 bad_off1 = (
ULONG)((bit_start +
num - stripe_start) * sectors_per_stripe * (
c->chunk_item->num_stripes - 2)) +
i;
2065 addr =
c->offset + (stripe_start * (
c->chunk_item->num_stripes - 2) *
c->chunk_item->stripe_length) + (bad_off1 <<
Vcb->sector_shift);
2067 context->stripes[parity2].rewrite =
true;
2074 uint64_t addr =
c->offset + (stripe_start * (
c->chunk_item->num_stripes - 2) *
c->chunk_item->stripe_length) + (bad_off1 <<
Vcb->sector_shift);
2081 ERR(
"out of memory\n");
2088 &
context->stripes[bad_stripe1].buf[(
num *
c->chunk_item->stripe_length) + (
i <<
Vcb->sector_shift)],
len);
2090 stripe = parity1 == 0 ? (
c->chunk_item->num_stripes - 1) : (parity1 - 1);
2092 if (
c->devices[parity2]->devobj) {
2093 uint16_t stripe_num, bad_stripe_num = 0;
2095 stripe_num =
c->chunk_item->num_stripes - 3;
2096 while (
stripe != parity2) {
2099 if (
stripe != bad_stripe1)
2102 bad_stripe_num = stripe_num;
2108 do_xor(scratch, &
context->stripes[parity2].buf[(
num *
c->chunk_item->stripe_length) + (
i <<
Vcb->sector_shift)],
len);
2110 if (bad_stripe_num != 0)
2119 if (
c->devices[parity1]->devobj) {
2124 if (
c->devices[parity2]->devobj) {
2133 scratch,
Vcb->superblock.node_size);
2135 if (
c->devices[parity1]->devobj) {
2138 stripe = (parity1 + 2) %
c->chunk_item->num_stripes;
2142 Vcb->superblock.node_size);
2147 do_xor(&
context->stripes[parity1].buf[(
num *
c->chunk_item->stripe_length) + (
i <<
Vcb->sector_shift)],
2149 Vcb->superblock.node_size);
2154 context->stripes[parity1].rewrite =
true;
2161 &
context->parity_scratch[
i <<
Vcb->sector_shift],
Vcb->superblock.node_size);
2165 stripe = parity1 == 0 ? (
c->chunk_item->num_stripes - 1) : (parity1 - 1);
2167 if (
c->devices[parity2]->devobj) {
2170 Vcb->superblock.node_size);
2174 while (
stripe != parity2) {
2177 do_xor(&
context->stripes[parity2].buf[(
num *
c->chunk_item->stripe_length) + (
i <<
Vcb->sector_shift)],
2179 Vcb->superblock.node_size);
2184 context->stripes[parity2].rewrite =
true;
2192 context->stripes[bad_stripe1].rewrite =
true;
2196 log_error(
Vcb,
addr,
c->devices[bad_stripe1]->devitem.dev_id,
true,
true,
false);
2198 log_error(
Vcb,
addr,
c->devices[bad_stripe1]->devitem.dev_id,
true,
false,
false);
2203 if (
c->devices[parity1]->devobj)
2206 if (
c->devices[parity2]->devobj)
2213 scratch,
Vcb->superblock.sector_size);
2218 stripe = (parity1 + 2) %
c->chunk_item->num_stripes;
2222 Vcb->superblock.sector_size);
2227 do_xor(&
context->stripes[parity1].buf[(
num *
c->chunk_item->stripe_length) + (
i <<
Vcb->sector_shift)],
2229 Vcb->superblock.sector_size);
2234 context->stripes[parity1].rewrite =
true;
2241 &
context->parity_scratch[
i <<
Vcb->sector_shift],
Vcb->superblock.sector_size);
2245 stripe = parity1 == 0 ? (
c->chunk_item->num_stripes - 1) : (parity1 - 1);
2249 Vcb->superblock.sector_size);
2253 while (
stripe != parity2) {
2256 do_xor(&
context->stripes[parity2].buf[(
num *
c->chunk_item->stripe_length) + (
i <<
Vcb->sector_shift)],
2258 Vcb->superblock.sector_size);
2263 context->stripes[parity2].rewrite =
true;
2270 context->stripes[bad_stripe1].rewrite =
true;
2272 log_error(
Vcb,
addr,
c->devices[bad_stripe1]->devitem.dev_id,
false,
true,
false);
2274 log_error(
Vcb,
addr,
c->devices[bad_stripe1]->devitem.dev_id,
false,
false,
false);
2278 }
else if (
num_errors == 2 && missing_devices == 0) {
2285 stripe = parity1 == 0 ? (
c->chunk_item->num_stripes - 1) : (parity1 - 1);
2290 k =
c->chunk_item->num_stripes - 3;
2295 if (
stripe == bad_stripe1)
2317 }
else if (
stripe == bad_stripe1)
2319 else if (
stripe == bad_stripe2)
2324 }
while (
stripe != parity2);
2329 denom =
gdiv(1, gyx ^ 1);
2330 a =
gmul(gyx, denom);
2331 b =
gmul(gx, denom);
2333 p = &
context->stripes[parity1].buf[(
num *
c->chunk_item->stripe_length) + (
i <<
Vcb->sector_shift)];
2334 q = &
context->stripes[parity2].buf[(
num *
c->chunk_item->stripe_length) + (
i <<
Vcb->sector_shift)];
2335 pxy = &
context->parity_scratch2[
i <<
Vcb->sector_shift];
2336 qxy = &
context->parity_scratch[
i <<
Vcb->sector_shift];
2338 for (
j = 0;
j <
len;
j++) {
2350 addr =
c->offset + (stripe_start * (
c->chunk_item->num_stripes - 2) *
c->chunk_item->stripe_length) + (bad_off1 <<
Vcb->sector_shift);
2357 &
context->parity_scratch[
i <<
Vcb->sector_shift],
Vcb->superblock.node_size);
2359 context->stripes[bad_stripe1].rewrite =
true;
2363 log_error(
Vcb,
addr,
c->devices[bad_stripe1]->devitem.dev_id,
true,
true,
false);
2365 log_error(
Vcb,
addr,
c->devices[bad_stripe1]->devitem.dev_id,
true,
false,
false);
2369 &
context->parity_scratch[
i <<
Vcb->sector_shift],
Vcb->superblock.sector_size);
2371 context->stripes[bad_stripe1].rewrite =
true;
2373 log_error(
Vcb,
addr,
c->devices[bad_stripe1]->devitem.dev_id,
false,
true,
false);
2375 log_error(
Vcb,
addr,
c->devices[bad_stripe1]->devitem.dev_id,
false,
false,
false);
2378 addr =
c->offset + (stripe_start * (
c->chunk_item->num_stripes - 2) *
c->chunk_item->stripe_length) + (bad_off2 <<
Vcb->sector_shift);
2385 &
context->parity_scratch2[
i <<
Vcb->sector_shift],
Vcb->superblock.node_size);
2387 context->stripes[bad_stripe2].rewrite =
true;
2391 log_error(
Vcb,
addr,
c->devices[bad_stripe2]->devitem.dev_id,
true,
true,
false);
2393 log_error(
Vcb,
addr,
c->devices[bad_stripe2]->devitem.dev_id,
true,
false,
false);
2397 &
context->parity_scratch2[
i <<
Vcb->sector_shift],
Vcb->superblock.sector_size);
2399 context->stripes[bad_stripe2].rewrite =
true;
2401 log_error(
Vcb,
addr,
c->devices[bad_stripe2]->devitem.dev_id,
false,
true,
false);
2403 log_error(
Vcb,
addr,
c->devices[bad_stripe2]->devitem.dev_id,
false,
false,
false);
2406 stripe = (parity2 + 1) %
c->chunk_item->num_stripes;
2407 off = (
ULONG)((bit_start +
num - stripe_start) * sectors_per_stripe * (
c->chunk_item->num_stripes - 2)) +
i;
2409 while (
stripe != parity1) {
2412 uint64_t addr =
c->offset + (stripe_start * (
c->chunk_item->num_stripes - 2) *
c->chunk_item->stripe_length) + (off <<
Vcb->sector_shift);
2418 off += sectors_per_stripe;
2437 TRACE(
"(%p, %p, %I64x, %I64x)\n",
Vcb,
c, stripe_start, stripe_end);
2439 full_stripe_len = (
c->chunk_item->num_stripes - num_parity_stripes) *
c->chunk_item->stripe_length;
2440 run_start =
c->offset + (stripe_start * full_stripe_len);
2441 run_end =
c->offset + ((stripe_end + 1) * full_stripe_len);
2443 searchkey.
obj_id = run_start;
2445 searchkey.
offset = 0xffffffffffffffff;
2449 ERR(
"find_item returned %08lx\n",
Status);
2453 num_sectors = (
uint32_t)(((stripe_end - stripe_start + 1) * full_stripe_len) >>
Vcb->sector_shift);
2458 ERR(
"out of memory\n");
2464 ERR(
"out of memory\n");
2476 if (!
context.parity_scratch) {
2477 ERR(
"out of memory\n");
2486 ERR(
"out of memory\n");
2498 ERR(
"out of memory\n");
2509 if (!
context.parity_scratch2) {
2510 ERR(
"out of memory\n");
2536 bool extent_is_tree =
false;
2541 extent_is_tree =
true;
2552 extent_is_tree =
true;
2563 searchkey.
offset = extent_start;
2567 ERR(
"find_item returned %08lx\n",
Status);
2585 (
ULONG)(((csum_end - csum_start) *
Vcb->csum_size) >>
Vcb->sector_shift));
2605 ERR(
"out of memory\n");
2610 max_read = (
uint32_t)
min(1048576 /
c->chunk_item->stripe_length, stripe_end - stripe_start + 1);
2612 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
2617 ERR(
"out of memory\n");
2619 for (
j = 0;
j <
i;
j++) {
2629 if (!
context.stripes[
i].errorarr) {
2632 ERR(
"out of memory\n");
2636 for (
j = 0;
j <
i;
j++) {
2648 context.stripes[
i].rewrite =
false;
2660 bool need_wait =
false;
2662 if (max_read < stripe_end + 1 -
stripe)
2663 read_stripes = max_read;
2667 context.stripes_left =
c->chunk_item->num_stripes;
2670 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
2671 if (
c->devices[
i]->devobj) {
2677 ERR(
"IoAllocateIrp failed\n");
2690 if (!
context.stripes[
i].Irp->AssociatedIrp.SystemBuffer) {
2691 ERR(
"out of memory\n");
2701 if (!
context.stripes[
i].Irp->MdlAddress) {
2702 ERR(
"IoAllocateMdl failed\n");
2716 ERR(
"MmProbeAndLockPages threw exception %08lx\n",
Status);
2729 context.stripes[
i].missing =
false;
2733 Vcb->scrub.data_scrubbed += read_stripes *
c->chunk_item->stripe_length;
2744 ERR(
"too many missing devices (%u, maximum 1)\n", missing_devices);
2748 ERR(
"too many missing devices (%u, maximum 2)\n", missing_devices);
2756 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
2757 if (
c->devices[
i]->devobj)
2765 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
2774 for (
i = 0;
i < read_stripes;
i++) {
2778 for (
i = 0;
i < read_stripes;
i++) {
2785 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
2796 context.stripes[
i].buf, (
uint32_t)(read_stripes *
c->chunk_item->stripe_length));
2799 ERR(
"write_data_phys returned %08lx\n",
Status);
2809 }
while (
stripe < stripe_end);
2814 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
2841 uint64_t full_stripe_len,
stripe, stripe_start = 0, stripe_end = 0, total_data = 0;
2844 full_stripe_len = (
c->chunk_item->num_stripes - num_parity_stripes) *
c->chunk_item->stripe_length;
2851 searchkey.
offset = 0xffffffffffffffff;
2855 ERR(
"find_item returned %08lx\n",
Status);
2873 ERR(
"extent %I64x has size less than sector_size (%I64x < %x)\n",
tp.
item->
key.
obj_id,
size,
Vcb->superblock.sector_size);
2880 if (
stripe > stripe_end + 1) {
2883 ERR(
"scrub_chunk_raid56_stripe_run returned %08lx\n",
Status);
2900 if (num_extents >= 64 || total_data >= 0x8000000)
2913 ERR(
"scrub_chunk_raid56_stripe_run returned %08lx\n",
Status);
2917 *
offset =
c->offset + ((stripe_end + 1) * full_stripe_len);
2927 bool b =
false, tree_run =
false;
2929 uint64_t total_data = 0, tree_run_start = 0, tree_run_end = 0;
2931 TRACE(
"chunk %I64x\n",
c->offset);
2958 searchkey.
offset = 0xffffffffffffffff;
2962 ERR(
"error - find_item returned %08lx\n",
Status);
2999 ERR(
"extent %I64x has size less than sector_size (%I64x < %x)\n",
tp.
item->
key.
obj_id,
size,
Vcb->superblock.sector_size);
3010 ERR(
"out of memory\n");
3019 ERR(
"out of memory\n");
3034 ERR(
"find_item returned %08lx\n",
Status);
3053 (
ULONG)(((ce -
cs) *
Vcb->csum_size) >>
Vcb->sector_shift));
3074 ERR(
"scrub_extent returned %08lx\n",
Status);
3086 }
else if (is_tree) {
3095 ERR(
"scrub_data_extent returned %08lx\n",
Status);
3112 if (num_extents >= 64 || total_data >= 0x8000000)