ReactOS  0.4.14-dev-583-g2a1ba2c
write.c File Reference
#include "btrfs_drv.h"
Include dependency graph for write.c:

Go to the source code of this file.

Classes

struct  write_stripe
 
struct  stripe
 
struct  log_stripe
 

Functions

 _Function_class_ (IO_COMPLETION_ROUTINE)
 
chunkget_chunk_from_address (device_extension *Vcb, uint64_t address)
 
static uint64_t find_new_chunk_address (device_extension *Vcb, uint64_t size)
 
static bool find_new_dup_stripes (device_extension *Vcb, stripe *stripes, uint64_t max_stripe_size, bool full_size)
 
static bool find_new_stripe (device_extension *Vcb, stripe *stripes, uint16_t i, uint64_t max_stripe_size, bool allow_missing, bool full_size)
 
NTSTATUS alloc_chunk (device_extension *Vcb, uint64_t flags, chunk **pc, bool full_size)
 
static NTSTATUS prepare_raid0_write (_Pre_satisfies_(_Curr_->chunk_item->num_stripes >0) _In_ chunk *c, _In_ uint64_t address, _In_reads_bytes_(length) void *data, _In_ uint32_t length, _In_ write_stripe *stripes, _In_ PIRP Irp, _In_ uint64_t irp_offset, _In_ write_data_context *wtc)
 
static NTSTATUS prepare_raid10_write (_Pre_satisfies_(_Curr_->chunk_item->sub_stripes >0 &&_Curr_->chunk_item->num_stripes >=_Curr_->chunk_item->sub_stripes) _In_ chunk *c, _In_ uint64_t address, _In_reads_bytes_(length) void *data, _In_ uint32_t length, _In_ write_stripe *stripes, _In_ PIRP Irp, _In_ uint64_t irp_offset, _In_ write_data_context *wtc)
 
static NTSTATUS add_partial_stripe (device_extension *Vcb, chunk *c, uint64_t address, uint32_t length, void *data)
 
static NTSTATUS prepare_raid5_write (device_extension *Vcb, chunk *c, uint64_t address, void *data, uint32_t length, write_stripe *stripes, PIRP Irp, uint64_t irp_offset, ULONG priority, write_data_context *wtc)
 
static NTSTATUS prepare_raid6_write (device_extension *Vcb, chunk *c, uint64_t address, void *data, uint32_t length, write_stripe *stripes, PIRP Irp, uint64_t irp_offset, ULONG priority, write_data_context *wtc)
 
NTSTATUS write_data (_In_ device_extension *Vcb, _In_ uint64_t address, _In_reads_bytes_(length) void *data, _In_ uint32_t length, _In_ write_data_context *wtc, _In_opt_ PIRP Irp, _In_opt_ chunk *c, _In_ bool file_write, _In_ uint64_t irp_offset, _In_ ULONG priority)
 
void get_raid56_lock_range (chunk *c, uint64_t address, uint64_t length, uint64_t *lockaddr, uint64_t *locklen)
 
NTSTATUS write_data_complete (device_extension *Vcb, uint64_t address, void *data, uint32_t length, PIRP Irp, chunk *c, bool file_write, uint64_t irp_offset, ULONG priority)
 
void free_write_data_stripes (write_data_context *wtc)
 
void add_extent (_In_ fcb *fcb, _In_ LIST_ENTRY *prevextle, _In_ __drv_aliasesMem extent *newext)
 
NTSTATUS excise_extents (device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback)
 
void add_insert_extent_rollback (LIST_ENTRY *rollback, fcb *fcb, extent *ext)
 
NTSTATUS add_extent_to_fcb (_In_ fcb *fcb, _In_ uint64_t offset, _In_reads_bytes_(edsize) EXTENT_DATA *ed, _In_ uint16_t edsize, _In_ bool unique, _In_opt_ _When_(return >=0, __drv_aliasesMem) uint32_t *csum, _In_ LIST_ENTRY *rollback)
 
static void remove_fcb_extent (fcb *fcb, extent *ext, LIST_ENTRY *rollback)
 
NTSTATUS calc_csum (_In_ device_extension *Vcb, _In_reads_bytes_(sectors *Vcb->superblock.sector_size) uint8_t *data, _In_ uint32_t sectors, _Out_writes_bytes_(sectors *sizeof(uint32_t)) uint32_t *csum)
 
 _Requires_lock_held_ (c->lock) _When_(return !=0
 
 _Releases_lock_ (c->lock)) bool insert_extent_chunk(_In_ device_extension *Vcb
 
 TRACE ("(%p, (%I64x, %I64x), %I64x, %I64x, %I64x, %u, %p, %p)\n", Vcb, fcb->subvol->id, fcb->inode, c->offset, start_data, length, prealloc, data, rollback)
 
 if (!find_data_address_in_chunk(Vcb, c, length, &address)) return false
 
 if (!ed)
 
 if (!prealloc &&data &&!(fcb->inode_item.flags &BTRFS_INODE_NODATASUM))
 
 if (!NT_SUCCESS(Status))
 
 ExFreePool (ed)
 
 space_list_subtract (c, false, address, length, rollback)
 
 mark_fcb_dirty (fcb)
 
 add_changed_extent_ref (c, address, length, fcb->subvol->id, fcb->inode, start_data, 1, fcb->inode_item.flags &BTRFS_INODE_NODATASUM)
 
 release_chunk_lock (c, Vcb)
 
 if (data)
 
static bool try_extend_data (device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t length, void *data, PIRP Irp, uint64_t *written, bool file_write, uint64_t irp_offset, LIST_ENTRY *rollback)
 
static NTSTATUS insert_chunk_fragmented (fcb *fcb, uint64_t start, uint64_t length, uint8_t *data, bool prealloc, LIST_ENTRY *rollback)
 
static NTSTATUS insert_prealloc_extent (fcb *fcb, uint64_t start, uint64_t length, LIST_ENTRY *rollback)
 
static NTSTATUS insert_extent (device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t length, void *data, PIRP Irp, bool file_write, uint64_t irp_offset, LIST_ENTRY *rollback)
 
NTSTATUS truncate_file (fcb *fcb, uint64_t end, PIRP Irp, LIST_ENTRY *rollback)
 
NTSTATUS extend_file (fcb *fcb, file_ref *fileref, uint64_t end, bool prealloc, PIRP Irp, LIST_ENTRY *rollback)
 
static NTSTATUS do_write_file_prealloc (fcb *fcb, extent *ext, uint64_t start_data, uint64_t end_data, void *data, uint64_t *written, PIRP Irp, bool file_write, uint64_t irp_offset, ULONG priority, LIST_ENTRY *rollback)
 
NTSTATUS do_write_file (fcb *fcb, uint64_t start, uint64_t end_data, void *data, PIRP Irp, bool file_write, uint32_t irp_offset, LIST_ENTRY *rollback)
 
NTSTATUS write_compressed (fcb *fcb, uint64_t start_data, uint64_t end_data, void *data, PIRP Irp, LIST_ENTRY *rollback)
 
NTSTATUS write_file2 (device_extension *Vcb, PIRP Irp, LARGE_INTEGER offset, void *buf, ULONG *length, bool paging_io, bool no_cache, bool wait, bool deferred_write, bool write_irp, LIST_ENTRY *rollback)
 
NTSTATUS write_file (device_extension *Vcb, PIRP Irp, bool wait, bool deferred_write)
 
 _Dispatch_type_ (IRP_MJ_WRITE)
 

Variables

_In_ fcbfcb
 
_In_ fcb _In_ chunkc
 
_In_ fcb _In_ chunk _In_ uint64_t start_data
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t length
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool prealloc
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ voiddata
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP Irp
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRYrollback
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t compression = compression
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t decoded_size = decoded_size
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool file_write
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool _In_ uint64_t irp_offset
 
NTSTATUS Status = add_extent_to_fcb(fcb, start_data, ed, edsize, true, csum, rollback)
 
EXTENT_DATAed = ExAllocatePoolWithTag(PagedPool, edsize, ALLOC_TAG)
 
EXTENT_DATA2ed2 = (EXTENT_DATA2*)ed->data
 
uint16_t edsize = (uint16_t)(offsetof(EXTENT_DATA, data[0]) + sizeof(EXTENT_DATA2))
 
uint32_tcsum = NULL
 
ed generation = Vcb->superblock.generation
 
ed encryption = BTRFS_ENCRYPTION_NONE
 
ed encoding = BTRFS_ENCODING_NONE
 
ed type = prealloc ? EXTENT_TYPE_PREALLOC : EXTENT_TYPE_REGULAR
 
ed2 address = address
 
ed2 size = length
 
ed2 offset = 0
 
ed2 num_bytes = decoded_size
 
c used = length
 
fcb inode_item st_blocks = decoded_size
 
fcb extents_changed = true
 
fcb inode_item_changed = true
 
return true
 

Function Documentation

◆ _Dispatch_type_()

_Dispatch_type_ ( IRP_MJ_WRITE  )

Definition at line 4705 of file write.c.

4707  {
4708  NTSTATUS Status;
4709  bool top_level;
4713  fcb* fcb = FileObject ? FileObject->FsContext : NULL;
4714  ccb* ccb = FileObject ? FileObject->FsContext2 : NULL;
4715  bool wait = FileObject ? IoIsOperationSynchronous(Irp) : true;
4716 
4718 
4719  top_level = is_top_level(Irp);
4720 
4721  if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
4723  goto exit;
4724  } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
4726  goto end;
4727  }
4728 
4729  if (!fcb) {
4730  ERR("fcb was NULL\n");
4732  goto end;
4733  }
4734 
4735  if (!ccb) {
4736  ERR("ccb was NULL\n");
4738  goto end;
4739  }
4740 
4741  if (Irp->RequestorMode == UserMode && !(ccb->access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
4742  WARN("insufficient permissions\n");
4744  goto end;
4745  }
4746 
4747  if (fcb == Vcb->volume_fcb) {
4748  if (!Vcb->locked || Vcb->locked_fileobj != FileObject) {
4749  ERR("trying to write to volume when not locked, or locked with another FileObject\n");
4751  goto end;
4752  }
4753 
4754  TRACE("writing directly to volume\n");
4755 
4757 
4758  Status = IoCallDriver(Vcb->Vpb->RealDevice, Irp);
4759  goto exit;
4760  }
4761 
4762  if (is_subvol_readonly(fcb->subvol, Irp)) {
4764  goto end;
4765  }
4766 
4767  if (Vcb->readonly) {
4769  goto end;
4770  }
4771 
4772  _SEH2_TRY {
4774  CcMdlWriteComplete(IrpSp->FileObject, &IrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress);
4775 
4776  Irp->MdlAddress = NULL;
4778  } else {
4779  if (!(Irp->Flags & IRP_PAGING_IO))
4781 
4782  // Don't offload jobs when doing paging IO - otherwise this can lead to
4783  // deadlocks in CcCopyWrite.
4784  if (Irp->Flags & IRP_PAGING_IO)
4785  wait = true;
4786 
4787  Status = write_file(Vcb, Irp, wait, false);
4788  }
4791  } _SEH2_END;
4792 
4793 end:
4794  Irp->IoStatus.Status = Status;
4795 
4796  TRACE("wrote %u bytes\n", Irp->IoStatus.Information);
4797 
4798  if (Status != STATUS_PENDING)
4800  else {
4802 
4803  if (!add_thread_job(Vcb, Irp))
4804  Status = do_write_job(Vcb, Irp);
4805  }
4806 
4807 exit:
4808  if (top_level)
4810 
4811  TRACE("returning %08x\n", Status);
4812 
4814 
4815  return Status;
4816 }
NTSTATUS write_file(device_extension *Vcb, PIRP Irp, bool wait, bool deferred_write)
Definition: write.c:4631
#define FsRtlEnterFileSystem
NTSTATUS Status
Definition: write.c:2817
#define FsRtlExitFileSystem
return true
Definition: write.c:2901
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
#define VCB_TYPE_FS
Definition: btrfs_drv.h:664
GLuint GLuint end
Definition: gl.h:1545
ACCESS_MASK access
Definition: btrfs_drv.h:383
BOOLEAN NTAPI IoIsOperationSynchronous(IN PIRP Irp)
Definition: irp.c:1882
NTSTATUS vol_write(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: volume.c:225
NTSTATUS do_write_job(device_extension *Vcb, PIRP Irp)
Definition: worker-thread.c:68
#define FILE_APPEND_DATA
Definition: nt_native.h:634
VOID NTAPI CcMdlWriteComplete(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain)
Definition: mdlsup.c:102
bool is_top_level(_In_ PIRP Irp)
Definition: btrfs.c:276
_SEH2_TRY
Definition: create.c:4250
#define IRP_MN_COMPLETE
Definition: iotypes.h:4064
static __inline bool is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1008
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
PVOID DeviceExtension
Definition: env_spec_w32.h:418
smooth NULL
Definition: ftsmooth.c:416
#define IoCompleteRequest
Definition: irp.c:1240
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
#define FILE_WRITE_DATA
Definition: nt_native.h:631
bool add_thread_job(device_extension *Vcb, PIRP Irp)
#define STATUS_PENDING
Definition: ntstatus.h:82
#define VCB_TYPE_VOLUME
Definition: btrfs_drv.h:666
#define Vcb
Definition: cdprocs.h:1425
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
* PFILE_OBJECT
Definition: iotypes.h:1955
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
_SEH2_END
Definition: create.c:4424
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
struct _root * subvol
Definition: btrfs_drv.h:284
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define IRP_PAGING_IO
static __inline POPLOCK fcb_oplock(fcb *fcb)
Definition: btrfs_drv.h:1629
#define IO_NO_INCREMENT
Definition: iotypes.h:566
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
NTSTATUS NTAPI FsRtlCheckOplock(IN POPLOCK Oplock, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
Definition: oplock.c:1172
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
void exit(int exitcode)
Definition: _exit.c:33
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
return STATUS_SUCCESS
Definition: btrfs.c:2938
IoMarkIrpPending(Irp)
TRACE("(%p, (%I64x, %I64x), %I64x, %I64x, %I64x, %u, %p, %p)\n", Vcb, fcb->subvol->id, fcb->inode, c->offset, start_data, length, prealloc, data, rollback)

◆ _Function_class_()

_Function_class_ ( IO_COMPLETION_ROUTINE  )

Definition at line 28 of file write.c.

38  {
39  LIST_ENTRY* le;
40  space* s;
41 
42  TRACE("(%p, %I64x, %I64x, %p)\n", Vcb, c->offset, length, address);
43 
44  if (length > c->chunk_item->size - c->used)
45  return false;
46 
47  if (!c->cache_loaded) {
49 
50  if (!NT_SUCCESS(Status)) {
51  ERR("load_cache_chunk returned %08x\n", Status);
52  return false;
53  }
54  }
55 
56  if (IsListEmpty(&c->space_size))
57  return false;
58 
59  le = c->space_size.Flink;
60  while (le != &c->space_size) {
61  s = CONTAINING_RECORD(le, space, list_entry_size);
62 
63  if (s->size == length) {
64  *address = s->address;
65  return true;
66  } else if (s->size < length) {
67  if (le == c->space_size.Flink)
68  return false;
69 
70  s = CONTAINING_RECORD(le->Blink, space, list_entry_size);
71 
72  *address = s->address;
73  return true;
74  }
75 
76  le = le->Flink;
77  }
78 
79  s = CONTAINING_RECORD(c->space_size.Blink, space, list_entry_size);
80 
81  if (s->size > length) {
82  *address = s->address;
83  return true;
84  }
85 
86  return false;
87 }
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
LONG NTSTATUS
Definition: precomp.h:26
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
smooth NULL
Definition: ftsmooth.c:416
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
GLuint address
Definition: glext.h:9393
GLdouble s
Definition: gl.h:2039
Definition: typedefs.h:117
Status
Definition: gdiplustypes.h:24
NTSTATUS load_cache_chunk(device_extension *Vcb, chunk *c, PIRP Irp)
Definition: free-space.c:979
#define ERR(fmt,...)
Definition: debug.h:109
TRACE("(%p, (%I64x, %I64x), %I64x, %I64x, %I64x, %u, %p, %p)\n", Vcb, fcb->subvol->id, fcb->inode, c->offset, start_data, length, prealloc, data, rollback)

◆ _Releases_lock_()

_Releases_lock_ ( c->  lock)

◆ _Requires_lock_held_()

_Requires_lock_held_ ( c->  lock)
pure virtual

◆ add_changed_extent_ref()

add_changed_extent_ref ( c  ,
address  ,
length  ,
fcb->subvol->  id,
fcb->  inode,
start_data  ,
,
fcb->inode_item.flags BTRFS_INODE_NODATASUM 
)

◆ add_extent()

void add_extent ( _In_ fcb fcb,
_In_ LIST_ENTRY prevextle,
_In_ __drv_aliasesMem extent newext 
)

Definition at line 2351 of file write.c.

2351  {
2352  LIST_ENTRY* le = prevextle->Flink;
2353 
2354  while (le != &fcb->extents) {
2356 
2357  if (ext->offset >= newext->offset) {
2358  InsertHeadList(ext->list_entry.Blink, &newext->list_entry);
2359  return;
2360  }
2361 
2362  le = le->Flink;
2363  }
2364 
2365  InsertTailList(&fcb->extents, &newext->list_entry);
2366 }
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
#define InsertTailList(ListHead, Entry)
char ext[3]
Definition: mkdosfs.c:358
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
LIST_ENTRY extents
Definition: btrfs_drv.h:296
Definition: typedefs.h:117
Definition: list.h:27

Referenced by do_write_file_prealloc(), duplicate_extents(), and excise_extents().

◆ add_extent_to_fcb()

NTSTATUS add_extent_to_fcb ( _In_ fcb fcb,
_In_ uint64_t  offset,
_In_reads_bytes_(edsize) EXTENT_DATA ed,
_In_ uint16_t  edsize,
_In_ bool  unique,
_In_opt_ _When_(return >=0, __drv_aliasesMem) uint32_t csum,
_In_ LIST_ENTRY rollback 
)

Definition at line 2720 of file write.c.

2721  {
2722  extent* ext;
2723  LIST_ENTRY* le;
2724 
2726  if (!ext) {
2727  ERR("out of memory\n");
2729  }
2730 
2731  ext->offset = offset;
2732  ext->datalen = edsize;
2733  ext->unique = unique;
2734  ext->ignore = false;
2735  ext->inserted = true;
2736  ext->csum = csum;
2737 
2738  RtlCopyMemory(&ext->extent_data, ed, edsize);
2739 
2740  le = fcb->extents.Flink;
2741  while (le != &fcb->extents) {
2742  extent* oldext = CONTAINING_RECORD(le, extent, list_entry);
2743 
2744  if (oldext->offset >= offset) {
2745  InsertHeadList(le->Blink, &ext->list_entry);
2746  goto end;
2747  }
2748 
2749  le = le->Flink;
2750  }
2751 
2752  InsertTailList(&fcb->extents, &ext->list_entry);
2753 
2754 end:
2756 
2757  return STATUS_SUCCESS;
2758 }
void add_insert_extent_rollback(LIST_ENTRY *rollback, fcb *fcb, extent *ext)
Definition: write.c:2701
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
GLintptr offset
Definition: glext.h:5920
GLuint GLuint end
Definition: gl.h:1545
#define InsertTailList(ListHead, Entry)
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint64_t offset
Definition: btrfs_drv.h:224
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
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
uint32_t * csum
Definition: write.c:2821
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2814
LIST_ENTRY extents
Definition: btrfs_drv.h:296
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Definition: typedefs.h:117
uint16_t edsize
Definition: write.c:2820
#define ERR(fmt,...)
Definition: debug.h:109
ed2 offset
Definition: write.c:2845
Definition: list.h:27
_ForwardIter unique(_ForwardIter __first, _ForwardIter __last)
Definition: _algo.h:298
return STATUS_SUCCESS
Definition: btrfs.c:2938
EXTENT_DATA * ed
Definition: write.c:2818

Referenced by duplicate_extents(), extend_file(), rename_stream_to_file(), truncate_file(), write_file2(), and zero_data().

◆ add_insert_extent_rollback()

void add_insert_extent_rollback ( LIST_ENTRY rollback,
fcb fcb,
extent ext 
)

Definition at line 2701 of file write.c.

2701  {
2702  rollback_extent* re;
2703 
2705  if (!re) {
2706  ERR("out of memory\n");
2707  return;
2708  }
2709 
2710  re->fcb = fcb;
2711  re->ext = ext;
2712 
2714 }
#define ALLOC_TAG
Definition: btrfs_drv.h:91
char ext[3]
Definition: mkdosfs.c:358
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2814
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define ERR(fmt,...)
Definition: debug.h:109
extent * ext
Definition: btrfs_drv.h:1221
_In_ fcb * fcb
Definition: write.c:2814
void add_rollback(_In_ LIST_ENTRY *rollback, _In_ enum rollback_type type, _In_ __drv_aliasesMem void *ptr)
Definition: treefuncs.c:836

Referenced by add_extent_to_fcb(), and do_write_file_prealloc().

◆ add_partial_stripe()

static NTSTATUS add_partial_stripe ( device_extension Vcb,
chunk c,
uint64_t  address,
uint32_t  length,
void data 
)
static

Definition at line 960 of file write.c.

960  {
962  LIST_ENTRY* le;
963  partial_stripe* ps;
964  uint64_t stripe_addr;
965  uint16_t num_data_stripes;
966 
967  num_data_stripes = c->chunk_item->num_stripes - (c->chunk_item->type & BLOCK_FLAG_RAID5 ? 1 : 2);
968  stripe_addr = address - ((address - c->offset) % (num_data_stripes * c->chunk_item->stripe_length));
969 
970  ExAcquireResourceExclusiveLite(&c->partial_stripes_lock, true);
971 
972  le = c->partial_stripes.Flink;
973  while (le != &c->partial_stripes) {
975 
976  if (ps->address == stripe_addr) {
977  // update existing entry
978 
979  RtlCopyMemory(ps->data + address - stripe_addr, data, length);
980  RtlClearBits(&ps->bmp, (ULONG)((address - stripe_addr) / Vcb->superblock.sector_size), length / Vcb->superblock.sector_size);
981 
982  // if now filled, flush
983  if (RtlAreBitsClear(&ps->bmp, 0, (ULONG)((num_data_stripes * c->chunk_item->stripe_length) / Vcb->superblock.sector_size))) {
985  if (!NT_SUCCESS(Status)) {
986  ERR("flush_partial_stripe returned %08x\n", Status);
987  goto end;
988  }
989 
991 
992  if (ps->bmparr)
993  ExFreePool(ps->bmparr);
994 
995  ExFreePool(ps);
996  }
997 
999  goto end;
1000  } else if (ps->address > stripe_addr)
1001  break;
1002 
1003  le = le->Flink;
1004  }
1005 
1006  // add new entry
1007 
1008  ps = ExAllocatePoolWithTag(NonPagedPool, offsetof(partial_stripe, data[0]) + (ULONG)(num_data_stripes * c->chunk_item->stripe_length), ALLOC_TAG);
1009  if (!ps) {
1010  ERR("out of memory\n");
1012  goto end;
1013  }
1014 
1015  ps->bmplen = (ULONG)(num_data_stripes * c->chunk_item->stripe_length) / Vcb->superblock.sector_size;
1016 
1017  ps->address = stripe_addr;
1018  ps->bmparr = ExAllocatePoolWithTag(NonPagedPool, (size_t)sector_align(((ps->bmplen / 8) + 1), sizeof(ULONG)), ALLOC_TAG);
1019  if (!ps->bmparr) {
1020  ERR("out of memory\n");
1021  ExFreePool(ps);
1023  goto end;
1024  }
1025 
1026  RtlInitializeBitMap(&ps->bmp, ps->bmparr, ps->bmplen);
1027  RtlSetAllBits(&ps->bmp);
1028 
1029  RtlCopyMemory(ps->data + address - stripe_addr, data, length);
1030  RtlClearBits(&ps->bmp, (ULONG)((address - stripe_addr) / Vcb->superblock.sector_size), length / Vcb->superblock.sector_size);
1031 
1032  InsertHeadList(le->Blink, &ps->list_entry);
1033 
1035 
1036 end:
1037  ExReleaseResourceLite(&c->partial_stripes_lock);
1038 
1039  return Status;
1040 }
ULONG * bmparr
Definition: btrfs_drv.h:547
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS Status
Definition: write.c:2817
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
NTSYSAPI BOOLEAN WINAPI RtlAreBitsClear(PCRTL_BITMAP, ULONG, ULONG)
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS flush_partial_stripe(device_extension *Vcb, chunk *c, partial_stripe *ps)
Definition: flushthread.c:5799
uint64_t address
Definition: btrfs_drv.h:546
GLuint GLuint end
Definition: gl.h:1545
RTL_BITMAP bmp
Definition: btrfs_drv.h:549
unsigned short int uint16_t
Definition: acefiex.h:54
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
LIST_ENTRY list_entry
Definition: btrfs_drv.h:550
#define offsetof(TYPE, MEMBER)
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
GLuint address
Definition: glext.h:9393
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
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
uint8_t data[1]
Definition: btrfs_drv.h:551
Definition: typedefs.h:117
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
UINT64 uint64_t
Definition: types.h:77
Definition: list.h:27
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
unsigned int ULONG
Definition: retypes.h:1
ExFreePool(ed)
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
return STATUS_SUCCESS
Definition: btrfs.c:2938
static uint64_t __inline sector_align(uint64_t n, uint64_t a)

Referenced by prepare_raid5_write(), and prepare_raid6_write().

◆ alloc_chunk()

NTSTATUS alloc_chunk ( device_extension Vcb,
uint64_t  flags,
chunk **  pc,
bool  full_size 
)

Definition at line 361 of file write.c.

361  {
363  uint64_t max_stripe_size, max_chunk_size, stripe_size, stripe_length, factor;
364  uint64_t total_size = 0, logaddr;
365  uint16_t i, type, num_stripes, sub_stripes, max_stripes, min_stripes, allowed_missing;
366  stripe* stripes = NULL;
367  uint16_t cisize;
368  CHUNK_ITEM_STRIPE* cis;
369  chunk* c = NULL;
370  space* s = NULL;
371  LIST_ENTRY* le;
372 
373  le = Vcb->devices.Flink;
374  while (le != &Vcb->devices) {
376  total_size += dev->devitem.num_bytes;
377 
378  le = le->Flink;
379  }
380 
381  TRACE("total_size = %I64x\n", total_size);
382 
383  // We purposely check for DATA first - mixed blocks have the same size
384  // as DATA ones.
385  if (flags & BLOCK_FLAG_DATA) {
386  max_stripe_size = 0x40000000; // 1 GB
387  max_chunk_size = 10 * max_stripe_size;
388  } else if (flags & BLOCK_FLAG_METADATA) {
389  if (total_size > 0xC80000000) // 50 GB
390  max_stripe_size = 0x40000000; // 1 GB
391  else
392  max_stripe_size = 0x10000000; // 256 MB
393 
394  max_chunk_size = max_stripe_size;
395  } else if (flags & BLOCK_FLAG_SYSTEM) {
396  max_stripe_size = 0x2000000; // 32 MB
397  max_chunk_size = 2 * max_stripe_size;
398  } else {
399  ERR("unknown chunk type\n");
400  return STATUS_INTERNAL_ERROR;
401  }
402 
403  if (flags & BLOCK_FLAG_DUPLICATE) {
404  min_stripes = 2;
405  max_stripes = 2;
406  sub_stripes = 0;
408  allowed_missing = 0;
409  } else if (flags & BLOCK_FLAG_RAID0) {
410  min_stripes = 2;
411  max_stripes = (uint16_t)min(0xffff, Vcb->superblock.num_devices);
412  sub_stripes = 0;
414  allowed_missing = 0;
415  } else if (flags & BLOCK_FLAG_RAID1) {
416  min_stripes = 2;
417  max_stripes = 2;
418  sub_stripes = 1;
420  allowed_missing = 1;
421  } else if (flags & BLOCK_FLAG_RAID10) {
422  min_stripes = 4;
423  max_stripes = (uint16_t)min(0xffff, Vcb->superblock.num_devices);
424  sub_stripes = 2;
426  allowed_missing = 1;
427  } else if (flags & BLOCK_FLAG_RAID5) {
428  min_stripes = 3;
429  max_stripes = (uint16_t)min(0xffff, Vcb->superblock.num_devices);
430  sub_stripes = 1;
432  allowed_missing = 1;
433  } else if (flags & BLOCK_FLAG_RAID6) {
434  min_stripes = 4;
435  max_stripes = 257;
436  sub_stripes = 1;
438  allowed_missing = 2;
439  } else { // SINGLE
440  min_stripes = 1;
441  max_stripes = 1;
442  sub_stripes = 1;
443  type = 0;
444  allowed_missing = 0;
445  }
446 
447  if (max_chunk_size > total_size / 10) { // cap at 10%
448  max_chunk_size = total_size / 10;
449  max_stripe_size = max_chunk_size / min_stripes;
450  }
451 
452  TRACE("would allocate a new chunk of %I64x bytes and stripe %I64x\n", max_chunk_size, max_stripe_size);
453 
454  stripes = ExAllocatePoolWithTag(PagedPool, sizeof(stripe) * max_stripes, ALLOC_TAG);
455  if (!stripes) {
456  ERR("out of memory\n");
458  goto end;
459  }
460 
461  num_stripes = 0;
462 
463  if (type == BLOCK_FLAG_DUPLICATE) {
464  if (!find_new_dup_stripes(Vcb, stripes, max_stripe_size, full_size)) {
466  goto end;
467  }
468  else
469  num_stripes = max_stripes;
470  } else {
471  for (i = 0; i < max_stripes; i++) {
472  if (!find_new_stripe(Vcb, stripes, i, max_stripe_size, false, full_size))
473  break;
474  else
475  num_stripes++;
476  }
477  }
478 
479  if (num_stripes < min_stripes && Vcb->options.allow_degraded && allowed_missing > 0) {
480  uint16_t added_missing = 0;
481 
482  for (i = num_stripes; i < max_stripes; i++) {
483  if (!find_new_stripe(Vcb, stripes, i, max_stripe_size, true, full_size))
484  break;
485  else {
486  added_missing++;
487  if (added_missing >= allowed_missing)
488  break;
489  }
490  }
491 
492  num_stripes += added_missing;
493  }
494 
495  // for RAID10, round down to an even number of stripes
496  if (type == BLOCK_FLAG_RAID10 && (num_stripes % sub_stripes) != 0) {
497  num_stripes -= num_stripes % sub_stripes;
498  }
499 
500  if (num_stripes < min_stripes) {
501  WARN("found %u stripes, needed at least %u\n", num_stripes, min_stripes);
503  goto end;
504  }
505 
507  if (!c) {
508  ERR("out of memory\n");
510  goto end;
511  }
512 
513  c->devices = NULL;
514 
515  cisize = sizeof(CHUNK_ITEM) + (num_stripes * sizeof(CHUNK_ITEM_STRIPE));
516  c->chunk_item = ExAllocatePoolWithTag(NonPagedPool, cisize, ALLOC_TAG);
517  if (!c->chunk_item) {
518  ERR("out of memory\n");
520  goto end;
521  }
522 
523  stripe_length = 0x10000; // FIXME? BTRFS_STRIPE_LEN in kernel
524 
525  if (type == BLOCK_FLAG_DUPLICATE && stripes[1].dh == stripes[0].dh)
526  stripe_size = min(stripes[0].dh->size / 2, max_stripe_size);
527  else {
528  stripe_size = max_stripe_size;
529  for (i = 0; i < num_stripes; i++) {
530  if (stripes[i].dh->size < stripe_size)
531  stripe_size = stripes[i].dh->size;
532  }
533  }
534 
535  if (type == 0 || type == BLOCK_FLAG_DUPLICATE || type == BLOCK_FLAG_RAID1)
536  factor = 1;
537  else if (type == BLOCK_FLAG_RAID0)
538  factor = num_stripes;
539  else if (type == BLOCK_FLAG_RAID10)
540  factor = num_stripes / sub_stripes;
541  else if (type == BLOCK_FLAG_RAID5)
542  factor = num_stripes - 1;
543  else if (type == BLOCK_FLAG_RAID6)
544  factor = num_stripes - 2;
545 
546  if (stripe_size * factor > max_chunk_size)
547  stripe_size = max_chunk_size / factor;
548 
549  if (stripe_size % stripe_length > 0)
550  stripe_size -= stripe_size % stripe_length;
551 
552  if (stripe_size == 0) {
553  ERR("not enough free space found (stripe_size == 0)\n");
555  goto end;
556  }
557 
558  c->chunk_item->size = stripe_size * factor;
559  c->chunk_item->root_id = Vcb->extent_root->id;
560  c->chunk_item->stripe_length = stripe_length;
561  c->chunk_item->type = flags;
562  c->chunk_item->opt_io_alignment = (uint32_t)c->chunk_item->stripe_length;
563  c->chunk_item->opt_io_width = (uint32_t)c->chunk_item->stripe_length;
564  c->chunk_item->sector_size = stripes[0].device->devitem.minimal_io_size;
565  c->chunk_item->num_stripes = num_stripes;
566  c->chunk_item->sub_stripes = sub_stripes;
567 
568  c->devices = ExAllocatePoolWithTag(NonPagedPool, sizeof(device*) * num_stripes, ALLOC_TAG);
569  if (!c->devices) {
570  ERR("out of memory\n");
572  goto end;
573  }
574 
575  cis = (CHUNK_ITEM_STRIPE*)&c->chunk_item[1];
576  for (i = 0; i < num_stripes; i++) {
577  cis[i].dev_id = stripes[i].device->devitem.dev_id;
578 
579  if (type == BLOCK_FLAG_DUPLICATE && i == 1 && stripes[i].dh == stripes[0].dh)
580  cis[i].offset = stripes[0].dh->address + stripe_size;
581  else
582  cis[i].offset = stripes[i].dh->address;
583 
584  cis[i].dev_uuid = stripes[i].device->devitem.device_uuid;
585 
586  c->devices[i] = stripes[i].device;
587  }
588 
589  logaddr = find_new_chunk_address(Vcb, c->chunk_item->size);
590 
591  Vcb->superblock.chunk_root_generation = Vcb->superblock.generation;
592 
593  c->size = cisize;
594  c->offset = logaddr;
595  c->used = c->oldused = 0;
596  c->cache = c->old_cache = NULL;
597  c->readonly = false;
598  c->reloc = false;
599  c->last_alloc_set = false;
600  c->last_stripe = 0;
601  c->cache_loaded = true;
602  c->changed = false;
603  c->space_changed = false;
604  c->balance_num = 0;
605 
606  InitializeListHead(&c->space);
607  InitializeListHead(&c->space_size);
608  InitializeListHead(&c->deleting);
609  InitializeListHead(&c->changed_extents);
610 
611  InitializeListHead(&c->range_locks);
612  ExInitializeResourceLite(&c->range_locks_lock);
613  KeInitializeEvent(&c->range_locks_event, NotificationEvent, false);
614 
615  InitializeListHead(&c->partial_stripes);
616  ExInitializeResourceLite(&c->partial_stripes_lock);
617 
618  ExInitializeResourceLite(&c->lock);
619  ExInitializeResourceLite(&c->changed_extents_lock);
620 
622  if (!s) {
623  ERR("out of memory\n");
625  goto end;
626  }
627 
628  s->address = c->offset;
629  s->size = c->chunk_item->size;
630  InsertTailList(&c->space, &s->list_entry);
631  InsertTailList(&c->space_size, &s->list_entry_size);
632 
634 
635  for (i = 0; i < num_stripes; i++) {
636  stripes[i].device->devitem.bytes_used += stripe_size;
637 
638  space_list_subtract2(&stripes[i].device->space, NULL, cis[i].offset, stripe_size, NULL, NULL);
639  }
640 
642 
644  Vcb->superblock.incompat_flags |= BTRFS_INCOMPAT_FLAGS_RAID56;
645 
646 end:
647  if (stripes)
648  ExFreePool(stripes);
649 
650  if (!NT_SUCCESS(Status)) {
651  if (c) {
652  if (c->devices)
653  ExFreePool(c->devices);
654 
655  if (c->chunk_item)
656  ExFreePool(c->chunk_item);
657 
658  ExFreePool(c);
659  }
660 
661  if (s) ExFreePool(s);
662  } else {
663  bool done = false;
664 
665  le = Vcb->chunks.Flink;
666  while (le != &Vcb->chunks) {
668 
669  if (c2->offset > c->offset) {
670  InsertHeadList(le->Blink, &c->list_entry);
671  done = true;
672  break;
673  }
674 
675  le = le->Flink;
676  }
677 
678  if (!done)
679  InsertTailList(&Vcb->chunks, &c->list_entry);
680 
681  c->created = true;
682  c->changed = true;
683  c->space_changed = true;
684  c->list_entry_balance.Flink = NULL;
685 
686  *pc = c;
687  }
688 
689  return Status;
690 }
LIST_ENTRY space
Definition: btrfs_drv.h:532
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS Status
Definition: write.c:2817
uint64_t dev_id
Definition: btrfs.h:330
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
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
uint64_t offset
Definition: btrfs_drv.h:557
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
Definition: write.c:111
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
#define InsertTailList(ListHead, Entry)
uint64_t address
Definition: btrfs_drv.h:511
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint64_t offset
Definition: btrfs.h:331
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
ed type
Definition: write.c:2840
Definition: devices.h:37
#define BLOCK_FLAG_SYSTEM
Definition: shellext.h:76
smooth NULL
Definition: ftsmooth.c:416
static bool find_new_dup_stripes(device_extension *Vcb, stripe *stripes, uint64_t max_stripe_size, bool full_size)
Definition: write.c:137
#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
BTRFS_UUID device_uuid
Definition: btrfs.h:174
#define BLOCK_FLAG_RAID0
Definition: shellext.h:78
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
static bool find_new_stripe(device_extension *Vcb, stripe *stripes, uint16_t i, uint64_t max_stripe_size, bool allow_missing, bool full_size)
Definition: write.c:248
#define for
Definition: utility.h:88
BTRFS_UUID dev_uuid
Definition: btrfs.h:332
#define BLOCK_FLAG_RAID6
Definition: shellext.h:83
GLbitfield flags
Definition: glext.h:7161
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
void protect_superblocks(_Inout_ chunk *c)
Definition: btrfs.c:3634
#define BLOCK_FLAG_METADATA
Definition: shellext.h:77
uint64_t dev_id
Definition: btrfs.h:162
GLdouble s
Definition: gl.h:2039
Definition: typedefs.h:117
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
device * device
Definition: write.c:113
uint64_t size
Definition: btrfs_drv.h:512
UINT64 uint64_t
Definition: types.h:77
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
space * dh
Definition: write.c:112
void space_list_subtract2(LIST_ENTRY *list, LIST_ENTRY *list_size, uint64_t address, uint64_t length, chunk *c, LIST_ENTRY *rollback)
Definition: free-space.c:1967
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
DEV_ITEM devitem
Definition: btrfs_drv.h:520
UINT32 uint32_t
Definition: types.h:75
#define BLOCK_FLAG_DATA
Definition: shellext.h:75
uint32_t minimal_io_size
Definition: btrfs.h:167
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
uint64_t bytes_used
Definition: btrfs.h:164
#define BTRFS_INCOMPAT_FLAGS_RAID56
Definition: btrfs.h:113
ExFreePool(ed)
#define BLOCK_FLAG_DUPLICATE
Definition: shellext.h:80
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
#define uint32_t
Definition: nsiface.idl:61
return STATUS_SUCCESS
Definition: btrfs.c:2938
_In_ fcb _In_ chunk * c
Definition: write.c:2814
static uint64_t find_new_chunk_address(device_extension *Vcb, uint64_t size)
Definition: write.c:116
#define BLOCK_FLAG_RAID1
Definition: shellext.h:79
TRACE("(%p, (%I64x, %I64x), %I64x, %I64x, %I64x, %u, %p, %p)\n", Vcb, fcb->subvol->id, fcb->inode, c->offset, start_data, length, prealloc, data, rollback)

Referenced by _Function_class_(), balance_data_chunk(), get_tree_new_address(), insert_cache_extent(), insert_chunk_fragmented(), insert_extent(), insert_prealloc_extent(), lzo_write_compressed_bit(), try_consolidation(), write_metadata_items(), zlib_write_compressed_bit(), and zstd_write_compressed_bit().

◆ calc_csum()

Definition at line 2782 of file write.c.

2783  {
2784  NTSTATUS Status;
2785  calc_job* cj;
2786 
2787  // From experimenting, it seems that 40 sectors is roughly the crossover
2788  // point where offloading the crc32 calculation becomes worth it.
2789 
2790  if (sectors < 40 || get_num_of_processors() < 2) {
2791  ULONG j;
2792 
2793  for (j = 0; j < sectors; j++) {
2794  csum[j] = ~calc_crc32c(0xffffffff, data + (j * Vcb->superblock.sector_size), Vcb->superblock.sector_size);
2795  }
2796 
2797  return STATUS_SUCCESS;
2798  }
2799 
2801  if (!NT_SUCCESS(Status)) {
2802  ERR("add_calc_job returned %08x\n", Status);
2803  return Status;
2804  }
2805 
2806  KeWaitForSingleObject(&cj->event, Executive, KernelMode, false, NULL);
2807  free_calc_job(cj);
2808 
2809  return STATUS_SUCCESS;
2810 }
_In_ ULONG cj
Definition: winddi.h:3540
NTSTATUS Status
Definition: write.c:2817
LONG NTSTATUS
Definition: precomp.h:26
void free_calc_job(calc_job *cj)
Definition: calcthread.c:53
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
static uint32_t calc_crc32c(uint32_t seed, uint8_t *msg, ULONG msglen)
Definition: recv.cpp:134
uint32_t get_num_of_processors()
Definition: btrfs.c:3957
smooth NULL
Definition: ftsmooth.c:416
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 NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
__u8 sectors[2]
Definition: mkdosfs.c:366
Definition: fs.h:216
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS add_calc_job(device_extension *Vcb, uint8_t *data, uint32_t sectors, uint32_t *csum, calc_job **pcj)
Definition: calcthread.c:22
return STATUS_SUCCESS
Definition: btrfs.c:2938

Referenced by do_write_file(), do_write_file_prealloc(), if(), scrub_extent_dup(), and scrub_extent_raid10().

◆ do_write_file()

NTSTATUS do_write_file ( fcb fcb,
uint64_t  start,
uint64_t  end_data,
void data,
PIRP  Irp,
bool  file_write,
uint32_t  irp_offset,
LIST_ENTRY rollback 
)

Definition at line 3939 of file write.c.

3939  {
3940  NTSTATUS Status;
3941  LIST_ENTRY *le, *le2;
3942  uint64_t written = 0, length = end_data - start;
3943  uint64_t last_cow_start;
3945 #ifdef DEBUG_PARANOID
3946  uint64_t last_off;
3947 #endif
3948  bool extents_changed = false;
3949 
3950  last_cow_start = 0;
3951 
3952  le = fcb->extents.Flink;
3953  while (le != &fcb->extents) {
3955 
3956  le2 = le->Flink;
3957 
3958  if (!ext->ignore) {
3959  EXTENT_DATA* ed = &ext->extent_data;
3961  uint64_t len;
3962 
3964 
3965  if (ext->offset + len <= start)
3966  goto nextitem;
3967 
3968  if (ext->offset > start + written + length)
3969  break;
3970 
3972  if (max(last_cow_start, start + written) < ext->offset) {
3973  uint64_t start_write = max(last_cow_start, start + written);
3974 
3975  extents_changed = true;
3976 
3977  Status = excise_extents(fcb->Vcb, fcb, start_write, ext->offset, Irp, rollback);
3978  if (!NT_SUCCESS(Status)) {
3979  ERR("excise_extents returned %08x\n", Status);
3980  return Status;
3981  }
3982 
3983  Status = insert_extent(fcb->Vcb, fcb, start_write, ext->offset - start_write, (uint8_t*)data + written, Irp, file_write, irp_offset + written, rollback);
3984  if (!NT_SUCCESS(Status)) {
3985  ERR("insert_extent returned %08x\n", Status);
3986  return Status;
3987  }
3988 
3989  written += ext->offset - start_write;
3990  length -= ext->offset - start_write;
3991 
3992  if (length == 0)
3993  break;
3994  }
3995 
3996  if (ed->type == EXTENT_TYPE_REGULAR) {
3997  uint64_t writeaddr = ed2->address + ed2->offset + start + written - ext->offset;
3998  uint64_t write_len = min(len, length);
3999  chunk* c;
4000 
4001  TRACE("doing non-COW write to %I64x\n", writeaddr);
4002 
4003  Status = write_data_complete(fcb->Vcb, writeaddr, (uint8_t*)data + written, (uint32_t)write_len, Irp, NULL, file_write, irp_offset + written, priority);
4004  if (!NT_SUCCESS(Status)) {
4005  ERR("write_data_complete returned %08x\n", Status);
4006  return Status;
4007  }
4008 
4009  c = get_chunk_from_address(fcb->Vcb, writeaddr);
4010  if (c)
4011  c->changed = true;
4012 
4013  // This shouldn't ever get called - nocow files should always also be nosum.
4015  calc_csum(fcb->Vcb, (uint8_t*)data + written, (uint32_t)(write_len / fcb->Vcb->superblock.sector_size),
4016  &ext->csum[(start + written - ext->offset) / fcb->Vcb->superblock.sector_size]);
4017 
4018  ext->inserted = true;
4019  extents_changed = true;
4020  }
4021 
4022  written += write_len;
4023  length -= write_len;
4024 
4025  if (length == 0)
4026  break;
4027  } else if (ed->type == EXTENT_TYPE_PREALLOC) {
4028  uint64_t write_len;
4029 
4030  Status = do_write_file_prealloc(fcb, ext, start + written, end_data, (uint8_t*)data + written, &write_len,
4031  Irp, file_write, irp_offset + written, priority, rollback);
4032  if (!NT_SUCCESS(Status)) {
4033  ERR("do_write_file_prealloc returned %08x\n", Status);
4034  return Status;
4035  }
4036 
4037  extents_changed = true;
4038 
4039  written += write_len;
4040  length -= write_len;
4041 
4042  if (length == 0)
4043  break;
4044  }
4045 
4046  last_cow_start = ext->offset + len;
4047  }
4048  }
4049 
4050 nextitem:
4051  le = le2;
4052  }
4053 
4054  if (length > 0) {
4055  uint64_t start_write = max(last_cow_start, start + written);
4056 
4057  extents_changed = true;
4058 
4059  Status = excise_extents(fcb->Vcb, fcb, start_write, end_data, Irp, rollback);
4060  if (!NT_SUCCESS(Status)) {
4061  ERR("excise_extents returned %08x\n", Status);
4062  return Status;
4063  }
4064 
4065  Status = insert_extent(fcb->Vcb, fcb, start_write, end_data - start_write, (uint8_t*)data + written, Irp, file_write, irp_offset + written, rollback);
4066  if (!NT_SUCCESS(Status)) {
4067  ERR("insert_extent returned %08x\n", Status);
4068  return Status;
4069  }
4070  }
4071 
4072 #ifdef DEBUG_PARANOID
4073  last_off = 0xffffffffffffffff;
4074 
4075  le = fcb->extents.Flink;
4076  while (le != &fcb->extents) {
4078 
4079  if (!ext->ignore) {
4080  if (ext->offset == last_off) {
4081  ERR("offset %I64x duplicated\n", ext->offset);
4082  int3;
4083  } else if (ext->offset < last_off && last_off != 0xffffffffffffffff) {
4084  ERR("offsets out of order\n");
4085  int3;
4086  }
4087 
4088  last_off = ext->offset;
4089  }
4090 
4091  le = le->Flink;
4092  }
4093 #endif
4094 
4095  if (extents_changed) {
4096  fcb->extents_changed = true;
4098  }
4099 
4100  return STATUS_SUCCESS;
4101 }
LOCAL void nextitem(arg_t *ap)
Definition: match.c:428
#define max(a, b)
Definition: svc.c:63
uint8_t type
Definition: btrfs.h:341
NTSTATUS Status
Definition: write.c:2817
fcb extents_changed
Definition: write.c:2882
#define BTRFS_INODE_NODATACOW
Definition: propsheet.h:77
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:61
EXTENT_DATA2 * ed2
Definition: write.c:2819
_In_ PIRP Irp
Definition: csq.h:116
uint64_t decoded_size
Definition: btrfs.h:337
#define FSRTL_FLAG2_IS_PAGING_FILE
Definition: fsrtltypes.h:57
LONG NTSTATUS
Definition: precomp.h:26
#define int3
Definition: btrfs_drv.h:1722
static NTSTATUS insert_extent(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t length, void *data, PIRP Irp, bool file_write, uint64_t irp_offset, LIST_ENTRY *rollback)
Definition: write.c:3125
static NTSTATUS do_write_file_prealloc(fcb *fcb, extent *ext, uint64_t start_data, uint64_t end_data, void *data, uint64_t *written, PIRP Irp, bool file_write, uint64_t irp_offset, ULONG priority, LIST_ENTRY *rollback)
Definition: write.c:3552
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool _In_ uint64_t irp_offset
Definition: write.c:2815
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:70
uint64_t address
Definition: btrfs.h:346
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool file_write
Definition: write.c:2814
bool extents_changed
Definition: btrfs_drv.h:319
smooth NULL
Definition: ftsmooth.c:416
char ext[3]
Definition: mkdosfs.c:358
NTSTATUS write_data_complete(device_extension *Vcb, uint64_t address, void *data, uint32_t length, PIRP Irp, chunk *c, bool file_write, uint64_t irp_offset, ULONG priority)
Definition: write.c:2166
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
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:279
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
const GLubyte * c
Definition: glext.h:8905
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2814
LIST_ENTRY extents
Definition: btrfs_drv.h:296
NTSTATUS calc_csum(_In_ device_extension *Vcb, _In_reads_bytes_(sectors *Vcb->superblock.sector_size) uint8_t *data, _In_ uint32_t sectors, _Out_writes_bytes_(sectors *sizeof(uint32_t)) uint32_t *csum)
Definition: write.c:2782
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLenum GLsizei len
Definition: glext.h:6722
Definition: typedefs.h:117
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:72
INODE_ITEM inode_item
Definition: btrfs_drv.h:288
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t num_bytes
Definition: btrfs.h:349
uint64_t flags
Definition: btrfs.h:280
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:71
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
uint8_t data[1]
Definition: btrfs.h:342
UINT64 uint64_t
Definition: types.h:77
GLuint start
Definition: gl.h:1545
chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address)
Definition: write.c:89
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
mark_fcb_dirty(fcb)
UINT32 uint32_t
Definition: types.h:75
NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback)
Definition: write.c:2368
if(!find_data_address_in_chunk(Vcb, c, length, &address)) return false
unsigned int ULONG
Definition: retypes.h:1
static int priority
Definition: timer.c:163
uint64_t offset
Definition: btrfs.h:348
return STATUS_SUCCESS
Definition: btrfs.c:2938
_In_ fcb _In_ chunk * c
Definition: write.c:2814
EXTENT_DATA * ed
Definition: write.c:2818
struct _device_extension * Vcb
Definition: btrfs_drv.h:283
uint8_t compression
Definition: btrfs.h:338
TRACE("(%p, (%I64x, %I64x), %I64x, %I64x, %I64x, %u, %p, %p)\n", Vcb, fcb->subvol->id, fcb->inode, c->offset, start_data, length, prealloc, data, rollback)

Referenced by duplicate_extents(), extend_file(), rename_stream_to_file(), truncate_file(), update_chunk_cache(), write_compressed(), write_file2(), and zero_data().

◆ do_write_file_prealloc()

static NTSTATUS do_write_file_prealloc ( fcb fcb,
extent ext,
uint64_t  start_data,
uint64_t  end_data,
void data,
uint64_t written,
PIRP  Irp,
bool  file_write,
uint64_t  irp_offset,
ULONG  priority,
LIST_ENTRY rollback 
)
static

Definition at line 3552 of file write.c.

3553  {
3554  EXTENT_DATA* ed = &ext->extent_data;
3556  NTSTATUS Status;
3557  chunk* c = NULL;
3558 
3559  if (start_data <= ext->offset && end_data >= ext->offset + ed2->num_bytes) { // replace all
3560  extent* newext;
3561 
3562  newext = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3563  if (!newext) {
3564  ERR("out of memory\n");
3566  }
3567 
3568  RtlCopyMemory(&newext->extent_data, &ext->extent_data, ext->datalen);
3569 
3571 
3573  NULL, file_write, irp_offset + ext->offset - start_data, priority);
3574  if (!NT_SUCCESS(Status)) {
3575  ERR("write_data_complete returned %08x\n", Status);
3576  return Status;
3577  }
3578 
3580  ULONG sl = (ULONG)(ed2->num_bytes / fcb->Vcb->superblock.sector_size);
3582 
3583  if (!csum) {
3584  ERR("out of memory\n");
3585  ExFreePool(newext);
3587  }
3588 
3589  Status = calc_csum(fcb->Vcb, (uint8_t*)data + ext->offset - start_data, sl, csum);
3590  if (!NT_SUCCESS(Status)) {
3591  ERR("calc_csum returned %08x\n", Status);
3592  ExFreePool(csum);
3593  ExFreePool(newext);
3594  return Status;
3595  }
3596 
3597  newext->csum = csum;
3598  } else
3599  newext->csum = NULL;
3600 
3601  *written = ed2->num_bytes;
3602 
3603  newext->offset = ext->offset;
3604  newext->datalen = ext->datalen;
3605  newext->unique = ext->unique;
3606  newext->ignore = false;
3607  newext->inserted = true;
3608  InsertHeadList(&ext->list_entry, &newext->list_entry);
3609 
3611 
3613 
3615  } else if (start_data <= ext->offset && end_data < ext->offset + ed2->num_bytes) { // replace beginning
3616  EXTENT_DATA2* ned2;
3617  extent *newext1, *newext2;
3618 
3619  newext1 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3620  if (!newext1) {
3621  ERR("out of memory\n");
3623  }
3624 
3625  newext2 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3626  if (!newext2) {
3627  ERR("out of memory\n");
3628  ExFreePool(newext1);
3630  }
3631 
3632  RtlCopyMemory(&newext1->extent_data, &ext->extent_data, ext->datalen);
3634  ned2 = (EXTENT_DATA2*)newext1->extent_data.data;
3635  ned2->num_bytes = end_data - ext->offset;
3636 
3637  RtlCopyMemory(&newext2->extent_data, &ext->extent_data, ext->datalen);
3638  ned2 = (EXTENT_DATA2*)newext2->extent_data.data;
3639  ned2->offset += end_data - ext->offset;
3640  ned2->num_bytes -= end_data - ext->offset;
3641 
3642  Status = write_data_complete(fcb->Vcb, ed2->address + ed2->offset, (uint8_t*)data + ext->offset - start_data, (uint32_t)(end_data - ext->offset),
3643  Irp, NULL, file_write, irp_offset + ext->offset - start_data, priority);
3644  if (!NT_SUCCESS(Status)) {
3645  ERR("write_data_complete returned %08x\n", Status);
3646  ExFreePool(newext1);
3647  ExFreePool(newext2);
3648  return Status;
3649  }
3650 
3652  ULONG sl = (ULONG)((end_data - ext->offset) / fcb->Vcb->superblock.sector_size);
3654 
3655  if (!csum) {
3656  ERR("out of memory\n");
3657  ExFreePool(newext1);
3658  ExFreePool(newext2);
3660  }
3661 
3662  Status = calc_csum(fcb->Vcb, (uint8_t*)data + ext->offset - start_data, sl, csum);
3663  if (!NT_SUCCESS(Status)) {
3664  ERR("calc_csum returned %08x\n", Status);
3665  ExFreePool(newext1);
3666  ExFreePool(newext2);
3667  ExFreePool(csum);
3668  return Status;
3669  }
3670 
3671  newext1->csum = csum;
3672  } else
3673  newext1->csum = NULL;
3674 
3675  *written = end_data - ext->offset;
3676 
3677  newext1->offset = ext->offset;
3678  newext1->datalen = ext->datalen;
3679  newext1->unique = ext->unique;
3680  newext1->ignore = false;
3681  newext1->inserted = true;
3682  InsertHeadList(&ext->list_entry, &newext1->list_entry);
3683 
3685 
3686  newext2->offset = end_data;
3687  newext2->datalen = ext->datalen;
3688  newext2->unique = ext->unique;
3689  newext2->ignore = false;
3690  newext2->inserted = true;
3691  newext2->csum = NULL;
3692  add_extent(fcb, &newext1->list_entry, newext2);
3693 
3695 
3697 
3698  if (!c)
3699  ERR("get_chunk_from_address(%I64x) failed\n", ed2->address);
3700  else {
3703 
3704  if (!NT_SUCCESS(Status)) {
3705  ERR("update_changed_extent_ref returned %08x\n", Status);
3706  return Status;
3707  }
3708  }
3709 
3711  } else if (start_data > ext->offset && end_data >= ext->offset + ed2->num_bytes) { // replace end
3712  EXTENT_DATA2* ned2;
3713  extent *newext1, *newext2;
3714 
3715  newext1 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3716  if (!newext1) {
3717  ERR("out of memory\n");
3719  }
3720 
3721  newext2 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3722  if (!newext2) {
3723  ERR("out of memory\n");
3724  ExFreePool(newext1);
3726  }
3727 
3728  RtlCopyMemory(&newext1->extent_data, &ext->extent_data, ext->datalen);
3729 
3730  ned2 = (EXTENT_DATA2*)newext1->extent_data.data;
3731  ned2->num_bytes = start_data - ext->offset;
3732 
3733  RtlCopyMemory(&newext2->extent_data, &ext->extent_data, ext->datalen);
3734 
3736  ned2 = (EXTENT_DATA2*)newext2->extent_data.data;
3737  ned2->offset += start_data - ext->offset;
3738  ned2->num_bytes = ext->offset + ed2->num_bytes - start_data;
3739 
3741  if (!NT_SUCCESS(Status)) {
3742  ERR("write_data_complete returned %08x\n", Status);
3743  ExFreePool(newext1);
3744  ExFreePool(newext2);
3745  return Status;
3746  }
3747 
3749  ULONG sl = (ULONG)(ned2->num_bytes / fcb->Vcb->superblock.sector_size);
3751 
3752  if (!csum) {
3753  ERR("out of memory\n");
3754  ExFreePool(newext1);
3755  ExFreePool(newext2);
3757  }
3758 
3759  Status = calc_csum(fcb->Vcb, data, sl, csum);
3760  if (!NT_SUCCESS(Status)) {
3761  ERR("calc_csum returned %08x\n", Status);
3762  ExFreePool(newext1);
3763  ExFreePool(newext2);
3764  ExFreePool(csum);
3765  return Status;
3766  }
3767 
3768  newext2->csum = csum;
3769  } else
3770  newext2->csum = NULL;
3771 
3772  *written = ned2->num_bytes;
3773 
3774  newext1->offset = ext->offset;
3775  newext1->datalen = ext->datalen;
3776  newext1->unique = ext->unique;
3777  newext1->ignore = false;
3778  newext1->inserted = true;
3779  newext1->csum = NULL;
3780  InsertHeadList(&ext->list_entry, &newext1->list_entry);
3781 
3783 
3784  newext2->offset = start_data;
3785  newext2->datalen = ext->datalen;
3786  newext2->unique = ext->unique;
3787  newext2->ignore = false;
3788  newext2->inserted = true;
3789  add_extent(fcb, &newext1->list_entry, newext2);
3790 
3792 
3794 
3795  if (!c)
3796  ERR("get_chunk_from_address(%I64x) failed\n", ed2->address);
3797  else {
3800 
3801  if (!NT_SUCCESS(Status)) {
3802  ERR("update_changed_extent_ref returned %08x\n", Status);
3803  return Status;
3804  }
3805  }
3806 
3808  } else if (start_data > ext->offset && end_data < ext->offset + ed2->num_bytes) { // replace middle
3809  EXTENT_DATA2* ned2;
3810  extent *newext1, *newext2, *newext3;
3811 
3812  newext1 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3813  if (!newext1) {
3814  ERR("out of memory\n");
3816  }
3817 
3818  newext2 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3819  if (!newext2) {
3820  ERR("out of memory\n");
3821  ExFreePool(newext1);
3823  }
3824 
3825  newext3 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3826  if (!newext3) {
3827  ERR("out of memory\n");
3828  ExFreePool(newext1);
3829  ExFreePool(newext2);
3831  }
3832 
3833  RtlCopyMemory(&newext1->extent_data, &ext->extent_data, ext->datalen);
3834  RtlCopyMemory(&newext2->extent_data, &ext->extent_data, ext->datalen);
3835  RtlCopyMemory(&newext3->extent_data, &ext->extent_data, ext->datalen);
3836 
3837  ned2 = (EXTENT_DATA2*)newext1->extent_data.data;
3838  ned2->num_bytes = start_data - ext->offset;
3839 
3841  ned2 = (EXTENT_DATA2*)newext2->extent_data.data;
3842  ned2->offset += start_data - ext->offset;
3843  ned2->num_bytes = end_data - start_data;
3844 
3845  ned2 = (EXTENT_DATA2*)newext3->extent_data.data;
3846  ned2->offset += end_data - ext->offset;
3847  ned2->num_bytes -= end_data - ext->offset;
3848 
3849  ned2 = (EXTENT_DATA2*)newext2->extent_data.data;
3851  if (!NT_SUCCESS(Status)) {
3852  ERR("write_data_complete returned %08x\n", Status);
3853  ExFreePool(newext1);
3854  ExFreePool(newext2);
3855  ExFreePool(newext3);
3856  return Status;
3857  }
3858 
3860  ULONG sl = (ULONG)((end_data - start_data) / fcb->Vcb->superblock.sector_size);
3862 
3863  if (!csum) {
3864  ERR("out of memory\n");
3865  ExFreePool(newext1);
3866  ExFreePool(newext2);
3867  ExFreePool(newext3);
3869  }
3870 
3871  Status = calc_csum(fcb->Vcb, data, sl, csum);
3872  if (!NT_SUCCESS(Status)) {
3873  ERR("calc_csum returned %08x\n", Status);
3874  ExFreePool(newext1);
3875  ExFreePool(newext2);
3876  ExFreePool(newext3);
3877  ExFreePool(csum);
3878  return Status;
3879  }
3880 
3881  newext2->csum = csum;
3882  } else
3883  newext2->csum = NULL;
3884 
3885  *written = end_data - start_data;
3886 
3887  newext1->offset = ext->offset;
3888  newext1->datalen = ext->datalen;
3889  newext1->unique = ext->unique;
3890  newext1->ignore = false;
3891  newext1->inserted = true;
3892  newext1->csum = NULL;
3893  InsertHeadList(&ext->list_entry, &newext1->list_entry);
3894 
3896 
3897  newext2->offset = start_data;
3898  newext2->datalen = ext->datalen;
3899  newext2->unique = ext->unique;
3900  newext2->ignore = false;
3901  newext2->inserted = true;
3902  add_extent(fcb, &newext1->list_entry, newext2);
3903 
3905 
3906  newext3->offset = end_data;
3907  newext3->datalen = ext->datalen;
3908  newext3->unique = ext->unique;
3909  newext3->ignore = false;
3910  newext3->inserted = true;
3911  newext3->csum = NULL;
3912  add_extent(fcb, &newext2->list_entry, newext3);
3913 
3915 
3917 
3918  if (!c)
3919  ERR("get_chunk_from_address(%I64x) failed\n", ed2->address);
3920  else {
3923 
3924  if (!NT_SUCCESS(Status)) {
3925  ERR("update_changed_extent_ref returned %08x\n", Status);
3926  return Status;
3927  }
3928  }
3929 
3931  }
3932 
3933  if (c)
3934  c->changed = true;
3935 
3936  return STATUS_SUCCESS;
3937 }
void add_extent(_In_ fcb *fcb, _In_ LIST_ENTRY *prevextle, _In_ __drv_aliasesMem extent *newext)
Definition: write.c:2351
void add_insert_extent_rollback(LIST_ENTRY *rollback, fcb *fcb, extent *ext)
Definition: write.c:2701
uint8_t type
Definition: btrfs.h:341
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS update_changed_extent_ref(device_extension *Vcb, chunk *c, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, int32_t count, bool no_csum, bool superseded, PIRP Irp)
Definition: extent-tree.c:1950
NTSTATUS Status
Definition: write.c:2817
EXTENT_DATA2 * ed2
Definition: write.c:2819
_In_ PIRP Irp
Definition: csq.h:116
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
LIST_ENTRY list_entry
Definition: btrfs_drv.h:231
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool _In_ uint64_t irp_offset
Definition: write.c:2815
uint16_t datalen
Definition: btrfs_drv.h:225
bool ignore
Definition: btrfs_drv.h:227
#define ALLOC_TAG
Definition: btrfs_drv.h:91
bool inserted
Definition: btrfs_drv.h:228
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool file_write
Definition: write.c:2814
uint64_t address
Definition: btrfs.h:346
uint64_t offset
Definition: btrfs_drv.h:224
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
uint64_t size
Definition: btrfs.h:347
NTSTATUS write_data_complete(device_extension *Vcb, uint64_t address, void *data, uint32_t length, PIRP Irp, chunk *c, bool file_write, uint64_t irp_offset, ULONG priority)
Definition: write.c:2166
bool unique
Definition: btrfs_drv.h:226
uint32_t * csum
Definition: write.c:2821
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t inode
Definition: btrfs_drv.h:285
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
const GLubyte * c
Definition: glext.h:8905
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2814
NTSTATUS calc_csum(_In_ device_extension *Vcb, _In_reads_bytes_(sectors *Vcb->superblock.sector_size) uint8_t *data, _In_ uint32_t sectors, _Out_writes_bytes_(sectors *sizeof(uint32_t)) uint32_t *csum)
Definition: write.c:2782
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
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP Irp
Definition: write.c:2814
_In_ fcb _In_ chunk _In_ uint64_t start_data
Definition: write.c:2814
INODE_ITEM inode_item
Definition: btrfs_drv.h:288
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t num_bytes
Definition: btrfs.h:349
uint64_t flags
Definition: btrfs.h:280
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:71
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
uint8_t data[1]
Definition: btrfs.h:342
uint32_t * csum
Definition: btrfs_drv.h:229
chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address)
Definition: write.c:89
struct _root * subvol
Definition: btrfs_drv.h:284
UINT32 uint32_t
Definition: types.h:75
Definition: fs.h:216
EXTENT_DATA extent_data
Definition: btrfs_drv.h:233
if(!find_data_address_in_chunk(Vcb, c, length, &address)) return false
unsigned int ULONG
Definition: retypes.h:1
static int priority
Definition: timer.c:163
uint64_t offset
Definition: btrfs.h:348
ExFreePool(ed)
static void remove_fcb_extent(fcb *fcb, extent *ext, LIST_ENTRY *rollback)
Definition: write.c:2763
#define uint32_t
Definition: nsiface.idl:61
return STATUS_SUCCESS
Definition: btrfs.c:2938
EXTENT_DATA * ed
Definition: write.c:2818
struct _device_extension * Vcb
Definition: btrfs_drv.h:283

Referenced by do_write_file().

◆ excise_extents()

NTSTATUS excise_extents ( device_extension Vcb,
fcb fcb,
uint64_t  start_data,
uint64_t  end_data,
PIRP  Irp,
LIST_ENTRY rollback 
)

Definition at line 2368 of file write.c.

2368  {
2369  NTSTATUS Status;
2370  LIST_ENTRY* le;
2371 
2372  le = fcb->extents.Flink;
2373 
2374  while (le != &fcb->extents) {
2375  LIST_ENTRY* le2 = le->Flink;
2377  EXTENT_DATA* ed = &ext->extent_data;
2378  EXTENT_DATA2* ed2 = NULL;
2379  uint64_t len;
2380 
2381  if (!ext->ignore) {
2382  if (ed->type != EXTENT_TYPE_INLINE)
2383  ed2 = (EXTENT_DATA2*)ed->data;
2384 
2386 
2387  if (ext->offset < end_data && ext->offset + len > start_data) {
2388  if (ed->type == EXTENT_TYPE_INLINE) {
2389  if (start_data <= ext->offset && end_data >= ext->offset + len) { // remove all
2391 
2393  fcb->inode_item_changed = true;
2394  } else {
2395  ERR("trying to split inline extent\n");
2396 #ifdef DEBUG_PARANOID
2397  int3;
2398 #endif
2399  return STATUS_INTERNAL_ERROR;
2400  }
2401  } else if (ed->type != EXTENT_TYPE_INLINE) {
2402  if (start_data <= ext->offset && end_data >= ext->offset + len) { // remove all
2403  if (ed2->size != 0) {
2404  chunk* c;
2405 
2407  fcb->inode_item_changed = true;
2408 
2410 
2411  if (!c) {
2412  ERR("get_chunk_from_address(%I64x) failed\n", ed2->address);
2413  } else {
2414  Status = update_changed_extent_ref(Vcb, c, ed2->address, ed2->size, fcb->subvol->id, fcb->inode, ext->offset - ed2->offset, -1,
2416  if (!NT_SUCCESS(Status)) {
2417  ERR("update_changed_extent_ref returned %08x\n", Status);
2418  goto end;
2419  }
2420  }
2421  }
2422 
2424  } else if (start_data <= ext->offset && end_data < ext->offset + len) { // remove beginning
2425  EXTENT_DATA2* ned2;
2426  extent* newext;
2427 
2428  if (ed2->size != 0) {
2429  fcb->inode_item.st_blocks -= end_data - ext->offset;
2430  fcb->inode_item_changed = true;
2431  }
2432 
2433  newext = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2), ALLOC_TAG);
2434  if (!newext) {
2435  ERR("out of memory\n");
2437  goto end;
2438  }
2439 
2440  ned2 = (EXTENT_DATA2*)newext->extent_data.data;
2441 
2442  newext->extent_data.generation = Vcb->superblock.generation;
2445  newext->extent_data.encryption = ed->encryption;
2446  newext->extent_data.encoding = ed->encoding;
2447  newext->extent_data.type = ed->type;
2448  ned2->address = ed2->address;
2449  ned2->size = ed2->size;
2450  ned2->offset = ed2->offset + (end_data - ext->offset);
2451  ned2->num_bytes = ed2->num_bytes - (end_data - ext->offset);
2452 
2453  newext->offset = end_data;
2454  newext->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
2455  newext->unique = ext->unique;
2456  newext->ignore = false;
2457  newext->inserted = true;
2458 
2459  if (ext->csum) {
2461  newext->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ned2->num_bytes * sizeof(uint32_t) / Vcb->superblock.sector_size), ALLOC_TAG);
2462  if (!newext->csum) {
2463  ERR("out of memory\n");
2465  ExFreePool(newext);
2466  goto end;
2467  }
2468 
2469  RtlCopyMemory(newext->csum, &ext->csum[(end_data - ext->offset) / Vcb->superblock.sector_size],
2470  (ULONG)(ned2->num_bytes * sizeof(uint32_t) / Vcb->superblock.sector_size));
2471  } else {
2472  newext->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2->size * sizeof(uint32_t) / Vcb->superblock.sector_size), ALLOC_TAG);
2473  if (!newext->csum) {
2474  ERR("out of memory\n");
2476  ExFreePool(newext);
2477  goto end;
2478  }
2479 
2480  RtlCopyMemory(newext->csum, ext->csum, (ULONG)(ed2->size * sizeof(uint32_t) / Vcb->superblock.sector_size));
2481  }
2482  } else
2483  newext->csum = NULL;
2484 
2485  add_extent(fcb, &ext->list_entry, newext);
2486 
2488  } else if (start_data > ext->offset && end_data >= ext->offset + len) { // remove end
2489  EXTENT_DATA2* ned2;
2490  extent* newext;
2491 
2492  if (ed2->size != 0) {
2493  fcb->inode_item.st_blocks -= ext->offset + len - start_data;
2494  fcb->inode_item_changed = true;
2495  }
2496 
2497  newext = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2), ALLOC_TAG);
2498  if (!newext) {
2499  ERR("out of memory\n");
2501  goto end;
2502  }
2503 
2504  ned2 = (EXTENT_DATA2*)newext->extent_data.data;
2505 
2506  newext->extent_data.generation = Vcb->superblock.generation;
2509  newext->extent_data.encryption = ed->encryption;
2510  newext->extent_data.encoding = ed->encoding;
2511  newext->extent_data.type = ed->type;
2512  ned2->address = ed2->address;
2513  ned2->size = ed2->size;
2514  ned2->offset = ed2->offset;
2515  ned2->num_bytes = start_data - ext->offset;
2516 
2517  newext->offset = ext->offset;
2518  newext->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
2519  newext->unique = ext->unique;
2520  newext->ignore = false;
2521  newext->inserted = true;
2522 
2523  if (ext->csum) {
2525  newext->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ned2->num_bytes * sizeof(uint32_t) / Vcb->superblock.sector_size), ALLOC_TAG);
2526  if (!newext->csum) {
2527  ERR("out of memory\n");
2529  ExFreePool(newext);
2530  goto end;
2531  }
2532 
2533  RtlCopyMemory(newext->csum, ext->csum, (ULONG)(ned2->num_bytes * sizeof(uint32_t) / Vcb->superblock.sector_size));
2534  } else {
2535  newext->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2->size * sizeof(uint32_t) / Vcb->superblock.sector_size), ALLOC_TAG);
2536  if (!newext->csum) {
2537  ERR("out of memory\n");
2539  ExFreePool(newext);
2540  goto end;
2541  }
2542 
2543  RtlCopyMemory(newext->csum, ext->csum, (ULONG)(ed2->size * sizeof(uint32_t) / Vcb->superblock.sector_size));
2544  }
2545  } else
2546  newext->csum = NULL;
2547 
2548  InsertHeadList(&ext->list_entry, &newext->list_entry);
2549 
2551  } else if (start_data > ext->offset && end_data < ext->offset + len) { // remove middle
2552  EXTENT_DATA2 *neda2, *nedb2;
2553  extent *newext1, *newext2;
2554 
2555  if (ed2->size != 0) {
2556  chunk* c;
2557 
2558  fcb->inode_item.st_blocks -= end_data - start_data;
2559  fcb->inode_item_changed = true;
2560 
2562 
2563  if (!c) {
2564  ERR("get_chunk_from_address(%I64x) failed\n", ed2->address);
2565  } else {
2568  if (!NT_SUCCESS(Status)) {
2569  ERR("update_changed_extent_ref returned %08x\n", Status);
2570  goto end;
2571  }
2572  }
2573  }
2574 
2575  newext1 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2), ALLOC_TAG);
2576  if (!newext1) {
2577  ERR("out of memory\n");
2579  goto end;
2580  }
2581 
2582  newext2 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2), ALLOC_TAG);
2583  if (!newext2) {
2584  ERR("out of memory\n");
2586  ExFreePool(newext1);
2587  goto end;
2588  }
2589 
2590  neda2 = (EXTENT_DATA2*)newext1->extent_data.data;
2591 
2592  newext1->extent_data.generation = Vcb->superblock.generation;
2594  newext1->extent_data.compression = ed->compression;
2595  newext1->extent_data.encryption = ed->encryption;
2596  newext1->extent_data.encoding = ed->encoding;
2597  newext1->extent_data.type = ed->type;
2598  neda2->address = ed2->address;
2599  neda2->size = ed2->size;
2600  neda2->offset = ed2->offset;
2601  neda2->num_bytes = start_data - ext->offset;
2602 
2603  nedb2 = (EXTENT_DATA2*)newext2->extent_data.data;
2604 
2605  newext2->extent_data.generation = Vcb->superblock.generation;
2607  newext2->extent_data.compression = ed->compression;
2608  newext2->extent_data.encryption = ed->encryption;
2609  newext2->extent_data.encoding = ed->encoding;
2610  newext2->extent_data.type = ed->type;
2611  nedb2->address = ed2->address;
2612  nedb2->size = ed2->size;
2613  nedb2->offset = ed2->offset + (end_data - ext->offset);
2614  nedb2->num_bytes = ext->offset + len - end_data;
2615 
2616  newext1->offset = ext->offset;
2617  newext1->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
2618  newext1->unique = ext->unique;
2619  newext1->ignore = false;
2620  newext1->inserted = true;
2621 
2622  newext2->offset = end_data;
2623  newext2->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
2624  newext2->unique = ext->unique;
2625  newext2->ignore = false;
2626  newext2->inserted = true;
2627 
2628  if (ext->csum) {
2630  newext1->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(neda2->num_bytes * sizeof(uint32_t) / Vcb->superblock.sector_size), ALLOC_TAG);
2631  if (!newext1->csum) {
2632  ERR("out of memory\n");
2634  ExFreePool(newext1);
2635  ExFreePool(newext2);
2636  goto end;
2637  }
2638 
2639  newext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(nedb2->num_bytes * sizeof(uint32_t) / Vcb->superblock.sector_size), ALLOC_TAG);
2640  if (!newext2->csum) {
2641  ERR("out of memory\n");
2643  ExFreePool(newext1->csum);
2644  ExFreePool(newext1);
2645  ExFreePool(newext2);
2646  goto end;
2647  }
2648 
2649  RtlCopyMemory(newext1->csum, ext->csum, (ULONG)(neda2->num_bytes * sizeof(uint32_t) / Vcb->superblock.sector_size));
2650  RtlCopyMemory(newext2->csum, &ext->csum[(end_data - ext->offset) / Vcb->superblock.sector_size],
2651  (ULONG)(nedb2->num_bytes * sizeof(uint32_t) / Vcb->superblock.sector_size));
2652  } else {
2653  newext1->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2->size * sizeof(uint32_t) / Vcb->superblock.sector_size), ALLOC_TAG);
2654  if (!newext1->csum) {
2655  ERR("out of memory\n");
2657  ExFreePool(newext1);
2658  ExFreePool(newext2);
2659  goto end;
2660  }
2661 
2662  newext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2->size * sizeof(uint32_t) / Vcb->superblock.sector_size), ALLOC_TAG);
2663  if (!newext2->csum) {
2664  ERR("out of memory\n");
2666  ExFreePool(newext1->csum);
2667  ExFreePool(newext1);
2668  ExFreePool(newext2);
2669  goto end;
2670  }
2671 
2672  RtlCopyMemory(newext1->csum, ext->csum, (ULONG)(ed2->size * sizeof(uint32_t) / Vcb->superblock.sector_size));
2673  RtlCopyMemory(newext2->csum, ext->csum, (ULONG)(ed2->size * sizeof(uint32_t) / Vcb->superblock.sector_size));
2674  }
2675  } else {
2676  newext1->csum = NULL;
2677  newext2->csum = NULL;
2678  }
2679 
2680  InsertHeadList(&ext->list_entry, &newext1->list_entry);
2681  add_extent(fcb, &newext1->list_entry, newext2);
2682 
2684  }
2685  }
2686  }
2687  }
2688 
2689  le = le2;
2690  }
2691 
2693 
2694 end:
2695  fcb->extents_changed = true;
2697 
2698  return Status;
2699 }
void add_extent(_In_ fcb *fcb, _In_ LIST_ENTRY *prevextle, _In_ __drv_aliasesMem extent *newext)
Definition: write.c:2351
uint64_t generation
Definition: btrfs.h:336
uint8_t type
Definition: btrfs.h:341
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS update_changed_extent_ref(device_extension *Vcb, chunk *c, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, int32_t count, bool no_csum, bool superseded, PIRP Irp)
Definition: extent-tree.c:1950
NTSTATUS Status
Definition: write.c:2817
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:61
EXTENT_DATA2 * ed2
Definition: write.c:2819
_In_ PIRP Irp
Definition: csq.h:116
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
uint64_t decoded_size
Definition: btrfs.h:337
LONG NTSTATUS
Definition: precomp.h:26
#define int3
Definition: btrfs_drv.h:1722
GLintptr offset
Definition: glext.h:5920
LIST_ENTRY list_entry
Definition: btrfs_drv.h:231
uint16_t datalen
Definition: btrfs_drv.h:225
GLuint GLuint end
Definition: gl.h:1545
uint8_t encryption
Definition: btrfs.h:339
bool ignore
Definition: btrfs_drv.h:227
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:91
bool inserted
Definition: btrfs_drv.h:228
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:70
uint64_t address
Definition: btrfs.h:346
uint64_t offset
Definition: btrfs_drv.h:224
bool extents_changed
Definition: btrfs_drv.h:319
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
uint64_t size
Definition: btrfs.h:347
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
bool unique
Definition: btrfs_drv.h:226
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
uint16_t encoding
Definition: btrfs.h:340
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t inode
Definition: btrfs_drv.h:285
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2814
LIST_ENTRY extents
Definition: btrfs_drv.h:296
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
_In_ fcb _In_ chunk _In_ uint64_t start_data
Definition: write.c:2814
GLenum GLsizei len
Definition: glext.h:6722
Definition: typedefs.h:117
INODE_ITEM inode_item
Definition: btrfs_drv.h:288
uint64_t num_bytes
Definition: btrfs.h:349
uint64_t st_blocks
Definition: btrfs.h:273
uint64_t flags
Definition: btrfs.h:280
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
uint8_t data[1]
Definition: btrfs.h:342
uint32_t * csum
Definition: btrfs_drv.h:229
UINT64 uint64_t
Definition: types.h:77
chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address)
Definition: write.c:89
struct _root * subvol
Definition: btrfs_drv.h:284
Definition: list.h:27
mark_fcb_dirty(fcb)
UINT32 uint32_t
Definition: types.h:75
EXTENT_DATA extent_data
Definition: btrfs_drv.h:233
if(!find_data_address_in_chunk(Vcb, c, length, &address)) return false
unsigned int ULONG
Definition: retypes.h:1
uint64_t offset
Definition: btrfs.h:348
ExFreePool(ed)
static void remove_fcb_extent(fcb *fcb, extent *ext, LIST_ENTRY *rollback)
Definition: write.c:2763
return STATUS_SUCCESS
Definition: btrfs.c:2938
_In_ fcb _In_ chunk * c
Definition: write.c:2814
EXTENT_DATA * ed
Definition: write.c:2818
bool inode_item_changed
Definition: btrfs_drv.h:302
uint8_t compression
Definition: btrfs.h:338

Referenced by allocate_cache_chunk(), check_for_orphans_root(), delete_fileref_fcb(), do_write_file(), drop_chunk(), duplicate_extents(), extend_file(), load_stored_free_space_cache(), lzo_write_compressed_bit(), remove_free_space_inode(), rename_file_to_stream(), set_zero_data(), truncate_file(), write_file2(), zero_data(), zlib_write_compressed_bit(), and zstd_write_compressed_bit().

◆ ExFreePool()

◆ extend_file()

NTSTATUS extend_file ( fcb fcb,
file_ref fileref,
uint64_t  end,
bool  prealloc,
PIRP  Irp,
LIST_ENTRY rollback 
)

Definition at line 3319 of file write.c.

3319  {
3320  uint64_t oldalloc, newalloc;
3321  bool cur_inline;
3322  NTSTATUS Status;
3323 
3324  TRACE("(%p, %p, %x, %u)\n", fcb, fileref, end, prealloc);
3325 
3326  if (fcb->ads) {
3327  if (end > 0xffff)
3328  return STATUS_DISK_FULL;
3329 
3330  return stream_set_end_of_file_information(fcb->Vcb, (uint16_t)end, fcb, fileref, false);
3331  } else {
3332  extent* ext = NULL;
3333  LIST_ENTRY* le;
3334 
3335  le = fcb->extents.Blink;
3336  while (le != &fcb->extents) {
3338 
3339  if (!ext2->ignore) {
3340  ext = ext2;
3341  break;
3342  }
3343 
3344  le = le->Blink;
3345  }
3346 
3347  oldalloc = 0;
3348  if (ext) {
3349  EXTENT_DATA* ed = &ext->extent_data;
3351 
3352  oldalloc = ext->offset + (ed->type == EXTENT_TYPE_INLINE ? ed->decoded_size : ed2->num_bytes);
3353  cur_inline = ed->type == EXTENT_TYPE_INLINE;
3354 
3355  if (cur_inline && end > fcb->Vcb->options.max_inline) {
3356  uint64_t origlength, length;
3357  uint8_t* data;
3358 
3359  TRACE("giving inline file proper extents\n");
3360 
3361  origlength = ed->decoded_size;
3362 
3363  cur_inline = false;
3364 
3365  length = sector_align(origlength, fcb->Vcb->superblock.sector_size);
3366 
3368  if (!data) {
3369  ERR("could not allocate %I64x bytes for data\n", length);
3371  }
3372 
3373  Status = read_file(fcb, data, 0, origlength, NULL, Irp);
3374  if (!NT_SUCCESS(Status)) {
3375  ERR("read_file returned %08x\n", Status);
3376  ExFreePool(data);
3377  return Status;
3378  }
3379 
3380  RtlZeroMemory(data + origlength, (ULONG)(length - origlength));
3381 
3383  if (!NT_SUCCESS(Status)) {
3384  ERR("excise_extents returned %08x\n", Status);
3385  ExFreePool(data);
3386  return Status;
3387  }
3388 
3389  Status = do_write_file(fcb, 0, length, data, Irp, false, 0, rollback);
3390  if (!NT_SUCCESS(Status)) {
3391  ERR("do_write_file returned %08x\n", Status);
3392  ExFreePool(data);
3393  return Status;
3394  }
3395 
3396  oldalloc = ext->offset + length;
3397 
3398  ExFreePool(data);
3399  }
3400 
3401  if (cur_inline) {
3402  uint16_t edsize;
3403 
3404  if (end > oldalloc) {
3405  edsize = (uint16_t)(offsetof(EXTENT_DATA, data[0]) + end - ext->offset);
3407 
3408  if (!ed) {
3409  ERR("out of memory\n");
3411  }
3412 
3413  ed->generation = fcb->Vcb->superblock.generation;
3414  ed->decoded_size = end - ext->offset;
3419 
3420  Status = read_file(fcb, ed->data, ext->offset, oldalloc, NULL, Irp);
3421  if (!NT_SUCCESS(Status)) {
3422  ERR("read_file returned %08x\n", Status);
3423  ExFreePool(ed);
3424  return Status;
3425  }
3426 
3427  RtlZeroMemory(ed->data + oldalloc - ext->offset, (ULONG)(end - oldalloc));
3428 
3430 
3431  Status = add_extent_to_fcb(fcb, ext->offset, ed, edsize, ext->unique, NULL, rollback);
3432  if (!NT_SUCCESS(Status)) {
3433  ERR("add_extent_to_fcb returned %08x\n", Status);
3434  ExFreePool(ed);
3435  return Status;
3436  }
3437 
3438  ExFreePool(ed);
3439 
3440  fcb->extents_changed = true;
3442  }
3443 
3444  TRACE("extending inline file (oldalloc = %I64x, end = %I64x)\n", oldalloc, end);
3445 
3447  TRACE("setting st_size to %I64x\n", end);
3448 
3450 
3451  fcb->Header.AllocationSize.QuadPart = fcb->Header.FileSize.QuadPart = fcb->Header.ValidDataLength.QuadPart = end;
3452  } else {
3453  newalloc = sector_align(end, fcb->Vcb->superblock.sector_size);
3454 
3455  if (newalloc > oldalloc) {
3456  if (prealloc) {
3457  // FIXME - try and extend previous extent first
3458 
3459  Status = insert_prealloc_extent(fcb, oldalloc, newalloc - oldalloc, rollback);
3460 
3461  if (!NT_SUCCESS(Status)) {
3462  ERR("insert_prealloc_extent returned %08x\n", Status);
3463  return Status;
3464  }
3465  }
3466 
3467  fcb->extents_changed = true;
3468  }
3469 
3471  fcb->inode_item_changed = true;
3473 
3474  TRACE("setting st_size to %I64x\n", end);
3475 
3476  TRACE("newalloc = %I64x\n", newalloc);
3477 
3478  fcb->Header.AllocationSize.QuadPart = newalloc;
3479  fcb->Header.FileSize.QuadPart = fcb->Header.ValidDataLength.QuadPart = end;
3480  }
3481  } else {
3482  if (end > fcb->Vcb->options.max_inline) {
3483  newalloc = sector_align(end, fcb->Vcb->superblock.sector_size);
3484 
3485  if (prealloc) {
3486  Status = insert_prealloc_extent(fcb, 0, newalloc, rollback);
3487 
3488  if (!NT_SUCCESS(Status)) {
3489  ERR("insert_prealloc_extent returned %08x\n", Status);
3490  return Status;
3491  }
3492  }
3493 
3494  fcb->extents_changed = true;
3495  fcb->inode_item_changed = true;
3497 
3499  TRACE("setting st_size to %I64x\n", end);
3500 
3501  TRACE("newalloc = %I64x\n", newalloc);
3502 
3503  fcb->Header.AllocationSize.QuadPart = newalloc;
3504  fcb->Header.FileSize.QuadPart = fcb->Header.ValidDataLength.QuadPart = end;
3505  } else {
3506  EXTENT_DATA* ed;
3507  uint16_t edsize;
3508 
3511 
3512  if (!ed) {
3513  ERR("out of memory\n");
3515  }
3516 
3517  ed->generation = fcb->Vcb->superblock.generation;
3518  ed->decoded_size = end;
3523 
3525 
3526  Status = add_extent_to_fcb(fcb, 0, ed, edsize, false, NULL, rollback);
3527  if (!NT_SUCCESS(Status)) {
3528  ERR("add_extent_to_fcb returned %08x\n", Status);
3529  ExFreePool(ed);
3530  return Status;
3531  }
3532 
3533  ExFreePool(ed);
3534 
3535  fcb->extents_changed = true;
3536  fcb->inode_item_changed = true;
3538 
3540  TRACE("setting st_size to %I64x\n", end);
3541 
3543 
3544  fcb->Header.AllocationSize.QuadPart = fcb->Header.FileSize.QuadPart = fcb->Header.ValidDataLength.QuadPart = end;
3545  }
3546  }
3547  }
3548 
3549  return STATUS_SUCCESS;
3550 }
uint64_t generation
Definition: btrfs.h:336
uint8_t type
Definition: btrfs.h:341
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t length
Definition: write.c:2814
static NTSTATUS insert_prealloc_extent(fcb *fcb, uint64_t start, uint64_t length, LIST_ENTRY *rollback)
Definition: write.c:3052
NTSTATUS Status
Definition: write.c:2817
NTSTATUS do_write_file(fcb *fcb, uint64_t start, uint64_t end_data, void *data, PIRP Irp, bool file_write, uint32_t irp_offset, LIST_ENTRY *rollback)
Definition: write.c:3939
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:61
EXTENT_DATA2 * ed2
Definition: write.c:2819
_In_ PIRP Irp
Definition: csq.h:116
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
uint64_t decoded_size
Definition: btrfs.h:337
LONG NTSTATUS
Definition: precomp.h:26
GLuint GLuint end
Definition: gl.h:1545
unsigned short int uint16_t
Definition: acefiex.h:54
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp)
Definition: read.c:2715
#define uint16_t
Definition: nsiface.idl:60
uint8_t encryption
Definition: btrfs.h:339
#define ALLOC_TAG
Definition: btrfs_drv.h:91
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:70
bool extents_changed
Definition: btrfs_drv.h:319
#define BTRFS_ENCODING_NONE
Definition: btrfs.h:68
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
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
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:279
uint16_t encoding
Definition: btrfs.h:340
#define BTRFS_ENCRYPTION_NONE
Definition: btrfs.h:66
uint64_t st_size
Definition: btrfs.h:272
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2814
LIST_ENTRY extents
Definition: btrfs_drv.h:296
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
static const BYTE ext2[]
Definition: encode.c:2699
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void * data
Definition: write.c:2814
Definition: typedefs.h:117
INODE_ITEM inode_item
Definition: btrfs_drv.h:288
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t num_bytes
Definition: btrfs.h:349
uint64_t st_blocks
Definition: btrfs.h:273
uint16_t edsize
Definition: write.c:2820
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool prealloc
Definition: write.c:2814
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
uint8_t data[1]
Definition: btrfs.h:342
UINT64 uint64_t
Definition: types.h:77
Definition: list.h:27
NTSTATUS stream_set_end_of_file_information(device_extension *Vcb, uint16_t end, fcb *fcb, file_ref *fileref, bool advance_only)
Definition: fileinfo.c:3107
mark_fcb_dirty(fcb)
NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback)
Definition: write.c:2368
bool ads
Definition: btrfs_drv.h:326
NTSTATUS add_extent_to_fcb(_In_ fcb *fcb, _In_ uint64_t offset, _In_reads_bytes_(edsize) EXTENT_DATA *ed, _In_ uint16_t edsize, _In_ bool unique, _In_opt_ _When_(return >=0, __drv_aliasesMem) uint32_t *csum, _In_ LIST_ENTRY *rollback)
Definition: write.c:2720
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
ExFreePool(ed)
static void remove_fcb_extent(fcb *fcb, extent *ext, LIST_ENTRY *rollback)
Definition: write.c:2763
return STATUS_SUCCESS
Definition: btrfs.c:2938
EXTENT_DATA * ed
Definition: write.c:2818
bool inode_item_changed
Definition: btrfs_drv.h:302
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
struct _device_extension * Vcb
Definition: btrfs_drv.h:283
uint8_t compression
Definition: btrfs.h:338
TRACE("(%p, (%I64x, %I64x), %I64x, %I64x, %I64x, %u, %p, %p)\n", Vcb, fcb->subvol->id, fcb->inode, c->offset, start_data, length, prealloc, data, rollback)

Referenced by file_create2(), open_file2(), set_end_of_file_information(), and write_file2().

◆ find_new_chunk_address()

static uint64_t find_new_chunk_address ( device_extension Vcb,
uint64_t  size 
)
static

Definition at line 116 of file write.c.

116  {
117  uint64_t lastaddr;
118  LIST_ENTRY* le;
119 
120  lastaddr = 0xc00000;
121 
122  le = Vcb->chunks.Flink;
123  while (le != &Vcb->chunks) {
125 
126  if (c->offset >= lastaddr + size)
127  return lastaddr;
128 
129  lastaddr = c->offset + c->chunk_item->size;
130 
131  le = le->Flink;
132  }
133 
134  return lastaddr;
135 }
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
GLsizeiptr size
Definition: glext.h:5919
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
Definition: typedefs.h:117
UINT64 uint64_t
Definition: types.h:77
Definition: list.h:27

Referenced by alloc_chunk().

◆ find_new_dup_stripes()

static bool find_new_dup_stripes ( device_extension Vcb,
stripe stripes,
uint64_t  max_stripe_size,
bool  full_size 
)
static

Definition at line 137 of file write.c.

137  {
138  uint64_t devusage = 0xffffffffffffffff;
139  space *devdh1 = NULL, *devdh2 = NULL;
140  LIST_ENTRY* le;
141  device* dev2 = NULL;
142 
143  le = Vcb->devices.Flink;
144 
145  while (le != &Vcb->devices) {
147 
148  if (!dev->readonly && !dev->reloc && dev->devobj) {
149  uint64_t usage = (dev->devitem.bytes_used * 4096) / dev->devitem.num_bytes;
150 
151  // favour devices which have been used the least
152  if (usage < devusage) {
153  if (!IsListEmpty(&dev->space)) {
154  LIST_ENTRY* le2;
155  space *dh1 = NULL, *dh2 = NULL;
156 
157  le2 = dev->space.Flink;
158  while (le2 != &dev->space) {
160 
161  if (dh->size >= max_stripe_size && (!dh1 || !dh2 || dh->size < dh1->size)) {
162  dh2 = dh1;
163  dh1 = dh;
164  }
165 
166  le2 = le2->Flink;
167  }
168 
169  if (dh1 && (dh2 || dh1->size >= 2 * max_stripe_size)) {
170  dev2 = dev;
171  devusage = usage;
172  devdh1 = dh1;
173  devdh2 = dh2 ? dh2 : dh1;
174  }
175  }
176  }
177  }
178 
179  le = le->Flink;
180  }
181 
182  if (!devdh1) {
183  uint64_t size = 0;
184 
185  // Can't find hole of at least max_stripe_size; look for the largest one we can find
186 
187  if (full_size)
188  return false;
189 
190  le = Vcb->devices.Flink;
191  while (le != &Vcb->devices) {
193 
194  if (!dev->readonly && !dev->reloc) {
195  if (!IsListEmpty(&dev->space)) {
196  LIST_ENTRY* le2;
197  space *dh1 = NULL, *dh2 = NULL;
198 
199  le2 = dev->space.Flink;
200  while (le2 != &dev->space) {
202 
203  if (!dh1 || !dh2 || dh->size < dh1->size) {
204  dh2 = dh1;
205  dh1 = dh;
206  }
207 
208  le2 = le2->Flink;
209  }
210 
211  if (dh1) {
212  uint64_t devsize;
213 
214  if (dh2)
215  devsize = max(dh1->size / 2, min(dh1->size, dh2->size));
216  else
217  devsize = dh1->size / 2;
218 
219  if (devsize > size) {
220  dev2 = dev;
221  devdh1 = dh1;
222 
223  if (dh2 && min(dh1->size, dh2->size) > dh1->size / 2)
224  devdh2 = dh2;
225  else
226  devdh2 = dh1;
227 
228  size = devsize;
229  }
230  }
231  }
232  }
233 
234  le = le->Flink;
235  }
236 
237  if (!devdh1)
238  return false;
239  }
240 
241  stripes[0].device = stripes[1].device = dev2;
242  stripes[0].dh = devdh1;
243  stripes[1].dh = devdh2;
244 
245  return true;
246 }
#define max(a, b)
Definition: svc.c:63
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
static int dev
Definition: mkdosfs.c:536
Definition: devices.h:37
smooth NULL
Definition: ftsmooth.c:416
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
GLsizeiptr size
Definition: glext.h:5919
#define Vcb
Definition: cdprocs.h:1425
GLsizeiptr const GLvoid GLenum usage
Definition: glext.h:5919
Definition: typedefs.h:117
device * device
Definition: write.c:113
uint64_t size
Definition: btrfs_drv.h:512
UINT64 uint64_t
Definition: types.h:77
space * dh
Definition: write.c:112
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
if(!find_data_address_in_chunk(Vcb, c, length, &address)) return false

Referenced by alloc_chunk().

◆ find_new_stripe()

static bool find_new_stripe ( device_extension Vcb,
stripe stripes,
uint16_t  i,
uint64_t  max_stripe_size,
bool  allow_missing,
bool  full_size 
)
static

Definition at line 248 of file write.c.

248  {
249  uint64_t k, devusage = 0xffffffffffffffff;
250  space* devdh = NULL;
251  LIST_ENTRY* le;
252  device* dev2 = NULL;
253 
254  le = Vcb->devices.Flink;
255  while (le != &Vcb->devices) {
257  uint64_t usage;
258  bool skip = false;
259 
260  if (dev->readonly || dev->reloc || (!dev->devobj && !allow_missing)) {
261  le = le->Flink;
262  continue;
263  }
264 
265  // skip this device if it already has a stripe
266  if (i > 0) {
267  for (k = 0; k < i; k++) {
268  if (stripes[k].device == dev) {
269  skip = true;
270  break;
271  }
272  }
273  }
274 
275  if (!skip) {
276  usage = (dev->devitem.bytes_used * 4096) / dev->devitem.num_bytes;
277 
278  // favour devices which have been used the least
279  if (usage < devusage) {
280  if (!IsListEmpty(&dev->space)) {
281  LIST_ENTRY* le2;
282 
283  le2 = dev->space.Flink;
284  while (le2 != &dev->space) {
286 
287  if ((dev2 != dev && dh->size >= max_stripe_size) ||
288  (dev2 == dev && dh->size >= max_stripe_size && dh->size < devdh->size)
289  ) {
290  devdh = dh;
291  dev2 = dev;
292  devusage = usage;
293  }
294 
295  le2 = le2->Flink;
296  }
297  }
298  }
299  }
300 
301  le = le->Flink;
302  }
303 
304  if (!devdh) {
305  // Can't find hole of at least max_stripe_size; look for the largest one we can find
306 
307  if (full_size)
308  return false;
309 
310  le = Vcb->devices.Flink;
311  while (le != &Vcb->devices) {
313  bool skip = false;
314 
315  if (dev->readonly || dev->reloc || (!dev->devobj && !allow_missing)) {
316  le = le->Flink;
317  continue;
318  }
319 
320  // skip this device if it already has a stripe
321  if (i > 0) {
322  for (k = 0; k < i; k++) {
323  if (stripes[k].device == dev) {
324  skip = true;
325  break;
326  }
327  }
328  }
329 
330  if (!skip) {
331  if (!IsListEmpty(&dev->space)) {
332  LIST_ENTRY* le2;
333 
334  le2 = dev->space.Flink;
335  while (le2 != &dev->space) {
337 
338  if (!devdh || devdh->size < dh->size) {
339  devdh = dh;
340  dev2 = dev;
341  }
342 
343  le2 = le2->Flink;
344  }
345  }
346  }
347 
348  le = le->Flink;
349  }
350 
351  if (!devdh)
352  return false;
353  }
354 
355  stripes[i].dh = devdh;
356  stripes[i].device = dev2;
357 
358  return true;
359 }
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
static int dev
Definition: mkdosfs.c:536
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
Definition: devices.h:37
smooth NULL
Definition: ftsmooth.c:416
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define Vcb
Definition: cdprocs.h:1425
GLsizeiptr const GLvoid GLenum usage
Definition: glext.h:5919
Definition: typedefs.h:117
device * device
Definition: write.c:113
uint64_t size
Definition: btrfs_drv.h:512
UINT64 uint64_t
Definition: types.h:77
space * dh
Definition: write.c:112
Definition: list.h:27
#define skip(...)
Definition: atltest.h:64
if(!find_data_address_in_chunk(Vcb, c, length, &address)) return false
int k
Definition: mpi.c:3369

Referenced by alloc_chunk().

◆ free_write_data_stripes()

void free_write_data_stripes ( write_data_context wtc)

Definition at line 2291 of file write.c.

2291  {
2292  LIST_ENTRY* le;
2293  PMDL last_mdl = NULL;
2294 
2295  if (wtc->parity1_mdl) {
2296  if (wtc->parity1_mdl->MdlFlags & MDL_PAGES_LOCKED)
2297  MmUnlockPages(wtc->parity1_mdl);
2298 
2299  IoFreeMdl(wtc->parity1_mdl);
2300  }
2301 
2302  if (wtc->parity2_mdl) {
2303  if (wtc->parity2_mdl->MdlFlags & MDL_PAGES_LOCKED)
2304  MmUnlockPages(wtc->parity2_mdl);
2305 
2306  IoFreeMdl(wtc->parity2_mdl);
2307  }
2308 
2309  if (wtc->mdl) {
2310  if (wtc->mdl->MdlFlags & MDL_PAGES_LOCKED)
2311  MmUnlockPages(wtc->mdl);
2312 
2313  IoFreeMdl(wtc->mdl);
2314  }
2315 
2316  if (wtc->parity1)
2317  ExFreePool(wtc->parity1);
2318 
2319  if (wtc->parity2)
2320  ExFreePool(wtc->parity2);
2321 
2322  if (wtc->scratch)
2323  ExFreePool(wtc->scratch);
2324 
2325  le = wtc->stripes.Flink;
2326  while (le != &wtc->stripes) {
2328 
2329  if (stripe->mdl && stripe->mdl != last_mdl) {
2330  if (stripe->mdl->MdlFlags & MDL_PAGES_LOCKED)
2331  MmUnlockPages(stripe->mdl);
2332 
2333  IoFreeMdl(stripe->mdl);
2334  }
2335 
2336  last_mdl = stripe->mdl;
2337 
2338  if (stripe->Irp)
2339  IoFreeIrp(stripe->Irp);
2340 
2341  le = le->Flink;
2342  }
2343 
2344  while (!IsListEmpty(&wtc->stripes)) {
2346 
2347  ExFreePool(stripe);
2348  }
2349 }
Definition: write.c:111
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1439
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
uint8_t * scratch
Definition: btrfs_drv.h:916
smooth NULL
Definition: ftsmooth.c:416
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19
uint8_t * parity1
Definition: btrfs_drv.h:916
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
Definition: typedefs.h:117
Definition: list.h:27
LIST_ENTRY stripes
Definition: btrfs_drv.h:913
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
ExFreePool(ed)
uint8_t * parity2
Definition: btrfs_drv.h:916

Referenced by do_tree_writes(), snapshot_tree_copy(), write_data(), and write_data_complete().

◆ get_chunk_from_address()

chunk* get_chunk_from_address ( device_extension Vcb,
uint64_t  address 
)

Definition at line 89 of file write.c.

89  {
90  LIST_ENTRY* le2;
91 
92  ExAcquireResourceSharedLite(&Vcb->chunk_lock, true);
93 
94  le2 = Vcb->chunks.Flink;
95  while (le2 != &Vcb->chunks) {
97 
98  if (address >= c->offset && address < c->offset + c->chunk_item->size) {
99  ExReleaseResourceLite(&Vcb->chunk_lock);
100  return c;
101  }
102 
103  le2 = le2->Flink;
104  }
105 
106  ExReleaseResourceLite(&Vcb->chunk_lock);
107 
108  return NULL;
109 }
GLintptr offset
Definition: glext.h:5920
smooth NULL
Definition: ftsmooth.c:416
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
GLuint address
Definition: glext.h:9393
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
Definition: typedefs.h:117
Definition: list.h:27
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
_In_ fcb _In_ chunk * c
Definition: write.c:2814

Referenced by add_data_reloc(), add_metadata_reloc(), add_metadata_reloc_extent_item(), allocate_cache_chunk(), allocate_tree_extents(), do_rollback(), do_tree_writes(), do_write_file(), do_write_file_prealloc(), duplicate_extents(), excise_extents(), flush_fcb(), get_tree_new_address(), move_across_subvols(), rationalize_extents(), read_data(), read_file(), reduce_tree_extent(), snapshot_tree_copy(), try_extend_data(), update_tree_extents(), write_data(), and write_data_complete().

◆ get_raid56_lock_range()

void get_raid56_lock_range ( chunk c,
uint64_t  address,
uint64_t  length,
uint64_t lockaddr,
uint64_t locklen 
)

Definition at line 2150 of file write.c.

2150  {
2151  uint64_t startoff, endoff;
2152  uint16_t startoffstripe, endoffstripe, datastripes;
2153 
2154  datastripes = c->chunk_item->num_stripes - (c->chunk_item->type & BLOCK_FLAG_RAID5 ? 1 : 2);
2155 
2156  get_raid0_offset(address - c->offset, c->chunk_item->stripe_length, datastripes, &startoff, &startoffstripe);
2157  get_raid0_offset(address + length - c->offset - 1, c->chunk_item->stripe_length, datastripes, &endoff, &endoffstripe);
2158 
2159  startoff -= startoff % c->chunk_item->stripe_length;
2160  endoff = sector_align(endoff, c->chunk_item->stripe_length);
2161 
2162  *lockaddr = c->offset + (startoff * datastripes);
2163  *locklen = (endoff - startoff) * datastripes;
2164 }
unsigned short int uint16_t
Definition: acefiex.h:54
_Post_satisfies_ static stripe __inline void get_raid0_offset(_In_ uint64_t off, _In_ uint64_t stripe_length, _In_ uint16_t num_stripes, _Out_ uint64_t *stripeoff, _Out_ uint16_t *stripe)
Definition: btrfs_drv.h:972
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
const GLubyte * c
Definition: glext.h:8905
GLuint address
Definition: glext.h:9393
UINT64 uint64_t
Definition: types.h:77
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
static uint64_t __inline sector_align(uint64_t n, uint64_t a)

Referenced by read_data(), and write_data_complete().

◆ if() [1/5]

◆ if() [2/5]

if ( ed)

Definition at line 2830 of file write.c.

2830  {
2831  ERR("out of memory\n");
2832  return false;
2833  }
#define ERR(fmt,...)
Definition: debug.h:109

◆ if() [3/5]

if ( !prealloc &&data &&!  fcb->inode_item.flags &BTRFS_INODE_NODATASUM)

Definition at line 2848 of file write.c.

2848  {
2849  ULONG sl = (ULONG)(length / Vcb->superblock.sector_size);
2850 
2852  if (!csum) {
2853  ERR("out of memory\n");
2854  ExFreePool(ed);
2855  return false;
2856  }
2857 
2858  Status = calc_csum(Vcb, data, sl, csum);
2859  if (!NT_SUCCESS(Status)) {
2860  ERR("calc_csum returned %08x\n", Status);
2861  ExFreePool(csum);
2862  ExFreePool(ed);
2863  return false;
2864  }
2865  }
#define ALLOC_TAG
Definition: btrfs_drv.h:91
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define Vcb
Definition: cdprocs.h:1425
NTSTATUS calc_csum(_In_ device_extension *Vcb, _In_reads_bytes_(sectors *Vcb->superblock.sector_size) uint8_t *data, _In_ uint32_t sectors, _Out_writes_bytes_(sectors *sizeof(uint32_t)) uint32_t *csum)
Definition: write.c:2782
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
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
UINT32 uint32_t
Definition: types.h:75
Definition: fs.h:216
unsigned int ULONG
Definition: retypes.h:1
ExFreePool(ed)
EXTENT_DATA * ed
Definition: write.c:2818

◆ if() [4/5]

if ( NT_SUCCESSStatus)

Definition at line 2868 of file write.c.

2868  {
2869  ERR("add_extent_to_fcb returned %08x\n", Status);
2870  if (csum) ExFreePool(csum);
2871  ExFreePool(ed);
2872  return false;
2873  }
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: fs.h:216
ExFreePool(ed)
EXTENT_DATA * ed
Definition: write.c:2818

◆ if() [5/5]

if ( data  )

Definition at line 2894 of file write.c.

2894  {
2897  if (!NT_SUCCESS(Status))
2898  ERR("write_data_complete returned %08x\n", Status);
2899  }
_In_ PIRP Irp
Definition: csq.h:116
#define FSRTL_FLAG2_IS_PAGING_FILE
Definition: fsrtltypes.h:57
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool _In_ uint64_t irp_offset
Definition: write.c:2815
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool file_write
Definition: write.c:2814
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS write_data_complete(device_extension *Vcb, uint64_t address, void *data, uint32_t length, PIRP Irp, chunk *c, bool file_write, uint64_t irp_offset, ULONG priority)
Definition: write.c:2166
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:279
#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
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
UINT32 uint32_t
Definition: types.h:75

◆ insert_chunk_fragmented()

static NTSTATUS insert_chunk_fragmented ( fcb fcb,
uint64_t  start,
uint64_t  length,
uint8_t data,
bool  prealloc,
LIST_ENTRY rollback 
)
static

Definition at line 2996 of file write.c.

2996  {
2997  LIST_ENTRY* le;
2998  uint64_t flags = fcb->Vcb->data_flags;
2999  bool page_file = fcb->Header.Flags2 & FSRTL_FLAG2_IS_PAGING_FILE;
3000  NTSTATUS Status;
3001  chunk* c;
3002 
3003  ExAcquireResourceSharedLite(&fcb->Vcb->chunk_lock, true);
3004 
3005  // first create as many chunks as we can
3006  do {
3007  Status = alloc_chunk(fcb->Vcb, flags, &c, false);
3008  } while (NT_SUCCESS(Status));
3009 
3010  if (Status != STATUS_DISK_FULL) {
3011  ERR("alloc_chunk returned %08x\n", Status);
3012  ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
3013  return Status;
3014  }
3015 
3016  le = fcb->Vcb->chunks.Flink;
3017  while (le != &fcb->Vcb->chunks) {
3019 
3020  if (!