ReactOS  0.4.15-dev-5112-g22d8c0f
flushthread.c File Reference
#include "btrfs_drv.h"
#include "xxhash.h"
#include "crc32c.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) - (2 * sizeof(leaf_node)))
 

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)
 
void calc_tree_checksum (device_extension *Vcb, tree_header *th)
 
static NTSTATUS write_trees (device_extension *Vcb, PIRP Irp)
 
static void update_backup_superblock (device_extension *Vcb, superblock_backup *sb, PIRP Irp)
 
static void calc_superblock_checksum (superblock *sb)
 
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, void *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

◆ MAX_CSUM_SIZE

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

Definition at line 28 of file flushthread.c.

Typedef Documentation

◆ write_superblocks_context

Function Documentation

◆ _Function_class_() [1/2]

_Function_class_ ( IO_COMPLETION_ROUTINE  )

Definition at line 52 of file flushthread.c.

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

◆ _Function_class_() [2/2]

_Function_class_ ( KSTART_ROUTINE  )

Definition at line 7796 of file flushthread.c.

7797  {
7798  DEVICE_OBJECT* devobj = context;
7800  LARGE_INTEGER due_time;
7801 
7802  ObReferenceObject(devobj);
7803 
7804  KeInitializeTimer(&Vcb->flush_thread_timer);
7805 
7806  due_time.QuadPart = (uint64_t)Vcb->options.flush_interval * -10000000;
7807 
7808  KeSetTimer(&Vcb->flush_thread_timer, due_time, NULL);
7809 
7810  while (true) {
7811  KeWaitForSingleObject(&Vcb->flush_thread_timer, Executive, KernelMode, false, NULL);
7812 
7813  if (!(devobj->Vpb->Flags & VPB_MOUNTED) || Vcb->removing)
7814  break;
7815 
7816  if (!Vcb->locked)
7817  do_flush(Vcb);
7818 
7819  KeSetTimer(&Vcb->flush_thread_timer, due_time, NULL);
7820  }
7821 
7822  ObDereferenceObject(devobj);
7823  KeCancelTimer(&Vcb->flush_thread_timer);
7824 
7825  KeSetEvent(&Vcb->flush_thread_finished, 0, false);
7826 
7828 }
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281
static void do_flush(device_extension *Vcb)
Definition: flushthread.c:7778
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
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:1415
#define ObDereferenceObject
Definition: obfuncs.h:203
_In_opt_ PVOID _In_ ULONG _In_ PVOID context
Definition: wdfdriver.h:113
#define uint64_t
Definition: nsiface.idl:62
NTSTATUS NTAPI PsTerminateSystemThread(IN NTSTATUS ExitStatus)
Definition: kill.c:1148
#define NULL
Definition: types.h:112
#define ObReferenceObject
Definition: obfuncs.h:204
#define STATUS_SUCCESS
Definition: shellext.h:65
#define VPB_MOUNTED
Definition: iotypes.h:1807
LONGLONG QuadPart
Definition: typedefs.h:114

◆ 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 1001 of file flushthread.c.

1001  {
1002  LIST_ENTRY *le2, *list;
1003  changed_extent_ref* cer;
1004 
1005  list = old ? &ce->old_refs : &ce->refs;
1006 
1007  le2 = list->Flink;
1008  while (le2 != list) {
1010 
1011  if (cer->type == TYPE_EXTENT_DATA_REF && cer->edr.root == edr->root && cer->edr.objid == edr->objid && cer->edr.offset == edr->offset) {
1012  cer->edr.count += edr->count;
1013  goto end;
1014  }
1015 
1016  le2 = le2->Flink;
1017  }
1018 
1020  if (!cer) {
1021  ERR("out of memory\n");
1023  }
1024 
1025  cer->type = TYPE_EXTENT_DATA_REF;
1026  RtlCopyMemory(&cer->edr, edr, sizeof(EXTENT_DATA_REF));
1027  InsertTailList(list, &cer->list_entry);
1028 
1029 end:
1030  if (old)
1031  ce->old_count += edr->count;
1032  else
1033  ce->count += edr->count;
1034 
1035  return STATUS_SUCCESS;
1036 }
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
uint64_t offset
Definition: btrfs.h:419
LIST_ENTRY list_entry
Definition: btrfs_drv.h:610
uint64_t objid
Definition: btrfs.h:418
#define InsertTailList(ListHead, Entry)
LIST_ENTRY old_refs
Definition: btrfs_drv.h:598
#define ALLOC_TAG
Definition: btrfs_drv.h:87
EXTENT_DATA_REF edr
Definition: btrfs_drv.h:606
uint32_t count
Definition: btrfs.h:420
uint64_t count
Definition: btrfs_drv.h:593
uint64_t root
Definition: btrfs.h:417
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:38
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
GLuint GLuint end
Definition: gl.h:1545
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Definition: _list.h:228
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
#define list
Definition: rosglue.h:35
LIST_ENTRY refs
Definition: btrfs_drv.h:597
Definition: list.h:27
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
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 1038 of file flushthread.c.

1038  {
1039  LIST_ENTRY *le2, *list;
1040  changed_extent_ref* cer;
1041 
1042  list = old ? &ce->old_refs : &ce->refs;
1043 
1044  le2 = list->Flink;
1045  while (le2 != list) {
1047 
1048  if (cer->type == TYPE_SHARED_DATA_REF && cer->sdr.offset == sdr->offset) {
1049  cer->sdr.count += sdr->count;
1050  goto end;
1051  }
1052 
1053  le2 = le2->Flink;
1054  }
1055 
1057  if (!cer) {
1058  ERR("out of memory\n");
1060  }
1061 
1062  cer->type = TYPE_SHARED_DATA_REF;
1063  RtlCopyMemory(&cer->sdr, sdr, sizeof(SHARED_DATA_REF));
1064  InsertTailList(list, &cer->list_entry);
1065 
1066 end:
1067  if (old)
1068  ce->old_count += sdr->count;
1069  else
1070  ce->count += sdr->count;
1071 
1072  return STATUS_SUCCESS;
1073 }
SHARED_DATA_REF sdr
Definition: btrfs_drv.h:607
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LIST_ENTRY list_entry
Definition: btrfs_drv.h:610
#define InsertTailList(ListHead, Entry)
LIST_ENTRY old_refs
Definition: btrfs_drv.h:598
#define ALLOC_TAG
Definition: btrfs_drv.h:87
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:121
#define TYPE_SHARED_DATA_REF
Definition: btrfs.h:41
GLuint GLuint end
Definition: gl.h:1545
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
uint32_t count
Definition: btrfs.h:442
Definition: _list.h:228
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
#define list
Definition: rosglue.h:35
LIST_ENTRY refs
Definition: btrfs_drv.h:597
Definition: list.h:27
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
uint64_t offset
Definition: btrfs.h:441
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,
void csum,
PIRP  Irp 
)

Definition at line 2596 of file flushthread.c.

2596  {
2597  KEY searchkey;
2598  traverse_ptr tp, next_tp;
2599  NTSTATUS Status;
2600  uint64_t startaddr, endaddr;
2601  ULONG len;
2602  RTL_BITMAP bmp;
2603  ULONG* bmparr;
2604  ULONG runlength, index;
2605 
2606  TRACE("(%p, %I64x, %lx, %p, %p)\n", Vcb, address, length, csum, Irp);
2607 
2608  searchkey.obj_id = EXTENT_CSUM_ID;
2609  searchkey.obj_type = TYPE_EXTENT_CSUM;
2610  searchkey.offset = address;
2611 
2612  // FIXME - create checksum_root if it doesn't exist at all
2613 
2614  Status = find_item(Vcb, Vcb->checksum_root, &tp, &searchkey, false, Irp);
2615  if (Status == STATUS_NOT_FOUND) { // tree is completely empty
2616  if (csum) { // not deleted
2617  ULONG length2 = length;
2618  uint64_t off = address;
2619  void* data = csum;
2620 
2621  do {
2622  uint16_t il = (uint16_t)min(length2, MAX_CSUM_SIZE / Vcb->csum_size);
2623 
2624  void* checksums = ExAllocatePoolWithTag(PagedPool, il * Vcb->csum_size, ALLOC_TAG);
2625  if (!checksums) {
2626  ERR("out of memory\n");
2627  return;
2628  }
2629 
2630  RtlCopyMemory(checksums, data, il * Vcb->csum_size);
2631 
2632  Status = insert_tree_item(Vcb, Vcb->checksum_root, EXTENT_CSUM_ID, TYPE_EXTENT_CSUM, off, checksums,
2633  il * Vcb->csum_size, NULL, Irp);
2634  if (!NT_SUCCESS(Status)) {
2635  ERR("insert_tree_item returned %08lx\n", Status);
2636  ExFreePool(checksums);
2637  return;
2638  }
2639 
2640  length2 -= il;
2641 
2642  if (length2 > 0) {
2643  off += (uint64_t)il << Vcb->sector_shift;
2644  data = (uint8_t*)data + (il * Vcb->csum_size);
2645  }
2646  } while (length2 > 0);
2647  }
2648  } else if (!NT_SUCCESS(Status)) {
2649  ERR("find_item returned %08lx\n", Status);
2650  return;
2651  } else {
2652  uint32_t tplen;
2653  void* checksums;
2654 
2655  // FIXME - check entry is TYPE_EXTENT_CSUM?
2656 
2657  if (tp.item->key.offset < address && tp.item->key.offset + (((uint64_t)tp.item->size << Vcb->sector_shift) / Vcb->csum_size) >= address)
2658  startaddr = tp.item->key.offset;
2659  else
2660  startaddr = address;
2661 
2662  searchkey.obj_id = EXTENT_CSUM_ID;
2663  searchkey.obj_type = TYPE_EXTENT_CSUM;
2664  searchkey.offset = address + (length << Vcb->sector_shift);
2665 
2666  Status = find_item(Vcb, Vcb->checksum_root, &tp, &searchkey, false, Irp);
2667  if (!NT_SUCCESS(Status)) {
2668  ERR("find_item returned %08lx\n", Status);
2669  return;
2670  }
2671 
2672  tplen = tp.item->size / Vcb->csum_size;
2673 
2674  if (tp.item->key.offset + (tplen << Vcb->sector_shift) >= address + (length << Vcb->sector_shift))
2675  endaddr = tp.item->key.offset + (tplen << Vcb->sector_shift);
2676  else
2677  endaddr = address + (length << Vcb->sector_shift);
2678 
2679  TRACE("cs starts at %I64x (%lx sectors)\n", address, length);
2680  TRACE("startaddr = %I64x\n", startaddr);
2681  TRACE("endaddr = %I64x\n", endaddr);
2682 
2683  len = (ULONG)((endaddr - startaddr) >> Vcb->sector_shift);
2684 
2685  checksums = ExAllocatePoolWithTag(PagedPool, Vcb->csum_size * len, ALLOC_TAG);
2686  if (!checksums) {
2687  ERR("out of memory\n");
2688  return;
2689  }
2690 
2691  bmparr = ExAllocatePoolWithTag(PagedPool, sizeof(ULONG) * ((len/8)+1), ALLOC_TAG);
2692  if (!bmparr) {
2693  ERR("out of memory\n");
2694  ExFreePool(checksums);
2695  return;
2696  }
2697 
2698  RtlInitializeBitMap(&bmp, bmparr, len);
2699  RtlSetAllBits(&bmp);
2700 
2701  searchkey.obj_id = EXTENT_CSUM_ID;
2702  searchkey.obj_type = TYPE_EXTENT_CSUM;
2703  searchkey.offset = address;
2704 
2705  Status = find_item(Vcb, Vcb->checksum_root, &tp, &searchkey, false, Irp);
2706  if (!NT_SUCCESS(Status)) {
2707  ERR("find_item returned %08lx\n", Status);
2708  ExFreePool(checksums);
2709  ExFreePool(bmparr);
2710  return;
2711  }
2712 
2713  // set bit = free space, cleared bit = allocated sector
2714 
2715  while (tp.item->key.offset < endaddr) {
2716  if (tp.item->key.offset >= startaddr) {
2717  if (tp.item->size > 0) {
2718  ULONG itemlen = (ULONG)min((len - ((tp.item->key.offset - startaddr) >> Vcb->sector_shift)) * Vcb->csum_size, tp.item->size);
2719 
2720  RtlCopyMemory((uint8_t*)checksums + (((tp.item->key.offset - startaddr) * Vcb->csum_size) >> Vcb->sector_shift),
2721  tp.item->data, itemlen);
2722  RtlClearBits(&bmp, (ULONG)((tp.item->key.offset - startaddr) >> Vcb->sector_shift), itemlen / Vcb->csum_size);
2723  }
2724 
2726  if (!NT_SUCCESS(Status)) {
2727  ERR("delete_tree_item returned %08lx\n", Status);
2728  ExFreePool(checksums);
2729  ExFreePool(bmparr);
2730  return;
2731  }
2732  }
2733 
2734  if (find_next_item(Vcb, &tp, &next_tp, false, Irp)) {
2735  tp = next_tp;
2736  } else
2737  break;
2738  }
2739 
2740  if (!csum) { // deleted
2741  RtlSetBits(&bmp, (ULONG)((address - startaddr) >> Vcb->sector_shift), length);
2742  } else {
2743  RtlCopyMemory((uint8_t*)checksums + (((address - startaddr) * Vcb->csum_size) >> Vcb->sector_shift),
2744  csum, length * Vcb->csum_size);
2745  RtlClearBits(&bmp, (ULONG)((address - startaddr) >> Vcb->sector_shift), length);
2746  }
2747 
2748  runlength = RtlFindFirstRunClear(&bmp, &index);
2749 
2750  while (runlength != 0) {
2751  if (index >= len)
2752  break;
2753 
2754  if (index + runlength >= len) {
2755  runlength = len - index;
2756 
2757  if (runlength == 0)
2758  break;
2759  }
2760 
2761  do {
2762  uint16_t rl;
2763  uint64_t off;
2764  void* data;
2765 
2766  if (runlength * Vcb->csum_size > MAX_CSUM_SIZE)
2767  rl = (uint16_t)(MAX_CSUM_SIZE / Vcb->csum_size);
2768  else
2769  rl = (uint16_t)runlength;
2770 
2771  data = ExAllocatePoolWithTag(PagedPool, Vcb->csum_size * rl, ALLOC_TAG);
2772  if (!data) {
2773  ERR("out of memory\n");
2774  ExFreePool(bmparr);
2775  ExFreePool(checksums);
2776  return;
2777  }
2778 
2779  RtlCopyMemory(data, (uint8_t*)checksums + (Vcb->csum_size * index), Vcb->csum_size * rl);
2780 
2781  off = startaddr + ((uint64_t)index << Vcb->sector_shift);
2782 
2783  Status = insert_tree_item(Vcb, Vcb->checksum_root, EXTENT_CSUM_ID, TYPE_EXTENT_CSUM, off, data, Vcb->csum_size * rl, NULL, Irp);
2784  if (!NT_SUCCESS(Status)) {
2785  ERR("insert_tree_item returned %08lx\n", Status);
2786  ExFreePool(data);
2787  ExFreePool(bmparr);
2788  ExFreePool(checksums);
2789  return;
2790  }
2791 
2792  runlength -= rl;
2793  index += rl;
2794  } while (runlength > 0);
2795 
2796  runlength = RtlFindNextForwardRunClear(&bmp, index, &index);
2797  }
2798 
2799  ExFreePool(bmparr);
2800  ExFreePool(checksums);
2801  }
2802 }
uint64_t obj_id
Definition: btrfs.h:144
#define MAX_CSUM_SIZE
Definition: flushthread.c:28
uint8_t obj_type
Definition: btrfs.h:145
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:414
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
NTSTATUS NTSTATUS bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp) __attribute__((nonnull(1
uint64_t offset
Definition: btrfs.h:146
uint8_t * data
Definition: btrfs_drv.h:415
#define TYPE_EXTENT_CSUM
Definition: btrfs.h:31
#define ALLOC_TAG
Definition: btrfs_drv.h:87
_In_ PIRP Irp
Definition: csq.h:116
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp) __attribute__((nonnull(1
GLuint index
Definition: glext.h:6031
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2965
Status
Definition: gdiplustypes.h:24
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define TRACE(s)
Definition: solgame.cpp:4
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
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
#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)
BYTE uint8_t
Definition: msvideo1.c:66
#define uint64_t
Definition: nsiface.idl:62
#define ERR(fmt,...)
Definition: debug.h:110
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
Definition: btrfs.h:143
#define EXTENT_CSUM_ID
Definition: btrfs.h:91
UINT64 uint64_t
Definition: types.h:77
NTSTATUS NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp) __attribute__((nonnull(1
NTSYSAPI ULONG NTAPI RtlFindFirstRunClear(_In_ PRTL_BITMAP BitMapHeader, _Out_ PULONG StartingIndex)
NTSYSAPI void WINAPI RtlSetBits(PRTL_BITMAP, ULONG, ULONG)
#define min(a, b)
Definition: monoChain.cc:55
#define NULL
Definition: types.h:112
UINT32 uint32_t
Definition: types.h:75
NTSYSAPI ULONG WINAPI RtlFindNextForwardRunClear(PCRTL_BITMAP, ULONG, PULONG)
Definition: ffs.h:52
unsigned int ULONG
Definition: retypes.h:1
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

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 609 of file flushthread.c.

609  {
610  ULONG level;
611  LIST_ENTRY* le;
612 
613  for (level = 0; level <= 255; level++) {
614  bool nothing_found = true;
615 
616  TRACE("level = %lu\n", level);
617 
618  le = Vcb->trees.Flink;
619  while (le != &Vcb->trees) {
621 
622  if (t->write && t->header.level == level) {
623  TRACE("tree %p: root = %I64x, level = %x, parent = %p\n", t, t->header.tree_id, t->header.level, t->parent);
624 
625  nothing_found = false;
626 
627  if (t->parent) {
628  if (!t->parent->write)
629  TRACE("adding tree %p (level %x)\n", t->parent, t->header.level);
630 
631  t->parent->write = true;
632  } else if (t->root != Vcb->root_root && t->root != Vcb->chunk_root) {
633  KEY searchkey;
636 
637  searchkey.obj_id = t->root->id;
638  searchkey.obj_type = TYPE_ROOT_ITEM;
639  searchkey.offset = 0xffffffffffffffff;
640 
641  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
642  if (!NT_SUCCESS(Status)) {
643  ERR("error - find_item returned %08lx\n", Status);
644  return Status;
645  }
646 
647  if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
648  ERR("could not find ROOT_ITEM for tree %I64x\n", searchkey.obj_id);
649  return STATUS_INTERNAL_ERROR;
650  }
651 
652  if (tp.item->size < sizeof(ROOT_ITEM)) { // if not full length, delete and create new entry
654 
655  if (!ri) {
656  ERR("out of memory\n");
658  }
659 
660  RtlCopyMemory(ri, &t->root->root_item, sizeof(ROOT_ITEM));
661 
663  if (!NT_SUCCESS(Status)) {
664  ERR("delete_tree_item returned %08lx\n", Status);
665  ExFreePool(ri);
666  return Status;
667  }
668 
669  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);
670  if (!NT_SUCCESS(Status)) {
671  ERR("insert_tree_item returned %08lx\n", Status);
672  ExFreePool(ri);
673  return Status;
674  }
675  }
676 
677  tree* t2 = tp.tree;
678  while (t2) {
679  t2->write = true;
680 
681  t2 = t2->parent;
682  }
683  }
684  }
685 
686  le = le->Flink;
687  }
688 
689  if (nothing_found)
690  break;
691  }
692 
693  return STATUS_SUCCESS;
694 }
uint64_t obj_id
Definition: btrfs.h:144
GLint level
Definition: gl.h:1546
uint8_t obj_type
Definition: btrfs.h:145
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:414
GLdouble GLdouble t
Definition: gl.h:2047
uint64_t offset
Definition: btrfs.h:146
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:87
tree * tree
Definition: btrfs_drv.h:501
_In_ PIRP Irp
Definition: csq.h:116
struct _tree * parent
Definition: btrfs_drv.h:431
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp) __attribute__((nonnull(1
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:2965
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define TRACE(s)
Definition: solgame.cpp:4
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:502
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:143
NTSTATUS NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp) __attribute__((nonnull(1
#define TYPE_ROOT_ITEM
Definition: btrfs.h:32
Definition: list.h:27
#define NULL
Definition: types.h:112
unsigned int ULONG
Definition: retypes.h:1
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
bool write
Definition: btrfs_drv.h:440
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by do_write2().

◆ add_parents_to_cache()

static void add_parents_to_cache ( tree t)
static

Definition at line 696 of file flushthread.c.

696  {
697  while (t->parent) {
698  t = t->parent;
699  t->write = true;
700  }
701 }
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 6354 of file flushthread.c.

6354  {
6355  KEY searchkey;
6356  traverse_ptr tp;
6357  NTSTATUS Status;
6358 
6359  searchkey.obj_id = root;
6360  searchkey.obj_type = TYPE_ROOT_ITEM;
6361  searchkey.offset = 0xffffffffffffffff;
6362 
6363  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
6364  if (!NT_SUCCESS(Status)) {
6365  ERR("error - find_item returned %08lx\n", Status);
6366  return Status;
6367  }
6368 
6369  if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
6370  ERR("could not find ROOT_ITEM for tree %I64x\n", searchkey.obj_id);
6371  return STATUS_INTERNAL_ERROR;
6372  }
6373 
6374  if (tp.item->size < sizeof(ROOT_ITEM)) { // if not full length, create new entry with new bits zeroed
6376  if (!ri) {
6377  ERR("out of memory\n");
6379  }
6380 
6381  if (tp.item->size > 0)
6382  RtlCopyMemory(ri, tp.item->data, tp.item->size);
6383 
6384  RtlZeroMemory(((uint8_t*)ri) + tp.item->size, sizeof(ROOT_ITEM) - tp.item->size);
6385 
6387  if (!NT_SUCCESS(Status)) {
6388  ERR("delete_tree_item returned %08lx\n", Status);
6389  ExFreePool(ri);
6390  return Status;
6391  }
6392 
6393  Status = insert_tree_item(Vcb, Vcb->root_root, searchkey.obj_id, searchkey.obj_type, tp.item->key.offset, ri, sizeof(ROOT_ITEM), NULL, Irp);
6394  if (!NT_SUCCESS(Status)) {
6395  ERR("insert_tree_item returned %08lx\n", Status);
6396  ExFreePool(ri);
6397  return Status;
6398  }
6399  } else {
6400  tp.tree->write = true;
6401  }
6402 
6403  return STATUS_SUCCESS;
6404 }
uint64_t obj_id
Definition: btrfs.h:144
uint8_t obj_type
Definition: btrfs.h:145
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
struct _root root
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:414
uint64_t offset
Definition: btrfs.h:146
uint8_t * data
Definition: btrfs_drv.h:415
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:87
tree * tree
Definition: btrfs_drv.h:501
_In_ PIRP Irp
Definition: csq.h:116
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp) __attribute__((nonnull(1
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2965
Status
Definition: gdiplustypes.h:24
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
#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
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:143
NTSTATUS NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp) __attribute__((nonnull(1
#define TYPE_ROOT_ITEM
Definition: btrfs.h:32
#define NULL
Definition: types.h:112
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
bool write
Definition: btrfs_drv.h:440
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

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 6225 of file flushthread.c.

6225  {
6226  KEY searchkey;
6227  traverse_ptr tp;
6228  NTSTATUS Status;
6229 
6230  searchkey.obj_id = parsubvolid;
6231  searchkey.obj_type = TYPE_ROOT_REF;
6232  searchkey.offset = subvolid;
6233 
6234  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
6235  if (!NT_SUCCESS(Status)) {
6236  ERR("error - find_item returned %08lx\n", Status);
6237  return Status;
6238  }
6239 
6240  if (!keycmp(searchkey, tp.item->key)) {
6241  uint16_t rrsize = tp.item->size + (uint16_t)offsetof(ROOT_REF, name[0]) + rr->n;
6242  uint8_t* rr2;
6243 
6244  rr2 = ExAllocatePoolWithTag(PagedPool, rrsize, ALLOC_TAG);
6245  if (!rr2) {
6246  ERR("out of memory\n");
6248  }
6249 
6250  if (tp.item->size > 0)
6251  RtlCopyMemory(rr2, tp.item->data, tp.item->size);
6252 
6253  RtlCopyMemory(rr2 + tp.item->size, rr, offsetof(ROOT_REF, name[0]) + rr->n);
6254  ExFreePool(rr);
6255 
6257  if (!NT_SUCCESS(Status)) {
6258  ERR("delete_tree_item returned %08lx\n", Status);
6259  ExFreePool(rr2);
6260  return Status;
6261  }
6262 
6263  Status = insert_tree_item(Vcb, Vcb->root_root, searchkey.obj_id, searchkey.obj_type, searchkey.offset, rr2, rrsize, NULL, Irp);
6264  if (!NT_SUCCESS(Status)) {
6265  ERR("insert_tree_item returned %08lx\n", Status);
6266  ExFreePool(rr2);
6267  return Status;
6268  }
6269  } else {
6270  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);
6271  if (!NT_SUCCESS(Status)) {
6272  ERR("insert_tree_item returned %08lx\n", Status);
6273  ExFreePool(rr);
6274  return Status;
6275  }
6276  }
6277 
6278  return STATUS_SUCCESS;
6279 }
#define TYPE_ROOT_REF
Definition: btrfs.h:34
uint64_t obj_id
Definition: btrfs.h:144
uint8_t obj_type
Definition: btrfs.h:145
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1008
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:414
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
uint64_t offset
Definition: btrfs.h:146
uint8_t * data
Definition: btrfs_drv.h:415
#define ALLOC_TAG
Definition: btrfs_drv.h:87
_In_ PIRP Irp
Definition: csq.h:116
#define offsetof(TYPE, MEMBER)
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp) __attribute__((nonnull(1
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2965
Status
Definition: gdiplustypes.h:24
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
#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
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:143
NTSTATUS NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp) __attribute__((nonnull(1
#define NULL
Definition: types.h:112
Definition: name.c:38
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

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 4154 of file flushthread.c.

4154  {
4155  sys_chunk* sc;
4156  LIST_ENTRY* le;
4157 
4158  if (Vcb->superblock.n + sizeof(KEY) + size > SYS_CHUNK_ARRAY_SIZE) {
4159  ERR("error - bootstrap is full\n");
4160  return STATUS_INTERNAL_ERROR;
4161  }
4162 
4164  if (!sc) {
4165  ERR("out of memory\n");
4167  }
4168 
4169  sc->key.obj_id = obj_id;
4170  sc->key.obj_type = obj_type;
4171  sc->key.offset = offset;
4172  sc->size = size;
4174  if (!sc->data) {
4175  ERR("out of memory\n");
4176  ExFreePool(sc);
4178  }
4179 
4180  RtlCopyMemory(sc->data, data, sc->size);
4181 
4182  le = Vcb->sys_chunks.Flink;
4183  while (le != &Vcb->sys_chunks) {
4185 
4186  if (keycmp(sc2->key, sc->key) == 1)
4187  break;
4188 
4189  le = le->Flink;
4190  }
4191  InsertTailList(le, &sc->list_entry);
4192 
4193  Vcb->superblock.n += sizeof(KEY) + size;
4194 
4196 
4197  return STATUS_SUCCESS;
4198 }
uint64_t obj_id
Definition: btrfs.h:144
uint8_t obj_type
Definition: btrfs.h:145
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1008
#define InsertTailList(ListHead, Entry)
uint64_t offset
Definition: btrfs.h:146
#define SYS_CHUNK_ARRAY_SIZE
Definition: btrfs.h:194
static void regen_bootstrap(device_extension *Vcb)
Definition: flushthread.c:4132
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:87
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:121
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
#define Vcb
Definition: cdprocs.h:1415
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:119
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:143
Definition: list.h:27
USHORT size
Definition: btrfs_drv.h:616
struct _KEY KEY
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
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 151 of file flushthread.c.

151  {
153  if (!s) {
154  ERR("out of memory\n");
155  return;
156  }
157 
158  s->address = address;
159  s->size = size;
160  dev->num_trim_entries++;
161 
162  InsertTailList(&dev->trim_list, &s->list_entry);
163 }
#define InsertTailList(ListHead, Entry)
#define ALLOC_TAG
Definition: btrfs_drv.h:87
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:110

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 5389 of file flushthread.c.

5389  {
5390  int i;
5391  ULONG sblen = (ULONG)sector_align(sizeof(superblock), Vcb->superblock.sector_size);
5392 
5393  i = 0;
5394  while (superblock_addrs[i] != 0) {
5395  if (superblock_addrs[i] + sblen >= address && superblock_addrs[i] < address + size) {
5396  if (superblock_addrs[i] > address)
5398 
5399  if (size <= superblock_addrs[i] + sblen - address)
5400  return;
5401 
5402  size -= superblock_addrs[i] + sblen - address;
5403  address = superblock_addrs[i] + sblen;
5404  } else if (superblock_addrs[i] > address + size)
5405  break;
5406 
5407  i++;
5408  }
5409 
5411 }
static void add_trim_entry(device *dev, uint64_t address, uint64_t size)
Definition: flushthread.c:151
GLsizeiptr size
Definition: glext.h:5919
#define Vcb
Definition: cdprocs.h:1415
GLuint address
Definition: glext.h:9393
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
static const uint64_t superblock_addrs[]
Definition: btrfs.h:16
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 1459 of file flushthread.c.

1459  {
1460  LIST_ENTRY* le;
1461  NTSTATUS Status;
1462  bool changed = false;
1463  uint8_t max_level = 0, level;
1464 
1465  TRACE("(%p)\n", Vcb);
1466 
1467  le = Vcb->trees.Flink;
1468  while (le != &Vcb->trees) {
1470 
1471  if (t->write && !t->has_new_address) {
1472  chunk* c;
1473 
1474  if (t->has_address) {
1475  c = get_chunk_from_address(Vcb, t->header.address);
1476 
1477  if (c) {
1478  if (!c->cache_loaded) {
1480 
1481  if (!c->cache_loaded) {
1483 
1484  if (!NT_SUCCESS(Status)) {
1485  ERR("load_cache_chunk returned %08lx\n", Status);
1487  return Status;
1488  }
1489  }
1490 
1492  }
1493  }
1494  }
1495 
1497  if (!NT_SUCCESS(Status)) {
1498  ERR("get_tree_new_address returned %08lx\n", Status);
1499  return Status;
1500  }
1501 
1502  TRACE("allocated extent %I64x\n", t->new_address);
1503 
1504  c = get_chunk_from_address(Vcb, t->new_address);
1505 
1506  if (c)
1507  c->used += Vcb->superblock.node_size;
1508  else {
1509  ERR("could not find chunk for address %I64x\n", t->new_address);
1510  return STATUS_INTERNAL_ERROR;
1511  }
1512 
1513  changed = true;
1514 
1515  if (t->header.level > max_level)
1516  max_level = t->header.level;
1517  }
1518 
1519  le = le->Flink;
1520  }
1521 
1522  if (!changed)
1523  return STATUS_SUCCESS;
1524 
1525  level = max_level;
1526  do {
1527  le = Vcb->trees.Flink;
1528  while (le != &Vcb->trees) {
1530 
1531  if (t->write && !t->updated_extents && t->has_address && t->header.level == level) {
1533  if (!NT_SUCCESS(Status)) {
1534  ERR("update_tree_extents returned %08lx\n", Status);
1535  return Status;
1536  }
1537  }
1538 
1539  le = le->Flink;
1540  }
1541 
1542  if (level == 0)
1543  break;
1544 
1545  level--;
1546  } while (true);
1547 
1548  return STATUS_SUCCESS;
1549 }
GLint level
Definition: gl.h:1546
NTSTATUS get_tree_new_address(device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:872
LONG NTSTATUS
Definition: precomp.h:26
GLdouble GLdouble t
Definition: gl.h:2047
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
_In_ PIRP Irp
Definition: csq.h:116
#define release_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1132
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
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define TRACE(s)
Definition: solgame.cpp:4
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
Definition: typedefs.h:119
BYTE uint8_t
Definition: msvideo1.c:66
NTSTATUS load_cache_chunk(device_extension *Vcb, chunk *c, PIRP Irp)
Definition: free-space.c:980
#define ERR(fmt,...)
Definition: debug.h:110
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1131
Definition: list.h:27
#define NULL
Definition: types.h:112
_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:1355
static NTSTATUS update_tree_extents(device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:1104
#define c
Definition: ke_i.h:80
#define STATUS_SUCCESS
Definition: shellext.h:65
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address) __attribute__((nonnull(1)))

Referenced by do_write2().

◆ calc_superblock_checksum()

static void calc_superblock_checksum ( superblock sb)
static

Definition at line 2205 of file flushthread.c.

2205  {
2206  switch (sb->csum_type) {
2207  case CSUM_TYPE_CRC32C:
2208  *(uint32_t*)sb = ~calc_crc32c(0xffffffff, (uint8_t*)&sb->uuid, (ULONG)sizeof(superblock) - sizeof(sb->checksum));
2209  break;
2210 
2211  case CSUM_TYPE_XXHASH:
2212  *(uint64_t*)sb = XXH64(&sb->uuid, sizeof(superblock) - sizeof(sb->checksum), 0);
2213  break;
2214 
2215  case CSUM_TYPE_SHA256:
2216  calc_sha256((uint8_t*)sb, &sb->uuid, sizeof(superblock) - sizeof(sb->checksum));
2217  break;
2218 
2219  case CSUM_TYPE_BLAKE2:
2220  blake2b((uint8_t*)sb, BLAKE2_HASH_SIZE, &sb->uuid, sizeof(superblock) - sizeof(sb->checksum));
2221  break;
2222  }
2223 }
superblock * sb
Definition: btrfs.c:4230
#define CSUM_TYPE_BLAKE2
Definition: btrfs.h:135
void blake2b(void *out, size_t outlen, const void *in, size_t inlen)
Definition: blake2b-ref.c:237
#define CSUM_TYPE_CRC32C
Definition: btrfs.h:132
void calc_sha256(uint8_t *hash, const void *input, size_t len)
Definition: sha256.c:126
uint16_t csum_type
Definition: btrfs.h:247
uint8_t checksum[32]
Definition: btrfs.h:224
#define CSUM_TYPE_XXHASH
Definition: btrfs.h:133
crc_func calc_crc32c
Definition: crc32c.c:23
BYTE uint8_t
Definition: msvideo1.c:66
XXH_PUBLIC_API unsigned long long XXH64(const void *input, size_t len, unsigned long long seed)
Definition: xxhash.c:555
#define CSUM_TYPE_SHA256
Definition: btrfs.h:134
UINT64 uint64_t
Definition: types.h:77
BTRFS_UUID uuid
Definition: btrfs.h:225
UINT32 uint32_t
Definition: types.h:75
#define BLAKE2_HASH_SIZE
Definition: btrfs_drv.h:1243
unsigned int ULONG
Definition: retypes.h:1

Referenced by write_superblock().

◆ calc_tree_checksum()

void calc_tree_checksum ( device_extension Vcb,
tree_header th 
)

Definition at line 1800 of file flushthread.c.

1800  {
1801  switch (Vcb->superblock.csum_type) {
1802  case CSUM_TYPE_CRC32C:
1803  *((uint32_t*)th) = ~calc_crc32c(0xffffffff, (uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
1804  break;
1805 
1806  case CSUM_TYPE_XXHASH:
1807  *((uint64_t*)th) = XXH64((uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum), 0);
1808  break;
1809 
1810  case CSUM_TYPE_SHA256:
1811  calc_sha256((uint8_t*)th, &th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
1812  break;
1813 
1814  case CSUM_TYPE_BLAKE2:
1815  blake2b((uint8_t*)th, BLAKE2_HASH_SIZE, &th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
1816  break;
1817  }
1818 }
#define CSUM_TYPE_BLAKE2
Definition: btrfs.h:135
void blake2b(void *out, size_t outlen, const void *in, size_t inlen)
Definition: blake2b-ref.c:237
uint8_t csum[32]
Definition: btrfs.h:154
#define CSUM_TYPE_CRC32C
Definition: btrfs.h:132
void calc_sha256(uint8_t *hash, const void *input, size_t len)
Definition: sha256.c:126
#define Vcb
Definition: cdprocs.h:1415
#define CSUM_TYPE_XXHASH
Definition: btrfs.h:133
crc_func calc_crc32c
Definition: crc32c.c:23
BYTE uint8_t
Definition: msvideo1.c:66
XXH_PUBLIC_API unsigned long long XXH64(const void *input, size_t len, unsigned long long seed)
Definition: xxhash.c:555
#define CSUM_TYPE_SHA256
Definition: btrfs.h:134
UINT64 uint64_t
Definition: types.h:77
BTRFS_UUID fs_uuid
Definition: btrfs.h:155
UINT32 uint32_t
Definition: types.h:75
#define BLAKE2_HASH_SIZE
Definition: btrfs_drv.h:1243

Referenced by snapshot_tree_copy(), write_metadata_items(), and write_trees().

◆ check_for_orphans()

static NTSTATUS check_for_orphans ( device_extension Vcb,
PIRP  Irp 
)
static

Definition at line 7332 of file flushthread.c.

7332  {
7333  NTSTATUS Status;
7334  LIST_ENTRY* le;
7335 
7336  if (IsListEmpty(&Vcb->dirty_filerefs))
7337  return STATUS_SUCCESS;
7338 
7339  le = Vcb->dirty_filerefs.Flink;
7340  while (le != &Vcb->dirty_filerefs) {
7342 
7343  if (!fr->fcb->subvol->checked_for_orphans) {
7345  if (!NT_SUCCESS(Status)) {
7346  ERR("check_for_orphans_root returned %08lx\n", Status);
7347  return Status;
7348  }
7349 
7350  fr->fcb->subvol->checked_for_orphans = true;
7351  }
7352 
7353  le = le->Flink;
7354  }
7355 
7356  return STATUS_SUCCESS;
7357 }
static NTSTATUS check_for_orphans_root(device_extension *Vcb, root *r, PIRP Irp)
Definition: flushthread.c:7257
LONG NTSTATUS
Definition: precomp.h:26
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
_In_ PIRP Irp
Definition: csq.h:116
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
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
fcb * fcb
Definition: btrfs_drv.h:342
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
struct _root * subvol
Definition: btrfs_drv.h:288
#define STATUS_SUCCESS
Definition: shellext.h:65
LIST_ENTRY list_entry_dirty
Definition: btrfs_drv.h:338

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 7257 of file flushthread.c.

7257  {
7258  NTSTATUS Status;
7259  KEY searchkey;
7260  traverse_ptr tp;
7262 
7263  TRACE("(%p, %p)\n", Vcb, r);
7264 
7266 
7267  searchkey.obj_id = BTRFS_ORPHAN_INODE_OBJID;
7268  searchkey.obj_type = TYPE_ORPHAN_INODE;
7269  searchkey.offset = 0;
7270 
7271  Status = find_item(Vcb, r, &tp, &searchkey, false, Irp);
7272  if (!NT_SUCCESS(Status)) {
7273  ERR("find_item returned %08lx\n", Status);
7274  return Status;
7275  }
7276 
7277  do {
7278  traverse_ptr next_tp;
7279 
7280  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))
7281  break;
7282 
7283  if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
7284  fcb* fcb;
7285 
7286  TRACE("removing orphaned inode %I64x\n", tp.item->key.offset);
7287 
7288  Status = open_fcb(Vcb, r, tp.item->key.offset, 0, NULL, false, NULL, &fcb, PagedPool, Irp);
7289  if (!NT_SUCCESS(Status))
7290  ERR("open_fcb returned %08lx\n", Status);
7291  else {
7292  if (fcb->inode_item.st_nlink == 0) {
7293  if (fcb->type != BTRFS_TYPE_DIRECTORY && fcb->inode_item.st_size > 0) {
7294  Status = excise_extents(Vcb, fcb, 0, sector_align(fcb->inode_item.st_size, Vcb->superblock.sector_size), Irp, &rollback);
7295  if (!NT_SUCCESS(Status)) {
7296  ERR("excise_extents returned %08lx\n", Status);
7297  goto end;
7298  }
7299  }
7300 
7301  fcb->deleted = true;
7302 
7304  }
7305 
7306  free_fcb(fcb);
7307 
7309  if (!NT_SUCCESS(Status)) {
7310  ERR("delete_tree_item returned %08lx\n", Status);
7311  goto end;
7312  }
7313  }
7314  }
7315 
7316  if (find_next_item(Vcb, &tp, &next_tp, false, Irp))
7317  tp = next_tp;
7318  else
7319  break;
7320  } while (true);
7321 
7323 
7325 
7326 end:
7328 
7329  return Status;
7330 }
uint64_t obj_id
Definition: btrfs.h:144
uint8_t obj_type
Definition: btrfs.h:145
void free_fcb(_Inout_ fcb *fcb)
Definition: btrfs.c:1703
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:706
LONG NTSTATUS
Definition: precomp.h:26
#define BTRFS_ORPHAN_INODE_OBJID
Definition: btrfs.h:130
NTSTATUS NTSTATUS bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp) __attribute__((nonnull(1
uint64_t offset
Definition: btrfs.h:146
_In_ PIRP Irp
Definition: csq.h:116
uint32_t st_nlink
Definition: btrfs.h:292
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1664
uint8_t type
Definition: btrfs_drv.h:291
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2965
Status
Definition: gdiplustypes.h:24
uint64_t st_size
Definition: btrfs.h:289
#define TRACE(s)
Definition: solgame.cpp:4
struct _fcb fcb
Definition: btrfs_drv.h:1355
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
NTSTATUS NTSTATUS void clear_rollback(LIST_ENTRY *rollback) __attribute__((nonnull(1)))
GLuint GLuint end
Definition: gl.h:1545
tree_data * item
Definition: btrfs_drv.h:502
Definition: typedefs.h:119
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback) __attribute__((nonnull(1
INODE_ITEM inode_item
Definition: btrfs_drv.h:292
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:143
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback) __attribute__((nonnull(1
bool deleted
Definition: btrfs_drv.h:295
NTSTATUS NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp) __attribute__((nonnull(1
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define NULL
Definition: types.h:112
_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:1355
#define TYPE_ORPHAN_INODE
Definition: btrfs.h:27
#define STATUS_SUCCESS
Definition: shellext.h:65
static uint64_t __inline sector_align(uint64_t n, uint64_t a)

Referenced by check_for_orphans().

◆ clean_space_cache()

static void clean_space_cache ( device_extension Vcb)
static

Definition at line 397 of file flushthread.c.

397  {
398  LIST_ENTRY* le;
399  chunk* c;
400 #ifndef DEBUG_TRIM_EMULATION
401  ULONG num;
402 #endif
403 
404  TRACE("(%p)\n", Vcb);
405 
406  ExAcquireResourceSharedLite(&Vcb->chunk_lock, true);
407 
408  le = Vcb->chunks.Flink;
409  while (le != &Vcb->chunks) {
411 
412  if (c->space_changed) {
414 
415  if (c->space_changed) {
416  if (Vcb->trim && !Vcb->options.no_trim)
418 
419  space_list_merge(&c->space, &c->space_size, &c->deleting);
420 
421  while (!IsListEmpty(&c->deleting)) {
423 
424  ExFreePool(s);
425  }
426  }
427 
428  c->space_changed = false;
429 
431  }
432 
433  le = le->Flink;
434  }
435 
436  ExReleaseResourceLite(&Vcb->chunk_lock);
437 
438  if (Vcb->trim && !Vcb->options.no_trim) {
439 #ifndef DEBUG_TRIM_EMULATION
441  ULONG total_num;
442 
443  context.left = 0;
444 
445  le = Vcb->devices.Flink;
446  while (le != &Vcb->devices) {
448 
449  if (dev->devobj && !dev->readonly && dev->trim && dev->num_trim_entries > 0)
450  context.left++;
451 
452  le = le->Flink;
453  }
454 
455  if (context.left == 0)
456  return;
457 
458  total_num = context.left;
459  num = 0;
460 
462 
464  if (!context.stripes) {
465  ERR("out of memory\n");
466  return;
467  }
468 
469  RtlZeroMemory(context.stripes, sizeof(ioctl_context_stripe) * context.left);
470 #endif
471 
472  le = Vcb->devices.Flink;
473  while (le != &Vcb->devices) {
475 
476  if (dev->devobj && !dev->readonly && dev->trim && dev->num_trim_entries > 0) {
477 #ifdef DEBUG_TRIM_EMULATION
478  trim_emulation(dev);
479 #else
480  LIST_ENTRY* le2;
481  ioctl_context_stripe* stripe = &context.stripes[num];
482  DEVICE_DATA_SET_RANGE* ranges;
483  ULONG datalen = (ULONG)sector_align(sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES), sizeof(uint64_t)) + (dev->num_trim_entries * sizeof(DEVICE_DATA_SET_RANGE)), i;
485 
487  if (!stripe->dmdsa) {
488  ERR("out of memory\n");
489  goto nextdev;
490  }
491 
492  stripe->dmdsa->Size = sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES);
493  stripe->dmdsa->Action = DeviceDsmAction_Trim;
495  stripe->dmdsa->ParameterBlockOffset = 0;
496  stripe->dmdsa->ParameterBlockLength = 0;
497  stripe->dmdsa->DataSetRangesOffset = (ULONG)sector_align(sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES), sizeof(uint64_t));
498  stripe->dmdsa->DataSetRangesLength = dev->num_trim_entries * sizeof(DEVICE_DATA_SET_RANGE);
499 
500  ranges = (DEVICE_DATA_SET_RANGE*)((uint8_t*)stripe->dmdsa + stripe->dmdsa->DataSetRangesOffset);
501 
502  i = 0;
503 
504  le2 = dev->trim_list.Flink;
505  while (le2 != &dev->trim_list) {
507 
508  ranges[i].StartingOffset = s->address;
509  ranges[i].LengthInBytes = s->size;
510  i++;
511 
512  le2 = le2->Flink;
513  }
514 
515  stripe->Irp = IoAllocateIrp(dev->devobj->StackSize, false);
516 
517  if (!stripe->Irp) {
518  ERR("IoAllocateIrp failed\n");
519  goto nextdev;
520  }
521 
524  IrpSp->FileObject = dev->fileobj;
525 
526  IrpSp->Parameters.DeviceIoControl.IoControlCode = IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES;
527  IrpSp->Parameters.DeviceIoControl.InputBufferLength = datalen;
528  IrpSp->Parameters.DeviceIoControl.OutputBufferLength = 0;
529 
530  stripe->Irp->AssociatedIrp.SystemBuffer = stripe->dmdsa;
531  stripe->Irp->Flags |= IRP_BUFFERED_IO;
532  stripe->Irp->UserBuffer = NULL;
533  stripe->Irp->UserIosb = &stripe->iosb;
534 
535  IoSetCompletionRoutine(stripe->Irp, ioctl_completion, &context, true, true, true);
536 
537  IoCallDriver(dev->devobj, stripe->Irp);
538 
539 nextdev:
540 #endif
541  while (!IsListEmpty(&dev->trim_list)) {
543  ExFreePool(s);
544  }
545 
546  dev->num_trim_entries = 0;
547 
548 #ifndef DEBUG_TRIM_EMULATION
549  num++;
550 #endif
551  }
552 
553  le = le->Flink;
554  }
555 
556 #ifndef DEBUG_TRIM_EMULATION
558 
559  for (num = 0; num < total_num; num++) {
560  if (context.stripes[num].dmdsa)
561  ExFreePool(context.stripes[num].dmdsa);
562 
563  if (context.stripes[num].Irp)
564  IoFreeIrp(context.stripes[num].Irp);
565  }
566 
567  ExFreePool(context.stripes);
568 #endif
569  }
570 }
Definition: http.c:7251
void space_list_merge(LIST_ENTRY *spacelist, LIST_ENTRY *spacelist_size, LIST_ENTRY *deleting)
Definition: free-space.c:1657
#define DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED
Definition: ntddstor.h:764
struct _DEVICE_MANAGE_DATA_SET_ATTRIBUTES DEVICE_MANAGE_DATA_SET_ATTRIBUTES
Definition: write.c:113
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1030
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:498
#define ALLOC_TAG
Definition: btrfs_drv.h:87
ULONGLONG LengthInBytes
Definition: ntddstor.h:768
Definition: devices.h:37
#define DeviceDsmAction_Trim
Definition: ntddstor.h:276
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
#define release_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1132
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:121
#define TRACE(s)
Definition: solgame.cpp:4
#define IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES
Definition: ntddstor.h:181
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
GLuint GLuint num
Definition: glext.h:9618
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
_In_opt_ PVOID _In_ ULONG _In_ PVOID context
Definition: wdfdriver.h:113
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
GLdouble s
Definition: gl.h:2039
Definition: typedefs.h:119
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
BYTE uint8_t
Definition: msvideo1.c:66
#define uint64_t
Definition: nsiface.idl:62
#define ERR(fmt,...)
Definition: debug.h:110
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define IRP_BUFFERED_IO
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 acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1131
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
Definition: list.h:27
#define NULL
Definition: types.h:112
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:767
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:262
static void clean_space_cache_chunk(device_extension *Vcb, chunk *c)
Definition: flushthread.c:165
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
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 165 of file flushthread.c.

165  {
166  LIST_ENTRY* le;
167  ULONG type;
168 
169  if (c->chunk_item->type & BLOCK_FLAG_DUPLICATE)
171  else if (c->chunk_item->type & BLOCK_FLAG_RAID0)
173  else if (c->chunk_item->type & BLOCK_FLAG_RAID1)
175  else if (c->chunk_item->type & BLOCK_FLAG_RAID10)
177  else if (c->chunk_item->type & BLOCK_FLAG_RAID5)
179  else if (c->chunk_item->type & BLOCK_FLAG_RAID6)
181  else if (c->chunk_item->type & BLOCK_FLAG_RAID1C3)
183  else if (c->chunk_item->type & BLOCK_FLAG_RAID1C4)
185  else // SINGLE
187 
188  le = c->deleting.Flink;
189  while (le != &c->deleting) {
191 
192  if (!Vcb->options.no_barrier || !(c->chunk_item->type & BLOCK_FLAG_METADATA)) {
193  CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&c->chunk_item[1];
194 
196  uint16_t i;
197 
198  for (i = 0; i < c->chunk_item->num_stripes; i++) {
199  if (c->devices[i] && c->devices[i]->devobj && !c->devices[i]->readonly && c->devices[i]->trim)
200  add_trim_entry(c->devices[i], s->address - c->offset + cis[i].offset, s->size);
201  }
202  } else if (type == BLOCK_FLAG_RAID0) {
203  uint64_t startoff, endoff;
204  uint16_t startoffstripe, endoffstripe, i;
205 
206  get_raid0_offset(s->address - c->offset, c->chunk_item->stripe_length, c->chunk_item->num_stripes, &startoff, &startoffstripe);
207  get_raid0_offset(s->address - c->offset + s->size - 1, c->chunk_item->stripe_length, c->chunk_item->num_stripes, &endoff, &endoffstripe);
208 
209  for (i = 0; i < c->chunk_item->num_stripes; i++) {
210  if (c->devices[i] && c->devices[i]->devobj && !c->devices[i]->readonly && c->devices[i]->trim) {
211  uint64_t stripestart, stripeend;
212 
213  if (startoffstripe > i)
214  stripestart = startoff - (startoff % c->chunk_item->stripe_length) + c->chunk_item->stripe_length;
215  else if (startoffstripe == i)
216  stripestart = startoff;
217  else
218  stripestart = startoff - (startoff % c->chunk_item->stripe_length);
219 
220  if (endoffstripe > i)
221  stripeend = endoff - (endoff % c->chunk_item->stripe_length) + c->chunk_item->stripe_length;
222  else if (endoffstripe == i)
223  stripeend = endoff + 1;
224  else
225  stripeend = endoff - (endoff % c->chunk_item->stripe_length);
226 
227  if (stripestart != stripeend)
228  add_trim_entry(c->devices[i], stripestart + cis[i].offset, stripeend - stripestart);
229  }
230  }
231  } else if (type == BLOCK_FLAG_RAID10) {
232  uint64_t startoff, endoff;
233  uint16_t sub_stripes, startoffstripe, endoffstripe, i;
234 
235  sub_stripes = max(1, c->chunk_item->sub_stripes);
236 
237  get_raid0_offset(s->address - c->offset, c->chunk_item->stripe_length, c->chunk_item->num_stripes / sub_stripes, &startoff, &startoffstripe);
238  get_raid0_offset(s->address - c->offset + s->size - 1, c->chunk_item->stripe_length, c->chunk_item->num_stripes / sub_stripes, &endoff, &endoffstripe);
239 
240  startoffstripe *= sub_stripes;
241  endoffstripe *= sub_stripes;
242 
243  for (i = 0; i < c->chunk_item->num_stripes; i += sub_stripes) {
244  ULONG j;
245  uint64_t stripestart, stripeend;
246 
247  if (startoffstripe > i)
248  stripestart = startoff - (startoff % c->chunk_item->stripe_length) + c->chunk_item->stripe_length;
249  else if (startoffstripe == i)
250  stripestart = startoff;
251  else
252  stripestart = startoff - (startoff % c->chunk_item->stripe_length);
253 
254  if (endoffstripe > i)
255  stripeend = endoff - (endoff % c->chunk_item->stripe_length) + c->chunk_item->stripe_length;
256  else if (endoffstripe == i)
257  stripeend = endoff + 1;
258  else
259  stripeend = endoff - (endoff % c->chunk_item->stripe_length);
260 
261  if (stripestart != stripeend) {
262  for (j = 0; j < sub_stripes; j++) {
263  if (c->devices[i+j] && c->devices[i+j]->devobj && !c->devices[i+j]->readonly && c->devices[i+j]->trim)
264  add_trim_entry(c->devices[i+j], stripestart + cis[i+j].offset, stripeend - stripestart);
265  }
266  }
267  }
268  }
269  // FIXME - RAID5(?), RAID6(?)
270  }
271 
272  le = le->Flink;
273  }
274 }
#define max(a, b)
Definition: svc.c:63
static void add_trim_entry(device *dev, uint64_t address, uint64_t size)
Definition: flushthread.c:151
unsigned short int uint16_t
Definition: acefiex.h:54
if(dx==0 &&dy==0)
Definition: linetemp.h:174
_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:989
#define BLOCK_FLAG_RAID1C3
Definition: btrfs.h:87
#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
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
#define BLOCK_FLAG_RAID6
Definition: shellext.h:83
#define BLOCK_FLAG_RAID1C4
Definition: btrfs.h:88
#define BLOCK_FLAG_METADATA
Definition: shellext.h:77
GLdouble s
Definition: gl.h:2039
Definition: typedefs.h:119
UINT64 uint64_t
Definition: types.h:77
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
Definition: list.h:27
unsigned int ULONG
Definition: retypes.h:1
#define BLOCK_FLAG_DUPLICATE
Definition: shellext.h:80
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
#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 4200 of file flushthread.c.

4200  {
4201  CHUNK_ITEM* ci;
4202  CHUNK_ITEM_STRIPE* cis;
4203  BLOCK_GROUP_ITEM* bgi;
4204  uint16_t i, factor;
4205  NTSTATUS Status;
4206 
4208  if (!ci) {
4209  ERR("out of memory\n");
4211  }
4212 
4213  RtlCopyMemory(ci, c->chunk_item, c->size);
4214 
4215  Status = insert_tree_item(Vcb, Vcb->chunk_root, 0x100, TYPE_CHUNK_ITEM, c->offset, ci, c->size, NULL, Irp);
4216  if (!NT_SUCCESS(Status)) {
4217  ERR("insert_tree_item failed\n");
4218  ExFreePool(ci);
4219  return Status;
4220  }
4221 
4222  if (c->chunk_item->type & BLOCK_FLAG_SYSTEM) {
4223  Status = add_to_bootstrap(Vcb, 0x100, TYPE_CHUNK_ITEM, c->offset, ci, c->size);
4224  if (!NT_SUCCESS(Status)) {
4225  ERR("add_to_bootstrap returned %08lx\n", Status);
4226  return Status;
4227  }
4228  }
4229 
4230  // add BLOCK_GROUP_ITEM to tree 2
4231 
4233  if (!bgi) {
4234  ERR("out of memory\n");
4236  }
4237 
4238  bgi->used = c->used;
4239  bgi->chunk_tree = 0x100;
4240  bgi->flags = c->chunk_item->type;
4241 
4242  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);
4243  if (!NT_SUCCESS(Status)) {
4244  ERR("insert_tree_item failed\n");
4245  ExFreePool(bgi);
4246  return Status;
4247  }
4248 
4249  if (c->chunk_item->type & BLOCK_FLAG_RAID0)
4250  factor = c->chunk_item->num_stripes;
4251  else if (c->chunk_item->type & BLOCK_FLAG_RAID10)
4252  factor = c->chunk_item->num_stripes / c->chunk_item->sub_stripes;
4253  else if (c->chunk_item->type & BLOCK_FLAG_RAID5)
4254  factor = c->chunk_item->num_stripes - 1;
4255  else if (c->chunk_item->type & BLOCK_FLAG_RAID6)
4256  factor = c->chunk_item->num_stripes - 2;
4257  else // SINGLE, DUPLICATE, RAID1, RAID1C3, RAID1C4
4258  factor = 1;
4259 
4260  // add DEV_EXTENTs to tree 4
4261 
4262  cis = (CHUNK_ITEM_STRIPE*)&c->chunk_item[1];
4263 
4264  for (i = 0; i < c->chunk_item->num_stripes; i++) {
4265  DEV_EXTENT* de;
4266 
4268  if (!de) {
4269  ERR("out of memory\n");
4271  }
4272 
4273  de->chunktree = Vcb->chunk_root->id;
4274  de->objid = 0x100;
4275  de->address = c->offset;
4276  de->length = c->chunk_item->size / factor;
4277  de->chunktree_uuid = Vcb->chunk_root->treeholder.tree->header.chunk_tree_uuid;
4278 
4279  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);
4280  if (!NT_SUCCESS(Status)) {
4281  ERR("insert_tree_item returned %08lx\n", Status);
4282  ExFreePool(de);
4283  return Status;
4284  }
4285 
4286  // FIXME - no point in calling this twice for the same device
4287  Status = update_dev_item(Vcb, c->devices[i], Irp);
4288  if (!NT_SUCCESS(Status)) {
4289  ERR("update_dev_item returned %08lx\n", Status);
4290  return Status;
4291  }
4292  }
4293 
4294  c->created = false;
4295  c->oldused = c->used;
4296 
4297  Vcb->superblock.bytes_used += c->used;
4298 
4299  return STATUS_SUCCESS;
4300 }
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
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:426
#define TYPE_CHUNK_ITEM
Definition: btrfs.h:48
LONG NTSTATUS
Definition: precomp.h:26
uint64_t length
Definition: btrfs.h:472
unsigned short int uint16_t
Definition: acefiex.h:54
uint64_t used
Definition: btrfs.h:424
#define ALLOC_TAG
Definition: btrfs_drv.h:87
_In_ PIRP Irp
Definition: csq.h:116
#define TYPE_DEV_EXTENT
Definition: btrfs.h:46
#define BLOCK_FLAG_SYSTEM
Definition: shellext.h:76
NTSTATUS update_dev_item(device_extension *Vcb, device *device, PIRP Irp)
Definition: flushthread.c:4087
#define BLOCK_FLAG_RAID10
Definition: shellext.h:81
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp) __attribute__((nonnull(1
Status
Definition: gdiplustypes.h:24
#define BLOCK_FLAG_RAID0
Definition: shellext.h:78
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
#define for
Definition: utility.h:88
uint64_t objid
Definition: btrfs.h:470
#define BLOCK_FLAG_RAID6
Definition: shellext.h:83
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define TYPE_BLOCK_GROUP_ITEM
Definition: btrfs.h:42
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:4154
#define ERR(fmt,...)
Definition: debug.h:110
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
uint64_t chunk_tree
Definition: btrfs.h:425
#define NULL
Definition: types.h:112
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
uint64_t chunktree
Definition: btrfs.h:469
BTRFS_UUID chunktree_uuid
Definition: btrfs.h:473
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
uint64_t address
Definition: btrfs.h:471

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 6128 of file flushthread.c.

6128  {
6129  KEY searchkey;
6130  traverse_ptr tp;
6131  NTSTATUS Status;
6132 
6133  searchkey.obj_id = parsubvolid;
6134  searchkey.obj_type = TYPE_ROOT_REF;
6135  searchkey.offset = subvolid;
6136 
6137  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
6138  if (!NT_SUCCESS(Status)) {
6139  ERR("error - find_item returned %08lx\n", Status);
6140  return Status;
6141  }
6142 
6143  if (!keycmp(searchkey, tp.item->key)) {
6144  if (tp.item->size < sizeof(ROOT_REF)) {
6145  ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(ROOT_REF));
6146  return STATUS_INTERNAL_ERROR;
6147  } else {
6148  ROOT_REF* rr;
6149  ULONG len;
6150 
6151  rr = (ROOT_REF*)tp.item->data;
6152  len = tp.item->size;
6153 
6154  do {
6155  uint16_t itemlen;
6156 
6157  if (len < sizeof(ROOT_REF) || len < offsetof(ROOT_REF, name[0]) + rr->n) {
6158  ERR("(%I64x,%x,%I64x) was truncated\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
6159  break;
6160  }
6161 
6162  itemlen = (uint16_t)offsetof(ROOT_REF, name[0]) + rr->n;
6163 
6164  if (rr->dir == parinode && rr->n == utf8->Length && RtlCompareMemory(rr->name, utf8->Buffer, rr->n) == rr->n) {
6165  uint16_t newlen = tp.item->size - itemlen;
6166 
6168  if (!NT_SUCCESS(Status)) {
6169  ERR("delete_tree_item returned %08lx\n", Status);
6170  return Status;
6171  }
6172 
6173  if (newlen == 0) {
6174  TRACE("deleting (%I64x,%x,%I64x)\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
6175  } else {
6176  uint8_t *newrr = ExAllocatePoolWithTag(PagedPool, newlen, ALLOC_TAG), *rroff;
6177 
6178  if (!newrr) {
6179  ERR("out of memory\n");
6181  }
6182 
6183  TRACE("modifying (%I64x,%x,%I64x)\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
6184 
6185  if ((uint8_t*)rr > tp.item->data) {
6186  RtlCopyMemory(newrr, tp.item->data, (uint8_t*)rr - tp.item->data);
6187  rroff = newrr + ((uint8_t*)rr - tp.item->data);
6188  } else {
6189  rroff = newrr;
6190  }
6191 
6192  if ((uint8_t*)&rr->name[rr->n] < tp.item->data + tp.item->size)
6193  RtlCopyMemory(rroff, &rr->name[rr->n], tp.item->size - ((uint8_t*)&rr->name[rr->n] - tp.item->data));
6194 
6195  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);
6196  if (!NT_SUCCESS(Status)) {
6197  ERR("insert_tree_item returned %08lx\n", Status);
6198  ExFreePool(newrr);
6199  return Status;
6200  }
6201  }
6202 
6203  break;
6204  }
6205 
6206  if (len > itemlen) {
6207  len -= itemlen;
6208  rr = (ROOT_REF*)&rr->name[rr->n];
6209  } else
6210  break;
6211  } while (len > 0);
6212  }
6213  } else {
6214  WARN("could not find ROOT_REF entry for subvol %I64x in %I64x\n", searchkey.offset, searchkey.obj_id);
6215  return STATUS_NOT_FOUND;
6216  }
6217 
6218  return STATUS_SUCCESS;
6219 }
#define TYPE_ROOT_REF
Definition: btrfs.h:34
uint64_t obj_id
Definition: btrfs.h:144
uint8_t obj_type
Definition: btrfs.h:145
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
char name[1]
Definition: btrfs.h:465
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1008
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:414
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
if(dx==0 &&dy==0)
Definition: linetemp.h:174
uint16_t n
Definition: btrfs.h:464
uint64_t offset
Definition: btrfs.h:146
uint8_t * data
Definition: btrfs_drv.h:415
uint64_t dir
Definition: btrfs.h:462
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:87
_In_ PIRP Irp
Definition: csq.h:116
#define offsetof(TYPE, MEMBER)
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp) __attribute__((nonnull(1
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2965
Status
Definition: gdiplustypes.h:24
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define TRACE(s)
Definition: solgame.cpp:4
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
#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
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:143
NTSTATUS NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp) __attribute__((nonnull(1
#define NULL
Definition: types.h:112
Definition: name.c:38
unsigned int ULONG
Definition: retypes.h:1
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465

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 4361 of file flushthread.c.

4362  {
4363  NTSTATUS Status;
4364  uint16_t xasize;
4365  DIR_ITEM* xa;
4366 
4367  TRACE("(%p, %I64x, %I64x, %.*s, %08x)\n", Vcb, subvol->id, inode, namelen, name, crc32);
4368 
4369  xasize = (uint16_t)offsetof(DIR_ITEM, name[0]) + namelen;
4370 
4371  xa = ExAllocatePoolWithTag(PagedPool, xasize, ALLOC_TAG);
4372  if (!xa) {
4373  ERR("out of memory\n");
4375  }
4376 
4377  xa->key.obj_id = 0;
4378  xa->key.obj_type = 0;
4379  xa->key.offset = 0;
4380  xa->transid = Vcb->superblock.generation;
4381  xa->m = 0;
4382  xa->n = namelen;
4383  xa->type = BTRFS_TYPE_EA;
4384  RtlCopyMemory(xa->name, name, namelen);
4385 
4387  if (!NT_SUCCESS(Status)) {
4388  ERR("insert_tree_item_batch returned %08lx\n", Status);
4389  ExFreePool(xa);
4390  return Status;
4391  }
4392 
4393  return STATUS_SUCCESS;
4394 }
uint64_t obj_id
Definition: btrfs.h:144
uint8_t obj_type
Definition: btrfs.h:145
#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:4436
LONG NTSTATUS
Definition: precomp.h:26
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:146
Definition: fs.h:78
#define ALLOC_TAG
Definition: btrfs_drv.h:87
uint16_t m
Definition: btrfs.h:275
KEY key
Definition: btrfs.h:273
char name[1]
Definition: btrfs.h:278
#define offsetof(TYPE, MEMBER)
uint8_t type
Definition: btrfs.h:277
Status
Definition: gdiplustypes.h:24
#define TRACE(s)
Definition: solgame.cpp:4
#define TYPE_XATTR_ITEM
Definition: btrfs.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define ERR(fmt,...)
Definition: debug.h:110
struct _root * subvol
Definition: btrfs_drv.h:288
#define crc32(crc, buf, len)
Definition: inflate.c:1081
Definition: name.c:38
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint64_t transid
Definition: btrfs.h:274
#define STATUS_SUCCESS
Definition: shellext.h:65
#define BTRFS_TYPE_EA
Definition: btrfs.h:270
uint16_t n
Definition: btrfs.h:276
#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 7778 of file flushthread.c.

7778  {
7779  NTSTATUS Status;
7780 
7781  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
7782 
7783  if (Vcb->need_write && !Vcb->readonly)
7784  Status = do_write(Vcb, NULL);
7785  else
7787 
7788  free_trees(Vcb);
7789 
7790  if (!NT_SUCCESS(Status))
7791  ERR("do_write returned %08lx\n", Status);
7792 
7793  ExReleaseResourceLite(&Vcb->tree_lock);
7794 }
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7759
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
Status
Definition: gdiplustypes.h:24
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
NTSTATUS NTSTATUS bool bool void free_trees(device_extension *Vcb) __attribute__((nonnull(1)))
#define ERR(fmt,...)
Definition: debug.h:110
#define NULL
Definition: types.h:112
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by _Function_class_().

◆ do_splits()

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

Definition at line 3648 of file flushthread.c.

3648  {
3649  ULONG level, max_level;
3650  uint32_t min_size, min_size_fst;
3651  bool empty, done_deletions = false;
3652  NTSTATUS Status;
3653  tree* t;
3654 
3655  TRACE("(%p)\n", Vcb);
3656 
3657  max_level = 0;
3658 
3659  for (level = 0; level <= 255; level++) {
3660  LIST_ENTRY *le, *nextle;
3661 
3662  empty = true;
3663 
3664  TRACE("doing level %lu\n", level);
3665 
3666  le = Vcb->trees.Flink;
3667 
3668  while (le != &Vcb->trees) {
3670 
3671  nextle = le->Flink;
3672 
3673  if (t->write && t->header.level == level) {
3674  empty = false;
3675 
3676  if (t->header.num_items == 0) {
3677  if (t->parent) {
3678  done_deletions = true;
3679 
3680  TRACE("deleting tree in root %I64x\n", t->root->id);
3681 
3682  t->root->root_item.bytes_used -= Vcb->superblock.node_size;
3683 
3684  if (t->has_new_address) { // delete associated EXTENT_ITEM
3685  Status = reduce_tree_extent(Vcb, t->new_address, t, t->parent->header.tree_id, t->header.level, Irp, rollback);
3686 
3687  if (!NT_SUCCESS(Status)) {
3688  ERR("reduce_tree_extent returned %08lx\n", Status);
3689  return Status;
3690  }
3691 
3692  t->has_new_address = false;
3693  } else if (t->has_address) {
3694  Status = reduce_tree_extent(Vcb,t->header.address, t, t->parent->header.tree_id, t->header.level, Irp, rollback);
3695 
3696  if (!NT_SUCCESS(Status)) {
3697  ERR("reduce_tree_extent returned %08lx\n", Status);
3698  return Status;
3699  }
3700 
3701  t->has_address = false;
3702  }
3703 
3704  if (!t->paritem->ignore) {
3705  t->paritem->ignore = true;
3706  t->parent->header.num_items--;
3707  t->parent->size -= sizeof(internal_node);
3708  }
3709 
3710  RemoveEntryList(&t->paritem->list_entry);
3711  ExFreePool(t->paritem);
3712  t->paritem = NULL;
3713 
3714  free_tree(t);
3715  } else if (t->header.level != 0) {
3716  if (t->has_new_address) {
3717  Status = update_extent_level(Vcb, t->new_address, t, 0, Irp);
3718 
3719  if (!NT_SUCCESS(Status)) {
3720  ERR("update_extent_level returned %08lx\n", Status);
3721  return Status;
3722  }
3723  }
3724 
3725  t->header.level = 0;
3726  }
3727  } else if (t->size > Vcb->superblock.node_size - sizeof(tree_header)) {
3728  TRACE("splitting overlarge tree (%x > %Ix)\n", t->size, Vcb->superblock.node_size - sizeof(tree_header));
3729 
3730  if (!t->updated_extents && t->has_address) {
3732  if (!NT_SUCCESS(Status)) {
3733  ERR("update_tree_extents_recursive returned %08lx\n", Status);
3734  return Status;
3735  }
3736  }
3737 
3738  Status = split_tree(Vcb, t);
3739 
3740  if (!NT_SUCCESS(Status)) {
3741  ERR("split_tree returned %08lx\n", Status);
3742  return Status;
3743  }
3744  }
3745  }
3746 
3747  le = nextle;
3748  }
3749 
3750  if (!empty) {
3751  max_level = level;
3752  } else {
3753  TRACE("nothing found for level %lu\n", level);
3754  break;
3755  }
3756  }
3757 
3758  min_size = (Vcb->superblock.node_size - sizeof(tree_header)) / 2;
3759  min_size_fst = (Vcb->superblock.node_size - sizeof(tree_header)) / 4;
3760 
3761  for (level = 0; level <= max_level; level++) {
3762  LIST_ENTRY* le;
3763 
3764  le = Vcb->trees.Flink;
3765 
3766  while (le != &Vcb->trees) {
3768 
3769  if (t->write && t->header.level == level && t->header.num_items > 0 && t->parent &&
3770  ((t->size < min_size && t->root->id != BTRFS_ROOT_FREE_SPACE) || (t->size < min_size_fst && t->root->id == BTRFS_ROOT_FREE_SPACE)) &&
3771  is_tree_unique(Vcb, t, Irp)) {
3772  bool done;
3773 
3774  do {
3775  Status = try_tree_amalgamate(Vcb, t, &done, &done_deletions, Irp, rollback);
3776  if (!NT_SUCCESS(Status)) {
3777  ERR("try_tree_amalgamate returned %08lx\n", Status);
3778  return Status;
3779  }
3780  } while (done && t->size < min_size);
3781  }
3782 
3783  le = le->Flink;
3784  }
3785  }
3786 
3787  // simplify trees if top tree only has one entry
3788 
3789  if (done_deletions) {
3790  for (level = max_level; level > 0; level--) {
3791  LIST_ENTRY *le, *nextle;
3792 
3793  le = Vcb->trees.Flink;
3794  while (le != &Vcb->trees) {
3795  nextle = le->Flink;
3797 
3798  if (t->write && t->header.level == level) {
3799  if (!t->parent && t->header.num_items == 1) {
3800  LIST_ENTRY* le2 = t->itemlist.Flink;
3801  tree_data* td = NULL;
3802  tree* child_tree = NULL;
3803 
3804  while (le2 != &t->itemlist) {
3806  if (!td->ignore)
3807  break;
3808  le2 = le2->Flink;
3809  }
3810 
3811  TRACE("deleting top-level tree in root %I64x with one item\n", t->root->id);
3812 
3813  if (t->has_new_address) { // delete associated EXTENT_ITEM
3814  Status = reduce_tree_extent(Vcb, t->new_address, t, t->header.tree_id, t->header.level, Irp, rollback);
3815 
3816  if (!NT_SUCCESS(Status)) {
3817  ERR("reduce_tree_extent returned %08lx\n", Status);
3818  return Status;
3819  }
3820 
3821  t->has_new_address = false;
3822  } else if (t->has_address) {
3823  Status = reduce_tree_extent(Vcb,t->header.address, t, t->header.tree_id, t->header.level, Irp, rollback);
3824 
3825  if (!NT_SUCCESS(Status)) {
3826  ERR("reduce_tree_extent returned %08lx\n", Status);
3827  return Status;
3828  }
3829 
3830  t->has_address = false;
3831  }
3832 
3833  if (!td->treeholder.tree) { // load first item if not already loaded
3834  KEY searchkey = {0,0,0};
3835  traverse_ptr tp;
3836 
3837  Status = find_item(Vcb, t->root, &tp, &searchkey, false, Irp);
3838  if (!NT_SUCCESS(Status)) {
3839  ERR("error - find_item returned %08lx\n", Status);
3840  return Status;
3841  }
3842  }
3843 
3844  child_tree = td->treeholder.tree;
3845 
3846  if (child_tree) {
3847  child_tree->parent = NULL;
3848  child_tree->paritem = NULL;
3849  }
3850 
3851  t->root->root_item.bytes_used -= Vcb->superblock.node_size;
3852 
3853  free_tree(t);
3854 
3855  if (child_tree)
3856  child_tree->root->treeholder.tree = child_tree;
3857  }
3858  }
3859 
3860  le = nextle;
3861  }
3862  }
3863  }
3864 
3865  return STATUS_SUCCESS;
3866 }
static NTSTATUS split_tree(device_extension *Vcb, tree *t)
Definition: flushthread.c:3197
static NTSTATUS update_extent_level(device_extension *Vcb, uint64_t address, tree *t, uint8_t level, PIRP Irp)
Definition: flushthread.c:3530
GLint level
Definition: gl.h:1546
struct _root * root
Definition: btrfs_drv.h:433
LONG NTSTATUS
Definition: precomp.h:26
tree_holder treeholder
Definition: btrfs_drv.h:411
GLdouble GLdouble t
Definition: gl.h:2047
NTSTATUS NTSTATUS void free_tree(tree *t) __attribute__((nonnull(1)))
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
_In_ PIRP Irp
Definition: csq.h:116
struct _tree * tree
Definition: btrfs_drv.h:401
tree_data * paritem
Definition: btrfs_drv.h:432
struct _tree * parent
Definition: btrfs_drv.h:431
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:2965
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define TRACE(s)
Definition: solgame.cpp:4
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
#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:950
#define Vcb
Definition: cdprocs.h:1415
static NTSTATUS update_tree_extents_recursive(device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:3630
bool is_tree_unique(device_extension *Vcb, tree *t, PIRP Irp)
Definition: flushthread.c:3237
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
bool ignore
Definition: btrfs_drv.h:407
Definition: btrfs.h:143
Definition: list.h:27
#define NULL
Definition: types.h:112
_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:1355
BOOL empty
Definition: button.c:170
UINT32 uint32_t
Definition: types.h:75
#define BTRFS_ROOT_FREE_SPACE
Definition: btrfs.h:62
unsigned int ULONG
Definition: retypes.h:1
#define STATUS_SUCCESS
Definition: shellext.h:65
static NTSTATUS try_tree_amalgamate(device_extension *Vcb, tree *t, bool *done, bool *done_deletions, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:3300
#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 1614 of file flushthread.c.

1614  {
1615  chunk* c;
1616  LIST_ENTRY* le;
1617  tree_write* tw;
1618  NTSTATUS Status;
1619  ULONG i, num_bits;
1620  write_data_context* wtc;
1621  ULONG bit_num = 0;
1622  bool raid56 = false;
1623 
1624  // merge together runs
1625  c = NULL;
1626  le = tree_writes->Flink;
1627  while (le != tree_writes) {
1629 
1630  if (!c || tw->address < c->offset || tw->address >= c->offset + c->chunk_item->size)
1632  else {
1634 
1635  if (tw->address == tw2->address + tw2->length) {
1637 
1638  if (!data) {
1639  ERR("out of memory\n");
1641  }
1642 
1643  RtlCopyMemory(data, tw2->data, tw2->length);
1644  RtlCopyMemory(&data[tw2->length], tw->data, tw->length);
1645 
1646  if (!no_free || tw2->allocated)
1647  ExFreePool(tw2->data);
1648 
1649  tw2->data = data;
1650  tw2->length += tw->length;
1651  tw2->allocated = true;
1652 
1653  if (!no_free || tw->allocated)
1654  ExFreePool(tw->data);
1655 
1657  ExFreePool(tw);
1658 
1659  le = tw2->list_entry.Flink;
1660  continue;
1661  }
1662  }
1663 
1664  tw->c = c;
1665 
1666  if (c->chunk_item->type & (BLOCK_FLAG_RAID5 | BLOCK_FLAG_RAID6))
1667  raid56 = true;
1668 
1669  le = le->Flink;
1670  }
1671 
1672  num_bits = 0;
1673 
1674  le = tree_writes->Flink;
1675  while (le != tree_writes) {
1677 
1678  num_bits++;
1679 
1680  le = le->Flink;
1681  }
1682 
1683  wtc = ExAllocatePoolWithTag(NonPagedPool, sizeof(write_data_context) * num_bits, ALLOC_TAG);
1684  if (!wtc) {
1685  ERR("out of memory\n");
1687  }
1688 
1689  le = tree_writes->Flink;
1690 
1691  while (le != tree_writes) {
1693 
1694  TRACE("address: %I64x, size: %x\n", tw->address, tw->length);
1695 
1696  KeInitializeEvent(&wtc[bit_num].Event, NotificationEvent, false);
1697  InitializeListHead(&wtc[bit_num].stripes);
1698  wtc[bit_num].need_wait = false;
1699  wtc[bit_num].stripes_left = 0;
1700  wtc[bit_num].parity1 = wtc[bit_num].parity2 = wtc[bit_num].scratch = NULL;
1701  wtc[bit_num].mdl = wtc[bit_num].parity1_mdl = wtc[bit_num].parity2_mdl = NULL;
1702 
1703  Status = write_data(Vcb, tw->address, tw->data, tw->length, &wtc[bit_num], NULL, NULL, false, 0, HighPagePriority);
1704  if (!NT_SUCCESS(Status)) {
1705  ERR("write_data returned %08lx\n", Status);
1706 
1707  for (i = 0; i < num_bits; i++) {
1708  free_write_data_stripes(&wtc[i]);
1709  }
1710  ExFreePool(wtc);
1711 
1712  return Status;
1713  }
1714 
1715  bit_num++;
1716 
1717  le = le->Flink;
1718  }
1719 
1720  for (i = 0; i < num_bits; i++) {
1721  if (wtc[i].stripes.Flink != &wtc[i].stripes) {
1722  // launch writes and wait
1723  le = wtc[i].stripes.Flink;
1724  while (le != &wtc[i].stripes) {
1726 
1727  if (stripe->status != WriteDataStatus_Ignore) {
1728  wtc[i].need_wait = true;
1730  }
1731 
1732  le = le->Flink;
1733  }
1734  }
1735  }
1736 
1737  for (i = 0; i < num_bits; i++) {
1738  if (wtc[i].need_wait)
1740  }
1741 
1742  for (i = 0; i < num_bits; i++) {
1743  le = wtc[i].stripes.Flink;
1744  while (le != &wtc[i].stripes) {
1746 
1747  if (stripe->status != WriteDataStatus_Ignore && !NT_SUCCESS(stripe->iosb.Status)) {
1748  Status = stripe->iosb.Status;
1750  break;
1751  }
1752 
1753  le = le->Flink;
1754  }
1755 
1756  free_write_data_stripes(&wtc[i]);
1757  }
1758 
1759  ExFreePool(wtc);
1760 
1761  if (raid56) {
1762  c = NULL;
1763 
1764  le = tree_writes->Flink;
1765  while (le != tree_writes) {
1767 
1768  if (tw->c != c) {
1769  c = tw->c;
1770 
1771  ExAcquireResourceExclusiveLite(&c->partial_stripes_lock, true);
1772 
1773  while (!IsListEmpty(&c->partial_stripes)) {
1775 
1776  Status = flush_partial_stripe(Vcb, c, ps);
1777 
1778  if (ps->bmparr)
1779  ExFreePool(ps->bmparr);
1780 
1781  ExFreePool(ps);
1782 
1783  if (!NT_SUCCESS(Status)) {
1784  ERR("flush_partial_stripe returned %08lx\n", Status);
1785  ExReleaseResourceLite(&c->partial_stripes_lock);
1786  return Status;
1787  }
1788  }
1789 
1790  ExReleaseResourceLite(&c->partial_stripes_lock);
1791  }
1792 
1793  le = le->Flink;
1794  }
1795  }
1796 
1797  return STATUS_SUCCESS;
1798 }
ULONG * bmparr
Definition: btrfs_drv.h:547
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
chunk * c
Definition: btrfs_drv.h:941
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
PDEVICE_OBJECT devobj
Definition: btrfs_drv.h:518
LONG NTSTATUS
Definition: precomp.h:26
Definition: write.c:113
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:87
uint8_t * scratch
Definition: btrfs_drv.h:933
bool allocated
Definition: btrfs_drv.h:942
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
Status
Definition: gdiplustypes.h:24
uint8_t * data
Definition: btrfs_drv.h:940
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define TRACE(s)
Definition: solgame.cpp:4
uint32_t length
Definition: btrfs_drv.h:939
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
uint8_t * parity1
Definition: btrfs_drv.h:933
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:943
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Definition: typedefs.h:119
uint64_t address
Definition: btrfs_drv.h:938
BYTE uint8_t
Definition: msvideo1.c:66
NTSTATUS NTSTATUS NTSTATUS void free_write_data_stripes(write_data_context *wtc) __attribute__((nonnull(1)))
#define ERR(fmt,...)
Definition: debug.h:110
device * device
Definition: write.c:115
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
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
void log_device_error(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ int error)
Definition: btrfs.c:5883
NTSTATUS flush_partial_stripe(device_extension *Vcb, chunk *c, partial_stripe *ps)
Definition: flushthread.c:5840
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
NTSTATUS NTSTATUS write_data(_In_ device_extension *Vcb, _In_ uint64_t address, _In_reads_bytes_(length) void *data, _In_ uint32_t length, _In_ write_data_context *wtc, _In_opt_ PIRP Irp, _In_opt_ chunk *c, _In_ bool file_write, _In_ uint64_t irp_offset, _In_ ULONG priority) __attribute__((nonnull(1
Definition: list.h:27
#define NULL
Definition: types.h:112
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
LIST_ENTRY stripes
Definition: btrfs_drv.h:930
#define BTRFS_DEV_STAT_WRITE_ERRORS
Definition: btrfs.h:539
#define c
Definition: ke_i.h:80
unsigned int ULONG
Definition: retypes.h:1
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
uint8_t * parity2
Definition: btrfs_drv.h:933
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address) __attribute__((nonnull(1)))

Referenced by write_metadata_items(), and write_trees().

◆ do_write()

NTSTATUS do_write ( device_extension Vcb,
PIRP  Irp 
)

Definition at line 7759 of file flushthread.c.

7759  {
7761  NTSTATUS Status;
7762 
7764 
7766 
7767  if (!NT_SUCCESS(Status)) {
7768  ERR("do_write2 returned %08lx, dropping into readonly mode\n", Status);
7769  Vcb->readonly = true;
7772  } else
7774 
7775  return Status;
7776 }
LONG NTSTATUS
Definition: precomp.h:26
_In_ PIRP Irp
Definition: csq.h:116
Status
Definition: gdiplustypes.h:24
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:1415
NTSTATUS NTSTATUS void clear_rollback(LIST_ENTRY *rollback) __attribute__((nonnull(1)))
static NTSTATUS do_write2(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:7359
Definition: typedefs.h:119
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback) __attribute__((nonnull(1
#define ERR(fmt,...)
Definition: debug.h:110
#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:1355
#define FSRTL_VOLUME_FORCED_CLOSED
Definition: fsrtltypes.h:98

Referenced by _Dispatch_type_(), _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 7359 of file flushthread.c.

7359  {
7360  NTSTATUS Status;
7361  LIST_ENTRY *le, batchlist;
7362  bool cache_changed = false;
7364  bool no_cache = false;
7365 #ifdef DEBUG_FLUSH_TIMES
7366  uint64_t filerefs = 0, fcbs = 0;
7367  LARGE_INTEGER freq, time1, time2;
7368 #endif
7369 #ifdef DEBUG_WRITE_LOOPS
7370  UINT loops = 0;
7371 #endif
7372 
7373  TRACE("(%p)\n", Vcb);
7374 
7375  InitializeListHead(&batchlist);
7376 
7377 #ifdef DEBUG_FLUSH_TIMES
7378  time1 = KeQueryPerformanceCounter(&freq);
7379 #endif
7380 
7382  if (!NT_SUCCESS(Status)) {
7383  ERR("check_for_orphans returned %08lx\n", Status);
7384  return Status;
7385  }
7386 
7387  ExAcquireResourceExclusiveLite(&Vcb->dirty_filerefs_lock, true);
7388 
7389  while (!IsListEmpty(&Vcb->dirty_filerefs)) {
7391 
7392  flush_fileref(fr, &batchlist, Irp);
7393  free_fileref(fr);
7394 
7395 #ifdef DEBUG_FLUSH_TIMES
7396  filerefs++;
7397 #endif
7398  }
7399 
7400  ExReleaseResourceLite(&Vcb->dirty_filerefs_lock);
7401 
7402  Status = commit_batch_list(Vcb, &batchlist, Irp);
7403  if (!NT_SUCCESS(Status)) {
7404  ERR("commit_batch_list returned %08lx\n", Status);
7405  return Status;
7406  }
7407 
7408 #ifdef DEBUG_FLUSH_TIMES
7410 
7411  ERR("flushed %I64u filerefs in %I64u (freq = %I64u)\n", filerefs, time2.QuadPart - time1.QuadPart, freq.QuadPart);
7412 
7413  time1 = KeQueryPerformanceCounter(&freq);
7414 #endif
7415 
7416  // We process deleted streams first, so we don't run over our xattr
7417  // limit unless we absolutely have to.
7418  // We also process deleted normal files, to avoid any problems
7419  // caused by inode collisions.
7420 
7421  ExAcquireResourceExclusiveLite(&Vcb->dirty_fcbs_lock, true);
7422 
7423  le = Vcb->dirty_fcbs.Flink;
7424  while (le != &Vcb->dirty_fcbs) {
7425  fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_dirty);
7426  LIST_ENTRY* le2 = le->Flink;
7427 
7428  if (fcb->deleted) {
7429  ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
7430  Status = flush_fcb(fcb, false, &batchlist, Irp);
7431  ExReleaseResourceLite(fcb->Header.Resource);
7432 
7433  free_fcb(fcb);
7434 
7435  if (!NT_SUCCESS(Status)) {
7436  ERR("flush_fcb returned %08lx\n", Status);
7437  clear_batch_list(Vcb, &batchlist);
7438  ExReleaseResourceLite(&Vcb->dirty_fcbs_lock);
7439  return Status;
7440  }
7441 
7442 #ifdef DEBUG_FLUSH_TIMES
7443  fcbs++;
7444 #endif
7445  }
7446 
7447  le = le2;
7448  }
7449 
7450  Status = commit_batch_list(Vcb, &batchlist, Irp);
7451  if (!NT_SUCCESS(Status)) {
7452  ERR("commit_batch_list returned %08lx\n", Status);
7453  ExReleaseResourceLite(&Vcb->dirty_fcbs_lock);
7454  return Status;
7455  }
7456 
7457  le = Vcb->dirty_fcbs.Flink;
7458  while (le != &Vcb->dirty_fcbs) {
7459  fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_dirty);
7460  LIST_ENTRY* le2 = le->Flink;
7461 
7462  if (fcb->subvol != Vcb->root_root) {
7463  ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
7464  Status = flush_fcb(fcb, false, &batchlist, Irp);
7465  ExReleaseResourceLite(fcb->Header.Resource);
7466  free_fcb(fcb);
7467 
7468  if (!NT_SUCCESS(Status)) {
7469  ERR("flush_fcb returned %08lx\n", Status);
7470  ExReleaseResourceLite(&Vcb->dirty_fcbs_lock);
7471  return Status;
7472  }
7473 
7474 #ifdef DEBUG_FLUSH_TIMES
7475  fcbs++;
7476 #endif
7477  }
7478 
7479  le = le2;
7480  }
7481 
7482  ExReleaseResourceLite(&Vcb->dirty_fcbs_lock);
7483 
7484  Status = commit_batch_list(Vcb, &batchlist, Irp);
7485  if (!NT_SUCCESS(Status)) {
7486  ERR("commit_batch_list returned %08lx\n", Status);
7487  return Status;
7488  }
7489 
7490 #ifdef DEBUG_FLUSH_TIMES
7492 
7493  ERR("flushed %I64u fcbs in %I64u (freq = %I64u)\n", filerefs, time2.QuadPart - time1.QuadPart, freq.QuadPart);
7494 #endif
7495 
7496  // no need to get dirty_subvols_lock here, as we have tree_lock exclusively
7497  while (!IsListEmpty(&Vcb->dirty_subvols)) {
7499 
7500  Status = flush_subvol(Vcb, r, Irp);
7501  if (!NT_SUCCESS(Status)) {
7502  ERR("flush_subvol returned %08lx\n", Status);
7503  return Status;
7504  }
7505  }
7506 
7507  if (!IsListEmpty(&Vcb->drop_roots)) {
7509 
7510  if (!NT_SUCCESS(Status)) {
7511  ERR("drop_roots returned %08lx\n", Status);
7512  return Status;
7513  }
7514  }
7515 
7516  Status = update_chunks(Vcb, &batchlist, Irp, rollback);
7517 
7518  if (!NT_SUCCESS(Status)) {
7519  ERR("update_chunks returned %08lx\n", Status);
7520  return Status;
7521  }
7522 
7523  Status = commit_batch_list(Vcb, &batchlist, Irp);
7524 
7525  // If only changing superblock, e.g. changing label, we still need to rewrite
7526  // the root tree so the generations match, otherwise you won't be able to mount on Linux.
7527  if (!Vcb->root_root->treeholder.tree || !Vcb->root_root->treeholder.tree->write) {
7528  KEY searchkey;
7529 
7530  traverse_ptr tp;
7531 
7532  searchkey.obj_id = 0;
7533  searchkey.obj_type = 0;
7534  searchkey.offset = 0;
7535 
7536  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
7537  if (!NT_SUCCESS(Status)) {
7538  ERR("error - find_item returned %08lx\n", Status);
7539  return Status;
7540  }
7541 
7542  Vcb->root_root->treeholder.tree->write = true;
7543  }
7544 
7545  // make sure we always update the extent tree
7547  if (!NT_SUCCESS(Status)) {
7548  ERR("add_root_item_to_cache returned %08lx\n", Status);
7549  return Status;
7550  }
7551 
7552  if (Vcb->stats_changed) {
7553  le = Vcb->devices.Flink;
7554  while (le != &Vcb->devices) {
7556 
7557  if (dev->stats_changed) {
7559  if (!NT_SUCCESS(Status)) {
7560  ERR("flush_changed_dev_stats returned %08lx\n", Status);
7561  return Status;
7562  }
7563  dev->stats_changed = false;
7564  }
7565 
7566  le = le->Flink;
7567  }
7568 
7569  Vcb->stats_changed = false;
7570  }
7571 
7572  do {
7573  Status = add_parents(Vcb, Irp);
7574  if (!NT_SUCCESS(Status)) {
7575  ERR("add_parents returned %08lx\n", Status);
7576  goto end;
7577  }
7578 
7580  if (!NT_SUCCESS(Status)) {
7581  ERR("allocate_tree_extents returned %08lx\n", Status);
7582  goto end;
7583  }
7584 
7586  if (!NT_SUCCESS(Status)) {
7587  ERR("do_splits returned %08lx\n", Status);
7588  goto end;
7589  }
7590 
7592  if (!NT_SUCCESS(Status)) {
7593  ERR("update_chunk_usage returned %08lx\n", Status);
7594  goto end;
7595  }
7596 
7597  if (!(Vcb->superblock.compat_ro_flags & BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE)) {
7598  if (!no_cache) {
7599  Status = allocate_cache(Vcb, &cache_changed, Irp, rollback);
7600  if (!NT_SUCCESS(Status)) {
7601  WARN("allocate_cache returned %08lx\n", Status);
7602  no_cache = true;
7603  cache_changed = false;
7604  }
7605  }
7606  } else {
7608  if (!NT_SUCCESS(Status)) {
7609  ERR("update_chunk_caches_tree returned %08lx\n", Status);
7610  goto end;
7611  }
7612  }
7613 
7614 #ifdef DEBUG_WRITE_LOOPS
7615  loops++;
7616 
7617  if (cache_changed)
7618  ERR("cache has changed, looping again\n");
7619 #endif
7620  } while (cache_changed || !trees_consistent(Vcb));
7621 
7622 #ifdef DEBUG_WRITE_LOOPS
7623  ERR("%u loops\n", loops);
7624 #endif
7625 
7626  TRACE("trees consistent\n");
7627 
7628  Status = update_root_root(Vcb, no_cache, Irp, rollback);
7629  if (!NT_SUCCESS(Status)) {
7630  ERR("update_root_root returned %08lx\n", Status);
7631  goto end;
7632  }
7633 
7634  Status = write_trees(Vcb, Irp);
7635  if (!NT_SUCCESS(Status)) {
7636  ERR("write_trees returned %08lx\n", Status);
7637  goto end;
7638  }
7639 
7641  if (!NT_SUCCESS(Status)) {
7642  ERR("test_not_full returned %08lx\n", Status);
7643  goto end;
7644  }
7645 
7646 #ifdef DEBUG_PARANOID
7647  le = Vcb->trees.Flink;
7648  while (le != &Vcb->trees) {
7650  KEY searchkey;
7651  traverse_ptr tp;
7652 
7653  searchkey.obj_id = t->header.address;
7654  searchkey.obj_type = TYPE_METADATA_ITEM;
7655  searchkey.offset = 0xffffffffffffffff;
7656 
7657  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
7658  if (!NT_SUCCESS(Status)) {
7659  ERR("error - find_item returned %08lx\n", Status);
7660  goto end;
7661  }
7662 
7663  if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
7664  searchkey.obj_id = t->header.address;
7665  searchkey.obj_type = TYPE_EXTENT_ITEM;
7666  searchkey.offset = 0xffffffffffffffff;
7667 
7668  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
7669  if (!NT_SUCCESS(Status)) {
7670  ERR("error - find_item returned %08lx\n", Status);
7671  goto end;
7672  }
7673 
7674  if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
7675  ERR("error - could not find entry in extent tree for tree at %I64x\n", t->header.address);
7677  goto end;
7678  }
7679  }
7680 
7681  le = le->Flink;
7682  }
7683 #endif
7684 
7685  Vcb->superblock.cache_generation = Vcb->superblock.generation;
7686 
7687  if (!Vcb->options.no_barrier)
7689 
7691  if (!NT_SUCCESS(Status)) {
7692  ERR("write_superblocks returned %08lx\n", Status);
7693  goto end;
7694  }
7695 
7696  vde = Vcb->vde;
7697 
7698  if (vde) {
7699  pdo_device_extension* pdode = vde->pdode;
7700 
7701  ExAcquireResourceSharedLite(&pdode->child_lock, true);
7702 
7703  le = pdode->children.Flink;
7704 
7705  while (le != &pdode->children) {
7707 
7708  vc->generation = Vcb->superblock.generation;
7709  le = le->Flink;
7710  }
7711 
7713  }
7714 
7716 
7717  le = Vcb->chunks.Flink;
7718  while (le != &Vcb->chunks) {
7720 
7721  c->changed = false;
7722  c->space_changed = false;
7723 
7724  le = le->Flink;
7725  }
7726 
7727  Vcb->superblock.generation++;
7728 
7730 
7731  le = Vcb->trees.Flink;
7732  while (le != &Vcb->trees) {
7734 
7735  t->write = false;
7736 
7737  le = le->Flink;
7738  }
7739 
7740  Vcb->need_write = false;
7741 
7742  while (!IsListEmpty(&Vcb->drop_roots)) {
7744 
7745  if (IsListEmpty(&r->fcbs)) {
7746  ExDeleteResourceLite(&r->nonpaged->load_tree_lock);
7747  ExFreePool(r->nonpaged);
7748  ExFreePool(r);
7749  } else
7750  r->dropped = true;
7751  }
7752 
7753 end:
7754  TRACE("do_write returning %08lx\n", Status);
7755 
7756  return Status;
7757 }
static NTSTATUS allocate_tree_extents(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:1459
uint64_t obj_id
Definition: btrfs.h:144
static NTSTATUS check_for_orphans(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7332
LARGE_INTEGER NTAPI KeQueryPerformanceCounter(IN PLARGE_INTEGER PerformanceFreq)
Definition: timer.c:138
static NTSTATUS add_parents(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:609
uint8_t obj_type
Definition: btrfs.h:145
static NTSTATUS flush_fileref(file_ref *fileref, LIST_ENTRY *batchlist, PIRP Irp)
Definition: flushthread.c:6406
static NTSTATUS update_root_root(device_extension *Vcb, bool no_cache, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:1551
static NTSTATUS update_chunk_usage(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:2804
static bool trees_consistent(device_extension *Vcb)
Definition: flushthread.c:572
void free_fcb(_Inout_ fcb *fcb)
Definition: btrfs.c:1703
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
GLdouble GLdouble t
Definition: gl.h:2047
static void clean_space_cache(device_extension *Vcb)
Definition: flushthread.c:397
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:4806
#define TYPE_METADATA_ITEM
Definition: btrfs.h:36
static NTSTATUS do_splits(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:3648
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
uint64_t offset
Definition: btrfs.h:146
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
NTSTATUS update_chunk_caches_tree(device_extension *Vcb, PIRP Irp)
Definition: free-space.c:2113
_In_ PIRP Irp
Definition: csq.h:116
uint64_t generation
Definition: btrfs_drv.h:848
Definition: devices.h:37
static NTSTATUS drop_roots(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:4066
static NTSTATUS flush_changed_dev_stats(device_extension *Vcb, device *dev, PIRP Irp)
Definition: flushthread.c:6882
static NTSTATUS test_not_full(device_extension *Vcb)
Definition: flushthread.c:7053
static NTSTATUS update_chunks(device_extension *Vcb, LIST_ENTRY *batchlist, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:6015
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:35
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
struct pdo_device_extension * pdode
Definition: btrfs_drv.h:870
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