ReactOS  0.4.15-dev-1070-ge1a01de
write.c File Reference
#include "btrfs_drv.h"
Include dependency graph for write.c:

Go to the source code of this file.

Classes

struct  write_stripe
 
struct  stripe
 
struct  log_stripe
 

Functions

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

Variables

_In_ fcbfcb
 
_In_ fcb _In_ chunkc
 
_In_ fcb _In_ chunk _In_ uint64_t start_data
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t length
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool prealloc
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ voiddata
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP Irp
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRYrollback
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t compression = compression
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t decoded_size = decoded_size
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool file_write
 
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool _In_ uint64_t irp_offset
 
NTSTATUS Status = add_extent_to_fcb(fcb, start_data, ed, edsize, true, csum, rollback)
 
EXTENT_DATAed = ExAllocatePoolWithTag(PagedPool, edsize, ALLOC_TAG)
 
EXTENT_DATA2ed2 = (EXTENT_DATA2*)ed->data
 
uint16_t edsize = (uint16_t)(offsetof(EXTENT_DATA, data[0]) + sizeof(EXTENT_DATA2))
 
voidcsum = 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 4617 of file write.c.

4619  {
4620  NTSTATUS Status;
4621  bool top_level;
4623  device_extension* Vcb = DeviceObject->DeviceExtension;
4625  fcb* fcb = FileObject ? FileObject->FsContext : NULL;
4626  ccb* ccb = FileObject ? FileObject->FsContext2 : NULL;
4627  bool wait = FileObject ? IoIsOperationSynchronous(Irp) : true;
4628 
4630 
4631  top_level = is_top_level(Irp);
4632 
4633  if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
4635  goto exit;
4636  } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
4638  goto end;
4639  }
4640 
4641  if (!fcb) {
4642  ERR("fcb was NULL\n");
4644  goto end;
4645  }
4646 
4647  if (!ccb) {
4648  ERR("ccb was NULL\n");
4650  goto end;
4651  }
4652 
4653  if (Irp->RequestorMode == UserMode && !(ccb->access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
4654  WARN("insufficient permissions\n");
4656  goto end;
4657  }
4658 
4659  if (fcb == Vcb->volume_fcb) {
4660  if (!Vcb->locked || Vcb->locked_fileobj != FileObject) {
4661  ERR("trying to write to volume when not locked, or locked with another FileObject\n");
4663  goto end;
4664  }
4665 
4666  TRACE("writing directly to volume\n");
4667 
4669 
4670  Status = IoCallDriver(Vcb->Vpb->RealDevice, Irp);
4671  goto exit;
4672  }
4673 
4674  if (is_subvol_readonly(fcb->subvol, Irp)) {
4676  goto end;
4677  }
4678 
4679  if (Vcb->readonly) {
4681  goto end;
4682  }
4683 
4684  _SEH2_TRY {
4686  CcMdlWriteComplete(IrpSp->FileObject, &IrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress);
4687 
4688  Irp->MdlAddress = NULL;
4690  } else {
4691  if (!(Irp->Flags & IRP_PAGING_IO))
4693 
4694  // Don't offload jobs when doing paging IO - otherwise this can lead to
4695  // deadlocks in CcCopyWrite.
4696  if (Irp->Flags & IRP_PAGING_IO)
4697  wait = true;
4698 
4699  Status = write_file(Vcb, Irp, wait, false);
4700  }
4703  } _SEH2_END;
4704 
4705 end:
4706  Irp->IoStatus.Status = Status;
4707 
4708  TRACE("wrote %Iu bytes\n", Irp->IoStatus.Information);
4709 
4710  if (Status != STATUS_PENDING)
4712  else {
4714 
4715  if (!add_thread_job(Vcb, Irp))
4716  Status = do_write_job(Vcb, Irp);
4717  }
4718 
4719 exit:
4720  if (top_level)
4722 
4723  TRACE("returning %08lx\n", Status);
4724 
4726 
4727  return Status;
4728 }
NTSTATUS write_file(device_extension *Vcb, PIRP Irp, bool wait, bool deferred_write)
Definition: write.c:4545
#define FsRtlEnterFileSystem
NTSTATUS Status
Definition: write.c:2803
#define FsRtlExitFileSystem
return true
Definition: write.c:2881
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
#define VCB_TYPE_FS
Definition: btrfs_drv.h:695
GLuint GLuint end
Definition: gl.h:1545
ACCESS_MASK access
Definition: btrfs_drv.h:398
BOOLEAN NTAPI IoIsOperationSynchronous(IN PIRP Irp)
Definition: irp.c:1882
NTSTATUS vol_write(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: volume.c:225
NTSTATUS do_write_job(device_extension *Vcb, PIRP Irp)
Definition: worker-thread.c:68
#define FILE_APPEND_DATA
Definition: nt_native.h:634
VOID NTAPI CcMdlWriteComplete(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain)
Definition: mdlsup.c:102
bool is_top_level(_In_ PIRP Irp)
Definition: btrfs.c:279
_SEH2_TRY
Definition: create.c:4226
#define IRP_MN_COMPLETE
Definition: iotypes.h:4399
static __inline bool is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1041
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
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:588
#define FILE_WRITE_DATA
Definition: nt_native.h:631
bool add_thread_job(device_extension *Vcb, PIRP Irp)
#define STATUS_PENDING
Definition: ntstatus.h:82
#define VCB_TYPE_VOLUME
Definition: btrfs_drv.h:697
#define Vcb
Definition: cdprocs.h:1415
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
* PFILE_OBJECT
Definition: iotypes.h:1978
Status
Definition: gdiplustypes.h:24
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
#define ERR(fmt,...)
Definition: debug.h:110
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
PFILE_OBJECT FileObject
Definition: iotypes.h:3148
_SEH2_END
Definition: create.c:4400
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
struct _root * subvol
Definition: btrfs_drv.h:299
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define IRP_PAGING_IO
static __inline POPLOCK fcb_oplock(fcb *fcb)
Definition: btrfs_drv.h:1683
#define IO_NO_INCREMENT
Definition: iotypes.h:581
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
NTSTATUS NTAPI FsRtlCheckOplock(IN POPLOCK Oplock, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
Definition: oplock.c:1172
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
void exit(int exitcode)
Definition: _exit.c:33
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
return STATUS_SUCCESS
Definition: btrfs.c:3014
IoMarkIrpPending(Irp)
TRACE("(%p, (%I64x, %I64x), %I64x, %I64x, %I64x, %u, %p, %p)\n", Vcb, fcb->subvol->id, fcb->inode, c->offset, start_data, length, prealloc, data, rollback)

◆ _Function_class_()

_Function_class_ ( IO_COMPLETION_ROUTINE  )

Definition at line 28 of file write.c.

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

◆ _Releases_lock_()

_Releases_lock_ ( c->  lock)

◆ _Requires_lock_held_()

_Requires_lock_held_ ( c->  lock)
pure virtual

◆ add_changed_extent_ref()

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

◆ add_extent()

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

Definition at line 2367 of file write.c.

2367  {
2368  LIST_ENTRY* le = prevextle->Flink;
2369 
2370  while (le != &fcb->extents) {
2372 
2373  if (ext->offset >= newext->offset) {
2374  InsertHeadList(ext->list_entry.Blink, &newext->list_entry);
2375  return;
2376  }
2377 
2378  le = le->Flink;
2379  }
2380 
2381  InsertTailList(&fcb->extents, &newext->list_entry);
2382 }
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:121
LIST_ENTRY extents
Definition: btrfs_drv.h:311
Definition: typedefs.h:119
Definition: list.h:27

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

◆ add_extent_to_fcb()

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

Definition at line 2736 of file write.c.

2737  {
2738  extent* ext;
2739  LIST_ENTRY* le;
2740 
2742  if (!ext) {
2743  ERR("out of memory\n");
2745  }
2746 
2747  ext->offset = offset;
2748  ext->datalen = edsize;
2749  ext->unique = unique;
2750  ext->ignore = false;
2751  ext->inserted = true;
2752  ext->csum = csum;
2753 
2754  RtlCopyMemory(&ext->extent_data, ed, edsize);
2755 
2756  le = fcb->extents.Flink;
2757  while (le != &fcb->extents) {
2758  extent* oldext = CONTAINING_RECORD(le, extent, list_entry);
2759 
2760  if (oldext->offset >= offset) {
2761  InsertHeadList(le->Blink, &ext->list_entry);
2762  goto end;
2763  }
2764 
2765  le = le->Flink;
2766  }
2767 
2768  InsertTailList(&fcb->extents, &ext->list_entry);
2769 
2770 end:
2772 
2773  return STATUS_SUCCESS;
2774 }
void add_insert_extent_rollback(LIST_ENTRY *rollback, fcb *fcb, extent *ext)
Definition: write.c:2717
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:122
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
GLintptr offset
Definition: glext.h:5920
GLuint GLuint end
Definition: gl.h:1545
#define InsertTailList(ListHead, Entry)
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint64_t offset
Definition: btrfs_drv.h:239
#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:121
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2800
LIST_ENTRY extents
Definition: btrfs_drv.h:311
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Definition: typedefs.h:119
uint16_t edsize
Definition: write.c:2806
#define ERR(fmt,...)
Definition: debug.h:110
ed2 offset
Definition: write.c:2831
Definition: list.h:27
_ForwardIter unique(_ForwardIter __first, _ForwardIter __last)
Definition: _algo.h:298
return STATUS_SUCCESS
Definition: btrfs.c:3014
EXTENT_DATA * ed
Definition: write.c:2804
void * csum
Definition: write.c:2807

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

◆ add_insert_extent_rollback()

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

Definition at line 2717 of file write.c.

2717  {
2718  rollback_extent* re;
2719 
2721  if (!re) {
2722  ERR("out of memory\n");
2723  return;
2724  }
2725 
2726  re->fcb = fcb;
2727  re->ext = ext;
2728 
2730 }
#define ALLOC_TAG
Definition: btrfs_drv.h:91
char ext[3]
Definition: mkdosfs.c:358
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2800
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define ERR(fmt,...)
Definition: debug.h:110
extent * ext
Definition: btrfs_drv.h:1264
_In_ fcb * fcb
Definition: write.c:2800
void add_rollback(_In_ LIST_ENTRY *rollback, _In_ enum rollback_type type, _In_ __drv_aliasesMem void *ptr)
Definition: treefuncs.c:837

Referenced by add_extent_to_fcb(), and do_write_file_prealloc().

◆ add_partial_stripe()

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

Definition at line 974 of file write.c.

974  {
976  LIST_ENTRY* le;
977  partial_stripe* ps;
978  uint64_t stripe_addr;
979  uint16_t num_data_stripes;
980 
981  num_data_stripes = c->chunk_item->num_stripes - (c->chunk_item->type & BLOCK_FLAG_RAID5 ? 1 : 2);
982  stripe_addr = address - ((address - c->offset) % (num_data_stripes * c->chunk_item->stripe_length));
983 
984  ExAcquireResourceExclusiveLite(&c->partial_stripes_lock, true);
985 
986  le = c->partial_stripes.Flink;
987  while (le != &c->partial_stripes) {
989 
990  if (ps->address == stripe_addr) {
991  // update existing entry
992 
993  RtlCopyMemory(ps->data + address - stripe_addr, data, length);
994  RtlClearBits(&ps->bmp, (ULONG)((address - stripe_addr) / Vcb->superblock.sector_size), length / Vcb->superblock.sector_size);
995 
996  // if now filled, flush
997  if (RtlAreBitsClear(&ps->bmp, 0, (ULONG)((num_data_stripes * c->chunk_item->stripe_length) / Vcb->superblock.sector_size))) {
999  if (!NT_SUCCESS(Status)) {
1000  ERR("flush_partial_stripe returned %08lx\n", Status);
1001  goto end;
1002  }
1003 
1005 
1006  if (ps->bmparr)
1007  ExFreePool(ps->bmparr);
1008 
1009  ExFreePool(ps);
1010  }
1011 
1013  goto end;
1014  } else if (ps->address > stripe_addr)
1015  break;
1016 
1017  le = le->Flink;
1018  }
1019 
1020  // add new entry
1021 
1022  ps = ExAllocatePoolWithTag(NonPagedPool, offsetof(partial_stripe, data[0]) + (ULONG)(num_data_stripes * c->chunk_item->stripe_length), ALLOC_TAG);
1023  if (!ps) {
1024  ERR("out of memory\n");
1026  goto end;
1027  }
1028 
1029  ps->bmplen = (ULONG)(num_data_stripes * c->chunk_item->stripe_length) / Vcb->superblock.sector_size;
1030 
1031  ps->address = stripe_addr;
1032  ps->bmparr = ExAllocatePoolWithTag(NonPagedPool, (size_t)sector_align(((ps->bmplen / 8) + 1), sizeof(ULONG)), ALLOC_TAG);
1033  if (!ps->bmparr) {
1034  ERR("out of memory\n");
1035  ExFreePool(ps);
1037  goto end;
1038  }
1039 
1040  RtlInitializeBitMap(&ps->bmp, ps->bmparr, ps->bmplen);
1041  RtlSetAllBits(&ps->bmp);
1042 
1043  RtlCopyMemory(ps->data + address - stripe_addr, data, length);
1044  RtlClearBits(&ps->bmp, (ULONG)((address - stripe_addr) / Vcb->superblock.sector_size), length / Vcb->superblock.sector_size);
1045 
1046  InsertHeadList(le->Blink, &ps->list_entry);
1047 
1049 
1050 end:
1051  ExReleaseResourceLite(&c->partial_stripes_lock);
1052 
1053  return Status;
1054 }
ULONG * bmparr
Definition: btrfs_drv.h:563
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS Status
Definition: write.c:2803
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS flush_partial_stripe(device_extension *Vcb, chunk *c, partial_stripe *ps)
Definition: flushthread.c:5863
uint64_t address
Definition: btrfs_drv.h:562
GLuint GLuint end
Definition: gl.h:1545
RTL_BITMAP bmp
Definition: btrfs_drv.h:565
unsigned short int uint16_t
Definition: acefiex.h:54
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define ALLOC_TAG
Definition: btrfs_drv.h:91
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
LIST_ENTRY list_entry
Definition: btrfs_drv.h:566
#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:121
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define Vcb
Definition: cdprocs.h:1415
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
Status
Definition: gdiplustypes.h:24
uint8_t data[1]
Definition: btrfs_drv.h:567
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
UINT64 uint64_t
Definition: types.h:77
Definition: list.h:27
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI BOOLEAN WINAPI RtlAreBitsClear(PCRTL_BITMAP, ULONG, ULONG)
ExFreePool(ed)
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
return STATUS_SUCCESS
Definition: btrfs.c:3014
static uint64_t __inline sector_align(uint64_t n, uint64_t a)

Referenced by prepare_raid5_write(), and prepare_raid6_write().

◆ alloc_chunk()

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

Definition at line 361 of file write.c.

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

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

◆ do_write_file()

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

Definition at line 3891 of file write.c.

3891  {
3892  NTSTATUS Status;
3893  LIST_ENTRY *le, *le2;
3894  uint64_t written = 0, length = end_data - start;
3895  uint64_t last_cow_start;
3897 #ifdef DEBUG_PARANOID
3898  uint64_t last_off;
3899 #endif
3900  bool extents_changed = false;
3901 
3902  last_cow_start = 0;
3903 
3904  le = fcb->extents.Flink;
3905  while (le != &fcb->extents) {
3907 
3908  le2 = le->Flink;
3909 
3910  if (!ext->ignore) {
3911  EXTENT_DATA* ed = &ext->extent_data;
3913  uint64_t len;
3914 
3916 
3917  if (ext->offset + len <= start)
3918  goto nextitem;
3919 
3920  if (ext->offset > start + written + length)
3921  break;
3922 
3924  if (max(last_cow_start, start + written) < ext->offset) {
3925  uint64_t start_write = max(last_cow_start, start + written);
3926 
3927  extents_changed = true;
3928 
3929  Status = excise_extents(fcb->Vcb, fcb, start_write, ext->offset, Irp, rollback);
3930  if (!NT_SUCCESS(Status)) {
3931  ERR("excise_extents returned %08lx\n", Status);
3932  return Status;
3933  }
3934 
3935  Status = insert_extent(fcb->Vcb, fcb, start_write, ext->offset - start_write, (uint8_t*)data + written, Irp, file_write, irp_offset + written, rollback);
3936  if (!NT_SUCCESS(Status)) {
3937  ERR("insert_extent returned %08lx\n", Status);
3938  return Status;
3939  }
3940 
3941  written += ext->offset - start_write;
3942  length -= ext->offset - start_write;
3943 
3944  if (length == 0)
3945  break;
3946  }
3947 
3948  if (ed->type == EXTENT_TYPE_REGULAR) {
3949  uint64_t writeaddr = ed2->address + ed2->offset + start + written - ext->offset;
3950  uint64_t write_len = min(len, length);
3951  chunk* c;
3952 
3953  TRACE("doing non-COW write to %I64x\n", writeaddr);
3954 
3955  Status = write_data_complete(fcb->Vcb, writeaddr, (uint8_t*)data + written, (uint32_t)write_len, Irp, NULL, file_write, irp_offset + written, priority);
3956  if (!NT_SUCCESS(Status)) {
3957  ERR("write_data_complete returned %08lx\n", Status);
3958  return Status;
3959  }
3960 
3961  c = get_chunk_from_address(fcb->Vcb, writeaddr);
3962  if (c)
3963  c->changed = true;
3964 
3965  // This shouldn't ever get called - nocow files should always also be nosum.
3967  do_calc_job(fcb->Vcb, (uint8_t*)data + written, (uint32_t)(write_len / fcb->Vcb->superblock.sector_size),
3968  (uint8_t*)ext->csum + ((start + written - ext->offset) * fcb->Vcb->csum_size / fcb->Vcb->superblock.sector_size));
3969 
3970  ext->inserted = true;
3971  extents_changed = true;
3972  }
3973 
3974  written += write_len;
3975  length -= write_len;
3976 
3977  if (length == 0)
3978  break;
3979  } else if (ed->type == EXTENT_TYPE_PREALLOC) {
3980  uint64_t write_len;
3981 
3982  Status = do_write_file_prealloc(fcb, ext, start + written, end_data, (uint8_t*)data + written, &write_len,
3983  Irp, file_write, irp_offset + written, priority, rollback);
3984  if (!NT_SUCCESS(Status)) {
3985  ERR("do_write_file_prealloc returned %08lx\n", Status);
3986  return Status;
3987  }
3988 
3989  extents_changed = true;
3990 
3991  written += write_len;
3992  length -= write_len;
3993 
3994  if (length == 0)
3995  break;
3996  }
3997 
3998  last_cow_start = ext->offset + len;
3999  }
4000  }
4001 
4002 nextitem:
4003  le = le2;
4004  }
4005 
4006  if (length > 0) {
4007  uint64_t start_write = max(last_cow_start, start + written);
4008 
4009  extents_changed = true;
4010 
4011  Status = excise_extents(fcb->Vcb, fcb, start_write, end_data, Irp, rollback);
4012  if (!NT_SUCCESS(Status)) {
4013  ERR("excise_extents returned %08lx\n", Status);
4014  return Status;
4015  }
4016 
4017  Status = insert_extent(fcb->Vcb, fcb, start_write, end_data - start_write, (uint8_t*)data + written, Irp, file_write, irp_offset + written, rollback);
4018  if (!NT_SUCCESS(Status)) {
4019  ERR("insert_extent returned %08lx\n", Status);
4020  return Status;
4021  }
4022  }
4023 
4024 #ifdef DEBUG_PARANOID
4025  last_off = 0xffffffffffffffff;
4026 
4027  le = fcb->extents.Flink;
4028  while (le != &fcb->extents) {
4030 
4031  if (!ext->ignore) {
4032  if (ext->offset == last_off) {
4033  ERR("offset %I64x duplicated\n", ext->offset);
4034  int3;
4035  } else if (ext->offset < last_off && last_off != 0xffffffffffffffff) {
4036  ERR("offsets out of order\n");
4037  int3;
4038  }
4039 
4040  last_off = ext->offset;
4041  }
4042 
4043  le = le->Flink;
4044  }
4045 #endif
4046 
4047  if (extents_changed) {
4048  fcb->extents_changed = true;
4050  }
4051 
4052  return STATUS_SUCCESS;
4053 }
LOCAL void nextitem(arg_t *ap)
Definition: match.c:428
#define max(a, b)
Definition: svc.c:63
uint8_t type
Definition: btrfs.h:351
NTSTATUS Status
Definition: write.c:2803
fcb extents_changed
Definition: write.c:2862
#define BTRFS_INODE_NODATACOW
Definition: propsheet.h:77
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:61
EXTENT_DATA2 * ed2
Definition: write.c:2805
_In_ PIRP Irp
Definition: csq.h:116
uint64_t decoded_size
Definition: btrfs.h:347
#define FSRTL_FLAG2_IS_PAGING_FILE
Definition: fsrtltypes.h:57
LONG NTSTATUS
Definition: precomp.h:26
#define int3
Definition: btrfs_drv.h:1791
static NTSTATUS insert_extent(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t length, void *data, PIRP Irp, bool file_write, uint64_t irp_offset, LIST_ENTRY *rollback)
Definition: write.c:3105
static NTSTATUS do_write_file_prealloc(fcb *fcb, extent *ext, uint64_t start_data, uint64_t end_data, void *data, uint64_t *written, PIRP Irp, bool file_write, uint64_t irp_offset, ULONG priority, LIST_ENTRY *rollback)
Definition: write.c:3532
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool _In_ uint64_t irp_offset
Definition: write.c:2801
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:70
void do_calc_job(device_extension *Vcb, uint8_t *data, uint32_t sectors, void *csum)
Definition: calcthread.c:141
uint64_t address
Definition: btrfs.h:356
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool file_write
Definition: write.c:2800
bool extents_changed
Definition: btrfs_drv.h:334
smooth NULL
Definition: ftsmooth.c:416
char ext[3]
Definition: mkdosfs.c:358
NTSTATUS write_data_complete(device_extension *Vcb, uint64_t address, void *data, uint32_t length, PIRP Irp, chunk *c, bool file_write, uint64_t irp_offset, ULONG priority)
Definition: write.c:2182
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:294
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
const GLubyte * c
Definition: glext.h:8905
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2800
LIST_ENTRY extents
Definition: btrfs_drv.h:311
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
Status
Definition: gdiplustypes.h:24
GLenum GLsizei len
Definition: glext.h:6722
Definition: typedefs.h:119
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:72
INODE_ITEM inode_item
Definition: btrfs_drv.h:303
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t num_bytes
Definition: btrfs.h:359
uint64_t flags
Definition: btrfs.h:290
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:71
#define ERR(fmt,...)
Definition: debug.h:110
uint8_t data[1]
Definition: btrfs.h:352
UINT64 uint64_t
Definition: types.h:77
GLuint start
Definition: gl.h:1545
chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address)
Definition: write.c:89
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
mark_fcb_dirty(fcb)
UINT32 uint32_t
Definition: types.h:75
NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback)
Definition: write.c:2384
if(!find_data_address_in_chunk(Vcb, c, length, &address)) return false
unsigned int ULONG
Definition: retypes.h:1
static int priority
Definition: timer.c:163
uint64_t offset
Definition: btrfs.h:358
return STATUS_SUCCESS
Definition: btrfs.c:3014
_In_ fcb _In_ chunk * c
Definition: write.c:2800
EXTENT_DATA * ed
Definition: write.c:2804
struct _device_extension * Vcb
Definition: btrfs_drv.h:298
uint8_t compression
Definition: btrfs.h:348
TRACE("(%p, (%I64x, %I64x), %I64x, %I64x, %I64x, %u, %p, %p)\n", Vcb, fcb->subvol->id, fcb->inode, c->offset, start_data, length, prealloc, data, rollback)

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

◆ do_write_file_prealloc()

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

Definition at line 3532 of file write.c.

3533  {
3534  EXTENT_DATA* ed = &ext->extent_data;
3536  NTSTATUS Status;
3537  chunk* c = NULL;
3538 
3539  if (start_data <= ext->offset && end_data >= ext->offset + ed2->num_bytes) { // replace all
3540  extent* newext;
3541 
3542  newext = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3543  if (!newext) {
3544  ERR("out of memory\n");
3546  }
3547 
3548  RtlCopyMemory(&newext->extent_data, &ext->extent_data, ext->datalen);
3549 
3551 
3553  NULL, file_write, irp_offset + ext->offset - start_data, priority);
3554  if (!NT_SUCCESS(Status)) {
3555  ERR("write_data_complete returned %08lx\n", Status);
3556  return Status;
3557  }
3558 
3560  ULONG sl = (ULONG)(ed2->num_bytes / fcb->Vcb->superblock.sector_size);
3561  void* csum = ExAllocatePoolWithTag(PagedPool, sl * fcb->Vcb->csum_size, ALLOC_TAG);
3562 
3563  if (!csum) {
3564  ERR("out of memory\n");
3565  ExFreePool(newext);
3567  }
3568 
3569  do_calc_job(fcb->Vcb, (uint8_t*)data + ext->offset - start_data, sl, csum);
3570 
3571  newext->csum = csum;
3572  } else
3573  newext->csum = NULL;
3574 
3575  *written = ed2->num_bytes;
3576 
3577  newext->offset = ext->offset;
3578  newext->datalen = ext->datalen;
3579  newext->unique = ext->unique;
3580  newext->ignore = false;
3581  newext->inserted = true;
3582  InsertHeadList(&ext->list_entry, &newext->list_entry);
3583 
3585 
3587 
3589  } else if (start_data <= ext->offset && end_data < ext->offset + ed2->num_bytes) { // replace beginning
3590  EXTENT_DATA2* ned2;
3591  extent *newext1, *newext2;
3592 
3593  newext1 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3594  if (!newext1) {
3595  ERR("out of memory\n");
3597  }
3598 
3599  newext2 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3600  if (!newext2) {
3601  ERR("out of memory\n");
3602  ExFreePool(newext1);
3604  }
3605 
3606  RtlCopyMemory(&newext1->extent_data, &ext->extent_data, ext->datalen);
3608  ned2 = (EXTENT_DATA2*)newext1->extent_data.data;
3609  ned2->num_bytes = end_data - ext->offset;
3610 
3611  RtlCopyMemory(&newext2->extent_data, &ext->extent_data, ext->datalen);
3612  ned2 = (EXTENT_DATA2*)newext2->extent_data.data;
3613  ned2->offset += end_data - ext->offset;
3614  ned2->num_bytes -= end_data - ext->offset;
3615 
3616  Status = write_data_complete(fcb->Vcb, ed2->address + ed2->offset, (uint8_t*)data + ext->offset - start_data, (uint32_t)(end_data - ext->offset),
3617  Irp, NULL, file_write, irp_offset + ext->offset - start_data, priority);
3618  if (!NT_SUCCESS(Status)) {
3619  ERR("write_data_complete returned %08lx\n", Status);
3620  ExFreePool(newext1);
3621  ExFreePool(newext2);
3622  return Status;
3623  }
3624 
3626  ULONG sl = (ULONG)((end_data - ext->offset) / fcb->Vcb->superblock.sector_size);
3627  void* csum = ExAllocatePoolWithTag(PagedPool, sl * fcb->Vcb->csum_size, ALLOC_TAG);
3628 
3629  if (!csum) {
3630  ERR("out of memory\n");
3631  ExFreePool(newext1);
3632  ExFreePool(newext2);
3634  }
3635 
3636  do_calc_job(fcb->Vcb, (uint8_t*)data + ext->offset - start_data, sl, csum);
3637 
3638  newext1->csum = csum;
3639  } else
3640  newext1->csum = NULL;
3641 
3642  *written = end_data - ext->offset;
3643 
3644  newext1->offset = ext->offset;
3645  newext1->datalen = ext->datalen;
3646  newext1->unique = ext->unique;
3647  newext1->ignore = false;
3648  newext1->inserted = true;
3649  InsertHeadList(&ext->list_entry, &newext1->list_entry);
3650 
3652 
3653  newext2->offset = end_data;
3654  newext2->datalen = ext->datalen;
3655  newext2->unique = ext->unique;
3656  newext2->ignore = false;
3657  newext2->inserted = true;
3658  newext2->csum = NULL;
3659  add_extent(fcb, &newext1->list_entry, newext2);
3660 
3662 
3664 
3665  if (!c)
3666  ERR("get_chunk_from_address(%I64x) failed\n", ed2->address);
3667  else {
3670 
3671  if (!NT_SUCCESS(Status)) {
3672  ERR("update_changed_extent_ref returned %08lx\n", Status);
3673  return Status;
3674  }
3675  }
3676 
3678  } else if (start_data > ext->offset && end_data >= ext->offset + ed2->num_bytes) { // replace end
3679  EXTENT_DATA2* ned2;
3680  extent *newext1, *newext2;
3681 
3682  newext1 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3683  if (!newext1) {
3684  ERR("out of memory\n");
3686  }
3687 
3688  newext2 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3689  if (!newext2) {
3690  ERR("out of memory\n");
3691  ExFreePool(newext1);
3693  }
3694 
3695  RtlCopyMemory(&newext1->extent_data, &ext->extent_data, ext->datalen);
3696 
3697  ned2 = (EXTENT_DATA2*)newext1->extent_data.data;
3698  ned2->num_bytes = start_data - ext->offset;
3699 
3700  RtlCopyMemory(&newext2->extent_data, &ext->extent_data, ext->datalen);
3701 
3703  ned2 = (EXTENT_DATA2*)newext2->extent_data.data;
3704  ned2->offset += start_data - ext->offset;
3705  ned2->num_bytes = ext->offset + ed2->num_bytes - start_data;
3706 
3708  if (!NT_SUCCESS(Status)) {
3709  ERR("write_data_complete returned %08lx\n", Status);
3710  ExFreePool(newext1);
3711  ExFreePool(newext2);
3712  return Status;
3713  }
3714 
3716  ULONG sl = (ULONG)(ned2->num_bytes / fcb->Vcb->superblock.sector_size);
3717  void* csum = ExAllocatePoolWithTag(PagedPool, sl * fcb->Vcb->csum_size, ALLOC_TAG);
3718 
3719  if (!csum) {
3720  ERR("out of memory\n");
3721  ExFreePool(newext1);
3722  ExFreePool(newext2);
3724  }
3725 
3726  do_calc_job(fcb->Vcb, data, sl, csum);
3727 
3728  newext2->csum = csum;
3729  } else
3730  newext2->csum = NULL;
3731 
3732  *written = ned2->num_bytes;
3733 
3734  newext1->offset = ext->offset;
3735  newext1->datalen = ext->datalen;
3736  newext1->unique = ext->unique;
3737  newext1->ignore = false;
3738  newext1->inserted = true;
3739  newext1->csum = NULL;
3740  InsertHeadList(&ext->list_entry, &newext1->list_entry);
3741 
3743 
3744  newext2->offset = start_data;
3745  newext2->datalen = ext->datalen;
3746  newext2->unique = ext->unique;
3747  newext2->ignore = false;
3748  newext2->inserted = true;
3749  add_extent(fcb, &newext1->list_entry, newext2);
3750 
3752 
3754 
3755  if (!c)
3756  ERR("get_chunk_from_address(%I64x) failed\n", ed2->address);
3757  else {
3760 
3761  if (!NT_SUCCESS(Status)) {
3762  ERR("update_changed_extent_ref returned %08lx\n", Status);
3763  return Status;
3764  }
3765  }
3766 
3768  } else if (start_data > ext->offset && end_data < ext->offset + ed2->num_bytes) { // replace middle
3769  EXTENT_DATA2* ned2;
3770  extent *newext1, *newext2, *newext3;
3771 
3772  newext1 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3773  if (!newext1) {
3774  ERR("out of memory\n");
3776  }
3777 
3778  newext2 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3779  if (!newext2) {
3780  ERR("out of memory\n");
3781  ExFreePool(newext1);
3783  }
3784 
3785  newext3 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + ext->datalen, ALLOC_TAG);
3786  if (!newext3) {
3787  ERR("out of memory\n");
3788  ExFreePool(newext1);
3789  ExFreePool(newext2);
3791  }
3792 
3793  RtlCopyMemory(&newext1->extent_data, &ext->extent_data, ext->datalen);
3794  RtlCopyMemory(&newext2->extent_data, &ext->extent_data, ext->datalen);
3795  RtlCopyMemory(&newext3->extent_data, &ext->extent_data, ext->datalen);
3796 
3797  ned2 = (EXTENT_DATA2*)newext1->extent_data.data;
3798  ned2->num_bytes = start_data - ext->offset;
3799 
3801  ned2 = (EXTENT_DATA2*)newext2->extent_data.data;
3802  ned2->offset += start_data - ext->offset;
3803  ned2->num_bytes = end_data - start_data;
3804 
3805  ned2 = (EXTENT_DATA2*)newext3->extent_data.data;
3806  ned2->offset += end_data - ext->offset;
3807  ned2->num_bytes -= end_data - ext->offset;
3808 
3809  ned2 = (EXTENT_DATA2*)newext2->extent_data.data;
3811  if (!NT_SUCCESS(Status)) {
3812  ERR("write_data_complete returned %08lx\n", Status);
3813  ExFreePool(newext1);
3814  ExFreePool(newext2);
3815  ExFreePool(newext3);
3816  return Status;
3817  }
3818 
3820  ULONG sl = (ULONG)((end_data - start_data) / fcb->Vcb->superblock.sector_size);
3821  void* csum = ExAllocatePoolWithTag(PagedPool, sl * fcb->Vcb->csum_size, ALLOC_TAG);
3822 
3823  if (!csum) {
3824  ERR("out of memory\n");
3825  ExFreePool(newext1);
3826  ExFreePool(newext2);
3827  ExFreePool(newext3);
3829  }
3830 
3831  do_calc_job(fcb->Vcb, data, sl, csum);
3832 
3833  newext2->csum = csum;
3834  } else
3835  newext2->csum = NULL;
3836 
3837  *written = end_data - start_data;
3838 
3839  newext1->offset = ext->offset;
3840  newext1->datalen = ext->datalen;
3841  newext1->unique = ext->unique;
3842  newext1->ignore = false;
3843  newext1->inserted = true;
3844  newext1->csum = NULL;
3845  InsertHeadList(&ext->list_entry, &newext1->list_entry);
3846 
3848 
3849  newext2->offset = start_data;
3850  newext2->datalen = ext->datalen;
3851  newext2->unique = ext->unique;
3852  newext2->ignore = false;
3853  newext2->inserted = true;
3854  add_extent(fcb, &newext1->list_entry, newext2);
3855 
3857 
3858  newext3->offset = end_data;
3859  newext3->datalen = ext->datalen;
3860  newext3->unique = ext->unique;
3861  newext3->ignore = false;
3862  newext3->inserted = true;
3863  newext3->csum = NULL;
3864  add_extent(fcb, &newext2->list_entry, newext3);
3865 
3867 
3869 
3870  if (!c)
3871  ERR("get_chunk_from_address(%I64x) failed\n", ed2->address);
3872  else {
3875 
3876  if (!NT_SUCCESS(Status)) {
3877  ERR("update_changed_extent_ref returned %08lx\n", Status);
3878  return Status;
3879  }
3880  }
3881 
3883  }
3884 
3885  if (c)
3886  c->changed = true;
3887 
3888  return STATUS_SUCCESS;
3889 }
void add_extent(_In_ fcb *fcb, _In_ LIST_ENTRY *prevextle, _In_ __drv_aliasesMem extent *newext)
Definition: write.c:2367
void add_insert_extent_rollback(LIST_ENTRY *rollback, fcb *fcb, extent *ext)
Definition: write.c:2717
uint8_t type
Definition: btrfs.h:351
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS update_changed_extent_ref(device_extension *Vcb, chunk *c, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, int32_t count, bool no_csum, bool superseded, PIRP Irp)
Definition: extent-tree.c:1951
NTSTATUS Status
Definition: write.c:2803
EXTENT_DATA2 * ed2
Definition: write.c:2805
_In_ PIRP Irp
Definition: csq.h:116
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
void * csum
Definition: btrfs_drv.h:244
LIST_ENTRY list_entry
Definition: btrfs_drv.h:246
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool _In_ uint64_t irp_offset
Definition: write.c:2801
uint16_t datalen
Definition: btrfs_drv.h:240
bool ignore
Definition: btrfs_drv.h:242
#define ALLOC_TAG
Definition: btrfs_drv.h:91
bool inserted
Definition: btrfs_drv.h:243
void do_calc_job(device_extension *Vcb, uint8_t *data, uint32_t sectors, void *csum)
Definition: calcthread.c:141
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool file_write
Definition: write.c:2800
uint64_t address
Definition: btrfs.h:356
uint64_t offset
Definition: btrfs_drv.h:239
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
uint64_t size
Definition: btrfs.h:357
NTSTATUS write_data_complete(device_extension *Vcb, uint64_t address, void *data, uint32_t length, PIRP Irp, chunk *c, bool file_write, uint64_t irp_offset, ULONG priority)
Definition: write.c:2182
bool unique
Definition: btrfs_drv.h:241
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t inode
Definition: btrfs_drv.h:300
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
const GLubyte * c
Definition: glext.h:8905
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2800
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
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP Irp
Definition: write.c:2800
_In_ fcb _In_ chunk _In_ uint64_t start_data
Definition: write.c:2800
INODE_ITEM inode_item
Definition: btrfs_drv.h:303
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t num_bytes
Definition: btrfs.h:359
uint64_t flags
Definition: btrfs.h:290
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:71
#define ERR(fmt,...)
Definition: debug.h:110
uint8_t data[1]
Definition: btrfs.h:352
chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address)
Definition: write.c:89
struct _root * subvol
Definition: btrfs_drv.h:299
UINT32 uint32_t
Definition: types.h:75
Definition: fs.h:216
EXTENT_DATA extent_data
Definition: btrfs_drv.h:248
if(!find_data_address_in_chunk(Vcb, c, length, &address)) return false
unsigned int ULONG
Definition: retypes.h:1
static int priority
Definition: timer.c:163
uint64_t offset
Definition: btrfs.h:358
ExFreePool(ed)
static void remove_fcb_extent(fcb *fcb, extent *ext, LIST_ENTRY *rollback)
Definition: write.c:2779
#define uint32_t
Definition: nsiface.idl:61
return STATUS_SUCCESS
Definition: btrfs.c:3014
EXTENT_DATA * ed
Definition: write.c:2804
struct _device_extension * Vcb
Definition: btrfs_drv.h:298
void * csum
Definition: write.c:2807

Referenced by do_write_file().

◆ excise_extents()

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

Definition at line 2384 of file write.c.

2384  {
2385  NTSTATUS Status;
2386  LIST_ENTRY* le;
2387 
2388  le = fcb->extents.Flink;
2389 
2390  while (le != &fcb->extents) {
2391  LIST_ENTRY* le2 = le->Flink;
2393  EXTENT_DATA* ed = &ext->extent_data;
2394  EXTENT_DATA2* ed2 = NULL;
2395  uint64_t len;
2396 
2397  if (!ext->ignore) {
2398  if (ed->type != EXTENT_TYPE_INLINE)
2399  ed2 = (EXTENT_DATA2*)ed->data;
2400 
2402 
2403  if (ext->offset < end_data && ext->offset + len > start_data) {
2404  if (ed->type == EXTENT_TYPE_INLINE) {
2405  if (start_data <= ext->offset && end_data >= ext->offset + len) { // remove all
2407 
2409  fcb->inode_item_changed = true;
2410  } else {
2411  ERR("trying to split inline extent\n");
2412 #ifdef DEBUG_PARANOID
2413  int3;
2414 #endif
2415  return STATUS_INTERNAL_ERROR;
2416  }
2417  } else if (ed->type != EXTENT_TYPE_INLINE) {
2418  if (start_data <= ext->offset && end_data >= ext->offset + len) { // remove all
2419  if (ed2->size != 0) {
2420  chunk* c;
2421 
2423  fcb->inode_item_changed = true;
2424 
2426 
2427  if (!c) {
2428  ERR("get_chunk_from_address(%I64x) failed\n", ed2->address);
2429  } else {
2430  Status = update_changed_extent_ref(Vcb, c, ed2->address, ed2->size, fcb->subvol->id, fcb->inode, ext->offset - ed2->offset, -1,
2432  if (!NT_SUCCESS(Status)) {
2433  ERR("update_changed_extent_ref returned %08lx\n", Status);
2434  goto end;
2435  }
2436  }
2437  }
2438 
2440  } else if (start_data <= ext->offset && end_data < ext->offset + len) { // remove beginning
2441  EXTENT_DATA2* ned2;
2442  extent* newext;
2443 
2444  if (ed2->size != 0) {
2445  fcb->inode_item.st_blocks -= end_data - ext->offset;
2446  fcb->inode_item_changed = true;
2447  }
2448 
2449  newext = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2), ALLOC_TAG);
2450  if (!newext) {
2451  ERR("out of memory\n");
2453  goto end;
2454  }
2455 
2456  ned2 = (EXTENT_DATA2*)newext->extent_data.data;
2457 
2458  newext->extent_data.generation = Vcb->superblock.generation;
2461  newext->extent_data.encryption = ed->encryption;
2462  newext->extent_data.encoding = ed->encoding;
2463  newext->extent_data.type = ed->type;
2464  ned2->address = ed2->address;
2465  ned2->size = ed2->size;
2466  ned2->offset = ed2->offset + (end_data - ext->offset);
2467  ned2->num_bytes = ed2->num_bytes - (end_data - ext->offset);
2468 
2469  newext->offset = end_data;
2470  newext->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
2471  newext->unique = ext->unique;
2472  newext->ignore = false;
2473  newext->inserted = true;
2474 
2475  if (ext->csum) {
2477  newext->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ned2->num_bytes * Vcb->csum_size / Vcb->superblock.sector_size), ALLOC_TAG);
2478  if (!newext->csum) {
2479  ERR("out of memory\n");
2481  ExFreePool(newext);
2482  goto end;
2483  }
2484 
2485  RtlCopyMemory(newext->csum, (uint8_t*)ext->csum + ((end_data - ext->offset) * Vcb->csum_size / Vcb->superblock.sector_size),
2486  (ULONG)(ned2->num_bytes * Vcb->csum_size / Vcb->superblock.sector_size));
2487  } else {
2488  newext->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2->size * Vcb->csum_size / Vcb->superblock.sector_size), ALLOC_TAG);
2489  if (!newext->csum) {
2490  ERR("out of memory\n");
2492  ExFreePool(newext);
2493  goto end;
2494  }
2495 
2496  RtlCopyMemory(newext->csum, ext->csum, (ULONG)(ed2->size * Vcb->csum_size / Vcb->superblock.sector_size));
2497  }
2498  } else
2499  newext->csum = NULL;
2500 
2501  add_extent(fcb, &ext->list_entry, newext);
2502 
2504  } else if (start_data > ext->offset && end_data >= ext->offset + len) { // remove end
2505  EXTENT_DATA2* ned2;
2506  extent* newext;
2507 
2508  if (ed2->size != 0) {
2509  fcb->inode_item.st_blocks -= ext->offset + len - start_data;
2510  fcb->inode_item_changed = true;
2511  }
2512 
2513  newext = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2), ALLOC_TAG);
2514  if (!newext) {
2515  ERR("out of memory\n");
2517  goto end;
2518  }
2519 
2520  ned2 = (EXTENT_DATA2*)newext->extent_data.data;
2521 
2522  newext->extent_data.generation = Vcb->superblock.generation;
2525  newext->extent_data.encryption = ed->encryption;
2526  newext->extent_data.encoding = ed->encoding;
2527  newext->extent_data.type = ed->type;
2528  ned2->address = ed2->address;
2529  ned2->size = ed2->size;
2530  ned2->offset = ed2->offset;
2531  ned2->num_bytes = start_data - ext->offset;
2532 
2533  newext->offset = ext->offset;
2534  newext->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
2535  newext->unique = ext->unique;
2536  newext->ignore = false;
2537  newext->inserted = true;
2538 
2539  if (ext->csum) {
2541  newext->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ned2->num_bytes * Vcb->csum_size / Vcb->superblock.sector_size), ALLOC_TAG);
2542  if (!newext->csum) {
2543  ERR("out of memory\n");
2545  ExFreePool(newext);
2546  goto end;
2547  }
2548 
2549  RtlCopyMemory(newext->csum, ext->csum, (ULONG)(ned2->num_bytes * Vcb->csum_size / Vcb->superblock.sector_size));
2550  } else {
2551  newext->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2->size * Vcb->csum_size / Vcb->superblock.sector_size), ALLOC_TAG);
2552  if (!newext->csum) {
2553  ERR("out of memory\n");
2555  ExFreePool(newext);
2556  goto end;
2557  }
2558 
2559  RtlCopyMemory(newext->csum, ext->csum, (ULONG)(ed2->size * Vcb->csum_size / Vcb->superblock.sector_size));
2560  }
2561  } else
2562  newext->csum = NULL;
2563 
2564  InsertHeadList(&ext->list_entry, &newext->list_entry);
2565 
2567  } else if (start_data > ext->offset && end_data < ext->offset + len) { // remove middle
2568  EXTENT_DATA2 *neda2, *nedb2;
2569  extent *newext1, *newext2;
2570 
2571  if (ed2->size != 0) {
2572  chunk* c;
2573 
2574  fcb->inode_item.st_blocks -= end_data - start_data;
2575  fcb->inode_item_changed = true;
2576 
2578 
2579  if (!c) {
2580  ERR("get_chunk_from_address(%I64x) failed\n", ed2->address);
2581  } else {
2584  if (!NT_SUCCESS(Status)) {
2585  ERR("update_changed_extent_ref returned %08lx\n", Status);
2586  goto end;
2587  }
2588  }
2589  }
2590 
2591  newext1 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2), ALLOC_TAG);
2592  if (!newext1) {
2593  ERR("out of memory\n");
2595  goto end;
2596  }
2597 
2598  newext2 = ExAllocatePoolWithTag(PagedPool, offsetof(extent, extent_data) + sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2), ALLOC_TAG);
2599  if (!newext2) {
2600  ERR("out of memory\n");
2602  ExFreePool(newext1);
2603  goto end;
2604  }
2605 
2606  neda2 = (EXTENT_DATA2*)newext1->extent_data.data;
2607 
2608  newext1->extent_data.generation = Vcb->superblock.generation;
2610  newext1->extent_data.compression = ed->compression;
2611  newext1->extent_data.encryption = ed->encryption;
2612  newext1->extent_data.encoding = ed->encoding;
2613  newext1->extent_data.type = ed->type;
2614  neda2->address = ed2->address;
2615  neda2->size = ed2->size;
2616  neda2->offset = ed2->offset;
2617  neda2->num_bytes = start_data - ext->offset;
2618 
2619  nedb2 = (EXTENT_DATA2*)newext2->extent_data.data;
2620 
2621  newext2->extent_data.generation = Vcb->superblock.generation;
2623  newext2->extent_data.compression = ed->compression;
2624  newext2->extent_data.encryption = ed->encryption;
2625  newext2->extent_data.encoding = ed->encoding;
2626  newext2->extent_data.type = ed->type;
2627  nedb2->address = ed2->address;
2628  nedb2->size = ed2->size;
2629  nedb2->offset = ed2->offset + (end_data - ext->offset);
2630  nedb2->num_bytes = ext->offset + len - end_data;
2631 
2632  newext1->offset = ext->offset;
2633  newext1->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
2634  newext1->unique = ext->unique;
2635  newext1->ignore = false;
2636  newext1->inserted = true;
2637 
2638  newext2->offset = end_data;
2639  newext2->datalen = sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2);
2640  newext2->unique = ext->unique;
2641  newext2->ignore = false;
2642  newext2->inserted = true;
2643 
2644  if (ext->csum) {
2646  newext1->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(neda2->num_bytes * Vcb->csum_size / Vcb->superblock.sector_size), ALLOC_TAG);
2647  if (!newext1->csum) {
2648  ERR("out of memory\n");
2650  ExFreePool(newext1);
2651  ExFreePool(newext2);
2652  goto end;
2653  }
2654 
2655  newext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(nedb2->num_bytes * Vcb->csum_size / Vcb->superblock.sector_size), ALLOC_TAG);
2656  if (!newext2->csum) {
2657  ERR("out of memory\n");
2659  ExFreePool(newext1->csum);
2660  ExFreePool(newext1);
2661  ExFreePool(newext2);
2662  goto end;
2663  }
2664 
2665  RtlCopyMemory(newext1->csum, ext->csum, (ULONG)(neda2->num_bytes * Vcb->csum_size / Vcb->superblock.sector_size));
2666  RtlCopyMemory(newext2->csum, (uint8_t*)ext->csum + ((end_data - ext->offset) * Vcb->csum_size / Vcb->superblock.sector_size),
2667  (ULONG)(nedb2->num_bytes * Vcb->csum_size / Vcb->superblock.sector_size));
2668  } else {
2669  newext1->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2->size * Vcb->csum_size / Vcb->superblock.sector_size), ALLOC_TAG);
2670  if (!newext1->csum) {
2671  ERR("out of memory\n");
2673  ExFreePool(newext1);
2674  ExFreePool(newext2);
2675  goto end;
2676  }
2677 
2678  newext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2->size * Vcb->csum_size / Vcb->superblock.sector_size), ALLOC_TAG);
2679  if (!newext2->csum) {
2680  ERR("out of memory\n");
2682  ExFreePool(newext1->csum);
2683  ExFreePool(newext1);
2684  ExFreePool(newext2);
2685  goto end;
2686  }
2687 
2688  RtlCopyMemory(newext1->csum, ext->csum, (ULONG)(ed2->size * Vcb->csum_size / Vcb->superblock.sector_size));
2689  RtlCopyMemory(newext2->csum, ext->csum, (ULONG)(ed2->size * Vcb->csum_size / Vcb->superblock.sector_size));
2690  }
2691  } else {
2692  newext1->csum = NULL;
2693  newext2->csum = NULL;
2694  }
2695 
2696  InsertHeadList(&ext->list_entry, &newext1->list_entry);
2697  add_extent(fcb, &newext1->list_entry, newext2);
2698 
2700  }
2701  }
2702  }
2703  }
2704 
2705  le = le2;
2706  }
2707 
2709 
2710 end:
2711  fcb->extents_changed = true;
2713 
2714  return Status;
2715 }
void add_extent(_In_ fcb *fcb, _In_ LIST_ENTRY *prevextle, _In_ __drv_aliasesMem extent *newext)
Definition: write.c:2367
uint64_t generation
Definition: btrfs.h:346
uint8_t type
Definition: btrfs.h:351
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS update_changed_extent_ref(device_extension *Vcb, chunk *c, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, int32_t count, bool no_csum, bool superseded, PIRP Irp)
Definition: extent-tree.c:1951
NTSTATUS Status
Definition: write.c:2803
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:61
EXTENT_DATA2 * ed2
Definition: write.c:2805
_In_ PIRP Irp
Definition: csq.h:116
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
uint64_t decoded_size
Definition: btrfs.h:347
LONG NTSTATUS
Definition: precomp.h:26
#define int3
Definition: btrfs_drv.h:1791
GLintptr offset
Definition: glext.h:5920
void * csum
Definition: btrfs_drv.h:244
LIST_ENTRY list_entry
Definition: btrfs_drv.h:246
uint16_t datalen
Definition: btrfs_drv.h:240
GLuint GLuint end
Definition: gl.h:1545
uint8_t encryption
Definition: btrfs.h:349
bool ignore
Definition: btrfs_drv.h:242
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:91
bool inserted
Definition: btrfs_drv.h:243
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:70
uint64_t address
Definition: btrfs.h:356
uint64_t offset
Definition: btrfs_drv.h:239
bool extents_changed
Definition: btrfs_drv.h:334
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
uint64_t size
Definition: btrfs.h:357
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
bool unique
Definition: btrfs_drv.h:241
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
uint16_t encoding
Definition: btrfs.h:350
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t inode
Definition: btrfs_drv.h:300
#define BTRFS_INODE_NODATASUM
Definition: propsheet.h:76
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2800
LIST_ENTRY extents
Definition: btrfs_drv.h:311
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Status
Definition: gdiplustypes.h:24
_In_ fcb _In_ chunk _In_ uint64_t start_data
Definition: write.c:2800
GLenum GLsizei len
Definition: glext.h:6722
Definition: typedefs.h:119
INODE_ITEM inode_item
Definition: btrfs_drv.h:303
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t num_bytes
Definition: btrfs.h:359
uint64_t st_blocks
Definition: btrfs.h:283
uint64_t flags
Definition: btrfs.h:290
#define ERR(fmt,...)
Definition: debug.h:110
uint8_t data[1]
Definition: btrfs.h:352
UINT64 uint64_t
Definition: types.h:77
chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address)
Definition: write.c:89
struct _root * subvol
Definition: btrfs_drv.h:299
Definition: list.h:27
mark_fcb_dirty(fcb)
EXTENT_DATA extent_data
Definition: btrfs_drv.h:248
if(!find_data_address_in_chunk(Vcb, c, length, &address)) return false
unsigned int ULONG
Definition: retypes.h:1
uint64_t offset
Definition: btrfs.h:358
ExFreePool(ed)
static void remove_fcb_extent(fcb *fcb, extent *ext, LIST_ENTRY *rollback)
Definition: write.c:2779
return STATUS_SUCCESS
Definition: btrfs.c:3014
_In_ fcb _In_ chunk * c
Definition: write.c:2800
EXTENT_DATA * ed
Definition: write.c:2804
bool inode_item_changed
Definition: btrfs_drv.h:317
uint8_t compression
Definition: btrfs.h:348

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

◆ ExFreePool()

◆ extend_file()

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

Definition at line 3299 of file write.c.

3299  {
3300  uint64_t oldalloc, newalloc;
3301  bool cur_inline;
3302  NTSTATUS Status;
3303 
3304  TRACE("(%p, %p, %I64x, %u)\n", fcb, fileref, end, prealloc);
3305 
3306  if (fcb->ads) {
3307  if (end > 0xffff)
3308  return STATUS_DISK_FULL;
3309 
3310  return stream_set_end_of_file_information(fcb->Vcb, (uint16_t)end, fcb, fileref, false);
3311  } else {
3312  extent* ext = NULL;
3313  LIST_ENTRY* le;
3314 
3315  le = fcb->extents.Blink;
3316  while (le != &fcb->extents) {
3318 
3319  if (!ext2->ignore) {
3320  ext = ext2;
3321  break;
3322  }
3323 
3324  le = le->Blink;
3325  }
3326 
3327  oldalloc = 0;
3328  if (ext) {
3329  EXTENT_DATA* ed = &ext->extent_data;
3331 
3332  oldalloc = ext->offset + (ed->type == EXTENT_TYPE_INLINE ? ed->decoded_size : ed2->num_bytes);
3333  cur_inline = ed->type == EXTENT_TYPE_INLINE;
3334 
3335  if (cur_inline && end > fcb->Vcb->options.max_inline) {
3336  uint64_t origlength, length;
3337  uint8_t* data;
3338 
3339  TRACE("giving inline file proper extents\n");
3340 
3341  origlength = ed->decoded_size;
3342 
3343  cur_inline = false;
3344 
3345  length = sector_align(origlength, fcb->Vcb->superblock.sector_size);
3346 
3348  if (!data) {
3349  ERR("could not allocate %I64x bytes for data\n", length);
3351  }
3352 
3353  Status = read_file(fcb, data, 0, origlength, NULL, Irp);
3354  if (!NT_SUCCESS(Status)) {
3355  ERR("read_file returned %08lx\n", Status);
3356  ExFreePool(data);
3357  return Status;
3358  }
3359 
3360  RtlZeroMemory(data + origlength, (ULONG)(length - origlength));
3361 
3363  if (!NT_SUCCESS(Status)) {
3364  ERR("excise_extents returned %08lx\n", Status);
3365  ExFreePool(data);
3366  return Status;
3367  }
3368 
3369  Status = do_write_file(fcb, 0, length, data, Irp, false, 0, rollback);
3370  if (!NT_SUCCESS(Status)) {
3371  ERR("do_write_file returned %08lx\n", Status);
3372  ExFreePool(data);
3373  return Status;
3374  }
3375 
3376  oldalloc = ext->offset + length;
3377 
3378  ExFreePool(data);
3379  }
3380 
3381  if (cur_inline) {
3382  uint16_t edsize;
3383 
3384  if (end > oldalloc) {
3385  edsize = (uint16_t)(offsetof(EXTENT_DATA, data[0]) + end - ext->offset);
3387 
3388  if (!ed) {
3389  ERR("out of memory\n");
3391  }
3392 
3393  ed->generation = fcb->Vcb->superblock.generation;
3394  ed->decoded_size = end - ext->offset;
3399 
3400  Status = read_file(fcb, ed->data, ext->offset, oldalloc, NULL, Irp);
3401  if (!NT_SUCCESS(Status)) {
3402  ERR("read_file returned %08lx\n", Status);
3403  ExFreePool(ed);
3404  return Status;
3405  }
3406 
3407  RtlZeroMemory(ed->data + oldalloc - ext->offset, (ULONG)(end - oldalloc));
3408 
3410 
3411  Status = add_extent_to_fcb(fcb, ext->offset, ed, edsize, ext->unique, NULL, rollback);
3412  if (!NT_SUCCESS(Status)) {
3413  ERR("add_extent_to_fcb returned %08lx\n", Status);
3414  ExFreePool(ed);
3415  return Status;
3416  }
3417 
3418  ExFreePool(ed);
3419 
3420  fcb->extents_changed = true;
3422  }
3423 
3424  TRACE("extending inline file (oldalloc = %I64x, end = %I64x)\n", oldalloc, end);
3425 
3427  TRACE("setting st_size to %I64x\n", end);
3428 
3430 
3431  fcb->Header.AllocationSize.QuadPart = fcb->Header.FileSize.QuadPart = fcb->Header.ValidDataLength.QuadPart = end;
3432  } else {
3433  newalloc = sector_align(end, fcb->Vcb->superblock.sector_size);
3434 
3435  if (newalloc > oldalloc) {
3436  if (prealloc) {
3437  // FIXME - try and extend previous extent first
3438 
3439  Status = insert_prealloc_extent(fcb, oldalloc, newalloc - oldalloc, rollback);
3440 
3441  if (!NT_SUCCESS(Status)) {
3442  ERR("insert_prealloc_extent returned %08lx\n", Status);
3443  return Status;
3444  }
3445  }
3446 
3447  fcb->extents_changed = true;
3448  }
3449 
3451  fcb->inode_item_changed = true;
3453 
3454  TRACE("setting st_size to %I64x\n", end);
3455 
3456  TRACE("newalloc = %I64x\n", newalloc);
3457 
3458  fcb->Header.AllocationSize.QuadPart = newalloc;
3459  fcb->Header.FileSize.QuadPart = fcb->Header.ValidDataLength.QuadPart = end;
3460  }
3461  } else {
3462  if (end > fcb->Vcb->options.max_inline) {
3463  newalloc = sector_align(end, fcb->Vcb->superblock.sector_size);
3464 
3465  if (prealloc) {
3466  Status = insert_prealloc_extent(fcb, 0, newalloc, rollback);
3467 
3468  if (!NT_SUCCESS(Status)) {
3469  ERR("insert_prealloc_extent returned %08lx\n", Status);
3470  return Status;
3471  }
3472  }
3473 
3474  fcb->extents_changed = true;
3475  fcb->inode_item_changed = true;
3477 
3479  TRACE("setting st_size to %I64x\n", end);
3480 
3481  TRACE("newalloc = %I64x\n", newalloc);
3482 
3483  fcb->Header.AllocationSize.QuadPart = newalloc;
3484  fcb->Header.FileSize.QuadPart = fcb->Header.ValidDataLength.QuadPart = end;
3485  } else {
3486  EXTENT_DATA* ed;
3487  uint16_t edsize;
3488 
3491 
3492  if (!ed) {
3493  ERR("out of memory\n");
3495  }
3496 
3497  ed->generation = fcb->Vcb->superblock.generation;
3498  ed->decoded_size = end;
3503 
3505 
3506  Status = add_extent_to_fcb(fcb, 0, ed, edsize, false, NULL, rollback);
3507  if (!NT_SUCCESS(Status)) {
3508  ERR("add_extent_to_fcb returned %08lx\n", Status);
3509  ExFreePool(ed);
3510  return Status;
3511  }
3512 
3513  ExFreePool(ed);
3514 
3515  fcb->extents_changed = true;
3516  fcb->inode_item_changed = true;
3518 
3520  TRACE("setting st_size to %I64x\n", end);
3521 
3523 
3524  fcb->Header.AllocationSize.QuadPart = fcb->Header.FileSize.QuadPart = fcb->Header.ValidDataLength.QuadPart = end;
3525  }
3526  }
3527  }
3528 
3529  return STATUS_SUCCESS;
3530 }
uint64_t generation
Definition: btrfs.h:346
uint8_t type
Definition: btrfs.h:351
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t length
Definition: write.c:2800
static NTSTATUS insert_prealloc_extent(fcb *fcb, uint64_t start, uint64_t length, LIST_ENTRY *rollback)
Definition: write.c:3032
NTSTATUS Status
Definition: write.c:2803
NTSTATUS do_write_file(fcb *fcb, uint64_t start, uint64_t end_data, void *data, PIRP Irp, bool file_write, uint32_t irp_offset, LIST_ENTRY *rollback)
Definition: write.c:3891
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:61
EXTENT_DATA2 * ed2
Definition: write.c:2805
_In_ PIRP Irp
Definition: csq.h:116
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
uint64_t decoded_size
Definition: btrfs.h:347
LONG NTSTATUS
Definition: precomp.h:26
GLuint GLuint end
Definition: gl.h:1545
unsigned short int uint16_t
Definition: acefiex.h:54
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp)
Definition: read.c:2828
#define uint16_t
Definition: nsiface.idl:60
uint8_t encryption
Definition: btrfs.h:349
#define ALLOC_TAG
Definition: btrfs_drv.h:91
#define EXTENT_TYPE_INLINE
Definition: btrfs.h:70
bool extents_changed
Definition: btrfs_drv.h:334
#define BTRFS_ENCODING_NONE
Definition: btrfs.h:68
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:294
uint16_t encoding
Definition: btrfs.h:350
#define BTRFS_ENCRYPTION_NONE
Definition: btrfs.h:66
uint64_t st_size
Definition: btrfs.h:282
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
NTSTATUS add_extent_to_fcb(_In_ fcb *fcb, _In_ uint64_t offset, _In_reads_bytes_(edsize) EXTENT_DATA *ed, _In_ uint16_t edsize, _In_ bool unique, _In_opt_ _When_(return >=0, __drv_aliasesMem) void *csum, _In_ LIST_ENTRY *rollback)
Definition: write.c:2736
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2800
LIST_ENTRY extents
Definition: btrfs_drv.h:311
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
static const BYTE ext2[]
Definition: encode.c:2699
Status
Definition: gdiplustypes.h:24
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void * data
Definition: write.c:2800
Definition: typedefs.h:119
INODE_ITEM inode_item
Definition: btrfs_drv.h:303
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t num_bytes
Definition: btrfs.h:359
uint64_t st_blocks
Definition: btrfs.h:283
uint16_t edsize
Definition: write.c:2806
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool prealloc
Definition: write.c:2800
#define ERR(fmt,...)
Definition: debug.h:110
uint8_t data[1]
Definition: btrfs.h:352
UINT64 uint64_t
Definition: types.h:77
Definition: list.h:27
NTSTATUS stream_set_end_of_file_information(device_extension *Vcb, uint16_t end, fcb *fcb, file_ref *fileref, bool advance_only)
Definition: fileinfo.c:3107
mark_fcb_dirty(fcb)
NTSTATUS excise_extents(device_extension *Vcb, fcb *fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY *rollback)
Definition: write.c:2384
bool ads
Definition: btrfs_drv.h:341
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
ExFreePool(ed)
static void remove_fcb_extent(fcb *fcb, extent *ext, LIST_ENTRY *rollback)
Definition: write.c:2779
return STATUS_SUCCESS
Definition: btrfs.c:3014
EXTENT_DATA * ed
Definition: write.c:2804
bool inode_item_changed
Definition: btrfs_drv.h:317
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
struct _device_extension * Vcb
Definition: btrfs_drv.h:298
uint8_t compression
Definition: btrfs.h:348
TRACE("(%p, (%I64x, %I64x), %I64x, %I64x, %I64x, %u, %p, %p)\n", Vcb, fcb->subvol->id, fcb->inode, c->offset, start_data, length, prealloc, data, rollback)

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

◆ find_new_chunk_address()

static uint64_t find_new_chunk_address ( device_extension Vcb,
uint64_t  size 
)
static

Definition at line 116 of file write.c.

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

Referenced by alloc_chunk().

◆ find_new_dup_stripes()

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

Definition at line 137 of file write.c.

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

Referenced by alloc_chunk().

◆ find_new_stripe()

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

Definition at line 248 of file write.c.

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

Referenced by alloc_chunk().

◆ free_write_data_stripes()

void free_write_data_stripes ( write_data_context wtc)

Definition at line 2307 of file write.c.

2307  {
2308  LIST_ENTRY* le;
2309  PMDL last_mdl = NULL;
2310 
2311  if (wtc->parity1_mdl) {
2312  if (wtc->parity1_mdl->MdlFlags & MDL_PAGES_LOCKED)
2313  MmUnlockPages(wtc->parity1_mdl);
2314 
2315  IoFreeMdl(wtc->parity1_mdl);
2316  }
2317 
2318  if (wtc->parity2_mdl) {
2319  if (wtc->parity2_mdl->MdlFlags & MDL_PAGES_LOCKED)
2320  MmUnlockPages(wtc->parity2_mdl);
2321 
2322  IoFreeMdl(wtc->parity2_mdl);
2323  }
2324 
2325  if (wtc->mdl) {
2326  if (wtc->mdl->MdlFlags & MDL_PAGES_LOCKED)
2327  MmUnlockPages(wtc->mdl);
2328 
2329  IoFreeMdl(wtc->mdl);
2330  }
2331 
2332  if (wtc->parity1)
2333  ExFreePool(wtc->parity1);
2334 
2335  if (wtc->parity2)
2336  ExFreePool(wtc->parity2);
2337 
2338  if (wtc->scratch)
2339  ExFreePool(wtc->scratch);
2340 
2341  le = wtc->stripes.Flink;
2342  while (le != &wtc->stripes) {
2344 
2345  if (stripe->mdl && stripe->mdl != last_mdl) {
2346  if (stripe->mdl->MdlFlags & MDL_PAGES_LOCKED)
2347  MmUnlockPages(stripe->mdl);
2348 
2349  IoFreeMdl(stripe->mdl);
2350  }
2351 
2352  last_mdl = stripe->mdl;
2353 
2354  if (stripe->Irp)
2355  IoFreeIrp(stripe->Irp);
2356 
2357  le = le->Flink;
2358  }
2359 
2360  while (!IsListEmpty(&wtc->stripes)) {
2362 
2363  ExFreePool(stripe);
2364  }
2365 }
Definition: write.c:111
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1439
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
uint8_t * scratch
Definition: btrfs_drv.h:949
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:121
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19
uint8_t * parity1
Definition: btrfs_drv.h:949
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
Definition: typedefs.h:119
Definition: list.h:27
LIST_ENTRY stripes
Definition: btrfs_drv.h:946
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
ExFreePool(ed)
uint8_t * parity2
Definition: btrfs_drv.h:949

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

◆ get_chunk_from_address()

chunk* get_chunk_from_address ( device_extension Vcb,
uint64_t  address 
)

Definition at line 89 of file write.c.

89  {
90  LIST_ENTRY* le2;
91 
92  ExAcquireResourceSharedLite(&Vcb->chunk_lock, true);
93 
94  le2 = Vcb->chunks.Flink;
95  while (le2 != &Vcb->chunks) {
97 
98  if (address >= c->offset && address < c->offset + c->chunk_item->size) {
99  ExReleaseResourceLite(&Vcb->chunk_lock);
100  return c;
101  }
102 
103  le2 = le2->Flink;
104  }
105 
106  ExReleaseResourceLite(&Vcb->chunk_lock);
107 
108  return NULL;
109 }
GLintptr offset
Definition: glext.h:5920
smooth NULL
Definition: ftsmooth.c:416
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define Vcb
Definition: cdprocs.h:1415
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:119
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:2800

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

◆ get_raid56_lock_range()

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

Definition at line 2166 of file write.c.

2166  {
2167  uint64_t startoff, endoff;
2168  uint16_t startoffstripe, endoffstripe, datastripes;
2169 
2170  datastripes = c->chunk_item->num_stripes - (c->chunk_item->type & BLOCK_FLAG_RAID5 ? 1 : 2);
2171 
2172  get_raid0_offset(address - c->offset, c->chunk_item->stripe_length, datastripes, &startoff, &startoffstripe);
2173  get_raid0_offset(address + length - c->offset - 1, c->chunk_item->stripe_length, datastripes, &endoff, &endoffstripe);
2174 
2175  startoff -= startoff % c->chunk_item->stripe_length;
2176  endoff = sector_align(endoff, c->chunk_item->stripe_length);
2177 
2178  *lockaddr = c->offset + (startoff * datastripes);
2179  *locklen = (endoff - startoff) * datastripes;
2180 }
unsigned short int uint16_t
Definition: acefiex.h:54
_Post_satisfies_ static stripe __inline void get_raid0_offset(_In_ uint64_t off, _In_ uint64_t stripe_length, _In_ uint16_t num_stripes, _Out_ uint64_t *stripeoff, _Out_ uint16_t *stripe)
Definition: btrfs_drv.h:1005
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
const GLubyte * c
Definition: glext.h:8905
GLuint address
Definition: glext.h:9393
UINT64 uint64_t
Definition: types.h:77
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
static uint64_t __inline sector_align(uint64_t n, uint64_t a)

Referenced by read_data(), and write_data_complete().

◆ if() [1/5]

◆ if() [2/5]

if ( ed)

Definition at line 2816 of file write.c.

2816  {
2817  ERR("out of memory\n");
2818  return false;
2819  }
#define ERR(fmt,...)
Definition: debug.h:110

◆ if() [3/5]

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

Definition at line 2834 of file write.c.

2834  {
2835  ULONG sl = (ULONG)(length / Vcb->superblock.sector_size);
2836 
2837  csum = ExAllocatePoolWithTag(PagedPool, sl * Vcb->csum_size, ALLOC_TAG);
2838  if (!csum) {
2839  ERR("out of memory\n");
2840  ExFreePool(ed);
2841  return false;
2842  }
2843 
2844  do_calc_job(Vcb, data, sl, csum);
2845  }
#define ALLOC_TAG
Definition: btrfs_drv.h:91
void do_calc_job(device_extension *Vcb, uint8_t *data, uint32_t sectors, void *csum)
Definition: calcthread.c:141
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define Vcb
Definition: cdprocs.h:1415
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
#define ERR(fmt,...)
Definition: debug.h:110
Definition: fs.h:216
unsigned int ULONG
Definition: retypes.h:1
ExFreePool(ed)
EXTENT_DATA * ed
Definition: write.c:2804

◆ if() [4/5]

if ( NT_SUCCESSStatus)

Definition at line 2848 of file write.c.

2848  {
2849  ERR("add_extent_to_fcb returned %08lx\n", Status);
2850  if (csum) ExFreePool(csum);
2851  ExFreePool(ed);
2852  return false;
2853  }
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
Definition: fs.h:216
ExFreePool(ed)
EXTENT_DATA * ed
Definition: write.c:2804

◆ if() [5/5]

if ( data  )

Definition at line 2874 of file write.c.

2874  {
2877  if (!NT_SUCCESS(Status))
2878  ERR("write_data_complete returned %08lx\n", Status);
2879  }
_In_ PIRP Irp
Definition: csq.h:116
#define FSRTL_FLAG2_IS_PAGING_FILE
Definition: fsrtltypes.h:57
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool _In_ uint64_t irp_offset
Definition: write.c:2801
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool file_write
Definition: write.c:2800
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS write_data_complete(device_extension *Vcb, uint64_t address, void *data, uint32_t length, PIRP Irp, chunk *c, bool file_write, uint64_t irp_offset, ULONG priority)
Definition: write.c:2182
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:294
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define Vcb
Definition: cdprocs.h:1415
GLuint address
Definition: glext.h:9393
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
UINT32 uint32_t
Definition: types.h:75

◆ insert_chunk_fragmented()

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

Definition at line 2976 of file write.c.

2976  {
2977  LIST_ENTRY* le;
2978  uint64_t flags = fcb->Vcb->data_flags;
2979  bool page_file = fcb->Header.Flags2 & FSRTL_FLAG2_IS_PAGING_FILE;
2980  NTSTATUS Status;
2981  chunk* c;
2982 
2983  ExAcquireResourceSharedLite(&fcb->Vcb->chunk_lock, true);
2984 
2985  // first create as many chunks as we can
2986  do {
2987  Status = alloc_chunk(fcb->Vcb, flags, &c, false);
2988  } while (NT_SUCCESS(Status));
2989 
2990  if (Status != STATUS_DISK_FULL) {
2991  ERR("alloc_chunk returned %08lx\n", Status);
2992  ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
2993  return Status;
2994  }
2995 
2996  le = fcb->Vcb->chunks.Flink;
2997  while (le != &fcb->Vcb->chunks) {
2999 
3000  if (!c->readonly && !c->reloc) {
3002 
3003  if (c->chunk_item->type == flags) {
3004  while (!IsListEmpty(&c->space_size) && length > 0) {
3005  space* s = CONTAINING_RECORD(c->space_size.Flink, space, list_entry_size);
3006  uint64_t extlen = min(length, s->size);
3007 
3008  if (insert_extent_chunk(fcb->Vcb, fcb, c, start, extlen, prealloc && !page_file, data, NULL, rollback, BTRFS_COMPRESSION_NONE, extlen, false, 0)) {
3009  start += extlen;
3010  length -= extlen;
3011  if (data) data += extlen;
3012 
3014  }
3015  }
3016  }
3017 
3019 
3020  if (length == 0)
3021  break;
3022  }
3023 
3024  le = le->Flink;
3025  }
3026 
3027  ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
3028 
3029  return length == 0 ? STATUS_SUCCESS : STATUS_DISK_FULL;
3030 }
NTSTATUS Status
Definition: write.c:2803
#define BTRFS_COMPRESSION_NONE
Definition: btrfs.h:61
#define FSRTL_FLAG2_IS_PAGING_FILE
Definition: fsrtltypes.h:57
LONG NTSTATUS
Definition: precomp.h:26
release_chunk_lock(c, Vcb)
_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
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:294
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
const GLubyte * c
Definition: glext.h:8905
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: write.c:2800
NTSTATUS alloc_chunk(device_extension *Vcb, uint64_t flags, chunk **pc, bool full_size)
Definition: write.c:361
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLbitfield flags
Definition: glext.h:7161
Status
Definition: gdiplustypes.h:24
GLdouble s
Definition: gl.h:2039
Definition: typedefs.h:119
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool prealloc
Definition: write.c:2800
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1137
GLuint start
Definition: gl.h:1545
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
return STATUS_SUCCESS
Definition: btrfs.c:3014
_In_ fcb _In_ chunk * c
Definition: write.c:2800
struct _device_extension * Vcb
Definition: btrfs_drv.h:298

Referenced by insert_extent(), and insert_prealloc_extent().

◆ insert_extent()

static NTSTATUS insert_extent ( device_extension Vcb,
fcb fcb,
uint64_t  start_data,
uint64_t  length,
void data,
PIRP  Irp,
bool  file_write,
uint64_t  irp_offset,
LIST_ENTRY rollback 
)
static

Definition at line 3105 of file write.c.

3106  {
3107  NTSTATUS Status;
3108  LIST_ENTRY* le;
3109  chunk* c;
3110  uint64_t flags, orig_length = length, written = 0;
3111 
3112  TRACE("(%p, (%I64x, %I64x), %I64x, %I64x, %p)\n", Vcb, fcb->subvol->id, fcb->inode, start_data, length, data);
3113 
3114  if (start_data > 0) {
3116 
3117  if (written == length)
3118  return STATUS_SUCCESS;
3119  else if (written > 0) {
3120  start_data += written;
3121  irp_offset += written;
3122  length -= written;
3123  data = &((uint8_t*)data)[written];
3124  }
3125  }
3126 
3127  flags = Vcb->data_flags;
3128 
3129  while (written < orig_length) {
3130  uint64_t newlen = min(length, MAX_EXTENT_SIZE);
3131  bool done = false;
3132 
3133  // Rather than necessarily writing the whole extent at once, we deal with it in blocks of 128 MB.
3134  // First, see if we can write the extent part to an existing chunk.
3135 
3136  ExAcquireResourceSharedLite(&Vcb->chunk_lock, true);
3137 
3138  le = Vcb->chunks.Flink;
3139  while (le != &Vcb->chunks) {
3141