ReactOS  0.4.14-dev-342-gdc047f9
flushthread.c File Reference
#include "btrfs_drv.h"
#include <ata.h>
#include <ntddscsi.h>
#include <ntddstor.h>
Include dependency graph for flushthread.c:

Go to the source code of this file.

Classes

struct  write_context
 
struct  EXTENT_ITEM_TREE2
 
struct  EXTENT_ITEM_SKINNY_METADATA
 
struct  ioctl_context_stripe
 
struct  ioctl_context
 
struct  write_superblocks_stripe
 
struct  _write_superblocks_context
 
struct  extent_range
 

Macros

#define MAX_CSUM_SIZE   (4096 - sizeof(tree_header) - sizeof(leaf_node))
 
#define DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED   0x80000000
 

Typedefs

typedef struct _write_superblocks_context write_superblocks_context
 

Functions

static NTSTATUS create_chunk (device_extension *Vcb, chunk *c, PIRP Irp)
 
static NTSTATUS update_tree_extents (device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
 
 _Function_class_ (IO_COMPLETION_ROUTINE)
 
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 void add_trim_entry (device *dev, uint64_t address, uint64_t size)
 
static void clean_space_cache_chunk (device_extension *Vcb, chunk *c)
 
static void clean_space_cache (device_extension *Vcb)
 
static bool trees_consistent (device_extension *Vcb)
 
static NTSTATUS add_parents (device_extension *Vcb, PIRP Irp)
 
static void add_parents_to_cache (tree *t)
 
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)
 
bool find_metadata_address_in_chunk (device_extension *Vcb, chunk *c, uint64_t *address)
 
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)
 
NTSTATUS get_tree_new_address (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 NTSTATUS add_changed_extent_ref_edr (changed_extent *ce, EXTENT_DATA_REF *edr, bool old)
 
static NTSTATUS add_changed_extent_ref_sdr (changed_extent *ce, SHARED_DATA_REF *sdr, bool old)
 
static bool shared_tree_is_unique (device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
 
static NTSTATUS allocate_tree_extents (device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
 
static NTSTATUS update_root_root (device_extension *Vcb, bool no_cache, PIRP Irp, LIST_ENTRY *rollback)
 
NTSTATUS do_tree_writes (device_extension *Vcb, LIST_ENTRY *tree_writes, bool no_free)
 
static NTSTATUS write_trees (device_extension *Vcb, PIRP Irp)
 
static void update_backup_superblock (device_extension *Vcb, superblock_backup *sb, PIRP Irp)
 
static NTSTATUS write_superblock (device_extension *Vcb, device *device, write_superblocks_context *context)
 
static NTSTATUS write_superblocks (device_extension *Vcb, PIRP Irp)
 
static NTSTATUS flush_changed_extent (device_extension *Vcb, chunk *c, changed_extent *ce, PIRP Irp, LIST_ENTRY *rollback)
 
void add_checksum_entry (device_extension *Vcb, uint64_t address, ULONG length, uint32_t *csum, PIRP Irp)
 
static NTSTATUS update_chunk_usage (device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
 
static void get_first_item (tree *t, KEY *key)
 
static NTSTATUS split_tree_at (device_extension *Vcb, tree *t, tree_data *newfirstitem, uint32_t numitems, uint32_t size)
 
static NTSTATUS split_tree (device_extension *Vcb, tree *t)
 
bool is_tree_unique (device_extension *Vcb, tree *t, PIRP Irp)
 
static NTSTATUS try_tree_amalgamate (device_extension *Vcb, tree *t, bool *done, bool *done_deletions, PIRP Irp, LIST_ENTRY *rollback)
 
static NTSTATUS update_extent_level (device_extension *Vcb, uint64_t address, tree *t, uint8_t level, PIRP Irp)
 
static NTSTATUS update_tree_extents_recursive (device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
 
static NTSTATUS do_splits (device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
 
static NTSTATUS remove_root_extents (device_extension *Vcb, root *r, tree_holder *th, uint8_t level, tree *parent, PIRP Irp, LIST_ENTRY *rollback)
 
static NTSTATUS drop_root (device_extension *Vcb, root *r, PIRP Irp, LIST_ENTRY *rollback)
 
static NTSTATUS drop_roots (device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
 
NTSTATUS update_dev_item (device_extension *Vcb, device *device, PIRP Irp)
 
static void regen_bootstrap (device_extension *Vcb)
 
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 void remove_from_bootstrap (device_extension *Vcb, uint64_t obj_id, uint8_t obj_type, uint64_t offset)
 
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 delete_xattr (device_extension *Vcb, LIST_ENTRY *batchlist, root *subvol, uint64_t inode, char *name, uint16_t namelen, uint32_t crc32)
 
static NTSTATUS insert_sparse_extent (fcb *fcb, LIST_ENTRY *batchlist, uint64_t start, uint64_t length)
 
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 void rationalize_extents (fcb *fcb, PIRP Irp)
 
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_chunk (device_extension *Vcb, chunk *c, LIST_ENTRY *batchlist, 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)
 
NTSTATUS flush_partial_stripe (device_extension *Vcb, chunk *c, partial_stripe *ps)
 
static NTSTATUS update_chunks (device_extension *Vcb, LIST_ENTRY *batchlist, PIRP Irp, LIST_ENTRY *rollback)
 
static NTSTATUS delete_root_ref (device_extension *Vcb, uint64_t subvolid, uint64_t parsubvolid, uint64_t parinode, PANSI_STRING utf8, PIRP Irp)
 
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)
 
static NTSTATUS update_root_backref (device_extension *Vcb, uint64_t subvolid, uint64_t parsubvolid, PIRP Irp)
 
static NTSTATUS add_root_item_to_cache (device_extension *Vcb, uint64_t root, PIRP Irp)
 
static NTSTATUS flush_fileref (file_ref *fileref, LIST_ENTRY *batchlist, PIRP Irp)
 
static void flush_disk_caches (device_extension *Vcb)
 
static NTSTATUS flush_changed_dev_stats (device_extension *Vcb, device *dev, PIRP Irp)
 
static NTSTATUS flush_subvol (device_extension *Vcb, root *r, PIRP Irp)
 
static NTSTATUS test_not_full (device_extension *Vcb)
 
static NTSTATUS check_for_orphans_root (device_extension *Vcb, root *r, PIRP Irp)
 
static NTSTATUS check_for_orphans (device_extension *Vcb, PIRP Irp)
 
static NTSTATUS do_write2 (device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
 
NTSTATUS do_write (device_extension *Vcb, PIRP Irp)
 
static void do_flush (device_extension *Vcb)
 
 _Function_class_ (KSTART_ROUTINE)
 

Macro Definition Documentation

◆ DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED

#define DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED   0x80000000

Definition at line 48 of file flushthread.c.

◆ MAX_CSUM_SIZE

#define MAX_CSUM_SIZE   (4096 - sizeof(tree_header) - sizeof(leaf_node))

Definition at line 23 of file flushthread.c.

Typedef Documentation

◆ write_superblocks_context

Function Documentation

◆ _Function_class_() [1/2]

_Function_class_ ( IO_COMPLETION_ROUTINE  )

Definition at line 51 of file flushthread.c.

52  {
53  write_context* context = conptr;
54 
56 
57  context->iosb = Irp->IoStatus;
58  KeSetEvent(&context->Event, 0, false);
59 
61 }
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
Definition: http.c:6587
_In_ PIRP Irp
Definition: csq.h:116
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
#define UNUSED(x)
Definition: btrfs_drv.h:86
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560

◆ _Function_class_() [2/2]

_Function_class_ ( KSTART_ROUTINE  )

Definition at line 7704 of file flushthread.c.

7705  {
7706  DEVICE_OBJECT* devobj = context;
7708  LARGE_INTEGER due_time;
7709 
7710  ObReferenceObject(devobj);
7711 
7712  KeInitializeTimer(&Vcb->flush_thread_timer);
7713 
7714  due_time.QuadPart = (uint64_t)Vcb->options.flush_interval * -10000000;
7715 
7716  KeSetTimer(&Vcb->flush_thread_timer, due_time, NULL);
7717 
7718  while (true) {
7719  KeWaitForSingleObject(&Vcb->flush_thread_timer, Executive, KernelMode, false, NULL);
7720 
7721  if (!(devobj->Vpb->Flags & VPB_MOUNTED) || Vcb->removing)
7722  break;
7723 
7724  if (!Vcb->locked)
7725  do_flush(Vcb);
7726 
7727  KeSetTimer(&Vcb->flush_thread_timer, due_time, NULL);
7728  }
7729 
7730  ObDereferenceObject(devobj);
7731  KeCancelTimer(&Vcb->flush_thread_timer);
7732 
7733  KeSetEvent(&Vcb->flush_thread_finished, 0, false);
7734 
7736 }
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281
Definition: http.c:6587
static void do_flush(device_extension *Vcb)
Definition: flushthread.c:7686
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
PVOID DeviceExtension
Definition: env_spec_w32.h:418
smooth NULL
Definition: ftsmooth.c:416
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
#define Vcb
Definition: cdprocs.h:1425
#define uint64_t
Definition: nsiface.idl:62
NTSTATUS NTAPI PsTerminateSystemThread(IN NTSTATUS ExitStatus)
Definition: kill.c:1144
#define ObReferenceObject
Definition: obfuncs.h:204
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define VPB_MOUNTED
Definition: iotypes.h:1764
LONGLONG QuadPart
Definition: typedefs.h:112

◆ add_changed_extent_ref_edr()

static NTSTATUS add_changed_extent_ref_edr ( changed_extent ce,
EXTENT_DATA_REF edr,
bool  old 
)
static

Definition at line 994 of file flushthread.c.

994  {
995  LIST_ENTRY *le2, *list;
996  changed_extent_ref* cer;
997 
998  list = old ? &ce->old_refs : &ce->refs;
999 
1000  le2 = list->Flink;
1001  while (le2 != list) {
1003 
1004  if (cer->type == TYPE_EXTENT_DATA_REF && cer->edr.root == edr->root && cer->edr.objid == edr->objid && cer->edr.offset == edr->offset) {
1005  cer->edr.count += edr->count;
1006  goto end;
1007  }
1008 
1009  le2 = le2->Flink;
1010  }
1011 
1013  if (!cer) {
1014  ERR("out of memory\n");
1016  }
1017 
1018  cer->type = TYPE_EXTENT_DATA_REF;
1019  RtlCopyMemory(&cer->edr, edr, sizeof(EXTENT_DATA_REF));
1020  InsertTailList(list, &cer->list_entry);
1021 
1022 end:
1023  if (old)
1024  ce->old_count += edr->count;
1025  else
1026  ce->count += edr->count;
1027 
1028  return STATUS_SUCCESS;
1029 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
uint64_t offset
Definition: btrfs.h:397
LIST_ENTRY list_entry
Definition: btrfs_drv.h:610
uint64_t objid
Definition: btrfs.h:396
GLuint GLuint end
Definition: gl.h:1545
#define InsertTailList(ListHead, Entry)
LIST_ENTRY old_refs
Definition: btrfs_drv.h:598
#define ALLOC_TAG
Definition: btrfs_drv.h:91
EXTENT_DATA_REF edr
Definition: btrfs_drv.h:606
uint32_t count
Definition: btrfs.h:398
uint64_t count
Definition: btrfs_drv.h:593
uint64_t root
Definition: btrfs.h:395
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define TYPE_EXTENT_DATA_REF
Definition: btrfs.h:34
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Definition: _list.h:228
Definition: typedefs.h:117
#define ERR(fmt,...)
Definition: debug.h:109
#define list
Definition: rosglue.h:35
LIST_ENTRY refs
Definition: btrfs_drv.h:597
Definition: list.h:27
return STATUS_SUCCESS
Definition: btrfs.c:2938
uint64_t old_count
Definition: btrfs_drv.h:594

Referenced by update_tree_extents().

◆ add_changed_extent_ref_sdr()

static NTSTATUS add_changed_extent_ref_sdr ( changed_extent ce,
SHARED_DATA_REF sdr,
bool  old 
)
static

Definition at line 1031 of file flushthread.c.

1031  {
1032  LIST_ENTRY *le2, *list;
1033  changed_extent_ref* cer;
1034 
1035  list = old ? &ce->old_refs : &ce->refs;
1036 
1037  le2 = list->Flink;
1038  while (le2 != list) {
1040 
1041  if (cer->type == TYPE_SHARED_DATA_REF && cer->sdr.offset == sdr->offset) {
1042  cer->sdr.count += sdr->count;
1043  goto end;
1044  }
1045 
1046  le2 = le2->Flink;
1047  }
1048 
1050  if (!cer) {
1051  ERR("out of memory\n");
1053  }
1054 
1055  cer->type = TYPE_SHARED_DATA_REF;
1056  RtlCopyMemory(&cer->sdr, sdr, sizeof(SHARED_DATA_REF));
1057  InsertTailList(list, &cer->list_entry);
1058 
1059 end:
1060  if (old)
1061  ce->old_count += sdr->count;
1062  else
1063  ce->count += sdr->count;
1064 
1065  return STATUS_SUCCESS;
1066 }
SHARED_DATA_REF sdr
Definition: btrfs_drv.h:607
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LIST_ENTRY list_entry
Definition: btrfs_drv.h:610
GLuint GLuint end
Definition: gl.h:1545
#define InsertTailList(ListHead, Entry)
LIST_ENTRY old_refs
Definition: btrfs_drv.h:598
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint64_t count
Definition: btrfs_drv.h:593
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define TYPE_SHARED_DATA_REF
Definition: btrfs.h:37
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
uint32_t count
Definition: btrfs.h:420
Definition: _list.h:228
Definition: typedefs.h:117
#define ERR(fmt,...)
Definition: debug.h:109
#define list
Definition: rosglue.h:35
LIST_ENTRY refs
Definition: btrfs_drv.h:597
Definition: list.h:27
return STATUS_SUCCESS
Definition: btrfs.c:2938
uint64_t offset
Definition: btrfs.h:419
uint64_t old_count
Definition: btrfs_drv.h:594

Referenced by update_tree_extents().

◆ add_checksum_entry()

void add_checksum_entry ( device_extension Vcb,
uint64_t  address,
ULONG  length,
uint32_t csum,
PIRP  Irp 
)

Definition at line 2555 of file flushthread.c.

2555  {
2556  KEY searchkey;
2557  traverse_ptr tp, next_tp;
2558  NTSTATUS Status;
2559  uint64_t startaddr, endaddr;
2560  ULONG len;
2561  uint32_t* checksums;
2562  RTL_BITMAP bmp;
2563  ULONG* bmparr;
2564  ULONG runlength, index;
2565 
2566  TRACE("(%p, %I64x, %x, %p, %p)\n", Vcb, address, length, csum, Irp);
2567 
2568  searchkey.obj_id = EXTENT_CSUM_ID;
2569  searchkey.obj_type = TYPE_EXTENT_CSUM;
2570  searchkey.offset = address;
2571 
2572  // FIXME - create checksum_root if it doesn't exist at all
2573 
2574  Status = find_item(Vcb, Vcb->checksum_root, &tp, &searchkey, false, Irp);
2575  if (Status == STATUS_NOT_FOUND) { // tree is completely empty
2576  if (csum) { // not deleted
2577  ULONG length2 = length;
2578  uint64_t off = address;
2579  uint32_t* data = csum;
2580 
2581  do {
2582  uint16_t il = (uint16_t)min(length2, MAX_CSUM_SIZE / sizeof(uint32_t));
2583 
2584  checksums = ExAllocatePoolWithTag(PagedPool, il * sizeof(uint32_t), ALLOC_TAG);
2585  if (!checksums) {
2586  ERR("out of memory\n");
2587  return;
2588  }
2589 
2590  RtlCopyMemory(checksums, data, il * sizeof(uint32_t));
2591 
2592  Status = insert_tree_item(Vcb, Vcb->checksum_root, EXTENT_CSUM_ID, TYPE_EXTENT_CSUM, off, checksums,
2593  il * sizeof(uint32_t), NULL, Irp);
2594  if (!NT_SUCCESS(Status)) {
2595  ERR("insert_tree_item returned %08x\n", Status);
2596  ExFreePool(checksums);
2597  return;
2598  }
2599 
2600  length2 -= il;
2601 
2602  if (length2 > 0) {
2603  off += il * Vcb->superblock.sector_size;
2604  data += il;
2605  }
2606  } while (length2 > 0);
2607  }
2608  } else if (!NT_SUCCESS(Status)) {
2609  ERR("find_item returned %08x\n", Status);
2610  return;
2611  } else {
2612  uint32_t tplen;
2613 
2614  // FIXME - check entry is TYPE_EXTENT_CSUM?
2615 
2616  if (tp.item->key.offset < address && tp.item->key.offset + (tp.item->size * Vcb->superblock.sector_size / sizeof(uint32_t)) >= address)
2617  startaddr = tp.item->key.offset;
2618  else
2619  startaddr = address;
2620 
2621  searchkey.obj_id = EXTENT_CSUM_ID;
2622  searchkey.obj_type = TYPE_EXTENT_CSUM;
2623  searchkey.offset = address + (length * Vcb->superblock.sector_size);
2624 
2625  Status = find_item(Vcb, Vcb->checksum_root, &tp, &searchkey, false, Irp);
2626  if (!NT_SUCCESS(Status)) {
2627  ERR("find_item returned %08x\n", Status);
2628  return;
2629  }
2630 
2631  tplen = tp.item->size / sizeof(uint32_t);
2632 
2633  if (tp.item->key.offset + (tplen * Vcb->superblock.sector_size) >= address + (length * Vcb->superblock.sector_size))
2634  endaddr = tp.item->key.offset + (tplen * Vcb->superblock.sector_size);
2635  else
2636  endaddr = address + (length * Vcb->superblock.sector_size);
2637 
2638  TRACE("cs starts at %I64x (%x sectors)\n", address, length);
2639  TRACE("startaddr = %I64x\n", startaddr);
2640  TRACE("endaddr = %I64x\n", endaddr);
2641 
2642  len = (ULONG)((endaddr - startaddr) / Vcb->superblock.sector_size);
2643 
2644  checksums = ExAllocatePoolWithTag(PagedPool, sizeof(uint32_t) * len, ALLOC_TAG);
2645  if (!checksums) {
2646  ERR("out of memory\n");
2647  return;
2648  }
2649 
2650  bmparr = ExAllocatePoolWithTag(PagedPool, sizeof(ULONG) * ((len/8)+1), ALLOC_TAG);
2651  if (!bmparr) {
2652  ERR("out of memory\n");
2653  ExFreePool(checksums);
2654  return;
2655  }
2656 
2657  RtlInitializeBitMap(&bmp, bmparr, len);
2658  RtlSetAllBits(&bmp);
2659 
2660  searchkey.obj_id = EXTENT_CSUM_ID;
2661  searchkey.obj_type = TYPE_EXTENT_CSUM;
2662  searchkey.offset = address;
2663 
2664  Status = find_item(Vcb, Vcb->checksum_root, &tp, &searchkey, false, Irp);
2665  if (!NT_SUCCESS(Status)) {
2666  ERR("find_item returned %08x\n", Status);
2667  ExFreePool(checksums);
2668  ExFreePool(bmparr);
2669  return;
2670  }
2671 
2672  // set bit = free space, cleared bit = allocated sector
2673 
2674  while (tp.item->key.offset < endaddr) {
2675  if (tp.item->key.offset >= startaddr) {
2676  if (tp.item->size > 0) {
2677  ULONG itemlen = (ULONG)min((len - (tp.item->key.offset - startaddr) / Vcb->superblock.sector_size) * sizeof(uint32_t), tp.item->size);
2678 
2679  RtlCopyMemory(&checksums[(tp.item->key.offset - startaddr) / Vcb->superblock.sector_size], tp.item->data, itemlen);
2680  RtlClearBits(&bmp, (ULONG)((tp.item->key.offset - startaddr) / Vcb->superblock.sector_size), itemlen / sizeof(uint32_t));
2681  }
2682 
2684  if (!NT_SUCCESS(Status)) {
2685  ERR("delete_tree_item returned %08x\n", Status);
2686  ExFreePool(checksums);
2687  ExFreePool(bmparr);
2688  return;
2689  }
2690  }
2691 
2692  if (find_next_item(Vcb, &tp, &next_tp, false, Irp)) {
2693  tp = next_tp;
2694  } else
2695  break;
2696  }
2697 
2698  if (!csum) { // deleted
2699  RtlSetBits(&bmp, (ULONG)((address - startaddr) / Vcb->superblock.sector_size), length);
2700  } else {
2701  RtlCopyMemory(&checksums[(address - startaddr) / Vcb->superblock.sector_size], csum, length * sizeof(uint32_t));
2702  RtlClearBits(&bmp, (ULONG)((address - startaddr) / Vcb->superblock.sector_size), length);
2703  }
2704 
2705  runlength = RtlFindFirstRunClear(&bmp, &index);
2706 
2707  while (runlength != 0) {
2708  if (index >= len)
2709  break;
2710 
2711  if (index + runlength >= len) {
2712  runlength = len - index;
2713 
2714  if (runlength == 0)
2715  break;
2716  }
2717 
2718  do {
2719  uint16_t rl;
2720  uint64_t off;
2721  uint32_t* data;
2722 
2723  if (runlength * sizeof(uint32_t) > MAX_CSUM_SIZE)
2724  rl = MAX_CSUM_SIZE / sizeof(uint32_t);
2725  else
2726  rl = (uint16_t)runlength;
2727 
2729  if (!data) {
2730  ERR("out of memory\n");
2731  ExFreePool(bmparr);
2732  ExFreePool(checksums);
2733  return;
2734  }
2735 
2736  RtlCopyMemory(data, &checksums[index], sizeof(uint32_t) * rl);
2737 
2738  off = startaddr + UInt32x32To64(index, Vcb->superblock.sector_size);
2739 
2740  Status = insert_tree_item(Vcb, Vcb->checksum_root, EXTENT_CSUM_ID, TYPE_EXTENT_CSUM, off, data, sizeof(uint32_t) * rl, NULL, Irp);
2741  if (!NT_SUCCESS(Status)) {
2742  ERR("insert_tree_item returned %08x\n", Status);
2743  ExFreePool(data);
2744  ExFreePool(bmparr);
2745  ExFreePool(checksums);
2746  return;
2747  }
2748 
2749  runlength -= rl;
2750  index += rl;
2751  } while (runlength > 0);
2752 
2753  runlength = RtlFindNextForwardRunClear(&bmp, index, &index);
2754  }
2755 
2756  ExFreePool(bmparr);
2757  ExFreePool(checksums);
2758  }
2759 }
uint64_t obj_id
Definition: btrfs.h:128
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
#define MAX_CSUM_SIZE
Definition: flushthread.c:23
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:129
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
_In_ PIRP Irp
Definition: csq.h:116
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:415
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
uint64_t offset
Definition: btrfs.h:130
uint8_t * data
Definition: btrfs_drv.h:416
#define TYPE_EXTENT_CSUM
Definition: btrfs.h:27
#define ALLOC_TAG
Definition: btrfs_drv.h:91
NTSYSAPI ULONG WINAPI RtlFindNextForwardRunClear(PCRTL_BITMAP, ULONG, PULONG)
smooth NULL
Definition: ftsmooth.c:416
GLuint index
Definition: glext.h:6031
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2855
uint32_t * csum
Definition: write.c:2821
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define TRACE(s)
Definition: solgame.cpp:4
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)
Definition: treefuncs.c:592
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define Vcb
Definition: cdprocs.h:1425
GLuint address
Definition: glext.h:9393
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
BITMAP bmp
Definition: alphablend.c:62
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)
Definition: treefuncs.c:857
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:502
#define index(s, c)
Definition: various.h:29
GLenum GLsizei len
Definition: glext.h:6722
static void startaddr(void)
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:127
#define EXTENT_CSUM_ID
Definition: btrfs.h:85
UINT64 uint64_t
Definition: types.h:77
NTSYSAPI ULONG NTAPI RtlFindFirstRunClear(_In_ PRTL_BITMAP BitMapHeader, _Out_ PULONG StartingIndex)
#define min(a, b)
Definition: monoChain.cc:55
UINT32 uint32_t
Definition: types.h:75
Definition: fs.h:216
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI void WINAPI RtlSetBits(PRTL_BITMAP, ULONG, ULONG)
#define uint32_t
Definition: nsiface.idl:61
#define UInt32x32To64(a, b)
Definition: intsafe.h:258
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:989
off
Definition: i386-dis.c:3909

Referenced by balance_data_chunk(), decrease_extent_refcount(), flush_fcb(), and rationalize_extents().

◆ add_parents()

static NTSTATUS add_parents ( device_extension Vcb,
PIRP  Irp 
)
static

Definition at line 595 of file flushthread.c.

595  {
596  ULONG level;
597  LIST_ENTRY* le;
598 
599  for (level = 0; level <= 255; level++) {
600  bool nothing_found = true;
601 
602  TRACE("level = %u\n", level);
603 
604  le = Vcb->trees.Flink;
605  while (le != &Vcb->trees) {
607 
608  if (t->write && t->header.level == level) {
609  TRACE("tree %p: root = %I64x, level = %x, parent = %p\n", t, t->header.tree_id, t->header.level, t->parent);
610 
611  nothing_found = false;
612 
613  if (t->parent) {
614  if (!t->parent->write)
615  TRACE("adding tree %p (level %x)\n", t->parent, t->header.level);
616 
617  t->parent->write = true;
618  } else if (t->root != Vcb->root_root && t->root != Vcb->chunk_root) {
619  KEY searchkey;
622 #ifdef __REACTOS__
623  tree* t2;
624 #endif
625 
626  searchkey.obj_id = t->root->id;
627  searchkey.obj_type = TYPE_ROOT_ITEM;
628  searchkey.offset = 0xffffffffffffffff;
629 
630  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
631  if (!NT_SUCCESS(Status)) {
632  ERR("error - find_item returned %08x\n", Status);
633  return Status;
634  }
635 
636  if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
637  ERR("could not find ROOT_ITEM for tree %I64x\n", searchkey.obj_id);
638  return STATUS_INTERNAL_ERROR;
639  }
640 
641  if (tp.item->size < sizeof(ROOT_ITEM)) { // if not full length, delete and create new entry
643 
644  if (!ri) {
645  ERR("out of memory\n");
647  }
648 
649  RtlCopyMemory(ri, &t->root->root_item, sizeof(ROOT_ITEM));
650 
652  if (!NT_SUCCESS(Status)) {
653  ERR("delete_tree_item returned %08x\n", Status);
654  ExFreePool(ri);
655  return Status;
656  }
657 
658  Status = insert_tree_item(Vcb, Vcb->root_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, ri, sizeof(ROOT_ITEM), NULL, Irp);
659  if (!NT_SUCCESS(Status)) {
660  ERR("insert_tree_item returned %08x\n", Status);
661  ExFreePool(ri);
662  return Status;
663  }
664  }
665 
666 #ifndef __REACTOS__
667  tree* t2 = tp.tree;
668 #else
669  t2 = tp.tree;
670 #endif
671  while (t2) {
672  t2->write = true;
673 
674  t2 = t2->parent;
675  }
676  }
677  }
678 
679  le = le->Flink;
680  }
681 
682  if (nothing_found)
683  break;
684  }
685 
686  return STATUS_SUCCESS;
687 }
uint64_t obj_id
Definition: btrfs.h:128
GLint level
Definition: gl.h:1546
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:129
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PIRP Irp
Definition: csq.h:116
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:415
GLdouble GLdouble t
Definition: gl.h:2047
uint64_t offset
Definition: btrfs.h:130
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:91
tree * tree
Definition: btrfs_drv.h:501
smooth NULL
Definition: ftsmooth.c:416
struct _tree * parent
Definition: btrfs_drv.h:432
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2855
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define TRACE(s)
Definition: solgame.cpp:4
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
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)
Definition: treefuncs.c:857
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:502
Definition: typedefs.h:117
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:127
#define TYPE_ROOT_ITEM
Definition: btrfs.h:28
Definition: list.h:27
unsigned int ULONG
Definition: retypes.h:1
return STATUS_SUCCESS
Definition: btrfs.c:2938
bool write
Definition: btrfs_drv.h:441
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:989

Referenced by do_write2().

◆ add_parents_to_cache()

static void add_parents_to_cache ( tree t)
static

Definition at line 689 of file flushthread.c.

689  {
690  while (t->parent) {
691  t = t->parent;
692  t->write = true;
693  }
694 }
GLdouble GLdouble t
Definition: gl.h:2047

Referenced by insert_tree_extent(), and insert_tree_extent_skinny().

◆ add_root_item_to_cache()

static NTSTATUS add_root_item_to_cache ( device_extension Vcb,
uint64_t  root,
PIRP  Irp 
)
static

Definition at line 6313 of file flushthread.c.

6313  {
6314  KEY searchkey;
6315  traverse_ptr tp;
6316  NTSTATUS Status;
6317 
6318  searchkey.obj_id = root;
6319  searchkey.obj_type = TYPE_ROOT_ITEM;
6320  searchkey.offset = 0xffffffffffffffff;
6321 
6322  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
6323  if (!NT_SUCCESS(Status)) {
6324  ERR("error - find_item returned %08x\n", Status);
6325  return Status;
6326  }
6327 
6328  if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
6329  ERR("could not find ROOT_ITEM for tree %I64x\n", searchkey.obj_id);
6330  return STATUS_INTERNAL_ERROR;
6331  }
6332 
6333  if (tp.item->size < sizeof(ROOT_ITEM)) { // if not full length, create new entry with new bits zeroed
6335  if (!ri) {
6336  ERR("out of memory\n");
6338  }
6339 
6340  if (tp.item->size > 0)
6341  RtlCopyMemory(ri, tp.item->data, tp.item->size);
6342 
6343  RtlZeroMemory(((uint8_t*)ri) + tp.item->size, sizeof(ROOT_ITEM) - tp.item->size);
6344 
6346  if (!NT_SUCCESS(Status)) {
6347  ERR("delete_tree_item returned %08x\n", Status);
6348  ExFreePool(ri);
6349  return Status;
6350  }
6351 
6352  Status = insert_tree_item(Vcb, Vcb->root_root, searchkey.obj_id, searchkey.obj_type, tp.item->key.offset, ri, sizeof(ROOT_ITEM), NULL, Irp);
6353  if (!NT_SUCCESS(Status)) {
6354  ERR("insert_tree_item returned %08x\n", Status);
6355  ExFreePool(ri);
6356  return Status;
6357  }
6358  } else {
6359  tp.tree->write = true;
6360  }
6361 
6362  return STATUS_SUCCESS;
6363 }
uint64_t obj_id
Definition: btrfs.h:128
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:129
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PIRP Irp
Definition: csq.h:116
struct _root root
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:415
uint64_t offset
Definition: btrfs.h:130
uint8_t * data
Definition: btrfs_drv.h:416
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:91
tree * tree
Definition: btrfs_drv.h:501
smooth NULL
Definition: ftsmooth.c:416
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2855
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
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)
Definition: treefuncs.c:857
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:502
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:127
#define TYPE_ROOT_ITEM
Definition: btrfs.h:28
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
return STATUS_SUCCESS
Definition: btrfs.c:2938
bool write
Definition: btrfs_drv.h:441
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:989

Referenced by do_write2().

◆ add_root_ref()

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 
)
static

Definition at line 6184 of file flushthread.c.

6184  {
6185  KEY searchkey;
6186  traverse_ptr tp;
6187  NTSTATUS Status;
6188 
6189  searchkey.obj_id = parsubvolid;
6190  searchkey.obj_type = TYPE_ROOT_REF;
6191  searchkey.offset = subvolid;
6192 
6193  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
6194  if (!NT_SUCCESS(Status)) {
6195  ERR("error - find_item returned %08x\n", Status);
6196  return Status;
6197  }
6198 
6199  if (!keycmp(searchkey, tp.item->key)) {
6200  uint16_t rrsize = tp.item->size + (uint16_t)offsetof(ROOT_REF, name[0]) + rr->n;
6201  uint8_t* rr2;
6202 
6203  rr2 = ExAllocatePoolWithTag(PagedPool, rrsize, ALLOC_TAG);
6204  if (!rr2) {
6205  ERR("out of memory\n");
6207  }
6208 
6209  if (tp.item->size > 0)
6210  RtlCopyMemory(rr2, tp.item->data, tp.item->size);
6211 
6212  RtlCopyMemory(rr2 + tp.item->size, rr, offsetof(ROOT_REF, name[0]) + rr->n);
6213  ExFreePool(rr);
6214 
6216  if (!NT_SUCCESS(Status)) {
6217  ERR("delete_tree_item returned %08x\n", Status);
6218  ExFreePool(rr2);
6219  return Status;
6220  }
6221 
6222  Status = insert_tree_item(Vcb, Vcb->root_root, searchkey.obj_id, searchkey.obj_type, searchkey.offset, rr2, rrsize, NULL, Irp);
6223  if (!NT_SUCCESS(Status)) {
6224  ERR("insert_tree_item returned %08x\n", Status);
6225  ExFreePool(rr2);
6226  return Status;
6227  }
6228  } else {
6229  Status = insert_tree_item(Vcb, Vcb->root_root, searchkey.obj_id, searchkey.obj_type, searchkey.offset, rr, (uint16_t)offsetof(ROOT_REF, name[0]) + rr->n, NULL, Irp);
6230  if (!NT_SUCCESS(Status)) {
6231  ERR("insert_tree_item returned %08x\n", Status);
6232  ExFreePool(rr);
6233  return Status;
6234  }
6235  }
6236 
6237  return STATUS_SUCCESS;
6238 }
#define TYPE_ROOT_REF
Definition: btrfs.h:30
uint64_t obj_id
Definition: btrfs.h:128
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:129
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PIRP Irp
Definition: csq.h:116
#define keycmp(key1, key2)
Definition: btrfs_drv.h:991
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:415
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
uint64_t offset
Definition: btrfs.h:130
uint8_t * data
Definition: btrfs_drv.h:416
#define ALLOC_TAG
Definition: btrfs_drv.h:91
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2855
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
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)
Definition: treefuncs.c:857
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:502
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:127
Definition: name.c:36
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:989

Referenced by flush_fileref().

◆ add_to_bootstrap()

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

Definition at line 4124 of file flushthread.c.

4124  {
4125  sys_chunk* sc;
4126  LIST_ENTRY* le;
4127 
4128  if (Vcb->superblock.n + sizeof(KEY) + size > SYS_CHUNK_ARRAY_SIZE) {
4129  ERR("error - bootstrap is full\n");
4130  return STATUS_INTERNAL_ERROR;
4131  }
4132 
4134  if (!sc) {
4135  ERR("out of memory\n");
4137  }
4138 
4139  sc->key.obj_id = obj_id;
4140  sc->key.obj_type = obj_type;
4141  sc->key.offset = offset;
4142  sc->size = size;
4144  if (!sc->data) {
4145  ERR("out of memory\n");
4146  ExFreePool(sc);
4148  }
4149 
4150  RtlCopyMemory(sc->data, data, sc->size);
4151 
4152  le = Vcb->sys_chunks.Flink;
4153  while (le != &Vcb->sys_chunks) {
4155 
4156  if (keycmp(sc2->key, sc->key) == 1)
4157  break;
4158 
4159  le = le->Flink;
4160  }
4161  InsertTailList(le, &sc->list_entry);
4162 
4163  Vcb->superblock.n += sizeof(KEY) + size;
4164 
4166 
4167  return STATUS_SUCCESS;
4168 }
uint64_t obj_id
Definition: btrfs.h:128
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:129
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define keycmp(key1, key2)
Definition: btrfs_drv.h:991
GLintptr offset
Definition: glext.h:5920
#define InsertTailList(ListHead, Entry)
uint64_t offset
Definition: btrfs.h:130
#define SYS_CHUNK_ARRAY_SIZE
Definition: btrfs.h:178
static void regen_bootstrap(device_extension *Vcb)
Definition: flushthread.c:4102
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:91
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
GLsizeiptr size
Definition: glext.h:5919
#define Vcb
Definition: cdprocs.h:1425
LIST_ENTRY list_entry
Definition: btrfs_drv.h:617
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Definition: typedefs.h:117
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:127
#define KEY
Definition: profile.c:30
Definition: list.h:27
USHORT size
Definition: btrfs_drv.h:616
return STATUS_SUCCESS
Definition: btrfs.c:2938
void * data
Definition: btrfs_drv.h:615
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by create_chunk().

◆ add_trim_entry()

static void add_trim_entry ( device dev,
uint64_t  address,
uint64_t  size 
)
static

Definition at line 150 of file flushthread.c.

150  {
152  if (!s) {
153  ERR("out of memory\n");
154  return;
155  }
156 
157  s->address = address;
158  s->size = size;
159  dev->num_trim_entries++;
160 
161  InsertTailList(&dev->trim_list, &s->list_entry);
162 }
#define InsertTailList(ListHead, Entry)
#define ALLOC_TAG
Definition: btrfs_drv.h:91
GLsizeiptr size
Definition: glext.h:5919
GLuint address
Definition: glext.h:9393
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
GLdouble s
Definition: gl.h:2039
#define ERR(fmt,...)
Definition: debug.h:109

Referenced by add_trim_entry_avoid_sb(), and clean_space_cache_chunk().

◆ add_trim_entry_avoid_sb()

void add_trim_entry_avoid_sb ( device_extension Vcb,
device dev,
uint64_t  address,
uint64_t  size 
)

Definition at line 5359 of file flushthread.c.

5359  {
5360  int i;
5361  ULONG sblen = (ULONG)sector_align(sizeof(superblock), Vcb->superblock.sector_size);
5362 
5363  i = 0;
5364  while (superblock_addrs[i] != 0) {
5365  if (superblock_addrs[i] + sblen >= address && superblock_addrs[i] < address + size) {
5366  if (superblock_addrs[i] > address)
5368 
5369  if (size <= superblock_addrs[i] + sblen - address)
5370  return;
5371 
5372  size -= superblock_addrs[i] + sblen - address;
5373  address = superblock_addrs[i] + sblen;
5374  } else if (superblock_addrs[i] > address + size)
5375  break;
5376 
5377  i++;
5378  }
5379 
5381 }
static void add_trim_entry(device *dev, uint64_t address, uint64_t size)
Definition: flushthread.c:150
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
Definition: glfuncs.h:248
GLsizeiptr size
Definition: glext.h:5919
#define Vcb
Definition: cdprocs.h:1425
GLuint address
Definition: glext.h:9393
static const uint64_t superblock_addrs[]
Definition: btrfs.h:13
unsigned int ULONG
Definition: retypes.h:1
static uint64_t __inline sector_align(uint64_t n, uint64_t a)

Referenced by drop_chunk(), and trim_unalloc_space().

◆ allocate_tree_extents()

static NTSTATUS allocate_tree_extents ( device_extension Vcb,
PIRP  Irp,
LIST_ENTRY rollback 
)
static

Definition at line 1452 of file flushthread.c.

1452  {
1453  LIST_ENTRY* le;
1454  NTSTATUS Status;
1455  bool changed = false;
1456  uint8_t max_level = 0, level;
1457 
1458  TRACE("(%p)\n", Vcb);
1459 
1460  le = Vcb->trees.Flink;
1461  while (le != &Vcb->trees) {
1463 
1464  if (t->write && !t->has_new_address) {
1465  chunk* c;
1466 
1467  if (t->has_address) {
1468  c = get_chunk_from_address(Vcb, t->header.address);
1469 
1470  if (c) {
1471  if (!c->cache_loaded) {
1473 
1474  if (!c->cache_loaded) {
1476 
1477  if (!NT_SUCCESS(Status)) {
1478  ERR("load_cache_chunk returned %08x\n", Status);
1480  return Status;
1481  }
1482  }
1483 
1485  }
1486  }
1487  }
1488 
1490  if (!NT_SUCCESS(Status)) {
1491  ERR("get_tree_new_address returned %08x\n", Status);
1492  return Status;
1493  }
1494 
1495  TRACE("allocated extent %I64x\n", t->new_address);
1496 
1497  c = get_chunk_from_address(Vcb, t->new_address);
1498 
1499  if (c)
1500  c->used += Vcb->superblock.node_size;
1501  else {
1502  ERR("could not find chunk for address %I64x\n", t->new_address);
1503  return STATUS_INTERNAL_ERROR;
1504  }
1505 
1506  changed = true;
1507 
1508  if (t->header.level > max_level)
1509  max_level = t->header.level;
1510  }
1511 
1512  le = le->Flink;
1513  }
1514 
1515  if (!changed)
1516  return STATUS_SUCCESS;
1517 
1518  level = max_level;
1519  do {
1520  le = Vcb->trees.Flink;
1521  while (le != &Vcb->trees) {
1523 
1524  if (t->write && !t->updated_extents && t->has_address && t->header.level == level) {
1526  if (!NT_SUCCESS(Status)) {
1527  ERR("update_tree_extents returned %08x\n", Status);
1528  return Status;
1529  }
1530  }
1531 
1532  le = le->Flink;
1533  }
1534 
1535  if (level == 0)
1536  break;
1537 
1538  level--;
1539  } while (true);
1540 
1541  return STATUS_SUCCESS;
1542 }
GLint level
Definition: gl.h:1546
NTSTATUS get_tree_new_address(device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:865
_In_ PIRP Irp
Definition: csq.h:116
LONG NTSTATUS
Definition: precomp.h:26
GLdouble GLdouble t
Definition: gl.h:2047
release_chunk_lock(c, Vcb)
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
smooth NULL
Definition: ftsmooth.c:416
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define TRACE(s)
Definition: solgame.cpp:4
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
Definition: typedefs.h:117
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
NTSTATUS load_cache_chunk(device_extension *Vcb, chunk *c, PIRP Irp)
Definition: free-space.c:979
#define ERR(fmt,...)
Definition: debug.h:109
chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address)
Definition: write.c:89
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1104
Definition: list.h:27
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1314
static NTSTATUS update_tree_extents(device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:1097
#define c
Definition: ke_i.h:80
return STATUS_SUCCESS
Definition: btrfs.c:2938

Referenced by do_write2().

◆ check_for_orphans()

static NTSTATUS check_for_orphans ( device_extension Vcb,
PIRP  Irp 
)
static

Definition at line 7243 of file flushthread.c.

7243  {
7244  NTSTATUS Status;
7245  LIST_ENTRY* le;
7246 
7247  if (IsListEmpty(&Vcb->dirty_filerefs))
7248  return STATUS_SUCCESS;
7249 
7250  le = Vcb->dirty_filerefs.Flink;
7251  while (le != &Vcb->dirty_filerefs) {
7253 
7254  if (!fr->fcb->subvol->checked_for_orphans) {
7256  if (!NT_SUCCESS(Status)) {
7257  ERR("check_for_orphans_root returned %08x\n", Status);
7258  return Status;
7259  }
7260 
7261  fr->fcb->subvol->checked_for_orphans = true;
7262  }
7263 
7264  le = le->Flink;
7265  }
7266 
7267  return STATUS_SUCCESS;
7268 }
static NTSTATUS check_for_orphans_root(device_extension *Vcb, root *r, PIRP Irp)
Definition: flushthread.c:7168
_In_ PIRP Irp
Definition: csq.h:116
LONG NTSTATUS
Definition: precomp.h:26
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
fcb * fcb
Definition: btrfs_drv.h:342
Definition: typedefs.h:117
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
struct _root * subvol
Definition: btrfs_drv.h:284
return STATUS_SUCCESS
Definition: btrfs.c:2938
LIST_ENTRY list_entry_dirty
Definition: btrfs_drv.h:334

Referenced by do_write2().

◆ check_for_orphans_root()

static NTSTATUS check_for_orphans_root ( device_extension Vcb,
root r,
PIRP  Irp 
)
static

Definition at line 7168 of file flushthread.c.

7168  {
7169  NTSTATUS Status;
7170  KEY searchkey;
7171  traverse_ptr tp;
7173 
7174  TRACE("(%p, %p)\n", Vcb, r);
7175 
7177 
7178  searchkey.obj_id = BTRFS_ORPHAN_INODE_OBJID;
7179  searchkey.obj_type = TYPE_ORPHAN_INODE;
7180  searchkey.offset = 0;
7181 
7182  Status = find_item(Vcb, r, &tp, &searchkey, false, Irp);
7183  if (!NT_SUCCESS(Status)) {
7184  ERR("find_item returned %08x\n", Status);
7185  return Status;
7186  }
7187 
7188  do {
7189  traverse_ptr next_tp;
7190 
7191  if (tp.item->key.obj_id > searchkey.obj_id || (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type > searchkey.obj_type))
7192  break;
7193 
7194  if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
7195  fcb* fcb;
7196 
7197  TRACE("removing orphaned inode %I64x\n", tp.item->key.offset);
7198 
7199  Status = open_fcb(Vcb, r, tp.item->key.offset, 0, NULL, false, NULL, &fcb, PagedPool, Irp);
7200  if (!NT_SUCCESS(Status))
7201  ERR("open_fcb returned %08x\n", Status);
7202  else {
7203  if (fcb->inode_item.st_nlink == 0) {
7204  if (fcb->type != BTRFS_TYPE_DIRECTORY && fcb->inode_item.st_size > 0) {
7205  Status = excise_extents(Vcb, fcb, 0, sector_align(fcb->inode_item.st_size, Vcb->superblock.sector_size), Irp, &rollback);
7206  if (!NT_SUCCESS(Status)) {
7207  ERR("excise_extents returned %08x\n", Status);
7208  goto end;
7209  }
7210  }
7211 
7212  fcb->deleted = true;
7213 
7215  }
7216 
7217  free_fcb(fcb);
7218 
7220  if (!NT_SUCCESS(Status)) {
7221  ERR("delete_tree_item returned %08x\n", Status);
7222  goto end;
7223  }
7224  }
7225  }
7226 
7227  if (find_next_item(Vcb, &tp, &next_tp, false, Irp))
7228  tp = next_tp;
7229  else
7230  break;
7231  } while (true);
7232 
7234 
7236 
7237 end:
7239 
7240  return Status;
7241 }
uint64_t obj_id
Definition: btrfs.h:128
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback)
Definition: treefuncs.c:1049
void clear_rollback(LIST_ENTRY *rollback)
Definition: treefuncs.c:1028
uint8_t obj_type
Definition: btrfs.h:129
void free_fcb(_Inout_ fcb *fcb)
Definition: btrfs.c:1653
_In_ PIRP Irp
Definition: csq.h:116
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
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)
Definition: create.c:668
LONG NTSTATUS
Definition: precomp.h:26
#define BTRFS_ORPHAN_INODE_OBJID
Definition: btrfs.h:119
GLuint GLuint end
Definition: gl.h:1545
uint64_t offset
Definition: btrfs.h:130
uint32_t st_nlink
Definition: btrfs.h:275
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
smooth NULL
Definition: ftsmooth.c:416
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1614
uint8_t type
Definition: btrfs_drv.h:287
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2855
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
uint64_t st_size
Definition: btrfs.h:272
#define TRACE(s)
Definition: solgame.cpp:4
struct _fcb fcb
Definition: btrfs_drv.h:1314
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)
Definition: treefuncs.c:592
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
tree_data * item
Definition: btrfs_drv.h:502
NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback)
Definition: write.c:2368
Definition: typedefs.h:117
INODE_ITEM inode_item
Definition: btrfs_drv.h:288
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:127
bool deleted
Definition: btrfs_drv.h:291
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1314
#define TYPE_ORPHAN_INODE
Definition: btrfs.h:23
return STATUS_SUCCESS
Definition: btrfs.c:2938
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:989

Referenced by check_for_orphans().

◆ clean_space_cache()

static void clean_space_cache ( device_extension Vcb)
static

Definition at line 393 of file flushthread.c.

393  {
394  LIST_ENTRY* le;
395  chunk* c;
396 #ifndef DEBUG_TRIM_EMULATION
397  ULONG num;
398 #endif
399 
400  TRACE("(%p)\n", Vcb);
401 
402  ExAcquireResourceSharedLite(&Vcb->chunk_lock, true);
403 
404  le = Vcb->chunks.Flink;
405  while (le != &Vcb->chunks) {
407 
408  if (c->space_changed) {
410 
411  if (c->space_changed)
413 
414  c->space_changed = false;
415 
417  }
418 
419  le = le->Flink;
420  }
421 
422  ExReleaseResourceLite(&Vcb->chunk_lock);
423 
424  if (Vcb->trim && !Vcb->options.no_trim) {
425 #ifndef DEBUG_TRIM_EMULATION
427  ULONG total_num;
428 
429  context.left = 0;
430 
431  le = Vcb->devices.Flink;
432  while (le != &Vcb->devices) {
434 
435  if (dev->devobj && !dev->readonly && dev->trim && dev->num_trim_entries > 0)
436  context.left++;
437 
438  le = le->Flink;
439  }
440 
441  if (context.left == 0)
442  return;
443 
444  total_num = context.left;
445  num = 0;
446 
448 
450  if (!context.stripes) {
451  ERR("out of memory\n");
452  return;
453  }
454 
455  RtlZeroMemory(context.stripes, sizeof(ioctl_context_stripe) * context.left);
456 #endif
457 
458  le = Vcb->devices.Flink;
459  while (le != &Vcb->devices) {
461 
462  if (dev->devobj && !dev->readonly && dev->trim && dev->num_trim_entries > 0) {
463 #ifdef DEBUG_TRIM_EMULATION
464  trim_emulation(dev);
465 #else
466  LIST_ENTRY* le2;
467  ioctl_context_stripe* stripe = &context.stripes[num];
468  DEVICE_DATA_SET_RANGE* ranges;
469  ULONG datalen = (ULONG)sector_align(sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES), sizeof(uint64_t)) + (dev->num_trim_entries * sizeof(DEVICE_DATA_SET_RANGE)), i;
471 
473  if (!stripe->dmdsa) {
474  ERR("out of memory\n");
475  goto nextdev;
476  }
477 
478  stripe->dmdsa->Size = sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES);
479  stripe->dmdsa->Action = DeviceDsmAction_Trim;
481  stripe->dmdsa->ParameterBlockOffset = 0;
482  stripe->dmdsa->ParameterBlockLength = 0;
483  stripe->dmdsa->DataSetRangesOffset = (ULONG)sector_align(sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES), sizeof(uint64_t));
484  stripe->dmdsa->DataSetRangesLength = dev->num_trim_entries * sizeof(DEVICE_DATA_SET_RANGE);
485 
486  ranges = (DEVICE_DATA_SET_RANGE*)((uint8_t*)stripe->dmdsa + stripe->dmdsa->DataSetRangesOffset);
487 
488  i = 0;
489 
490  le2 = dev->trim_list.Flink;
491  while (le2 != &dev->trim_list) {
493 
494  ranges[i].StartingOffset = s->address;
495  ranges[i].LengthInBytes = s->size;
496  i++;
497 
498  le2 = le2->Flink;
499  }
500 
501  stripe->Irp = IoAllocateIrp(dev->devobj->StackSize, false);
502 
503  if (!stripe->Irp) {
504  ERR("IoAllocateIrp failed\n");
505  goto nextdev;
506  }
507 
510  IrpSp->FileObject = dev->fileobj;
511 
512  IrpSp->Parameters.DeviceIoControl.IoControlCode = IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES;
513  IrpSp->Parameters.DeviceIoControl.InputBufferLength = datalen;
514  IrpSp->Parameters.DeviceIoControl.OutputBufferLength = 0;
515 
516  stripe->Irp->AssociatedIrp.SystemBuffer = stripe->dmdsa;
517  stripe->Irp->Flags |= IRP_BUFFERED_IO;
518  stripe->Irp->UserBuffer = NULL;
519  stripe->Irp->UserIosb = &stripe->iosb;
520 
521  IoSetCompletionRoutine(stripe->Irp, ioctl_completion, &context, true, true, true);
522 
523  IoCallDriver(dev->devobj, stripe->Irp);
524 
525 nextdev:
526 #endif
527  while (!IsListEmpty(&dev->trim_list)) {
529  ExFreePool(s);
530  }
531 
532  dev->num_trim_entries = 0;
533 
534 #ifndef DEBUG_TRIM_EMULATION
535  num++;
536 #endif
537  }
538 
539  le = le->Flink;
540  }
541 
542 #ifndef DEBUG_TRIM_EMULATION
544 
545  for (num = 0; num < total_num; num++) {
546  if (context.stripes[num].dmdsa)
547  ExFreePool(context.stripes[num].dmdsa);
548 
549  if (context.stripes[num].Irp)
550  IoFreeIrp(context.stripes[num].Irp);
551  }
552 
553  ExFreePool(context.stripes);
554 #endif
555  }
556 }
Definition: http.c:6587
struct _DEVICE_MANAGE_DATA_SET_ATTRIBUTES DEVICE_MANAGE_DATA_SET_ATTRIBUTES
release_chunk_lock(c, Vcb)
Definition: write.c:111
#define DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED
Definition: flushthread.c:48
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1027
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
struct _DEVICE_DATA_SET_RANGE DEVICE_DATA_SET_RANGE
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:515
#define ALLOC_TAG
Definition: btrfs_drv.h:91
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
Definition: glfuncs.h:248
ULONGLONG LengthInBytes
Definition: ntddstor.h:573
Definition: devices.h:37
#define DeviceDsmAction_Trim
Definition: ntddstor.h:211
smooth NULL
Definition: ftsmooth.c:416
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define TRACE(s)
Definition: solgame.cpp:4
#define IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES
Definition: ntddstor.h:170
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
GLuint GLuint num
Definition: glext.h:9618
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
GLdouble s
Definition: gl.h:2039
Definition: typedefs.h:117
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2647
BYTE uint8_t
Definition: msvideo1.c:66
#define uint64_t
Definition: nsiface.idl:62
#define ERR(fmt,...)
Definition: debug.h:109
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define IRP_BUFFERED_IO
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1104
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
Definition: list.h:27
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
LONGLONG StartingOffset
Definition: ntddstor.h:572
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
#define c
Definition: ke_i.h:80
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
static void clean_space_cache_chunk(device_extension *Vcb, chunk *c)
Definition: flushthread.c:164
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52

Referenced by do_write2().

◆ clean_space_cache_chunk()

static void clean_space_cache_chunk ( device_extension Vcb,
chunk c 
)
static

Definition at line 164 of file flushthread.c.

164  {
165  ULONG type;
166 
167  if (Vcb->trim && !Vcb->options.no_trim) {
168  if (c->chunk_item->type & BLOCK_FLAG_DUPLICATE)
170  else if (c->chunk_item->type & BLOCK_FLAG_RAID0)
172  else if (c->chunk_item->type & BLOCK_FLAG_RAID1)
174  else if (c->chunk_item->type & BLOCK_FLAG_RAID10)
176  else if (c->chunk_item->type & BLOCK_FLAG_RAID5)
178  else if (c->chunk_item->type & BLOCK_FLAG_RAID6)
180  else // SINGLE
182  }
183 
184  while (!IsListEmpty(&c->deleting)) {
185  space* s = CONTAINING_RECORD(c->deleting.Flink, space, list_entry);
186 
187  if (Vcb->trim && !Vcb->options.no_trim && (!Vcb->options.no_barrier || !(c->chunk_item->type & BLOCK_FLAG_METADATA))) {
188  CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&c->chunk_item[1];
189 
191  uint16_t i;
192 
193  for (i = 0; i < c->chunk_item->num_stripes; i++) {
194  if (c->devices[i] && c->devices[i]->devobj && !c->devices[i]->readonly && c->devices[i]->trim)
195  add_trim_entry(c->devices[i], s->address - c->offset + cis[i].offset, s->size);
196  }
197  } else if (type == BLOCK_FLAG_RAID0) {
198  uint64_t startoff, endoff;
199  uint16_t startoffstripe, endoffstripe, i;
200 
201  get_raid0_offset(s->address - c->offset, c->chunk_item->stripe_length, c->chunk_item->num_stripes, &startoff, &startoffstripe);
202  get_raid0_offset(s->address - c->offset + s->size - 1, c->chunk_item->stripe_length, c->chunk_item->num_stripes, &endoff, &endoffstripe);
203 
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) {
206  uint64_t stripestart, stripeend;
207 
208  if (startoffstripe > i)
209  stripestart = startoff - (startoff % c->chunk_item->stripe_length) + c->chunk_item->stripe_length;
210  else if (startoffstripe == i)
211  stripestart = startoff;
212  else
213  stripestart = startoff - (startoff % c->chunk_item->stripe_length);
214 
215  if (endoffstripe > i)
216  stripeend = endoff - (endoff % c->chunk_item->stripe_length) + c->chunk_item->stripe_length;
217  else if (endoffstripe == i)
218  stripeend = endoff + 1;
219  else
220  stripeend = endoff - (endoff % c->chunk_item->stripe_length);
221 
222  if (stripestart != stripeend)
223  add_trim_entry(c->devices[i], stripestart + cis[i].offset, stripeend - stripestart);
224  }
225  }
226  } else if (type == BLOCK_FLAG_RAID10) {
227  uint64_t startoff, endoff;
228  uint16_t sub_stripes, startoffstripe, endoffstripe, i;
229 
230  sub_stripes = max(1, c->chunk_item->sub_stripes);
231 
232  get_raid0_offset(s->address - c->offset, c->chunk_item->stripe_length, c->chunk_item->num_stripes / sub_stripes, &startoff, &startoffstripe);
233  get_raid0_offset(s->address - c->offset + s->size - 1, c->chunk_item->stripe_length, c->chunk_item->num_stripes / sub_stripes, &endoff, &endoffstripe);
234 
235  startoffstripe *= sub_stripes;
236  endoffstripe *= sub_stripes;
237 
238  for (i = 0; i < c->chunk_item->num_stripes; i += sub_stripes) {
239  ULONG j;
240  uint64_t stripestart, stripeend;
241 
242  if (startoffstripe > i)
243  stripestart = startoff - (startoff % c->chunk_item->stripe_length) + c->chunk_item->stripe_length;
244  else if (startoffstripe == i)
245  stripestart = startoff;
246  else
247  stripestart = startoff - (startoff % c->chunk_item->stripe_length);
248 
249  if (endoffstripe > i)
250  stripeend = endoff - (endoff % c->chunk_item->stripe_length) + c->chunk_item->stripe_length;
251  else if (endoffstripe == i)
252  stripeend = endoff + 1;
253  else
254  stripeend = endoff - (endoff % c->chunk_item->stripe_length);
255 
256  if (stripestart != stripeend) {
257  for (j = 0; j < sub_stripes; j++) {
258  if (c->devices[i+j] && c->devices[i+j]->devobj && !c->devices[i+j]->readonly && c->devices[i+j]->trim)
259  add_trim_entry(c->devices[i+j], stripestart + cis[i+j].offset, stripeend - stripestart);
260  }
261  }
262  }
263  }
264  // FIXME - RAID5(?), RAID6(?)
265  }
266 
267  RemoveEntryList(&s->list_entry);
268  ExFreePool(s);
269  }
270 }
#define max(a, b)
Definition: svc.c:63
static void add_trim_entry(device *dev, uint64_t address, uint64_t size)
Definition: flushthread.c:150
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
unsigned short int uint16_t
Definition: acefiex.h:54
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
_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)
Definition: btrfs_drv.h:972
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
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
Definition: glfuncs.h:248
#define BLOCK_FLAG_RAID10
Definition: shellext.h:81
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
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
Definition: glfuncs.h:250
#define BLOCK_FLAG_RAID0
Definition: shellext.h:78
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
#define BLOCK_FLAG_RAID6
Definition: shellext.h:83
#define BLOCK_FLAG_METADATA
Definition: shellext.h:77
GLdouble s
Definition: gl.h:2039
UINT64 uint64_t
Definition: types.h:77
Definition: list.h:27
unsigned int ULONG
Definition: retypes.h:1
#define BLOCK_FLAG_DUPLICATE
Definition: shellext.h:80
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define BLOCK_FLAG_RAID1
Definition: shellext.h:79

Referenced by clean_space_cache().

◆ create_chunk()

static NTSTATUS create_chunk ( device_extension Vcb,
chunk c,
PIRP  Irp 
)
static

Definition at line 4170 of file flushthread.c.

4170  {
4171  CHUNK_ITEM* ci;
4172  CHUNK_ITEM_STRIPE* cis;
4173  BLOCK_GROUP_ITEM* bgi;
4174  uint16_t i, factor;
4175  NTSTATUS Status;
4176 
4178  if (!ci) {
4179  ERR("out of memory\n");
4181  }
4182 
4183  RtlCopyMemory(ci, c->chunk_item, c->size);
4184 
4185  Status = insert_tree_item(Vcb, Vcb->chunk_root, 0x100, TYPE_CHUNK_ITEM, c->offset, ci, c->size, NULL, Irp);
4186  if (!NT_SUCCESS(Status)) {
4187  ERR("insert_tree_item failed\n");
4188  ExFreePool(ci);
4189  return Status;
4190  }
4191 
4192  if (c->chunk_item->type & BLOCK_FLAG_SYSTEM) {
4193  Status = add_to_bootstrap(Vcb, 0x100, TYPE_CHUNK_ITEM, c->offset, ci, c->size);
4194  if (!NT_SUCCESS(Status)) {
4195  ERR("add_to_bootstrap returned %08x\n", Status);
4196  return Status;
4197  }
4198  }
4199 
4200  // add BLOCK_GROUP_ITEM to tree 2
4201 
4203  if (!bgi) {
4204  ERR("out of memory\n");
4206  }
4207 
4208  bgi->used = c->used;
4209  bgi->chunk_tree = 0x100;
4210  bgi->flags = c->chunk_item->type;
4211 
4212  Status = insert_tree_item(Vcb, Vcb->extent_root, c->offset, TYPE_BLOCK_GROUP_ITEM, c->chunk_item->size, bgi, sizeof(BLOCK_GROUP_ITEM), NULL, Irp);
4213  if (!NT_SUCCESS(Status)) {
4214  ERR("insert_tree_item failed\n");
4215  ExFreePool(bgi);
4216  return Status;
4217  }
4218 
4219  if (c->chunk_item->type & BLOCK_FLAG_RAID0)
4220  factor = c->chunk_item->num_stripes;
4221  else if (c->chunk_item->type & BLOCK_FLAG_RAID10)
4222  factor = c->chunk_item->num_stripes / c->chunk_item->sub_stripes;
4223  else if (c->chunk_item->type & BLOCK_FLAG_RAID5)
4224  factor = c->chunk_item->num_stripes - 1;
4225  else if (c->chunk_item->type & BLOCK_FLAG_RAID6)
4226  factor = c->chunk_item->num_stripes - 2;
4227  else // SINGLE, DUPLICATE, RAID1
4228  factor = 1;
4229 
4230  // add DEV_EXTENTs to tree 4
4231 
4232  cis = (CHUNK_ITEM_STRIPE*)&c->chunk_item[1];
4233 
4234  for (i = 0; i < c->chunk_item->num_stripes; i++) {
4235  DEV_EXTENT* de;
4236 
4238  if (!de) {
4239  ERR("out of memory\n");
4241  }
4242 
4243  de->chunktree = Vcb->chunk_root->id;
4244  de->objid = 0x100;
4245  de->address = c->offset;
4246  de->length = c->chunk_item->size / factor;
4247  de->chunktree_uuid = Vcb->chunk_root->treeholder.tree->header.chunk_tree_uuid;
4248 
4249  Status = insert_tree_item(Vcb, Vcb->dev_root, c->devices[i]->devitem.dev_id, TYPE_DEV_EXTENT, cis[i].offset, de, sizeof(DEV_EXTENT), NULL, Irp);
4250  if (!NT_SUCCESS(Status)) {
4251  ERR("insert_tree_item returned %08x\n", Status);
4252  ExFreePool(de);
4253  return Status;
4254  }
4255 
4256  // FIXME - no point in calling this twice for the same device
4257  Status = update_dev_item(Vcb, c->devices[i], Irp);
4258  if (!NT_SUCCESS(Status)) {
4259  ERR("update_dev_item returned %08x\n", Status);
4260  return Status;
4261  }
4262  }
4263 
4264  c->created = false;
4265  c->oldused = c->used;
4266 
4267  Vcb->superblock.bytes_used += chunk_estimate_phys_size(Vcb, c, c->used);
4268 
4269  return STATUS_SUCCESS;
4270 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PIRP Irp
Definition: csq.h:116
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
Definition: glfuncs.h:178
uint64_t flags
Definition: btrfs.h:404
#define TYPE_CHUNK_ITEM
Definition: btrfs.h:44
LONG NTSTATUS
Definition: precomp.h:26
uint64_t length
Definition: btrfs.h:450
unsigned short int uint16_t
Definition: acefiex.h:54
uint64_t used
Definition: btrfs.h:402
#define ALLOC_TAG
Definition: btrfs_drv.h:91
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
Definition: glfuncs.h:248
#define TYPE_DEV_EXTENT
Definition: btrfs.h:42
#define BLOCK_FLAG_SYSTEM
Definition: shellext.h:76
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS update_dev_item(device_extension *Vcb, device *device, PIRP Irp)
Definition: flushthread.c:4057
#define BLOCK_FLAG_RAID10
Definition: shellext.h:81
#define BLOCK_FLAG_RAID0
Definition: shellext.h:78
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
#define for
Definition: utility.h:88
uint64_t objid
Definition: btrfs.h:448
#define BLOCK_FLAG_RAID6
Definition: shellext.h:83
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)
Definition: treefuncs.c:857
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define TYPE_BLOCK_GROUP_ITEM
Definition: btrfs.h:38
static NTSTATUS add_to_bootstrap(device_extension *Vcb, uint64_t obj_id, uint8_t obj_type, uint64_t offset, void *data, uint16_t size)
Definition: flushthread.c:4124
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
uint64_t chunk_tree
Definition: btrfs.h:403
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
uint64_t chunktree
Definition: btrfs.h:447
BTRFS_UUID chunktree_uuid
Definition: btrfs.h:451
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
uint64_t address
Definition: btrfs.h:449
uint64_t chunk_estimate_phys_size(device_extension *Vcb, chunk *c, uint64_t u)
Definition: btrfs.c:3733

Referenced by update_chunk_usage(), and update_chunks().

◆ delete_root_ref()

static NTSTATUS delete_root_ref ( device_extension Vcb,
uint64_t  subvolid,
uint64_t  parsubvolid,
uint64_t  parinode,
PANSI_STRING  utf8,
PIRP  Irp 
)
static

Definition at line 6087 of file flushthread.c.

6087  {
6088  KEY searchkey;
6089  traverse_ptr tp;
6090  NTSTATUS Status;
6091 
6092  searchkey.obj_id = parsubvolid;
6093  searchkey.obj_type = TYPE_ROOT_REF;
6094  searchkey.offset = subvolid;
6095 
6096  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
6097  if (!NT_SUCCESS(Status)) {
6098  ERR("error - find_item returned %08x\n", Status);
6099  return Status;
6100  }
6101 
6102  if (!keycmp(searchkey, tp.item->key)) {
6103  if (tp.item->size < sizeof(ROOT_REF)) {
6104  ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %u\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(ROOT_REF));
6105  return STATUS_INTERNAL_ERROR;
6106  } else {
6107  ROOT_REF* rr;
6108  ULONG len;
6109 
6110  rr = (ROOT_REF*)tp.item->data;
6111  len = tp.item->size;
6112 
6113  do {
6114  uint16_t itemlen;
6115 
6116  if (len < sizeof(ROOT_REF) || len < offsetof(ROOT_REF, name[0]) + rr->n) {
6117  ERR("(%I64x,%x,%I64x) was truncated\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
6118  break;
6119  }
6120 
6121  itemlen = (uint16_t)offsetof(ROOT_REF, name[0]) + rr->n;
6122 
6123  if (rr->dir == parinode && rr->n == utf8->Length && RtlCompareMemory(rr->name, utf8->Buffer, rr->n) == rr->n) {
6124  uint16_t newlen = tp.item->size - itemlen;
6125 
6127  if (!NT_SUCCESS(Status)) {
6128  ERR("delete_tree_item returned %08x\n", Status);
6129  return Status;
6130  }
6131 
6132  if (newlen == 0) {
6133  TRACE("deleting (%I64x,%x,%I64x)\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
6134  } else {
6135  uint8_t *newrr = ExAllocatePoolWithTag(PagedPool, newlen, ALLOC_TAG), *rroff;
6136 
6137  if (!newrr) {
6138  ERR("out of memory\n");
6140  }
6141 
6142  TRACE("modifying (%I64x,%x,%I64x)\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
6143 
6144  if ((uint8_t*)rr > tp.item->data) {
6145  RtlCopyMemory(newrr, tp.item->data, (uint8_t*)rr - tp.item->data);
6146  rroff = newrr + ((uint8_t*)rr - tp.item->data);
6147  } else {
6148  rroff = newrr;
6149  }
6150 
6151  if ((uint8_t*)&rr->name[rr->n] < tp.item->data + tp.item->size)
6152  RtlCopyMemory(rroff, &rr->name[rr->n], tp.item->size - ((uint8_t*)&rr->name[rr->n] - tp.item->data));
6153 
6154  Status = insert_tree_item(Vcb, Vcb->root_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newrr, newlen, NULL, Irp);
6155  if (!NT_SUCCESS(Status)) {
6156  ERR("insert_tree_item returned %08x\n", Status);
6157  ExFreePool(newrr);
6158  return Status;
6159  }
6160  }
6161 
6162  break;
6163  }
6164 
6165  if (len > itemlen) {
6166  len -= itemlen;
6167  rr = (ROOT_REF*)&rr->name[rr->n];
6168  } else
6169  break;
6170  } while (len > 0);
6171  }
6172  } else {
6173  WARN("could not find ROOT_REF entry for subvol %I64x in %I64x\n", searchkey.offset, searchkey.obj_id);
6174  return STATUS_NOT_FOUND;
6175  }
6176 
6177  return STATUS_SUCCESS;
6178 }
#define TYPE_ROOT_REF
Definition: btrfs.h:30
uint64_t obj_id
Definition: btrfs.h:128
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:129
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
char name[1]
Definition: btrfs.h:443
_In_ PIRP Irp
Definition: csq.h:116
#define keycmp(key1, key2)
Definition: btrfs_drv.h:991
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:415
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
uint16_t n
Definition: btrfs.h:442
uint64_t offset
Definition: btrfs.h:130
uint8_t * data
Definition: btrfs_drv.h:416
uint64_t dir
Definition: btrfs.h:440
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:91
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2855
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define TRACE(s)
Definition: solgame.cpp:4
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
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)
Definition: treefuncs.c:857
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:502
GLenum GLsizei len
Definition: glext.h:6722
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:127
Definition: name.c:36
unsigned int ULONG
Definition: retypes.h:1
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:989

Referenced by flush_fileref().

◆ delete_xattr()

static NTSTATUS delete_xattr ( device_extension Vcb,
LIST_ENTRY batchlist,
root subvol,
uint64_t  inode,
char name,
uint16_t  namelen,
uint32_t  crc32 
)
static

Definition at line 4331 of file flushthread.c.

4332  {
4333  NTSTATUS Status;
4334  uint16_t xasize;
4335  DIR_ITEM* xa;
4336 
4337  TRACE("(%p, %I64x, %I64x, %.*s, %08x)\n", Vcb, subvol->id, inode, namelen, name, crc32);
4338 
4339  xasize = (uint16_t)offsetof(DIR_ITEM, name[0]) + namelen;
4340 
4341  xa = ExAllocatePoolWithTag(PagedPool, xasize, ALLOC_TAG);
4342  if (!xa) {
4343  ERR("out of memory\n");
4345  }
4346 
4347  xa->key.obj_id = 0;
4348  xa->key.obj_type = 0;
4349  xa->key.offset = 0;
4350  xa->transid = Vcb->superblock.generation;
4351  xa->m = 0;
4352  xa->n = namelen;
4353  xa->type = BTRFS_TYPE_EA;
4354  RtlCopyMemory(xa->name, name, namelen);
4355 
4357  if (!NT_SUCCESS(Status)) {
4358  ERR("insert_tree_item_batch returned %08x\n", Status);
4359  ExFreePool(xa);
4360  return Status;
4361  }
4362 
4363  return STATUS_SUCCESS;
4364 }
uint64_t obj_id
Definition: btrfs.h:128
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:129
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
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)
Definition: flushthread.c:4406
LONG NTSTATUS
Definition: precomp.h:26
uint32_t crc32
Definition: btrfs.c:4138
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
GLint namelen
Definition: glext.h:7232
uint64_t offset
Definition: btrfs.h:130
Definition: fs.h:78
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint16_t m
Definition: btrfs.h:258
KEY key
Definition: btrfs.h:256
char name[1]
Definition: btrfs.h:261
#define offsetof(TYPE, MEMBER)
uint8_t type
Definition: btrfs.h:260
#define TRACE(s)
Definition: solgame.cpp:4
#define TYPE_XATTR_ITEM
Definition: btrfs.h:22
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
struct _root * subvol
Definition: btrfs_drv.h:284
Definition: name.c:36
uint64_t transid
Definition: btrfs.h:257
#define BTRFS_TYPE_EA
Definition: btrfs.h:253
uint16_t n
Definition: btrfs.h:259
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by flush_fcb().

◆ do_flush()

static void do_flush ( device_extension Vcb)
static

Definition at line 7686 of file flushthread.c.

7686  {
7687  NTSTATUS Status;
7688 
7689  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
7690 
7691  if (Vcb->need_write && !Vcb->readonly)
7692  Status = do_write(Vcb, NULL);
7693  else
7695 
7696  free_trees(Vcb);
7697 
7698  if (!NT_SUCCESS(Status))
7699  ERR("do_write returned %08x\n", Status);
7700 
7701  ExReleaseResourceLite(&Vcb->tree_lock);
7702 }
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7667
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
smooth NULL
Definition: ftsmooth.c:416
void free_trees(device_extension *Vcb)
Definition: treefuncs.c:793
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
return STATUS_SUCCESS
Definition: btrfs.c:2938

Referenced by _Function_class_().

◆ do_splits()

static NTSTATUS do_splits ( device_extension Vcb,
PIRP  Irp,
LIST_ENTRY rollback 
)
static

Definition at line 3620 of file flushthread.c.

3620  {
3621  ULONG level, max_level;
3622  uint32_t min_size;
3623  bool empty, done_deletions = false;
3624  NTSTATUS Status;
3625  tree* t;
3626 
3627  TRACE("(%p)\n", Vcb);
3628 
3629  max_level = 0;
3630 
3631  for (level = 0; level <= 255; level++) {
3632  LIST_ENTRY *le, *nextle;
3633 
3634  empty = true;
3635 
3636  TRACE("doing level %u\n", level);
3637 
3638  le = Vcb->trees.Flink;
3639 
3640  while (le != &Vcb->trees) {
3642 
3643  nextle = le->Flink;
3644 
3645  if (t->write && t->header.level == level) {
3646  empty = false;
3647 
3648  if (t->header.num_items == 0) {
3649  if (t->parent) {
3650  done_deletions = true;
3651 
3652  TRACE("deleting tree in root %I64x\n", t->root->id);
3653 
3654  t->root->root_item.bytes_used -= Vcb->superblock.node_size;
3655 
3656  if (t->has_new_address) { // delete associated EXTENT_ITEM
3657  Status = reduce_tree_extent(Vcb, t->new_address, t, t->parent->header.tree_id, t->header.level, Irp, rollback);
3658 
3659  if (!NT_SUCCESS(Status)) {
3660  ERR("reduce_tree_extent returned %08x\n", Status);
3661  return Status;
3662  }
3663 
3664  t->has_new_address = false;
3665  } else if (t->has_address) {
3666  Status = reduce_tree_extent(Vcb,t->header.address, t, t->parent->header.tree_id, t->header.level, Irp, rollback);
3667 
3668  if (!NT_SUCCESS(Status)) {
3669  ERR("reduce_tree_extent returned %08x\n", Status);
3670  return Status;
3671  }
3672 
3673  t->has_address = false;
3674  }
3675 
3676  if (!t->paritem->ignore) {
3677  t->paritem->ignore = true;
3678  t->parent->header.num_items--;
3679  t->parent->size -= sizeof(internal_node);
3680  }
3681 
3682  RemoveEntryList(&t->paritem->list_entry);
3683  ExFreePool(t->paritem);
3684  t->paritem = NULL;
3685 
3686  free_tree(t);
3687  } else if (t->header.level != 0) {
3688  if (t->has_new_address) {
3689  Status = update_extent_level(Vcb, t->new_address, t, 0, Irp);
3690 
3691  if (!NT_SUCCESS(Status)) {
3692  ERR("update_extent_level returned %08x\n", Status);
3693  return Status;
3694  }
3695  }
3696 
3697  t->header.level = 0;
3698  }
3699  } else if (t->size > Vcb->superblock.node_size - sizeof(tree_header)) {
3700  TRACE("splitting overlarge tree (%x > %x)\n", t->size, Vcb->superblock.node_size - sizeof(tree_header));
3701 
3702  if (!t->updated_extents && t->has_address) {
3704  if (!NT_SUCCESS(Status)) {
3705  ERR("update_tree_extents_recursive returned %08x\n", Status);
3706  return Status;
3707  }
3708  }
3709 
3710  Status = split_tree(Vcb, t);
3711 
3712  if (!NT_SUCCESS(Status)) {
3713  ERR("split_tree returned %08x\n", Status);
3714  return Status;
3715  }
3716  }
3717  }
3718 
3719  le = nextle;
3720  }
3721 
3722  if (!empty) {
3723  max_level = level;
3724  } else {
3725  TRACE("nothing found for level %u\n", level);
3726  break;
3727  }
3728  }
3729 
3730  min_size = (Vcb->superblock.node_size - sizeof(tree_header)) / 2;
3731 
3732  for (level = 0; level <= max_level; level++) {
3733  LIST_ENTRY* le;
3734 
3735  le = Vcb->trees.Flink;
3736 
3737  while (le != &Vcb->trees) {
3739 
3740  if (t->write && t->header.level == level && t->header.num_items > 0 && t->parent && t->size < min_size &&
3741  t->root->id != BTRFS_ROOT_FREE_SPACE && is_tree_unique(Vcb, t, Irp)) {
3742  bool done;
3743 
3744  do {
3745  Status = try_tree_amalgamate(Vcb, t, &done, &done_deletions, Irp, rollback);
3746  if (!NT_SUCCESS(Status)) {
3747  ERR("try_tree_amalgamate returned %08x\n", Status);
3748  return Status;
3749  }
3750  } while (done && t->size < min_size);
3751  }
3752 
3753  le = le->Flink;
3754  }
3755  }
3756 
3757  // simplify trees if top tree only has one entry
3758 
3759  if (done_deletions) {
3760  for (level = max_level; level > 0; level--) {
3761  LIST_ENTRY *le, *nextle;
3762 
3763  le = Vcb->trees.Flink;
3764  while (le != &Vcb->trees) {
3765  nextle = le->Flink;
3767 
3768  if (t->write && t->header.level == level) {
3769  if (!t->parent && t->header.num_items == 1) {
3770  LIST_ENTRY* le2 = t->itemlist.Flink;
3771  tree_data* td = NULL;
3772  tree* child_tree = NULL;
3773 
3774  while (le2 != &t->itemlist) {
3776  if (!td->ignore)
3777  break;
3778  le2 = le2->Flink;
3779  }
3780 
3781  TRACE("deleting top-level tree in root %I64x with one item\n", t->root->id);
3782 
3783  if (t->has_new_address) { // delete associated EXTENT_ITEM
3784  Status = reduce_tree_extent(Vcb, t->new_address, t, t->header.tree_id, t->header.level, Irp, rollback);
3785 
3786  if (!NT_SUCCESS(Status)) {
3787  ERR("reduce_tree_extent returned %08x\n", Status);
3788  return Status;
3789  }
3790 
3791  t->has_new_address = false;
3792  } else if (t->has_address) {
3793  Status = reduce_tree_extent(Vcb,t->header.address, t, t->header.tree_id, t->header.level, Irp, rollback);
3794 
3795  if (!NT_SUCCESS(Status)) {
3796  ERR("reduce_tree_extent returned %08x\n", Status);
3797  return Status;
3798  }
3799 
3800  t->has_address = false;
3801  }
3802 
3803  if (!td->treeholder.tree) { // load first item if not already loaded
3804  KEY searchkey = {0,0,0};
3805  traverse_ptr tp;
3806 
3807  Status = find_item(Vcb, t->root, &tp, &searchkey, false, Irp);
3808  if (!NT_SUCCESS(Status)) {
3809  ERR("error - find_item returned %08x\n", Status);
3810  return Status;
3811  }
3812  }
3813 
3814  child_tree = td->treeholder.tree;
3815 
3816  if (child_tree) {
3817  child_tree->parent = NULL;
3818  child_tree->paritem = NULL;
3819  }
3820 
3821  t->root->root_item.bytes_used -= Vcb->superblock.node_size;
3822 
3823  free_tree(t);
3824 
3825  if (child_tree)
3826  child_tree->root->treeholder.tree = child_tree;
3827  }
3828  }
3829 
3830  le = nextle;
3831  }
3832  }
3833  }
3834 
3835  return STATUS_SUCCESS;
3836 }
static NTSTATUS split_tree(device_extension *Vcb, tree *t)
Definition: flushthread.c:3169
static NTSTATUS update_extent_level(device_extension *Vcb, uint64_t address, tree *t, uint8_t level, PIRP Irp)
Definition: flushthread.c:3502
GLint level
Definition: gl.h:1546
struct _root * root
Definition: btrfs_drv.h:434
_In_ PIRP Irp
Definition: csq.h:116
LONG NTSTATUS
Definition: precomp.h:26
tree_holder treeholder
Definition: btrfs_drv.h:412
GLdouble GLdouble t
Definition: gl.h:2047
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
struct _tree * tree
Definition: btrfs_drv.h:402
tree_data * paritem
Definition: btrfs_drv.h:433
smooth NULL
Definition: ftsmooth.c:416
struct _tree * parent
Definition: btrfs_drv.h:432
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2855
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define TRACE(s)
Definition: solgame.cpp:4
void free_tree(tree *t)
Definition: treefuncs.c:260
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
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)
Definition: flushthread.c:943
#define Vcb
Definition: cdprocs.h:1425
static NTSTATUS update_tree_extents_recursive(device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:3602
bool is_tree_unique(device_extension *Vcb, tree *t, PIRP Irp)
Definition: flushthread.c:3209
Definition: typedefs.h:117
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
bool ignore
Definition: btrfs_drv.h:408
Definition: btrfs.h:127
Definition: list.h:27
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1314
BOOL empty
Definition: button.c:170
UINT32 uint32_t
Definition: types.h:75
#define BTRFS_ROOT_FREE_SPACE
Definition: btrfs.h:58
unsigned int ULONG
Definition: retypes.h:1
return STATUS_SUCCESS
Definition: btrfs.c:2938
static NTSTATUS try_tree_amalgamate(device_extension *Vcb, tree *t, bool *done, bool *done_deletions, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:3272
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by do_write2().

◆ do_tree_writes()

NTSTATUS do_tree_writes ( device_extension Vcb,
LIST_ENTRY tree_writes,
bool  no_free 
)

Definition at line 1607 of file flushthread.c.

1607  {
1608  chunk* c;
1609  LIST_ENTRY* le;
1610  tree_write* tw;
1611  NTSTATUS Status;
1612  ULONG i, num_bits;
1613  write_data_context* wtc;
1614  ULONG bit_num = 0;
1615  bool raid56 = false;
1616 
1617  // merge together runs
1618  c = NULL;
1619  le = tree_writes->Flink;
1620  while (le != tree_writes) {
1622 
1623  if (!c || tw->address < c->offset || tw->address >= c->offset + c->chunk_item->size)
1625  else {
1627 
1628  if (tw->address == tw2->address + tw2->length) {
1630 
1631  if (!data) {
1632  ERR("out of memory\n");
1634  }
1635 
1636  RtlCopyMemory(data, tw2->data, tw2->length);
1637  RtlCopyMemory(&data[tw2->length], tw->data, tw->length);
1638 
1639  if (!no_free || tw2->allocated)
1640  ExFreePool(tw2->data);
1641 
1642  tw2->data = data;
1643  tw2->length += tw->length;
1644  tw2->allocated = true;
1645 
1646  if (!no_free || tw->allocated)
1647  ExFreePool(tw->data);
1648 
1650  ExFreePool(tw);
1651 
1652  le = tw2->list_entry.Flink;
1653  continue;
1654  }
1655  }
1656 
1657  tw->c = c;
1658 
1659  if (c->chunk_item->type & (BLOCK_FLAG_RAID5 | BLOCK_FLAG_RAID6))
1660  raid56 = true;
1661 
1662  le = le->Flink;
1663  }
1664 
1665  num_bits = 0;
1666 
1667  le = tree_writes->Flink;
1668  while (le != tree_writes) {
1670 
1671  num_bits++;
1672 
1673  le = le->Flink;
1674  }
1675 
1676  wtc = ExAllocatePoolWithTag(NonPagedPool, sizeof(write_data_context) * num_bits, ALLOC_TAG);
1677  if (!wtc) {
1678  ERR("out of memory\n");
1680  }
1681 
1682  le = tree_writes->Flink;
1683 
1684  while (le != tree_writes) {
1686 
1687  TRACE("address: %I64x, size: %x\n", tw->address, tw->length);
1688 
1689  KeInitializeEvent(&wtc[bit_num].Event, NotificationEvent, false);
1690  InitializeListHead(&wtc[bit_num].stripes);
1691  wtc[bit_num].need_wait = false;
1692  wtc[bit_num].stripes_left = 0;
1693  wtc[bit_num].parity1 = wtc[bit_num].parity2 = wtc[bit_num].scratch = NULL;
1694  wtc[bit_num].mdl = wtc[bit_num].parity1_mdl = wtc[bit_num].parity2_mdl = NULL;
1695 
1696  Status = write_data(Vcb, tw->address, tw->data, tw->length, &wtc[bit_num], NULL, NULL, false, 0, HighPagePriority);
1697  if (!NT_SUCCESS(Status)) {
1698  ERR("write_data returned %08x\n", Status);
1699 
1700  for (i = 0; i < num_bits; i++) {
1701  free_write_data_stripes(&wtc[i]);
1702  }
1703  ExFreePool(wtc);
1704 
1705  return Status;
1706  }
1707 
1708  bit_num++;
1709 
1710  le = le->Flink;
1711  }
1712 
1713  for (i = 0; i < num_bits; i++) {
1714  if (wtc[i].stripes.Flink != &wtc[i].stripes) {
1715  // launch writes and wait
1716  le = wtc[i].stripes.Flink;
1717  while (le != &wtc[i].stripes) {
1719 
1720  if (stripe->status != WriteDataStatus_Ignore) {
1721  wtc[i].need_wait = true;
1723  }
1724 
1725  le = le->Flink;
1726  }
1727  }
1728  }
1729 
1730  for (i = 0; i < num_bits; i++) {
1731  if (wtc[i].need_wait)
1733  }
1734 
1735  for (i = 0; i < num_bits; i++) {
1736  le = wtc[i].stripes.Flink;
1737  while (le != &wtc[i].stripes) {
1739 
1740  if (stripe->status != WriteDataStatus_Ignore && !NT_SUCCESS(stripe->iosb.Status)) {
1741  Status = stripe->iosb.Status;
1743  break;
1744  }
1745 
1746  le = le->Flink;
1747  }
1748 
1749  free_write_data_stripes(&wtc[i]);
1750  }
1751 
1752  ExFreePool(wtc);
1753 
1754  if (raid56) {
1755  c = NULL;
1756 
1757  le = tree_writes->Flink;
1758  while (le != tree_writes) {
1760 
1761  if (tw->c != c) {
1762  c = tw->c;
1763 
1764  ExAcquireResourceExclusiveLite(&c->partial_stripes_lock, true);
1765 
1766  while (!IsListEmpty(&c->partial_stripes)) {
1768 
1769  Status = flush_partial_stripe(Vcb, c, ps);
1770 
1771  if (ps->bmparr)
1772  ExFreePool(ps->bmparr);
1773 
1774  ExFreePool(ps);
1775 
1776  if (!NT_SUCCESS(Status)) {
1777  ERR("flush_partial_stripe returned %08x\n", Status);
1778  ExReleaseResourceLite(&c->partial_stripes_lock);
1779  return Status;
1780  }
1781  }
1782 
1783  ExReleaseResourceLite(&c->partial_stripes_lock);
1784  }
1785 
1786  le = le->Flink;
1787  }
1788  }
1789 
1790  return STATUS_SUCCESS;
1791 }
ULONG * bmparr
Definition: btrfs_drv.h:547
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
chunk * c
Definition: btrfs_drv.h:924
void free_write_data_stripes(write_data_context *wtc)
Definition: write.c:2291
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
PDEVICE_OBJECT devobj
Definition: btrfs_drv.h:518
LONG NTSTATUS
Definition: precomp.h:26
Definition: write.c:111
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define ALLOC_TAG
Definition: btrfs_drv.h:91
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
Definition: glfuncs.h:248
uint8_t * scratch
Definition: btrfs_drv.h:916
bool allocated
Definition: btrfs_drv.h:925
smooth NULL
Definition: ftsmooth.c:416
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
uint8_t * data
Definition: btrfs_drv.h:923
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define TRACE(s)
Definition: solgame.cpp:4
uint32_t length
Definition: btrfs_drv.h:922
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
uint8_t * parity1
Definition: btrfs_drv.h:916
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
#define BLOCK_FLAG_RAID6
Definition: shellext.h:83
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
LIST_ENTRY list_entry
Definition: btrfs_drv.h:926
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Definition: typedefs.h:117
uint64_t address
Definition: btrfs_drv.h:921
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
device * device
Definition: write.c:113
chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address)
Definition: write.c:89
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
void log_device_error(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ int error)
Definition: btrfs.c:5543
NTSTATUS flush_partial_stripe(device_extension *Vcb, chunk *c, partial_stripe *ps)
Definition: flushthread.c:5799
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
Definition: list.h:27
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
LIST_ENTRY stripes
Definition: btrfs_drv.h:913
#define BTRFS_DEV_STAT_WRITE_ERRORS
Definition: btrfs.h:517
#define c
Definition: ke_i.h:80
unsigned int ULONG
Definition: retypes.h:1
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
return STATUS_SUCCESS
Definition: btrfs.c:2938
uint8_t * parity2
Definition: btrfs_drv.h:916
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
static int write_data(void *user_ptr, void *user_data, int length)
Definition: gifformat.c:1904

Referenced by write_metadata_items(), and write_trees().

◆ do_write()

NTSTATUS do_write ( device_extension Vcb,
PIRP  Irp 
)

Definition at line 7667 of file flushthread.c.

7667  {
7669  NTSTATUS Status;
7670 
7672 
7674 
7675  if (!NT_SUCCESS(Status)) {
7676  ERR("do_write2 returned %08x, dropping into readonly mode\n", Status);
7677  Vcb->readonly = true;
7680  } else
7682 
7683  return Status;
7684 }
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback)
Definition: treefuncs.c:1049
void clear_rollback(LIST_ENTRY *rollback)
Definition: treefuncs.c:1028
_In_ PIRP Irp
Definition: csq.h:116
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
static NTSTATUS do_write2(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:7270
Definition: typedefs.h:117
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1314
#define FSRTL_VOLUME_FORCED_CLOSED
Definition: fsrtltypes.h:98

Referenced by _Function_class_(), add_balance_item(), add_device(), balance_data_chunk(), balance_metadata_chunk(), dismount_volume(), do_create_snapshot(), do_flush(), finish_removing_device(), invalidate_volumes(), lock_volume(), pnp_query_remove_device(), remove_balance_item(), and try_consolidation().

◆ do_write2()

static NTSTATUS do_write2 ( device_extension Vcb,
PIRP  Irp,
LIST_ENTRY rollback 
)
static

Definition at line 7270 of file flushthread.c.

7270  {
7271  NTSTATUS Status;
7272  LIST_ENTRY *le, batchlist;
7273  bool cache_changed = false;
7275  bool no_cache = false;
7276 #ifdef DEBUG_FLUSH_TIMES
7277  uint64_t filerefs = 0, fcbs = 0;
7278  LARGE_INTEGER freq, time1, time2;
7279 #endif
7280 #ifdef DEBUG_WRITE_LOOPS
7281  UINT loops = 0;
7282 #endif
7283 
7284  TRACE("(%p)\n", Vcb);
7285 
7286  InitializeListHead(&batchlist);
7287 
7288 #ifdef DEBUG_FLUSH_TIMES
7289  time1 = KeQueryPerformanceCounter(&freq);
7290 #endif
7291 
7293  if (!NT_SUCCESS(Status)) {
7294  ERR("check_for_orphans returned %08x\n", Status);
7295  return Status;
7296  }
7297 
7298  ExAcquireResourceExclusiveLite(&Vcb->dirty_filerefs_lock, true);
7299 
7300  while (!IsListEmpty(&Vcb->dirty_filerefs)) {
7302 
7303  flush_fileref(fr, &batchlist, Irp);
7304  free_fileref(fr);
7305 
7306 #ifdef DEBUG_FLUSH_TIMES
7307  filerefs++;
7308 #endif
7309  }
7310 
7311  ExReleaseResourceLite(&Vcb->dirty_filerefs_lock);
7312 
7313  Status = commit_batch_list(Vcb, &batchlist, Irp);
7314  if (!NT_SUCCESS(Status)) {
7315  ERR("commit_batch_list returned %08x\n", Status);
7316  return Status;
7317  }
7318 
7319 #ifdef DEBUG_FLUSH_TIMES
7321 
7322  ERR("flushed %I64u filerefs in %I64u (freq = %I64u)\n", filerefs, time2.QuadPart - time1.QuadPart, freq.QuadPart);
7323 
7324  time1 = KeQueryPerformanceCounter(&freq);
7325 #endif
7326 
7327  // We process deleted streams first, so we don't run over our xattr
7328  // limit unless we absolutely have to.
7329  // We also process deleted normal files, to avoid any problems
7330  // caused by inode collisions.
7331 
7332  ExAcquireResourceExclusiveLite(&Vcb->dirty_fcbs_lock, true);
7333 
7334  le = Vcb->dirty_fcbs.Flink;
7335  while (le != &Vcb->dirty_fcbs) {
7336  fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_dirty);
7337  LIST_ENTRY* le2 = le->Flink;
7338 
7339  if (fcb->deleted) {
7340  ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
7341  Status = flush_fcb(fcb, false, &batchlist, Irp);
7342  ExReleaseResourceLite(fcb->Header.Resource);
7343 
7344  free_fcb(fcb);
7345 
7346  if (!NT_SUCCESS(Status)) {
7347  ERR("flush_fcb returned %08x\n", Status);
7348  clear_batch_list(Vcb, &batchlist);
7349  ExReleaseResourceLite(&Vcb->dirty_fcbs_lock);
7350  return Status;
7351  }
7352 
7353 #ifdef DEBUG_FLUSH_TIMES
7354  fcbs++;
7355 #endif
7356  }
7357 
7358  le = le2;
7359  }
7360 
7361  Status = commit_batch_list(Vcb, &batchlist, Irp);
7362  if (!NT_SUCCESS(Status)) {
7363  ERR("commit_batch_list returned %08x\n", Status);
7364  ExReleaseResourceLite(&Vcb->dirty_fcbs_lock);
7365  return Status;
7366  }
7367 
7368  le = Vcb->dirty_fcbs.Flink;
7369  while (le != &Vcb->dirty_fcbs) {
7370  fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_dirty);
7371  LIST_ENTRY* le2 = le->Flink;
7372 
7373  if (fcb->subvol != Vcb->root_root) {
7374  ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
7375  Status = flush_fcb(fcb, false, &batchlist, Irp);
7376  ExReleaseResourceLite(fcb->Header.Resource);
7377  free_fcb(fcb);
7378 
7379  if (!NT_SUCCESS(Status)) {
7380  ERR("flush_fcb returned %08x\n", Status);
7381  ExReleaseResourceLite(&Vcb->dirty_fcbs_lock);
7382  return Status;
7383  }
7384 
7385 #ifdef DEBUG_FLUSH_TIMES
7386  fcbs++;
7387 #endif
7388  }
7389 
7390  le = le2;
7391  }
7392 
7393  ExReleaseResourceLite(&Vcb->dirty_fcbs_lock);
7394 
7395  Status = commit_batch_list(Vcb, &batchlist, Irp);
7396  if (!NT_SUCCESS(Status)) {
7397  ERR("commit_batch_list returned %08x\n", Status);
7398  return Status;
7399  }
7400 
7401 #ifdef DEBUG_FLUSH_TIMES
7403 
7404  ERR("flushed %I64u fcbs in %I64u (freq = %I64u)\n", filerefs, time2.QuadPart - time1.QuadPart, freq.QuadPart);
7405 #endif
7406 
7407  // no need to get dirty_subvols_lock here, as we have tree_lock exclusively
7408  while (!IsListEmpty(&Vcb->dirty_subvols)) {
7410 
7411  Status = flush_subvol(Vcb, r, Irp);
7412  if (!NT_SUCCESS(Status)) {
7413  ERR("flush_subvol returned %08x\n", Status);
7414  return Status;
7415  }
7416  }
7417 
7418  if (!IsListEmpty(&Vcb->drop_roots)) {
7420 
7421  if (!NT_SUCCESS(Status)) {
7422  ERR("drop_roots returned %08x\n", Status);
7423  return Status;
7424  }
7425  }
7426 
7427  Status = update_chunks(Vcb, &batchlist, Irp, rollback);
7428 
7429  if (!NT_SUCCESS(Status)) {
7430  ERR("update_chunks returned %08x\n", Status);
7431  return Status;
7432  }
7433 
7434  Status = commit_batch_list(Vcb, &batchlist, Irp);
7435 
7436  // If only changing superblock, e.g. changing label, we still need to rewrite
7437  // the root tree so the generations match, otherwise you won't be able to mount on Linux.
7438  if (!Vcb->root_root->treeholder.tree || !Vcb->root_root->treeholder.tree->write) {
7439  KEY searchkey;
7440 
7441  traverse_ptr tp;
7442 
7443  searchkey.obj_id = 0;
7444  searchkey.obj_type = 0;
7445  searchkey.offset = 0;
7446 
7447  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
7448  if (!NT_SUCCESS(Status)) {
7449  ERR("error - find_item returned %08x\n", Status);
7450  return Status;
7451  }
7452 
7453  Vcb->root_root->treeholder.tree->write = true;
7454  }
7455 
7456  // make sure we always update the extent tree
7458  if (!NT_SUCCESS(Status)) {
7459  ERR("add_root_item_to_cache returned %08x\n", Status);
7460  return Status;
7461  }
7462 
7463  if (Vcb->stats_changed) {
7464  le = Vcb->devices.Flink;
7465  while (le != &Vcb->devices) {
7467 
7468  if (dev->stats_changed) {
7470  if (!NT_SUCCESS(Status)) {
7471  ERR("flush_changed_dev_stats returned %08x\n", Status);
7472  return Status;
7473  }
7474  dev->stats_changed = false;
7475  }
7476 
7477  le = le->Flink;
7478  }
7479 
7480  Vcb->stats_changed = false;
7481  }
7482 
7483  do {
7484  Status = add_parents(Vcb, Irp);
7485  if (!NT_SUCCESS(Status)) {
7486  ERR("add_parents returned %08x\n", Status);
7487  goto end;
7488  }
7489 
7491  if (!NT_SUCCESS(Status)) {
7492  ERR("allocate_tree_extents returned %08x\n", Status);
7493  goto end;
7494  }
7495 
7497  if (!NT_SUCCESS(Status)) {
7498  ERR("do_splits returned %08x\n", Status);
7499  goto end;
7500  }
7501 
7503  if (!NT_SUCCESS(Status)) {
7504  ERR("update_chunk_usage returned %08x\n", Status);
7505  goto end;
7506  }
7507 
7508  if (!(Vcb->superblock.compat_ro_flags & BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE)) {
7509  if (!no_cache) {
7510  Status = allocate_cache(Vcb, &cache_changed, Irp, rollback);
7511  if (!NT_SUCCESS(Status)) {
7512  WARN("allocate_cache returned %08x\n", Status);
7513  no_cache = true;
7514  cache_changed = false;
7515  }
7516  }
7517  } else {
7519  if (!NT_SUCCESS(Status)) {
7520  ERR("update_chunk_caches_tree returned %08x\n", Status);
7521  goto end;
7522  }
7523  }
7524 
7525 #ifdef DEBUG_WRITE_LOOPS
7526  loops++;
7527 
7528  if (cache_changed)
7529  ERR("cache has changed, looping again\n");
7530 #endif
7531  } while (cache_changed || !trees_consistent(Vcb));
7532 
7533 #ifdef DEBUG_WRITE_LOOPS
7534  ERR("%u loops\n", loops);
7535 #endif
7536 
7537  TRACE("trees consistent\n");
7538 
7539  Status = update_root_root(Vcb, no_cache, Irp, rollback);
7540  if (!NT_SUCCESS(Status)) {
7541  ERR("update_root_root returned %08x\n", Status);
7542  goto end;
7543  }
7544 
7545  Status = write_trees(Vcb, Irp);
7546  if (!NT_SUCCESS(Status)) {
7547  ERR("write_trees returned %08x\n", Status);
7548  goto end;
7549  }
7550 
7552  if (!NT_SUCCESS(Status)) {
7553  ERR("test_not_full returned %08x\n", Status);
7554  goto end;
7555  }
7556 
7557 #ifdef DEBUG_PARANOID
7558  le = Vcb->trees.Flink;
7559  while (le != &Vcb->trees) {
7561  KEY searchkey;
7562  traverse_ptr tp;
7563 
7564  searchkey.obj_id = t->header.address;
7565  searchkey.obj_type = TYPE_METADATA_ITEM;
7566  searchkey.offset = 0xffffffffffffffff;
7567 
7568  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
7569  if (!NT_SUCCESS(Status)) {
7570  ERR("error - find_item returned %08x\n", Status);
7571  goto end;
7572  }
7573 
7574  if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
7575  searchkey.obj_id = t->header.address;
7576  searchkey.obj_type = TYPE_EXTENT_ITEM;
7577  searchkey.offset = 0xffffffffffffffff;
7578 
7579  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
7580  if (!NT_SUCCESS(Status)) {
7581  ERR("error - find_item returned %08x\n", Status);
7582  goto end;
7583  }
7584 
7585  if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
7586  ERR("error - could not find entry in extent tree for tree at %I64x\n", t->header.address);
7588  goto end;
7589  }
7590  }
7591 
7592  le = le->Flink;
7593  }
7594 #endif
7595 
7596  Vcb->superblock.cache_generation = Vcb->superblock.generation;
7597 
7598  if (!Vcb->options.no_barrier)
7600 
7602  if (!NT_SUCCESS(Status)) {
7603  ERR("write_superblocks returned %08x\n", Status);
7604  goto end;
7605  }
7606 
7607  vde = Vcb->vde;
7608 
7609  if (vde) {
7610  pdo_device_extension* pdode = vde->pdode;
7611 
7612  ExAcquireResourceSharedLite(&pdode->child_lock, true);
7613 
7614  le = pdode->children.Flink;
7615 
7616  while (le != &pdode->children) {
7618 
7619  vc->generation = Vcb->superblock.generation;
7620  le = le->Flink;
7621  }
7622 
7624  }
7625 
7627 
7628  le = Vcb->chunks.Flink;
7629  while (le != &Vcb->chunks) {
7631 
7632  c->changed = false;
7633  c->space_changed = false;
7634 
7635  le = le->Flink;
7636  }
7637 
7638  Vcb->superblock.generation++;
7639 
7641 
7642  le = Vcb->trees.Flink;
7643  while (le != &Vcb->trees) {
7645 
7646  t->write = false;
7647 
7648  le = le->Flink;
7649  }
7650 
7651  Vcb->need_write = false;
7652 
7653  while (!IsListEmpty(&Vcb->drop_roots)) {
7655 
7656  ExDeleteResourceLite(&r->nonpaged->load_tree_lock);
7657  ExFreePool(r->nonpaged);
7658  ExFreePool(r);
7659  }
7660 
7661 end:
7662  TRACE("do_write returning %08x\n", Status);
7663 
7664  return Status;
7665 }
static NTSTATUS allocate_tree_extents(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:1452
uint64_t obj_id
Definition: btrfs.h:128
static NTSTATUS check_for_orphans(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7243
LARGE_INTEGER NTAPI KeQueryPerformanceCounter(IN PLARGE_INTEGER PerformanceFreq)
Definition: timer.c:138
static NTSTATUS add_parents(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:595
uint8_t obj_type
Definition: btrfs.h:129
static NTSTATUS flush_fileref(file_ref *fileref, LIST_ENTRY *batchlist, PIRP Irp)
Definition: flushthread.c:6365
static NTSTATUS update_root_root(device_extension *Vcb, bool no_cache, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:1544
static NTSTATUS update_chunk_usage(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:2761
static bool trees_consistent(device_extension *Vcb)
Definition: flushthread.c:558
void free_fcb(_Inout_ fcb *fcb)
Definition: btrfs.c:1653
_In_ PIRP Irp
Definition: csq.h:116
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
GLdouble GLdouble t
Definition: gl.h:2047
static void clean_space_cache(device_extension *Vcb)
Definition: flushthread.c:393
NTSTATUS NTAPI ExDeleteResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1456
NTSTATUS flush_fcb(fcb *fcb, bool cache, LIST_ENTRY *batchlist, PIRP Irp)
Definition: flushthread.c:4776
GLuint GLuint end
Definition: gl.h:1545
#define TYPE_METADATA_ITEM
Definition: btrfs.h:32
static NTSTATUS do_splits(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:3620
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
uint64_t offset
Definition: btrfs.h:130
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
NTSTATUS update_chunk_caches_tree(device_extension *Vcb, PIRP Irp)
Definition: free-space.c:1916
uint64_t generation
Definition: btrfs_drv.h:832
Definition: devices.h:37
static NTSTATUS drop_roots(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:4036
static NTSTATUS flush_changed_dev_stats(device_extension *Vcb, device *dev, PIRP Irp)
Definition: flushthread.c:6848
static NTSTATUS test_not_full(device_extension *Vcb)
Definition: flushthread.c:7019
static NTSTATUS update_chunks(device_extension *Vcb, LIST_ENTRY *batchlist, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:5974
smooth NULL
Definition: ftsmooth.c:416
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:31
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
struct pdo_device_extension * pdode
Definition: btrfs_drv.h:853
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
NTSTATUS commit_batch_list(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *batchlist, PIRP Irp)
Definition: treefuncs.c:2280
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2855
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:279
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define TRACE(s)
Definition: solgame.cpp:4
void clear_batch_list(device_extension *Vcb, LIST_ENTRY *batchlist)
Definition: treefuncs.c:1203
static NTSTATUS write_trees(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:1793
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static NTSTATUS write_superblocks(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:2279
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
static NTSTATUS add_root_item_to_cache(device_extension *Vcb, uint64_t root, PIRP Irp)
Definition: flushthread.c:6313
ERESOURCE child_lock
Definition: btrfs_drv.h:871
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
static NTSTATUS flush_subvol(device_extension *Vcb, root *r, PIRP Irp)
Definition: flushthread.c:6892
tree_data * item
Definition: btrfs_drv.h:502
#define BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE
Definition: btrfs.h:103
Definition: typedefs.h:117
Status
Definition: gdiplustypes.h:24
NTSTATUS allocate_cache(device_extension *Vcb, bool *changed, PIRP Irp, LIST_ENTRY *rollback)
Definition: free-space.c:1378
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:127
UINT64 uint64_t
Definition: types.h:77
bool deleted
Definition: btrfs_drv.h:291
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
struct _root * subvol
Definition: btrfs_drv.h:284
Definition: list.h:27
unsigned int UINT
Definition: ndis.h:50
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1314
void free_fileref(_Inout_ file_ref *fr)
Definition: btrfs.c:1768
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
static void flush_disk_caches(device_extension *Vcb)
Definition: flushthread.c:6752
#define BTRFS_ROOT_EXTENT
Definition: btrfs.h:51
LIST_ENTRY children
Definition: btrfs_drv.h:872
return STATUS_SUCCESS
Definition: btrfs.c:2938
LIST_ENTRY list_entry_dirty
Definition: btrfs_drv.h:334
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
LONGLONG QuadPart
Definition: typedefs.h:112

Referenced by do_write().

◆ drop_chunk()

static NTSTATUS drop_chunk ( device_extension Vcb,
chunk c,
LIST_ENTRY batchlist,
PIRP  Irp,
LIST_ENTRY rollback 
)
static

Definition at line 5383 of file flushthread.c.

5383  {
5384  NTSTATUS Status;
5385  KEY searchkey;
5386  traverse_ptr tp;
5387  uint64_t i, factor;
5388 #ifdef __REACTOS__
5389  uint64_t phys_used;
5390 #endif
5391  CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&c->chunk_item[1];;
5392 
5393  TRACE("dropping chunk %I64x\n", c->offset);
5394 
5395  if (c->chunk_item->type & BLOCK_FLAG_RAID0)
5396  factor = c->chunk_item->num_stripes;
5397  else if (c->chunk_item->type & BLOCK_FLAG_RAID10)
5398  factor = c->chunk_item->num_stripes / c->chunk_item->sub_stripes;
5399  else if (c->chunk_item->type & BLOCK_FLAG_RAID5)
5400  factor = c->chunk_item->num_stripes - 1;
5401  else if (c->chunk_item->type & BLOCK_FLAG_RAID6)
5402  factor = c->chunk_item->num_stripes - 2;
5403  else // SINGLE, DUPLICATE, RAID1
5404  factor = 1;
5405 
5406  // do TRIM
5407  if (Vcb->trim && !Vcb->options.no_trim) {
5408  uint64_t len = c->chunk_item->size / factor;
5409 
5410  for (i = 0; i < c->chunk_item->num_stripes; i++) {
5411  if (c->devices[i] && c->devices[i]->devobj && !c->devices[i]->readonly && c->devices[i]->trim)
5412  add_trim_entry_avoid_sb(Vcb, c->devices[i], cis[i].offset, len);
5413  }
5414  }
5415 
5416  if (!c->cache) {
5418 
5419  if (!