ReactOS  0.4.13-dev-100-gc8611ae
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 address)
 
static UINT64 find_new_chunk_address (device_extension *Vcb, UINT64 size)
 
static BOOL find_new_dup_stripes (device_extension *Vcb, stripe *stripes, UINT64 max_stripe_size, BOOL full_size)
 
static BOOL find_new_stripe (device_extension *Vcb, stripe *stripes, UINT16 i, UINT64 max_stripe_size, BOOL allow_missing, BOOL full_size)
 
NTSTATUS alloc_chunk (device_extension *Vcb, UINT64 flags, chunk **pc, BOOL full_size)
 
static NTSTATUS prepare_raid0_write (_Pre_satisfies_(_Curr_->chunk_item->num_stripes >0) _In_ chunk *c, _In_ UINT64 address, _In_reads_bytes_(length) void *data, _In_ UINT32 length, _In_ write_stripe *stripes, _In_ PIRP Irp, _In_ UINT64 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 address, _In_reads_bytes_(length) void *data, _In_ UINT32 length, _In_ write_stripe *stripes, _In_ PIRP Irp, _In_ UINT64 irp_offset, _In_ write_data_context *wtc)
 
static NTSTATUS add_partial_stripe (device_extension *Vcb, chunk *c, UINT64 address, UINT32 length, void *data)
 
static NTSTATUS prepare_raid5_write (device_extension *Vcb, chunk *c, UINT64 address, void *data, UINT32 length, write_stripe *stripes, PIRP Irp, UINT64 irp_offset, ULONG priority, write_data_context *wtc)
 
static NTSTATUS prepare_raid6_write (device_extension *Vcb, chunk *c, UINT64 address, void *data, UINT32 length, write_stripe *stripes, PIRP Irp, UINT64 irp_offset, ULONG priority, write_data_context *wtc)
 
NTSTATUS write_data (_In_ device_extension *Vcb, _In_ UINT64 address, _In_reads_bytes_(length) void *data, _In_ UINT32 length, _In_ write_data_context *wtc, _In_opt_ PIRP Irp, _In_opt_ chunk *c, _In_ BOOL file_write, _In_ UINT64 irp_offset, _In_ ULONG priority)
 
void get_raid56_lock_range (chunk *c, UINT64 address, UINT64 length, UINT64 *lockaddr, UINT64 *locklen)
 
NTSTATUS write_data_complete (device_extension *Vcb, UINT64 address, void *data, UINT32 length, PIRP Irp, chunk *c, BOOL file_write, UINT64 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 start_data, UINT64 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 offset, _In_reads_bytes_(edsize) EXTENT_DATA *ed, _In_ UINT16 edsize, _In_ BOOL unique, _In_opt_ _When_(return >=0, __drv_aliasesMem) UINT32 *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 *data, _In_ UINT32 sectors, _Out_writes_bytes_(sectors *sizeof(UINT32)) UINT32 *csum)
 
 _Requires_lock_held_ (c->lock) _When_(return !=0
 
 _Releases_lock_ (c->lock)) BOOL insert_extent_chunk(_In_ device_extension *Vcb
 
 TRACE ("(%p, (%llx, %llx), %llx, %llx, %llx, %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 start_data, UINT64 length, void *data, PIRP Irp, UINT64 *written, BOOL file_write, UINT64 irp_offset, LIST_ENTRY *rollback)
 
static NTSTATUS insert_chunk_fragmented (fcb *fcb, UINT64 start, UINT64 length, UINT8 *data, BOOL prealloc, LIST_ENTRY *rollback)
 
static NTSTATUS insert_prealloc_extent (fcb *fcb, UINT64 start, UINT64 length, LIST_ENTRY *rollback)
 
static NTSTATUS insert_extent (device_extension *Vcb, fcb *fcb, UINT64 start_data, UINT64 length, void *data, PIRP Irp, BOOL file_write, UINT64 irp_offset, LIST_ENTRY *rollback)
 
NTSTATUS truncate_file (fcb *fcb, UINT64 end, PIRP Irp, LIST_ENTRY *rollback)
 
NTSTATUS extend_file (fcb *fcb, file_ref *fileref, UINT64 end, BOOL prealloc, PIRP Irp, LIST_ENTRY *rollback)
 
static NTSTATUS do_write_file_prealloc (fcb *fcb, extent *ext, UINT64 start_data, UINT64 end_data, void *data, UINT64 *written, PIRP Irp, BOOL file_write, UINT64 irp_offset, ULONG priority, LIST_ENTRY *rollback)
 
NTSTATUS do_write_file (fcb *fcb, UINT64 start, UINT64 end_data, void *data, PIRP Irp, BOOL file_write, UINT32 irp_offset, LIST_ENTRY *rollback)
 
NTSTATUS write_compressed (fcb *fcb, UINT64 start_data, UINT64 end_data, void *data, PIRP Irp, LIST_ENTRY *rollback)
 
NTSTATUS write_file2 (device_extension *Vcb, PIRP Irp, LARGE_INTEGER offset, void *buf, ULONG *length, BOOLEAN paging_io, BOOLEAN no_cache, BOOLEAN wait, BOOLEAN deferred_write, BOOLEAN write_irp, LIST_ENTRY *rollback)
 
NTSTATUS write_file (device_extension *Vcb, PIRP Irp, BOOLEAN wait, BOOLEAN deferred_write)
 
 _Dispatch_type_ (IRP_MJ_WRITE)
 

Variables

_In_ fcbfcb
 
_In_ fcb _In_ chunkc
 
_In_ fcb _In_ chunk _In_ UINT64 start_data
 
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 length
 
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL prealloc
 
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ voiddata
 
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP Irp
 
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRYrollback
 
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ UINT8 compression = compression
 
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ UINT8 _In_ UINT64 decoded_size = decoded_size
 
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ UINT8 _In_ UINT64 _In_ BOOL file_write
 
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ UINT8 _In_ UINT64 _In_ BOOL _In_ UINT64 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 edsize = (UINT16)(offsetof(EXTENT_DATA, data[0]) + sizeof(EXTENT_DATA2))
 
UINT32csum = 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 4708 of file write.c.

4710  {
4711  NTSTATUS Status;
4712  BOOL top_level;
4716  fcb* fcb = FileObject ? FileObject->FsContext : NULL;
4717  ccb* ccb = FileObject ? FileObject->FsContext2 : NULL;
4719 
4721 
4722  top_level = is_top_level(Irp);
4723 
4724  if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
4726  goto exit;
4727  } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
4729  goto end;
4730  }
4731 
4732  if (!fcb) {
4733  ERR("fcb was NULL\n");
4735  goto end;
4736  }
4737 
4738  if (!ccb) {
4739  ERR("ccb was NULL\n");
4741  goto end;
4742  }
4743 
4744  if (Irp->RequestorMode == UserMode && !(ccb->access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
4745  WARN("insufficient permissions\n");
4747  goto end;
4748  }
4749 
4750  if (fcb == Vcb->volume_fcb) {
4751  if (!Vcb->locked || Vcb->locked_fileobj != FileObject) {
4752  ERR("trying to write to volume when not locked, or locked with another FileObject\n");
4754  goto end;
4755  }
4756 
4757  TRACE("writing directly to volume\n");
4758 
4760 
4761  Status = IoCallDriver(Vcb->Vpb->RealDevice, Irp);
4762  goto exit;
4763  }
4764 
4765  if (is_subvol_readonly(fcb->subvol, Irp)) {
4767  goto end;
4768  }
4769 
4770  if (Vcb->readonly) {
4772  goto end;
4773  }
4774 
4775  _SEH2_TRY {
4777  CcMdlWriteComplete(IrpSp->FileObject, &IrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress);
4778 
4779  Irp->MdlAddress = NULL;
4781  } else {
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  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 }
return TRUE
Definition: write.c:2909
NTSTATUS write_file(device_extension *Vcb, PIRP Irp, BOOLEAN wait, BOOLEAN deferred_write)
Definition: write.c:4634
#define FsRtlEnterFileSystem
NTSTATUS Status
Definition: write.c:2825
#define FsRtlExitFileSystem
_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:627
GLuint GLuint end
Definition: gl.h:1545
TRACE("(%p, (%llx, %llx), %llx, %llx, %llx, %u, %p, %p)\n", Vcb, fcb->subvol->id, fcb->inode, c->offset, start_data, length, prealloc, data, rollback)
ACCESS_MASK access
Definition: btrfs_drv.h:357
BOOLEAN NTAPI IoIsOperationSynchronous(IN PIRP Irp)
Definition: irp.c:1882
NTSTATUS vol_write(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: volume.c:206
#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
_SEH2_TRY
Definition: create.c:4250
#define IRP_MN_COMPLETE
Definition: iotypes.h:4063
unsigned int BOOL
Definition: ntddk_ex.h:94
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
PVOID DeviceExtension
Definition: env_spec_w32.h:418
unsigned char BOOLEAN
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)
static __inline BOOL is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1012
#define STATUS_PENDING
Definition: ntstatus.h:82
#define VCB_TYPE_VOLUME
Definition: btrfs_drv.h:629
#define Vcb
Definition: cdprocs.h:1425
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
* PFILE_OBJECT
Definition: iotypes.h:1954
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
void do_write_job(device_extension *Vcb, PIRP Irp)
Definition: worker-thread.c:66
PFILE_OBJECT FileObject
Definition: iotypes.h:2812
_SEH2_END
Definition: create.c:4424
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
struct _root * subvol
Definition: btrfs_drv.h:261
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
BOOL is_top_level(_In_ PIRP Irp)
Definition: btrfs.c:256
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define IRP_PAGING_IO
#define IO_NO_INCREMENT
Definition: iotypes.h:565
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#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:2771
return STATUS_SUCCESS
Definition: btrfs.c:2725
IoMarkIrpPending(Irp)

◆ _Function_class_()

_Function_class_ ( IO_COMPLETION_ROUTINE  )

Definition at line 28 of file write.c.

42  {
43  LIST_ENTRY* le;
44  space* s;
45 
46  TRACE("(%p, %llx, %llx, %p)\n", Vcb, c->offset, length, address);
47 
48  if (length > c->chunk_item->size - c->used)
49  return FALSE;
50 
51  if (!c->cache_loaded) {
53 
54  if (!NT_SUCCESS(Status)) {
55  ERR("load_cache_chunk returned %08x\n", Status);
56  return FALSE;
57  }
58  }
59 
60  if (IsListEmpty(&c->space_size))
61  return FALSE;
62 
63  le = c->space_size.Flink;
64  while (le != &c->space_size) {
65  s = CONTAINING_RECORD(le, space, list_entry_size);
66 
67  if (s->size == length) {
68  *address = s->address;
69  return TRUE;
70  } else if (s->size < length) {
71  if (le == c->space_size.Flink)
72  return FALSE;
73 
74  s = CONTAINING_RECORD(le->Blink, space, list_entry_size);
75 
76  *address = s->address;
77  return TRUE;
78  }
79 
80  le = le->Flink;
81  }
82 
83  s = CONTAINING_RECORD(c->space_size.Blink, space, list_entry_size);
84 
85  if (s->size > length) {
86  *address = s->address;
87  return TRUE;
88  }
89 
90  return FALSE;
91 }
return TRUE
Definition: write.c:2909
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
LONG NTSTATUS
Definition: precomp.h:26
TRACE("(%p, (%llx, %llx), %llx, %llx, %llx, %u, %p, %p)\n", Vcb, fcb->subvol->id, fcb->inode, c->offset, start_data, length, prealloc, data, rollback)
_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:947
#define ERR(fmt,...)
Definition: debug.h:109

◆ _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 2359 of file write.c.

2359  {
2360  LIST_ENTRY* le = prevextle->Flink;
2361 
2362  while (le != &fcb->extents) {
2364 
2365  if (ext->offset >= newext->offset) {
2366  InsertHeadList(ext->list_entry.Blink, &newext->list_entry);
2367  return;
2368  }
2369 
2370  le = le->Flink;
2371  }
2372 
2373  InsertTailList(&fcb->extents, &newext->list_entry);
2374 }
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:273
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  offset,
_In_reads_bytes_(edsize) EXTENT_DATA ed,
_In_ UINT16  edsize,
_In_ BOOL  unique,
_In_opt_ _When_(return >=0, __drv_aliasesMem) UINT32 csum,
_In_ LIST_ENTRY rollback 
)

Definition at line 2728 of file write.c.

2729  {
2730  extent* ext;
2731  LIST_ENTRY* le;
2732 
2734  if (!ext) {
2735  ERR("out of memory\n");
2737  }
2738 
2739  ext->offset = offset;
2740  ext->datalen = edsize;
2741  ext->unique = unique;
2742  ext->ignore = FALSE;
2743  ext->inserted = TRUE;
2744  ext->csum = csum;
2745 
2746  RtlCopyMemory(&ext->extent_data, ed, edsize);
2747 
2748  le = fcb->extents.Flink;
2749  while (le != &fcb->extents) {
2750  extent* oldext = CONTAINING_RECORD(le, extent, list_entry);
2751 
2752  if (oldext->offset >= offset) {
2753  InsertHeadList(le->Blink, &ext->list_entry);
2754  goto end;
2755  }
2756 
2757  le = le->Flink;
2758  }
2759 
2760  InsertTailList(&fcb->extents, &ext->list_entry);
2761 
2762 end:
2764 
2765  return STATUS_SUCCESS;
2766 }
return TRUE
Definition: write.c:2909
void add_insert_extent_rollback(LIST_ENTRY *rollback, fcb *fcb, extent *ext)
Definition: write.c:2709
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
UINT32 * csum
Definition: write.c:2829
GLuint GLuint end
Definition: gl.h:1545
#define InsertTailList(ListHead, Entry)
#define ALLOC_TAG
Definition: btrfs_drv.h:86
UINT64 offset
Definition: btrfs_drv.h:202
#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
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
LIST_ENTRY extents
Definition: btrfs_drv.h:273
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Definition: typedefs.h:117
#define ERR(fmt,...)
Definition: debug.h:109
ed2 offset
Definition: write.c:2853
Definition: list.h:27
UINT16 edsize
Definition: write.c:2828
_ForwardIter unique(_ForwardIter __first, _ForwardIter __last)
Definition: _algo.h:298
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2822
return STATUS_SUCCESS
Definition: btrfs.c:2725
EXTENT_DATA * ed
Definition: write.c:2826

Referenced by duplicate_extents(), extend_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 2709 of file write.c.

2709  {
2710  rollback_extent* re;
2711 
2713  if (!re) {
2714  ERR("out of memory\n");
2715  return;
2716  }
2717 
2718  re->fcb = fcb;
2719  re->ext = ext;
2720 
2722 }
#define ALLOC_TAG
Definition: btrfs_drv.h:86
char ext[3]
Definition: mkdosfs.c:358
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define ERR(fmt,...)
Definition: debug.h:109
extent * ext
Definition: btrfs_drv.h:1215
_In_ fcb * fcb
Definition: write.c:2822
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2822
void add_rollback(_In_ LIST_ENTRY *rollback, _In_ enum rollback_type type, _In_ __drv_aliasesMem void *ptr)
Definition: treefuncs.c:817

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  address,
UINT32  length,
void data 
)
static

Definition at line 964 of file write.c.

964  {
966  LIST_ENTRY* le;
967  partial_stripe* ps;
968  UINT64 stripe_addr;
969  UINT16 num_data_stripes;
970  ULONG bmplen;
971 
972  num_data_stripes = c->chunk_item->num_stripes - (c->chunk_item->type & BLOCK_FLAG_RAID5 ? 1 : 2);
973  stripe_addr = address - ((address - c->offset) % (num_data_stripes * c->chunk_item->stripe_length));
974 
975  ExAcquireResourceExclusiveLite(&c->partial_stripes_lock, TRUE);
976 
977  le = c->partial_stripes.Flink;
978  while (le != &c->partial_stripes) {
980 
981  if (ps->address == stripe_addr) {
982  // update existing entry
983 
984  RtlCopyMemory(ps->data + address - stripe_addr, data, length);
985  RtlClearBits(&ps->bmp, (ULONG)((address - stripe_addr) / Vcb->superblock.sector_size), length / Vcb->superblock.sector_size);
986 
987  // if now filled, flush
988  if (RtlAreBitsClear(&ps->bmp, 0, (ULONG)((num_data_stripes * c->chunk_item->stripe_length) / Vcb->superblock.sector_size))) {
990  if (!NT_SUCCESS(Status)) {
991  ERR("flush_partial_stripe returned %08x\n", Status);
992  goto end;
993  }
994 
996 
997  if (ps->bmparr)
998  ExFreePool(ps->bmparr);
999 
1000  ExFreePool(ps);
1001  }
1002 
1004  goto end;
1005  } else if (ps->address > stripe_addr)
1006  break;
1007 
1008  le = le->Flink;
1009  }
1010 
1011  // add new entry
1012 
1013  ps = ExAllocatePoolWithTag(NonPagedPool, offsetof(partial_stripe, data[0]) + (ULONG)(num_data_stripes * c->chunk_item->stripe_length), ALLOC_TAG);
1014  if (!ps) {
1015  ERR("out of memory\n");
1017  goto end;
1018  }
1019 
1020  bmplen = (ULONG)sector_align(((num_data_stripes * c->chunk_item->stripe_length) / (8 * Vcb->superblock.sector_size) + 1), sizeof(ULONG));
1021 
1022  ps->address = stripe_addr;
1024  if (!ps->bmparr) {
1025  ERR("out of memory\n");
1026  ExFreePool(ps);
1028  goto end;
1029  }
1030 
1031  RtlInitializeBitMap(&ps->bmp, ps->bmparr, (ULONG)((num_data_stripes * c->chunk_item->stripe_length) / Vcb->superblock.sector_size));
1032  RtlSetAllBits(&ps->bmp);
1033 
1034  RtlCopyMemory(ps->data + address - stripe_addr, data, length);
1035  RtlClearBits(&ps->bmp, (ULONG)((address - stripe_addr) / Vcb->superblock.sector_size), length / Vcb->superblock.sector_size);
1036 
1037  InsertHeadList(le->Blink, &ps->list_entry);
1038 
1040 
1041 end:
1042  ExReleaseResourceLite(&c->partial_stripes_lock);
1043 
1044  return Status;
1045 }
return TRUE
Definition: write.c:2909
ULONG * bmparr
Definition: btrfs_drv.h:512
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:2825
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:5549
GLuint GLuint end
Definition: gl.h:1545
RTL_BITMAP bmp
Definition: btrfs_drv.h:513
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:86
LIST_ENTRY list_entry
Definition: btrfs_drv.h:514
#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
UINT64 address
Definition: btrfs_drv.h:511
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
Definition: typedefs.h:117
UINT8 data[1]
Definition: btrfs_drv.h:515
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
unsigned short UINT16
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:77
unsigned long long UINT64
return STATUS_SUCCESS
Definition: btrfs.c:2725
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  flags,
chunk **  pc,
BOOL  full_size 
)

Definition at line 365 of file write.c.

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

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 2790 of file write.c.

2791  {
2792  NTSTATUS Status;
2793  calc_job* cj;
2794 
2795  // From experimenting, it seems that 40 sectors is roughly the crossover
2796  // point where offloading the crc32 calculation becomes worth it.
2797 
2798  if (sectors < 40 || KeQueryActiveProcessorCount(NULL) < 2) {
2799  ULONG j;
2800 
2801  for (j = 0; j < sectors; j++) {
2802  csum[j] = ~calc_crc32c(0xffffffff, data + (j * Vcb->superblock.sector_size), Vcb->superblock.sector_size);
2803  }
2804 
2805  return STATUS_SUCCESS;
2806  }
2807 
2809  if (!NT_SUCCESS(Status)) {
2810  ERR("add_calc_job returned %08x\n", Status);
2811  return Status;
2812  }
2813 
2815  free_calc_job(cj);
2816 
2817  return STATUS_SUCCESS;
2818 }
_In_ ULONG cj
Definition: winddi.h:3540
NTSTATUS Status
Definition: write.c:2825
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
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
NTSTATUS add_calc_job(device_extension *Vcb, UINT8 *data, UINT32 sectors, UINT32 *csum, calc_job **pcj)
Definition: calcthread.c:22
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
NTKERNELAPI ULONG NTAPI KeQueryActiveProcessorCount(OUT PKAFFINITY ActiveProcessors OPTIONAL)
Definition: ke.c:15
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
return STATUS_SUCCESS
Definition: btrfs.c:2725

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  start,
UINT64  end_data,
void data,
PIRP  Irp,
BOOL  file_write,
UINT32  irp_offset,
LIST_ENTRY rollback 
)

Definition at line 3947 of file write.c.

3947  {
3948  NTSTATUS Status;
3949  LIST_ENTRY *le, *le2;
3950  UINT64 written = 0, length = end_data - start;
3951  UINT64 last_cow_start;
3953 #ifdef DEBUG_PARANOID
3954  UINT64 last_off;
3955 #endif
3956 
3957  last_cow_start = 0;
3958 
3959  le = fcb->extents.Flink;
3960  while (le != &fcb->extents) {
3962 
3963  le2 = le->Flink;
3964 
3965  if (!ext->ignore) {
3966  EXTENT_DATA* ed = &ext->extent_data;
3968  UINT64 len;
3969 
3971 
3972  if (ext->offset + len <= start)
3973  goto nextitem;
3974 
3975  if (ext->offset > start + written + length)
3976  break;
3977 
3979  if (max(last_cow_start, start + written) < ext->offset) {
3980  UINT64 start_write = max(last_cow_start, start + written);
3981 
3982  Status = excise_extents(fcb->Vcb, fcb, start_write, ext->offset, Irp, rollback);
3983  if (!NT_SUCCESS(Status)) {
3984  ERR("excise_extents returned %08x\n", Status);
3985  return Status;
3986  }
3987 
3988  Status = insert_extent(fcb->Vcb, fcb, start_write, ext->offset - start_write, (UINT8*)data + written, Irp, file_write, irp_offset + written, rollback);
3989  if (!NT_SUCCESS(Status)) {
3990  ERR("insert_extent returned %08x\n", Status);
3991  return Status;
3992  }
3993 
3994  written += ext->offset - start_write;
3995  length -= ext->offset - start_write;
3996 
3997  if (length == 0)
3998  break;
3999  }
4000 
4001  if (ed->type == EXTENT_TYPE_REGULAR) {
4002  UINT64 writeaddr = ed2->address + ed2->offset + start + written - ext->offset;
4003  UINT64 write_len = min(len, length);
4004  chunk* c;
4005 
4006  TRACE("doing non-COW write to %llx\n", writeaddr);
4007 
4008  Status = write_data_complete(fcb->Vcb, writeaddr, (UINT8*)data + written, (UINT32)write_len, Irp, NULL, file_write, irp_offset + written, priority);
4009  if (!NT_SUCCESS(Status)) {
4010  ERR("write_data_complete returned %08x\n", Status);
4011  return Status;
4012  }
4013 
4014  c = get_chunk_from_address(fcb->Vcb, writeaddr);
4015  if (c)
4016  c->changed = TRUE;
4017 
4018  // This shouldn't ever get called - nocow files should always also be nosum.
4020  calc_csum(fcb->Vcb, (UINT8*)data + written, (UINT32)(write_len / fcb->Vcb->superblock.sector_size),
4021  &ext->csum[(start + written - ext->offset) / fcb->Vcb->superblock.sector_size]);
4022 
4023  ext->inserted = TRUE;
4024  }
4025 
4026  written += write_len;
4027  length -= write_len;
4028 
4029  if (length == 0)
4030  break;
4031  } else if (ed->type == EXTENT_TYPE_PREALLOC) {
4032  UINT64 write_len;
4033 
4034  Status = do_write_file_prealloc(fcb, ext, start + written, end_data, (UINT8*)data + written, &write_len,
4035  Irp, file_write, irp_offset + written, priority, rollback);
4036  if (!NT_SUCCESS(Status)) {
4037  ERR("do_write_file_prealloc returned %08x\n", Status);
4038  return Status;
4039  }
4040 
4041  written += write_len;
4042  length -= write_len;
4043 
4044  if (length == 0)
4045  break;
4046  }
4047 
4048  last_cow_start = ext->offset + len;
4049  }
4050  }
4051 
4052 nextitem:
4053  le = le2;
4054  }
4055 
4056  if (length > 0) {
4057  UINT64 start_write = max(last_cow_start, start + written);
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*)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 %llx 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 
4097 
4098  return STATUS_SUCCESS;
4099 }
return TRUE
Definition: write.c:2909
LOCAL void nextitem(arg_t *ap)
Definition: match.c:428
#define max(a, b)
Definition: svc.c:63
NTSTATUS Status
Definition: write.c:2825
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ UINT8 _In_ UINT64 _In_ BOOL file_write
Definition: write.c:2822
#define BTRFS_INODE_NODATACOW
Definition: propsheet.h:77
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:58
UINT64 num_bytes
Definition: btrfs.h:344
EXTENT_DATA2 * ed2
Definition: write.c:2827
_In_ PIRP Irp
Definition: csq.h:116
chunk * get_chunk_from_address(device_extension *Vcb, UINT64 address)
Definition: write.c:93
#define FSRTL_FLAG2_IS_PAGING_FILE
Definition: fsrtltypes.h:57
LONG NTSTATUS
Definition: precomp.h:26
#define int3
Definition: btrfs_drv.h:1683
TRACE("(%p, (%llx, %llx), %llx, %llx, %llx, %u, %p, %p)\n", Vcb, fcb->subvol->id, fcb->inode, c->offset, start_data, length, prealloc, data, rollback)
UINT8 data[1]
Definition: btrfs.h:337
NTSTATUS write_data_complete(device_extension *Vcb, UINT64 address, void *data, UINT32 length, PIRP Irp, chunk *c, BOOL file_write, UINT64 irp_offset, ULONG priority)
Definition: write.c:2170
NTSTATUS calc_csum(_In_ device_extension *Vcb, _In_reads_bytes_(sectors *Vcb->superblock.sector_size) UINT8 *data, _In_ UINT32 sectors, _Out_writes_bytes_(sectors *sizeof(UINT32)) UINT32 *csum)
Definition: write.c:2790
UINT64 decoded_size
Definition: btrfs.h:332
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:67
unsigned int UINT32
UINT64 address
Definition: btrfs.h:341
UINT8 type
Definition: btrfs.h:336
smooth NULL
Definition: ftsmooth.c:416
char ext[3]
Definition: mkdosfs.c:358
BOOL extents_changed
Definition: btrfs_drv.h:292
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
UINT64 offset
Definition: btrfs.h:343
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:256
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
LIST_ENTRY extents
Definition: btrfs_drv.h:273
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLenum GLsizei len
Definition: glext.h:6722
if(!find_data_address_in_chunk(Vcb, c, length, &address)) return FALSE
Definition: typedefs.h:117
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:69
INODE_ITEM inode_item
Definition: btrfs_drv.h:264
UINT8 compression
Definition: btrfs.h:333
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:68
Status
Definition: gdiplustypes.h:24
static NTSTATUS insert_extent(device_extension *Vcb, fcb *fcb, UINT64 start_data, UINT64 length, void *data, PIRP Irp, BOOL file_write, UINT64 irp_offset, LIST_ENTRY *rollback)
Definition: write.c:3133
#define ERR(fmt,...)
Definition: debug.h:109
GLuint start
Definition: gl.h:1545
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
UINT64 flags
Definition: btrfs.h:275
mark_fcb_dirty(fcb)
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ UINT8 _In_ UINT64 _In_ BOOL _In_ UINT64 irp_offset
Definition: write.c:2823
unsigned int ULONG
Definition: retypes.h:1
static int priority
Definition: timer.c:163
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2822
NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, UINT64 start_data, UINT64 end_data, PIRP Irp, LIST_ENTRY *rollback)
Definition: write.c:2376
unsigned long long UINT64
return STATUS_SUCCESS
Definition: btrfs.c:2725
unsigned char UINT8
_In_ fcb _In_ chunk * c
Definition: write.c:2822
EXTENT_DATA * ed
Definition: write.c:2826
struct _device_extension * Vcb
Definition: btrfs_drv.h:260
static NTSTATUS do_write_file_prealloc(fcb *fcb, extent *ext, UINT64 start_data, UINT64 end_data, void *data, UINT64 *written, PIRP Irp, BOOL file_write, UINT64 irp_offset, ULONG priority, LIST_ENTRY *rollback)
Definition: write.c:3560

Referenced by duplicate_extents(), extend_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  start_data,
UINT64  end_data,
void data,
UINT64 written,
PIRP  Irp,
BOOL  file_write,
UINT64  irp_offset,
ULONG  priority,
LIST_ENTRY rollback 
)
static

Definition at line 3560 of file write.c.

3561  {
3562  EXTENT_DATA* ed = &ext->extent_data;
3564  NTSTATUS Status;
3565  chunk* c = NULL;
3566 
3567  if (start_data <= ext->offset && end_data >= ext->offset + ed2->num_bytes) { // replace all
3568  extent* newext;
3569 
3570  newext = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3571  if (!newext) {
3572  ERR("out of memory\n");
3574  }
3575 
3576  RtlCopyMemory(&newext->extent_data, &ext->extent_data, ext->datalen);
3577 
3579 
3581  NULL, file_write, irp_offset + ext->offset - start_data, priority);
3582  if (!NT_SUCCESS(Status)) {
3583  ERR("write_data_complete returned %08x\n", Status);
3584  return Status;
3585  }
3586 
3588  ULONG sl = (ULONG)(ed2->num_bytes / fcb->Vcb->superblock.sector_size);
3590 
3591  if (!csum) {
3592  ERR("out of memory\n");
3593  ExFreePool(newext);
3595  }
3596 
3597  Status = calc_csum(fcb->Vcb, (UINT8*)data + ext->offset - start_data, sl, csum);
3598  if (!NT_SUCCESS(Status)) {
3599  ERR("calc_csum returned %08x\n", Status);
3600  ExFreePool(csum);
3601  ExFreePool(newext);
3602  return Status;
3603  }
3604 
3605  newext->csum = csum;
3606  } else
3607  newext->csum = NULL;
3608 
3609  *written = ed2->num_bytes;
3610 
3611  newext->offset = ext->offset;
3612  newext->datalen = ext->datalen;
3613  newext->unique = ext->unique;
3614  newext->ignore = FALSE;
3615  newext->inserted = TRUE;
3616  InsertHeadList(&ext->list_entry, &newext->list_entry);
3617 
3619 
3621 
3623  } else if (start_data <= ext->offset && end_data < ext->offset + ed2->num_bytes) { // replace beginning
3624  EXTENT_DATA2* ned2;
3625  extent *newext1, *newext2;
3626 
3627  newext1 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3628  if (!newext1) {
3629  ERR("out of memory\n");
3631  }
3632 
3633  newext2 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3634  if (!newext2) {
3635  ERR("out of memory\n");
3636  ExFreePool(newext1);
3638  }
3639 
3640  RtlCopyMemory(&newext1->extent_data, &ext->extent_data, ext->datalen);
3642  ned2 = (EXTENT_DATA2*)newext1->extent_data.data;
3643  ned2->num_bytes = end_data - ext->offset;
3644 
3645  RtlCopyMemory(&newext2->extent_data, &ext->extent_data, ext->datalen);
3646  ned2 = (EXTENT_DATA2*)newext2->extent_data.data;
3647  ned2->offset += end_data - ext->offset;
3648  ned2->num_bytes -= end_data - ext->offset;
3649 
3650  Status = write_data_complete(fcb->Vcb, ed2->address + ed2->offset, (UINT8*)data + ext->offset - start_data, (UINT32)(end_data - ext->offset),
3651  Irp, NULL, file_write, irp_offset + ext->offset - start_data, priority);
3652  if (!NT_SUCCESS(Status)) {
3653  ERR("write_data_complete returned %08x\n", Status);
3654  ExFreePool(newext1);
3655  ExFreePool(newext2);
3656  return Status;
3657  }
3658 
3660  ULONG sl = (ULONG)((end_data - ext->offset) / fcb->Vcb->superblock.sector_size);
3662 
3663  if (!csum) {
3664  ERR("out of memory\n");
3665  ExFreePool(newext1);
3666  ExFreePool(newext2);
3668  }
3669 
3670  Status = calc_csum(fcb->Vcb, (UINT8*)data + ext->offset - start_data, sl, csum);
3671  if (!NT_SUCCESS(Status)) {
3672  ERR("calc_csum returned %08x\n", Status);
3673  ExFreePool(newext1);
3674  ExFreePool(newext2);
3675  ExFreePool(csum);
3676  return Status;
3677  }
3678 
3679  newext1->csum = csum;
3680  } else
3681  newext1->csum = NULL;
3682 
3683  *written = end_data - ext->offset;
3684 
3685  newext1->offset = ext->offset;
3686  newext1->datalen = ext->datalen;
3687  newext1->unique = ext->unique;
3688  newext1->ignore = FALSE;
3689  newext1->inserted = TRUE;
3690  InsertHeadList(&ext->list_entry, &newext1->list_entry);
3691 
3693 
3694  newext2->offset = end_data;
3695  newext2->datalen = ext->datalen;
3696  newext2->unique = ext->unique;
3697  newext2->ignore = FALSE;
3698  newext2->inserted = TRUE;
3699  newext2->csum = NULL;
3700  add_extent(fcb, &newext1->list_entry, newext2);
3701 
3703 
3705 
3706  if (!c)
3707  ERR("get_chunk_from_address(%llx) failed\n", ed2->address);
3708  else {
3711 
3712  if (!NT_SUCCESS(Status)) {
3713  ERR("update_changed_extent_ref returned %08x\n", Status);
3714  return Status;
3715  }
3716  }
3717 
3719  } else if (start_data > ext->offset && end_data >= ext->offset + ed2->num_bytes) { // replace end
3720  EXTENT_DATA2* ned2;
3721  extent *newext1, *newext2;
3722 
3723  newext1 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3724  if (!newext1) {
3725  ERR("out of memory\n");
3727  }
3728 
3729  newext2 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3730  if (!newext2) {
3731  ERR("out of memory\n");
3732  ExFreePool(newext1);
3734  }
3735 
3736  RtlCopyMemory(&newext1->extent_data, &ext->extent_data, ext->datalen);
3737 
3738  ned2 = (EXTENT_DATA2*)newext1->extent_data.data;
3739  ned2->num_bytes = start_data - ext->offset;
3740 
3741  RtlCopyMemory(&newext2->extent_data, &ext->extent_data, ext->datalen);
3742 
3744  ned2 = (EXTENT_DATA2*)newext2->extent_data.data;
3745  ned2->offset += start_data - ext->offset;
3746  ned2->num_bytes = ext->offset + ed2->num_bytes - start_data;
3747 
3749  if (!NT_SUCCESS(Status)) {
3750  ERR("write_data_complete returned %08x\n", Status);
3751  ExFreePool(newext1);
3752  ExFreePool(newext2);
3753  return Status;
3754  }
3755 
3757  ULONG sl = (ULONG)(ned2->num_bytes / fcb->Vcb->superblock.sector_size);
3759 
3760  if (!csum) {
3761  ERR("out of memory\n");
3762  ExFreePool(newext1);
3763  ExFreePool(newext2);
3765  }
3766 
3767  Status = calc_csum(fcb->Vcb, data, sl, csum);
3768  if (!NT_SUCCESS(Status)) {
3769  ERR("calc_csum returned %08x\n", Status);
3770  ExFreePool(newext1);
3771  ExFreePool(newext2);
3772  ExFreePool(csum);
3773  return Status;
3774  }
3775 
3776  newext2->csum = csum;
3777  } else
3778  newext2->csum = NULL;
3779 
3780  *written = ned2->num_bytes;
3781 
3782  newext1->offset = ext->offset;
3783  newext1->datalen = ext->datalen;
3784  newext1->unique = ext->unique;
3785  newext1->ignore = FALSE;
3786  newext1->inserted = TRUE;
3787  newext1->csum = NULL;
3788  InsertHeadList(&ext->list_entry, &newext1->list_entry);
3789 
3791 
3792  newext2->offset = start_data;
3793  newext2->datalen = ext->datalen;
3794  newext2->unique = ext->unique;
3795  newext2->ignore = FALSE;
3796  newext2->inserted = TRUE;
3797  add_extent(fcb, &newext1->list_entry, newext2);
3798 
3800 
3802 
3803  if (!c)
3804  ERR("get_chunk_from_address(%llx) failed\n", ed2->address);
3805  else {
3808 
3809  if (!NT_SUCCESS(Status)) {
3810  ERR("update_changed_extent_ref returned %08x\n", Status);
3811  return Status;
3812  }
3813  }
3814 
3816  } else if (start_data > ext->offset && end_data < ext->offset + ed2->num_bytes) { // replace middle
3817  EXTENT_DATA2* ned2;
3818  extent *newext1, *newext2, *newext3;
3819 
3820  newext1 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3821  if (!newext1) {
3822  ERR("out of memory\n");
3824  }
3825 
3826  newext2 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3827  if (!newext2) {
3828  ERR("out of memory\n");
3829  ExFreePool(newext1);
3831  }
3832 
3833  newext3 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3834  if (!newext3) {
3835  ERR("out of memory\n");
3836  ExFreePool(newext1);
3837  ExFreePool(newext2);
3839  }
3840 
3841  RtlCopyMemory(&newext1->extent_data, &ext->extent_data, ext->datalen);
3842  RtlCopyMemory(&newext2->extent_data, &ext->extent_data, ext->datalen);
3843  RtlCopyMemory(&newext3->extent_data, &ext->extent_data, ext->datalen);
3844 
3845  ned2 = (EXTENT_DATA2*)newext1->extent_data.data;
3846  ned2->num_bytes = start_data - ext->offset;
3847 
3849  ned2 = (EXTENT_DATA2*)newext2->extent_data.data;
3850  ned2->offset += start_data - ext->offset;
3851  ned2->num_bytes = end_data - start_data;
3852 
3853  ned2 = (EXTENT_DATA2*)newext3->extent_data.data;
3854  ned2->offset += end_data - ext->offset;
3855  ned2->num_bytes -= end_data - ext->offset;
3856 
3857  ned2 = (EXTENT_DATA2*)newext2->extent_data.data;
3859  if (!NT_SUCCESS(Status)) {
3860  ERR("write_data_complete returned %08x\n", Status);
3861  ExFreePool(newext1);
3862  ExFreePool(newext2);
3863  ExFreePool(newext3);
3864  return Status;
3865  }
3866 
3868  ULONG sl = (ULONG)((end_data - start_data) / fcb->Vcb->superblock.sector_size);
3870 
3871  if (!csum) {
3872  ERR("out of memory\n");
3873  ExFreePool(newext1);
3874  ExFreePool(newext2);
3875  ExFreePool(newext3);
3877  }
3878 
3879  Status = calc_csum(fcb->Vcb, data, sl, csum);
3880  if (!NT_SUCCESS(Status)) {
3881  ERR("calc_csum returned %08x\n", Status);
3882  ExFreePool(newext1);
3883  ExFreePool(newext2);
3884  ExFreePool(newext3);
3885  ExFreePool(csum);
3886  return Status;
3887  }
3888 
3889  newext2->csum = csum;
3890  } else
3891  newext2->csum = NULL;
3892 
3893  *written = end_data - start_data;
3894 
3895  newext1->offset = ext->offset;
3896  newext1->datalen = ext->datalen;
3897  newext1->unique = ext->unique;
3898  newext1->ignore = FALSE;
3899  newext1->inserted = TRUE;
3900  newext1->csum = NULL;
3901  InsertHeadList(&ext->list_entry, &newext1->list_entry);
3902 
3904 
3905  newext2->offset = start_data;
3906  newext2->datalen = ext->datalen;
3907  newext2->unique = ext->unique;
3908  newext2->ignore = FALSE;
3909  newext2->inserted = TRUE;
3910  add_extent(fcb, &newext1->list_entry, newext2);
3911 
3913 
3914  newext3->offset = end_data;
3915  newext3->datalen = ext->datalen;
3916  newext3->unique = ext->unique;
3917  newext3->ignore = FALSE;
3918  newext3->inserted = TRUE;
3919  newext3->csum = NULL;
3920  add_extent(fcb, &newext2->list_entry, newext3);
3921 
3923 
3925 
3926  if (!c)
3927  ERR("get_chunk_from_address(%llx) failed\n", ed2->address);
3928  else {
3931 
3932  if (!NT_SUCCESS(Status)) {
3933  ERR("update_changed_extent_ref returned %08x\n", Status);
3934  return Status;
3935  }
3936  }
3937 
3939  }
3940 
3941  if (c)
3942  c->changed = TRUE;
3943 
3944  return STATUS_SUCCESS;
3945 }
void add_extent(_In_ fcb *fcb, _In_ LIST_ENTRY *prevextle, _In_ __drv_aliasesMem extent *newext)
Definition: write.c:2359
return TRUE
Definition: write.c:2909
void add_insert_extent_rollback(LIST_ENTRY *rollback, fcb *fcb, extent *ext)
Definition: write.c:2709
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP Irp
Definition: write.c:2822
NTSTATUS Status
Definition: write.c:2825
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ UINT8 _In_ UINT64 _In_ BOOL file_write
Definition: write.c:2822
UINT64 num_bytes
Definition: btrfs.h:344
EXTENT_DATA2 * ed2
Definition: write.c:2827
_In_ PIRP Irp
Definition: csq.h:116
UINT64 size
Definition: btrfs.h:342
chunk * get_chunk_from_address(device_extension *Vcb, UINT64 address)
Definition: write.c:93
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
UINT64 inode
Definition: btrfs_drv.h:262
LONG NTSTATUS
Definition: precomp.h:26
BOOL unique
Definition: btrfs_drv.h:204
GLintptr offset
Definition: glext.h:5920
LIST_ENTRY list_entry
Definition: btrfs_drv.h:209
UINT32 * csum
Definition: write.c:2829
UINT8 data[1]
Definition: btrfs.h:337
NTSTATUS write_data_complete(device_extension *Vcb, UINT64 address, void *data, UINT32 length, PIRP Irp, chunk *c, BOOL file_write, UINT64 irp_offset, ULONG priority)
Definition: write.c:2170
#define ALLOC_TAG
Definition: btrfs_drv.h:86
NTSTATUS calc_csum(_In_ device_extension *Vcb, _In_reads_bytes_(sectors *Vcb->superblock.sector_size) UINT8 *data, _In_ UINT32 sectors, _Out_writes_bytes_(sectors *sizeof(UINT32)) UINT32 *csum)
Definition: write.c:2790
unsigned int UINT32
UINT16 datalen
Definition: btrfs_drv.h:203
UINT64 offset
Definition: btrfs_drv.h:202
UINT64 address
Definition: btrfs.h:341
UINT8 type
Definition: btrfs.h:336
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
UINT32 * csum
Definition: btrfs_drv.h:207
UINT64 offset
Definition: btrfs.h:343
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
_In_ fcb _In_ chunk _In_ UINT64 start_data
Definition: write.c:2822
const GLubyte * c
Definition: glext.h:8905
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
NTSTATUS update_changed_extent_ref(device_extension *Vcb, chunk *c, UINT64 address, UINT64 size, UINT64 root, UINT64 objid, UINT64 offset, INT32 count, BOOL no_csum, BOOL superseded, PIRP Irp)
Definition: extent-tree.c:1950
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
if(!find_data_address_in_chunk(Vcb, c, length, &address)) return FALSE
INODE_ITEM inode_item
Definition: btrfs_drv.h:264
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:68
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
BOOL ignore
Definition: btrfs_drv.h:205
struct _root * subvol
Definition: btrfs_drv.h:261
UINT64 flags
Definition: btrfs.h:275
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ UINT8 _In_ UINT64 _In_ BOOL _In_ UINT64 irp_offset
Definition: write.c:2823
Definition: fs.h:216
EXTENT_DATA extent_data
Definition: btrfs_drv.h:211
unsigned int ULONG
Definition: retypes.h:1
static int priority
Definition: timer.c:163
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2822
ExFreePool(ed)
static void remove_fcb_extent(fcb *fcb, extent *ext, LIST_ENTRY *rollback)
Definition: write.c:2771
return STATUS_SUCCESS
Definition: btrfs.c:2725
unsigned char UINT8
EXTENT_DATA * ed
Definition: write.c:2826
BOOL inserted
Definition: btrfs_drv.h:206
struct _device_extension * Vcb
Definition: btrfs_drv.h:260

Referenced by do_write_file().

◆ excise_extents()

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

Definition at line 2376 of file write.c.

2376  {
2377  NTSTATUS Status;
2378  LIST_ENTRY* le;
2379 
2380  le = fcb->extents.Flink;
2381 
2382  while (le != &fcb->extents) {
2383  LIST_ENTRY* le2 = le->Flink;
2385  EXTENT_DATA* ed = &ext->extent_data;
2386  EXTENT_DATA2* ed2 = NULL;
2387  UINT64 len;
2388 
2389  if (!ext->ignore) {
2390  if (ed->type != EXTENT_TYPE_INLINE)
2391  ed2 = (EXTENT_DATA2*)ed->data;
2392 
2394 
2395  if (ext->offset < end_data && ext->offset + len > start_data) {
2396  if (ed->type == EXTENT_TYPE_INLINE) {
2397  if (start_data <= ext->offset && end_data >= ext->offset + len) { // remove all
2399 
2402  } else {
2403  ERR("trying to split inline extent\n");
2404 #ifdef DEBUG_PARANOID
2405  int3;
2406 #endif
2407  return STATUS_INTERNAL_ERROR;
2408  }
2409  } else if (ed->type != EXTENT_TYPE_INLINE) {
2410  if (start_data <= ext->offset && end_data >= ext->offset + len) { // remove all
2411  if (ed2->size != 0) {
2412  chunk* c;
2413 
2416 
2418 
2419  if (!c) {
2420  ERR("get_chunk_from_address(%llx) failed\n", ed2->address);
2421  } else {
2422  Status = update_changed_extent_ref(Vcb, c, ed2->address, ed2->size, fcb->subvol->id, fcb->inode, ext->offset - ed2->offset, -1,
2424  if (!NT_SUCCESS(Status)) {
2425  ERR("update_changed_extent_ref returned %08x\n", Status);
2426  goto end;
2427  }
2428  }
2429  }
2430 
2432  } else if (start_data <= ext->offset && end_data < ext->offset + len) { // remove beginning
2433  EXTENT_DATA2* ned2;
2434  extent* newext;
2435 
2436  if (ed2->size != 0) {
2437  fcb->inode_item.st_blocks -= end_data - ext->offset;
2439  }
2440 
2441  newext = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2), ALLOC_TAG);
2442  if (!newext) {
2443  ERR("out of memory\n");
2445  goto end;
2446  }
2447 
2448  ned2 = (EXTENT_DATA2*)newext->extent_data.data;
2449 
2450  newext->extent_data.generation = Vcb->superblock.generation;
2453  newext->extent_data.encryption = ed->encryption;
2454  newext->extent_data.encoding = ed->encoding;
2455  newext->extent_data.type = ed->type;
2456  ned2->address = ed2->address;
2457  ned2->size = ed2->size;
2458  ned2->offset = ed2->offset + (end_data - ext->offset);
2459  ned2->num_bytes = ed2->num_bytes - (end_data - ext->offset);
2460 
2461  newext->offset = end_data;
2462  newext->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
2463  newext->unique = ext->unique;
2464  newext->ignore = FALSE;
2465  newext->inserted = TRUE;
2466 
2467  if (ext->csum) {
2469  newext->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ned2->num_bytes * sizeof(UINT32) / Vcb->superblock.sector_size), ALLOC_TAG);
2470  if (!newext->csum) {
2471  ERR("out of memory\n");
2473  ExFreePool(newext);
2474  goto end;
2475  }
2476 
2477  RtlCopyMemory(newext->csum, &ext->csum[(end_data - ext->offset) / Vcb->superblock.sector_size],
2478  (ULONG)(ned2->num_bytes * sizeof(UINT32) / Vcb->superblock.sector_size));
2479  } else {
2480  newext->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2->size * sizeof(UINT32) / Vcb->superblock.sector_size), ALLOC_TAG);
2481  if (!newext->csum) {
2482  ERR("out of memory\n");
2484  ExFreePool(newext);
2485  goto end;
2486  }
2487 
2488  RtlCopyMemory(newext->csum, ext->csum, (ULONG)(ed2->size * sizeof(UINT32) / Vcb->superblock.sector_size));
2489  }
2490  } else
2491  newext->csum = NULL;
2492 
2493  add_extent(fcb, &ext->list_entry, newext);
2494 
2496  } else if (start_data > ext->offset && end_data >= ext->offset + len) { // remove end
2497  EXTENT_DATA2* ned2;
2498  extent* newext;
2499 
2500  if (ed2->size != 0) {
2501  fcb->inode_item.st_blocks -= ext->offset + len - start_data;
2503  }
2504 
2505  newext = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2), ALLOC_TAG);
2506  if (!newext) {
2507  ERR("out of memory\n");
2509  goto end;
2510  }
2511 
2512  ned2 = (EXTENT_DATA2*)newext->extent_data.data;
2513 
2514  newext->extent_data.generation = Vcb->superblock.generation;
2517  newext->extent_data.encryption = ed->encryption;
2518  newext->extent_data.encoding = ed->encoding;
2519  newext->extent_data.type = ed->type;
2520  ned2->address = ed2->address;
2521  ned2->size = ed2->size;
2522  ned2->offset = ed2->offset;
2523  ned2->num_bytes = start_data - ext->offset;
2524 
2525  newext->offset = ext->offset;
2526  newext->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
2527  newext->unique = ext->unique;
2528  newext->ignore = FALSE;
2529  newext->inserted = TRUE;
2530 
2531  if (ext->csum) {
2533  newext->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ned2->num_bytes * sizeof(UINT32) / Vcb->superblock.sector_size), ALLOC_TAG);
2534  if (!newext->csum) {
2535  ERR("out of memory\n");
2537  ExFreePool(newext);
2538  goto end;
2539  }
2540 
2541  RtlCopyMemory(newext->csum, ext->csum, (ULONG)(ned2->num_bytes * sizeof(UINT32) / Vcb->superblock.sector_size));
2542  } else {
2543  newext->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2->size * sizeof(UINT32) / Vcb->superblock.sector_size), ALLOC_TAG);
2544  if (!newext->csum) {
2545  ERR("out of memory\n");
2547  ExFreePool(newext);
2548  goto end;
2549  }
2550 
2551  RtlCopyMemory(newext->csum, ext->csum, (ULONG)(ed2->size * sizeof(UINT32) / Vcb->superblock.sector_size));
2552  }
2553  } else
2554  newext->csum = NULL;
2555 
2556  InsertHeadList(&ext->list_entry, &newext->list_entry);
2557 
2559  } else if (start_data > ext->offset && end_data < ext->offset + len) { // remove middle
2560  EXTENT_DATA2 *neda2, *nedb2;
2561  extent *newext1, *newext2;
2562 
2563  if (ed2->size != 0) {
2564  chunk* c;
2565 
2566  fcb->inode_item.st_blocks -= end_data - start_data;
2568 
2570 
2571  if (!c) {
2572  ERR("get_chunk_from_address(%llx) failed\n", ed2->address);
2573  } else {
2576  if (!NT_SUCCESS(Status)) {
2577  ERR("update_changed_extent_ref returned %08x\n", Status);
2578  goto end;
2579  }
2580  }
2581  }
2582 
2583  newext1 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2), ALLOC_TAG);
2584  if (!newext1) {
2585  ERR("out of memory\n");
2587  goto end;
2588  }
2589 
2590  newext2 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2), ALLOC_TAG);
2591  if (!newext2) {
2592  ERR("out of memory\n");
2594  ExFreePool(newext1);
2595  goto end;
2596  }
2597 
2598  neda2 = (EXTENT_DATA2*)newext1->extent_data.data;
2599 
2600  newext1->extent_data.generation = Vcb->superblock.generation;
2602  newext1->extent_data.compression = ed->compression;
2603  newext1->extent_data.encryption = ed->encryption;
2604  newext1->extent_data.encoding = ed->encoding;
2605  newext1->extent_data.type = ed->type;
2606  neda2->address = ed2->address;
2607  neda2->size = ed2->size;
2608  neda2->offset = ed2->offset;
2609  neda2->num_bytes = start_data - ext->offset;
2610 
2611  nedb2 = (EXTENT_DATA2*)newext2->extent_data.data;
2612 
2613  newext2->extent_data.generation = Vcb->superblock.generation;
2615  newext2->extent_data.compression = ed->compression;
2616  newext2->extent_data.encryption = ed->encryption;
2617  newext2->extent_data.encoding = ed->encoding;
2618  newext2->extent_data.type = ed->type;
2619  nedb2->address = ed2->address;
2620  nedb2->size = ed2->size;
2621  nedb2->offset = ed2->offset + (end_data - ext->offset);
2622  nedb2->num_bytes = ext->offset + len - end_data;
2623 
2624  newext1->offset = ext->offset;
2625  newext1->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
2626  newext1->unique = ext->unique;
2627  newext1->ignore = FALSE;
2628  newext1->inserted = TRUE;
2629 
2630  newext2->offset = end_data;
2631  newext2->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
2632  newext2->unique = ext->unique;
2633  newext2->ignore = FALSE;
2634  newext2->inserted = TRUE;
2635 
2636  if (ext->csum) {
2638  newext1->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(neda2->num_bytes * sizeof(UINT32) / Vcb->superblock.sector_size), ALLOC_TAG);
2639  if (!newext1->csum) {
2640  ERR("out of memory\n");
2642  ExFreePool(newext1);
2643  ExFreePool(newext2);
2644  goto end;
2645  }
2646 
2647  newext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(nedb2->num_bytes * sizeof(UINT32) / Vcb->superblock.sector_size), ALLOC_TAG);
2648  if (!newext2->csum) {
2649  ERR("out of memory\n");
2651  ExFreePool(newext1->csum);
2652  ExFreePool(newext1);
2653  ExFreePool(newext2);
2654  goto end;
2655  }
2656 
2657  RtlCopyMemory(newext1->csum, ext->csum, (ULONG)(neda2->num_bytes * sizeof(UINT32) / Vcb->superblock.sector_size));
2658  RtlCopyMemory(newext2->csum, &ext->csum[(end_data - ext->offset) / Vcb->superblock.sector_size],
2659  (ULONG)(nedb2->num_bytes * sizeof(UINT32) / Vcb->superblock.sector_size));
2660  } else {
2661  newext1->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2->size * sizeof(UINT32) / Vcb->superblock.sector_size), ALLOC_TAG);
2662  if (!newext1->csum) {
2663  ERR("out of memory\n");
2665  ExFreePool(newext1);
2666  ExFreePool(newext2);
2667  goto end;
2668  }
2669 
2670  newext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2->size * sizeof(UINT32) / Vcb->superblock.sector_size), ALLOC_TAG);
2671  if (!newext2->csum) {
2672  ERR("out of memory\n");
2674  ExFreePool(newext1->csum);
2675  ExFreePool(newext1);
2676  ExFreePool(newext2);
2677  goto end;
2678  }
2679 
2680  RtlCopyMemory(newext1->csum, ext->csum, (ULONG)(ed2->size * sizeof(UINT32) / Vcb->superblock.sector_size));
2681  RtlCopyMemory(newext2->csum, ext->csum, (ULONG)(ed2->size * sizeof(UINT32) / Vcb->superblock.sector_size));
2682  }
2683  } else {
2684  newext1->csum = NULL;
2685  newext2->csum = NULL;
2686  }
2687 
2688  InsertHeadList(&ext->list_entry, &newext1->list_entry);
2689  add_extent(fcb, &newext1->list_entry, newext2);
2690 
2692  }
2693  }
2694  }
2695  }
2696 
2697  le = le2;
2698  }
2699 
2701 
2702 end:
2705 
2706  return Status;
2707 }
void add_extent(_In_ fcb *fcb, _In_ LIST_ENTRY *prevextle, _In_ __drv_aliasesMem extent *newext)
Definition: write.c:2359
return TRUE
Definition: write.c:2909
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS Status
Definition: write.c:2825
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:58
UINT64 num_bytes
Definition: btrfs.h:344
EXTENT_DATA2 * ed2
Definition: write.c:2827
_In_ PIRP Irp
Definition: csq.h:116
UINT64 size
Definition: btrfs.h:342
chunk * get_chunk_from_address(device_extension *Vcb, UINT64 address)
Definition: write.c:93
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
UINT64 inode
Definition: btrfs_drv.h:262
LONG NTSTATUS
Definition: precomp.h:26
#define int3
Definition: btrfs_drv.h:1683
BOOL unique
Definition: btrfs_drv.h:204
GLintptr offset
Definition: glext.h:5920
LIST_ENTRY list_entry
Definition: btrfs_drv.h:209
GLuint GLuint end
Definition: gl.h:1545
UINT8 data[1]
Definition: btrfs.h:337
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:86
UINT64 decoded_size
Definition: btrfs.h:332
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:67
UINT8 encryption
Definition: btrfs.h:334
unsigned int UINT32
UINT16 datalen
Definition: btrfs_drv.h:203
UINT64 offset
Definition: btrfs_drv.h:202
UINT64 address
Definition: btrfs.h:341
UINT8 type
Definition: btrfs.h:336
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
BOOL extents_changed
Definition: btrfs_drv.h:292
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 * csum
Definition: btrfs_drv.h:207
UINT64 offset
Definition: btrfs.h:343
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
_In_ fcb _In_ chunk _In_ UINT64 start_data
Definition: write.c:2822
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
LIST_ENTRY extents
Definition: btrfs_drv.h:273
NTSTATUS update_changed_extent_ref(device_extension *Vcb, chunk *c, UINT64 address, UINT64 size, UINT64 root, UINT64 objid, UINT64 offset, INT32 count, BOOL no_csum, BOOL superseded, PIRP Irp)
Definition: extent-tree.c:1950
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
BOOL inode_item_changed
Definition: btrfs_drv.h:279
UINT64 st_blocks
Definition: btrfs.h:268
UINT16 encoding
Definition: btrfs.h:335
GLenum GLsizei len
Definition: glext.h:6722
if(!find_data_address_in_chunk(Vcb, c, length, &address)) return FALSE
Definition: typedefs.h:117
INODE_ITEM inode_item
Definition: btrfs_drv.h:264
UINT8 compression
Definition: btrfs.h:333
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
BOOL ignore
Definition: btrfs_drv.h:205
struct _root * subvol
Definition: btrfs_drv.h:261
Definition: list.h:27
UINT64 generation
Definition: btrfs.h:331
UINT64 flags
Definition: btrfs.h:275
mark_fcb_dirty(fcb)
EXTENT_DATA extent_data
Definition: btrfs_drv.h:211
unsigned int ULONG
Definition: retypes.h:1
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2822
ExFreePool(ed)
unsigned long long UINT64
static void remove_fcb_extent(fcb *fcb, extent *ext, LIST_ENTRY *rollback)
Definition: write.c:2771
return STATUS_SUCCESS
Definition: btrfs.c:2725
_In_ fcb _In_ chunk * c
Definition: write.c:2822
EXTENT_DATA * ed
Definition: write.c:2826
BOOL inserted
Definition: btrfs_drv.h:206

Referenced by allocate_cache_chunk(), delete_fileref(), do_write_file(), drop_chunk(), duplicate_extents(), extend_file(), load_stored_free_space_cache(), lzo_write_compressed_bit(), remove_free_space_inode(), 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  end,
BOOL  prealloc,
PIRP  Irp,
LIST_ENTRY rollback 
)

Definition at line 3327 of file write.c.

3327  {
3328  UINT64 oldalloc, newalloc;
3329  BOOL cur_inline;
3330  NTSTATUS Status;
3331 
3332  TRACE("(%p, %p, %x, %u)\n", fcb, fileref, end, prealloc);
3333 
3334  if (fcb->ads) {
3335  if (end > 0xffff)
3336  return STATUS_DISK_FULL;
3337 
3339  } else {
3340  extent* ext = NULL;
3341  LIST_ENTRY* le;
3342 
3343  le = fcb->extents.Blink;
3344  while (le != &fcb->extents) {
3346 
3347  if (!ext2->ignore) {
3348  ext = ext2;
3349  break;
3350  }
3351 
3352  le = le->Blink;
3353  }
3354 
3355  oldalloc = 0;
3356  if (ext) {
3357  EXTENT_DATA* ed = &ext->extent_data;
3359 
3360  oldalloc = ext->offset + (ed->type == EXTENT_TYPE_INLINE ? ed->decoded_size : ed2->num_bytes);
3361  cur_inline = ed->type == EXTENT_TYPE_INLINE;
3362 
3363  if (cur_inline && end > fcb->Vcb->options.max_inline) {
3364  UINT64 origlength, length;
3365  UINT8* data;
3366 
3367  TRACE("giving inline file proper extents\n");
3368 
3369  origlength = ed->decoded_size;
3370 
3371  cur_inline = FALSE;
3372 
3373  length = sector_align(origlength, fcb->Vcb->superblock.sector_size);
3374 
3376  if (!data) {
3377  ERR("could not allocate %llx bytes for data\n", length);
3379  }
3380 
3381  Status = read_file(fcb, data, 0, origlength, NULL, Irp);
3382  if (!NT_SUCCESS(Status)) {
3383  ERR("read_file returned %08x\n", Status);
3384  ExFreePool(data);
3385  return Status;
3386  }
3387 
3388  RtlZeroMemory(data + origlength, (ULONG)(length - origlength));
3389 
3391  if (!NT_SUCCESS(Status)) {
3392  ERR("excise_extents returned %08x\n", Status);
3393  ExFreePool(data);
3394  return Status;
3395  }
3396 
3398  if (!NT_SUCCESS(Status)) {
3399  ERR("do_write_file returned %08x\n", Status);
3400  ExFreePool(data);
3401  return Status;
3402  }
3403 
3404  oldalloc = ext->offset + length;
3405 
3406  ExFreePool(data);
3407  }
3408 
3409  if (cur_inline) {
3410  UINT16 edsize;
3411 
3412  if (end > oldalloc) {
3413  edsize = (UINT16)(offsetof(EXTENT_DATA, data[0]) + end - ext->offset);
3415 
3416  if (!ed) {
3417  ERR("out of memory\n");
3419  }
3420 
3421  ed->generation = fcb->Vcb->superblock.generation;
3422  ed->decoded_size = end - ext->offset;
3427 
3428  Status = read_file(fcb, ed->data, ext->offset, oldalloc, NULL, Irp);
3429  if (!NT_SUCCESS(Status)) {
3430  ERR("read_file returned %08x\n", Status);
3431  ExFreePool(ed);
3432  return Status;
3433  }
3434 
3435  RtlZeroMemory(ed->data + oldalloc - ext->offset, (ULONG)(end - oldalloc));
3436 
3438 
3439  Status = add_extent_to_fcb(fcb, ext->offset, ed, edsize, ext->unique, NULL, rollback);
3440  if (!NT_SUCCESS(Status)) {
3441  ERR("add_extent_to_fcb returned %08x\n", Status);
3442  ExFreePool(ed);
3443  return Status;
3444  }
3445 
3446  ExFreePool(ed);
3447 
3450  }
3451 
3452  TRACE("extending inline file (oldalloc = %llx, end = %llx)\n", oldalloc, end);
3453 
3455  TRACE("setting st_size to %llx\n", end);
3456 
3458 
3459  fcb->Header.AllocationSize.QuadPart = fcb->Header.FileSize.QuadPart = fcb->Header.ValidDataLength.QuadPart = end;
3460  } else {
3461  newalloc = sector_align(end, fcb->Vcb->superblock.sector_size);
3462 
3463  if (newalloc > oldalloc) {
3464  if (prealloc) {
3465  // FIXME - try and extend previous extent first
3466 
3467  Status = insert_prealloc_extent(fcb, oldalloc, newalloc - oldalloc, rollback);
3468 
3469  if (!NT_SUCCESS(Status)) {
3470  ERR("insert_prealloc_extent returned %08x\n", Status);
3471  return Status;
3472  }
3473  }
3474 
3476  }
3477 
3481 
3482  TRACE("setting st_size to %llx\n", end);
3483 
3484  TRACE("newalloc = %llx\n", newalloc);
3485 
3486  fcb->Header.AllocationSize.QuadPart = newalloc;
3487  fcb->Header.FileSize.QuadPart = fcb->Header.ValidDataLength.QuadPart = end;
3488  }
3489  } else {
3490  if (end > fcb->Vcb->options.max_inline) {
3491  newalloc = sector_align(end, fcb->Vcb->superblock.sector_size);
3492 
3493  if (prealloc) {
3494  Status = insert_prealloc_extent(fcb, 0, newalloc, rollback);
3495 
3496  if (!NT_SUCCESS(Status)) {
3497  ERR("insert_prealloc_extent returned %08x\n", Status);
3498  return Status;
3499  }
3500  }
3501 
3505 
3507  TRACE("setting st_size to %llx\n", end);
3508 
3509  TRACE("newalloc = %llx\n", newalloc);
3510 
3511  fcb->Header.AllocationSize.QuadPart = newalloc;
3512  fcb->Header.FileSize.QuadPart = fcb->Header.ValidDataLength.QuadPart = end;
3513  } else {
3514  EXTENT_DATA* ed;
3515  UINT16 edsize;
3516 
3517  edsize = (UINT16)(offsetof(EXTENT_DATA, data[0]) + end);
3519 
3520  if (!ed) {
3521  ERR("out of memory\n");
3523  }
3524 
3525  ed->generation = fcb->Vcb->superblock.generation;
3526  ed->decoded_size = end;
3531 
3533 
3535  if (!NT_SUCCESS(Status)) {
3536  ERR("add_extent_to_fcb returned %08x\n", Status);
3537  ExFreePool(ed);
3538  return Status;
3539  }
3540 
3541  ExFreePool(ed);
3542 
3546 
3548  TRACE("setting st_size to %llx\n", end);
3549 
3551 
3552  fcb->Header.AllocationSize.QuadPart = fcb->Header.FileSize.QuadPart = fcb->Header.ValidDataLength.QuadPart = end;
3553  }
3554  }
3555  }
3556 
3557  return STATUS_SUCCESS;
3558 }
return TRUE
Definition: write.c:2909
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS Status
Definition: write.c:2825
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:58
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 length
Definition: write.c:2822
UINT64 num_bytes
Definition: btrfs.h:344
EXTENT_DATA2 * ed2
Definition: write.c:2827
_In_ PIRP Irp
Definition: csq.h:116
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
NTSTATUS stream_set_end_of_file_information(device_extension *Vcb, UINT16 end, fcb *fcb, file_ref *fileref, BOOL advance_only)
Definition: fileinfo.c:1936
LONG NTSTATUS
Definition: precomp.h:26
GLuint GLuint end
Definition: gl.h:1545
TRACE("(%p, (%llx, %llx), %llx, %llx, %llx, %u, %p, %p)\n", Vcb, fcb->subvol->id, fcb->inode, c->offset, start_data, length, prealloc, data, rollback)
UINT8 data[1]
Definition: btrfs.h:337
#define ALLOC_TAG
Definition: btrfs_drv.h:86
UINT64 decoded_size
Definition: btrfs.h:332
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:67
NTSTATUS do_write_file(fcb *fcb, UINT64 start, UINT64 end_data, void *data, PIRP Irp, BOOL file_write, UINT32 irp_offset, LIST_ENTRY *rollback)
Definition: write.c:3947
UINT8 encryption
Definition: btrfs.h:334
unsigned int BOOL
Definition: ntddk_ex.h:94
UINT8 type
Definition: btrfs.h:336
#define BTRFS_ENCODING_NONE
Definition: btrfs.h:65
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
BOOL extents_changed
Definition: btrfs_drv.h:292
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:256
#define BTRFS_ENCRYPTION_NONE
Definition: btrfs.h:63
NTSTATUS add_extent_to_fcb(_In_ fcb *fcb, _In_ UINT64 offset, _In_reads_bytes_(edsize) EXTENT_DATA *ed, _In_ UINT16 edsize, _In_ BOOL unique, _In_opt_ _When_(return >=0, __drv_aliasesMem) UINT32 *csum, _In_ LIST_ENTRY *rollback)
Definition: write.c:2728
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
LIST_ENTRY extents
Definition: btrfs_drv.h:273
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
NTSTATUS read_file(fcb *fcb, UINT8 *data, UINT64 start, UINT64 length, ULONG *pbr, PIRP Irp)
Definition: read.c:2737
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
static const BYTE ext2[]
Definition: encode.c:2699
BOOL inode_item_changed
Definition: btrfs_drv.h:279
UINT64 st_blocks
Definition: btrfs.h:268
BOOL ads
Definition: btrfs_drv.h:299
UINT16 encoding
Definition: btrfs.h:335
Definition: typedefs.h:117
INODE_ITEM inode_item
Definition: btrfs_drv.h:264
UINT8 compression
Definition: btrfs.h:333
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void * data
Definition: write.c:2822
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
UINT64 st_size
Definition: btrfs.h:267
static NTSTATUS insert_prealloc_extent(fcb *fcb, UINT64 start, UINT64 length, LIST_ENTRY *rollback)
Definition: write.c:3060
unsigned short UINT16
Definition: list.h:27
UINT64 generation
Definition: btrfs.h:331
mark_fcb_dirty(fcb)
UINT16 edsize
Definition: write.c:2828
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2822
ExFreePool(ed)
NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, UINT64 start_data, UINT64 end_data, PIRP Irp, LIST_ENTRY *rollback)
Definition: write.c:2376
unsigned long long UINT64
static void remove_fcb_extent(fcb *fcb, extent *ext, LIST_ENTRY *rollback)
Definition: write.c:2771
return STATUS_SUCCESS
Definition: btrfs.c:2725
unsigned char UINT8
EXTENT_DATA * ed
Definition: write.c:2826
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
struct _device_extension * Vcb
Definition: btrfs_drv.h:260
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL prealloc
Definition: write.c:2822

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

◆ find_new_chunk_address()

static UINT64 find_new_chunk_address ( device_extension Vcb,
UINT64  size 
)
static

Definition at line 120 of file write.c.

120  {
121  UINT64 lastaddr;
122  LIST_ENTRY* le;
123 
124  lastaddr = 0xc00000;
125 
126  le = Vcb->chunks.Flink;
127  while (le != &Vcb->chunks) {
129 
130  if (c->offset >= lastaddr + size)
131  return lastaddr;
132 
133  lastaddr = c->offset + c->chunk_item->size;
134 
135  le = le->Flink;
136  }
137 
138  return lastaddr;
139 }
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
Definition: list.h:27
unsigned long long UINT64

Referenced by alloc_chunk().

◆ find_new_dup_stripes()

static BOOL find_new_dup_stripes ( device_extension Vcb,
stripe stripes,
UINT64  max_stripe_size,
BOOL  full_size 
)
static

Definition at line 141 of file write.c.

141  {
142  UINT64 devusage = 0xffffffffffffffff;
143  space *devdh1 = NULL, *devdh2 = NULL;
144  LIST_ENTRY* le;
145  device* dev2 = NULL;
146 
147  le = Vcb->devices.Flink;
148 
149  while (le != &Vcb->devices) {
151 
152  if (!dev->readonly && !dev->reloc && dev->devobj) {
153  UINT64 usage = (dev->devitem.bytes_used * 4096) / dev->devitem.num_bytes;
154 
155  // favour devices which have been used the least
156  if (usage < devusage) {
157  if (!IsListEmpty(&dev->space)) {
158  LIST_ENTRY* le2;
159  space *dh1 = NULL, *dh2 = NULL;
160 
161  le2 = dev->space.Flink;
162  while (le2 != &dev->space) {
164 
165  if (dh->size >= max_stripe_size && (!dh1 || !dh2 || dh->size < dh1->size)) {
166  dh2 = dh1;
167  dh1 = dh;
168  }
169 
170  le2 = le2->Flink;
171  }
172 
173  if (dh1 && (dh2 || dh1->size >= 2 * max_stripe_size)) {
174  dev2 = dev;
175  devusage = usage;
176  devdh1 = dh1;
177  devdh2 = dh2 ? dh2 : dh1;
178  }
179  }
180  }
181  }
182 
183  le = le->Flink;
184  }
185 
186  if (!devdh1) {
187  UINT64 size = 0;
188 
189  // Can't find hole of at least max_stripe_size; look for the largest one we can find
190 
191  if (full_size)
192  return FALSE;
193 
194  le = Vcb->devices.Flink;
195  while (le != &Vcb->devices) {
197 
198  if (!dev->readonly && !dev->reloc) {
199  if (!IsListEmpty(&dev->space)) {
200  LIST_ENTRY* le2;
201  space *dh1 = NULL, *dh2 = NULL;
202 
203  le2 = dev->space.Flink;
204  while (le2 != &dev->space) {
206 
207  if (!dh1 || !dh2 || dh->size < dh1->size) {
208  dh2 = dh1;
209  dh1 = dh;
210  }
211 
212  le2 = le2->Flink;
213  }
214 
215  if (dh1) {
216  UINT64 devsize;
217 
218  if (dh2)
219  devsize = max(dh1->size / 2, min(dh1->size, dh2->size));
220  else
221  devsize = dh1->size / 2;
222 
223  if (devsize > size) {
224  dev2 = dev;
225  devdh1 = dh1;
226 
227  if (dh2 && min(dh1->size, dh2->size) > dh1->size / 2)
228  devdh2 = dh2;
229  else
230  devdh2 = dh1;
231 
232  size = devsize;
233  }
234  }
235  }
236  }
237 
238  le = le->Flink;
239  }
240 
241  if (!devdh1)
242  return FALSE;
243  }
244 
245  stripes[0].device = stripes[1].device = dev2;
246  stripes[0].dh = devdh1;
247  stripes[1].dh = devdh2;
248 
249  return TRUE;
250 }
return TRUE
Definition: write.c:2909
#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
UINT64 size
Definition: btrfs_drv.h:478
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
if(!find_data_address_in_chunk(Vcb, c, length, &address)) return FALSE
Definition: typedefs.h:117
device * device
Definition: write.c:117
space * dh
Definition: write.c:116
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
unsigned long long UINT64

Referenced by alloc_chunk().

◆ find_new_stripe()

static BOOL find_new_stripe ( device_extension Vcb,
stripe stripes,
UINT16  i,
UINT64  max_stripe_size,
BOOL  allow_missing,
BOOL  full_size 
)
static

Definition at line 252 of file write.c.

252  {
253  UINT64 k, devusage = 0xffffffffffffffff;
254  space* devdh = NULL;
255  LIST_ENTRY* le;
256  device* dev2 = NULL;
257 
258  le = Vcb->devices.Flink;
259  while (le != &Vcb->devices) {
261  UINT64 usage;
262  BOOL skip = FALSE;
263 
264  if (dev->readonly || dev->reloc || (!dev->devobj && !allow_missing)) {
265  le = le->Flink;
266  continue;
267  }
268 
269  // skip this device if it already has a stripe
270  if (i > 0) {
271  for (k = 0; k < i; k++) {
272  if (stripes[k].device == dev) {
273  skip = TRUE;
274  break;
275  }
276  }
277  }
278 
279  if (!skip) {
280  usage = (dev->devitem.bytes_used * 4096) / dev->devitem.num_bytes;
281 
282  // favour devices which have been used the least
283  if (usage < devusage) {
284  if (!IsListEmpty(&dev->space)) {
285  LIST_ENTRY* le2;
286 
287  le2 = dev->space.Flink;
288  while (le2 != &dev->space) {
290 
291  if ((dev2 != dev && dh->size >= max_stripe_size) ||
292  (dev2 == dev && dh->size >= max_stripe_size && dh->size < devdh->size)
293  ) {
294  devdh = dh;
295  dev2 = dev;
296  devusage = usage;
297  }
298 
299  le2 = le2->Flink;
300  }
301  }
302  }
303  }
304 
305  le = le->Flink;
306  }
307 
308  if (!devdh) {
309  // Can't find hole of at least max_stripe_size; look for the largest one we can find
310 
311  if (full_size)
312  return FALSE;
313 
314  le = Vcb->devices.Flink;
315  while (le != &Vcb->devices) {
317  BOOL skip = FALSE;
318 
319  if (dev->readonly || dev->reloc || (!dev->devobj && !allow_missing)) {
320  le = le->Flink;
321  continue;
322  }
323 
324  // skip this device if it already has a stripe
325  if (i > 0) {
326  for (k = 0; k < i; k++) {
327  if (stripes[k].device == dev) {
328  skip = TRUE;
329  break;
330  }
331  }
332  }
333 
334  if (!skip) {
335  if (!IsListEmpty(&dev->space)) {
336  LIST_ENTRY* le2;
337 
338  le2 = dev->space.Flink;
339  while (le2 != &dev->space) {
341 
342  if (!devdh || devdh->size < dh->size) {
343  devdh = dh;
344  dev2 = dev;
345  }
346 
347  le2 = le2->Flink;
348  }
349  }
350  }
351 
352  le = le->Flink;
353  }
354 
355  if (!devdh)
356  return FALSE;
357  }
358 
359  stripes[i].dh = devdh;
360  stripes[i].device = dev2;
361 
362  return TRUE;
363 }
return TRUE
Definition: write.c:2909
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
static int dev
Definition: mkdosfs.c:536
UINT64 size
Definition: btrfs_drv.h:478
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
unsigned int BOOL
Definition: ntddk_ex.h:94
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
if(!find_data_address_in_chunk(Vcb, c, length, &address)) return FALSE
Definition: typedefs.h:117
device * device
Definition: write.c:117
space * dh
Definition: write.c:116
Definition: list.h:27
#define skip(...)
unsigned long long UINT64
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 2299 of file write.c.

2299  {
2300  LIST_ENTRY* le;
2301  PMDL last_mdl = NULL;
2302 
2303  if (wtc->parity1_mdl) {
2304  if (wtc->parity1_mdl->MdlFlags & MDL_PAGES_LOCKED)
2305  MmUnlockPages(wtc->parity1_mdl);
2306 
2307  IoFreeMdl(wtc->parity1_mdl);
2308  }
2309 
2310  if (wtc->parity2_mdl) {
2311  if (wtc->parity2_mdl->MdlFlags & MDL_PAGES_LOCKED)
2312  MmUnlockPages(wtc->parity2_mdl);
2313 
2314  IoFreeMdl(wtc->parity2_mdl);
2315  }
2316 
2317  if (wtc->mdl) {
2318  if (wtc->mdl->MdlFlags & MDL_PAGES_LOCKED)
2319  MmUnlockPages(wtc->mdl);
2320 
2321  IoFreeMdl(wtc->mdl);
2322  }
2323 
2324  if (wtc->parity1)
2325  ExFreePool(wtc->parity1);
2326 
2327  if (wtc->parity2)
2328  ExFreePool(wtc->parity2);
2329 
2330  if (wtc->scratch)
2331  ExFreePool(wtc->scratch);
2332 
2333  le = wtc->stripes.Flink;
2334  while (le != &wtc->stripes) {
2336 
2337  if (stripe->mdl && stripe->mdl != last_mdl) {
2338  if (stripe->mdl->MdlFlags & MDL_PAGES_LOCKED)
2339  MmUnlockPages(stripe->mdl);
2340 
2341  IoFreeMdl(stripe->mdl);
2342  }
2343 
2344  last_mdl = stripe->mdl;
2345 
2346  if (stripe->Irp)
2347  IoFreeIrp(stripe->Irp);
2348 
2349  le = le->Flink;
2350  }
2351 
2352  while (!IsListEmpty(&wtc->stripes)) {
2354 
2355  ExFreePool(stripe);
2356  }
2357 }
Definition: write.c:115
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
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
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
Definition: typedefs.h:117
Definition: list.h:27
LIST_ENTRY stripes
Definition: btrfs_drv.h:890
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
ExFreePool(ed)

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

Definition at line 93 of file write.c.

93  {
94  LIST_ENTRY* le2;
95 
96  ExAcquireResourceSharedLite(&Vcb->chunk_lock, TRUE);
97 
98  le2 = Vcb->chunks.Flink;
99  while (le2 != &Vcb->chunks) {
101 
102  if (address >= c->offset && address < c->offset + c->chunk_item->size) {
103  ExReleaseResourceLite(&Vcb->chunk_lock);
104  return c;
105  }
106 
107  le2 = le2->Flink;
108  }
109 
110  ExReleaseResourceLite(&Vcb->chunk_lock);
111 
112  return NULL;
113 }
return TRUE
Definition: write.c:2909
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:2822

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  address,
UINT64  length,
UINT64 lockaddr,
UINT64 locklen 
)

Definition at line 2154 of file write.c.

2154  {
2155  UINT64 startoff, endoff;
2156  UINT16 startoffstripe, endoffstripe, datastripes;
2157 
2158  datastripes = c->chunk_item->num_stripes - (c->chunk_item->type & BLOCK_FLAG_RAID5 ? 1 : 2);
2159 
2160  get_raid0_offset(address - c->offset, c->chunk_item->stripe_length, datastripes, &startoff, &startoffstripe);
2161  get_raid0_offset(address + length - c->offset - 1, c->chunk_item->stripe_length, datastripes, &endoff, &endoffstripe);
2162 
2163  startoff -= startoff % c->chunk_item->stripe_length;
2164  endoff = sector_align(endoff, c->chunk_item->stripe_length);
2165 
2166  *lockaddr = c->offset + (startoff * datastripes);
2167  *locklen = (endoff - startoff) * datastripes;
2168 }
_Post_satisfies_ static stripe __inline void get_raid0_offset(_In_ UINT64 off, _In_ UINT64 stripe_length, _In_ UINT16 num_stripes, _Out_ UINT64 *stripeoff, _Out_ UINT16 *stripe)
Definition: btrfs_drv.h:976
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
const GLubyte * c
Definition: glext.h:8905
GLuint address
Definition: glext.h:9393
unsigned short UINT16
#define BLOCK_FLAG_RAID5
Definition: shellext.h:77
unsigned long long UINT64
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 2838 of file write.c.

2838  {
2839  ERR("out of memory\n");
2840  return FALSE;
2841  }
#define ERR(fmt,...)
Definition: debug.h:109

◆ if() [3/5]

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

Definition at line 2856 of file write.c.

2856  {
2857  ULONG sl = (ULONG)(length / Vcb->superblock.sector_size);
2858 
2860  if (!csum) {
2861  ERR("out of memory\n");
2862  ExFreePool(ed);
2863  return FALSE;
2864  }
2865 
2866  Status = calc_csum(Vcb, data, sl, csum);
2867  if (!NT_SUCCESS(Status)) {
2868  ERR("calc_csum returned %08x\n", Status);
2869  ExFreePool(csum);
2870  ExFreePool(ed);
2871  return FALSE;
2872  }
2873  }
#define ALLOC_TAG
Definition: btrfs_drv.h:86
NTSTATUS calc_csum(_In_ device_extension *Vcb, _In_reads_bytes_(sectors *Vcb->superblock.sector_size) UINT8 *data, _In_ UINT32 sectors, _Out_writes_bytes_(sectors *sizeof(UINT32)) UINT32 *csum)
Definition: write.c:2790
unsigned int UINT32
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define Vcb
Definition: cdprocs.h:1425
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
Definition: fs.h:216
unsigned int ULONG
Definition: retypes.h:1
ExFreePool(ed)
EXTENT_DATA * ed
Definition: write.c:2826

◆ if() [4/5]

if ( NT_SUCCESSStatus)

Definition at line 2876 of file write.c.

2876  {
2877  ERR("add_extent_to_fcb returned %08x\n", Status);
2878  if (csum) ExFreePool(csum);
2879  ExFreePool(ed);
2880  return FALSE;
2881  }
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: fs.h:216
ExFreePool(ed)
EXTENT_DATA * ed
Definition: write.c:2826

◆ if() [5/5]

if ( data  )

Definition at line 2902 of file write.c.

2902  {
2905  if (!NT_SUCCESS(Status))
2906  ERR("write_data_complete returned %08x\n", Status);
2907  }
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ UINT8 _In_ UINT64 _In_ BOOL file_write
Definition: write.c:2822
_In_ PIRP Irp
Definition: csq.h:116
#define FSRTL_FLAG2_IS_PAGING_FILE
Definition: fsrtltypes.h:57
NTSTATUS write_data_complete(device_extension *Vcb, UINT64 address, void *data, UINT32 length, PIRP Irp, chunk *c, BOOL file_write, UINT64 irp_offset, ULONG priority)
Definition: write.c:2170
unsigned int UINT32
smooth NULL
Definition: ftsmooth.c:416
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:256
#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
_In_ fcb _In_ chunk _In_ UINT64 _In_ UINT64 _In_ BOOL _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ UINT8 _In_ UINT64 _In_ BOOL _In_ UINT64 irp_offset
Definition: write.c:2823

◆ insert_chunk_fragmented()

static NTSTATUS insert_chunk_fragmented ( fcb fcb,
UINT64  start,