45 if (
length >
c->chunk_item->size -
c->used)
48 if (!
c->cache_loaded) {
52 ERR(
"load_cache_chunk returned %08lx\n",
Status);
61 while (le != &
c->space_size) {
68 if (le ==
c->space_size.Flink)
96 le2 =
Vcb->chunks.Flink;
97 while (le2 != &
Vcb->chunks) {
100 if (
address >=
c->offset && address < c->
offset +
c->chunk_item->size) {
125 le =
Vcb->chunks.Flink;
126 while (le != &
Vcb->chunks) {
129 if (
c->offset >= lastaddr +
size)
132 lastaddr =
c->offset +
c->chunk_item->size;
142 uint64_t devusage = 0xffffffffffffffff;
147 le =
Vcb->devices.Flink;
149 while (le != &
Vcb->devices) {
152 if (!
dev->readonly && !
dev->reloc &&
dev->devobj) {
161 le2 =
dev->space.Flink;
162 while (le2 != &
dev->space) {
165 if (dh->
size >= max_stripe_size && (!dh1 || !dh2 || dh->
size < dh1->
size)) {
173 if (dh1 && (dh2 || dh1->
size >= 2 * max_stripe_size)) {
177 devdh2 = dh2 ? dh2 : dh1;
194 le =
Vcb->devices.Flink;
195 while (le != &
Vcb->devices) {
198 if (!
dev->readonly && !
dev->reloc) {
203 le2 =
dev->space.Flink;
204 while (le2 != &
dev->space) {
207 if (!dh1 || !dh2 || dh->
size < dh1->
size) {
221 devsize = dh1->
size / 2;
223 if (devsize >
size) {
227 if (dh2 &&
min(dh1->
size, dh2->size) > dh1->
size / 2)
245 stripes[0].device = stripes[1].device = dev2;
246 stripes[0].dh = devdh1;
247 stripes[1].dh = devdh2;
254 uint64_t k, devusage = 0xffffffffffffffff;
259 le =
Vcb->devices.Flink;
260 while (le != &
Vcb->devices) {
265 if (
dev->readonly ||
dev->reloc || (!
dev->devobj && !allow_missing)) {
272 for (
k = 0;
k <
i;
k++) {
281 usage = (
dev->devitem.bytes_used * 4096) /
dev->devitem.num_bytes;
288 le2 =
dev->space.Flink;
289 while (le2 != &
dev->space) {
292 if ((dev2 !=
dev && dh->
size >= max_stripe_size) ||
315 le =
Vcb->devices.Flink;
316 while (le != &
Vcb->devices) {
320 if (
dev->readonly ||
dev->reloc || (!
dev->devobj && !allow_missing)) {
327 for (
k = 0;
k <
i;
k++) {
339 le2 =
dev->space.Flink;
340 while (le2 != &
dev->space) {
343 if (!devdh || devdh->
size < dh->
size) {
360 stripes[
i].dh = devdh;
361 stripes[
i].device = dev2;
369 uint64_t max_stripe_size, max_chunk_size, stripe_size, stripe_length,
factor;
371 uint16_t i,
type, num_stripes, sub_stripes, max_stripes, min_stripes, allowed_missing;
379 le =
Vcb->devices.Flink;
380 while (le != &
Vcb->devices) {
382 total_size +=
dev->devitem.num_bytes;
387 TRACE(
"total_size = %I64x\n", total_size);
392 max_stripe_size = 0x40000000;
393 max_chunk_size = 10 * max_stripe_size;
395 if (total_size > 0xC80000000)
396 max_stripe_size = 0x40000000;
398 max_stripe_size = 0x10000000;
400 max_chunk_size = max_stripe_size;
402 max_stripe_size = 0x2000000;
403 max_chunk_size = 2 * max_stripe_size;
405 ERR(
"unknown chunk type\n");
465 if (max_chunk_size > total_size / 10) {
466 max_chunk_size = total_size / 10;
467 max_stripe_size = max_chunk_size / min_stripes;
470 if (max_stripe_size > total_size / (10 * min_stripes))
471 max_stripe_size = total_size / (10 * min_stripes);
473 TRACE(
"would allocate a new chunk of %I64x bytes and stripe %I64x\n", max_chunk_size, max_stripe_size);
477 ERR(
"out of memory\n");
485 if (!find_new_dup_stripes(
Vcb, stripes, max_stripe_size, full_size)) {
489 num_stripes = max_stripes;
491 for (
i = 0;
i < max_stripes;
i++) {
492 if (!find_new_stripe(
Vcb, stripes,
i, max_stripe_size,
false, full_size))
499 if (num_stripes < min_stripes && Vcb->
options.allow_degraded && allowed_missing > 0) {
502 for (
i = num_stripes;
i < max_stripes;
i++) {
503 if (!find_new_stripe(
Vcb, stripes,
i, max_stripe_size,
true, full_size))
507 if (added_missing >= allowed_missing)
512 num_stripes += added_missing;
517 num_stripes -= num_stripes % sub_stripes;
520 if (num_stripes < min_stripes) {
521 WARN(
"found %u stripes, needed at least %u\n", num_stripes, min_stripes);
528 ERR(
"out of memory\n");
537 if (!
c->chunk_item) {
538 ERR(
"out of memory\n");
543 stripe_length = 0x10000;
546 stripe_size =
min(stripes[0].dh->size / 2, max_stripe_size);
548 stripe_size = max_stripe_size;
549 for (
i = 0;
i < num_stripes;
i++) {
550 if (stripes[
i].dh->size < stripe_size)
551 stripe_size = stripes[
i].
dh->
size;
558 factor = num_stripes / sub_stripes;
566 if (stripe_size *
factor > max_chunk_size)
567 stripe_size = max_chunk_size /
factor;
569 if (stripe_size % stripe_length > 0)
570 stripe_size -= stripe_size % stripe_length;
572 if (stripe_size == 0) {
573 ERR(
"not enough free space found (stripe_size == 0)\n");
578 c->chunk_item->size = stripe_size *
factor;
579 c->chunk_item->root_id =
Vcb->extent_root->id;
580 c->chunk_item->stripe_length = stripe_length;
581 c->chunk_item->type =
flags;
582 c->chunk_item->opt_io_alignment = (
uint32_t)
c->chunk_item->stripe_length;
583 c->chunk_item->opt_io_width = (
uint32_t)
c->chunk_item->stripe_length;
585 c->chunk_item->num_stripes = num_stripes;
586 c->chunk_item->sub_stripes = sub_stripes;
590 ERR(
"out of memory\n");
596 for (
i = 0;
i < num_stripes;
i++) {
609 logaddr = find_new_chunk_address(
Vcb,
c->chunk_item->size);
611 Vcb->superblock.chunk_root_generation =
Vcb->superblock.generation;
615 c->used =
c->oldused = 0;
616 c->cache =
c->old_cache =
NULL;
619 c->last_alloc_set =
false;
621 c->cache_loaded =
true;
623 c->space_changed =
false;
643 ERR(
"out of memory\n");
648 s->address =
c->offset;
649 s->size =
c->chunk_item->size;
655 for (
i = 0;
i < num_stripes;
i++) {
685 le =
Vcb->chunks.Flink;
686 while (le != &
Vcb->chunks) {
703 c->space_changed =
true;
704 c->list_entry_balance.Flink =
NULL;
716 uint16_t startoffstripe, endoffstripe, stripenum;
725 ERR(
"out of memory\n");
733 master_mdl =
Irp->MdlAddress;
740 ERR(
"out of memory\n");
748 ERR(
"out of memory\n");
754 wtc->mdl = master_mdl;
762 ERR(
"out of memory\n");
773 ERR(
"MmProbeAndLockPages threw exception %08lx\n",
Status);
778 wtc->mdl = master_mdl;
783 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
784 if (startoffstripe >
i)
785 stripes[
i].start = startoff - (startoff %
c->chunk_item->stripe_length) +
c->chunk_item->stripe_length;
786 else if (startoffstripe ==
i)
787 stripes[
i].start = startoff;
789 stripes[
i].start = startoff - (startoff %
c->chunk_item->stripe_length);
791 if (endoffstripe >
i)
792 stripes[
i].end = endoff - (endoff %
c->chunk_item->stripe_length) +
c->chunk_item->stripe_length;
793 else if (endoffstripe ==
i)
794 stripes[
i].end = endoff + 1;
796 stripes[
i].end = endoff - (endoff %
c->chunk_item->stripe_length);
800 if (!stripes[
i].
mdl) {
801 ERR(
"IoAllocateMdl failed\n");
811 stripenum = startoffstripe;
818 c->chunk_item->stripe_length - (stripes[stripenum].start %
c->chunk_item->stripe_length));
822 stripeoff[stripenum] += writelen;
824 }
else if (
length - pos < c->chunk_item->stripe_length) {
830 stripeoff[stripenum] +=
c->chunk_item->stripe_length;
831 pos +=
c->chunk_item->stripe_length;
834 stripenum = (stripenum + 1) %
c->chunk_item->num_stripes;
843static
NTSTATUS prepare_raid10_write(
_Pre_satisfies_(_Curr_->chunk_item->sub_stripes>0&&_Curr_->chunk_item->num_stripes>=_Curr_->chunk_item->sub_stripes)
_In_ chunk*
c,
847 uint16_t startoffstripe, endoffstripe, stripenum;
854 get_raid0_offset(
address -
c->offset,
c->chunk_item->stripe_length,
c->chunk_item->num_stripes /
c->chunk_item->sub_stripes, &startoff, &startoffstripe);
855 get_raid0_offset(
address +
length -
c->offset - 1,
c->chunk_item->stripe_length,
c->chunk_item->num_stripes /
c->chunk_item->sub_stripes, &endoff, &endoffstripe);
857 stripenum = startoffstripe;
858 startoffstripe *=
c->chunk_item->sub_stripes;
859 endoffstripe *=
c->chunk_item->sub_stripes;
862 master_mdl =
Irp->MdlAddress;
869 ERR(
"out of memory\n");
877 ERR(
"out of memory\n");
883 wtc->mdl = master_mdl;
891 ERR(
"out of memory\n");
902 ERR(
"MmProbeAndLockPages threw exception %08lx\n",
Status);
907 wtc->mdl = master_mdl;
912 for (
i = 0;
i <
c->chunk_item->num_stripes;
i +=
c->chunk_item->sub_stripes) {
915 if (startoffstripe >
i)
916 stripes[
i].start = startoff - (startoff %
c->chunk_item->stripe_length) +
c->chunk_item->stripe_length;
917 else if (startoffstripe ==
i)
918 stripes[
i].start = startoff;
920 stripes[
i].start = startoff - (startoff %
c->chunk_item->stripe_length);
922 if (endoffstripe >
i)
923 stripes[
i].end = endoff - (endoff %
c->chunk_item->stripe_length) +
c->chunk_item->stripe_length;
924 else if (endoffstripe ==
i)
925 stripes[
i].end = endoff + 1;
927 stripes[
i].end = endoff - (endoff %
c->chunk_item->stripe_length);
930 if (!stripes[
i].
mdl) {
931 ERR(
"IoAllocateMdl failed\n");
935 for (
j = 1;
j <
c->chunk_item->sub_stripes;
j++) {
936 stripes[
i+
j].start = stripes[
i].start;
937 stripes[
i+
j].end = stripes[
i].end;
938 stripes[
i+
j].data = stripes[
i].data;
939 stripes[
i+
j].mdl = stripes[
i].mdl;
947 ERR(
"out of memory\n");
957 uint32_t writelen = (
uint32_t)
min(stripes[stripenum *
c->chunk_item->sub_stripes].end - stripes[stripenum *
c->chunk_item->sub_stripes].start,
958 c->chunk_item->stripe_length - (stripes[stripenum *
c->chunk_item->sub_stripes].start %
c->chunk_item->stripe_length));
962 stripeoff[stripenum] += writelen;
964 }
else if (
length - pos < c->chunk_item->stripe_length) {
970 stripeoff[stripenum] +=
c->chunk_item->stripe_length;
971 pos +=
c->chunk_item->stripe_length;
974 stripenum = (stripenum + 1) % (
c->chunk_item->num_stripes /
c->chunk_item->sub_stripes);
990 num_data_stripes =
c->chunk_item->num_stripes - (
c->chunk_item->type &
BLOCK_FLAG_RAID5 ? 1 : 2);
991 stripe_addr =
address - ((
address -
c->offset) % (num_data_stripes *
c->chunk_item->stripe_length));
995 le =
c->partial_stripes.
Flink;
996 while (le != &
c->partial_stripes) {
999 if (ps->
address == stripe_addr) {
1009 ERR(
"flush_partial_stripe returned %08lx\n",
Status);
1023 }
else if (ps->
address > stripe_addr)
1033 ERR(
"out of memory\n");
1038 ps->
bmplen = (
ULONG)(num_data_stripes *
c->chunk_item->stripe_length) >>
Vcb->sector_shift;
1043 ERR(
"out of memory\n");
1073 uint64_t startoff, endoff, parity_start, parity_end;
1074 uint16_t startoffstripe, endoffstripe, parity, num_data_stripes =
c->chunk_item->num_stripes - 1;
1083 if ((
address +
length -
c->offset) % (num_data_stripes *
c->chunk_item->stripe_length) > 0) {
1089 ERR(
"add_partial_stripe returned %08lx\n",
Status);
1096 if (
length > 0 && (
address -
c->offset) % (num_data_stripes *
c->chunk_item->stripe_length) > 0) {
1097 uint64_t delta = (num_data_stripes *
c->chunk_item->stripe_length) - ((
address -
c->offset) % (num_data_stripes *
c->chunk_item->stripe_length));
1101 ERR(
"add_partial_stripe returned %08lx\n",
Status);
1107 irp_offset += delta;
1121 parity = (((
address -
c->offset +
pos) / (num_data_stripes *
c->chunk_item->stripe_length)) + num_data_stripes) %
c->chunk_item->num_stripes;
1124 uint16_t stripe = (parity + startoffstripe + 1) %
c->chunk_item->num_stripes;
1129 if (
i == startoffstripe) {
1130 writelen = (
ULONG)
min(
length,
c->chunk_item->stripe_length - (startoff %
c->chunk_item->stripe_length));
1132 stripes[
stripe].start = startoff;
1133 stripes[
stripe].end = startoff + writelen;
1142 stripes[
stripe].start = startoff - (startoff %
c->chunk_item->stripe_length);
1143 stripes[
stripe].end = stripes[
stripe].start + writelen;
1158 for (
i = 0;
i < startoffstripe;
i++) {
1159 stripe = (parity +
i + 1) %
c->chunk_item->num_stripes;
1161 stripes[
stripe].start = stripes[
stripe].end = startoff - (startoff %
c->chunk_item->stripe_length) +
c->chunk_item->stripe_length;
1164 stripes[parity].start = stripes[parity].end = startoff - (startoff %
c->chunk_item->stripe_length) +
c->chunk_item->stripe_length;
1166 if (
length -
pos >
c->chunk_item->num_stripes * num_data_stripes *
c->chunk_item->stripe_length) {
1167 skip = (
ULONG)(((
length -
pos) / (
c->chunk_item->num_stripes * num_data_stripes *
c->chunk_item->stripe_length)) - 1);
1169 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
1170 stripes[
i].end +=
skip *
c->chunk_item->num_stripes *
c->chunk_item->stripe_length;
1173 pos +=
skip * num_data_stripes *
c->chunk_item->num_stripes *
c->chunk_item->stripe_length;
1175 }
else if (
length -
pos >=
c->chunk_item->stripe_length * num_data_stripes) {
1176 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
1177 stripes[
i].end +=
c->chunk_item->stripe_length;
1180 pos +=
c->chunk_item->stripe_length * num_data_stripes;
1186 if (endoffstripe ==
i) {
1187 stripes[
stripe].end = endoff + 1;
1189 }
else if (endoffstripe >
i)
1190 stripes[
stripe].end = endoff - (endoff %
c->chunk_item->stripe_length) +
c->chunk_item->stripe_length;
1200 parity_start = 0xffffffffffffffff;
1203 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
1204 if (stripes[
i].
start != 0 || stripes[
i].
end != 0) {
1205 parity_start =
min(stripes[
i].
start, parity_start);
1206 parity_end =
max(stripes[
i].
end, parity_end);
1210 if (parity_end == parity_start) {
1215 parity = (((
address -
c->offset) / (num_data_stripes *
c->chunk_item->stripe_length)) + num_data_stripes) %
c->chunk_item->num_stripes;
1216 stripes[parity].start = parity_start;
1218 parity = (((
address -
c->offset +
length - 1) / (num_data_stripes *
c->chunk_item->stripe_length)) + num_data_stripes) %
c->chunk_item->num_stripes;
1219 stripes[parity].end = parity_end;
1223 ERR(
"out of memory\n");
1230 for (
i = 0;
i < num_data_stripes;
i++) {
1232 if (!log_stripes[
i].
mdl) {
1233 ERR(
"out of memory\n");
1243 if (!wtc->parity1) {
1244 ERR(
"out of memory\n");
1250 if (!wtc->parity1_mdl) {
1251 ERR(
"out of memory\n");
1259 master_mdl =
Irp->MdlAddress;
1262 if (!wtc->scratch) {
1263 ERR(
"out of memory\n");
1272 ERR(
"out of memory\n");
1279 wtc->mdl = master_mdl;
1283 ERR(
"out of memory\n");
1297 ERR(
"MmProbeAndLockPages threw exception %08lx\n",
Status);
1302 wtc->mdl = master_mdl;
1306 parity_pfns = (
PFN_NUMBER*)(wtc->parity1_mdl + 1);
1311 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
1314 if (!stripes[
i].
mdl) {
1315 ERR(
"IoAllocateMdl failed\n");
1324 ERR(
"out of memory\n");
1337 parity = (((
address -
c->offset +
pos) / (num_data_stripes *
c->chunk_item->stripe_length)) + num_data_stripes) %
c->chunk_item->num_stripes;
1340 uint16_t stripe = (parity + startoffstripe + 1) %
c->chunk_item->num_stripes;
1342 c->chunk_item->stripe_length - (stripes[
stripe].start %
c->chunk_item->stripe_length)));
1352 stripeoff[
stripe] = writelen;
1356 i = startoffstripe + 1;
1365 if (writelen > maxwritelen)
1366 maxwritelen = writelen;
1373 stripeoff[
stripe] = writelen;
1383 stripeoff[parity] = maxwritelen;
1384 parity_pos = maxwritelen;
1385 }
else if (
length -
pos >=
c->chunk_item->stripe_length * num_data_stripes) {
1397 stripeoff[
stripe] +=
c->chunk_item->stripe_length;
1398 pos +=
c->chunk_item->stripe_length;
1407 stripeoff[parity] +=
c->chunk_item->stripe_length;
1408 parity_pos +=
c->chunk_item->stripe_length;
1411 uint32_t writelen, maxwritelen = 0;
1421 if (writelen > maxwritelen)
1422 maxwritelen = writelen;
1429 stripeoff[
stripe] += writelen;
1442 for (
i = 0;
i < num_data_stripes;
i++) {
1455 for (
i = 0;
i < num_data_stripes;
i++) {
1456 if (log_stripes[
i].
mdl)
1472 uint64_t startoff, endoff, parity_start, parity_end;
1473 uint16_t startoffstripe, endoffstripe, parity1, num_data_stripes =
c->chunk_item->num_stripes - 2;
1479 PFN_NUMBER *pfns, *parity1_pfns, *parity2_pfns;
1482 if ((
address +
length -
c->offset) % (num_data_stripes *
c->chunk_item->stripe_length) > 0) {
1488 ERR(
"add_partial_stripe returned %08lx\n",
Status);
1495 if (
length > 0 && (
address -
c->offset) % (num_data_stripes *
c->chunk_item->stripe_length) > 0) {
1496 uint64_t delta = (num_data_stripes *
c->chunk_item->stripe_length) - ((
address -
c->offset) % (num_data_stripes *
c->chunk_item->stripe_length));
1500 ERR(
"add_partial_stripe returned %08lx\n",
Status);
1506 irp_offset += delta;
1520 parity1 = (((
address -
c->offset +
pos) / (num_data_stripes *
c->chunk_item->stripe_length)) + num_data_stripes) %
c->chunk_item->num_stripes;
1523 uint16_t stripe = (parity1 + startoffstripe + 2) %
c->chunk_item->num_stripes;
1524 uint16_t parity2 = (parity1 + 1) %
c->chunk_item->num_stripes;
1528 while (
stripe != parity1) {
1529 if (
i == startoffstripe) {
1530 writelen = (
ULONG)
min(
length,
c->chunk_item->stripe_length - (startoff %
c->chunk_item->stripe_length));
1532 stripes[
stripe].start = startoff;
1533 stripes[
stripe].end = startoff + writelen;
1542 stripes[
stripe].start = startoff - (startoff %
c->chunk_item->stripe_length);
1543 stripes[
stripe].end = stripes[
stripe].start + writelen;
1558 for (
i = 0;
i < startoffstripe;
i++) {
1559 stripe = (parity1 +
i + 2) %
c->chunk_item->num_stripes;
1561 stripes[
stripe].start = stripes[
stripe].end = startoff - (startoff %
c->chunk_item->stripe_length) +
c->chunk_item->stripe_length;
1564 stripes[parity1].start = stripes[parity1].end = stripes[parity2].start = stripes[parity2].end =
1565 startoff - (startoff %
c->chunk_item->stripe_length) +
c->chunk_item->stripe_length;
1567 if (
length -
pos >
c->chunk_item->num_stripes * num_data_stripes *
c->chunk_item->stripe_length) {
1568 skip = (
ULONG)(((
length -
pos) / (
c->chunk_item->num_stripes * num_data_stripes *
c->chunk_item->stripe_length)) - 1);
1570 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
1571 stripes[
i].end +=
skip *
c->chunk_item->num_stripes *
c->chunk_item->stripe_length;
1574 pos +=
skip * num_data_stripes *
c->chunk_item->num_stripes *
c->chunk_item->stripe_length;
1576 }
else if (
length -
pos >=
c->chunk_item->stripe_length * num_data_stripes) {
1577 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
1578 stripes[
i].end +=
c->chunk_item->stripe_length;
1581 pos +=
c->chunk_item->stripe_length * num_data_stripes;
1587 if (endoffstripe ==
i) {
1588 stripes[
stripe].end = endoff + 1;
1590 }
else if (endoffstripe >
i)
1591 stripes[
stripe].end = endoff - (endoff %
c->chunk_item->stripe_length) +
c->chunk_item->stripe_length;
1601 parity_start = 0xffffffffffffffff;
1604 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
1605 if (stripes[
i].
start != 0 || stripes[
i].
end != 0) {
1606 parity_start =
min(stripes[
i].
start, parity_start);
1607 parity_end =
max(stripes[
i].
end, parity_end);
1611 if (parity_end == parity_start) {
1616 parity1 = (((
address -
c->offset) / (num_data_stripes *
c->chunk_item->stripe_length)) + num_data_stripes) %
c->chunk_item->num_stripes;
1617 stripes[parity1].start = stripes[(parity1 + 1) %
c->chunk_item->num_stripes].start = parity_start;
1619 parity1 = (((
address -
c->offset +
length - 1) / (num_data_stripes *
c->chunk_item->stripe_length)) + num_data_stripes) %
c->chunk_item->num_stripes;
1620 stripes[parity1].end = stripes[(parity1 + 1) %
c->chunk_item->num_stripes].end = parity_end;
1624 ERR(
"out of memory\n");
1631 for (
i = 0;
i < num_data_stripes;
i++) {
1633 if (!log_stripes[
i].
mdl) {
1634 ERR(
"out of memory\n");
1644 if (!wtc->parity1) {
1645 ERR(
"out of memory\n");
1651 if (!wtc->parity2) {
1652 ERR(
"out of memory\n");
1658 if (!wtc->parity1_mdl) {
1659 ERR(
"out of memory\n");
1667 if (!wtc->parity2_mdl) {
1668 ERR(
"out of memory\n");
1676 master_mdl =
Irp->MdlAddress;
1679 if (!wtc->scratch) {
1680 ERR(
"out of memory\n");
1689 ERR(
"out of memory\n");
1696 wtc->mdl = master_mdl;
1700 ERR(
"out of memory\n");
1714 ERR(
"MmProbeAndLockPages threw exception %08lx\n",
Status);
1719 wtc->mdl = master_mdl;
1723 parity1_pfns = (
PFN_NUMBER*)(wtc->parity1_mdl + 1);
1724 parity2_pfns = (
PFN_NUMBER*)(wtc->parity2_mdl + 1);
1729 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
1732 if (!stripes[
i].
mdl) {
1733 ERR(
"IoAllocateMdl failed\n");
1742 ERR(
"out of memory\n");
1755 parity1 = (((
address -
c->offset +
pos) / (num_data_stripes *
c->chunk_item->stripe_length)) + num_data_stripes) %
c->chunk_item->num_stripes;
1758 uint16_t stripe = (parity1 + startoffstripe + 2) %
c->chunk_item->num_stripes, parity2;
1760 c->chunk_item->stripe_length - (stripes[
stripe].start %
c->chunk_item->stripe_length)));
1770 stripeoff[
stripe] = writelen;
1774 i = startoffstripe + 1;
1783 if (writelen > maxwritelen)
1784 maxwritelen = writelen;
1791 stripeoff[
stripe] = writelen;
1800 stripeoff[parity1] = maxwritelen;
1802 parity2 = (parity1 + 1) %
c->chunk_item->num_stripes;
1804 stripe_pfns = (
PFN_NUMBER*)(stripes[parity2].mdl + 1);
1806 stripeoff[parity2] = maxwritelen;
1808 parity_pos = maxwritelen;
1809 }
else if (
length -
pos >=
c->chunk_item->stripe_length * num_data_stripes) {
1810 uint16_t stripe = (parity1 + 2) %
c->chunk_item->num_stripes, parity2;
1821 stripeoff[
stripe] +=
c->chunk_item->stripe_length;
1822 pos +=
c->chunk_item->stripe_length;
1830 stripeoff[parity1] +=
c->chunk_item->stripe_length;
1832 parity2 = (parity1 + 1) %
c->chunk_item->num_stripes;
1834 stripe_pfns = (
PFN_NUMBER*)(stripes[parity2].mdl + 1);
1836 stripeoff[parity2] +=
c->chunk_item->stripe_length;
1838 parity_pos +=
c->chunk_item->stripe_length;
1840 uint16_t stripe = (parity1 + 2) %
c->chunk_item->num_stripes, parity2;
1841 uint32_t writelen, maxwritelen = 0;
1851 if (writelen > maxwritelen)
1852 maxwritelen = writelen;
1859 stripeoff[
stripe] += writelen;
1869 parity2 = (parity1 + 1) %
c->chunk_item->num_stripes;
1871 stripe_pfns = (
PFN_NUMBER*)(stripes[parity2].mdl + 1);
1876 for (
i = 0;
i < num_data_stripes;
i++) {
1894 for (
i = 0;
i < num_data_stripes;
i++) {
1895 if (log_stripes[
i].
mdl)
1916 ULONG allowed_missing, missing;
1923 ERR(
"could not get chunk for address %I64x\n",
address);
1930 ERR(
"out of memory\n");
1941 ERR(
"prepare_raid0_write returned %08lx\n",
Status);
1942 goto prepare_failed;
1945 allowed_missing = 0;
1949 ERR(
"prepare_raid10_write returned %08lx\n",
Status);
1950 goto prepare_failed;
1953 allowed_missing = 1;
1957 ERR(
"prepare_raid5_write returned %08lx\n",
Status);
1958 goto prepare_failed;
1961 allowed_missing = 1;
1965 ERR(
"prepare_raid6_write returned %08lx\n",
Status);
1966 goto prepare_failed;
1969 allowed_missing = 2;
1971 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
1977 if (
c->devices[
i]->devobj) {
1985 if (!stripes[
i].
mdl) {
1986 ERR(
"IoAllocateMdl failed\n");
1988 goto prepare_failed;
1994 if (!stripes[
i].
mdl) {
1995 ERR(
"IoAllocateMdl failed\n");
1997 goto prepare_failed;
2009 ERR(
"MmProbeAndLockPages threw exception %08lx\n",
Status);
2012 goto prepare_failed;
2018 allowed_missing =
c->chunk_item->num_stripes - 1;
2022 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
2023 if (!
c->devices[
i]->devobj)
2027 if (missing > allowed_missing) {
2028 ERR(
"cannot write as %lu missing devices (maximum %lu)\n", missing, allowed_missing);
2030 goto prepare_failed;
2033 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
2039 ERR(
"out of memory\n");
2044 if (stripes[
i].
start == stripes[
i].
end || !
c->devices[
i]->devobj) {
2061 ERR(
"IoAllocateIrp failed\n");
2070 ERR(
"IoMakeAssociatedIrp failed\n");
2090#ifdef DEBUG_PARANOID
2103 wtc->stripes_left++;
2126 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
2135 if (wtc->parity1_mdl) {
2140 wtc->parity1_mdl =
NULL;
2143 if (wtc->parity2_mdl) {
2148 wtc->parity2_mdl =
NULL;
2161 wtc->parity1 =
NULL;
2166 wtc->parity2 =
NULL;
2171 wtc->scratch =
NULL;
2181 uint16_t startoffstripe, endoffstripe, datastripes;
2183 datastripes =
c->chunk_item->num_stripes - (
c->chunk_item->type &
BLOCK_FLAG_RAID5 ? 1 : 2);
2188 startoff -= startoff %
c->chunk_item->stripe_length;
2189 endoff =
sector_align(endoff,
c->chunk_item->stripe_length);
2191 *lockaddr =
c->offset + (startoff * datastripes);
2192 *locklen = (endoff - startoff) * datastripes;
2210 ERR(
"could not get chunk for address %I64x\n",
address);
2227 ERR(
"write_data returned %08lx\n",
Status);
2239 bool no_wait =
true;
2303 while (le != &
context->stripes) {
2327 if (wtc->parity1_mdl) {
2334 if (wtc->parity2_mdl) {
2357 le = wtc->stripes.
Flink;
2358 while (le != &wtc->stripes) {
2390 if (
ext->offset >= newext->offset) {
2423 if (start_data <= ext->
offset && end_data >=
ext->offset +
len) {
2429 ERR(
"trying to split inline extent\n");
2430#ifdef DEBUG_PARANOID
2438 if (start_data <= ext->
offset && end_data >=
ext->offset +
len) {
2439 if (ed2->
size != 0) {
2448 ERR(
"get_chunk_from_address(%I64x) failed\n", ed2->
address);
2453 ERR(
"update_changed_extent_ref returned %08lx\n",
Status);
2460 }
else if (start_data <= ext->
offset && end_data < ext->
offset +
len) {
2464 if (ed2->
size != 0) {
2471 ERR(
"out of memory\n");
2489 newext->
offset = end_data;
2498 if (!newext->
csum) {
2499 ERR(
"out of memory\n");
2509 if (!newext->
csum) {
2510 ERR(
"out of memory\n");
2528 if (ed2->
size != 0) {
2535 ERR(
"out of memory\n");
2562 if (!newext->
csum) {
2563 ERR(
"out of memory\n");
2572 if (!newext->
csum) {
2573 ERR(
"out of memory\n");
2589 extent *newext1, *newext2;
2591 if (ed2->
size != 0) {
2600 ERR(
"get_chunk_from_address(%I64x) failed\n", ed2->
address);
2605 ERR(
"update_changed_extent_ref returned %08lx\n",
Status);
2613 ERR(
"out of memory\n");
2620 ERR(
"out of memory\n");
2658 newext2->
offset = end_data;
2667 if (!newext1->
csum) {
2668 ERR(
"out of memory\n");
2676 if (!newext2->
csum) {
2677 ERR(
"out of memory\n");
2690 if (!newext1->
csum) {
2691 ERR(
"out of memory\n");
2699 if (!newext2->
csum) {
2700 ERR(
"out of memory\n");
2743 ERR(
"out of memory\n");
2754#pragma warning(push)
2755#pragma warning(suppress: 28194)
2765 ERR(
"out of memory\n");
2770 ext->datalen = edsize;
2772 ext->ignore =
false;
2773 ext->inserted =
true;
2810 ERR(
"out of memory\n");
2833 TRACE(
"(%p, (%I64x, %I64x), %I64x, %I64x, %I64x, %u, %p, %p)\n",
Vcb,
fcb->
subvol->id,
fcb->
inode,
c->offset,
start_data,
length,
prealloc,
data,
rollback);
2841 ERR(
"out of memory\n");
2863 ERR(
"out of memory\n");
2873 ERR(
"add_extent_to_fcb returned %08lx\n",
Status);
2902 ERR(
"write_data_complete returned %08lx\n",
Status);
2939 ed = &
ext->extent_data;
2942 TRACE(
"not extending extent which is not regular or prealloc\n");
2955 if (
c->reloc ||
c->readonly ||
c->chunk_item->type !=
Vcb->data_flags)
2960 if (
length >
c->chunk_item->size -
c->used) {
2965 if (!
c->cache_loaded) {
2969 ERR(
"load_cache_chunk returned %08lx\n",
Status);
2976 while (le != &
c->space) {
2982 success =
insert_extent_chunk(
Vcb,
fcb,
c,
start_data, newlen,
false,
data,
Irp,
rollback,
BTRFS_COMPRESSION_NONE, newlen,
file_write, irp_offset);
3017 ERR(
"alloc_chunk returned %08lx\n",
Status);
3022 le =
fcb->
Vcb->chunks.Flink;
3023 while (le != &
fcb->
Vcb->chunks) {
3026 if (!
c->readonly && !
c->reloc) {
3029 if (
c->chunk_item->type ==
flags) {
3034 if (
insert_extent_chunk(
fcb->
Vcb,
fcb,
c,
start, extlen,
prealloc && !page_file,
data,
NULL,
rollback,
BTRFS_COMPRESSION_NONE, extlen,
false, 0)) {
3073 le =
fcb->
Vcb->chunks.Flink;
3074 while (le != &
fcb->
Vcb->chunks) {
3077 if (!
c->readonly && !
c->reloc) {
3080 if (
c->chunk_item->type ==
flags && (
c->chunk_item->size -
c->used) >= extlen) {
3081 if (
insert_extent_chunk(
fcb->
Vcb,
fcb,
c,
start, extlen, !page_file,
NULL,
NULL,
rollback,
BTRFS_COMPRESSION_NONE, extlen,
false, 0)) {
3102 ERR(
"alloc_chunk returned %08lx\n",
Status);
3108 if (
c->chunk_item->type ==
flags && (
c->chunk_item->size -
c->used) >= extlen) {
3109 if (
insert_extent_chunk(
fcb->
Vcb,
fcb,
c,
start, extlen, !page_file,
NULL,
NULL,
rollback,
BTRFS_COMPRESSION_NONE, extlen,
false, 0))
3117 ERR(
"insert_chunk_fragmented returned %08lx\n",
Status);
3140 TRACE(
"(%p, (%I64x, %I64x), %I64x, %I64x, %p)\n",
Vcb,
fcb->
subvol->id,
fcb->
inode,
start_data,
length,
data);
3147 else if (written > 0) {
3149 irp_offset += written;
3157 while (written < orig_length) {
3166 le =
Vcb->chunks.Flink;
3167 while (le != &
Vcb->chunks) {
3170 if (!
c->readonly && !
c->reloc) {
3173 if (
c->chunk_item->type ==
flags && (
c->chunk_item->size -
c->used) >= newlen &&
3174 insert_extent_chunk(
Vcb,
fcb,
c,
start_data, newlen,
false,
data,
Irp,
rollback,
BTRFS_COMPRESSION_NONE, newlen,
file_write, irp_offset)) {
3177 if (written == orig_length) {
3183 irp_offset += newlen;
3208 ERR(
"alloc_chunk returned %08lx\n",
Status);
3215 if (
c->chunk_item->type ==
flags && (
c->chunk_item->size -
c->used) >= newlen &&
3216 insert_extent_chunk(
Vcb,
fcb,
c,
start_data, newlen,
false,
data,
Irp,
rollback,
BTRFS_COMPRESSION_NONE, newlen,
file_write, irp_offset)) {
3219 if (written == orig_length)
3224 irp_offset += newlen;
3235 ERR(
"insert_chunk_fragmented returned %08lx\n",
Status);
3252 bool make_inline =
end <=
fcb->
Vcb->options.max_inline;
3256 ERR(
"out of memory\n");
3262 ERR(
"read_file returned %08lx\n",
Status);
3269 ERR(
"excise_extents returned %08lx\n",
Status);
3279 ERR(
"do_write_file returned %08lx\n",
Status);
3295 ERR(
"add_extent_to_fcb returned %08lx\n",
Status);
3304 TRACE(
"setting st_size to %I64x\n",
end);
3318 ERR(
"excise_extents returned %08lx\n",
Status);
3324 TRACE(
"setting st_size to %I64x\n",
end);
3357 if (!
ext2->ignore) {
3373 if (cur_inline &&
end >
fcb->
Vcb->options.max_inline) {
3377 TRACE(
"giving inline file proper extents\n");
3387 ERR(
"could not allocate %I64x bytes for data\n",
length);
3393 ERR(
"read_file returned %08lx\n",
Status);
3402 ERR(
"excise_extents returned %08lx\n",
Status);
3409 ERR(
"do_write_file returned %08lx\n",
Status);
3422 if (
end > oldalloc) {
3427 ERR(
"out of memory\n");
3440 ERR(
"read_file returned %08lx\n",
Status);
3451 ERR(
"add_extent_to_fcb returned %08lx\n",
Status);
3462 TRACE(
"extending inline file (oldalloc = %I64x, end = %I64x)\n", oldalloc,
end);
3465 TRACE(
"setting st_size to %I64x\n",
end);
3473 if (newalloc > oldalloc) {
3480 ERR(
"insert_prealloc_extent returned %08lx\n",
Status);
3492 TRACE(
"setting st_size to %I64x\n",
end);
3494 TRACE(
"newalloc = %I64x\n", newalloc);
3496 fcb->
Header.AllocationSize.QuadPart = newalloc;
3500 if (
end >
fcb->
Vcb->options.max_inline) {
3507 ERR(
"insert_prealloc_extent returned %08lx\n",
Status);
3517 TRACE(
"setting st_size to %I64x\n",
end);
3519 TRACE(
"newalloc = %I64x\n", newalloc);
3521 fcb->
Header.AllocationSize.QuadPart = newalloc;
3531 ERR(
"out of memory\n");
3546 ERR(
"add_extent_to_fcb returned %08lx\n",
Status);
3558 TRACE(
"setting st_size to %I64x\n",
end);