[BTRFS] Upgrade to 1.2.1

CORE-16004
This commit is contained in:
Pierre Schweitzer 2019-05-11 11:20:02 +02:00
parent 927e1d0968
commit 883b1f31ac
No known key found for this signature in database
GPG key ID: 7545556C3D585B0B
16 changed files with 1788 additions and 1441 deletions

View file

@ -2108,8 +2108,6 @@ end:
// update open FCBs
// FIXME - speed this up(?)
acquire_fcb_lock_shared(Vcb);
le = Vcb->all_fcbs.Flink;
while (le != &Vcb->all_fcbs) {
struct _fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_all);
@ -2148,8 +2146,6 @@ end:
le = le->Flink;
}
release_fcb_lock(Vcb);
} else
do_rollback(Vcb, &rollback);

View file

@ -1036,6 +1036,8 @@ NTSTATUS create_root(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) devi
return STATUS_INSUFFICIENT_RESOURCES;
}
t->nonpaged = NULL;
t->is_unique = TRUE;
t->uniqueness_determined = TRUE;
t->buf = NULL;
@ -1065,7 +1067,9 @@ NTSTATUS create_root(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) devi
r->send_ops = 0;
RtlZeroMemory(&r->root_item, sizeof(ROOT_ITEM));
r->root_item.num_references = 1;
r->fcbs_version = 0;
InitializeListHead(&r->fcbs);
RtlZeroMemory(r->fcbs_ptrs, sizeof(LIST_ENTRY*) * 256);
RtlCopyMemory(ri, &r->root_item, sizeof(ROOT_ITEM));
@ -1391,7 +1395,7 @@ void send_notification_fcb(_In_ file_ref* fileref, _In_ ULONG filter_match, _In_
return;
}
acquire_fcb_lock_exclusive(fcb->Vcb);
ExAcquireResourceExclusiveLite(&fcb->Vcb->fileref_lock, TRUE);
le = fcb->hardlinks.Flink;
while (le != &fcb->hardlinks) {
@ -1410,7 +1414,7 @@ void send_notification_fcb(_In_ file_ref* fileref, _In_ ULONG filter_match, _In_
Status = fileref_get_filename(parfr, &fn, NULL, &pathlen);
if (Status != STATUS_BUFFER_OVERFLOW) {
ERR("fileref_get_filename returned %08x\n", Status);
free_fileref(fcb->Vcb, parfr);
free_fileref(parfr);
break;
}
@ -1419,7 +1423,7 @@ void send_notification_fcb(_In_ file_ref* fileref, _In_ ULONG filter_match, _In_
if (pathlen + hl->name.Length > 0xffff) {
WARN("pathlen + hl->name.Length was too long for FsRtlNotifyFilterReportChange\n");
free_fileref(fcb->Vcb, parfr);
free_fileref(parfr);
break;
}
@ -1427,14 +1431,14 @@ void send_notification_fcb(_In_ file_ref* fileref, _In_ ULONG filter_match, _In_
fn.Buffer = ExAllocatePoolWithTag(PagedPool, fn.MaximumLength, ALLOC_TAG);
if (!fn.Buffer) {
ERR("out of memory\n");
free_fileref(fcb->Vcb, parfr);
free_fileref(parfr);
break;
}
Status = fileref_get_filename(parfr, &fn, NULL, NULL);
if (!NT_SUCCESS(Status)) {
ERR("fileref_get_filename returned %08x\n", Status);
free_fileref(fcb->Vcb, parfr);
free_fileref(parfr);
ExFreePool(fn.Buffer);
break;
}
@ -1452,13 +1456,13 @@ void send_notification_fcb(_In_ file_ref* fileref, _In_ ULONG filter_match, _In_
ExFreePool(fn.Buffer);
free_fileref(fcb->Vcb, parfr);
free_fileref(parfr);
}
le = le->Flink;
}
release_fcb_lock(fcb->Vcb);
ExReleaseResourceLite(&fcb->Vcb->fileref_lock);
}
void mark_fcb_dirty(_In_ fcb* fcb) {
@ -1497,24 +1501,31 @@ void mark_fileref_dirty(_In_ file_ref* fileref) {
}
#ifdef DEBUG_FCB_REFCOUNTS
void _free_fcb(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension* Vcb, _Inout_ fcb* fcb, _In_ const char* func) {
void _free_fcb(_Inout_ fcb* fcb, _In_ const char* func) {
LONG rc = InterlockedDecrement(&fcb->refcount);
#else
void free_fcb(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension* Vcb, _Inout_ fcb* fcb) {
void free_fcb(_Inout_ fcb* fcb) {
InterlockedDecrement(&fcb->refcount);
#endif
LONG rc;
rc = InterlockedDecrement(&fcb->refcount);
#ifdef DEBUG_FCB_REFCOUNTS
#ifdef DEBUG_LONG_MESSAGES
ERR("fcb %p: refcount now %i (subvol %llx, inode %llx)\n", fcb, rc, fcb->subvol ? fcb->subvol->id : 0, fcb->inode);
ERR("fcb %p (%s): refcount now %i (subvol %llx, inode %llx)\n", fcb, func, rc, fcb->subvol ? fcb->subvol->id : 0, fcb->inode);
#else
ERR("fcb %p: refcount now %i (subvol %llx, inode %llx)\n", fcb, rc, fcb->subvol ? fcb->subvol->id : 0, fcb->inode);
ERR("fcb %p (%s): refcount now %i (subvol %llx, inode %llx)\n", fcb, func, rc, fcb->subvol ? fcb->subvol->id : 0, fcb->inode);
#endif
#endif
}
if (rc > 0)
return;
void reap_fcb(fcb* fcb) {
UINT8 c = fcb->hash >> 24;
if (fcb->subvol && fcb->subvol->fcbs_ptrs[c] == &fcb->list_entry) {
if (fcb->list_entry.Flink != &fcb->subvol->fcbs && (CONTAINING_RECORD(fcb->list_entry.Flink, struct _fcb, list_entry)->hash >> 24) == c)
fcb->subvol->fcbs_ptrs[c] = fcb->list_entry.Flink;
else
fcb->subvol->fcbs_ptrs[c] = NULL;
}
if (fcb->list_entry.Flink)
RemoveEntryList(&fcb->list_entry);
@ -1526,7 +1537,7 @@ void free_fcb(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_exten
ExDeleteResourceLite(&fcb->nonpaged->paging_resource);
ExDeleteResourceLite(&fcb->nonpaged->dir_children_lock);
ExFreeToNPagedLookasideList(&Vcb->fcb_np_lookaside, fcb->nonpaged);
ExFreeToNPagedLookasideList(&fcb->Vcb->fcb_np_lookaside, fcb->nonpaged);
if (fcb->sd)
ExFreePool(fcb->sd);
@ -1596,21 +1607,31 @@ void free_fcb(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_exten
if (fcb->pool_type == NonPagedPool)
ExFreePool(fcb);
else
ExFreeToPagedLookasideList(&Vcb->fcb_lookaside, fcb);
#ifdef DEBUG_FCB_REFCOUNTS
#ifdef DEBUG_LONG_MESSAGES
_debug_message(func, file, line, "freeing fcb %p\n", fcb);
#else
_debug_message(func, "freeing fcb %p\n", fcb);
#endif
#endif
ExFreeToPagedLookasideList(&fcb->Vcb->fcb_lookaside, fcb);
}
void free_fileref(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension* Vcb, _Inout_ file_ref* fr) {
void reap_fcbs(device_extension* Vcb) {
LIST_ENTRY* le;
le = Vcb->all_fcbs.Flink;
while (le != &Vcb->all_fcbs) {
fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_all);
LIST_ENTRY* le2 = le->Flink;
if (fcb->refcount == 0)
reap_fcb(fcb);
le = le2;
}
}
void free_fileref(_Inout_ file_ref* fr) {
LONG rc;
rc = InterlockedDecrement(&fr->refcount);
#ifdef __REACTOS__
(void)rc;
#endif
#ifdef DEBUG_FCB_REFCOUNTS
ERR("fileref %p: refcount now %i\n", fr, rc);
@ -1622,13 +1643,9 @@ void free_fileref(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_e
int3;
}
#endif
}
if (rc > 0)
return;
if (fr->parent)
ExAcquireResourceExclusiveLite(&fr->parent->nonpaged->children_lock, TRUE);
void reap_fileref(device_extension* Vcb, file_ref* fr) {
// FIXME - do we need a file_ref lock?
// FIXME - do delete if needed
@ -1636,7 +1653,6 @@ void free_fileref(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_e
if (fr->debug_desc)
ExFreePool(fr->debug_desc);
ExDeleteResourceLite(&fr->nonpaged->children_lock);
ExDeleteResourceLite(&fr->nonpaged->fileref_lock);
ExFreeToNPagedLookasideList(&Vcb->fileref_np_lookaside, fr->nonpaged);
@ -1656,22 +1672,38 @@ void free_fileref(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_e
if (fr->list_entry.Flink)
RemoveEntryList(&fr->list_entry);
if (fr->parent) {
ExReleaseResourceLite(&fr->parent->nonpaged->children_lock);
free_fileref(Vcb, fr->parent);
}
if (fr->parent)
free_fileref(fr->parent);
free_fcb(Vcb, fr->fcb);
free_fcb(fr->fcb);
ExFreeToPagedLookasideList(&Vcb->fileref_lookaside, fr);
}
void reap_filerefs(device_extension* Vcb, file_ref* fr) {
LIST_ENTRY* le;
// FIXME - recursion is a bad idea in kernel mode
le = fr->children.Flink;
while (le != &fr->children) {
file_ref* c = CONTAINING_RECORD(le, file_ref, list_entry);
LIST_ENTRY* le2 = le->Flink;
reap_filerefs(Vcb, c);
le = le2;
}
if (fr->refcount == 0)
reap_fileref(Vcb, fr);
}
static NTSTATUS close_file(_In_ PFILE_OBJECT FileObject, _In_ PIRP Irp) {
fcb* fcb;
ccb* ccb;
file_ref* fileref = NULL;
LONG open_files;
device_extension* Vcb;
UNUSED(Irp);
@ -1735,16 +1767,10 @@ static NTSTATUS close_file(_In_ PFILE_OBJECT FileObject, _In_ PIRP Irp) {
if (!(fcb->Vcb->Vpb->Flags & VPB_MOUNTED))
return STATUS_SUCCESS;
Vcb = fcb->Vcb;
acquire_fcb_lock_exclusive(Vcb);
if (fileref)
free_fileref(fcb->Vcb, fileref);
free_fileref(fileref);
else
free_fcb(Vcb, fcb);
release_fcb_lock(Vcb);
free_fcb(fcb);
return STATUS_SUCCESS;
}
@ -1835,10 +1861,8 @@ void uninit(_In_ device_extension* Vcb) {
KeSetTimer(&Vcb->flush_thread_timer, time, NULL); // trigger the timer early
KeWaitForSingleObject(&Vcb->flush_thread_finished, Executive, KernelMode, FALSE, NULL);
acquire_fcb_lock_exclusive(Vcb);
free_fcb(Vcb, Vcb->volume_fcb);
free_fcb(Vcb, Vcb->dummy_fcb);
release_fcb_lock(Vcb);
reap_fcb(Vcb->volume_fcb);
reap_fcb(Vcb->dummy_fcb);
if (Vcb->root_file)
ObDereferenceObject(Vcb->root_file);
@ -1848,9 +1872,7 @@ void uninit(_In_ device_extension* Vcb) {
chunk* c = CONTAINING_RECORD(le, chunk, list_entry);
if (c->cache) {
acquire_fcb_lock_exclusive(Vcb);
free_fcb(Vcb, c->cache);
release_fcb_lock(Vcb);
reap_fcb(c->cache);
c->cache = NULL;
}
@ -1885,11 +1907,8 @@ void uninit(_In_ device_extension* Vcb) {
if (c->devices)
ExFreePool(c->devices);
if (c->cache) {
acquire_fcb_lock_exclusive(Vcb);
free_fcb(Vcb, c->cache);
release_fcb_lock(Vcb);
}
if (c->cache)
reap_fcb(c->cache);
ExDeleteResourceLite(&c->range_locks_lock);
ExDeleteResourceLite(&c->partial_stripes_lock);
@ -1924,6 +1943,7 @@ void uninit(_In_ device_extension* Vcb) {
ExReleaseResourceLite(&Vcb->scrub.stats_lock);
ExDeleteResourceLite(&Vcb->fcb_lock);
ExDeleteResourceLite(&Vcb->fileref_lock);
ExDeleteResourceLite(&Vcb->load_lock);
ExDeleteResourceLite(&Vcb->tree_lock);
ExDeleteResourceLite(&Vcb->chunk_lock);
@ -2269,21 +2289,19 @@ static NTSTATUS drv_cleanup(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
ExReleaseResourceLite(fcb->Header.Resource);
locked = FALSE;
// fcb_lock needs to be acquired before fcb->Header.Resource
acquire_fcb_lock_exclusive(fcb->Vcb);
// fileref_lock needs to be acquired before fcb->Header.Resource
ExAcquireResourceExclusiveLite(&fcb->Vcb->fileref_lock, TRUE);
Status = delete_fileref(fileref, FileObject, Irp, &rollback);
if (!NT_SUCCESS(Status)) {
ERR("delete_fileref returned %08x\n", Status);
do_rollback(fcb->Vcb, &rollback);
release_fcb_lock(fcb->Vcb);
ExReleaseResourceLite(&fcb->Vcb->fileref_lock);
ExReleaseResourceLite(&fcb->Vcb->tree_lock);
goto exit;
}
release_fcb_lock(fcb->Vcb);
locked = FALSE;
ExReleaseResourceLite(&fcb->Vcb->fileref_lock);
clear_rollback(&rollback);
} else if (FileObject->Flags & FO_CACHE_SUPPORTED && fcb->nonpaged->segment_object.DataSectionObject) {
@ -2658,7 +2676,9 @@ static NTSTATUS add_root(_Inout_ device_extension* Vcb, _In_ UINT64 id, _In_ UIN
r->treeholder.generation = generation;
r->parent = 0;
r->send_ops = 0;
r->fcbs_version = 0;
InitializeListHead(&r->fcbs);
RtlZeroMemory(r->fcbs_ptrs, sizeof(LIST_ENTRY*) * 256);
r->nonpaged = ExAllocatePoolWithTag(NonPagedPool, sizeof(root_nonpaged), ALLOC_TAG);
if (!r->nonpaged) {
@ -4132,6 +4152,7 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
Vcb->need_write = FALSE;
ExInitializeResourceLite(&Vcb->fcb_lock);
ExInitializeResourceLite(&Vcb->fileref_lock);
ExInitializeResourceLite(&Vcb->chunk_lock);
ExInitializeResourceLite(&Vcb->dirty_fcbs_lock);
ExInitializeResourceLite(&Vcb->dirty_filerefs_lock);
@ -4260,6 +4281,8 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
InitializeListHead(&Vcb->dirty_subvols);
InitializeListHead(&Vcb->send_ops);
ExInitializeFastMutex(&Vcb->trees_list_mutex);
InitializeListHead(&Vcb->DirNotifyList);
InitializeListHead(&Vcb->scrub.errors);
@ -4424,6 +4447,7 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
root_fcb->Vcb = Vcb;
root_fcb->inode = SUBVOL_ROOT_INODE;
root_fcb->hash = calc_crc32c(0xffffffff, (UINT8*)&root_fcb->inode, sizeof(UINT64));
root_fcb->type = BTRFS_TYPE_DIRECTORY;
#ifdef DEBUG_FCB_REFCOUNTS
@ -4479,6 +4503,8 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
InsertTailList(&root_fcb->subvol->fcbs, &root_fcb->list_entry);
InsertTailList(&Vcb->all_fcbs, &root_fcb->list_entry_all);
root_fcb->subvol->fcbs_ptrs[root_fcb->hash >> 24] = &root_fcb->list_entry;
root_fcb->fileref = Vcb->root_fileref;
root_ccb = ExAllocatePoolWithTag(PagedPool, sizeof(ccb), ALLOC_TAG);
@ -4596,25 +4622,21 @@ exit2:
if (Vcb->root_file)
ObDereferenceObject(Vcb->root_file);
else if (Vcb->root_fileref) {
acquire_fcb_lock_exclusive(Vcb);
free_fileref(Vcb, Vcb->root_fileref);
release_fcb_lock(Vcb);
} else if (root_fcb) {
acquire_fcb_lock_exclusive(Vcb);
free_fcb(Vcb, root_fcb);
release_fcb_lock(Vcb);
}
else if (Vcb->root_fileref)
free_fileref(Vcb->root_fileref);
else if (root_fcb)
free_fcb(root_fcb);
if (Vcb->volume_fcb) {
acquire_fcb_lock_exclusive(Vcb);
free_fcb(Vcb, Vcb->volume_fcb);
release_fcb_lock(Vcb);
}
if (root_fcb && root_fcb->refcount == 0)
reap_fcb(root_fcb);
if (Vcb->volume_fcb)
reap_fcb(Vcb->volume_fcb);
ExDeleteResourceLite(&Vcb->tree_lock);
ExDeleteResourceLite(&Vcb->load_lock);
ExDeleteResourceLite(&Vcb->fcb_lock);
ExDeleteResourceLite(&Vcb->fileref_lock);
ExDeleteResourceLite(&Vcb->chunk_lock);
ExDeleteResourceLite(&Vcb->dirty_fcbs_lock);
ExDeleteResourceLite(&Vcb->dirty_filerefs_lock);

View file

@ -13,13 +13,11 @@
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.K.) resources
// English (United Kingdom) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
@ -27,18 +25,18 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
// TEXTINCLUDE
//
1 TEXTINCLUDE
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
@ -53,8 +51,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,1,0,0
PRODUCTVERSION 1,1,0,0
FILEVERSION 1,2,1,0
PRODUCTVERSION 1,2,1,0
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -70,12 +68,12 @@ BEGIN
BLOCK "080904b0"
BEGIN
VALUE "FileDescription", "WinBtrfs"
VALUE "FileVersion", "1.1"
VALUE "FileVersion", "1.2.1"
VALUE "InternalName", "btrfs"
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-18"
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-19"
VALUE "OriginalFilename", "btrfs.sys"
VALUE "ProductName", "WinBtrfs"
VALUE "ProductVersion", "1.1"
VALUE "ProductVersion", "1.2.1"
END
END
BLOCK "VarFileInfo"
@ -84,7 +82,7 @@ BEGIN
END
END
#endif // English (U.K.) resources
#endif // English (United Kingdom) resources
/////////////////////////////////////////////////////////////////////////////

View file

@ -260,6 +260,7 @@ typedef struct _fcb {
struct _device_extension* Vcb;
struct _root* subvol;
UINT64 inode;
UINT32 hash;
UINT8 type;
INODE_ITEM inode_item;
SECURITY_DESCRIPTOR* sd;
@ -309,7 +310,6 @@ typedef struct _fcb {
typedef struct {
ERESOURCE fileref_lock;
ERESOURCE children_lock;
} file_ref_nonpaged;
typedef struct _file_ref {
@ -392,7 +392,12 @@ typedef struct _tree_data {
};
} tree_data;
typedef struct {
FAST_MUTEX mutex;
} tree_nonpaged;
typedef struct _tree {
tree_nonpaged* nonpaged;
tree_header header;
UINT32 hash;
BOOL has_address;
@ -428,7 +433,9 @@ typedef struct _root {
PEPROCESS reserved;
UINT64 parent;
LONG send_ops;
UINT64 fcbs_version;
LIST_ENTRY fcbs;
LIST_ENTRY* fcbs_ptrs[256];
LIST_ENTRY list_entry;
LIST_ENTRY list_entry_dirty;
} root;
@ -742,6 +749,7 @@ typedef struct _device_extension {
file_ref* root_fileref;
LONG open_files;
_Has_lock_level_(fcb_lock) ERESOURCE fcb_lock;
ERESOURCE fileref_lock;
ERESOURCE load_lock;
_Has_lock_level_(tree_lock) ERESOURCE tree_lock;
PNOTIFY_SYNC NotifySync;
@ -768,6 +776,7 @@ typedef struct _device_extension {
LIST_ENTRY trees;
LIST_ENTRY trees_hash;
LIST_ENTRY* trees_ptrs[256];
FAST_MUTEX trees_list_mutex;
LIST_ENTRY all_fcbs;
LIST_ENTRY dirty_fcbs;
ERESOURCE dirty_fcbs_lock;
@ -1087,9 +1096,9 @@ BOOL get_xattr(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension* Vc
_Out_ UINT8** data, _Out_ UINT16* datalen, _In_opt_ PIRP Irp);
#ifndef DEBUG_FCB_REFCOUNTS
void free_fcb(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension* Vcb, _Inout_ fcb* fcb);
void free_fcb(_Inout_ fcb* fcb);
#endif
void free_fileref(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension* Vcb, _Inout_ file_ref* fr);
void free_fileref(_Inout_ file_ref* fr);
void protect_superblocks(_Inout_ chunk* c);
BOOL is_top_level(_In_ PIRP Irp);
NTSTATUS create_root(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_ UINT64 id,
@ -1129,6 +1138,10 @@ NTSTATUS NTAPI AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDev
#else
NTSTATUS AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject);
#endif
void reap_fcb(fcb* fcb);
void reap_fcbs(device_extension* Vcb);
void reap_fileref(device_extension* Vcb, file_ref* fr);
void reap_filerefs(device_extension* Vcb, file_ref* fr);
#ifdef _MSC_VER
#define funcname __FUNCTION__
@ -1192,8 +1205,8 @@ void _debug_message(_In_ const char* func, _In_ char* s, ...);
#endif
#ifdef DEBUG_FCB_REFCOUNTS
void _free_fcb(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension* Vcb, _Inout_ fcb* fcb, _In_ const char* func);
#define free_fcb(Vcb, fcb) _free_fcb(Vcb, fcb, funcname)
void _free_fcb(_Inout_ fcb* fcb, _In_ const char* func);
#define free_fcb(fcb) _free_fcb(fcb, funcname)
#endif
// in fastio.c
@ -1251,9 +1264,9 @@ NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock)
_In_ UINT8 obj_type, _In_ UINT64 offset, _In_reads_bytes_opt_(size) _When_(return >= 0, __drv_aliasesMem) void* data,
_In_ UINT16 size, _Out_opt_ traverse_ptr* ptp, _In_opt_ PIRP Irp);
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _Inout_ traverse_ptr* tp);
tree* free_tree(tree* t);
NTSTATUS load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, UINT64 generation, PIRP Irp);
NTSTATUS do_load_tree(device_extension* Vcb, tree_holder* th, root* r, tree* t, tree_data* td, BOOL* loaded, PIRP Irp);
void free_tree(tree* t);
NTSTATUS load_tree(device_extension* Vcb, UINT64 addr, UINT8* buf, root* r, tree** pt);
NTSTATUS do_load_tree(device_extension* Vcb, tree_holder* th, root* r, tree* t, tree_data* td, PIRP Irp);
void clear_rollback(LIST_ENTRY* rollback);
void do_rollback(device_extension* Vcb, LIST_ENTRY* rollback);
void free_trees_root(device_extension* Vcb, root* r);
@ -1380,7 +1393,6 @@ NTSTATUS NTAPI drv_set_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
BOOL has_open_children(file_ref* fileref);
NTSTATUS stream_set_end_of_file_information(device_extension* Vcb, UINT16 end, fcb* fcb, file_ref* fileref, BOOL advance_only);
NTSTATUS fileref_get_filename(file_ref* fileref, PUNICODE_STRING fn, USHORT* name_offset, ULONG* preqlen);
NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension* Vcb, root* subvol, UINT64 inode, file_ref** pfr, PIRP Irp);
void insert_dir_child_into_hash_lists(fcb* fcb, dir_child* dc);
void remove_dir_child_from_hash_lists(fcb* fcb, dir_child* dc);
@ -1411,6 +1423,7 @@ fcb* create_fcb(device_extension* Vcb, POOL_TYPE pool_type);
NTSTATUS find_file_in_dir(PUNICODE_STRING filename, fcb* fcb, root** subvol, UINT64* inode, dir_child** pdc, BOOL case_sensitive);
UINT32 inherit_mode(fcb* parfcb, BOOL is_dir);
file_ref* create_fileref(device_extension* Vcb);
NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension* Vcb, root* subvol, UINT64 inode, file_ref** pfr, PIRP Irp);
// in fsctl.c
NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP* Pirp, UINT32 type);

File diff suppressed because it is too large Load diff

View file

@ -91,7 +91,7 @@ ULONG get_reparse_tag(device_extension* Vcb, root* subvol, UINT64 inode, UINT8 t
ExReleaseResourceLite(fcb->Header.Resource);
free_fcb(Vcb, fcb);
free_fcb(fcb);
return tag;
}
@ -602,7 +602,6 @@ static NTSTATUS query_directory(PIRP Irp) {
BOOL has_wildcard = FALSE, specific_file = FALSE, initial;
dir_entry de;
UINT64 newoffset;
ANSI_STRING utf8;
dir_child* dc = NULL;
TRACE("query directory\n");
@ -612,8 +611,6 @@ static NTSTATUS query_directory(PIRP Irp) {
ccb = IrpSp->FileObject->FsContext2;
fileref = ccb ? ccb->fileref : NULL;
utf8.Buffer = NULL;
if (!fileref)
return STATUS_INVALID_PARAMETER;
@ -642,11 +639,6 @@ static NTSTATUS query_directory(PIRP Irp) {
if (fileref->fcb == Vcb->dummy_fcb)
return STATUS_NO_MORE_FILES;
ExAcquireResourceSharedLite(&Vcb->tree_lock, TRUE);
acquire_fcb_lock_shared(Vcb);
TRACE("%S\n", file_desc(IrpSp->FileObject));
if (IrpSp->Flags == 0) {
TRACE("QD flags: (none)\n");
} else {
@ -708,8 +700,7 @@ static NTSTATUS query_directory(PIRP Irp) {
ccb->query_string.Buffer = ExAllocatePoolWithTag(PagedPool, IrpSp->Parameters.QueryDirectory.FileName->Length, ALLOC_TAG);
if (!ccb->query_string.Buffer) {
ERR("out of memory\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
goto end2;
return STATUS_INSUFFICIENT_RESOURCES;
}
ccb->query_string.Length = ccb->query_string.MaximumLength = IrpSp->Parameters.QueryDirectory.FileName->Length;
@ -725,10 +716,8 @@ static NTSTATUS query_directory(PIRP Irp) {
if (!(IrpSp->Flags & SL_RESTART_SCAN)) {
initial = FALSE;
if (specific_file) {
Status = STATUS_NO_MORE_FILES;
goto end2;
}
if (specific_file)
return STATUS_NO_MORE_FILES;
}
}
@ -738,6 +727,8 @@ static NTSTATUS query_directory(PIRP Irp) {
newoffset = ccb->query_dir_offset;
ExAcquireResourceSharedLite(&Vcb->tree_lock, TRUE);
ExAcquireResourceSharedLite(&fileref->fcb->nonpaged->dir_children_lock, TRUE);
Status = next_dir_entry(fileref, &newoffset, &de, &dc);
@ -923,15 +914,10 @@ static NTSTATUS query_directory(PIRP Irp) {
end:
ExReleaseResourceLite(&fileref->fcb->nonpaged->dir_children_lock);
end2:
release_fcb_lock(Vcb);
ExReleaseResourceLite(&Vcb->tree_lock);
TRACE("returning %08x\n", Status);
if (utf8.Buffer)
ExFreePool(utf8.Buffer);
return Status;
}

View file

@ -19,7 +19,7 @@
#if (NTDDI_VERSION >= NTDDI_WIN10)
// not currently in mingw - introduced with Windows 10
#ifndef FileIdInformation
#ifndef _MSC_VER
#define FileIdInformation (enum _FILE_INFORMATION_CLASS)59
#define FileStatLxInformation (enum _FILE_INFORMATION_CLASS)70
@ -230,8 +230,6 @@ static NTSTATUS set_disposition_information(device_extension* Vcb, PIRP Irp, PFI
if (!fileref)
return STATUS_INVALID_PARAMETER;
acquire_fcb_lock_exclusive(Vcb);
ExAcquireResourceExclusiveLite(fcb->Header.Resource, TRUE);
TRACE("changing delete_on_close to %s for %S (fcb %p)\n", fdi->DeleteFile ? "TRUE" : "FALSE", file_desc(FileObject), fcb);
@ -277,8 +275,6 @@ static NTSTATUS set_disposition_information(device_extension* Vcb, PIRP Irp, PFI
end:
ExReleaseResourceLite(fcb->Header.Resource);
release_fcb_lock(Vcb);
// send notification that directory is about to be deleted
if (NT_SUCCESS(Status) && fdi->DeleteFile && fcb->type == BTRFS_TYPE_DIRECTORY) {
FsRtlNotifyFullChangeDirectory(Vcb->NotifySync, &Vcb->DirNotifyList, FileObject->FsContext,
@ -343,7 +339,7 @@ static NTSTATUS duplicate_fcb(fcb* oldfcb, fcb** pfcb) {
if (!fcb->adsxattr.Buffer) {
ERR("out of memory\n");
free_fcb(Vcb, fcb);
free_fcb(fcb);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -357,7 +353,7 @@ static NTSTATUS duplicate_fcb(fcb* oldfcb, fcb** pfcb) {
if (!fcb->adsdata.Buffer) {
ERR("out of memory\n");
free_fcb(Vcb, fcb);
free_fcb(fcb);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -374,7 +370,7 @@ static NTSTATUS duplicate_fcb(fcb* oldfcb, fcb** pfcb) {
fcb->sd = ExAllocatePoolWithTag(PagedPool, RtlLengthSecurityDescriptor(oldfcb->sd), ALLOC_TAG);
if (!fcb->sd) {
ERR("out of memory\n");
free_fcb(Vcb, fcb);
free_fcb(fcb);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -392,7 +388,7 @@ static NTSTATUS duplicate_fcb(fcb* oldfcb, fcb** pfcb) {
if (!ext2) {
ERR("out of memory\n");
free_fcb(Vcb, fcb);
free_fcb(fcb);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -420,7 +416,7 @@ static NTSTATUS duplicate_fcb(fcb* oldfcb, fcb** pfcb) {
ext2->csum = ExAllocatePoolWithTag(PagedPool, len, ALLOC_TAG);
if (!ext2->csum) {
ERR("out of memory\n");
free_fcb(Vcb, fcb);
free_fcb(fcb);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -442,7 +438,7 @@ static NTSTATUS duplicate_fcb(fcb* oldfcb, fcb** pfcb) {
if (!hl2) {
ERR("out of memory\n");
free_fcb(Vcb, fcb);
free_fcb(fcb);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -455,7 +451,7 @@ static NTSTATUS duplicate_fcb(fcb* oldfcb, fcb** pfcb) {
if (!hl2->name.Buffer) {
ERR("out of memory\n");
ExFreePool(hl2);
free_fcb(Vcb, fcb);
free_fcb(fcb);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -468,7 +464,7 @@ static NTSTATUS duplicate_fcb(fcb* oldfcb, fcb** pfcb) {
ERR("out of memory\n");
ExFreePool(hl2->name.Buffer);
ExFreePool(hl2);
free_fcb(Vcb, fcb);
free_fcb(fcb);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -485,7 +481,7 @@ static NTSTATUS duplicate_fcb(fcb* oldfcb, fcb** pfcb) {
fcb->reparse_xattr.Buffer = ExAllocatePoolWithTag(PagedPool, fcb->reparse_xattr.MaximumLength, ALLOC_TAG);
if (!fcb->reparse_xattr.Buffer) {
ERR("out of memory\n");
free_fcb(Vcb, fcb);
free_fcb(fcb);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -498,7 +494,7 @@ static NTSTATUS duplicate_fcb(fcb* oldfcb, fcb** pfcb) {
fcb->ea_xattr.Buffer = ExAllocatePoolWithTag(PagedPool, fcb->ea_xattr.MaximumLength, ALLOC_TAG);
if (!fcb->ea_xattr.Buffer) {
ERR("out of memory\n");
free_fcb(Vcb, fcb);
free_fcb(fcb);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -518,7 +514,7 @@ static NTSTATUS duplicate_fcb(fcb* oldfcb, fcb** pfcb) {
if (!xa2) {
ERR("out of memory\n");
free_fcb(Vcb, fcb);
free_fcb(fcb);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -666,11 +662,13 @@ static NTSTATUS create_directory_fcb(device_extension* Vcb, root* r, fcb* parfcb
Status = SeAssignSecurity(parfcb->sd, NULL, (void**)&fcb->sd, TRUE, &subjcont, IoGetFileObjectGenericMapping(), PagedPool);
if (!NT_SUCCESS(Status)) {
reap_fcb(fcb);
ERR("SeAssignSecurity returned %08x\n", Status);
return Status;
}
if (!fcb->sd) {
reap_fcb(fcb);
ERR("SeAssignSecurity returned NULL security descriptor\n");
return STATUS_INTERNAL_ERROR;
}
@ -689,16 +687,12 @@ static NTSTATUS create_directory_fcb(device_extension* Vcb, root* r, fcb* parfcb
fcb->inode_item_changed = TRUE;
InsertTailList(&r->fcbs, &fcb->list_entry);
InsertTailList(&Vcb->all_fcbs, &fcb->list_entry_all);
fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
fcb->Header.AllocationSize.QuadPart = 0;
fcb->Header.FileSize.QuadPart = 0;
fcb->Header.ValidDataLength.QuadPart = 0;
fcb->created = TRUE;
mark_fcb_dirty(fcb);
if (parfcb->inode_item.flags & BTRFS_INODE_COMPRESS)
fcb->inode_item.flags |= BTRFS_INODE_COMPRESS;
@ -722,6 +716,14 @@ static NTSTATUS create_directory_fcb(device_extension* Vcb, root* r, fcb* parfcb
RtlZeroMemory(fcb->hash_ptrs_uc, sizeof(LIST_ENTRY*) * 256);
acquire_fcb_lock_exclusive(Vcb);
InsertTailList(&r->fcbs, &fcb->list_entry);
InsertTailList(&Vcb->all_fcbs, &fcb->list_entry_all);
r->fcbs_version++;
release_fcb_lock(Vcb);
mark_fcb_dirty(fcb);
*pfcb = fcb;
return STATUS_SUCCESS;
@ -735,11 +737,15 @@ static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destd
BTRFS_TIME now;
file_ref* origparent;
// FIXME - make sure me->dummyfileref and me->dummyfcb get freed properly
InitializeListHead(&move_list);
KeQuerySystemTime(&time);
win_time_to_unix(time, &now);
acquire_fcb_lock_exclusive(fileref->fcb->Vcb);
me = ExAllocatePoolWithTag(PagedPool, sizeof(move_entry), ALLOC_TAG);
if (!me) {
@ -1020,9 +1026,9 @@ static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destd
me->dummyfileref->parent = me->parent ? me->parent->dummyfileref : origparent;
increase_fileref_refcount(me->dummyfileref->parent);
ExAcquireResourceExclusiveLite(&me->dummyfileref->parent->nonpaged->children_lock, TRUE);
ExAcquireResourceExclusiveLite(&me->dummyfileref->parent->fcb->nonpaged->dir_children_lock, TRUE);
InsertTailList(&me->dummyfileref->parent->children, &me->dummyfileref->list_entry);
ExReleaseResourceLite(&me->dummyfileref->parent->nonpaged->children_lock);
ExReleaseResourceLite(&me->dummyfileref->parent->fcb->nonpaged->dir_children_lock);
me->dummyfileref->debug_desc = me->fileref->debug_desc;
@ -1104,12 +1110,12 @@ static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destd
ExReleaseResourceLite(&destdir->fcb->nonpaged->dir_children_lock);
}
free_fileref(fileref->fcb->Vcb, me->fileref->parent);
free_fileref(me->fileref->parent);
me->fileref->parent = destdir;
ExAcquireResourceExclusiveLite(&me->fileref->parent->nonpaged->children_lock, TRUE);
ExAcquireResourceExclusiveLite(&me->fileref->parent->fcb->nonpaged->dir_children_lock, TRUE);
InsertTailList(&me->fileref->parent->children, &me->fileref->list_entry);
ExReleaseResourceLite(&me->fileref->parent->nonpaged->children_lock);
ExReleaseResourceLite(&me->fileref->parent->fcb->nonpaged->dir_children_lock);
TRACE("me->fileref->parent->fcb->inode_item.st_size (inode %llx) was %llx\n", me->fileref->parent->fcb->inode, me->fileref->parent->fcb->inode_item.st_size);
me->fileref->parent->fcb->inode_item.st_size += me->fileref->dc->utf8.Length * 2;
@ -1237,16 +1243,21 @@ end:
me = CONTAINING_RECORD(le, move_entry, list_entry);
if (me->dummyfcb)
free_fcb(fileref->fcb->Vcb, me->dummyfcb);
free_fcb(me->dummyfcb);
if (me->dummyfileref)
free_fileref(fileref->fcb->Vcb, me->dummyfileref);
free_fileref(me->dummyfileref);
free_fileref(fileref->fcb->Vcb, me->fileref);
free_fileref(me->fileref);
ExFreePool(me);
}
destdir->fcb->subvol->fcbs_version++;
fileref->fcb->subvol->fcbs_version++;
release_fcb_lock(fileref->fcb->Vcb);
return Status;
}
@ -1390,7 +1401,7 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB
}
ExAcquireResourceSharedLite(&Vcb->tree_lock, TRUE);
acquire_fcb_lock_exclusive(Vcb);
ExAcquireResourceExclusiveLite(&Vcb->fileref_lock, TRUE);
ExAcquireResourceExclusiveLite(fcb->Header.Resource, TRUE);
if (fcb->ads) {
@ -1457,7 +1468,7 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB
}
if (fileref == oldfileref || oldfileref->deleted) {
free_fileref(Vcb, oldfileref);
free_fileref(oldfileref);
oldfileref = NULL;
}
}
@ -1726,10 +1737,10 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB
fileref->created = TRUE;
fileref->parent = related;
ExAcquireResourceExclusiveLite(&fileref->parent->nonpaged->children_lock, TRUE);
ExAcquireResourceExclusiveLite(&fileref->parent->fcb->nonpaged->dir_children_lock, TRUE);
InsertHeadList(&fileref->list_entry, &fr2->list_entry);
RemoveEntryList(&fileref->list_entry);
ExReleaseResourceLite(&fileref->parent->nonpaged->children_lock);
ExReleaseResourceLite(&fileref->parent->fcb->nonpaged->dir_children_lock);
mark_fileref_dirty(fr2);
mark_fileref_dirty(fileref);
@ -1794,9 +1805,9 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB
ExReleaseResourceLite(&related->fcb->nonpaged->dir_children_lock);
}
ExAcquireResourceExclusiveLite(&related->nonpaged->children_lock, TRUE);
ExAcquireResourceExclusiveLite(&related->fcb->nonpaged->dir_children_lock, TRUE);
InsertTailList(&related->children, &fileref->list_entry);
ExReleaseResourceLite(&related->nonpaged->children_lock);
ExReleaseResourceLite(&related->fcb->nonpaged->dir_children_lock);
if (fcb->inode_item.st_nlink > 1) {
// add new hardlink entry to fcb
@ -1900,7 +1911,7 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB
fr2->parent->fcb->inode_item.st_ctime = now;
fr2->parent->fcb->inode_item.st_mtime = now;
free_fileref(Vcb, fr2);
free_fileref(fr2);
fr2->parent->fcb->inode_item_changed = TRUE;
mark_fcb_dirty(fr2->parent->fcb);
@ -1913,13 +1924,13 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB
end:
if (oldfileref)
free_fileref(Vcb, oldfileref);
free_fileref(oldfileref);
if (!NT_SUCCESS(Status) && related)
free_fileref(Vcb, related);
free_fileref(related);
if (!NT_SUCCESS(Status) && fr2)
free_fileref(Vcb, fr2);
free_fileref(fr2);
if (NT_SUCCESS(Status))
clear_rollback(&rollback);
@ -1927,7 +1938,7 @@ end:
do_rollback(Vcb, &rollback);
ExReleaseResourceLite(fcb->Header.Resource);
release_fcb_lock(Vcb);
ExReleaseResourceLite(&Vcb->fileref_lock);
ExReleaseResourceLite(&Vcb->tree_lock);
return Status;
@ -2227,7 +2238,7 @@ static NTSTATUS set_link_information(device_extension* Vcb, PIRP Irp, PFILE_OBJE
}
ExAcquireResourceSharedLite(&Vcb->tree_lock, TRUE);
acquire_fcb_lock_exclusive(Vcb);
ExAcquireResourceExclusiveLite(&Vcb->fileref_lock, TRUE);
ExAcquireResourceExclusiveLite(fcb->Header.Resource, TRUE);
if (fcb->type == BTRFS_TYPE_DIRECTORY) {
@ -2299,7 +2310,7 @@ static NTSTATUS set_link_information(device_extension* Vcb, PIRP Irp, PFILE_OBJE
goto end;
}
} else {
free_fileref(Vcb, oldfileref);
free_fileref(oldfileref);
oldfileref = NULL;
}
}
@ -2364,9 +2375,9 @@ static NTSTATUS set_link_information(device_extension* Vcb, PIRP Irp, PFILE_OBJE
fr2->dc = dc;
dc->fileref = fr2;
ExAcquireResourceExclusiveLite(&related->nonpaged->children_lock, TRUE);
ExAcquireResourceExclusiveLite(&related->fcb->nonpaged->dir_children_lock, TRUE);
InsertTailList(&related->children, &fr2->list_entry);
ExReleaseResourceLite(&related->nonpaged->children_lock);
ExReleaseResourceLite(&related->fcb->nonpaged->dir_children_lock);
// add hardlink for existing fileref, if it's not there already
if (IsListEmpty(&fcb->hardlinks)) {
@ -2447,7 +2458,7 @@ static NTSTATUS set_link_information(device_extension* Vcb, PIRP Irp, PFILE_OBJE
InsertTailList(&fcb->hardlinks, &hl->list_entry);
mark_fileref_dirty(fr2);
free_fileref(Vcb, fr2);
free_fileref(fr2);
// update inode's INODE_ITEM
@ -2482,13 +2493,13 @@ static NTSTATUS set_link_information(device_extension* Vcb, PIRP Irp, PFILE_OBJE
end:
if (oldfileref)
free_fileref(Vcb, oldfileref);
free_fileref(oldfileref);
if (!NT_SUCCESS(Status) && related)
free_fileref(Vcb, related);
free_fileref(related);
if (!NT_SUCCESS(Status) && fr2)
free_fileref(Vcb, fr2);
free_fileref(fr2);
if (NT_SUCCESS(Status))
clear_rollback(&rollback);
@ -2496,7 +2507,7 @@ end:
do_rollback(Vcb, &rollback);
ExReleaseResourceLite(fcb->Header.Resource);
release_fcb_lock(Vcb);
ExReleaseResourceLite(&Vcb->fileref_lock);
ExReleaseResourceLite(&Vcb->tree_lock);
return Status;
@ -3186,282 +3197,7 @@ static NTSTATUS fill_in_file_standard_link_information(FILE_STANDARD_LINK_INFORM
return STATUS_SUCCESS;
}
#endif /* __REACTOS__ */
NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension* Vcb,
root* subvol, UINT64 inode, file_ref** pfr, PIRP Irp) {
NTSTATUS Status;
fcb* fcb;
UINT64 parent = 0;
UNICODE_STRING name;
BOOL hl_alloc = FALSE;
file_ref *parfr, *fr;
Status = open_fcb(Vcb, subvol, inode, 0, NULL, NULL, &fcb, PagedPool, Irp);
if (!NT_SUCCESS(Status)) {
ERR("open_fcb returned %08x\n", Status);
return Status;
}
if (fcb->fileref) {
*pfr = fcb->fileref;
increase_fileref_refcount(fcb->fileref);
return STATUS_SUCCESS;
}
// find hardlink if fcb doesn't have any loaded
if (IsListEmpty(&fcb->hardlinks)) {
KEY searchkey;
traverse_ptr tp;
searchkey.obj_id = fcb->inode;
searchkey.obj_type = TYPE_INODE_EXTREF;
searchkey.offset = 0xffffffffffffffff;
Status = find_item(Vcb, fcb->subvol, &tp, &searchkey, FALSE, Irp);
if (!NT_SUCCESS(Status)) {
ERR("find_item returned %08x\n", Status);
free_fcb(Vcb, fcb);
return Status;
}
if (tp.item->key.obj_id == fcb->inode) {
if (tp.item->key.obj_type == TYPE_INODE_REF) {
INODE_REF* ir;
ULONG stringlen;
ir = (INODE_REF*)tp.item->data;
parent = tp.item->key.offset;
Status = RtlUTF8ToUnicodeN(NULL, 0, &stringlen, ir->name, ir->n);
if (!NT_SUCCESS(Status)) {
ERR("RtlUTF8ToUnicodeN 1 returned %08x\n", Status);
free_fcb(Vcb, fcb);
return Status;
}
name.Length = name.MaximumLength = (UINT16)stringlen;
if (stringlen == 0)
name.Buffer = NULL;
else {
name.Buffer = ExAllocatePoolWithTag(PagedPool, name.MaximumLength, ALLOC_TAG);
if (!name.Buffer) {
ERR("out of memory\n");
free_fcb(Vcb, fcb);
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = RtlUTF8ToUnicodeN(name.Buffer, stringlen, &stringlen, ir->name, ir->n);
if (!NT_SUCCESS(Status)) {
ERR("RtlUTF8ToUnicodeN 2 returned %08x\n", Status);
ExFreePool(name.Buffer);
free_fcb(Vcb, fcb);
return Status;
}
hl_alloc = TRUE;
}
} else if (tp.item->key.obj_type == TYPE_INODE_EXTREF) {
INODE_EXTREF* ier;
ULONG stringlen;
ier = (INODE_EXTREF*)tp.item->data;
parent = ier->dir;
Status = RtlUTF8ToUnicodeN(NULL, 0, &stringlen, ier->name, ier->n);
if (!NT_SUCCESS(Status)) {
ERR("RtlUTF8ToUnicodeN 1 returned %08x\n", Status);
free_fcb(Vcb, fcb);
return Status;
}
name.Length = name.MaximumLength = (UINT16)stringlen;
if (stringlen == 0)
name.Buffer = NULL;
else {
name.Buffer = ExAllocatePoolWithTag(PagedPool, name.MaximumLength, ALLOC_TAG);
if (!name.Buffer) {
ERR("out of memory\n");
free_fcb(Vcb, fcb);
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = RtlUTF8ToUnicodeN(name.Buffer, stringlen, &stringlen, ier->name, ier->n);
if (!NT_SUCCESS(Status)) {
ERR("RtlUTF8ToUnicodeN 2 returned %08x\n", Status);
ExFreePool(name.Buffer);
free_fcb(Vcb, fcb);
return Status;
}
hl_alloc = TRUE;
}
}
}
} else {
hardlink* hl = CONTAINING_RECORD(fcb->hardlinks.Flink, hardlink, list_entry);
name = hl->name;
parent = hl->parent;
}
if (parent == 0) {
ERR("subvol %llx, inode %llx has no hardlinks\n", subvol->id, inode);
free_fcb(Vcb, fcb);
if (hl_alloc) ExFreePool(name.Buffer);
return STATUS_INVALID_PARAMETER;
}
if (parent == inode) { // subvolume root
KEY searchkey;
traverse_ptr tp;
searchkey.obj_id = subvol->id;
searchkey.obj_type = TYPE_ROOT_BACKREF;
searchkey.offset = 0xffffffffffffffff;
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE, Irp);
if (!NT_SUCCESS(Status)) {
ERR("find_item returned %08x\n", Status);
free_fcb(Vcb, fcb);
if (hl_alloc) ExFreePool(name.Buffer);
return Status;
}
if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
ROOT_REF* rr = (ROOT_REF*)tp.item->data;
LIST_ENTRY* le;
root* r = NULL;
ULONG stringlen;
if (tp.item->size < sizeof(ROOT_REF)) {
ERR("(%llx,%x,%llx) was %u bytes, expected at least %u\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(ROOT_REF));
free_fcb(Vcb, fcb);
if (hl_alloc) ExFreePool(name.Buffer);
return STATUS_INTERNAL_ERROR;
}
if (tp.item->size < offsetof(ROOT_REF, name[0]) + rr->n) {
ERR("(%llx,%x,%llx) was %u bytes, expected %u\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, offsetof(ROOT_REF, name[0]) + rr->n);
free_fcb(Vcb, fcb);
if (hl_alloc) ExFreePool(name.Buffer);
return STATUS_INTERNAL_ERROR;
}
le = Vcb->roots.Flink;
while (le != &Vcb->roots) {
root* r2 = CONTAINING_RECORD(le, root, list_entry);
if (r2->id == tp.item->key.offset) {
r = r2;
break;
}
le = le->Flink;
}
if (!r) {
ERR("couldn't find subvol %llx\n", tp.item->key.offset);
free_fcb(Vcb, fcb);
if (hl_alloc) ExFreePool(name.Buffer);
return STATUS_INTERNAL_ERROR;
}
Status = open_fileref_by_inode(Vcb, r, rr->dir, &parfr, Irp);
if (!NT_SUCCESS(Status)) {
ERR("open_fileref_by_inode returned %08x\n", Status);
free_fcb(Vcb, fcb);
if (hl_alloc) ExFreePool(name.Buffer);
return Status;
}
if (hl_alloc) {
ExFreePool(name.Buffer);
hl_alloc = FALSE;
}
Status = RtlUTF8ToUnicodeN(NULL, 0, &stringlen, rr->name, rr->n);
if (!NT_SUCCESS(Status)) {
ERR("RtlUTF8ToUnicodeN 1 returned %08x\n", Status);
free_fcb(Vcb, fcb);
return Status;
}
name.Length = name.MaximumLength = (UINT16)stringlen;
if (stringlen == 0)
name.Buffer = NULL;
else {
name.Buffer = ExAllocatePoolWithTag(PagedPool, name.MaximumLength, ALLOC_TAG);
if (!name.Buffer) {
ERR("out of memory\n");
free_fcb(Vcb, fcb);
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = RtlUTF8ToUnicodeN(name.Buffer, stringlen, &stringlen, rr->name, rr->n);
if (!NT_SUCCESS(Status)) {
ERR("RtlUTF8ToUnicodeN 2 returned %08x\n", Status);
ExFreePool(name.Buffer);
free_fcb(Vcb, fcb);
return Status;
}
hl_alloc = TRUE;
}
} else {
ERR("couldn't find parent for subvol %llx\n", subvol->id);
free_fcb(Vcb, fcb);
if (hl_alloc) ExFreePool(name.Buffer);
return STATUS_INTERNAL_ERROR;
}
} else {
Status = open_fileref_by_inode(Vcb, subvol, parent, &parfr, Irp);
if (!NT_SUCCESS(Status)) {
ERR("open_fileref_by_inode returned %08x\n", Status);
free_fcb(Vcb, fcb);
if (hl_alloc)
ExFreePool(name.Buffer);
return Status;
}
}
Status = open_fileref_child(Vcb, parfr, &name, TRUE, TRUE, FALSE, PagedPool, &fr, Irp);
if (!NT_SUCCESS(Status)) {
ERR("open_fileref_child returned %08x\n", Status);
if (hl_alloc)
ExFreePool(name.Buffer);
free_fcb(Vcb, fcb);
free_fileref(Vcb, parfr);
return Status;
}
*pfr = fr;
if (hl_alloc)
ExFreePool(name.Buffer);
free_fcb(Vcb, fcb);
free_fileref(Vcb, parfr);
return STATUS_SUCCESS;
}
#ifndef __REACTOS__
static NTSTATUS fill_in_hard_link_information(FILE_LINKS_INFORMATION* fli, file_ref* fileref, PIRP Irp, LONG* length) {
NTSTATUS Status;
LIST_ENTRY* le;
@ -3517,7 +3253,7 @@ static NTSTATUS fill_in_hard_link_information(FILE_LINKS_INFORMATION* fli, file_
len = bytes_needed;
}
} else {
acquire_fcb_lock_exclusive(fcb->Vcb);
ExAcquireResourceExclusiveLite(&fcb->Vcb->fileref_lock, TRUE);
if (IsListEmpty(&fcb->hardlinks)) {
bytes_needed += sizeof(FILE_LINK_ENTRY_INFORMATION) + fileref->dc->name.Length - sizeof(WCHAR);
@ -3603,14 +3339,14 @@ static NTSTATUS fill_in_hard_link_information(FILE_LINKS_INFORMATION* fli, file_
}
}
free_fileref(fcb->Vcb, parfr);
free_fileref(parfr);
}
le = le->Flink;
}
}
release_fcb_lock(fcb->Vcb);
ExReleaseResourceLite(&fcb->Vcb->fileref_lock);
}
fli->BytesNeeded = bytes_needed;

View file

@ -2704,7 +2704,11 @@ static NTSTATUS update_chunk_usage(device_extension* Vcb, PIRP Irp, LIST_ENTRY*
}
}
free_fcb(Vcb, c->old_cache);
free_fcb(c->old_cache);
if (c->old_cache->refcount == 0)
reap_fcb(c->old_cache);
c->old_cache = NULL;
}
@ -2810,6 +2814,18 @@ static NTSTATUS split_tree_at(device_extension* Vcb, tree* t, tree_data* newfirs
return STATUS_INSUFFICIENT_RESOURCES;
}
if (t->header.level > 0) {
nt->nonpaged = ExAllocatePoolWithTag(NonPagedPool, sizeof(tree_nonpaged), ALLOC_TAG);
if (!nt->nonpaged) {
ERR("out of memory\n");
ExFreePool(nt);
return STATUS_INSUFFICIENT_RESOURCES;
}
ExInitializeFastMutex(&nt->nonpaged->mutex);
} else
nt->nonpaged = NULL;
RtlCopyMemory(&nt->header, &t->header, sizeof(tree_header));
nt->header.address = 0;
nt->header.generation = Vcb->superblock.generation;
@ -2924,6 +2940,15 @@ static NTSTATUS split_tree_at(device_extension* Vcb, tree* t, tree_data* newfirs
return STATUS_INSUFFICIENT_RESOURCES;
}
pt->nonpaged = ExAllocatePoolWithTag(NonPagedPool, sizeof(tree_nonpaged), ALLOC_TAG);
if (!pt->nonpaged) {
ERR("out of memory\n");
ExFreePool(pt);
return STATUS_INSUFFICIENT_RESOURCES;
}
ExInitializeFastMutex(&pt->nonpaged->mutex);
RtlCopyMemory(&pt->header, &nt->header, sizeof(tree_header));
pt->header.address = 0;
pt->header.num_items = 2;
@ -3103,7 +3128,6 @@ static NTSTATUS try_tree_amalgamate(device_extension* Vcb, tree* t, BOOL* done,
tree_data* nextparitem = NULL;
NTSTATUS Status;
tree *next_tree, *par;
BOOL loaded;
*done = FALSE;
@ -3127,10 +3151,12 @@ static NTSTATUS try_tree_amalgamate(device_extension* Vcb, tree* t, BOOL* done,
TRACE("nextparitem: key = %llx,%x,%llx\n", nextparitem->key.obj_id, nextparitem->key.obj_type, nextparitem->key.offset);
Status = do_load_tree(Vcb, &nextparitem->treeholder, t->root, t->parent, nextparitem, &loaded, NULL);
if (!NT_SUCCESS(Status)) {
ERR("do_load_tree returned %08x\n", Status);
return Status;
if (!nextparitem->treeholder.tree) {
Status = do_load_tree(Vcb, &nextparitem->treeholder, t->root, t->parent, nextparitem, NULL);
if (!NT_SUCCESS(Status)) {
ERR("do_load_tree returned %08x\n", Status);
return Status;
}
}
if (!is_tree_unique(Vcb, nextparitem->treeholder.tree, Irp))
@ -3667,7 +3693,27 @@ static NTSTATUS remove_root_extents(device_extension* Vcb, root* r, tree_holder*
NTSTATUS Status;
if (!th->tree) {
Status = load_tree(Vcb, th->address, r, &th->tree, th->generation, NULL);
UINT8* buf;
chunk* c;
buf = ExAllocatePoolWithTag(PagedPool, Vcb->superblock.node_size, ALLOC_TAG);
if (!buf) {
ERR("out of memory\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = read_data(Vcb, th->address, Vcb->superblock.node_size, NULL, TRUE, buf, NULL,
&c, Irp, th->generation, FALSE, NormalPagePriority);
if (!NT_SUCCESS(Status)) {
ERR("read_data returned 0x%08x\n", Status);
ExFreePool(buf);
return Status;
}
Status = load_tree(Vcb, th->address, buf, r, &th->tree);
if (!th->tree || th->tree->buf != buf)
ExFreePool(buf);
if (!NT_SUCCESS(Status)) {
ERR("load_tree(%llx) returned %08x\n", th->address, Status);
@ -4070,6 +4116,7 @@ static NTSTATUS create_chunk(device_extension* Vcb, chunk* c, PIRP Irp) {
}
c->created = FALSE;
c->oldused = c->used;
return STATUS_SUCCESS;
}
@ -5194,7 +5241,10 @@ static NTSTATUS drop_chunk(device_extension* Vcb, chunk* c, LIST_ENTRY* batchlis
Status = flush_fcb(c->cache, TRUE, batchlist, Irp);
free_fcb(Vcb, c->cache);
free_fcb(c->cache);
if (c->cache->refcount == 0)
reap_fcb(c->cache);
if (!NT_SUCCESS(Status)) {
ERR("flush_fcb returned %08x\n", Status);
@ -6921,7 +6971,7 @@ static NTSTATUS do_write2(device_extension* Vcb, PIRP Irp, LIST_ENTRY* rollback)
file_ref* fr = CONTAINING_RECORD(RemoveHeadList(&Vcb->dirty_filerefs), file_ref, list_entry_dirty);
flush_fileref(fr, &batchlist, Irp);
free_fileref(Vcb, fr);
free_fileref(fr);
#ifdef DEBUG_FLUSH_TIMES
filerefs++;
@ -6961,7 +7011,7 @@ static NTSTATUS do_write2(device_extension* Vcb, PIRP Irp, LIST_ENTRY* rollback)
Status = flush_fcb(fcb, FALSE, &batchlist, Irp);
ExReleaseResourceLite(fcb->Header.Resource);
free_fcb(Vcb, fcb);
free_fcb(fcb);
if (!NT_SUCCESS(Status)) {
ERR("flush_fcb returned %08x\n", Status);
@ -6994,7 +7044,7 @@ static NTSTATUS do_write2(device_extension* Vcb, PIRP Irp, LIST_ENTRY* rollback)
ExAcquireResourceExclusiveLite(fcb->Header.Resource, TRUE);
Status = flush_fcb(fcb, FALSE, &batchlist, Irp);
ExReleaseResourceLite(fcb->Header.Resource);
free_fcb(Vcb, fcb);
free_fcb(fcb);
if (!NT_SUCCESS(Status)) {
ERR("flush_fcb returned %08x\n", Status);

View file

@ -46,11 +46,11 @@ static NTSTATUS remove_free_space_inode(device_extension* Vcb, UINT64 inode, LIS
Status = flush_fcb(fcb, FALSE, batchlist, Irp);
if (!NT_SUCCESS(Status)) {
ERR("flush_fcb returned %08x\n", Status);
free_fcb(Vcb, fcb);
free_fcb(fcb);
return Status;
}
free_fcb(Vcb, fcb);
free_fcb(fcb);
return STATUS_SUCCESS;
}
@ -103,7 +103,7 @@ NTSTATUS clear_free_space_cache(device_extension* Vcb, LIST_ENTRY* batchlist, PI
chunk* c = CONTAINING_RECORD(le, chunk, list_entry);
if (c->offset == tp.item->key.offset && c->cache) {
free_fcb(Vcb, c->cache);
reap_fcb(c->cache);
c->cache = NULL;
}
@ -508,7 +508,7 @@ NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c, BOOL load
if (c->cache->inode_item.st_size == 0) {
WARN("cache had zero length\n");
free_fcb(Vcb, c->cache);
free_fcb(c->cache);
c->cache = NULL;
return STATUS_NOT_FOUND;
}
@ -524,11 +524,16 @@ NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c, BOOL load
if (!data) {
ERR("out of memory\n");
free_fcb(Vcb, c->cache);
free_fcb(c->cache);
c->cache = NULL;
return STATUS_INSUFFICIENT_RESOURCES;
}
if (c->chunk_item->size < 0x6400000) { // 100 MB
WARN("deleting free space cache for chunk smaller than 100MB\n");
goto clearcache;
}
Status = read_file(c->cache, data, 0, c->cache->inode_item.st_size, NULL, NULL);
if (!NT_SUCCESS(Status)) {
ERR("read_file returned %08x\n", Status);
@ -537,7 +542,7 @@ NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c, BOOL load
c->cache->deleted = TRUE;
mark_fcb_dirty(c->cache);
free_fcb(Vcb, c->cache);
free_fcb(c->cache);
c->cache = NULL;
return STATUS_NOT_FOUND;
}
@ -1126,7 +1131,7 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
fsi = ExAllocatePoolWithTag(PagedPool, sizeof(FREE_SPACE_ITEM), ALLOC_TAG);
if (!fsi) {
ERR("out of memory\n");
free_fcb(Vcb, c->cache);
reap_fcb(c->cache);
c->cache = NULL;
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -1139,7 +1144,7 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
if (!NT_SUCCESS(Status)) {
ERR("error - find_item returned %08x\n", Status);
ExFreePool(fsi);
free_fcb(Vcb, c->cache);
reap_fcb(c->cache);
c->cache = NULL;
return Status;
}
@ -1149,7 +1154,7 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
if (!NT_SUCCESS(Status)) {
ERR("delete_tree_item returned %08x\n", Status);
ExFreePool(fsi);
free_fcb(Vcb, c->cache);
reap_fcb(c->cache);
c->cache = NULL;
return Status;
}
@ -1163,7 +1168,7 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
if (!NT_SUCCESS(Status)) {
ERR("insert_tree_item returned %08x\n", Status);
ExFreePool(fsi);
free_fcb(Vcb, c->cache);
reap_fcb(c->cache);
c->cache = NULL;
return Status;
}
@ -1173,7 +1178,7 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
Status = insert_cache_extent(c->cache, 0, new_cache_size, rollback);
if (!NT_SUCCESS(Status)) {
ERR("insert_cache_extent returned %08x\n", Status);
free_fcb(Vcb, c->cache);
reap_fcb(c->cache);
c->cache = NULL;
return Status;
}
@ -1184,7 +1189,7 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
Status = flush_fcb(c->cache, TRUE, batchlist, Irp);
if (!NT_SUCCESS(Status)) {
ERR("flush_fcb returned %08x\n", Status);
free_fcb(Vcb, c->cache);
free_fcb(c->cache);
c->cache = NULL;
return Status;
}
@ -1357,7 +1362,7 @@ NTSTATUS allocate_cache(device_extension* Vcb, BOOL* changed, PIRP Irp, LIST_ENT
while (le != &Vcb->chunks) {
chunk* c = CONTAINING_RECORD(le, chunk, list_entry);
if (c->space_changed) {
if (c->space_changed && c->chunk_item->size >= 0x6400000) { // 100MB
BOOL b;
acquire_chunk_lock(c, Vcb);
@ -1827,7 +1832,7 @@ NTSTATUS update_chunk_caches(device_extension* Vcb, PIRP Irp, LIST_ENTRY* rollba
while (le != &Vcb->chunks) {
c = CONTAINING_RECORD(le, chunk, list_entry);
if (c->space_changed) {
if (c->space_changed && c->chunk_item->size >= 0x6400000) { // 100MB
acquire_chunk_lock(c, Vcb);
Status = update_chunk_cache(Vcb, c, &now, &batchlist, Irp, rollback);
release_chunk_lock(c, Vcb);

View file

@ -435,7 +435,7 @@ static NTSTATUS do_create_snapshot(device_extension* Vcb, PFILE_OBJECT parent, f
Status = open_fcb(Vcb, r, r->root_item.objid, BTRFS_TYPE_DIRECTORY, utf8, fcb, &fr->fcb, PagedPool, Irp);
if (!NT_SUCCESS(Status)) {
ERR("open_fcb returned %08x\n", Status);
free_fileref(Vcb, fr);
free_fileref(fr);
goto end;
}
@ -448,9 +448,9 @@ static NTSTATUS do_create_snapshot(device_extension* Vcb, PFILE_OBJECT parent, f
fr->dc = dc;
dc->fileref = fr;
ExAcquireResourceExclusiveLite(&fileref->nonpaged->children_lock, TRUE);
ExAcquireResourceExclusiveLite(&fileref->fcb->nonpaged->dir_children_lock, TRUE);
InsertTailList(&fileref->children, &fr->list_entry);
ExReleaseResourceLite(&fileref->nonpaged->children_lock);
ExReleaseResourceLite(&fileref->fcb->nonpaged->dir_children_lock);
increase_fileref_refcount(fileref);
@ -462,7 +462,7 @@ static NTSTATUS do_create_snapshot(device_extension* Vcb, PFILE_OBJECT parent, f
fr->fcb->subvol->parent = fileref->fcb->subvol->id;
free_fileref(Vcb, fr);
free_fileref(fr);
// change fcb's INODE_ITEM
@ -641,11 +641,11 @@ static NTSTATUS create_snapshot(device_extension* Vcb, PFILE_OBJECT FileObject,
if (NT_SUCCESS(Status)) {
if (!fr2->deleted) {
WARN("file already exists\n");
free_fileref(Vcb, fr2);
free_fileref(fr2);
Status = STATUS_OBJECT_NAME_COLLISION;
goto end3;
} else
free_fileref(Vcb, fr2);
free_fileref(fr2);
} else if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) {
ERR("open_fileref returned %08x\n", Status);
goto end3;
@ -726,7 +726,7 @@ static NTSTATUS create_snapshot(device_extension* Vcb, PFILE_OBJECT FileObject,
Status = STATUS_SUCCESS;
} else {
send_notification_fileref(fr, FILE_NOTIFY_CHANGE_DIR_NAME, FILE_ACTION_ADDED, NULL);
free_fileref(Vcb, fr);
free_fileref(fr);
}
}
@ -866,11 +866,11 @@ static NTSTATUS create_subvol(device_extension* Vcb, PFILE_OBJECT FileObject, vo
if (NT_SUCCESS(Status)) {
if (!fr2->deleted) {
WARN("file already exists\n");
free_fileref(Vcb, fr2);
free_fileref(fr2);
Status = STATUS_OBJECT_NAME_COLLISION;
goto end;
} else
free_fileref(Vcb, fr2);
free_fileref(fr2);
} else if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) {
ERR("open_fileref returned %08x\n", Status);
goto end;
@ -1005,6 +1005,7 @@ static NTSTATUS create_subvol(device_extension* Vcb, PFILE_OBJECT FileObject, vo
acquire_fcb_lock_exclusive(Vcb);
InsertTailList(&r->fcbs, &rootfcb->list_entry);
InsertTailList(&Vcb->all_fcbs, &rootfcb->list_entry_all);
r->fcbs_version++;
release_fcb_lock(Vcb);
rootfcb->Header.IsFastIoPossible = fast_io_possible(rootfcb);
@ -1049,9 +1050,7 @@ static NTSTATUS create_subvol(device_extension* Vcb, PFILE_OBJECT FileObject, vo
if (!fr) {
ERR("out of memory\n");
acquire_fcb_lock_exclusive(Vcb);
free_fcb(Vcb, rootfcb);
release_fcb_lock(Vcb);
reap_fcb(rootfcb);
Status = STATUS_INSUFFICIENT_RESOURCES;
goto end;
@ -1073,9 +1072,7 @@ static NTSTATUS create_subvol(device_extension* Vcb, PFILE_OBJECT FileObject, vo
fr->fcb->hash_ptrs = ExAllocatePoolWithTag(PagedPool, sizeof(LIST_ENTRY*) * 256, ALLOC_TAG);
if (!fr->fcb->hash_ptrs) {
ERR("out of memory\n");
acquire_fcb_lock_exclusive(Vcb);
free_fileref(Vcb, fr);
release_fcb_lock(Vcb);
free_fileref(fr);
Status = STATUS_INSUFFICIENT_RESOURCES;
goto end;
}
@ -1085,18 +1082,16 @@ static NTSTATUS create_subvol(device_extension* Vcb, PFILE_OBJECT FileObject, vo
fr->fcb->hash_ptrs_uc = ExAllocatePoolWithTag(PagedPool, sizeof(LIST_ENTRY*) * 256, ALLOC_TAG);
if (!fr->fcb->hash_ptrs_uc) {
ERR("out of memory\n");
acquire_fcb_lock_exclusive(Vcb);
free_fileref(Vcb, fr);
release_fcb_lock(Vcb);
free_fileref(fr);
Status = STATUS_INSUFFICIENT_RESOURCES;
goto end;
}
RtlZeroMemory(fr->fcb->hash_ptrs_uc, sizeof(LIST_ENTRY*) * 256);
ExAcquireResourceExclusiveLite(&fileref->nonpaged->children_lock, TRUE);
ExAcquireResourceExclusiveLite(&fileref->fcb->nonpaged->dir_children_lock, TRUE);
InsertTailList(&fileref->children, &fr->list_entry);
ExReleaseResourceLite(&fileref->nonpaged->children_lock);
ExReleaseResourceLite(&fileref->fcb->nonpaged->dir_children_lock);
increase_fileref_refcount(fileref);
@ -1154,11 +1149,8 @@ end:
}
end2:
if (fr) {
acquire_fcb_lock_exclusive(Vcb);
free_fileref(Vcb, fr);
release_fcb_lock(Vcb);
}
if (fr)
free_fileref(fr);
return Status;
}
@ -2233,15 +2225,15 @@ static NTSTATUS lock_volume(device_extension* Vcb, PIRP Irp) {
if (Vcb->locked)
return STATUS_SUCCESS;
acquire_fcb_lock_exclusive(Vcb);
ExAcquireResourceExclusiveLite(&Vcb->fileref_lock, TRUE);
if (Vcb->root_fileref && Vcb->root_fileref->fcb && (Vcb->root_fileref->open_count > 0 || has_open_children(Vcb->root_fileref))) {
Status = STATUS_ACCESS_DENIED;
release_fcb_lock(Vcb);
ExReleaseResourceLite(&Vcb->fileref_lock);
goto end;
}
release_fcb_lock(Vcb);
ExReleaseResourceLite(&Vcb->fileref_lock);
if (Vcb->balance.thread && KeReadStateEvent(&Vcb->balance.event)) {
ExAcquireResourceExclusiveLite(&Vcb->tree_lock, TRUE);
@ -3768,8 +3760,6 @@ static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data
name.Length = name.MaximumLength = bmn->namelen;
name.Buffer = bmn->name;
acquire_fcb_lock_exclusive(Vcb);
Status = find_file_in_dir(&name, parfcb, &subvol, &inode, &dc, TRUE);
if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) {
ERR("find_file_in_dir returned %08x\n", Status);
@ -3782,36 +3772,6 @@ static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data
goto end;
}
if (bmn->inode == 0) {
inode = InterlockedIncrement64(&parfcb->subvol->lastinode);
lastle = parfcb->subvol->fcbs.Blink;
} else {
if (bmn->inode > (UINT64)parfcb->subvol->lastinode) {
inode = parfcb->subvol->lastinode = bmn->inode;
lastle = parfcb->subvol->fcbs.Blink;
} else {
LIST_ENTRY* le = parfcb->subvol->fcbs.Flink;
lastle = parfcb->subvol->fcbs.Blink;;
while (le != &parfcb->subvol->fcbs) {
struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
if (fcb2->inode == bmn->inode && !fcb2->deleted) {
WARN("inode collision\n");
Status = STATUS_INVALID_PARAMETER;
goto end;
} else if (fcb2->inode > bmn->inode) {
lastle = fcb2->list_entry.Blink;
break;
}
le = le->Flink;
}
inode = bmn->inode;
}
}
KeQuerySystemTime(&time);
win_time_to_unix(time, &now);
@ -3897,8 +3857,6 @@ static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data
InterlockedIncrement(&parfcb->refcount);
fcb->subvol = parfcb->subvol;
fcb->inode = inode;
fcb->type = bmn->type;
SeCaptureSubjectContext(&subjcont);
@ -3907,7 +3865,7 @@ static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data
if (!NT_SUCCESS(Status)) {
ERR("SeAssignSecurityEx returned %08x\n", Status);
free_fcb(Vcb, fcb);
reap_fcb(fcb);
goto end;
}
@ -3922,10 +3880,52 @@ static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data
find_gid(fcb, parfcb, &subjcont);
ExAcquireResourceExclusiveLite(&Vcb->fileref_lock, TRUE);
acquire_fcb_lock_exclusive(Vcb);
if (bmn->inode == 0) {
inode = InterlockedIncrement64(&parfcb->subvol->lastinode);
lastle = parfcb->subvol->fcbs.Blink;
} else {
if (bmn->inode > (UINT64)parfcb->subvol->lastinode) {
inode = parfcb->subvol->lastinode = bmn->inode;
lastle = parfcb->subvol->fcbs.Blink;
} else {
LIST_ENTRY* le = parfcb->subvol->fcbs.Flink;
lastle = parfcb->subvol->fcbs.Blink;;
while (le != &parfcb->subvol->fcbs) {
struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
if (fcb2->inode == bmn->inode && !fcb2->deleted) {
release_fcb_lock(Vcb);
ExReleaseResourceLite(&Vcb->fileref_lock);
WARN("inode collision\n");
Status = STATUS_INVALID_PARAMETER;
goto end;
} else if (fcb2->inode > bmn->inode) {
lastle = fcb2->list_entry.Blink;
break;
}
le = le->Flink;
}
inode = bmn->inode;
}
}
fcb->inode = inode;
fcb->type = bmn->type;
fileref = create_fileref(Vcb);
if (!fileref) {
release_fcb_lock(Vcb);
ExReleaseResourceLite(&Vcb->fileref_lock);
ERR("out of memory\n");
free_fcb(Vcb, fcb);
reap_fcb(fcb);
Status = STATUS_INSUFFICIENT_RESOURCES;
goto end;
}
@ -3933,16 +3933,16 @@ static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data
fileref->fcb = fcb;
fcb->created = TRUE;
mark_fcb_dirty(fcb);
fileref->created = TRUE;
mark_fileref_dirty(fileref);
fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
fcb->subvol->root_item.ctime = now;
fileref->parent = parfileref;
mark_fcb_dirty(fcb);
mark_fileref_dirty(fileref);
Status = add_dir_child(fileref->parent->fcb, fcb->inode, FALSE, &utf8, &name, fcb->type, &dc);
if (!NT_SUCCESS(Status))
WARN("add_dir_child returned %08x\n", Status);
@ -3950,17 +3950,20 @@ static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data
fileref->dc = dc;
dc->fileref = fileref;
ExAcquireResourceExclusiveLite(&parfileref->nonpaged->children_lock, TRUE);
ExAcquireResourceExclusiveLite(&parfileref->fcb->nonpaged->dir_children_lock, TRUE);
InsertTailList(&parfileref->children, &fileref->list_entry);
ExReleaseResourceLite(&parfileref->nonpaged->children_lock);
ExReleaseResourceLite(&parfileref->fcb->nonpaged->dir_children_lock);
increase_fileref_refcount(parfileref);
if (fcb->type == BTRFS_TYPE_DIRECTORY) {
fcb->hash_ptrs = ExAllocatePoolWithTag(PagedPool, sizeof(LIST_ENTRY*) * 256, ALLOC_TAG);
if (!fcb->hash_ptrs) {
release_fcb_lock(Vcb);
ExReleaseResourceLite(&Vcb->fileref_lock);
ERR("out of memory\n");
free_fileref(Vcb, fileref);
free_fileref(fileref);
Status = STATUS_INSUFFICIENT_RESOURCES;
goto end;
}
@ -3969,8 +3972,11 @@ static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data
fcb->hash_ptrs_uc = ExAllocatePoolWithTag(PagedPool, sizeof(LIST_ENTRY*) * 256, ALLOC_TAG);
if (!fcb->hash_ptrs_uc) {
release_fcb_lock(Vcb);
ExReleaseResourceLite(&Vcb->fileref_lock);
ERR("out of memory\n");
free_fileref(Vcb, fileref);
free_fileref(fileref);
Status = STATUS_INSUFFICIENT_RESOURCES;
goto end;
}
@ -3995,7 +4001,11 @@ static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data
if (!parccb->user_set_write_time)
parfcb->inode_item.st_mtime = now;
parfcb->subvol->fcbs_version++;
ExReleaseResourceLite(parfcb->Header.Resource);
release_fcb_lock(Vcb);
ExReleaseResourceLite(&Vcb->fileref_lock);
parfcb->inode_item_changed = TRUE;
mark_fcb_dirty(parfcb);
@ -4008,7 +4018,6 @@ static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data
Status = STATUS_SUCCESS;
end:
release_fcb_lock(Vcb);
ExFreePool(utf8.Buffer);
@ -4458,11 +4467,11 @@ static NTSTATUS get_subvol_path(device_extension* Vcb, UINT64 id, WCHAR* out, UL
return STATUS_INTERNAL_ERROR;
}
acquire_fcb_lock_shared(Vcb);
ExAcquireResourceExclusiveLite(&Vcb->fileref_lock, TRUE);
Status = open_fileref_by_inode(Vcb, r, r->root_item.objid, &fr, Irp);
if (!NT_SUCCESS(Status)) {
release_fcb_lock(Vcb);
ExReleaseResourceLite(&Vcb->fileref_lock);
ERR("open_fileref_by_inode returned %08x\n", Status);
return Status;
}
@ -4478,9 +4487,9 @@ static NTSTATUS get_subvol_path(device_extension* Vcb, UINT64 id, WCHAR* out, UL
else
ERR("fileref_get_filename returned %08x\n", Status);
free_fileref(Vcb, fr);
free_fileref(fr);
release_fcb_lock(Vcb);
ExReleaseResourceLite(&Vcb->fileref_lock);
return Status;
}

View file

@ -161,7 +161,7 @@ static NTSTATUS pnp_cancel_remove_device(PDEVICE_OBJECT DeviceObject) {
ExAcquireResourceSharedLite(&Vcb->tree_lock, TRUE);
acquire_fcb_lock_exclusive(Vcb);
ExAcquireResourceExclusiveLite(&Vcb->fileref_lock, TRUE);
if (Vcb->root_fileref && Vcb->root_fileref->fcb && (Vcb->root_fileref->open_count > 0 || has_open_children(Vcb->root_fileref))) {
Status = STATUS_ACCESS_DENIED;
@ -175,7 +175,7 @@ static NTSTATUS pnp_cancel_remove_device(PDEVICE_OBJECT DeviceObject) {
}
end:
release_fcb_lock(Vcb);
ExReleaseResourceLite(&Vcb->fileref_lock);
ExReleaseResourceLite(&Vcb->tree_lock);
return STATUS_SUCCESS;
@ -187,8 +187,6 @@ NTSTATUS pnp_query_remove_device(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
ExAcquireResourceExclusiveLite(&Vcb->tree_lock, TRUE);
acquire_fcb_lock_exclusive(Vcb);
if (Vcb->root_fileref && Vcb->root_fileref->fcb && (Vcb->root_fileref->open_count > 0 || has_open_children(Vcb->root_fileref))) {
Status = STATUS_ACCESS_DENIED;
goto end;
@ -216,8 +214,6 @@ NTSTATUS pnp_query_remove_device(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
Status = STATUS_SUCCESS;
end:
release_fcb_lock(Vcb);
ExReleaseResourceLite(&Vcb->tree_lock);
return Status;

View file

@ -3359,7 +3359,7 @@ NTSTATUS NTAPI drv_read(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
if (Irp->Flags & IRP_PAGING_IO)
wait = TRUE;
if (!(Irp->Flags & IRP_PAGING_IO) && FileObject->SectionObjectPointer->DataSectionObject) {
if (!(Irp->Flags & IRP_PAGING_IO) && FileObject->SectionObjectPointer && FileObject->SectionObjectPointer->DataSectionObject) {
IO_STATUS_BLOCK iosb;
CcFlushCache(FileObject->SectionObjectPointer, &IrpSp->Parameters.Read.ByteOffset, IrpSp->Parameters.Read.Length, &iosb);

View file

@ -1,6 +1,7 @@
//{{NO_DEPENDENCIES}}
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by btrfs.rc
//
// Next default values for new objects
//

View file

@ -483,8 +483,6 @@ void remove_volume_child(_Inout_ _Requires_exclusive_lock_held_(_Curr_->child_lo
}
if (remove) {
PDEVICE_OBJECT pdo;
if (vde->name.Buffer)
ExFreePool(vde->name.Buffer);
@ -493,11 +491,7 @@ void remove_volume_child(_Inout_ _Requires_exclusive_lock_held_(_Curr_->child_lo
ExDeleteResourceLite(&pdode->child_lock);
pdo = vde->pdo;
IoDeleteDevice(vde->device);
if (!no_pnp)
IoDeleteDevice(pdo);
}
} else
ExReleaseResourceLite(&pdode->child_lock);

View file

@ -17,39 +17,34 @@
#include "btrfs_drv.h"
NTSTATUS load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, UINT64 generation, PIRP Irp) {
UINT8* buf;
NTSTATUS Status;
NTSTATUS load_tree(device_extension* Vcb, UINT64 addr, UINT8* buf, root* r, tree** pt) {
tree_header* th;
tree* t;
tree_data* td;
chunk* c;
UINT8 h;
BOOL inserted;
LIST_ENTRY* le;
buf = ExAllocatePoolWithTag(PagedPool, Vcb->superblock.node_size, ALLOC_TAG);
if (!buf) {
ERR("out of memory\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = read_data(Vcb, addr, Vcb->superblock.node_size, NULL, TRUE, buf, NULL, &c, Irp, generation, FALSE, NormalPagePriority);
if (!NT_SUCCESS(Status)) {
ERR("read_data returned 0x%08x\n", Status);
ExFreePool(buf);
return Status;
}
th = (tree_header*)buf;
t = ExAllocatePoolWithTag(PagedPool, sizeof(tree), ALLOC_TAG);
if (!t) {
ERR("out of memory\n");
ExFreePool(buf);
return STATUS_INSUFFICIENT_RESOURCES;
}
if (th->level > 0) {
t->nonpaged = ExAllocatePoolWithTag(NonPagedPool, sizeof(tree_nonpaged), ALLOC_TAG);
if (!t->nonpaged) {
ERR("out of memory\n");
ExFreePool(t);
return STATUS_INSUFFICIENT_RESOURCES;
}
ExInitializeFastMutex(&t->nonpaged->mutex);
} else
t->nonpaged = NULL;
RtlCopyMemory(&t->header, th, sizeof(tree_header));
t->hash = calc_crc32c(0xffffffff, (UINT8*)&addr, sizeof(UINT64));
t->has_address = TRUE;
@ -73,7 +68,6 @@ NTSTATUS load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, UINT6
if ((t->header.num_items * sizeof(leaf_node)) + sizeof(tree_header) > Vcb->superblock.node_size) {
ERR("tree at %llx has more items than expected (%x)\n", t->header.num_items);
ExFreePool(t);
ExFreePool(buf);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -82,7 +76,6 @@ NTSTATUS load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, UINT6
if (!td) {
ERR("out of memory\n");
ExFreePool(t);
ExFreePool(buf);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -97,7 +90,6 @@ NTSTATUS load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, UINT6
ERR("overlarge item in tree %llx: %u > %u\n", addr, ln[i].size, Vcb->superblock.node_size - sizeof(tree_header) - sizeof(leaf_node));
ExFreeToPagedLookasideList(&t->Vcb->tree_data_lookaside, td);
ExFreePool(t);
ExFreePool(buf);
return STATUS_INTERNAL_ERROR;
}
@ -119,7 +111,6 @@ NTSTATUS load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, UINT6
if ((t->header.num_items * sizeof(internal_node)) + sizeof(tree_header) > Vcb->superblock.node_size) {
ERR("tree at %llx has more items than expected (%x)\n", t->header.num_items);
ExFreePool(t);
ExFreePool(buf);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -128,7 +119,6 @@ NTSTATUS load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, UINT6
if (!td) {
ERR("out of memory\n");
ExFreePool(t);
ExFreePool(buf);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -145,9 +135,10 @@ NTSTATUS load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, UINT6
t->size = t->header.num_items * sizeof(internal_node);
t->buf = NULL;
ExFreePool(buf);
}
ExAcquireFastMutex(&Vcb->trees_list_mutex);
InsertTailList(&Vcb->trees, &t->list_entry);
h = t->hash >> 24;
@ -190,6 +181,8 @@ NTSTATUS load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, UINT6
if (!Vcb->trees_ptrs[h] || t->list_entry_hash.Flink == Vcb->trees_ptrs[h])
Vcb->trees_ptrs[h] = &t->list_entry_hash;
ExReleaseFastMutex(&Vcb->trees_list_mutex);
TRACE("returning %p\n", t);
*pt = t;
@ -197,10 +190,79 @@ NTSTATUS load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, UINT6
return STATUS_SUCCESS;
}
static tree* free_tree2(tree* t) {
static NTSTATUS do_load_tree2(device_extension* Vcb, tree_holder* th, UINT8* buf, root* r, tree* t, tree_data* td) {
if (!th->tree) {
NTSTATUS Status;
tree* nt;
Status = load_tree(Vcb, th->address, buf, r, &nt);
if (!NT_SUCCESS(Status)) {
ERR("load_tree returned %08x\n", Status);
return Status;
}
nt->parent = t;
#ifdef DEBUG_PARANOID
if (t && t->header.level <= nt->header.level) int3;
#endif
nt->paritem = td;
th->tree = nt;
}
return STATUS_SUCCESS;
}
NTSTATUS do_load_tree(device_extension* Vcb, tree_holder* th, root* r, tree* t, tree_data* td, PIRP Irp) {
NTSTATUS Status;
UINT8* buf;
chunk* c;
buf = ExAllocatePoolWithTag(PagedPool, Vcb->superblock.node_size, ALLOC_TAG);
if (!buf) {
ERR("out of memory\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = read_data(Vcb, th->address, Vcb->superblock.node_size, NULL, TRUE, buf, NULL,
&c, Irp, th->generation, FALSE, NormalPagePriority);
if (!NT_SUCCESS(Status)) {
ERR("read_data returned 0x%08x\n", Status);
ExFreePool(buf);
return Status;
}
if (t)
ExAcquireFastMutex(&t->nonpaged->mutex);
else
ExAcquireResourceExclusiveLite(&r->nonpaged->load_tree_lock, TRUE);
Status = do_load_tree2(Vcb, th, buf, r, t, td);
if (t)
ExReleaseFastMutex(&t->nonpaged->mutex);
else
ExReleaseResourceLite(&r->nonpaged->load_tree_lock);
if (!th->tree || th->tree->buf != buf)
ExFreePool(buf);
if (!NT_SUCCESS(Status)) {
ERR("do_load_tree2 returned %08x\n", Status);
return Status;
}
return Status;
}
void free_tree(tree* t) {
tree* par;
root* r = t->root;
// No need to acquire lock, as this is only ever called while Vcb->tree_lock held exclusively
par = t->parent;
if (r && r->treeholder.tree != t)
@ -245,59 +307,10 @@ static tree* free_tree2(tree* t) {
if (t->buf)
ExFreePool(t->buf);
if (t->nonpaged)
ExFreePool(t->nonpaged);
ExFreePool(t);
return NULL;
}
NTSTATUS do_load_tree(device_extension* Vcb, tree_holder* th, root* r, tree* t, tree_data* td, BOOL* loaded, PIRP Irp) {
BOOL ret;
ExAcquireResourceExclusiveLite(&r->nonpaged->load_tree_lock, TRUE);
if (!th->tree) {
NTSTATUS Status;
tree* nt;
Status = load_tree(Vcb, th->address, r, &nt, th->generation, Irp);
if (!NT_SUCCESS(Status)) {
ERR("load_tree returned %08x\n", Status);
ExReleaseResourceLite(&r->nonpaged->load_tree_lock);
return Status;
}
nt->parent = t;
#ifdef DEBUG_PARANOID
if (t && t->header.level <= nt->header.level) int3;
#endif
nt->paritem = td;
th->tree = nt;
ret = TRUE;
} else
ret = FALSE;
ExReleaseResourceLite(&r->nonpaged->load_tree_lock);
*loaded = ret;
return STATUS_SUCCESS;
}
tree* free_tree(tree* t) {
tree* ret;
root* r = t->root;
ExAcquireResourceExclusiveLite(&r->nonpaged->load_tree_lock, TRUE);
ret = free_tree2(t);
ExReleaseResourceLite(&r->nonpaged->load_tree_lock);
return ret;
}
static __inline tree_data* first_item(tree* t) {
@ -504,7 +517,6 @@ static NTSTATUS find_item_in_tree(device_extension* Vcb, tree* t, traverse_ptr*
return STATUS_SUCCESS;
} else {
NTSTATUS Status;
BOOL loaded;
while (td && td->treeholder.tree && IsListEmpty(&td->treeholder.tree->itemlist)) {
td = prev_item(t, td);
@ -520,7 +532,7 @@ static NTSTATUS find_item_in_tree(device_extension* Vcb, tree* t, traverse_ptr*
}
if (!td->treeholder.tree) {
Status = do_load_tree(Vcb, &td->treeholder, t->root, t, td, &loaded, Irp);
Status = do_load_tree(Vcb, &td->treeholder, t->root, t, td, Irp);
if (!NT_SUCCESS(Status)) {
ERR("do_load_tree returned %08x\n", Status);
return Status;
@ -536,10 +548,9 @@ static NTSTATUS find_item_in_tree(device_extension* Vcb, tree* t, traverse_ptr*
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_ root* r, _Out_ traverse_ptr* tp,
_In_ const KEY* searchkey, _In_ BOOL ignore, _In_opt_ PIRP Irp) {
NTSTATUS Status;
BOOL loaded;
if (!r->treeholder.tree) {
Status = do_load_tree(Vcb, &r->treeholder, r, NULL, NULL, &loaded, Irp);
Status = do_load_tree(Vcb, &r->treeholder, r, NULL, NULL, Irp);
if (!NT_SUCCESS(Status)) {
ERR("do_load_tree returned %08x\n", Status);
return Status;
@ -556,10 +567,9 @@ NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension
NTSTATUS find_item_to_level(device_extension* Vcb, root* r, traverse_ptr* tp, const KEY* searchkey, BOOL ignore, UINT8 level, PIRP Irp) {
NTSTATUS Status;
BOOL loaded;
if (!r->treeholder.tree) {
Status = do_load_tree(Vcb, &r->treeholder, r, NULL, NULL, &loaded, Irp);
Status = do_load_tree(Vcb, &r->treeholder, r, NULL, NULL, Irp);
if (!NT_SUCCESS(Status)) {
ERR("do_load_tree returned %08x\n", Status);
return Status;
@ -583,7 +593,6 @@ BOOL find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vc
tree* t;
tree_data *td = NULL, *next;
NTSTATUS Status;
BOOL loaded;
next = next_item(tp->tree, tp->item);
@ -623,10 +632,12 @@ BOOL find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vc
if (!t)
return FALSE;
Status = do_load_tree(Vcb, &td->treeholder, t->parent->root, t->parent, td, &loaded, Irp);
if (!NT_SUCCESS(Status)) {
ERR("do_load_tree returned %08x\n", Status);
return FALSE;
if (!td->treeholder.tree) {
Status = do_load_tree(Vcb, &td->treeholder, t->parent->root, t->parent, td, Irp);
if (!NT_SUCCESS(Status)) {
ERR("do_load_tree returned %08x\n", Status);
return FALSE;
}
}
t = td->treeholder.tree;
@ -636,10 +647,12 @@ BOOL find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vc
fi = first_item(t);
Status = do_load_tree(Vcb, &fi->treeholder, t->parent->root, t, fi, &loaded, Irp);
if (!NT_SUCCESS(Status)) {
ERR("do_load_tree returned %08x\n", Status);
return FALSE;
if (!fi->treeholder.tree) {
Status = do_load_tree(Vcb, &fi->treeholder, t->parent->root, t, fi, Irp);
if (!NT_SUCCESS(Status)) {
ERR("do_load_tree returned %08x\n", Status);
return FALSE;
}
}
t = fi->treeholder.tree;
@ -686,7 +699,6 @@ BOOL find_prev_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vc
tree* t;
tree_data* td;
NTSTATUS Status;
BOOL loaded;
// FIXME - support ignore flag
if (prev_item(tp->tree, tp->item)) {
@ -709,10 +721,12 @@ BOOL find_prev_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vc
td = prev_item(t->parent, t->paritem);
Status = do_load_tree(Vcb, &td->treeholder, t->parent->root, t->parent, td, &loaded, Irp);
if (!NT_SUCCESS(Status)) {
ERR("do_load_tree returned %08x\n", Status);
return FALSE;
if (!td->treeholder.tree) {
Status = do_load_tree(Vcb, &td->treeholder, t->parent->root, t->parent, td, Irp);
if (!NT_SUCCESS(Status)) {
ERR("do_load_tree returned %08x\n", Status);
return FALSE;
}
}
t = td->treeholder.tree;
@ -722,10 +736,12 @@ BOOL find_prev_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vc
li = last_item(t);
Status = do_load_tree(Vcb, &li->treeholder, t->parent->root, t, li, &loaded, Irp);
if (!NT_SUCCESS(Status)) {
ERR("do_load_tree returned %08x\n", Status);
return FALSE;
if (!li->treeholder.tree) {
Status = do_load_tree(Vcb, &li->treeholder, t->parent->root, t, li, Irp);
if (!NT_SUCCESS(Status)) {
ERR("do_load_tree returned %08x\n", Status);
return FALSE;
}
}
t = li->treeholder.tree;
@ -756,7 +772,7 @@ void free_trees_root(device_extension* Vcb, root* r) {
empty = FALSE;
free_tree2(t);
free_tree(t);
if (top && r->treeholder.tree == t)
r->treeholder.tree = NULL;
@ -793,7 +809,7 @@ void free_trees(device_extension* Vcb) {
empty = FALSE;
free_tree2(t);
free_tree(t);
if (top && r->treeholder.tree == t)
r->treeholder.tree = NULL;
@ -808,6 +824,9 @@ void free_trees(device_extension* Vcb) {
if (empty)
break;
}
reap_filerefs(Vcb, Vcb->root_fileref);
reap_fcbs(Vcb);
}
#ifdef _MSC_VER
@ -859,9 +878,7 @@ NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock)
if (Status == STATUS_NOT_FOUND) {
if (r) {
if (!r->treeholder.tree) {
BOOL loaded;
Status = do_load_tree(Vcb, &r->treeholder, r, NULL, NULL, &loaded, Irp);
Status = do_load_tree(Vcb, &r->treeholder, r, NULL, NULL, Irp);
if (!NT_SUCCESS(Status)) {
ERR("do_load_tree returned %08x\n", Status);
return Status;

View file

@ -774,6 +774,30 @@ static NTSTATUS vol_ioctl_passthrough(volume_device_extension* vde, PIRP Irp) {
return Status;
}
static NTSTATUS vol_query_stable_guid(volume_device_extension* vde, PIRP Irp) {
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
MOUNTDEV_STABLE_GUID* mdsg;
pdo_device_extension* pdode;
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTDEV_STABLE_GUID)) {
Irp->IoStatus.Information = sizeof(MOUNTDEV_STABLE_GUID);
return STATUS_BUFFER_TOO_SMALL;
}
mdsg = Irp->AssociatedIrp.SystemBuffer;
if (!vde->pdo)
return STATUS_INVALID_PARAMETER;
pdode = vde->pdode;
RtlCopyMemory(&mdsg->StableGuid, &pdode->uuid, sizeof(BTRFS_UUID));
Irp->IoStatus.Information = sizeof(MOUNTDEV_STABLE_GUID);
return STATUS_SUCCESS;
}
NTSTATUS vol_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
volume_device_extension* vde = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
@ -797,8 +821,7 @@ NTSTATUS vol_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
break;
case IOCTL_MOUNTDEV_QUERY_STABLE_GUID:
TRACE("unhandled control code IOCTL_MOUNTDEV_QUERY_STABLE_GUID\n");
break;
return vol_query_stable_guid(vde, Irp);
case IOCTL_MOUNTDEV_LINK_CREATED:
TRACE("unhandled control code IOCTL_MOUNTDEV_LINK_CREATED\n");
@ -811,12 +834,12 @@ NTSTATUS vol_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
return vol_is_dynamic(Irp);
case IOCTL_VOLUME_ONLINE:
TRACE("unhandled control code IOCTL_VOLUME_ONLINE\n");
break;
Irp->IoStatus.Information = 0;
return STATUS_SUCCESS;
case IOCTL_VOLUME_POST_ONLINE:
TRACE("unhandled control code IOCTL_VOLUME_POST_ONLINE\n");
break;
Irp->IoStatus.Information = 0;
return STATUS_SUCCESS;
case IOCTL_DISK_GET_DRIVE_GEOMETRY:
return vol_get_drive_geometry(DeviceObject, Irp);