28#define MAX_CSUM_SIZE (4096 - sizeof(tree_header) - (2 * sizeof(leaf_node)))
32#define BATCH_ITEM_LIMIT 1000
89 ERR(
"IoAllocateIrp failed\n");
98 Irp->AssociatedIrp.SystemBuffer =
data;
103 if (!
Irp->MdlAddress) {
118 ERR(
"MmProbeAndLockPages threw exception %08lx\n",
Status);
143 ERR(
"IoCallDriver returned %08lx\n",
Status);
160 ERR(
"out of memory\n");
166 dev->num_trim_entries++;
195 while (le != &
c->deleting) {
204 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
205 if (
c->devices[
i] &&
c->devices[
i]->devobj && !
c->devices[
i]->readonly &&
c->devices[
i]->trim)
210 uint16_t startoffstripe, endoffstripe,
i;
212 get_raid0_offset(
s->address -
c->offset,
c->chunk_item->stripe_length,
c->chunk_item->num_stripes, &startoff, &startoffstripe);
213 get_raid0_offset(
s->address -
c->offset +
s->size - 1,
c->chunk_item->stripe_length,
c->chunk_item->num_stripes, &endoff, &endoffstripe);
215 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
216 if (
c->devices[
i] &&
c->devices[
i]->devobj && !
c->devices[
i]->readonly &&
c->devices[
i]->trim) {
219 if (startoffstripe >
i)
220 stripestart = startoff - (startoff %
c->chunk_item->stripe_length) +
c->chunk_item->stripe_length;
221 else if (startoffstripe ==
i)
222 stripestart = startoff;
224 stripestart = startoff - (startoff %
c->chunk_item->stripe_length);
226 if (endoffstripe >
i)
227 stripeend = endoff - (endoff %
c->chunk_item->stripe_length) +
c->chunk_item->stripe_length;
228 else if (endoffstripe ==
i)
229 stripeend = endoff + 1;
231 stripeend = endoff - (endoff %
c->chunk_item->stripe_length);
233 if (stripestart != stripeend)
239 uint16_t sub_stripes, startoffstripe, endoffstripe,
i;
241 sub_stripes =
max(1,
c->chunk_item->sub_stripes);
243 get_raid0_offset(
s->address -
c->offset,
c->chunk_item->stripe_length,
c->chunk_item->num_stripes / sub_stripes, &startoff, &startoffstripe);
244 get_raid0_offset(
s->address -
c->offset +
s->size - 1,
c->chunk_item->stripe_length,
c->chunk_item->num_stripes / sub_stripes, &endoff, &endoffstripe);
246 startoffstripe *= sub_stripes;
247 endoffstripe *= sub_stripes;
249 for (
i = 0;
i <
c->chunk_item->num_stripes;
i += sub_stripes) {
253 if (startoffstripe >
i)
254 stripestart = startoff - (startoff %
c->chunk_item->stripe_length) +
c->chunk_item->stripe_length;
255 else if (startoffstripe ==
i)
256 stripestart = startoff;
258 stripestart = startoff - (startoff %
c->chunk_item->stripe_length);
260 if (endoffstripe >
i)
261 stripeend = endoff - (endoff %
c->chunk_item->stripe_length) +
c->chunk_item->stripe_length;
262 else if (endoffstripe ==
i)
263 stripeend = endoff + 1;
265 stripeend = endoff - (endoff %
c->chunk_item->stripe_length);
267 if (stripestart != stripeend) {
268 for (
j = 0;
j < sub_stripes;
j++) {
269 if (
c->devices[
i+
j] &&
c->devices[
i+
j]->devobj && !
c->devices[
i+
j]->readonly &&
c->devices[
i+
j]->trim)
287#ifdef DEBUG_TRIM_EMULATION
313#ifdef DEBUG_TRIM_EMULATION
317 unsigned int i = 0,
count = 0;
319 le =
dev->trim_list.Flink;
320 while (le != &
dev->trim_list) {
331 ERR(
"out of memory\n");
338 le =
dev->trim_list.Flink;
339 while (le != &
dev->trim_list) {
343 WARN(
"(%I64x, %I64x)\n",
s->address,
s->size);
348 ERR(
"IoAllocateIrp failed\n");
357 ERR(
"out of memory\n");
364 ERR(
"IoAllocateMdl failed\n");
406#ifndef DEBUG_TRIM_EMULATION
414 le =
Vcb->chunks.Flink;
415 while (le != &
Vcb->chunks) {
418 if (
c->space_changed) {
421 if (
c->space_changed) {
422 if (
Vcb->trim && !
Vcb->options.no_trim)
434 c->space_changed =
false;
444 if (
Vcb->trim && !
Vcb->options.no_trim) {
445#ifndef DEBUG_TRIM_EMULATION
451 le =
Vcb->devices.Flink;
452 while (le != &
Vcb->devices) {
455 if (
dev->devobj && !
dev->readonly &&
dev->trim &&
dev->num_trim_entries > 0)
471 ERR(
"out of memory\n");
478 le =
Vcb->devices.Flink;
479 while (le != &
Vcb->devices) {
482 if (
dev->devobj && !
dev->readonly &&
dev->trim &&
dev->num_trim_entries > 0) {
483#ifdef DEBUG_TRIM_EMULATION
494 ERR(
"out of memory\n");
501 stripe->dmdsa->ParameterBlockOffset = 0;
502 stripe->dmdsa->ParameterBlockLength = 0;
510 le2 =
dev->trim_list.Flink;
511 while (le2 != &
dev->trim_list) {
524 ERR(
"IoAllocateIrp failed\n");
536 stripe->Irp->AssociatedIrp.SystemBuffer =
stripe->dmdsa;
552 dev->num_trim_entries = 0;
554#ifndef DEBUG_TRIM_EMULATION
562#ifndef DEBUG_TRIM_EMULATION
582 le =
Vcb->trees.Flink;
583 while (le != &
Vcb->trees) {
587 if (
t->header.num_items == 0 &&
t->parent) {
588#ifdef DEBUG_WRITE_LOOPS
589 ERR(
"empty tree found, looping again\n");
595#ifdef DEBUG_WRITE_LOOPS
596 ERR(
"overlarge tree found (%u > %u), looping again\n",
t->size,
maxsize);
601 if (!
t->has_new_address) {
602#ifdef DEBUG_WRITE_LOOPS
603 ERR(
"tree found without new address, looping again\n");
620 bool nothing_found =
true;
624 le =
Vcb->trees.Flink;
625 while (le != &
Vcb->trees) {
628 if (
t->write &&
t->header.level ==
level) {
629 TRACE(
"tree %p: root = %I64x, level = %x, parent = %p\n",
t,
t->header.tree_id,
t->header.level,
t->parent);
631 nothing_found =
false;
634 if (!
t->parent->write)
635 TRACE(
"adding tree %p (level %x)\n",
t->parent,
t->header.level);
637 t->parent->write =
true;
638 }
else if (
t->root !=
Vcb->root_root &&
t->root !=
Vcb->chunk_root) {
643 searchkey.
obj_id =
t->root->id;
645 searchkey.
offset = 0xffffffffffffffff;
649 ERR(
"error - find_item returned %08lx\n",
Status);
654 ERR(
"could not find ROOT_ITEM for tree %I64x\n", searchkey.
obj_id);
662 ERR(
"out of memory\n");
670 ERR(
"delete_tree_item returned %08lx\n",
Status);
677 ERR(
"insert_tree_item returned %08lx\n",
Status);
716 ERR(
"out of memory\n");
728 ERR(
"insert_tree_item returned %08lx\n",
Status);
750 if (
Vcb->superblock.node_size >
c->chunk_item->size -
c->used)
753 if (!
c->cache_loaded) {
757 ERR(
"load_cache_chunk returned %08lx\n",
Status);
765 if (!
c->last_alloc_set) {
768 c->last_alloc =
s->address;
769 c->last_alloc_set =
true;
771 if (
s->size >=
Vcb->superblock.node_size) {
773 c->last_alloc +=
Vcb->superblock.node_size;
779 while (le != &
c->space) {
782 if (
s->address <=
c->last_alloc &&
s->address +
s->size >=
c->last_alloc +
Vcb->superblock.node_size) {
784 c->last_alloc +=
Vcb->superblock.node_size;
792 while (le != &
c->space_size) {
795 if (
s->size ==
Vcb->superblock.node_size) {
797 c->last_alloc =
s->address +
Vcb->superblock.node_size;
799 }
else if (
s->size <
Vcb->superblock.node_size) {
800 if (le ==
c->space_size.
Flink)
806 c->last_alloc =
s->address +
Vcb->superblock.node_size;
816 if (
s->size >
Vcb->superblock.node_size) {
818 c->last_alloc =
s->address +
Vcb->superblock.node_size;
831 TRACE(
"(%p, %x, %I64x, %p, %p, %p, %p)\n",
Vcb,
level, root_id,
c, new_address,
Irp,
rollback);
847 ERR(
"out of memory\n");
860 ERR(
"insert_tree_item returned %08lx\n",
Status);
889 if (
t->has_address) {
894 t->new_address =
addr;
895 t->has_new_address =
true;
902 le =
Vcb->chunks.Flink;
903 while (le != &
Vcb->chunks) {
906 if (!
c->readonly && !
c->reloc) {
913 t->new_address =
addr;
914 t->has_new_address =
true;
930 ERR(
"alloc_chunk returned %08lx\n",
Status);
937 if ((
c->chunk_item->size -
c->used) >=
Vcb->superblock.node_size) {
941 t->new_address =
addr;
942 t->has_new_address =
true;
951 ERR(
"couldn't find any metadata chunks with %x bytes free\n",
Vcb->superblock.node_size);
964 ERR(
"error - refcount for extent %I64x was 0\n",
address);
971 root =
t->header.tree_id;
975 ERR(
"decrease_extent_refcount_tree returned %08lx\n",
Status);
985 if (!
c->cache_loaded) {
989 ERR(
"load_cache_chunk returned %08lx\n",
Status);
995 c->used -=
Vcb->superblock.node_size;
1001 ERR(
"could not find chunk for address %I64x\n",
address);
1014 while (le2 !=
list) {
1027 ERR(
"out of memory\n");
1051 while (le2 !=
list) {
1064 ERR(
"out of memory\n");
1086 if (!
t->updated_extents &&
t->has_address) {
1089 ERR(
"update_tree_extents returned %08lx\n",
Status);
1094 searchkey.
obj_id =
t->header.address;
1096 searchkey.
offset = 0xffffffffffffffff;
1100 ERR(
"error - find_item returned %08lx\n",
Status);
1116 ERR(
"refcount for extent %I64x was 0\n",
t->header.address);
1124 if (
t->header.level == 0) {
1128 while (le != &
t->itemlist) {
1145 le2 =
c->changed_extents.
Flink;
1146 while (le2 != &
c->changed_extents) {
1158 edr.
root =
t->root->id;
1166 ERR(
"add_changed_extent_ref_edr returned %08lx\n",
Status);
1172 ERR(
"add_changed_extent_ref_edr returned %08lx\n",
Status);
1179 ERR(
"increase_extent_refcount returned %08lx\n",
Status);
1189 sdr.
offset =
t->header.address;
1195 ERR(
"decrease_extent_refcount returned %08lx\n",
Status);
1203 while (le2 != &ce->
refs) {
1249 while (le != &
t->itemlist) {
1256 &tbr, &td->
key,
t->header.level - 1,
Irp);
1258 ERR(
"increase_extent_refcount returned %08lx\n",
Status);
1268 sbr.
offset =
t->header.address;
1271 t->header.address,
false,
Irp);
1273 ERR(
"decrease_extent_refcount returned %08lx\n",
Status);
1292 sbr.
offset =
t->parent->header.address;
1295 t->parent->header.address,
false,
Irp);
1297 ERR(
"decrease_extent_refcount returned %08lx\n",
Status);
1304 tbr.
offset =
t->parent->header.tree_id;
1306 tbr.
offset =
t->header.tree_id;
1309 t->parent ? &
t->paritem->key :
NULL,
t->header.level,
Irp);
1311 ERR(
"increase_extent_refcount returned %08lx\n",
Status);
1317 t->header.flags &= ~HEADER_FLAG_SHARED_BACKREF;
1320 if (rc > 1 ||
t->header.tree_id ==
t->root->id) {
1324 ERR(
"reduce_tree_extent returned %08lx\n",
Status);
1329 t->has_address =
false;
1332 if (
t->header.tree_id ==
t->root->id) {
1337 if (
t->header.level > 0) {
1341 while (le != &
t->itemlist) {
1345 if (
t->header.tree_id ==
t->root->id) {
1348 sbr.
offset =
t->header.address;
1360 ERR(
"increase_extent_refcount returned %08lx\n",
Status);
1371 while (le != &
t->itemlist) {
1387 le2 =
c->changed_extents.
Flink;
1388 while (le2 != &
c->changed_extents) {
1400 if (
t->header.tree_id ==
t->root->id) {
1403 sdr.
offset =
t->header.address;
1409 ERR(
"add_changed_extent_ref_edr returned %08lx\n",
Status);
1415 ERR(
"add_changed_extent_ref_edr returned %08lx\n",
Status);
1424 edr.
root =
t->root->id;
1432 ERR(
"add_changed_extent_ref_edr returned %08lx\n",
Status);
1438 ERR(
"add_changed_extent_ref_edr returned %08lx\n",
Status);
1447 ERR(
"increase_extent_refcount returned %08lx\n",
Status);
1459 t->updated_extents =
true;
1460 t->header.tree_id =
t->root->id;
1468 bool changed =
false;
1473 le =
Vcb->trees.Flink;
1474 while (le != &
Vcb->trees) {
1477 if (
t->write && !
t->has_new_address) {
1480 if (
t->has_address) {
1484 if (!
c->cache_loaded) {
1487 if (!
c->cache_loaded) {
1491 ERR(
"load_cache_chunk returned %08lx\n",
Status);
1504 ERR(
"get_tree_new_address returned %08lx\n",
Status);
1508 TRACE(
"allocated extent %I64x\n",
t->new_address);
1513 c->used +=
Vcb->superblock.node_size;
1515 ERR(
"could not find chunk for address %I64x\n",
t->new_address);
1521 if (
t->header.level > max_level)
1522 max_level =
t->header.level;
1533 le =
Vcb->trees.Flink;
1534 while (le != &
Vcb->trees) {
1537 if (
t->write && !
t->updated_extents &&
t->has_address &&
t->header.level ==
level) {
1540 ERR(
"update_tree_extents returned %08lx\n",
Status);
1563 le =
Vcb->trees.Flink;
1564 while (le != &
Vcb->trees) {
1567 if (
t->write && !
t->parent) {
1568 if (
t->root !=
Vcb->root_root &&
t->root !=
Vcb->chunk_root) {
1572 searchkey.
obj_id =
t->root->id;
1574 searchkey.
offset = 0xffffffffffffffff;
1578 ERR(
"error - find_item returned %08lx\n",
Status);
1583 ERR(
"could not find ROOT_ITEM for tree %I64x\n", searchkey.
obj_id);
1587 TRACE(
"updating the address for root %I64x to %I64x\n", searchkey.
obj_id,
t->new_address);
1589 t->root->root_item.block_number =
t->new_address;
1590 t->root->root_item.root_level =
t->header.level;
1591 t->root->root_item.generation =
Vcb->superblock.generation;
1592 t->root->root_item.generation2 =
Vcb->superblock.generation;
1599 t->root->treeholder.address =
t->new_address;
1600 t->root->treeholder.generation =
Vcb->superblock.generation;
1612 ERR(
"update_chunk_caches returned %08lx\n",
Status);
1628 bool raid56 =
false;
1632 le = tree_writes->
Flink;
1633 while (le != tree_writes) {
1645 ERR(
"out of memory\n");
1680 le = tree_writes->
Flink;
1681 while (le != tree_writes) {
1691 ERR(
"out of memory\n");
1695 le = tree_writes->
Flink;
1697 while (le != tree_writes) {
1711 ERR(
"write_data returned %08lx\n",
Status);
1713 for (
i = 0;
i < num_bits;
i++) {
1726 for (
i = 0;
i < num_bits;
i++) {
1727 if (wtc[
i].stripes.Flink != &wtc[
i].
stripes) {
1730 while (le != &wtc[
i].stripes) {
1743 for (
i = 0;
i < num_bits;
i++) {
1744 if (wtc[
i].need_wait)
1748 for (
i = 0;
i < num_bits;
i++) {
1750 while (le != &wtc[
i].stripes) {
1770 le = tree_writes->
Flink;
1771 while (le != tree_writes) {
1790 ERR(
"flush_partial_stripe returned %08lx\n",
Status);
1807 switch (
Vcb->superblock.csum_type) {
1839 bool nothing_found =
true;
1843 le =
Vcb->trees.Flink;
1844 while (le != &
Vcb->trees) {
1847 if (
t->write &&
t->header.level ==
level) {
1848 KEY firstitem, searchkey;
1852 if (!
t->has_new_address) {
1853 ERR(
"error - tried to write tree with no new address\n");
1858 while (le2 != &
t->itemlist) {
1861 firstitem = td->
key;
1868 t->paritem->key = firstitem;
1869 t->paritem->treeholder.address =
t->new_address;
1870 t->paritem->treeholder.generation =
Vcb->superblock.generation;
1876 searchkey.
obj_id =
t->new_address;
1878 searchkey.
offset =
Vcb->superblock.node_size;
1882 ERR(
"error - find_item returned %08lx\n",
Status);
1887 ERR(
"could not find %I64x,%x,%I64x in extent_root (found %I64x,%x,%I64x instead)\n", searchkey.
obj_id, searchkey.
obj_type, searchkey.
offset,
tp.
item->
key.
obj_id,
tp.
item->
key.
obj_type,
tp.
item->
key.
offset);
1900 nothing_found =
false;
1910 TRACE(
"allocated tree extents\n");
1912 le =
Vcb->trees.Flink;
1913 while (le != &
Vcb->trees) {
1916#ifdef DEBUG_PARANOID
1922#ifdef DEBUG_PARANOID
1927 while (le2 != &
t->itemlist) {
1936 }
else if (
keycmp(td->
key, lastkey) == -1) {
1945 if (
t->header.level == 0)
1951 if (
t->header.level == 0)
1956 if (num_items !=
t->header.num_items) {
1957 ERR(
"tree %I64x, level %x: num_items was %x, expected %x\n",
t->root->id,
t->header.level, num_items,
t->header.num_items);
1961 if (
size !=
t->size) {
1962 ERR(
"tree %I64x, level %x: size was %x, expected %x\n",
t->root->id,
t->header.level,
size,
t->size);
1966 if (
t->header.num_items == 0 &&
t->parent) {
1967 ERR(
"tree %I64x, level %x: tried to write empty tree with parent\n",
t->root->id,
t->header.level);
1972 ERR(
"tree %I64x, level %x: tried to write overlarge tree (%x > %Ix)\n",
t->root->id,
t->header.level,
t->size,
Vcb->superblock.node_size -
sizeof(
tree_header));
1977 ERR(
"tree %p\n",
t);
1979 while (le2 != &
t->itemlist) {
1989 t->header.address =
t->new_address;
1990 t->header.generation =
Vcb->superblock.generation;
1991 t->header.tree_id =
t->root->id;
1993 t->header.fs_uuid =
Vcb->superblock.metadata_uuid;
1994 t->has_address =
true;
1998 ERR(
"out of memory\n");
2008 if (
t->header.level == 0) {
2014 while (le2 != &
t->itemlist) {
2035 while (le2 != &
t->itemlist) {
2052 ERR(
"out of memory\n");
2066 bool inserted =
false;
2068 le2 = tree_writes.
Flink;
2069 while (le2 != &tree_writes) {
2091 ERR(
"do_tree_writes returned %08lx\n",
Status);
2118 sb->root_tree_generation =
Vcb->superblock.generation;
2122 sb->chunk_tree_generation =
Vcb->superblock.chunk_root_generation;
2127 searchkey.
offset = 0xffffffffffffffff;
2245 ERR(
"out of memory\n");
2261 ERR(
"out of memory\n");
2270 ERR(
"IoAllocateIrp failed\n");
2284 stripe->Irp->AssociatedIrp.SystemBuffer =
sb;
2291 ERR(
"IoAllocateMdl failed\n");
2321 ERR(
"no superblocks written!\n");
2334 le =
Vcb->trees.Flink;
2335 while (le != &
Vcb->trees) {
2338 if (
t->write && !
t->parent) {
2339 if (
t->root ==
Vcb->root_root) {
2340 Vcb->superblock.root_tree_addr =
t->new_address;
2341 Vcb->superblock.root_level =
t->header.level;
2342 }
else if (
t->root ==
Vcb->chunk_root) {
2343 Vcb->superblock.chunk_tree_addr =
t->new_address;
2344 Vcb->superblock.chunk_root_generation =
t->header.generation;
2345 Vcb->superblock.chunk_root_level =
t->header.level;
2362 le =
Vcb->devices.Flink;
2363 while (le != &
Vcb->devices) {
2366 if (
dev->devobj && !
dev->readonly) {
2369 ERR(
"write_superblock returned %08lx\n",
Status);
2378 ERR(
"error - not writing any superblocks\n");
2384 while (le != &
context.stripes) {
2395 while (le != &
context.stripes) {
2453 while (le != &ce->
refs) {
2476 ERR(
"increase_extent_refcount_data returned %08lx\n",
Status);
2499 while (le != &ce->
refs) {
2527 ERR(
"decrease_extent_refcount_data returned %08lx\n",
Status);
2543 ERR(
"error - find_item returned %08lx\n",
Status);
2548 ERR(
"could not find (%I64x,%x,%I64x) in extent tree\n", searchkey.
obj_id, searchkey.
obj_type, searchkey.
offset);
2556 ERR(
"out of memory\n");
2566 ERR(
"insert_tree_item returned %08lx\n",
Status);
2573 ERR(
"delete_tree_item returned %08lx\n",
Status);
2585#ifdef DEBUG_PARANOID
2587 WARN(
"old_refs not empty\n");
2592 c->used -= ce->
size;
2632 ERR(
"out of memory\n");
2641 ERR(
"insert_tree_item returned %08lx\n",
Status);
2652 }
while (length2 > 0);
2655 ERR(
"find_item returned %08lx\n",
Status);
2674 ERR(
"find_item returned %08lx\n",
Status);
2687 TRACE(
"endaddr = %I64x\n", endaddr);
2693 ERR(
"out of memory\n");
2699 ERR(
"out of memory\n");
2713 ERR(
"find_item returned %08lx\n",
Status);
2733 ERR(
"delete_tree_item returned %08lx\n",
Status);
2756 while (runlength != 0) {
2779 ERR(
"out of memory\n");
2791 ERR(
"insert_tree_item returned %08lx\n",
Status);
2800 }
while (runlength > 0);
2822 while (le != &
Vcb->chunks) {
2827 if (!
c->cache_loaded && (!
IsListEmpty(&
c->changed_extents) ||
c->used !=
c->oldused)) {
2831 ERR(
"load_cache_chunk returned %08lx\n",
Status);
2837 le2 =
c->changed_extents.Flink;
2838 while (le2 != &
c->changed_extents) {
2844 ERR(
"flush_changed_extent returned %08lx\n",
Status);
2857 ERR(
"create_chunk returned %08lx\n",
Status);
2864 if (
c->old_cache->dirty) {
2871 ERR(
"flush_fcb returned %08lx\n",
Status);
2879 ERR(
"commit_batch_list returned %08lx\n",
Status);
2887 if (
c->old_cache->refcount == 0)
2890 c->old_cache =
NULL;
2893 if (
c->used !=
c->oldused) {
2896 searchkey.
offset =
c->chunk_item->size;
2900 ERR(
"error - find_item returned %08lx\n",
Status);
2906 ERR(
"could not find (%I64x,%x,%I64x) in extent_root\n", searchkey.
obj_id, searchkey.
obj_type, searchkey.
offset);
2921 ERR(
"out of memory\n");
2928 bgi->
used =
c->used;
2930#ifdef DEBUG_PARANOID
2931 if (bgi->
used & 0x8000000000000000) {
2932 ERR(
"refusing to write BLOCK_GROUP_ITEM with negative usage value (%I64x)\n", bgi->
used);
2937 TRACE(
"adjusting usage of chunk %I64x to %I64x\n",
c->offset,
c->used);
2941 ERR(
"delete_tree_item returned %08lx\n",
Status);
2949 ERR(
"insert_tree_item returned %08lx\n",
Status);
2955 Vcb->superblock.bytes_used +=
c->used -
c->oldused;
2956 c->oldused =
c->used;
2976 while (le != &
t->itemlist) {
2993 ERR(
"out of memory\n");
2997 if (
t->header.level > 0) {
2999 if (!
nt->nonpaged) {
3000 ERR(
"out of memory\n");
3010 nt->header.address = 0;
3011 nt->header.generation =
Vcb->superblock.generation;
3012 nt->header.num_items =
t->header.num_items - numitems;
3015 nt->has_address =
false;
3017 nt->parent =
t->parent;
3019#ifdef DEBUG_PARANOID
3020 if (
nt->parent &&
nt->parent->header.level <=
nt->header.level)
int3;
3024 nt->new_address = 0;
3025 nt->has_new_address =
false;
3026 nt->updated_extents =
false;
3027 nt->uniqueness_determined =
true;
3028 nt->is_unique =
true;
3029 nt->list_entry_hash.Flink =
NULL;
3036 nt->itemlist.Blink =
t->itemlist.Blink;
3037 nt->itemlist.Flink->Blink = &
nt->itemlist;
3038 nt->itemlist.Blink->Flink = &
nt->itemlist;
3041 t->itemlist.
Blink->Flink = &
t->itemlist;
3045 t->header.num_items = numitems;
3050 if (
nt->header.level > 0) {
3053 while (le != &
nt->itemlist) {
3058#ifdef DEBUG_PARANOID
3068 while (le != &
nt->itemlist) {
3075 ERR(
"out of memory\n");
3089 td = ExAllocateFromPagedLookasideList(&
Vcb->tree_data_lookaside);
3091 ERR(
"out of memory\n");
3095 td->
key = newfirstitem->
key;
3104 nt->parent->header.num_items++;
3110 TRACE(
"adding new tree parent\n");
3112 if (
nt->header.level == 255) {
3113 ERR(
"cannot add parent to tree at level 255\n");
3119 ERR(
"out of memory\n");
3124 if (!
pt->nonpaged) {
3125 ERR(
"out of memory\n");
3133 pt->header.address = 0;
3134 pt->header.num_items = 2;
3135 pt->header.level =
nt->header.level + 1;
3138 pt->has_address =
false;
3143 pt->new_address = 0;
3144 pt->has_new_address =
false;
3145 pt->updated_extents =
false;
3147 pt->uniqueness_determined =
true;
3148 pt->is_unique =
true;
3149 pt->list_entry_hash.Flink =
NULL;
3155 td = ExAllocateFromPagedLookasideList(&
Vcb->tree_data_lookaside);
3157 ERR(
"out of memory\n");
3170 td = ExAllocateFromPagedLookasideList(&
Vcb->tree_data_lookaside);
3172 ERR(
"out of memory\n");
3176 td->
key = newfirstitem->
key;
3187 t->root->treeholder.tree =
pt;
3192#ifdef DEBUG_PARANOID
3193 if (
t->parent &&
t->parent->header.level <=
t->header.level)
int3;
3194 if (
nt->parent &&
nt->parent->header.level <=
nt->header.level)
int3;
3198 t->root->root_item.bytes_used +=
Vcb->superblock.node_size;
3213 while (le != &
t->itemlist) {
3217 if (
t->header.level == 0)
3222 if (numitems == 0 &&
ds >
Vcb->superblock.node_size -
sizeof(
tree_header)) {
3223 ERR(
"(%I64x,%x,%I64x) in tree %I64x is too large (%x > %Ix)\n",
3251 if (
t->uniqueness_determined)
3252 return t->is_unique;
3257 if (
t->has_address) {
3258 searchkey.
obj_id =
t->header.address;
3260 searchkey.
offset = 0xffffffffffffffff;
3264 ERR(
"error - find_item returned %08lx\n",
Status);
3301 t->uniqueness_determined =
true;
3310 tree *next_tree, *par;
3314 TRACE(
"trying to amalgamate tree in root %I64x, level %x (size %u)\n",
t->root->id,
t->header.level,
t->size);
3317 le =
t->paritem->list_entry.
Flink;
3318 while (le != &
t->parent->itemlist) {
3337 ERR(
"do_load_tree returned %08lx\n",
Status);
3350 ERR(
"update_tree_extents returned %08lx\n",
Status);
3359 t->size += next_tree->
size;
3364 while (le != &next_tree->
itemlist) {
3369#ifdef DEBUG_PARANOID
3380 while (le != &next_tree->
itemlist) {
3387 ERR(
"out of memory\n");
3401 t->itemlist.Blink->Flink->Blink =
t->itemlist.Blink;
3403 t->itemlist.Blink->Flink = &
t->itemlist;
3408 next_tree->
size = 0;
3414 ERR(
"reduce_tree_extent returned %08lx\n",
Status);
3421 ERR(
"reduce_tree_extent returned %08lx\n",
Status);
3426 if (!nextparitem->
ignore) {
3427 nextparitem->
ignore =
true;
3428 next_tree->
parent->header.num_items--;
3431 *done_deletions =
true;
3444 next_tree->
root->root_item.bytes_used -=
Vcb->superblock.node_size;
3451 ULONG avg_size = (
t->size + next_tree->
size) / 2;
3452 KEY firstitem = {0, 0, 0};
3453 bool changed =
false;
3455 TRACE(
"attempting rebalance\n");
3476#ifdef DEBUG_PARANOID
3483 ERR(
"out of memory\n");
3497 t->header.num_items++;
3508 while (le != &next_tree->
itemlist) {
3512 firstitem = td->
key;
3544 searchkey.
offset =
t->header.level;
3548 ERR(
"error - find_item returned %08lx\n",
Status);
3559 ERR(
"out of memory\n");
3569 ERR(
"delete_tree_item returned %08lx\n",
Status);
3576 ERR(
"insert_tree_item returned %08lx\n",
Status);
3587 searchkey.
offset = 0xffffffffffffffff;
3591 ERR(
"error - find_item returned %08lx\n",
Status);
3606 ERR(
"out of memory\n");
3614 ERR(
"delete_tree_item returned %08lx\n",
Status);
3623 ERR(
"insert_tree_item returned %08lx\n",
Status);
3631 ERR(
"could not find EXTENT_ITEM for address %I64x\n",
address);
3639 if (
t->parent && !
t->parent->updated_extents &&
t->parent->has_address) {
3647 ERR(
"update_tree_extents returned %08lx\n",
Status);
3657 bool empty, done_deletions =
false;
3672 le =
Vcb->trees.Flink;
3674 while (le != &
Vcb->trees) {
3679 if (
t->write &&
t->header.level ==
level) {
3682 if (
t->header.num_items == 0) {
3684 done_deletions =
true;
3686 TRACE(
"deleting tree in root %I64x\n",
t->root->id);
3688 t->root->root_item.bytes_used -=
Vcb->superblock.node_size;
3690 if (
t->has_new_address) {
3694 ERR(
"reduce_tree_extent returned %08lx\n",
Status);
3698 t->has_new_address =
false;
3699 }
else if (
t->has_address) {
3703 ERR(
"reduce_tree_extent returned %08lx\n",
Status);
3707 t->has_address =
false;
3710 if (!
t->paritem->ignore) {
3711 t->paritem->ignore =
true;
3712 t->parent->header.num_items--;
3721 }
else if (
t->header.level != 0) {
3722 if (
t->has_new_address) {
3726 ERR(
"update_extent_level returned %08lx\n",
Status);
3731 t->header.level = 0;
3733 }
else if (
t->size >
Vcb->superblock.node_size -
sizeof(
tree_header)) {
3734 TRACE(
"splitting overlarge tree (%x > %Ix)\n",
t->size,
Vcb->superblock.node_size -
sizeof(
tree_header));
3736 if (!
t->updated_extents &&
t->has_address) {
3739 ERR(
"update_tree_extents_recursive returned %08lx\n",
Status);
3747 ERR(
"split_tree returned %08lx\n",
Status);
3759 TRACE(
"nothing found for level %lu\n",
level);
3764 min_size = (
Vcb->superblock.node_size -
sizeof(
tree_header)) / 2;
3765 min_size_fst = (
Vcb->superblock.node_size -
sizeof(
tree_header)) / 4;
3770 le =
Vcb->trees.Flink;
3772 while (le != &
Vcb->trees) {
3775 if (
t->write &&
t->header.level ==
level &&
t->header.num_items > 0 &&
t->parent &&
3783 ERR(
"try_tree_amalgamate returned %08lx\n",
Status);
3786 }
while (done &&
t->size < min_size);
3795 if (done_deletions) {
3799 le =
Vcb->trees.Flink;
3800 while (le != &
Vcb->trees) {
3804 if (
t->write &&
t->header.level ==
level) {
3805 if (!
t->parent &&
t->header.num_items == 1) {
3810 while (le2 != &
t->itemlist) {
3817 TRACE(
"deleting top-level tree in root %I64x with one item\n",
t->root->id);
3819 if (
t->has_new_address) {
3823 ERR(
"reduce_tree_extent returned %08lx\n",
Status);
3827 t->has_new_address =
false;
3828 }
else if (
t->has_address) {
3832 ERR(
"reduce_tree_extent returned %08lx\n",
Status);
3836 t->has_address =
false;
3840 KEY searchkey = {0,0,0};
3845 ERR(
"error - find_item returned %08lx\n",
Status);
3857 t->root->root_item.bytes_used -=
Vcb->superblock.node_size;
3862 child_tree->
root->treeholder.tree = child_tree;
3883 ERR(
"out of memory\n");
3890 ERR(
"read_data returned 0x%08lx\n",
Status);
3909 while (le != &th->
tree->itemlist) {
3916 ERR(
"remove_root_extents returned %08lx\n",
Status);
3925 if (th->
tree && !th->
tree->updated_extents && th->
tree->has_address) {
3928 ERR(
"update_tree_extents returned %08lx\n",
Status);
3933 if (!th->
tree || th->
tree->has_address) {
3952 ERR(
"remove_root_extents returned %08lx\n",
Status);
3957 if (
Vcb->uuid_root) {
3970 ERR(
"delete_tree_item returned %08lx\n",
Status);
3978 if (
r->root_item.rtransid > 0) {
3994 ERR(
"delete_tree_item returned %08lx\n",
Status);
4003 if (
ids[
i] ==
r->id) {
4008 ERR(
"out of memory\n");
4020 ERR(
"delete_tree_item returned %08lx\n",
Status);
4028 ERR(
"insert_tree_item returned %08lx\n",
Status);
4047 searchkey.
offset = 0xffffffffffffffff;
4051 ERR(
"find_item returned %08lx\n",
Status);
4059 ERR(
"delete_tree_item returned %08lx\n",
Status);
4076 while (le != &
Vcb->drop_roots) {
4083 ERR(
"drop_root(%I64x) returned %08lx\n",
r->id,
Status);
4105 ERR(
"error - find_item returned %08lx\n",
Status);
4116 ERR(
"delete_tree_item returned %08lx\n",
Status);
4122 ERR(
"out of memory\n");
4130 ERR(
"insert_tree_item returned %08lx\n",
Status);
4144 le =
Vcb->sys_chunks.Flink;
4145 while (le != &
Vcb->sys_chunks) {
4165 ERR(
"error - bootstrap is full\n");
4171 ERR(
"out of memory\n");
4181 ERR(
"out of memory\n");
4188 le =
Vcb->sys_chunks.Flink;
4189 while (le != &
Vcb->sys_chunks) {
4215 ERR(
"out of memory\n");
4223 ERR(
"insert_tree_item failed\n");
4231 ERR(
"add_to_bootstrap returned %08lx\n",
Status);
4240 ERR(
"out of memory\n");
4244 bgi->
used =
c->used;
4246 bgi->
flags =
c->chunk_item->type;
4250 ERR(
"insert_tree_item failed\n");
4256 factor =
c->chunk_item->num_stripes;
4258 factor =
c->chunk_item->num_stripes /
c->chunk_item->sub_stripes;
4260 factor =
c->chunk_item->num_stripes - 1;
4262 factor =
c->chunk_item->num_stripes - 2;
4270 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
4275 ERR(
"out of memory\n");
4287 ERR(
"insert_tree_item returned %08lx\n",
Status);
4295 ERR(
"update_dev_item returned %08lx\n",
Status);
4301 c->oldused =
c->used;
4303 Vcb->superblock.bytes_used +=
c->used;
4312 le =
Vcb->sys_chunks.Flink;
4313 while (le != &
Vcb->sys_chunks) {
4319 Vcb->superblock.n -=
sizeof(
KEY) + sc2->
size;
4337 TRACE(
"(%p, %I64x, %I64x, %.*s, %08x, %p, %u)\n",
Vcb, subvol->
id,
inode,
namelen,
name,
crc32,
data,
datalen);
4343 ERR(
"out of memory\n");
4359 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
4373 TRACE(
"(%p, %I64x, %I64x, %.*s, %08x)\n",
Vcb, subvol->
id,
inode,
namelen,
name,
crc32);
4379 ERR(
"out of memory\n");
4394 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
4411 ERR(
"out of memory\n");
4430 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
4447 while (le != &bii->
items) {
4476 midpoint = midpoint->
Blink;
4485 ERR(
"out of memory\n");
4498 before_midpoint = midpoint->
Blink;
4514#pragma warning(push)
4515#pragma warning(suppress: 28194)
4524 le = batchlist->
Flink;
4525 while (le != batchlist) {
4539 ERR(
"out of memory\n");
4553 ERR(
"out of memory\n");
4565 bi = ExAllocateFromPagedLookasideList(&
Vcb->batch_item_lookaside);
4567 ERR(
"out of memory\n");
4589 while (le2 != &bii->
items) {
4633 bool changed =
false, truncating =
false;
4648 le2 = extent_ranges.
Flink;
4649 while (le2 != &extent_ranges) {
4664 ERR(
"out of memory\n");
4688 if (num_extents == 0 || (num_extents == 1 && !truncating))
4691 le = extent_ranges.
Flink;
4692 while (le != &extent_ranges) {
4701 ERR(
"get_chunk_from_address(%I64x) failed\n", er->
address);
4706 while (le2 != &extent_ranges) {
4722 le = extent_ranges.
Flink;
4723 while (le != &extent_ranges) {
4740 ERR(
"update_changed_extent_ref returned %08lx\n",
Status);
4766 ERR(
"load_cache_chunk returned %08lx\n",
Status);
4796 ERR(
"update_changed_extent_ref returned %08lx\n",
Status);
4820 ERR(
"load_cache_chunk returned %08lx\n",
Status);
4839 if (num_extents < 2)
4843 le = extent_ranges.
Flink;
4844 while (le != &extent_ranges) {
4882 le2 = extent_ranges.
Flink;
4883 while (le2 != &extent_ranges) {
4892 ERR(
"update_changed_extent_ref returned %08lx\n",
Status);
4899 ext->extent_data.decoded_size = ed2->
size;
4930#ifdef DEBUG_PARANOID
4932 bool extents_changed;
4939 ERR(
"delete_xattr returned %08lx\n",
Status);
4946 ERR(
"set_xattr returned %08lx\n",
Status);
4958 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
4966 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
4975#ifdef DEBUG_PARANOID
4981 bool prealloc =
false, extents_inline =
false;
5037 if (ed2->
size != 0 && ed2->
address == ned2->address && ed2->
size == ned2->size &&
5047 ERR(
"out of memory\n");
5060 ext->extent_data.generation =
fcb->
Vcb->superblock.generation;
5073 ERR(
"get_chunk_from_address(%I64x) failed\n", ed2->
address);
5078 ERR(
"update_changed_extent_ref returned %08lx\n",
Status);
5097 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
5111 ext->inserted =
false;
5116 ERR(
"insert_sparse_extent returned %08lx\n",
Status);
5123 ERR(
"out of memory\n");
5133 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
5141 extents_inline =
true;
5160 ERR(
"insert_sparse_extent returned %08lx\n",
Status);
5180 searchkey.
offset = 0xffffffffffffffff;
5184 ERR(
"error - find_item returned %08lx\n",
Status);
5192 ERR(
"out of memory\n");
5201 ERR(
"insert_tree_item returned %08lx\n",
Status);
5207 ERR(
"could not find INODE_ITEM for inode %I64x in subvol %I64x\n",
fcb->
inode,
fcb->
subvol->id);
5212#ifdef DEBUG_PARANOID
5224 ERR(
"delete_tree_item returned %08lx\n",
Status);
5230 searchkey.
offset = ii_offset;
5234 ERR(
"error - find_item returned %08lx\n",
Status);
5239 ERR(
"could not find INODE_ITEM for inode %I64x in subvol %I64x\n",
fcb->
inode,
fcb->
subvol->id);
5246#ifdef DEBUG_PARANOID
5248 ERR(
"error - size has changed but extents not marked as changed\n");
5260 ERR(
"out of memory\n");
5270 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
5282 ERR(
"set_xattr returned %08lx\n",
Status);
5288 ERR(
"delete_xattr returned %08lx\n",
Status);
5302 TRACE(
"inserting new DOSATTRIB xattr\n");
5305 atts &= ~FILE_ATTRIBUTE_READONLY;
5307 val2 = &
val[
sizeof(
val) - 1];
5311 *val2 =
c <= 9 ? (
c +
'0') : (
c - 0xa +
'a');
5315 }
while (
atts != 0);
5324 ERR(
"set_xattr returned %08lx\n",
Status);
5330 ERR(
"delete_xattr returned %08lx\n",
Status);
5344 ERR(
"set_xattr returned %08lx\n",
Status);
5350 ERR(
"delete_xattr returned %08lx\n",
Status);
5363 ERR(
"set_xattr returned %08lx\n",
Status);
5369 ERR(
"delete_xattr returned %08lx\n",
Status);
5381 ERR(
"delete_xattr returned %08lx\n",
Status);
5385 static const char zlib[] =
"zlib";
5390 ERR(
"set_xattr returned %08lx\n",
Status);
5394 static const char lzo[] =
"lzo";
5399 ERR(
"set_xattr returned %08lx\n",
Status);
5403 static const char zstd[] =
"zstd";
5408 ERR(
"set_xattr returned %08lx\n",
Status);
5430 ERR(
"delete_xattr returned %08lx\n",
Status);
5440 ERR(
"set_xattr returned %08lx\n",
Status);
5458 ERR(
"delete_xattr returned %08lx\n",
Status);
5467 ERR(
"set_xattr returned %08lx\n",
Status);
5478 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
5538 TRACE(
"dropping chunk %I64x\n",
c->offset);
5541 factor =
c->chunk_item->num_stripes;
5543 factor =
c->chunk_item->num_stripes /
c->chunk_item->sub_stripes;
5545 factor =
c->chunk_item->num_stripes - 1;
5547 factor =
c->chunk_item->num_stripes - 2;
5552 if (
Vcb->trim && !
Vcb->options.no_trim) {
5555 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
5556 if (
c->devices[
i] &&
c->devices[
i]->devobj && !
c->devices[
i]->readonly &&
c->devices[
i]->trim)
5565 WARN(
"load_stored_free_space_cache returned %08lx\n",
Status);
5570 c->cache->deleted =
true;
5574 ERR(
"excise_extents returned %08lx\n",
Status);
5582 if (
c->cache->refcount == 0)
5586 ERR(
"flush_fcb returned %08lx\n",
Status);
5596 ERR(
"error - find_item returned %08lx\n",
Status);
5603 ERR(
"delete_tree_item returned %08lx\n",
Status);
5609 if (
Vcb->space_root) {
5613 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
5618 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
5627 ERR(
"error - find_item returned %08lx\n",
Status);
5634 ERR(
"delete_tree_item returned %08lx\n",
Status);
5641 c->devices[
i]->devitem.bytes_used -= de->
length;
5643 if (
Vcb->balance.thread &&
Vcb->balance.shrinking &&
Vcb->balance.opts[0].devid ==
c->devices[
i]->devitem.dev_id) {
5644 if (cis[
i].offset < Vcb->balance.opts[0].drange_start && cis[
i].
offset + de->
length >
Vcb->balance.opts[0].drange_start)
5654 c->devices[
i]->devitem.bytes_used -=
len;
5656 if (
Vcb->balance.thread &&
Vcb->balance.shrinking &&
Vcb->balance.opts[0].devid ==
c->devices[
i]->devitem.dev_id) {
5657 if (cis[
i].offset < Vcb->balance.opts[0].drange_start && cis[
i].
offset +
len >
Vcb->balance.opts[0].drange_start)
5665 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
5666 if (
c->devices[
i]) {
5672 searchkey.
offset =
c->devices[
i]->devitem.dev_id;
5676 ERR(
"error - find_item returned %08lx\n",
Status);
5683 ERR(
"delete_tree_item returned %08lx\n",
Status);
5689 ERR(
"out of memory\n");
5697 ERR(
"insert_tree_item returned %08lx\n",
Status);
5702 for (
j =
i + 1;
j <
c->chunk_item->num_stripes;
j++) {
5703 if (
c->devices[
j] ==
c->devices[
i])
5711 searchkey.
obj_id = 0x100;
5717 ERR(
"error - find_item returned %08lx\n",
Status);
5725 ERR(
"delete_tree_item returned %08lx\n",
Status);
5729 WARN(
"could not find CHUNK_ITEM for chunk %I64x\n",
c->offset);
5734 searchkey.
offset = 0xffffffffffffffff;
5738 ERR(
"error - find_item returned %08lx\n",
Status);
5746 ERR(
"delete_tree_item returned %08lx\n",
Status);
5750 WARN(
"could not find BLOCK_GROUP_ITEM for chunk %I64x\n",
c->offset);
5762 bool clear_flag =
true;
5764 le =
Vcb->chunks.Flink;
5765 while (le != &
Vcb->chunks) {
5777 Vcb->superblock.incompat_flags &= ~BTRFS_INCOMPAT_FLAGS_RAID56;
5784 bool clear_flag =
true;
5786 le =
Vcb->chunks.Flink;
5787 while (le != &
Vcb->chunks) {
5799 Vcb->superblock.incompat_flags &= ~BTRFS_INCOMPAT_FLAGS_RAID1C34;
5802 Vcb->superblock.bytes_used -=
c->oldused;
5835 ULONG sl = (
ULONG)(
c->chunk_item->stripe_length >>
Vcb->sector_shift);
5842 stripe = (parity + (
offset / sl) + 1) %
c->chunk_item->num_stripes;
5844 if (
c->devices[
stripe]->devobj) {
5846 readlen <<
Vcb->sector_shift, ps->
data + (
offset <<
Vcb->sector_shift),
false);
5848 ERR(
"sync_read_phys returned %08lx\n",
Status);
5857 ERR(
"out of memory\n");
5861 for (
i = 0;
i <
c->chunk_item->num_stripes;
i++) {
5863 if (!
c->devices[
i]->devobj) {
5868 if (
i == 0 || (
stripe == 0 &&
i == 1)) {
5870 readlen <<
Vcb->sector_shift, ps->
data + (
offset <<
Vcb->sector_shift),
false);
5872 ERR(
"sync_read_phys returned %08lx\n",
Status);
5878 readlen <<
Vcb->sector_shift, scratch,
false);
5880 ERR(
"sync_read_phys returned %08lx\n",
Status);
5897 ERR(
"out of memory\n");
5901 i = (parity + 1) %
c->chunk_item->num_stripes;
5902 logstripe = (
c->chunk_item->num_stripes +
c->chunk_item->num_stripes - 1 - parity +
stripe) %
c->chunk_item->num_stripes;
5904 for (
k = 0;
k <
c->chunk_item->num_stripes;
k++) {
5906 if (
c->devices[
i]->devobj) {
5908 readlen <<
Vcb->sector_shift, scratch + (
k * readlen <<
Vcb->sector_shift),
false);
5910 ERR(
"sync_read_phys returned %08lx\n",
Status);
5925 i = (
i + 1) %
c->chunk_item->num_stripes;
5928 if (
num_errors == 0 || error_stripe ==
c->chunk_item->num_stripes - 1) {
5929 for (
k = 0;
k <
c->chunk_item->num_stripes - 1;
k++) {
5930 if (
k != logstripe) {
5931 if (
k == 0 || (
k == 1 && logstripe == 0)) {
5933 readlen <<
Vcb->sector_shift);
5936 readlen <<
Vcb->sector_shift);
5941 raid6_recover2(scratch,
c->chunk_item->num_stripes, readlen <<
Vcb->sector_shift, logstripe,
5942 error_stripe, scratch + (
c->chunk_item->num_stripes * readlen <<
Vcb->sector_shift));
5945 readlen <<
Vcb->sector_shift);
5967 uint64_t ps_length = num_data_stripes *
c->chunk_item->stripe_length;
5968 ULONG stripe_length = (
ULONG)
c->chunk_item->stripe_length;
5974 parity2 = (((ps->
address -
c->offset) / ps_length) +
c->chunk_item->num_stripes - 1) %
c->chunk_item->num_stripes;
5981 while (runlength != 0) {
5992 if (
index > last1) {
5995 ERR(
"partial_stripe_read returned %08lx\n",
Status);
6000 last1 =
index + runlength;
6005 if (last1 < ps_length >>
Vcb->sector_shift) {
6008 ERR(
"partial_stripe_read returned %08lx\n",
Status);
6015 while (le != &
c->space) {
6018 if (
s->address +
s->size > ps->
address &&
s->address < ps->
address + ps_length) {
6023 }
else if (
s->address >= ps->
address + ps_length)
6030 while (le != &
c->deleting) {
6033 if (
s->address +
s->size > ps->
address &&
s->address < ps->
address + ps_length) {
6038 }
else if (
s->address >= ps->
address + ps_length)
6044 stripe = (parity2 + 1) %
c->chunk_item->num_stripes;
6047 for (
k = 0;
k < num_data_stripes;
k++) {
6048 if (
c->devices[
stripe]->devobj) {
6051 ERR(
"write_data_phys returned %08lx\n",
Status);
6056 data += stripe_length;
6062 if (
c->devices[parity2]->devobj) {
6065 for (
i = 1;
i <
c->chunk_item->num_stripes - 1;
i++) {
6071 ERR(
"write_data_phys returned %08lx\n",
Status);
6076 uint16_t parity1 = (parity2 +
c->chunk_item->num_stripes - 1) %
c->chunk_item->num_stripes;
6078 if (
c->devices[parity1]->devobj ||
c->devices[parity2]->devobj) {
6084 ERR(
"out of memory\n");
6088 i =
c->chunk_item->num_stripes - 3;
6091 if (
i ==
c->chunk_item->num_stripes - 3) {
6093 RtlCopyMemory(scratch + stripe_length, ps->
data + (
i * stripe_length), stripe_length);
6095 do_xor(scratch, ps->
data + (
i * stripe_length), stripe_length);
6098 do_xor(scratch + stripe_length, ps->
data + (
i * stripe_length), stripe_length);
6107 if (
c->devices[parity1]->devobj) {
6108 Status =
write_data_phys(
c->devices[parity1]->devobj,
c->devices[parity1]->fileobj, cis[parity1].
offset + startoff, scratch, stripe_length);
6110 ERR(
"write_data_phys returned %08lx\n",
Status);
6116 if (
c->devices[parity2]->devobj) {
6118 scratch + stripe_length, stripe_length);
6120 ERR(
"write_data_phys returned %08lx\n",
Status);
6142 le =
Vcb->chunks.Flink;
6143 while (le != &
Vcb->chunks) {
6166 ERR(
"flush_partial_stripe returned %08lx\n",
Status);
6177 if (
c->list_entry_balance.Flink) {
6183 if (
c->space_changed ||
c->created) {
6184 bool created =
c->created;
6186 used_minus_cache =
c->used;
6189 if (used_minus_cache > 0 &&
c->chunk_item->type &
BLOCK_FLAG_DATA &&
c->cache &&
c->cache->inode_item.st_size ==
c->used) {
6192 le3 =
c->cache->extents.
Flink;
6193 while (le3 != &
c->cache->extents) {
6202 used_minus_cache -= ed2->
size;
6210 if (used_minus_cache == 0) {
6213 ERR(
"drop_chunk returned %08lx\n",
Status);
6222 }
else if (
c->created) {
6225 ERR(
"create_chunk returned %08lx\n",
Status);
6232 if (used_minus_cache > 0 || created)
6251 searchkey.
obj_id = parsubvolid;
6253 searchkey.
offset = subvolid;
6257 ERR(
"error - find_item returned %08lx\n",
Status);
6287 ERR(
"delete_tree_item returned %08lx\n",
Status);
6297 ERR(
"out of memory\n");
6315 ERR(
"insert_tree_item returned %08lx\n",
Status);
6324 if (
len > itemlen) {
6332 WARN(
"could not find ROOT_REF entry for subvol %I64x in %I64x\n", searchkey.offset, searchkey.obj_id);
6340#pragma warning(push)
6341#pragma warning(suppress: 28194)
6348 searchkey.
obj_id = parsubvolid;
6350 searchkey.
offset = subvolid;
6354 ERR(
"error - find_item returned %08lx\n",
Status);
6364 ERR(
"out of memory\n");
6376 ERR(
"delete_tree_item returned %08lx\n",
Status);
6383 ERR(
"insert_tree_item returned %08lx\n",
Status);
6390 ERR(
"insert_tree_item returned %08lx\n",
Status);
6409 searchkey.
obj_id = parsubvolid;
6411 searchkey.
offset = subvolid;
6415 ERR(
"error - find_item returned %08lx\n",
Status);
6424 ERR(
"out of memory\n");
6434 searchkey.
obj_id = subvolid;
6436 searchkey.
offset = parsubvolid;
6440 ERR(
"error - find_item returned %08lx\n",
Status);
6451 ERR(
"delete_tree_item returned %08lx\n",
Status);
6463 ERR(
"insert_tree_item returned %08lx\n",
Status);
6479 searchkey.
offset = 0xffffffffffffffff;
6483 ERR(
"error - find_item returned %08lx\n",
Status);
6488 ERR(
"could not find ROOT_ITEM for tree %I64x\n", searchkey.
obj_id);
6495 ERR(
"out of memory\n");
6506 ERR(
"delete_tree_item returned %08lx\n",
Status);
6513 ERR(
"insert_tree_item returned %08lx\n",
Status);
6529 fileref->
dirty =
false;
6534 fileref->
dirty =
false;
6548 ERR(
"out of memory\n");
6570 ERR(
"out of memory\n");
6579 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
6586 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
6595 ERR(
"out of memory\n");
6606 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
6609 }
else if (fileref->
fcb != fileref->
fcb->
Vcb->dummy_fcb) {
6617 ERR(
"out of memory\n");
6628 ERR(
"add_root_ref returned %08lx\n",
Status);
6634 ERR(
"update_root_backref returned %08lx\n",
Status);
6640 }
else if (fileref->
deleted) {
6651 ERR(
"out of memory\n");
6656 di->
n =
name->Length;
6664 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
6675 ERR(
"out of memory\n");
6680 ir->
n =
name->Length;
6686 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
6689 }
else if (fileref->
fcb != fileref->
fcb->
Vcb->dummy_fcb) {
6692 ERR(
"delete_root_ref returned %08lx\n",
Status);
6698 ERR(
"update_root_backref returned %08lx\n",
Status);
6708 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
6731 ERR(
"out of memory\n");
6744 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
6754 ERR(
"out of memory\n");
6760 ERR(
"out of memory\n");
6788 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
6801 ERR(
"out of memory\n");
6813 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
6823 ERR(
"out of memory\n");
6835 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
6840 }
else if (fileref->
fcb != fileref->
fcb->
Vcb->dummy_fcb) {
6846 ERR(
"delete_root_ref returned %08lx\n",
Status);
6855 ERR(
"out of memory\n");
6867 ERR(
"add_root_ref returned %08lx\n",
Status);
6874 ERR(
"update_root_backref returned %08lx\n",
Status);
6885 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
6895 ERR(
"insert_tree_item_batch returned %08lx\n",
Status);
6906 fileref->
dirty =
false;
6918 le =
Vcb->devices.Flink;
6920 while (le != &
Vcb->devices) {
6923 if (
dev->devobj && !
dev->readonly &&
dev->can_flush)
6938 ERR(
"out of memory\n");
6944 le =
Vcb->devices.Flink;
6946 while (le != &
Vcb->devices) {
6949 if (
dev->devobj && !
dev->readonly &&
dev->can_flush) {
6956 stripe->apte.TimeOutValue = 5;
6962 ERR(
"IoAllocateIrp failed\n");
6974 stripe->Irp->AssociatedIrp.SystemBuffer = &
stripe->apte;
6992 for (
unsigned int i = 0;
i <
num;
i++) {
7013 ERR(
"find_item returned %08lx\n",
Status);
7020 ERR(
"delete_tree_item returned %08lx\n",
Status);
7028 ERR(
"out of memory\n");
7036 ERR(
"insert_tree_item returned %08lx\n",
Status);
7047 if (
r !=
Vcb->root_root &&
r !=
Vcb->chunk_root) {
7054 searchkey.
offset = 0xffffffffffffffff;
7058 ERR(
"error - find_item returned %08lx\n",
Status);
7063 ERR(
"could not find ROOT_ITEM for tree %I64x\n", searchkey.
obj_id);
7069 ERR(
"out of memory\n");
7077 ERR(
"delete_tree_item returned %08lx\n",
Status);
7083 ERR(
"insert_tree_item returned %08lx\n",
Status);
7092 if (!
Vcb->uuid_root) {
7095 TRACE(
"uuid root doesn't exist, creating it\n");
7100 ERR(
"create_root returned %08lx\n",
Status);
7104 Vcb->uuid_root = uuid_root;
7113 ERR(
"find_item returned %08lx\n",
Status);
7123 ERR(
"out of memory\n");
7132 ERR(
"delete_tree_item returned %08lx\n",
Status);
7139 ERR(
"insert_tree_item returned %08lx\n",
Status);
7149 ERR(
"out of memory\n");
7157 ERR(
"insert_tree_item returned %08lx\n",
Status);
7163 r->received =
false;
7180 reserve =
Vcb->extent_root->root_item.bytes_used;
7181 reserve +=
Vcb->root_root->root_item.bytes_used;
7182 if (
Vcb->checksum_root)
reserve +=
Vcb->checksum_root->root_item.bytes_used;
7194 le =
Vcb->devices.Flink;
7195 while (le != &
Vcb->devices) {
7198 if (!
dev->readonly) {
7208 }
else if (
space >= s3)
7215 could_alloc = s3 * 2;
7219 le =
Vcb->devices.Flink;
7220 while (le != &
Vcb->devices) {
7223 if (!
dev->readonly) {
7235 }
else if (
space >= s3) {
7238 }
else if (
space >= s4)
7245 could_alloc = s4 * 2;
7249 le =
Vcb->devices.Flink;
7250 while (le != &
Vcb->devices) {
7253 if (!
dev->readonly) {
7269 could_alloc =
s2 * 2;
7271 le =
Vcb->devices.Flink;
7272 while (le != &
Vcb->devices) {
7275 if (!
dev->readonly) {
7278 could_alloc =
max(could_alloc,
space);
7286 le =
Vcb->devices.Flink;
7287 while (le != &
Vcb->devices) {
7290 if (!
dev->readonly) {
7300 }
else if (
space >= s3)
7311 le =
Vcb->devices.Flink;
7312 while (le != &
Vcb->devices) {
7315 if (!
dev->readonly) {
7327 }
else if (
space >= s3) {
7330 }
else if (
space >= s4)
7339 le =
Vcb->devices.Flink;
7340 while (le != &
Vcb->devices) {
7343 if (!
dev->readonly) {
7346 could_alloc =
max(could_alloc,
space);
7358 le =
Vcb->chunks.Flink;
7359 while (le != &
Vcb->chunks) {
7363 free_space +=
c->chunk_item->size -
c->used;
7365 if (free_space + could_alloc >=
reserve)
7391 ERR(
"find_item returned %08lx\n",
Status);
7408 ERR(
"open_fcb returned %08lx\n",
Status);
7414 ERR(
"excise_extents returned %08lx\n",
Status);
7428 ERR(
"delete_tree_item returned %08lx\n",
Status);
7457 le =
Vcb->dirty_filerefs.Flink;
7458 while (le != &
Vcb->dirty_filerefs) {
7461 if (!fr->
fcb->
subvol->checked_for_orphans) {
7464 ERR(
"check_for_orphans_root returned %08lx\n",
Status);
7468 fr->
fcb->
subvol->checked_for_orphans =
true;
7480 bool cache_changed =
false;
7482 bool no_cache =
false;
7483#ifdef DEBUG_FLUSH_TIMES
7487#ifdef DEBUG_WRITE_LOOPS
7495#ifdef DEBUG_FLUSH_TIMES
7501 ERR(
"check_for_orphans returned %08lx\n",
Status);
7513#ifdef DEBUG_FLUSH_TIMES
7522 ERR(
"commit_batch_list returned %08lx\n",
Status);
7526#ifdef DEBUG_FLUSH_TIMES
7541 le =
Vcb->dirty_fcbs.Flink;
7542 while (le != &
Vcb->dirty_fcbs) {
7554 ERR(
"flush_fcb returned %08lx\n",
Status);
7560#ifdef DEBUG_FLUSH_TIMES
7570 ERR(
"commit_batch_list returned %08lx\n",
Status);
7575 le =
Vcb->dirty_fcbs.Flink;
7576 while (le != &
Vcb->dirty_fcbs) {
7587 ERR(
"flush_fcb returned %08lx\n",
Status);
7592#ifdef DEBUG_FLUSH_TIMES
7604 ERR(
"commit_batch_list returned %08lx\n",
Status);
7608#ifdef DEBUG_FLUSH_TIMES
7620 ERR(
"flush_subvol returned %08lx\n",
Status);
7629 ERR(
"drop_roots returned %08lx\n",
Status);
7637 ERR(
"update_chunks returned %08lx\n",
Status);
7645 if (!
Vcb->root_root->treeholder.tree || !
Vcb->root_root->treeholder.tree->write) {
7656 ERR(
"error - find_item returned %08lx\n",
Status);
7660 Vcb->root_root->treeholder.tree->write =
true;
7666 ERR(
"add_root_item_to_cache returned %08lx\n",
Status);
7670 if (
Vcb->stats_changed) {
7671 le =
Vcb->devices.Flink;
7672 while (le != &
Vcb->devices) {
7675 if (
dev->stats_changed) {
7678 ERR(
"flush_changed_dev_stats returned %08lx\n",
Status);
7681 dev->stats_changed =
false;
7687 Vcb->stats_changed =
false;
7693 ERR(
"add_parents returned %08lx\n",
Status);
7699 ERR(
"allocate_tree_extents returned %08lx\n",
Status);
7705 ERR(
"do_splits returned %08lx\n",
Status);
7711 ERR(
"update_chunk_usage returned %08lx\n",
Status);
7719 WARN(
"allocate_cache returned %08lx\n",
Status);
7721 cache_changed =
false;
7727 ERR(
"update_chunk_caches_tree returned %08lx\n",
Status);
7732#ifdef DEBUG_WRITE_LOOPS
7736 ERR(
"cache has changed, looping again\n");
7740#ifdef DEBUG_WRITE_LOOPS
7741 ERR(
"%u loops\n", loops);
7744 TRACE(
"trees consistent\n");
7748 ERR(
"update_root_root returned %08lx\n",
Status);
7754 ERR(
"write_trees returned %08lx\n",
Status);
7760 ERR(
"test_not_full returned %08lx\n",
Status);
7764#ifdef DEBUG_PARANOID
7765 le =
Vcb->trees.Flink;
7766 while (le != &
Vcb->trees) {
7771 searchkey.
obj_id =
t->header.address;
7773 searchkey.
offset = 0xffffffffffffffff;
7777 ERR(
"error - find_item returned %08lx\n",
Status);
7782 searchkey.
obj_id =
t->header.address;
7784 searchkey.
offset = 0xffffffffffffffff;
7788 ERR(
"error - find_item returned %08lx\n",
Status);
7793 ERR(
"error - could not find entry in extent tree for tree at %I64x\n",
t->header.address);
7803 Vcb->superblock.cache_generation =
Vcb->superblock.generation;
7805 if (!
Vcb->options.no_barrier)
7810 ERR(
"write_superblocks returned %08lx\n",
Status);
7835 le =
Vcb->chunks.Flink;
7836 while (le != &
Vcb->chunks) {
7840 c->space_changed =
false;
7845 Vcb->superblock.generation++;
7849 le =
Vcb->trees.Flink;
7850 while (le != &
Vcb->trees) {
7858 Vcb->need_write =
false;
7886 ERR(
"do_write2 returned %08lx, dropping into readonly mode\n",
Status);
7887 Vcb->readonly =
true;
7901 if (
Vcb->need_write && !
Vcb->readonly)
7909 ERR(
"do_write returned %08lx\n",
Status);
unsigned short int uint16_t
static void startaddr(void)
#define InterlockedDecrement
void blake2b(void *out, size_t outlen, const void *in, size_t inlen)
NTSTATUS load_stored_free_space_cache(device_extension *Vcb, chunk *c, bool load_only, PIRP Irp)
#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
#define EA_CASE_SENSITIVE
_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)
uint64_t get_extent_refcount(device_extension *Vcb, uint64_t address, uint64_t size, PIRP Irp)
uint64_t find_extent_shared_tree_refcount(device_extension *Vcb, uint64_t address, uint64_t parent, PIRP Irp)
#define keycmp(key1, key2)
void void free_trees_root(device_extension *Vcb, root *r) __attribute__((nonnull(1
void galois_double(uint8_t *data, uint32_t len)
NTSTATUS load_cache_chunk(device_extension *Vcb, chunk *c, PIRP Irp)
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 raid6_recover2(uint8_t *sectors, uint16_t num_stripes, ULONG sector_size, uint16_t missing1, uint16_t missing2, uint8_t *out)
void space_list_add2(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c, LIST_ENTRY *rollback)
uint64_t get_extent_flags(device_extension *Vcb, uint64_t address, PIRP Irp)
void void void NTSTATUS commit_batch_list(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *batchlist, PIRP Irp) __attribute__((nonnull(1
#define EA_PROP_COMPRESSION_HASH
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool prealloc
NTSTATUS increase_extent_refcount_data(device_extension *Vcb, uint64_t address, uint64_t size, uint64_t root, uint64_t inode, uint64_t offset, uint32_t refcount, PIRP Irp)
NTSTATUS NTSTATUS NTSTATUS void free_write_data_stripes(write_data_context *wtc) __attribute__((nonnull(1)))
NTSTATUS NTSTATUS void free_tree(tree *t) __attribute__((nonnull(1)))
#define EA_DOSATTRIB_HASH
uint32_t find_extent_shared_data_refcount(device_extension *Vcb, uint64_t address, uint64_t parent, PIRP Irp)
NTSTATUS update_chunk_caches(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
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)
NTSTATUS decrease_extent_refcount_tree(device_extension *Vcb, uint64_t address, uint64_t size, uint64_t root, uint8_t level, PIRP Irp)
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address) __attribute__((nonnull(1)))
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback) __attribute__((nonnull(1
NTSTATUS load_tree(device_extension *Vcb, uint64_t addr, uint8_t *buf, root *r, tree **pt) __attribute__((nonnull(1
_In_ uint16_t _Out_ ULONG * atts
void void void NTSTATUS void clear_batch_list(device_extension *Vcb, LIST_ENTRY *batchlist) __attribute__((nonnull(1
NTSTATUS increase_extent_refcount(device_extension *Vcb, uint64_t address, uint64_t size, uint8_t type, void *data, KEY *firstitem, uint8_t level, PIRP Irp)
#define EA_PROP_COMPRESSION
NTSTATUS update_chunk_caches_tree(device_extension *Vcb, PIRP Irp)
NTSTATUS NTSTATUS do_load_tree(device_extension *Vcb, tree_holder *th, root *r, tree *t, tree_data *td, PIRP Irp) __attribute__((nonnull(1
void space_list_add(chunk *c, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, root *subvol, uint64_t inode, uint8_t type, PANSI_STRING utf8, bool always_add_hl, fcb *parent, fcb **pfcb, POOL_TYPE pooltype, PIRP Irp)
void calc_sha256(uint8_t *hash, const void *input, size_t len)
NTSTATUS NTSTATUS bool bool void free_trees(device_extension *Vcb) __attribute__((nonnull(1)))
void update_extent_flags(device_extension *Vcb, uint64_t address, uint64_t flags, PIRP Irp)
#define EA_CASE_SENSITIVE_HASH
NTSTATUS decrease_extent_refcount(device_extension *Vcb, uint64_t address, uint64_t size, uint8_t type, void *data, KEY *firstitem, uint8_t level, uint64_t parent, bool superseded, PIRP Irp)
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp) __attribute__((nonnull(1
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)
void space_list_merge(LIST_ENTRY *spacelist, LIST_ENTRY *spacelist_size, LIST_ENTRY *deleting)
NTSTATUS allocate_cache(device_extension *Vcb, bool *changed, PIRP Irp, LIST_ENTRY *rollback)
NTSTATUS NTSTATUS bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp) __attribute__((nonnull(1
#define release_chunk_lock(c, Vcb)
NTSTATUS NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp) __attribute__((nonnull(1
void space_list_subtract(chunk *c, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
NTSTATUS decrease_extent_refcount_data(device_extension *Vcb, uint64_t address, uint64_t size, uint64_t root, uint64_t inode, uint64_t offset, uint32_t refcount, bool superseded, PIRP Irp)
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
#define RtlInitializeBitMap
#define RtlFindNextForwardRunClear
#define RtlFindFirstRunClear
#define NT_SUCCESS(StatCode)
static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
static const WCHAR empty[]
#define crc32(crc, buf, len)
static const WCHAR *const ext[]
static LONG find_item(PropertyBag *This, LPCOLESTR name)
void mark_fcb_dirty(_In_ fcb *fcb)
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
void log_device_error(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ int error)
void free_fileref(_Inout_ file_ref *fr)
NTSTATUS create_root(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ uint64_t id, _Out_ root **rootptr, _In_ bool no_tree, _In_ uint64_t offset, _In_opt_ PIRP Irp)
void free_fcb(_Inout_ fcb *fcb)
NTSTATUS sync_read_phys(_In_ PDEVICE_OBJECT DeviceObject, _In_ PFILE_OBJECT FileObject, _In_ uint64_t StartingOffset, _In_ ULONG Length, _Out_writes_bytes_(Length) PUCHAR Buffer, _In_ bool override)
#define FREE_SPACE_CACHE_ID
#define BTRFS_NUM_BACKUP_ROOTS
#define BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA
#define TYPE_EXTENT_DATA_REF
#define EXTENT_TYPE_PREALLOC
#define BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE
static const uint64_t superblock_addrs[]
#define HEADER_FLAG_WRITTEN
#define BTRFS_ROOT_FREE_SPACE
#define HEADER_FLAG_SHARED_BACKREF
#define BTRFS_ENCODING_NONE
#define TYPE_SHARED_BLOCK_REF
#define TYPE_ORPHAN_INODE
#define TYPE_SUBVOL_REC_UUID
#define EXTENT_TYPE_INLINE
#define BLOCK_FLAG_RAID1C4
#define EXTENT_ITEM_TREE_BLOCK
#define TYPE_SHARED_DATA_REF
#define HEADER_FLAG_MIXED_BACKREF
#define BTRFS_DEV_STAT_WRITE_ERRORS
#define TYPE_BLOCK_GROUP_ITEM
#define TYPE_ROOT_BACKREF
#define TYPE_TREE_BLOCK_REF
#define EXTENT_TYPE_REGULAR
#define BTRFS_COMPRESSION_NONE
#define EXTENT_ITEM_SHARED_BACKREFS
#define BTRFS_ROOT_DEVTREE
#define BLOCK_FLAG_RAID1C3
#define SYS_CHUNK_ARRAY_SIZE
#define BTRFS_ROOT_FSTREE
#define BTRFS_ROOT_EXTENT
#define BTRFS_ROOT_CHECKSUM
#define BTRFS_ENCRYPTION_NONE
#define TYPE_FREE_SPACE_INFO
#define TYPE_METADATA_ITEM
#define BTRFS_INCOMPAT_FLAGS_NO_HOLES
#define BTRFS_ORPHAN_INODE_OBJID
_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 KeWaitForSingleObject(pEvt, foo, a, b, c)
#define RtlCompareMemory(s1, s2, l)
#define KeInitializeEvent(pEvt, foo, foo2)
#define KeSetEvent(pEvt, foo, foo2)
#define ExAcquireResourceExclusiveLite(res, wait)
#define ExDeleteResourceLite(res)
#define RemoveHeadList(ListHead)
#define InitializeListHead(ListHead)
#define ExAcquireResourceSharedLite(res, wait)
static NTSTATUS split_tree_at(device_extension *Vcb, tree *t, tree_data *newfirstitem, uint32_t numitems, uint32_t size)
static NTSTATUS flush_changed_dev_stats(device_extension *Vcb, device *dev, PIRP Irp)
static NTSTATUS update_tree_extents_recursive(device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
static NTSTATUS reduce_tree_extent(device_extension *Vcb, uint64_t address, tree *t, uint64_t parent_root, uint8_t level, PIRP Irp, LIST_ENTRY *rollback)
static void get_first_item(tree *t, KEY *key)
static bool insert_tree_extent(device_extension *Vcb, uint8_t level, uint64_t root_id, chunk *c, uint64_t *new_address, PIRP Irp, LIST_ENTRY *rollback)
static NTSTATUS insert_sparse_extent(fcb *fcb, LIST_ENTRY *batchlist, uint64_t start, uint64_t length)
static void remove_from_bootstrap(device_extension *Vcb, uint64_t obj_id, uint8_t obj_type, uint64_t offset)
NTSTATUS flush_fcb(fcb *fcb, bool cache, LIST_ENTRY *batchlist, PIRP Irp)
void add_trim_entry_avoid_sb(device_extension *Vcb, device *dev, uint64_t address, uint64_t size)
static NTSTATUS drop_root(device_extension *Vcb, root *r, PIRP Irp, LIST_ENTRY *rollback)
static NTSTATUS flush_fileref(file_ref *fileref, LIST_ENTRY *batchlist, PIRP Irp)
static NTSTATUS update_extent_level(device_extension *Vcb, uint64_t address, tree *t, uint8_t level, PIRP Irp)
static NTSTATUS split_batch_item_list(batch_item_ind *bii)
static NTSTATUS write_trees(device_extension *Vcb, PIRP Irp)
static bool shared_tree_is_unique(device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
static void add_trim_entry(device *dev, uint64_t address, uint64_t size)
static NTSTATUS flush_subvol(device_extension *Vcb, root *r, PIRP Irp)
static void calc_superblock_checksum(superblock *sb)
static bool trees_consistent(device_extension *Vcb)
static void rationalize_extents(fcb *fcb, PIRP Irp)
static void update_backup_superblock(device_extension *Vcb, superblock_backup *sb, PIRP Irp)
static NTSTATUS delete_root_ref(device_extension *Vcb, uint64_t subvolid, uint64_t parsubvolid, uint64_t parinode, PANSI_STRING utf8, PIRP Irp)
static NTSTATUS update_chunks(device_extension *Vcb, LIST_ENTRY *batchlist, PIRP Irp, LIST_ENTRY *rollback)
static NTSTATUS write_superblocks(device_extension *Vcb, PIRP Irp)
NTSTATUS update_dev_item(device_extension *Vcb, device *device, PIRP Irp)
static NTSTATUS create_chunk(device_extension *Vcb, chunk *c, PIRP Irp)
static NTSTATUS drop_roots(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
static NTSTATUS test_not_full(device_extension *Vcb)
static NTSTATUS split_tree(device_extension *Vcb, tree *t)
static NTSTATUS allocate_tree_extents(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
static NTSTATUS add_changed_extent_ref_sdr(changed_extent *ce, SHARED_DATA_REF *sdr, bool old)
static void do_flush(device_extension *Vcb)
static NTSTATUS update_tree_extents(device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
static NTSTATUS check_for_orphans_root(device_extension *Vcb, root *r, PIRP Irp)
static NTSTATUS do_write2(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
static NTSTATUS add_root_ref(_In_ device_extension *Vcb, _In_ uint64_t subvolid, _In_ uint64_t parsubvolid, _In_ __drv_aliasesMem ROOT_REF *rr, _In_opt_ PIRP Irp)
NTSTATUS flush_partial_stripe(device_extension *Vcb, chunk *c, partial_stripe *ps)
static NTSTATUS drop_chunk(device_extension *Vcb, chunk *c, LIST_ENTRY *batchlist, PIRP Irp, LIST_ENTRY *rollback)
static void add_parents_to_cache(tree *t)
static NTSTATUS check_for_orphans(device_extension *Vcb, PIRP Irp)
static NTSTATUS add_changed_extent_ref_edr(changed_extent *ce, EXTENT_DATA_REF *edr, bool old)
struct _write_superblocks_context write_superblocks_context
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
static NTSTATUS update_chunk_usage(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
static NTSTATUS insert_tree_item_batch(LIST_ENTRY *batchlist, device_extension *Vcb, root *r, uint64_t objid, uint8_t objtype, uint64_t offset, _In_opt_ _When_(return >=0, __drv_aliasesMem) void *data, uint16_t datalen, enum batch_operation operation)
static NTSTATUS add_root_item_to_cache(device_extension *Vcb, uint64_t root, PIRP Irp)
static NTSTATUS remove_root_extents(device_extension *Vcb, root *r, tree_holder *th, uint8_t level, tree *parent, PIRP Irp, LIST_ENTRY *rollback)
NTSTATUS write_data_phys(_In_ PDEVICE_OBJECT device, _In_ PFILE_OBJECT fileobj, _In_ uint64_t address, _In_reads_bytes_(length) void *data, _In_ uint32_t length)
static NTSTATUS do_splits(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
static NTSTATUS add_to_bootstrap(device_extension *Vcb, uint64_t obj_id, uint8_t obj_type, uint64_t offset, void *data, uint16_t size)
static NTSTATUS set_xattr(device_extension *Vcb, LIST_ENTRY *batchlist, root *subvol, uint64_t inode, char *name, uint16_t namelen, uint32_t crc32, uint8_t *data, uint16_t datalen)
static NTSTATUS write_superblock(device_extension *Vcb, device *device, write_superblocks_context *context)
static NTSTATUS delete_xattr(device_extension *Vcb, LIST_ENTRY *batchlist, root *subvol, uint64_t inode, char *name, uint16_t namelen, uint32_t crc32)
static void regen_bootstrap(device_extension *Vcb)
void calc_tree_checksum(device_extension *Vcb, tree_header *th)
static NTSTATUS update_root_backref(device_extension *Vcb, uint64_t subvolid, uint64_t parsubvolid, PIRP Irp)
static void flush_disk_caches(device_extension *Vcb)
NTSTATUS do_tree_writes(device_extension *Vcb, LIST_ENTRY *tree_writes, bool no_free)
static NTSTATUS try_tree_amalgamate(device_extension *Vcb, tree *t, bool *done, bool *done_deletions, PIRP Irp, LIST_ENTRY *rollback)
static NTSTATUS update_root_root(device_extension *Vcb, bool no_cache, PIRP Irp, LIST_ENTRY *rollback)
NTSTATUS get_tree_new_address(device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
static void clean_space_cache_chunk(device_extension *Vcb, chunk *c)
bool find_metadata_address_in_chunk(device_extension *Vcb, chunk *c, uint64_t *address)
static bool insert_tree_extent_skinny(device_extension *Vcb, uint8_t level, uint64_t root_id, chunk *c, uint64_t address, PIRP Irp, LIST_ENTRY *rollback)
static NTSTATUS flush_changed_extent(device_extension *Vcb, chunk *c, changed_extent *ce, PIRP Irp, LIST_ENTRY *rollback)
static NTSTATUS partial_stripe_read(device_extension *Vcb, chunk *c, partial_stripe *ps, uint64_t startoff, uint16_t parity, ULONG offset, ULONG len)
static void clean_space_cache(device_extension *Vcb)
bool is_tree_unique(device_extension *Vcb, tree *t, PIRP Irp)
void add_checksum_entry(device_extension *Vcb, uint64_t address, ULONG length, void *csum, PIRP Irp)
static NTSTATUS add_parents(device_extension *Vcb, PIRP Irp)
#define FSRTL_VOLUME_FORCED_CLOSED
GLuint GLuint GLsizei count
GLuint GLuint GLsizei GLenum type
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLdouble GLdouble GLdouble r
GLboolean GLboolean GLboolean b
GLenum GLuint GLenum GLsizei const GLchar * buf
GLuint GLsizei GLsizei * length
GLenum const GLvoid * addr
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
LARGE_INTEGER NTAPI KeQueryPerformanceCounter(IN PLARGE_INTEGER PerformanceFreq)
NTSYSAPI ULONG WINAPI RtlLengthSecurityDescriptor(PSECURITY_DESCRIPTOR)
#define EXCEPTION_EXECUTE_HANDLER
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
int const JOCTET unsigned int datalen
int const JOCTET * dataptr
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)
#define cmp(status, error)
#define _In_reads_bytes_(s)
#define _Function_class_(n)
struct _DEVICE_MANAGE_DATA_SET_ATTRIBUTES DEVICE_MANAGE_DATA_SET_ATTRIBUTES
#define DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED
#define IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES
#define DeviceDsmAction_Trim
struct _DEVICE_DATA_SET_RANGE DEVICE_DATA_SET_RANGE
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
BOOLEAN NTAPI ExIsResourceAcquiredExclusiveLite(IN PERESOURCE Resource)
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
VOID NTAPI IoFreeIrp(IN PIRP Irp)
NTSTATUS NTAPI PsTerminateSystemThread(IN NTSTATUS ExitStatus)
#define STATUS_INTERNAL_ERROR
#define STATUS_UNEXPECTED_IO_ERROR
#define BTRFS_INODE_PREALLOC
#define BTRFS_INODE_NODATASUM
#define _SEH2_GetExceptionCode()
#define _SEH2_EXCEPT(...)
#define IRP_MJ_DEVICE_CONTROL
#define offsetof(TYPE, MEMBER)
#define IOCTL_ATA_PASS_THROUGH
struct _ATA_PASS_THROUGH_EX ATA_PASS_THROUGH_EX
static const void * body(MD5_CTX *ctx, const void *data, unsigned long size)
#define SUBVOL_ROOT_INODE
#define STATUS_MORE_PROCESSING_REQUIRED
#define BTRFS_TYPE_DIRECTORY
#define BLOCK_FLAG_DUPLICATE
#define BLOCK_FLAG_SYSTEM
#define BLOCK_FLAG_RAID10
#define BLOCK_FLAG_METADATA
_In_ size_t const maxsize
BTRFS_UUID chunktree_uuid
struct _IO_STACK_LOCATION::@4104::@4109 Write
union _IO_STACK_LOCATION::@1611 Parameters
struct _IO_STACK_LOCATION::@1611::@1612 DeviceIoControl
struct _LIST_ENTRY * Blink
struct _LIST_ENTRY * Flink
struct _device_extension * Vcb
ANSI_STRING reparse_xattr
bool reparse_xattr_changed
enum prop_compression_type prop_compression
LIST_ENTRY list_entry_dirty
bool prop_compression_changed
FSRTL_ADVANCED_FCB_HEADER Header
struct _file_ref * parent
struct pdo_device_extension * pdode
enum batch_operation operation
DEVICE_MANAGE_DATA_SET_ATTRIBUTES * dmdsa
ioctl_context_stripe * stripes
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
#define RtlCopyMemory(Destination, Source, Length)
#define RtlZeroMemory(Destination, Length)
#define CONTAINING_RECORD(address, type, field)
#define STATUS_INSUFFICIENT_RESOURCES
#define IDE_COMMAND_FLUSH_CACHE
_In_ PDEVICE_OBJECT DeviceObject
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
#define IRP_INPUT_OPERATION
#define ObDereferenceObject
#define ObReferenceObject
XXH_PUBLIC_API unsigned long long XXH64(const void *input, size_t len, unsigned long long seed)