ReactOS  0.4.15-dev-338-g3dad100
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) - sizeof(leaf_node))
 
#define DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED   0x80000000
 

Typedefs

typedef struct _write_superblocks_context write_superblocks_context
 

Functions

static NTSTATUS create_chunk (device_extension *Vcb, chunk *c, PIRP Irp)
 
static NTSTATUS update_tree_extents (device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
 
 _Function_class_ (IO_COMPLETION_ROUTINE)
 
NTSTATUS write_data_phys (_In_ PDEVICE_OBJECT device, _In_ PFILE_OBJECT fileobj, _In_ uint64_t address, _In_reads_bytes_(length) void *data, _In_ uint32_t length)
 
static void add_trim_entry (device *dev, uint64_t address, uint64_t size)
 
static void clean_space_cache_chunk (device_extension *Vcb, chunk *c)
 
static void clean_space_cache (device_extension *Vcb)
 
static bool trees_consistent (device_extension *Vcb)
 
static NTSTATUS add_parents (device_extension *Vcb, PIRP Irp)
 
static void add_parents_to_cache (tree *t)
 
static bool insert_tree_extent_skinny (device_extension *Vcb, uint8_t level, uint64_t root_id, chunk *c, uint64_t address, PIRP Irp, LIST_ENTRY *rollback)
 
bool find_metadata_address_in_chunk (device_extension *Vcb, chunk *c, uint64_t *address)
 
static bool insert_tree_extent (device_extension *Vcb, uint8_t level, uint64_t root_id, chunk *c, uint64_t *new_address, PIRP Irp, LIST_ENTRY *rollback)
 
NTSTATUS get_tree_new_address (device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
 
static NTSTATUS reduce_tree_extent (device_extension *Vcb, uint64_t address, tree *t, uint64_t parent_root, uint8_t level, PIRP Irp, LIST_ENTRY *rollback)
 
static NTSTATUS add_changed_extent_ref_edr (changed_extent *ce, EXTENT_DATA_REF *edr, bool old)
 
static NTSTATUS add_changed_extent_ref_sdr (changed_extent *ce, SHARED_DATA_REF *sdr, bool old)
 
static bool shared_tree_is_unique (device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
 
static NTSTATUS allocate_tree_extents (device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
 
static NTSTATUS update_root_root (device_extension *Vcb, bool no_cache, PIRP Irp, LIST_ENTRY *rollback)
 
NTSTATUS do_tree_writes (device_extension *Vcb, LIST_ENTRY *tree_writes, bool no_free)
 
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

◆ DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED

#define DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED   0x80000000

Definition at line 50 of file flushthread.c.

◆ MAX_CSUM_SIZE

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

Definition at line 25 of file flushthread.c.

Typedef Documentation

◆ write_superblocks_context

Function Documentation

◆ _Function_class_() [1/2]

_Function_class_ ( IO_COMPLETION_ROUTINE  )

Definition at line 53 of file flushthread.c.

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

◆ _Function_class_() [2/2]

_Function_class_ ( KSTART_ROUTINE  )

Definition at line 7826 of file flushthread.c.

7827  {
7828  DEVICE_OBJECT* devobj = context;
7830  LARGE_INTEGER due_time;
7831 
7832  ObReferenceObject(devobj);
7833 
7834  KeInitializeTimer(&Vcb->flush_thread_timer);
7835 
7836  due_time.QuadPart = (uint64_t)Vcb->options.flush_interval * -10000000;
7837 
7838  KeSetTimer(&Vcb->flush_thread_timer, due_time, NULL);
7839 
7840  while (true) {
7841  KeWaitForSingleObject(&Vcb->flush_thread_timer, Executive, KernelMode, false, NULL);
7842 
7843  if (!(devobj->Vpb->Flags & VPB_MOUNTED) || Vcb->removing)
7844  break;
7845 
7846  if (!Vcb->locked)
7847  do_flush(Vcb);
7848 
7849  KeSetTimer(&Vcb->flush_thread_timer, due_time, NULL);
7850  }
7851 
7852  ObDereferenceObject(devobj);
7853  KeCancelTimer(&Vcb->flush_thread_timer);
7854 
7855  KeSetEvent(&Vcb->flush_thread_finished, 0, false);
7856 
7858 }
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281
Definition: http.c:7094
static void do_flush(device_extension *Vcb)
Definition: flushthread.c:7808
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
PVOID DeviceExtension
Definition: env_spec_w32.h:418
smooth NULL
Definition: ftsmooth.c:416
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
#define Vcb
Definition: cdprocs.h:1425
#define uint64_t
Definition: nsiface.idl:62
NTSTATUS NTAPI PsTerminateSystemThread(IN NTSTATUS ExitStatus)
Definition: kill.c:1144
#define ObReferenceObject
Definition: obfuncs.h:204
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define VPB_MOUNTED
Definition: iotypes.h:1764
LONGLONG QuadPart
Definition: typedefs.h:113

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

1000  {
1001  LIST_ENTRY *le2, *list;
1002  changed_extent_ref* cer;
1003 
1004  list = old ? &ce->old_refs : &ce->refs;
1005 
1006  le2 = list->Flink;
1007  while (le2 != list) {
1009 
1010  if (cer->type == TYPE_EXTENT_DATA_REF && cer->edr.root == edr->root && cer->edr.objid == edr->objid && cer->edr.offset == edr->offset) {
1011  cer->edr.count += edr->count;
1012  goto end;
1013  }
1014 
1015  le2 = le2->Flink;
1016  }
1017 
1019  if (!cer) {
1020  ERR("out of memory\n");
1022  }
1023 
1024  cer->type = TYPE_EXTENT_DATA_REF;
1025  RtlCopyMemory(&cer->edr, edr, sizeof(EXTENT_DATA_REF));
1026  InsertTailList(list, &cer->list_entry);
1027 
1028 end:
1029  if (old)
1030  ce->old_count += edr->count;
1031  else
1032  ce->count += edr->count;
1033 
1034  return STATUS_SUCCESS;
1035 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
uint64_t offset
Definition: btrfs.h:407
LIST_ENTRY list_entry
Definition: btrfs_drv.h:626
uint64_t objid
Definition: btrfs.h:406
GLuint GLuint end
Definition: gl.h:1545
#define InsertTailList(ListHead, Entry)
LIST_ENTRY old_refs
Definition: btrfs_drv.h:614
#define ALLOC_TAG
Definition: btrfs_drv.h:91
EXTENT_DATA_REF edr
Definition: btrfs_drv.h:622
uint32_t count
Definition: btrfs.h:408
uint64_t count
Definition: btrfs_drv.h:609
uint64_t root
Definition: btrfs.h:405
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define TYPE_EXTENT_DATA_REF
Definition: btrfs.h:34
struct _LIST_ENTRY * Flink
Definition: typedefs.h:120
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Definition: _list.h:228
Definition: typedefs.h:118
#define ERR(fmt,...)
Definition: debug.h:110
#define list
Definition: rosglue.h:35
LIST_ENTRY refs
Definition: btrfs_drv.h:613
Definition: list.h:27
return STATUS_SUCCESS
Definition: btrfs.c:3014
uint64_t old_count
Definition: btrfs_drv.h:610

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

1037  {
1038  LIST_ENTRY *le2, *list;
1039  changed_extent_ref* cer;
1040 
1041  list = old ? &ce->old_refs : &ce->refs;
1042 
1043  le2 = list->Flink;
1044  while (le2 != list) {
1046 
1047  if (cer->type == TYPE_SHARED_DATA_REF && cer->sdr.offset == sdr->offset) {
1048  cer->sdr.count += sdr->count;
1049  goto end;
1050  }
1051 
1052  le2 = le2->Flink;
1053  }
1054 
1056  if (!cer) {
1057  ERR("out of memory\n");
1059  }
1060 
1061  cer->type = TYPE_SHARED_DATA_REF;
1062  RtlCopyMemory(&cer->sdr, sdr, sizeof(SHARED_DATA_REF));
1063  InsertTailList(list, &cer->list_entry);
1064 
1065 end:
1066  if (old)
1067  ce->old_count += sdr->count;
1068  else
1069  ce->count += sdr->count;
1070 
1071  return STATUS_SUCCESS;
1072 }
SHARED_DATA_REF sdr
Definition: btrfs_drv.h:623
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LIST_ENTRY list_entry
Definition: btrfs_drv.h:626
GLuint GLuint end
Definition: gl.h:1545
#define InsertTailList(ListHead, Entry)
LIST_ENTRY old_refs
Definition: btrfs_drv.h:614
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint64_t count
Definition: btrfs_drv.h:609
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:120
#define TYPE_SHARED_DATA_REF
Definition: btrfs.h:37
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
uint32_t count
Definition: btrfs.h:430
Definition: _list.h:228
Definition: typedefs.h:118
#define ERR(fmt,...)
Definition: debug.h:110
#define list
Definition: rosglue.h:35
LIST_ENTRY refs
Definition: btrfs_drv.h:613
Definition: list.h:27
return STATUS_SUCCESS
Definition: btrfs.c:3014
uint64_t offset
Definition: btrfs.h:429
uint64_t old_count
Definition: btrfs_drv.h:610

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

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

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

◆ add_parents()

static NTSTATUS add_parents ( device_extension Vcb,
PIRP  Irp 
)
static

Definition at line 601 of file flushthread.c.

601  {
602  ULONG level;
603  LIST_ENTRY* le;
604 
605  for (level = 0; level <= 255; level++) {
606  bool nothing_found = true;
607 
608  TRACE("level = %lu\n", level);
609 
610  le = Vcb->trees.Flink;
611  while (le != &Vcb->trees) {
613 
614  if (t->write && t->header.level == level) {
615  TRACE("tree %p: root = %I64x, level = %x, parent = %p\n", t, t->header.tree_id, t->header.level, t->parent);
616 
617  nothing_found = false;
618 
619  if (t->parent) {
620  if (!t->parent->write)
621  TRACE("adding tree %p (level %x)\n", t->parent, t->header.level);
622 
623  t->parent->write = true;
624  } else if (t->root != Vcb->root_root && t->root != Vcb->chunk_root) {
625  KEY searchkey;
628 #ifdef __REACTOS__
629  tree* t2;
630 #endif
631 
632  searchkey.obj_id = t->root->id;
633  searchkey.obj_type = TYPE_ROOT_ITEM;
634  searchkey.offset = 0xffffffffffffffff;
635 
636  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
637  if (!NT_SUCCESS(Status)) {
638  ERR("error - find_item returned %08lx\n", Status);
639  return Status;
640  }
641 
642  if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
643  ERR("could not find ROOT_ITEM for tree %I64x\n", searchkey.obj_id);
644  return STATUS_INTERNAL_ERROR;
645  }
646 
647  if (tp.item->size < sizeof(ROOT_ITEM)) { // if not full length, delete and create new entry
649 
650  if (!ri) {
651  ERR("out of memory\n");
653  }
654 
655  RtlCopyMemory(ri, &t->root->root_item, sizeof(ROOT_ITEM));
656 
658  if (!NT_SUCCESS(Status)) {
659  ERR("delete_tree_item returned %08lx\n", Status);
660  ExFreePool(ri);
661  return Status;
662  }
663 
664  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);
665  if (!NT_SUCCESS(Status)) {
666  ERR("insert_tree_item returned %08lx\n", Status);
667  ExFreePool(ri);
668  return Status;
669  }
670  }
671 
672 #ifndef __REACTOS__
673  tree* t2 = tp.tree;
674 #else
675  t2 = tp.tree;
676 #endif
677  while (t2) {
678  t2->write = true;
679 
680  t2 = t2->parent;
681  }
682  }
683  }
684 
685  le = le->Flink;
686  }
687 
688  if (nothing_found)
689  break;
690  }
691 
692  return STATUS_SUCCESS;
693 }
uint64_t obj_id
Definition: btrfs.h:137
GLint level
Definition: gl.h:1546
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PIRP Irp
Definition: csq.h:116
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
GLdouble GLdouble t
Definition: gl.h:2047
uint64_t offset
Definition: btrfs.h:139
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:91
tree * tree
Definition: btrfs_drv.h:517
smooth NULL
Definition: ftsmooth.c:416
struct _tree * parent
Definition: btrfs_drv.h:447
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:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
struct _LIST_ENTRY * Flink
Definition: typedefs.h:120
#define TRACE(s)
Definition: solgame.cpp:4
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp)
Definition: treefuncs.c:858
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:518
Definition: typedefs.h:118
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
#define TYPE_ROOT_ITEM
Definition: btrfs.h:28
Definition: list.h:27
unsigned int ULONG
Definition: retypes.h:1
return STATUS_SUCCESS
Definition: btrfs.c:3014
bool write
Definition: btrfs_drv.h:456
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:990

Referenced by do_write2().

◆ add_parents_to_cache()

static void add_parents_to_cache ( tree t)
static

Definition at line 695 of file flushthread.c.

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

6377  {
6378  KEY searchkey;
6379  traverse_ptr tp;
6380  NTSTATUS Status;
6381 
6382  searchkey.obj_id = root;
6383  searchkey.obj_type = TYPE_ROOT_ITEM;
6384  searchkey.offset = 0xffffffffffffffff;
6385 
6386  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
6387  if (!NT_SUCCESS(Status)) {
6388  ERR("error - find_item returned %08lx\n", Status);
6389  return Status;
6390  }
6391 
6392  if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
6393  ERR("could not find ROOT_ITEM for tree %I64x\n", searchkey.obj_id);
6394  return STATUS_INTERNAL_ERROR;
6395  }
6396 
6397  if (tp.item->size < sizeof(ROOT_ITEM)) { // if not full length, create new entry with new bits zeroed
6399  if (!ri) {
6400  ERR("out of memory\n");
6402  }
6403 
6404  if (tp.item->size > 0)
6405  RtlCopyMemory(ri, tp.item->data, tp.item->size);
6406 
6407  RtlZeroMemory(((uint8_t*)ri) + tp.item->size, sizeof(ROOT_ITEM) - tp.item->size);
6408 
6410  if (!NT_SUCCESS(Status)) {
6411  ERR("delete_tree_item returned %08lx\n", Status);
6412  ExFreePool(ri);
6413  return Status;
6414  }
6415 
6416  Status = insert_tree_item(Vcb, Vcb->root_root, searchkey.obj_id, searchkey.obj_type, tp.item->key.offset, ri, sizeof(ROOT_ITEM), NULL, Irp);
6417  if (!NT_SUCCESS(Status)) {
6418  ERR("insert_tree_item returned %08lx\n", Status);
6419  ExFreePool(ri);
6420  return Status;
6421  }
6422  } else {
6423  tp.tree->write = true;
6424  }
6425 
6426  return STATUS_SUCCESS;
6427 }
uint64_t obj_id
Definition: btrfs.h:137
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PIRP Irp
Definition: csq.h:116
struct _root root
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:91
tree * tree
Definition: btrfs_drv.h:517
smooth NULL
Definition: ftsmooth.c:416
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp)
Definition: treefuncs.c:858
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:518
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
#define TYPE_ROOT_ITEM
Definition: btrfs.h:28
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
return STATUS_SUCCESS
Definition: btrfs.c:3014
bool write
Definition: btrfs_drv.h:456
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:990

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

6248  {
6249  KEY searchkey;
6250  traverse_ptr tp;
6251  NTSTATUS Status;
6252 
6253  searchkey.obj_id = parsubvolid;
6254  searchkey.obj_type = TYPE_ROOT_REF;
6255  searchkey.offset = subvolid;
6256 
6257  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
6258  if (!NT_SUCCESS(Status)) {
6259  ERR("error - find_item returned %08lx\n", Status);
6260  return Status;
6261  }
6262 
6263  if (!keycmp(searchkey, tp.item->key)) {
6264  uint16_t rrsize = tp.item->size + (uint16_t)offsetof(ROOT_REF, name[0]) + rr->n;
6265  uint8_t* rr2;
6266 
6267  rr2 = ExAllocatePoolWithTag(PagedPool, rrsize, ALLOC_TAG);
6268  if (!rr2) {
6269  ERR("out of memory\n");
6271  }
6272 
6273  if (tp.item->size > 0)
6274  RtlCopyMemory(rr2, tp.item->data, tp.item->size);
6275 
6276  RtlCopyMemory(rr2 + tp.item->size, rr, offsetof(ROOT_REF, name[0]) + rr->n);
6277  ExFreePool(rr);
6278 
6280  if (!NT_SUCCESS(Status)) {
6281  ERR("delete_tree_item returned %08lx\n", Status);
6282  ExFreePool(rr2);
6283  return Status;
6284  }
6285 
6286  Status = insert_tree_item(Vcb, Vcb->root_root, searchkey.obj_id, searchkey.obj_type, searchkey.offset, rr2, rrsize, NULL, Irp);
6287  if (!NT_SUCCESS(Status)) {
6288  ERR("insert_tree_item returned %08lx\n", Status);
6289  ExFreePool(rr2);
6290  return Status;
6291  }
6292  } else {
6293  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);
6294  if (!NT_SUCCESS(Status)) {
6295  ERR("insert_tree_item returned %08lx\n", Status);
6296  ExFreePool(rr);
6297  return Status;
6298  }
6299  }
6300 
6301  return STATUS_SUCCESS;
6302 }
#define TYPE_ROOT_REF
Definition: btrfs.h:30
uint64_t obj_id
Definition: btrfs.h:137
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PIRP Irp
Definition: csq.h:116
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1024
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
#define ALLOC_TAG
Definition: btrfs_drv.h:91
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp)
Definition: treefuncs.c:858
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:518
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
Definition: name.c:38
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:990

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

4166  {
4167  sys_chunk* sc;
4168  LIST_ENTRY* le;
4169 
4170  if (Vcb->superblock.n + sizeof(KEY) + size > SYS_CHUNK_ARRAY_SIZE) {
4171  ERR("error - bootstrap is full\n");
4172  return STATUS_INTERNAL_ERROR;
4173  }
4174 
4176  if (!sc) {
4177  ERR("out of memory\n");
4179  }
4180 
4181  sc->key.obj_id = obj_id;
4182  sc->key.obj_type = obj_type;
4183  sc->key.offset = offset;
4184  sc->size = size;
4186  if (!sc->data) {
4187  ERR("out of memory\n");
4188  ExFreePool(sc);
4190  }
4191 
4192  RtlCopyMemory(sc->data, data, sc->size);
4193 
4194  le = Vcb->sys_chunks.Flink;
4195  while (le != &Vcb->sys_chunks) {
4197 
4198  if (keycmp(sc2->key, sc->key) == 1)
4199  break;
4200 
4201  le = le->Flink;
4202  }
4203  InsertTailList(le, &sc->list_entry);
4204 
4205  Vcb->superblock.n += sizeof(KEY) + size;
4206 
4208 
4209  return STATUS_SUCCESS;
4210 }
uint64_t obj_id
Definition: btrfs.h:137
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1024
GLintptr offset
Definition: glext.h:5920
#define InsertTailList(ListHead, Entry)
uint64_t offset
Definition: btrfs.h:139
#define SYS_CHUNK_ARRAY_SIZE
Definition: btrfs.h:187
static void regen_bootstrap(device_extension *Vcb)
Definition: flushthread.c:4144
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:91
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:120
GLsizeiptr size
Definition: glext.h:5919
#define Vcb
Definition: cdprocs.h:1425
LIST_ENTRY list_entry
Definition: btrfs_drv.h:633
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:118
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
#define KEY
Definition: profile.c:30
Definition: list.h:27
USHORT size
Definition: btrfs_drv.h:632
return STATUS_SUCCESS
Definition: btrfs.c:3014
void * data
Definition: btrfs_drv.h:631
#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 152 of file flushthread.c.

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

5401  {
5402  int i;
5403  ULONG sblen = (ULONG)sector_align(sizeof(superblock), Vcb->superblock.sector_size);
5404 
5405  i = 0;
5406  while (superblock_addrs[i] != 0) {
5407  if (superblock_addrs[i] + sblen >= address && superblock_addrs[i] < address + size) {
5408  if (superblock_addrs[i] > address)
5410 
5411  if (size <= superblock_addrs[i] + sblen - address)
5412  return;
5413 
5414  size -= superblock_addrs[i] + sblen - address;
5415  address = superblock_addrs[i] + sblen;
5416  } else if (superblock_addrs[i] > address + size)
5417  break;
5418 
5419  i++;
5420  }
5421 
5423 }
static void add_trim_entry(device *dev, uint64_t address, uint64_t size)
Definition: flushthread.c:152
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizeiptr size
Definition: glext.h:5919
#define Vcb
Definition: cdprocs.h:1425
GLuint address
Definition: glext.h:9393
static const uint64_t superblock_addrs[]
Definition: btrfs.h:13
unsigned int ULONG
Definition: retypes.h:1
static uint64_t __inline sector_align(uint64_t n, uint64_t a)

Referenced by drop_chunk(), and trim_unalloc_space().

◆ allocate_tree_extents()

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

Definition at line 1458 of file flushthread.c.

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

Referenced by do_write2().

◆ calc_superblock_checksum()

static void calc_superblock_checksum ( superblock sb)
static

Definition at line 2204 of file flushthread.c.

2204  {
2205  switch (sb->csum_type) {
2206  case CSUM_TYPE_CRC32C:
2207  *(uint32_t*)sb = ~calc_crc32c(0xffffffff, (uint8_t*)&sb->uuid, (ULONG)sizeof(superblock) - sizeof(sb->checksum));
2208  break;
2209 
2210  case CSUM_TYPE_XXHASH:
2211  *(uint64_t*)sb = XXH64(&sb->uuid, sizeof(superblock) - sizeof(sb->checksum), 0);
2212  break;
2213 
2214  case CSUM_TYPE_SHA256:
2215  calc_sha256((uint8_t*)sb, &sb->uuid, sizeof(superblock) - sizeof(sb->checksum));
2216  break;
2217 
2218  case CSUM_TYPE_BLAKE2:
2219  blake2b((uint8_t*)sb, BLAKE2_HASH_SIZE, &sb->uuid, sizeof(superblock) - sizeof(sb->checksum));
2220  break;
2221  }
2222 }
superblock * sb
Definition: btrfs.c:4220
#define CSUM_TYPE_BLAKE2
Definition: btrfs.h:128
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:125
void calc_sha256(uint8_t *hash, const void *input, size_t len)
Definition: sha256.c:126
uint16_t csum_type
Definition: btrfs.h:240
uint8_t checksum[32]
Definition: btrfs.h:217
#define CSUM_TYPE_XXHASH
Definition: btrfs.h:126
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:127
UINT64 uint64_t
Definition: types.h:77
BTRFS_UUID uuid
Definition: btrfs.h:218
UINT32 uint32_t
Definition: types.h:75
#define BLAKE2_HASH_SIZE
Definition: btrfs_drv.h:1252
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 1799 of file flushthread.c.

1799  {
1800  switch (Vcb->superblock.csum_type) {
1801  case CSUM_TYPE_CRC32C:
1802  *((uint32_t*)th) = ~calc_crc32c(0xffffffff, (uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
1803  break;
1804 
1805  case CSUM_TYPE_XXHASH:
1806  *((uint64_t*)th) = XXH64((uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum), 0);
1807  break;
1808 
1809  case CSUM_TYPE_SHA256:
1810  calc_sha256((uint8_t*)th, &th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
1811  break;
1812 
1813  case CSUM_TYPE_BLAKE2:
1814  blake2b((uint8_t*)th, BLAKE2_HASH_SIZE, &th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
1815  break;
1816  }
1817 }
#define CSUM_TYPE_BLAKE2
Definition: btrfs.h:128
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:147
#define CSUM_TYPE_CRC32C
Definition: btrfs.h:125
void calc_sha256(uint8_t *hash, const void *input, size_t len)
Definition: sha256.c:126
#define Vcb
Definition: cdprocs.h:1425
#define CSUM_TYPE_XXHASH
Definition: btrfs.h:126
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:127
UINT64 uint64_t
Definition: types.h:77
BTRFS_UUID fs_uuid
Definition: btrfs.h:148
UINT32 uint32_t
Definition: types.h:75
#define BLAKE2_HASH_SIZE
Definition: btrfs_drv.h:1252

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

7362  {
7363  NTSTATUS Status;
7364  LIST_ENTRY* le;
7365 
7366  if (IsListEmpty(&Vcb->dirty_filerefs))
7367  return STATUS_SUCCESS;
7368 
7369  le = Vcb->dirty_filerefs.Flink;
7370  while (le != &Vcb->dirty_filerefs) {
7372 
7373  if (!fr->fcb->subvol->checked_for_orphans) {
7375  if (!NT_SUCCESS(Status)) {
7376  ERR("check_for_orphans_root returned %08lx\n", Status);
7377  return Status;
7378  }
7379 
7380  fr->fcb->subvol->checked_for_orphans = true;
7381  }
7382 
7383  le = le->Flink;
7384  }
7385 
7386  return STATUS_SUCCESS;
7387 }
static NTSTATUS check_for_orphans_root(device_extension *Vcb, root *r, PIRP Irp)
Definition: flushthread.c:7287
_In_ PIRP Irp
Definition: csq.h:116
LONG NTSTATUS
Definition: precomp.h:26
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:120
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
fcb * fcb
Definition: btrfs_drv.h:357
Definition: typedefs.h:118
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
struct _root * subvol
Definition: btrfs_drv.h:299
return STATUS_SUCCESS
Definition: btrfs.c:3014
LIST_ENTRY list_entry_dirty
Definition: btrfs_drv.h:349

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

7287  {
7288  NTSTATUS Status;
7289  KEY searchkey;
7290  traverse_ptr tp;
7292 
7293  TRACE("(%p, %p)\n", Vcb, r);
7294 
7296 
7297  searchkey.obj_id = BTRFS_ORPHAN_INODE_OBJID;
7298  searchkey.obj_type = TYPE_ORPHAN_INODE;
7299  searchkey.offset = 0;
7300 
7301  Status = find_item(Vcb, r, &tp, &searchkey, false, Irp);
7302  if (!NT_SUCCESS(Status)) {
7303  ERR("find_item returned %08lx\n", Status);
7304  return Status;
7305  }
7306 
7307  do {
7308  traverse_ptr next_tp;
7309 
7310  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))
7311  break;
7312 
7313  if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
7314  fcb* fcb;
7315 
7316  TRACE("removing orphaned inode %I64x\n", tp.item->key.offset);
7317 
7318  Status = open_fcb(Vcb, r, tp.item->key.offset, 0, NULL, false, NULL, &fcb, PagedPool, Irp);
7319  if (!NT_SUCCESS(Status))
7320  ERR("open_fcb returned %08lx\n", Status);
7321  else {
7322  if (fcb->inode_item.st_nlink == 0) {
7323  if (fcb->type != BTRFS_TYPE_DIRECTORY && fcb->inode_item.st_size > 0) {
7324  Status = excise_extents(Vcb, fcb, 0, sector_align(fcb->inode_item.st_size, Vcb->superblock.sector_size), Irp, &rollback);
7325  if (!NT_SUCCESS(Status)) {
7326  ERR("excise_extents returned %08lx\n", Status);
7327  goto end;
7328  }
7329  }
7330 
7331  fcb->deleted = true;
7332 
7334  }
7335 
7336  free_fcb(fcb);
7337 
7339  if (!NT_SUCCESS(Status)) {
7340  ERR("delete_tree_item returned %08lx\n", Status);
7341  goto end;
7342  }
7343  }
7344  }
7345 
7346  if (find_next_item(Vcb, &tp, &next_tp, false, Irp))
7347  tp = next_tp;
7348  else
7349  break;
7350  } while (true);
7351 
7353 
7355 
7356 end:
7358 
7359  return Status;
7360 }
uint64_t obj_id
Definition: btrfs.h:137
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback)
Definition: treefuncs.c:1050
void clear_rollback(LIST_ENTRY *rollback)
Definition: treefuncs.c:1029
uint8_t obj_type
Definition: btrfs.h:138
void free_fcb(_Inout_ fcb *fcb)
Definition: btrfs.c:1664
_In_ PIRP Irp
Definition: csq.h:116
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension *Vcb, root *subvol, uint64_t inode, uint8_t type, PANSI_STRING utf8, bool always_add_hl, fcb *parent, fcb **pfcb, POOL_TYPE pooltype, PIRP Irp)
Definition: create.c:699
LONG NTSTATUS
Definition: precomp.h:26
#define BTRFS_ORPHAN_INODE_OBJID
Definition: btrfs.h:123
GLuint GLuint end
Definition: gl.h:1545
uint64_t offset
Definition: btrfs.h:139
uint32_t st_nlink
Definition: btrfs.h:285
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
smooth NULL
Definition: ftsmooth.c:416
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1625
uint8_t type
Definition: btrfs_drv.h:302
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
uint64_t st_size
Definition: btrfs.h:282
#define TRACE(s)
Definition: solgame.cpp:4
struct _fcb fcb
Definition: btrfs_drv.h:1357
bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp)
Definition: treefuncs.c:593
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
tree_data * item
Definition: btrfs_drv.h:518
NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback)
Definition: write.c:2384
Definition: typedefs.h:118
INODE_ITEM inode_item
Definition: btrfs_drv.h:303
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
bool deleted
Definition: btrfs_drv.h:306
#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:1357
#define TYPE_ORPHAN_INODE
Definition: btrfs.h:23
return STATUS_SUCCESS
Definition: btrfs.c:3014
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:990

Referenced by check_for_orphans().

◆ clean_space_cache()

static void clean_space_cache ( device_extension Vcb)
static

Definition at line 399 of file flushthread.c.

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

Referenced by do_write2().

◆ clean_space_cache_chunk()

static void clean_space_cache_chunk ( device_extension Vcb,
chunk c 
)
static

Definition at line 166 of file flushthread.c.

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

Referenced by clean_space_cache().

◆ create_chunk()

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

Definition at line 4212 of file flushthread.c.

4212  {
4213  CHUNK_ITEM* ci;
4214  CHUNK_ITEM_STRIPE* cis;
4215  BLOCK_GROUP_ITEM* bgi;
4216  uint16_t i, factor;
4217  NTSTATUS Status;
4218 
4220  if (!ci) {
4221  ERR("out of memory\n");
4223  }
4224 
4225  RtlCopyMemory(ci, c->chunk_item, c->size);
4226 
4227  Status = insert_tree_item(Vcb, Vcb->chunk_root, 0x100, TYPE_CHUNK_ITEM, c->offset, ci, c->size, NULL, Irp);
4228  if (!NT_SUCCESS(Status)) {
4229  ERR("insert_tree_item failed\n");
4230  ExFreePool(ci);
4231  return Status;
4232  }
4233 
4234  if (c->chunk_item->type & BLOCK_FLAG_SYSTEM) {
4235  Status = add_to_bootstrap(Vcb, 0x100, TYPE_CHUNK_ITEM, c->offset, ci, c->size);
4236  if (!NT_SUCCESS(Status)) {
4237  ERR("add_to_bootstrap returned %08lx\n", Status);
4238  return Status;
4239  }
4240  }
4241 
4242  // add BLOCK_GROUP_ITEM to tree 2
4243 
4245  if (!bgi) {
4246  ERR("out of memory\n");
4248  }
4249 
4250  bgi->used = c->used;
4251  bgi->chunk_tree = 0x100;
4252  bgi->flags = c->chunk_item->type;
4253 
4254  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);
4255  if (!NT_SUCCESS(Status)) {
4256  ERR("insert_tree_item failed\n");
4257  ExFreePool(bgi);
4258  return Status;
4259  }
4260 
4261  if (c->chunk_item->type & BLOCK_FLAG_RAID0)
4262  factor = c->chunk_item->num_stripes;
4263  else if (c->chunk_item->type & BLOCK_FLAG_RAID10)
4264  factor = c->chunk_item->num_stripes / c->chunk_item->sub_stripes;
4265  else if (c->chunk_item->type & BLOCK_FLAG_RAID5)
4266  factor = c->chunk_item->num_stripes - 1;
4267  else if (c->chunk_item->type & BLOCK_FLAG_RAID6)
4268  factor = c->chunk_item->num_stripes - 2;
4269  else // SINGLE, DUPLICATE, RAID1, RAID1C3, RAID1C4
4270  factor = 1;
4271 
4272  // add DEV_EXTENTs to tree 4
4273 
4274  cis = (CHUNK_ITEM_STRIPE*)&c->chunk_item[1];
4275 
4276  for (i = 0; i < c->chunk_item->num_stripes; i++) {
4277  DEV_EXTENT* de;
4278 
4280  if (!de) {
4281  ERR("out of memory\n");
4283  }
4284 
4285  de->chunktree = Vcb->chunk_root->id;
4286  de->objid = 0x100;
4287  de->address = c->offset;
4288  de->length = c->chunk_item->size / factor;
4289  de->chunktree_uuid = Vcb->chunk_root->treeholder.tree->header.chunk_tree_uuid;
4290 
4291  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);
4292  if (!NT_SUCCESS(Status)) {
4293  ERR("insert_tree_item returned %08lx\n", Status);
4294  ExFreePool(de);
4295  return Status;
4296  }
4297 
4298  // FIXME - no point in calling this twice for the same device
4299  Status = update_dev_item(Vcb, c->devices[i], Irp);
4300  if (!NT_SUCCESS(Status)) {
4301  ERR("update_dev_item returned %08lx\n", Status);
4302  return Status;
4303  }
4304  }
4305 
4306  c->created = false;
4307  c->oldused = c->used;
4308 
4309  Vcb->superblock.bytes_used += chunk_estimate_phys_size(Vcb, c, c->used);
4310 
4311  return STATUS_SUCCESS;
4312 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PIRP Irp
Definition: csq.h:116
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint factor
Definition: glfuncs.h:178
uint64_t flags
Definition: btrfs.h:414
#define TYPE_CHUNK_ITEM
Definition: btrfs.h:44
LONG NTSTATUS
Definition: precomp.h:26
uint64_t length
Definition: btrfs.h:460
unsigned short int uint16_t
Definition: acefiex.h:54
uint64_t used
Definition: btrfs.h:412
#define ALLOC_TAG
Definition: btrfs_drv.h:91
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define TYPE_DEV_EXTENT
Definition: btrfs.h:42
#define BLOCK_FLAG_SYSTEM
Definition: shellext.h:76
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS update_dev_item(device_extension *Vcb, device *device, PIRP Irp)
Definition: flushthread.c:4099
#define BLOCK_FLAG_RAID10
Definition: shellext.h:81
#define BLOCK_FLAG_RAID0
Definition: shellext.h:78
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
#define for
Definition: utility.h:88
uint64_t objid
Definition: btrfs.h:458
#define BLOCK_FLAG_RAID6
Definition: shellext.h:83
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp)
Definition: treefuncs.c:858
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define TYPE_BLOCK_GROUP_ITEM
Definition: btrfs.h:38
static NTSTATUS add_to_bootstrap(device_extension *Vcb, uint64_t obj_id, uint8_t obj_type, uint64_t offset, void *data, uint16_t size)
Definition: flushthread.c:4166
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
uint64_t chunk_tree
Definition: btrfs.h:413
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
uint64_t chunktree
Definition: btrfs.h:457
BTRFS_UUID chunktree_uuid
Definition: btrfs.h:461
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
uint64_t address
Definition: btrfs.h:459
uint64_t chunk_estimate_phys_size(device_extension *Vcb, chunk *c, uint64_t u)
Definition: btrfs.c:3809

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

6151  {
6152  KEY searchkey;
6153  traverse_ptr tp;
6154  NTSTATUS Status;
6155 
6156  searchkey.obj_id = parsubvolid;
6157  searchkey.obj_type = TYPE_ROOT_REF;
6158  searchkey.offset = subvolid;
6159 
6160  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
6161  if (!NT_SUCCESS(Status)) {
6162  ERR("error - find_item returned %08lx\n", Status);
6163  return Status;
6164  }
6165 
6166  if (!keycmp(searchkey, tp.item->key)) {
6167  if (tp.item->size < sizeof(ROOT_REF)) {
6168  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));
6169  return STATUS_INTERNAL_ERROR;
6170  } else {
6171  ROOT_REF* rr;
6172  ULONG len;
6173 
6174  rr = (ROOT_REF*)tp.item->data;
6175  len = tp.item->size;
6176 
6177  do {
6178  uint16_t itemlen;
6179 
6180  if (len < sizeof(ROOT_REF) || len < offsetof(ROOT_REF, name[0]) + rr->n) {
6181  ERR("(%I64x,%x,%I64x) was truncated\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
6182  break;
6183  }
6184 
6185  itemlen = (uint16_t)offsetof(ROOT_REF, name[0]) + rr->n;
6186 
6187  if (rr->dir == parinode && rr->n == utf8->Length && RtlCompareMemory(rr->name, utf8->Buffer, rr->n) == rr->n) {
6188  uint16_t newlen = tp.item->size - itemlen;
6189 
6191  if (!NT_SUCCESS(Status)) {
6192  ERR("delete_tree_item returned %08lx\n", Status);
6193  return Status;
6194  }
6195 
6196  if (newlen == 0) {
6197  TRACE("deleting (%I64x,%x,%I64x)\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
6198  } else {
6199  uint8_t *newrr = ExAllocatePoolWithTag(PagedPool, newlen, ALLOC_TAG), *rroff;
6200 
6201  if (!newrr) {
6202  ERR("out of memory\n");
6204  }
6205 
6206  TRACE("modifying (%I64x,%x,%I64x)\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
6207 
6208  if ((uint8_t*)rr > tp.item->data) {
6209  RtlCopyMemory(newrr, tp.item->data, (uint8_t*)rr - tp.item->data);
6210  rroff = newrr + ((uint8_t*)rr - tp.item->data);
6211  } else {
6212  rroff = newrr;
6213  }
6214 
6215  if ((uint8_t*)&rr->name[rr->n] < tp.item->data + tp.item->size)
6216  RtlCopyMemory(rroff, &rr->name[rr->n], tp.item->size - ((uint8_t*)&rr->name[rr->n] - tp.item->data));
6217 
6218  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);
6219  if (!NT_SUCCESS(Status)) {
6220  ERR("insert_tree_item returned %08lx\n", Status);
6221  ExFreePool(newrr);
6222  return Status;
6223  }
6224  }
6225 
6226  break;
6227  }
6228 
6229  if (len > itemlen) {
6230  len -= itemlen;
6231  rr = (ROOT_REF*)&rr->name[rr->n];
6232  } else
6233  break;
6234  } while (len > 0);
6235  }
6236  } else {
6237  WARN("could not find ROOT_REF entry for subvol %I64x in %I64x\n", searchkey.offset, searchkey.obj_id);
6238  return STATUS_NOT_FOUND;
6239  }
6240 
6241  return STATUS_SUCCESS;
6242 }
#define TYPE_ROOT_REF
Definition: btrfs.h:30
uint64_t obj_id
Definition: btrfs.h:137
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
char name[1]
Definition: btrfs.h:453
_In_ PIRP Irp
Definition: csq.h:116
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1024
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
uint16_t n
Definition: btrfs.h:452
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
uint64_t dir
Definition: btrfs.h:450
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:91
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define TRACE(s)
Definition: solgame.cpp:4
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp)
Definition: treefuncs.c:858
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:518
GLenum GLsizei len
Definition: glext.h:6722
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
Definition: name.c:38
unsigned int ULONG
Definition: retypes.h:1
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:990

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

4374  {
4375  NTSTATUS Status;
4376  uint16_t xasize;
4377  DIR_ITEM* xa;
4378 
4379  TRACE("(%p, %I64x, %I64x, %.*s, %08x)\n", Vcb, subvol->id, inode, namelen, name, crc32);
4380 
4381  xasize = (uint16_t)offsetof(DIR_ITEM, name[0]) + namelen;
4382 
4383  xa = ExAllocatePoolWithTag(PagedPool, xasize, ALLOC_TAG);
4384  if (!xa) {
4385  ERR("out of memory\n");
4387  }
4388 
4389  xa->key.obj_id = 0;
4390  xa->key.obj_type = 0;
4391  xa->key.offset = 0;
4392  xa->transid = Vcb->superblock.generation;
4393  xa->m = 0;
4394  xa->n = namelen;
4395  xa->type = BTRFS_TYPE_EA;
4396  RtlCopyMemory(xa->name, name, namelen);
4397 
4399  if (!NT_SUCCESS(Status)) {
4400  ERR("insert_tree_item_batch returned %08lx\n", Status);
4401  ExFreePool(xa);
4402  return Status;
4403  }
4404 
4405  return STATUS_SUCCESS;
4406 }
uint64_t obj_id
Definition: btrfs.h:137
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
uint32 __fastcall crc32(IN uint8 *s, IN uint32 len)
Definition: udf_info.cpp:4290
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:4448
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:139
Definition: fs.h:78
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint16_t m
Definition: btrfs.h:268
KEY key
Definition: btrfs.h:266
char name[1]
Definition: btrfs.h:271
#define offsetof(TYPE, MEMBER)
uint8_t type
Definition: btrfs.h:270
#define TRACE(s)
Definition: solgame.cpp:4
#define TYPE_XATTR_ITEM
Definition: btrfs.h:22
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
struct _root * subvol
Definition: btrfs_drv.h:299
Definition: name.c:38
uint64_t transid
Definition: btrfs.h:267
#define BTRFS_TYPE_EA
Definition: btrfs.h:263
uint16_t n
Definition: btrfs.h:269
return STATUS_SUCCESS
Definition: btrfs.c:3014
#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 7808 of file flushthread.c.

7808  {
7809  NTSTATUS Status;
7810 
7811  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
7812 
7813  if (Vcb->need_write && !Vcb->readonly)
7814  Status = do_write(Vcb, NULL);
7815  else
7817 
7818  free_trees(Vcb);
7819 
7820  if (!NT_SUCCESS(Status))
7821  ERR("do_write returned %08lx\n", Status);
7822 
7823  ExReleaseResourceLite(&Vcb->tree_lock);
7824 }
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7789
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
smooth NULL
Definition: ftsmooth.c:416
void free_trees(device_extension *Vcb)
Definition: treefuncs.c:794
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
return STATUS_SUCCESS
Definition: btrfs.c:3014

Referenced by _Function_class_().

◆ do_splits()

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

Definition at line 3662 of file flushthread.c.

3662  {
3663  ULONG level, max_level;
3664  uint32_t min_size;
3665  bool empty, done_deletions = false;
3666  NTSTATUS Status;
3667  tree* t;
3668 
3669  TRACE("(%p)\n", Vcb);
3670 
3671  max_level = 0;
3672 
3673  for (level = 0; level <= 255; level++) {
3674  LIST_ENTRY *le, *nextle;
3675 
3676  empty = true;
3677 
3678  TRACE("doing level %lu\n", level);
3679 
3680  le = Vcb->trees.Flink;
3681 
3682  while (le != &Vcb->trees) {
3684 
3685  nextle = le->Flink;
3686 
3687  if (t->write && t->header.level == level) {
3688  empty = false;
3689 
3690  if (t->header.num_items == 0) {
3691  if (t->parent) {
3692  done_deletions = true;
3693 
3694  TRACE("deleting tree in root %I64x\n", t->root->id);
3695 
3696  t->root->root_item.bytes_used -= Vcb->superblock.node_size;
3697 
3698  if (t->has_new_address) { // delete associated EXTENT_ITEM
3699  Status = reduce_tree_extent(Vcb, t->new_address, t, t->parent->header.tree_id, t->header.level, Irp, rollback);
3700 
3701  if (!NT_SUCCESS(Status)) {
3702  ERR("reduce_tree_extent returned %08lx\n", Status);
3703  return Status;
3704  }
3705 
3706  t->has_new_address = false;
3707  } else if (t->has_address) {
3708  Status = reduce_tree_extent(Vcb,t->header.address, t, t->parent->header.tree_id, t->header.level, Irp, rollback);
3709 
3710  if (!NT_SUCCESS(Status)) {
3711  ERR("reduce_tree_extent returned %08lx\n", Status);
3712  return Status;
3713  }
3714 
3715  t->has_address = false;
3716  }
3717 
3718  if (!t->paritem->ignore) {
3719  t->paritem->ignore = true;
3720  t->parent->header.num_items--;
3721  t->parent->size -= sizeof(internal_node);
3722  }
3723 
3724  RemoveEntryList(&t->paritem->list_entry);
3725  ExFreePool(t->paritem);
3726  t->paritem = NULL;
3727 
3728  free_tree(t);
3729  } else if (t->header.level != 0) {
3730  if (t->has_new_address) {
3731  Status = update_extent_level(Vcb, t->new_address, t, 0, Irp);
3732 
3733  if (!NT_SUCCESS(Status)) {
3734  ERR("update_extent_level returned %08lx\n", Status);
3735  return Status;
3736  }
3737  }
3738 
3739  t->header.level = 0;
3740  }
3741  } else if (t->size > Vcb->superblock.node_size - sizeof(tree_header)) {
3742  TRACE("splitting overlarge tree (%x > %Ix)\n", t->size, Vcb->superblock.node_size - sizeof(tree_header));
3743 
3744  if (!t->updated_extents && t->has_address) {
3746  if (!NT_SUCCESS(Status)) {
3747  ERR("update_tree_extents_recursive returned %08lx\n", Status);
3748  return Status;
3749  }
3750  }
3751 
3752  Status = split_tree(Vcb, t);
3753 
3754  if (!NT_SUCCESS(Status)) {
3755  ERR("split_tree returned %08lx\n", Status);
3756  return Status;
3757  }
3758  }
3759  }
3760 
3761  le = nextle;
3762  }
3763 
3764  if (!empty) {
3765  max_level = level;
3766  } else {
3767  TRACE("nothing found for level %lu\n", level);
3768  break;
3769  }
3770  }
3771 
3772  min_size = (Vcb->superblock.node_size - sizeof(tree_header)) / 2;
3773 
3774  for (level = 0; level <= max_level; level++) {
3775  LIST_ENTRY* le;
3776 
3777  le = Vcb->trees.Flink;
3778 
3779  while (le != &Vcb->trees) {
3781 
3782  if (t->write && t->header.level == level && t->header.num_items > 0 && t->parent && t->size < min_size &&
3783  t->root->id != BTRFS_ROOT_FREE_SPACE && is_tree_unique(Vcb, t, Irp)) {
3784  bool done;
3785 
3786  do {
3787  Status = try_tree_amalgamate(Vcb, t, &done, &done_deletions, Irp, rollback);
3788  if (!NT_SUCCESS(Status)) {
3789  ERR("try_tree_amalgamate returned %08lx\n", Status);
3790  return Status;
3791  }
3792  } while (done && t->size < min_size);
3793  }
3794 
3795  le = le->Flink;
3796  }
3797  }
3798 
3799  // simplify trees if top tree only has one entry
3800 
3801  if (done_deletions) {
3802  for (level = max_level; level > 0; level--) {
3803  LIST_ENTRY *le, *nextle;
3804 
3805  le = Vcb->trees.Flink;
3806  while (le != &Vcb->trees) {
3807  nextle = le->Flink;
3809 
3810  if (t->write && t->header.level == level) {
3811  if (!t->parent && t->header.num_items == 1) {
3812  LIST_ENTRY* le2 = t->itemlist.Flink;
3813  tree_data* td = NULL;
3814  tree* child_tree = NULL;
3815 
3816  while (le2 != &t->itemlist) {
3818  if (!td->ignore)
3819  break;
3820  le2 = le2->Flink;
3821  }
3822 
3823  TRACE("deleting top-level tree in root %I64x with one item\n", t->root->id);
3824 
3825  if (t->has_new_address) { // delete associated EXTENT_ITEM
3826  Status = reduce_tree_extent(Vcb, t->new_address, t, t->header.tree_id, t->header.level, Irp, rollback);
3827 
3828  if (!NT_SUCCESS(Status)) {
3829  ERR("reduce_tree_extent returned %08lx\n", Status);
3830  return Status;
3831  }
3832 
3833  t->has_new_address = false;
3834  } else if (t->has_address) {
3835  Status = reduce_tree_extent(Vcb,t->header.address, t, t->header.tree_id, t->header.level, Irp, rollback);
3836 
3837  if (!NT_SUCCESS(Status)) {
3838  ERR("reduce_tree_extent returned %08lx\n", Status);
3839  return Status;
3840  }
3841 
3842  t->has_address = false;
3843  }
3844 
3845  if (!td->treeholder.tree) { // load first item if not already loaded
3846  KEY searchkey = {0,0,0};
3847  traverse_ptr tp;
3848 
3849  Status = find_item(Vcb, t->root, &tp, &searchkey, false, Irp);
3850  if (!NT_SUCCESS(Status)) {
3851  ERR("error - find_item returned %08lx\n", Status);
3852  return Status;
3853  }
3854  }
3855 
3856  child_tree = td->treeholder.tree;
3857 
3858  if (child_tree) {
3859  child_tree->parent = NULL;
3860  child_tree->paritem = NULL;
3861  }
3862 
3863  t->root->root_item.bytes_used -= Vcb->superblock.node_size;
3864 
3865  free_tree(t);
3866 
3867  if (child_tree)
3868  child_tree->root->treeholder.tree = child_tree;
3869  }
3870  }
3871 
3872  le = nextle;
3873  }
3874  }
3875  }
3876 
3877  return STATUS_SUCCESS;
3878 }
static NTSTATUS split_tree(device_extension *Vcb, tree *t)
Definition: flushthread.c:3211
static NTSTATUS update_extent_level(device_extension *Vcb, uint64_t address, tree *t, uint8_t level, PIRP Irp)
Definition: flushthread.c:3544
GLint level
Definition: gl.h:1546
struct _root * root
Definition: btrfs_drv.h:449
_In_ PIRP Irp
Definition: csq.h:116
LONG NTSTATUS
Definition: precomp.h:26
tree_holder treeholder
Definition: btrfs_drv.h:427
GLdouble GLdouble t
Definition: gl.h:2047
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
struct _tree * tree
Definition: btrfs_drv.h:417
tree_data * paritem
Definition: btrfs_drv.h:448
smooth NULL
Definition: ftsmooth.c:416
struct _tree * parent
Definition: btrfs_drv.h:447
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:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
struct _LIST_ENTRY * Flink
Definition: typedefs.h:120
#define TRACE(s)
Definition: solgame.cpp:4
void free_tree(tree *t)
Definition: treefuncs.c:261
#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:949
#define Vcb
Definition: cdprocs.h:1425
static NTSTATUS update_tree_extents_recursive(device_extension *Vcb, tree *t, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:3644
bool is_tree_unique(device_extension *Vcb, tree *t, PIRP Irp)
Definition: flushthread.c:3251
Definition: typedefs.h:118
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
bool ignore
Definition: btrfs_drv.h:423
Definition: btrfs.h:136
Definition: list.h:27
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1357
BOOL empty
Definition: button.c:170
UINT32 uint32_t
Definition: types.h:75
#define BTRFS_ROOT_FREE_SPACE
Definition: btrfs.h:58
unsigned int ULONG
Definition: retypes.h:1
return STATUS_SUCCESS
Definition: btrfs.c:3014
static NTSTATUS try_tree_amalgamate(device_extension *Vcb, tree *t, bool *done, bool *done_deletions, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:3314
#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 1613 of file flushthread.c.

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

Referenced by write_metadata_items(), and write_trees().

◆ do_write()

NTSTATUS do_write ( device_extension Vcb,
PIRP  Irp 
)

Definition at line 7789 of file flushthread.c.

7789  {
7791  NTSTATUS Status;
7792 
7794 
7796 
7797  if (!NT_SUCCESS(Status)) {
7798  ERR("do_write2 returned %08lx, dropping into readonly mode\n", Status);
7799  Vcb->readonly = true;
7802  } else
7804 
7805  return Status;
7806 }
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback)
Definition: treefuncs.c:1050
void clear_rollback(LIST_ENTRY *rollback)
Definition: treefuncs.c:1029
_In_ PIRP Irp
Definition: csq.h:116
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
static NTSTATUS do_write2(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:7389
Definition: typedefs.h:118
Status
Definition: gdiplustypes.h:24
#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:1357
#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 7389 of file flushthread.c.

7389  {
7390  NTSTATUS Status;
7391  LIST_ENTRY *le, batchlist;
7392  bool cache_changed = false;
7394  bool no_cache = false;
7395 #ifdef DEBUG_FLUSH_TIMES
7396  uint64_t filerefs = 0, fcbs = 0;
7397  LARGE_INTEGER freq, time1, time2;
7398 #endif
7399 #ifdef DEBUG_WRITE_LOOPS
7400  UINT loops = 0;
7401 #endif
7402 
7403  TRACE("(%p)\n", Vcb);
7404 
7405  InitializeListHead(&batchlist);
7406 
7407 #ifdef DEBUG_FLUSH_TIMES
7408  time1 = KeQueryPerformanceCounter(&freq);
7409 #endif
7410 
7412  if (!NT_SUCCESS(Status)) {
7413  ERR("check_for_orphans returned %08lx\n", Status);
7414  return Status;
7415  }
7416 
7417  ExAcquireResourceExclusiveLite(&Vcb->dirty_filerefs_lock, true);
7418 
7419  while (!IsListEmpty(&Vcb->dirty_filerefs)) {
7421 
7422  flush_fileref(fr, &batchlist, Irp);
7423  free_fileref(fr);
7424 
7425 #ifdef DEBUG_FLUSH_TIMES
7426  filerefs++;
7427 #endif
7428  }
7429 
7430  ExReleaseResourceLite(&Vcb->dirty_filerefs_lock);
7431 
7432  Status = commit_batch_list(Vcb, &batchlist, Irp);
7433  if (!NT_SUCCESS(Status)) {
7434  ERR("commit_batch_list returned %08lx\n", Status);
7435  return Status;
7436  }
7437 
7438 #ifdef DEBUG_FLUSH_TIMES
7440 
7441  ERR("flushed %I64u filerefs in %I64u (freq = %I64u)\n", filerefs, time2.QuadPart - time1.QuadPart, freq.QuadPart);
7442 
7443  time1 = KeQueryPerformanceCounter(&freq);
7444 #endif
7445 
7446  // We process deleted streams first, so we don't run over our xattr
7447  // limit unless we absolutely have to.
7448  // We also process deleted normal files, to avoid any problems
7449  // caused by inode collisions.
7450 
7451  ExAcquireResourceExclusiveLite(&Vcb->dirty_fcbs_lock, true);
7452 
7453  le = Vcb->dirty_fcbs.Flink;
7454  while (le != &Vcb->dirty_fcbs) {
7455  fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_dirty);
7456  LIST_ENTRY* le2 = le->Flink;
7457 
7458  if (fcb->deleted) {
7459  ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
7460  Status = flush_fcb(fcb, false, &batchlist, Irp);
7461  ExReleaseResourceLite(fcb->Header.Resource);
7462 
7463  free_fcb(fcb);
7464 
7465  if (!NT_SUCCESS(Status)) {
7466  ERR("flush_fcb returned %08lx\n", Status);
7467  clear_batch_list(Vcb, &batchlist);
7468  ExReleaseResourceLite(&Vcb->dirty_fcbs_lock);
7469  return Status;
7470  }
7471 
7472 #ifdef DEBUG_FLUSH_TIMES
7473  fcbs++;
7474 #endif
7475  }
7476 
7477  le = le2;
7478  }
7479 
7480  Status = commit_batch_list(Vcb, &batchlist, Irp);
7481  if (!NT_SUCCESS(Status)) {
7482  ERR("commit_batch_list returned %08lx\n", Status);
7483  ExReleaseResourceLite(&Vcb->dirty_fcbs_lock);
7484  return Status;
7485  }
7486 
7487  le = Vcb->dirty_fcbs.Flink;
7488  while (le != &Vcb->dirty_fcbs) {
7489  fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_dirty);
7490  LIST_ENTRY* le2 = le->Flink;
7491 
7492  if (fcb->subvol != Vcb->root_root) {
7493  ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
7494  Status = flush_fcb(fcb, false, &batchlist, Irp);
7495  ExReleaseResourceLite(fcb->Header.Resource);
7496  free_fcb(fcb);
7497 
7498  if (!NT_SUCCESS(Status)) {
7499  ERR("flush_fcb returned %08lx\n", Status);
7500  ExReleaseResourceLite(&Vcb->dirty_fcbs_lock);
7501  return Status;
7502  }
7503 
7504 #ifdef DEBUG_FLUSH_TIMES
7505  fcbs++;
7506 #endif
7507  }
7508 
7509  le = le2;
7510  }
7511 
7512  ExReleaseResourceLite(&Vcb->dirty_fcbs_lock);
7513 
7514  Status = commit_batch_list(Vcb, &batchlist, Irp);
7515  if (!NT_SUCCESS(Status)) {
7516  ERR("commit_batch_list returned %08lx\n", Status);
7517  return Status;
7518  }
7519 
7520 #ifdef DEBUG_FLUSH_TIMES
7522 
7523  ERR("flushed %I64u fcbs in %I64u (freq = %I64u)\n", filerefs, time2.QuadPart - time1.QuadPart, freq.QuadPart);
7524 #endif
7525 
7526  // no need to get dirty_subvols_lock here, as we have tree_lock exclusively
7527  while (!IsListEmpty(&Vcb->dirty_subvols)) {
7529 
7530  Status = flush_subvol(Vcb, r, Irp);
7531  if (!NT_SUCCESS(Status)) {
7532  ERR("flush_subvol returned %08lx\n", Status);
7533  return Status;
7534  }
7535  }
7536 
7537  if (!IsListEmpty(&Vcb->drop_roots)) {
7539 
7540  if (!NT_SUCCESS(Status)) {
7541  ERR("drop_roots returned %08lx\n", Status);
7542  return Status;
7543  }
7544  }
7545 
7546  Status = update_chunks(Vcb, &batchlist, Irp, rollback);
7547 
7548  if (!NT_SUCCESS(Status)) {
7549  ERR("update_chunks returned %08lx\n", Status);
7550  return Status;
7551  }
7552 
7553  Status = commit_batch_list(Vcb, &batchlist, Irp);
7554 
7555  // If only changing superblock, e.g. changing label, we still need to rewrite
7556  // the root tree so the generations match, otherwise you won't be able to mount on Linux.
7557  if (!Vcb->root_root->treeholder.tree || !Vcb->root_root->treeholder.tree->write) {
7558  KEY searchkey;
7559 
7560  traverse_ptr tp;
7561 
7562  searchkey.obj_id = 0;
7563  searchkey.obj_type = 0;
7564  searchkey.offset = 0;
7565 
7566  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, Irp);
7567  if (!NT_SUCCESS(Status)) {
7568  ERR("error - find_item returned %08lx\n", Status);
7569  return Status;
7570  }
7571 
7572  Vcb->root_root->treeholder.tree->write = true;
7573  }
7574 
7575  // make sure we always update the extent tree
7577  if (!NT_SUCCESS(Status)) {
7578  ERR("add_root_item_to_cache returned %08lx\n", Status);
7579  return Status;
7580  }
7581 
7582  if (Vcb->stats_changed) {
7583  le = Vcb->devices.Flink;
7584  while (le != &Vcb->devices) {
7586 
7587  if (dev->stats_changed) {
7589  if (!NT_SUCCESS(Status)) {
7590  ERR("flush_changed_dev_stats returned %08lx\n", Status);
7591  return Status;
7592  }
7593  dev->stats_changed = false;
7594  }
7595 
7596  le = le->Flink;
7597  }
7598 
7599  Vcb->stats_changed = false;
7600  }
7601 
7602  do {
7603  Status = add_parents(Vcb, Irp);
7604  if (!NT_SUCCESS(Status)) {
7605  ERR("add_parents returned %08lx\n", Status);
7606  goto end;
7607  }
7608 
7610  if (!NT_SUCCESS(Status)) {
7611  ERR("allocate_tree_extents returned %08lx\n", Status);
7612  goto end;
7613  }
7614 
7616  if (!NT_SUCCESS(Status)) {
7617  ERR("do_splits returned %08lx\n", Status);
7618  goto end;
7619  }
7620 
7622  if (!NT_SUCCESS(Status)) {
7623  ERR("update_chunk_usage returned %08lx\n", Status);
7624  goto end;
7625  }
7626 
7627  if (!(Vcb->superblock.compat_ro_flags & BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE)) {
7628  if (!no_cache) {
7629  Status = allocate_cache(Vcb, &cache_changed, Irp, rollback);
7630  if (!NT_SUCCESS(Status)) {
7631  WARN("allocate_cache returned %08lx\n", Status);
7632  no_cache = true;
7633  cache_changed = false;
7634  }
7635  }
7636  } else {
7638  if (!NT_SUCCESS(Status)) {
7639  ERR("update_chunk_caches_tree returned %08lx\n", Status);
7640  goto end;
7641  }
7642  }
7643 
7644 #ifdef DEBUG_WRITE_LOOPS
7645  loops++;
7646 
7647  if (cache_changed)
7648  ERR("cache has changed, looping again\n");
7649 #endif
7650  } while (cache_changed || !trees_consistent(Vcb));
7651 
7652 #ifdef DEBUG_WRITE_LOOPS
7653  ERR("%u loops\n", loops);
7654 #endif
7655 
7656  TRACE("trees consistent\n");
7657 
7658  Status = update_root_root(Vcb, no_cache, Irp, rollback);
7659  if (!NT_SUCCESS(Status)) {
7660  ERR("update_root_root returned %08lx\n", Status);
7661  goto end;
7662  }
7663 
7664  Status = write_trees(Vcb, Irp);
7665  if (!NT_SUCCESS(Status)) {
7666  ERR("write_trees returned %08lx\n", Status);
7667  goto end;
7668  }
7669 
7671  if (!NT_SUCCESS(Status)) {
7672  ERR("test_not_full returned %08lx\n", Status);
7673  goto end;
7674  }
7675 
7676 #ifdef DEBUG_PARANOID
7677  le = Vcb->trees.Flink;
7678  while (le != &Vcb->trees) {
7680  KEY searchkey;
7681  traverse_ptr tp;
7682 
7683  searchkey.obj_id = t->header.address;
7684  searchkey.obj_type = TYPE_METADATA_ITEM;
7685  searchkey.offset = 0xffffffffffffffff;
7686 
7687  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
7688  if (!NT_SUCCESS(Status)) {
7689  ERR("error - find_item returned %08lx\n", Status);
7690  goto end;
7691  }
7692 
7693  if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
7694  searchkey.obj_id = t->header.address;
7695  searchkey.obj_type = TYPE_EXTENT_ITEM;
7696  searchkey.offset = 0xffffffffffffffff;
7697 
7698  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, Irp);
7699  if (!NT_SUCCESS(Status)) {
7700  ERR("error - find_item returned %08lx\n", Status);
7701  goto end;
7702  }
7703 
7704  if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
7705  ERR("error - could not find entry in extent tree for tree at %I64x\n", t->header.address);
7707  goto end;
7708  }
7709  }
7710 
7711  le = le->Flink;
7712  }
7713 #endif
7714 
7715  Vcb->superblock.cache_generation = Vcb->superblock.generation;
7716 
7717  if (!Vcb->options.no_barrier)
7719 
7721  if (!NT_SUCCESS(Status)) {
7722  ERR("write_superblocks returned %08lx\n", Status);
7723  goto end;
7724  }
7725 
7726  vde = Vcb->vde;
7727 
7728  if (vde) {
7729  pdo_device_extension* pdode = vde->pdode;
7730 
7731  ExAcquireResourceSharedLite(&pdode->child_lock, true);
7732 
7733  le = pdode->children.Flink;
7734 
7735  while (le != &pdode->children) {
7737 
7738  vc->generation = Vcb->superblock.generation;
7739  le = le->Flink;
7740  }
7741 
7743  }
7744 
7746 
7747  le = Vcb->chunks.Flink;
7748  while (le != &Vcb->chunks) {
7750 
7751  c->changed = false;
7752  c->space_changed = false;
7753 
7754  le = le->Flink;
7755  }
7756 
7757  Vcb->superblock.generation++;
7758 
7760 
7761  le = Vcb->trees.Flink;
7762  while (le != &Vcb->trees) {
7764 
7765  t->write = false;
7766 
7767  le = le->Flink;
7768  }
7769 
7770  Vcb->need_write = false;
7771 
7772  while (!IsListEmpty(&Vcb->drop_roots)) {
7774 
7775  if (IsListEmpty(&r->fcbs)) {
7776  ExDeleteResourceLite(&r->nonpaged->load_tree_lock);
7777  ExFreePool(r->nonpaged);
7778  ExFreePool(r);
7779  } else
7780  r->dropped = true;
7781  }
7782 
7783 end:
7784  TRACE("do_write returning %08lx\n", Status);
7785 
7786  return Status;
7787 }
static NTSTATUS allocate_tree_extents(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:1458
uint64_t obj_id
Definition: btrfs.h:137
static NTSTATUS check_for_orphans(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7362
LARGE_INTEGER NTAPI KeQueryPerformanceCounter(IN PLARGE_INTEGER PerformanceFreq)
Definition: timer.c:138
static NTSTATUS add_parents(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:601
uint8_t obj_type
Definition: btrfs.h:138
static NTSTATUS flush_fileref(file_ref *fileref, LIST_ENTRY *batchlist, PIRP Irp)
Definition: flushthread.c:6429
static NTSTATUS update_root_root(device_extension *Vcb, bool no_cache, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:1550
static NTSTATUS update_chunk_usage(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:2803
static bool trees_consistent(device_extension *Vcb)
Definition: flushthread.c:564
void free_fcb(_Inout_ fcb *fcb)
Definition: btrfs.c:1664
_In_ PIRP Irp
Definition: csq.h:116
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:399
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:4818
GLuint GLuint end
Definition: gl.h:1545
#define TYPE_METADATA_ITEM
Definition: btrfs.h:32
static NTSTATUS do_splits(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:3662
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
uint64_t offset
Definition: btrfs.h:139
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
NTSTATUS update_chunk_caches_tree(device_extension *Vcb, PIRP Irp)
Definition: free-space.c:1917
uint64_t generation
Definition: btrfs_drv.h:864
Definition: devices.h:37
static NTSTATUS drop_roots(device_extension *Vcb, PIRP Irp, LIST_ENTRY *rollback)
Definition: flushthread.c:4078