mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[BTRFS] Upgrade to 1.2.1
CORE-16004
This commit is contained in:
parent
927e1d0968
commit
883b1f31ac
16 changed files with 1788 additions and 1441 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by btrfs.rc
|
||||
//
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue