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);
3583 ERR(
"out of memory\n");
3594 ERR(
"write_data_complete returned %08lx\n",
Status);
3603 ERR(
"out of memory\n");
3623 add_insert_extent_rollback(
rollback,
fcb, newext);
3630 extent *newext1, *newext2;
3634 ERR(
"out of memory\n");
3640 ERR(
"out of memory\n");
3658 ERR(
"write_data_complete returned %08lx\n",
Status);
3669 ERR(
"out of memory\n");
3681 *written = end_data -
ext->offset;
3690 add_insert_extent_rollback(
rollback,
fcb, newext1);
3692 newext2->
offset = end_data;
3700 add_insert_extent_rollback(
rollback,
fcb, newext2);
3705 ERR(
"get_chunk_from_address(%I64x) failed\n", ed2->
address);
3711 ERR(
"update_changed_extent_ref returned %08lx\n",
Status);
3719 extent *newext1, *newext2;
3723 ERR(
"out of memory\n");
3729 ERR(
"out of memory\n");
3748 ERR(
"write_data_complete returned %08lx\n",
Status);
3759 ERR(
"out of memory\n");
3781 add_insert_extent_rollback(
rollback,
fcb, newext1);
3790 add_insert_extent_rollback(
rollback,
fcb, newext2);
3795 ERR(
"get_chunk_from_address(%I64x) failed\n", ed2->
address);
3801 ERR(
"update_changed_extent_ref returned %08lx\n",
Status);
3809 extent *newext1, *newext2, *newext3;
3813 ERR(
"out of memory\n");
3819 ERR(
"out of memory\n");
3826 ERR(
"out of memory\n");
3851 ERR(
"write_data_complete returned %08lx\n",
Status);
3863 ERR(
"out of memory\n");
3886 add_insert_extent_rollback(
rollback,
fcb, newext1);
3895 add_insert_extent_rollback(
rollback,
fcb, newext2);
3897 newext3->
offset = end_data;
3905 add_insert_extent_rollback(
rollback,
fcb, newext3);
3910 ERR(
"get_chunk_from_address(%I64x) failed\n", ed2->
address);
3916 ERR(
"update_changed_extent_ref returned %08lx\n",
Status);
3937#ifdef DEBUG_PARANOID
3940 bool extents_changed =
false;
3966 if (
max(last_cow_start,
start + written) <
ext->offset) {
3969 extents_changed =
true;
3973 ERR(
"excise_extents returned %08lx\n",
Status);
3979 ERR(
"insert_extent returned %08lx\n",
Status);
3983 written +=
ext->offset - start_write;
3996 TRACE(
"doing non-COW write to %I64x\n", writeaddr);
4000 ERR(
"write_data_complete returned %08lx\n",
Status);
4013 ext->inserted =
true;
4014 extents_changed =
true;
4017 written += write_len;
4028 ERR(
"do_write_file_prealloc returned %08lx\n",
Status);
4032 extents_changed =
true;
4034 written += write_len;
4041 last_cow_start =
ext->offset +
len;
4052 extents_changed =
true;
4056 ERR(
"excise_extents returned %08lx\n",
Status);
4062 ERR(
"insert_extent returned %08lx\n",
Status);
4067#ifdef DEBUG_PARANOID
4068 last_off = 0xffffffffffffffff;
4075 if (
ext->offset == last_off) {
4076 ERR(
"offset %I64x duplicated\n",
ext->offset);
4078 }
else if (
ext->offset < last_off && last_off != 0xffffffffffffffff) {
4079 ERR(
"offsets out of order\n");
4083 last_off =
ext->offset;
4090 if (extents_changed) {
4108 bool changed_length =
false;
4115 bool paging_lock =
false, acquired_fcb_lock =
false, acquired_tree_lock =
false, pagefile;
4118 TRACE(
"(%p, %p, %I64x, %p, %lx, %u, %u)\n",
Vcb,
FileObject,
offset.QuadPart,
buf, *
length, paging_io, no_cache);
4121 TRACE(
"returning success for zero-length write\n");
4126 ERR(
"error - FileObject was NULL\n");
4149 if (!wait && no_cache)
4152 if (no_cache && !paging_io &&
FileObject->SectionObjectPointer->DataSectionObject) {
4185 acquired_tree_lock =
true;
4193 acquired_fcb_lock =
true;
4199 acquired_fcb_lock =
true;
4207 TRACE(
"newlength = %I64x\n", newlength);
4209 if (off64 + *
length > newlength) {
4211 if (off64 >= newlength) {
4212 TRACE(
"paging IO tried to write beyond end of file (file size = %I64x, offset = %I64x, length = %lx)\n", newlength, off64, *
length);
4213 TRACE(
"FileObject: AllocationSize = %I64x, FileSize = %I64x, ValidDataLength = %I64x\n",
4215 Irp->IoStatus.Information = 0;
4222 newlength = off64 + *
length;
4223 changed_length =
true;
4225 TRACE(
"extending length to %I64x\n", newlength);
4230 make_inline =
false;
4232 make_inline = newlength <=
fcb->
Vcb->options.max_inline;
4234 if (changed_length) {
4236 if (!acquired_tree_lock) {
4244 acquired_tree_lock =
true;
4249 ERR(
"extend_file returned %08lx\n",
Status);
4255 fcb->
Header.FileSize.QuadPart = newlength;
4256 fcb->
Header.ValidDataLength.QuadPart = newlength;
4258 TRACE(
"AllocationSize = %I64x\n",
fcb->
Header.AllocationSize.QuadPart);
4260 TRACE(
"ValidDataLength = %I64x\n",
fcb->
Header.ValidDataLength.QuadPart);
4267 if (!
FileObject->PrivateCacheMap || changed_length) {
4290 TRACE(
"CcCopyWriteEx(%p, %I64x, %lx, %u, %p, %p)\n",
FileObject, off64, *
length,
true,
buf,
Irp->Tail.Overlay.Thread);
4295 TRACE(
"CcCopyWriteEx finished\n");
4302 TRACE(
"CcCopyWrite finished\n");
4311 if (changed_length) {
4320 if (changed_length) {
4324 ERR(
"error - xattr too long (%I64u > %lu)\n", newlength,
fcb->
adsmaxlen);
4331 ERR(
"out of memory\n");
4348 fcb->
Header.AllocationSize.QuadPart = newlength;
4349 fcb->
Header.FileSize.QuadPart = newlength;
4350 fcb->
Header.ValidDataLength.QuadPart = newlength;
4356 fcb->
Header.ValidDataLength.QuadPart = newlength;
4384 fcb->
Header.ValidDataLength.QuadPart = newlength;
4393 ERR(
"out of memory\n");
4401 TRACE(
"end_data = %I64x\n", end_data);
4404 if (changed_length) {
4413 ERR(
"read_file returned %08lx\n",
Status);
4425 ERR(
"error - excise_extents returned %08lx\n",
Status);
4440 ERR(
"add_extent_to_fcb returned %08lx\n",
Status);
4450 ERR(
"write_compressed returned %08lx\n",
Status);
4455 if (write_irp &&
Irp->MdlAddress && no_buf) {
4468 ERR(
"MmProbeAndLockPages threw exception %08lx\n",
Status);
4490 ERR(
"do_write_file returned %08lx\n",
Status);
4505 if (fileref && fileref->
parent)
4506 origii = &fileref->
parent->fcb->inode_item;
4508 ERR(
"no parent fcb found for stream\n");
4515 origii->
transid =
Vcb->superblock.generation;
4522 if (changed_length) {
4523 TRACE(
"setting st_size to %I64x\n", newlength);
4530 fileref->
parent->fcb->inode_item_changed =
true;
4546 if (changed_length) {
4561 fcb->
subvol->root_item.ctransid =
Vcb->superblock.generation;
4573 TRACE(
"CurrentByteOffset was: %I64x\n",
FileObject->CurrentByteOffset.QuadPart);
4575 TRACE(
"CurrentByteOffset now: %I64x\n",
FileObject->CurrentByteOffset.QuadPart);
4578 if (acquired_fcb_lock)
4581 if (acquired_tree_lock)
4604 Irp->IoStatus.Information = 0;
4609 if (!
Irp->AssociatedIrp.SystemBuffer) {
4612 if (
Irp->MdlAddress && !
buf) {
4613 ERR(
"MmGetSystemAddressForMdlSafe returned NULL\n");
4618 buf =
Irp->AssociatedIrp.SystemBuffer;
4623 WARN(
"tried to write to locked region\n");
4634 ERR(
"write_file2 returned %08lx\n",
Status);
4689 ERR(
"fcb was NULL\n");
4695 ERR(
"ccb was NULL\n");
4701 WARN(
"insufficient permissions\n");
4706 if (
fcb ==
Vcb->volume_fcb) {
4708 ERR(
"trying to write to volume when not locked, or locked with another FileObject\n");
4713 TRACE(
"writing directly to volume\n");
4726 if (
Vcb->readonly) {
4755 TRACE(
"wrote %Iu bytes\n",
Irp->IoStatus.Information);
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
unsigned short int uint16_t
#define InterlockedDecrement
static void write_file(HANDLE hFile, const WCHAR *str)
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp) __attribute__((nonnull(1
#define acquire_chunk_lock(c, Vcb)
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
_Post_satisfies_ static stripe __inline void get_raid0_offset(_In_ uint64_t off, _In_ uint64_t stripe_length, _In_ uint16_t num_stripes, _Out_ uint64_t *stripeoff, _Out_ uint16_t *stripe)
bool add_thread_job(device_extension *Vcb, PIRP Irp)
void do_calc_job(device_extension *Vcb, uint8_t *data, uint32_t sectors, void *csum)
void galois_double(uint8_t *data, uint32_t len)
NTSTATUS load_cache_chunk(device_extension *Vcb, chunk *c, PIRP Irp)
NTSTATUS NTSTATUS write_file2(device_extension *Vcb, PIRP Irp, LARGE_INTEGER offset, void *buf, ULONG *length, bool paging_io, bool no_cache, bool wait, bool deferred_write, bool write_irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
NTSTATUS alloc_chunk(device_extension *Vcb, uint64_t flags, chunk **pc, bool full_size) __attribute__((nonnull(1
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
void void void add_rollback(_In_ LIST_ENTRY *rollback, _In_ enum rollback_type type, _In_ __drv_aliasesMem void *ptr) __attribute__((nonnull(1
#define _Dispatch_type_(a)
NTSTATUS bool find_data_address_in_chunk(device_extension *Vcb, chunk *c, uint64_t length, uint64_t *address) __attribute__((nonnull(1
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool prealloc
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t decoded_size
NTSTATUS do_write_file(fcb *fcb, uint64_t start_data, uint64_t end_data, void *data, PIRP Irp, bool file_write, uint32_t irp_offset, LIST_ENTRY *rollback) __attribute__((nonnull(1
NTSTATUS do_write_job(device_extension *Vcb, PIRP Irp)
NTSTATUS NTSTATUS NTSTATUS void free_write_data_stripes(write_data_context *wtc) __attribute__((nonnull(1)))
void space_list_subtract2(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c, LIST_ENTRY *rollback)
@ WriteDataStatus_Pending
@ WriteDataStatus_Cancelled
@ WriteDataStatus_Cancelling
@ WriteDataStatus_Success
NTSTATUS stream_set_end_of_file_information(device_extension *Vcb, uint16_t end, fcb *fcb, file_ref *fileref, bool advance_only)
VOID(__stdcall * tFsRtlUpdateDiskCounters)(ULONG64 BytesRead, ULONG64 BytesWritten)
NTSTATUS flush_partial_stripe(device_extension *Vcb, chunk *c, partial_stripe *ps)
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t compression
_In_ fcb _In_ chunk _In_ uint64_t start_data
#define COMPRESSED_EXTENT_SIZE
void add_changed_extent_ref(chunk *c, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, uint32_t count, bool no_csum)
static __inline POPLOCK fcb_oplock(fcb *fcb)
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address) __attribute__((nonnull(1)))
NTSTATUS NTSTATUS NTSTATUS NTSTATUS extend_file(fcb *fcb, file_ref *fileref, uint64_t end, bool prealloc, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback) __attribute__((nonnull(1
VOID(__stdcall * tPsUpdateDiskCounters)(PEPROCESS Process, ULONG64 BytesRead, ULONG64 BytesWritten, ULONG ReadOperationCount, ULONG WriteOperationCount, ULONG FlushOperationCount)
NTSTATUS NTSTATUS NTSTATUS truncate_file(fcb *fcb, uint64_t end, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
NTSTATUS write_compressed(fcb *fcb, uint64_t start_data, uint64_t end_data, void *data, PIRP Irp, LIST_ENTRY *rollback)
NTSTATUS bool void NTSTATUS add_extent_to_fcb(_In_ fcb *fcb, _In_ uint64_t offset, _In_reads_bytes_(edsize) EXTENT_DATA *ed, _In_ uint16_t edsize, _In_ bool unique, _In_opt_ _When_(return >=0, __drv_aliasesMem) void *csum, _In_ LIST_ENTRY *rollback) __attribute__((nonnull(1
NTSTATUS NTSTATUS NTSTATUS write_data_complete(device_extension *Vcb, uint64_t address, void *data, uint32_t length, PIRP Irp, chunk *c, bool file_write, uint64_t irp_offset, ULONG priority) __attribute__((nonnull(1
PEPROCESS __stdcall PsGetThreadProcess(_In_ PETHREAD Thread)
BOOLEAN(__stdcall * tCcCopyWriteEx)(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, PVOID Buffer, PETHREAD IoIssuerThread)
NTSTATUS bool void NTSTATUS void add_extent(_In_ fcb *fcb, _In_ LIST_ENTRY *prevextle, _In_ __drv_aliasesMem extent *newext) __attribute__((nonnull(1
bool fcb_is_inline(fcb *fcb)
NTSTATUS NTSTATUS void clear_rollback(LIST_ENTRY *rollback) __attribute__((nonnull(1)))
NTSTATUS update_changed_extent_ref(device_extension *Vcb, chunk *c, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, int32_t count, bool no_csum, bool superseded, PIRP Irp)
NTSTATUS vol_write(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
#define release_chunk_lock(c, Vcb)
static __inline void * map_user_buffer(PIRP Irp, ULONG priority)
void space_list_subtract(chunk *c, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
NTSTATUS bool void get_raid56_lock_range(chunk *c, uint64_t address, uint64_t length, uint64_t *lockaddr, uint64_t *locklen) __attribute__((nonnull(1
static __inline bool is_subvol_readonly(root *r, PIRP Irp)
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool file_write
static __inline bool write_fcb_compressed(fcb *fcb)
VOID NTAPI CcPrepareMdlWrite(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus)
VOID NTAPI CcMdlWriteComplete(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain)
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
#define _Requires_lock_held_(lock)
#define _Releases_lock_(lock)
#define RtlInitializeBitMap
#define NT_SUCCESS(StatCode)
static const WCHAR *const ext[]
void mark_fcb_dirty(_In_ fcb *fcb)
void log_device_error(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ int error)
void chunk_lock_range(_In_ device_extension *Vcb, _In_ chunk *c, _In_ uint64_t start, _In_ uint64_t length)
tCcCopyWriteEx fCcCopyWriteEx
void chunk_unlock_range(_In_ device_extension *Vcb, _In_ chunk *c, _In_ uint64_t start, _In_ uint64_t length)
void mark_fileref_dirty(_In_ file_ref *fileref)
bool is_top_level(_In_ PIRP Irp)
tPsUpdateDiskCounters fPsUpdateDiskCounters
void queue_notification_fcb(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
tFsRtlUpdateDiskCounters fFsRtlUpdateDiskCounters
void protect_superblocks(_Inout_ chunk *c)
void init_file_cache(_In_ PFILE_OBJECT FileObject, _In_ CC_FILE_SIZES *ccfs)
#define BTRFS_INCOMPAT_FLAGS_RAID56
#define EXTENT_TYPE_PREALLOC
#define BTRFS_ENCODING_NONE
#define EXTENT_TYPE_INLINE
#define BLOCK_FLAG_RAID1C4
#define BTRFS_DEV_STAT_WRITE_ERRORS
#define EXTENT_TYPE_REGULAR
#define BTRFS_COMPRESSION_NONE
#define BLOCK_FLAG_RAID1C3
#define BTRFS_ENCRYPTION_NONE
bool insert_extent_chunk(_In_ device_extension *Vcb, _In_ fcb *fcb, _In_ chunk *c, _In_ uint64_t start_data, _In_ uint64_t length, _In_ bool prealloc, _In_opt_ void *data, _In_opt_ PIRP Irp, _In_ LIST_ENTRY *rollback, _In_ uint8_t compression, _In_ uint64_t decoded_size, _In_ bool file_write, _In_ uint64_t irp_offset)
_In_ PIO_STACK_LOCATION IrpSp
#define RemoveEntryList(Entry)
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
#define IsListEmpty(ListHead)
#define PsGetCurrentThread()
NTSTATUS ExInitializeResourceLite(PULONG res)
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
#define KeInitializeEvent(pEvt, foo, foo2)
#define KeSetEvent(pEvt, foo, foo2)
#define KeQuerySystemTime(t)
#define ExAcquireResourceExclusiveLite(res, wait)
#define RemoveHeadList(ListHead)
#define InitializeListHead(ListHead)
#define ExAcquireResourceSharedLite(res, wait)
#define FILE_WRITE_TO_END_OF_FILE
BOOLEAN NTAPI FsRtlCheckLockForWriteAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
#define FSRTL_FLAG2_IS_PAGING_FILE
VOID NTAPI CcSetFileSizes(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes)
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
GLuint GLuint GLsizei GLenum type
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLenum GLuint GLenum GLsizei const GLchar * buf
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLuint GLsizei GLsizei * length
GLsizeiptr const GLvoid GLenum usage
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint factor
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
#define EXCEPTION_EXECUTE_HANDLER
VOID NTAPI IoBuildPartialMdl(IN PMDL SourceMdl, IN PMDL TargetMdl, IN PVOID VirtualAddress, IN ULONG Length)
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
static PIO_STATUS_BLOCK iosb
#define _Function_class_(x)
#define _In_reads_bytes_(size)
#define _Pre_satisfies_(cond)
#define _When_(expr, annos)
DRIVER_DISPATCH(nfs41_FsdDispatch)
#define IoSkipCurrentIrpStackLocation(Irp)
BOOLEAN NTAPI CcCopyWrite(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN PVOID Buffer)
BOOLEAN NTAPI CcCanIWrite(IN PFILE_OBJECT FileObject, IN ULONG BytesToWrite, IN BOOLEAN Wait, IN UCHAR Retrying)
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
BOOLEAN NTAPI ExIsResourceAcquiredExclusiveLite(IN PERESOURCE Resource)
#define IoCompleteRequest
BOOLEAN NTAPI IoIsOperationSynchronous(IN PIRP Irp)
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
BOOLEAN NTAPI IoCancelIrp(IN PIRP Irp)
PIRP NTAPI IoGetTopLevelIrp(VOID)
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
VOID NTAPI IoFreeIrp(IN PIRP Irp)
PIRP NTAPI IoMakeAssociatedIrp(IN PIRP Irp, IN CCHAR StackSize)
BOOLEAN NTAPI IoIsSystemThread(IN PETHREAD Thread)
#define STATUS_INTERNAL_ERROR
#define STATUS_FILE_LOCK_CONFLICT
NTSTATUS NTAPI FsRtlCheckOplock(IN POPLOCK Oplock, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
#define BTRFS_INODE_NODATASUM
#define BTRFS_INODE_NODATACOW
#define _SEH2_GetExceptionCode()
#define _SEH2_EXCEPT(...)
#define offsetof(TYPE, MEMBER)
int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
#define STATUS_DEVICE_NOT_READY
#define STATUS_MORE_PROCESSING_REQUIRED
#define BLOCK_FLAG_DUPLICATE
#define BLOCK_FLAG_SYSTEM
#define BTRFS_TYPE_SYMLINK
#define BLOCK_FLAG_RAID10
#define BLOCK_FLAG_METADATA
LARGE_INTEGER ValidDataLength
LARGE_INTEGER AllocationSize
struct _IO_STACK_LOCATION::@3974::@3979 Write
union _IO_STACK_LOCATION::@1575 Parameters
struct _LIST_ENTRY * Blink
struct _LIST_ENTRY * Flink
bool user_set_change_time
struct _device_extension * Vcb
FSRTL_ADVANCED_FCB_HEADER Header
struct _file_ref * parent
#define RtlCopyMemory(Destination, Source, Length)
#define RtlZeroMemory(Destination, Length)
#define CONTAINING_RECORD(address, type, field)
#define STATUS_INVALID_DEVICE_REQUEST
#define STATUS_MEDIA_WRITE_PROTECTED
#define STATUS_ACCESS_DENIED
#define STATUS_INVALID_PARAMETER
#define STATUS_INSUFFICIENT_RESOURCES
_In_ PDEVICE_OBJECT DeviceObject
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
#define success(from, fromstr, to, tostr)
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
#define FILE_ACTION_MODIFIED_STREAM
#define FILE_NOTIFY_CHANGE_SIZE
#define FILE_ACTION_MODIFIED
#define FILE_NOTIFY_CHANGE_STREAM_WRITE
#define FILE_NOTIFY_CHANGE_STREAM_SIZE
#define FO_SYNCHRONOUS_IO
#define FILE_NOTIFY_CHANGE_LAST_WRITE
#define MmGetMdlVirtualAddress(_Mdl)
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)