From 4672b2ba5e111fe9730cdbf4e51fb28c1ce7d473 Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Mon, 16 Oct 2017 20:05:33 +0200 Subject: [PATCH] [BTRFS] Upgrade to BtrFS 1.0.1 CID 1419459, 1419378 CORE-13896 --- drivers/filesystems/btrfs/balance.c | 4 +- drivers/filesystems/btrfs/btrfs.c | 66 +++++--- drivers/filesystems/btrfs/btrfs.rc | 8 +- drivers/filesystems/btrfs/btrfs_drv.h | 54 +++++- drivers/filesystems/btrfs/create.c | 208 ++++++++++++++++-------- drivers/filesystems/btrfs/dirctrl.c | 11 +- drivers/filesystems/btrfs/fileinfo.c | 22 +-- drivers/filesystems/btrfs/flushthread.c | 9 +- drivers/filesystems/btrfs/fsctl.c | 37 +++-- drivers/filesystems/btrfs/pnp.c | 8 +- drivers/filesystems/btrfs/read.c | 21 ++- drivers/filesystems/btrfs/reparse.c | 16 +- drivers/filesystems/btrfs/search.c | 3 +- drivers/filesystems/btrfs/volume.c | 2 +- drivers/filesystems/btrfs/write.c | 12 +- 15 files changed, 329 insertions(+), 152 deletions(-) diff --git a/drivers/filesystems/btrfs/balance.c b/drivers/filesystems/btrfs/balance.c index cf9717480da..980089618a4 100644 --- a/drivers/filesystems/btrfs/balance.c +++ b/drivers/filesystems/btrfs/balance.c @@ -2112,7 +2112,7 @@ end: // update open FCBs // FIXME - speed this up(?) - ExAcquireResourceSharedLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_shared(Vcb); le = Vcb->all_fcbs.Flink; while (le != &Vcb->all_fcbs) { @@ -2153,7 +2153,7 @@ end: le = le->Flink; } - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); } else do_rollback(Vcb, &rollback); diff --git a/drivers/filesystems/btrfs/btrfs.c b/drivers/filesystems/btrfs/btrfs.c index 0e3e9175310..236184eafac 100644 --- a/drivers/filesystems/btrfs/btrfs.c +++ b/drivers/filesystems/btrfs/btrfs.c @@ -1352,7 +1352,7 @@ void send_notification_fcb(_In_ file_ref* fileref, _In_ ULONG filter_match, _In_ return; } - ExAcquireResourceExclusiveLite(&fcb->Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(fcb->Vcb); le = fcb->hardlinks.Flink; while (le != &fcb->hardlinks) { @@ -1419,7 +1419,7 @@ void send_notification_fcb(_In_ file_ref* fileref, _In_ ULONG filter_match, _In_ le = le->Flink; } - ExReleaseResourceLite(&fcb->Vcb->fcb_lock); + release_fcb_lock(fcb->Vcb); } void mark_fcb_dirty(_In_ fcb* fcb) { @@ -1698,14 +1698,14 @@ static NTSTATUS close_file(_In_ PFILE_OBJECT FileObject, _In_ PIRP Irp) { Vcb = fcb->Vcb; - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); if (fileref) free_fileref(fcb->Vcb, fileref); else free_fcb(Vcb, fcb); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); return STATUS_SUCCESS; } @@ -1804,10 +1804,10 @@ void uninit(_In_ device_extension* Vcb, _In_ BOOL flush) { KeSetTimer(&Vcb->flush_thread_timer, time, NULL); // trigger the timer early KeWaitForSingleObject(&Vcb->flush_thread_finished, Executive, KernelMode, FALSE, NULL); - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fcb(Vcb, Vcb->volume_fcb); free_fcb(Vcb, Vcb->dummy_fcb); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); if (Vcb->root_file) ObDereferenceObject(Vcb->root_file); @@ -1817,9 +1817,9 @@ void uninit(_In_ device_extension* Vcb, _In_ BOOL flush) { chunk* c = CONTAINING_RECORD(le, chunk, list_entry); if (c->cache) { - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fcb(Vcb, c->cache); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); c->cache = NULL; } @@ -1855,9 +1855,9 @@ void uninit(_In_ device_extension* Vcb, _In_ BOOL flush) { ExFreePool(c->devices); if (c->cache) { - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fcb(Vcb, c->cache); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); } ExDeleteResourceLite(&c->range_locks_lock); @@ -1915,7 +1915,7 @@ void uninit(_In_ device_extension* Vcb, _In_ BOOL flush) { ZwClose(Vcb->flush_thread_handle); } -NTSTATUS delete_fileref(_In_ file_ref* fileref, _In_ PFILE_OBJECT FileObject, _In_opt_ PIRP Irp, _In_ LIST_ENTRY* rollback) { +NTSTATUS delete_fileref(_In_ file_ref* fileref, _In_opt_ PFILE_OBJECT FileObject, _In_opt_ PIRP Irp, _In_ LIST_ENTRY* rollback) { LARGE_INTEGER newlength, time; BTRFS_TIME now; NTSTATUS Status; @@ -1995,6 +1995,18 @@ NTSTATUS delete_fileref(_In_ file_ref* fileref, _In_ PFILE_OBJECT FileObject, _I } fileref->fcb->deleted = TRUE; + + le = fileref->children.Flink; + while (le != &fileref->children) { + file_ref* fr2 = CONTAINING_RECORD(le, file_ref, list_entry); + + if (fr2->fcb->ads) { + fr2->fcb->deleted = TRUE; + mark_fcb_dirty(fr2->fcb); + } + + le = le->Flink; + } } if (fileref->dc) { @@ -2024,11 +2036,25 @@ NTSTATUS delete_fileref(_In_ file_ref* fileref, _In_ PFILE_OBJECT FileObject, _I mark_fcb_dirty(fileref->fcb); // so ROOT_ITEM gets updated } else { + LIST_ENTRY* le; + // FIXME - we need a lock here RemoveEntryList(&fileref->fcb->subvol->list_entry); InsertTailList(&fileref->fcb->Vcb->drop_roots, &fileref->fcb->subvol->list_entry); + + le = fileref->children.Flink; + while (le != &fileref->children) { + file_ref* fr2 = CONTAINING_RECORD(le, file_ref, list_entry); + + if (fr2->fcb->ads) { + fr2->fcb->deleted = TRUE; + mark_fcb_dirty(fr2->fcb); + } + + le = le->Flink; + } } } } else { @@ -2209,18 +2235,18 @@ static NTSTATUS drv_cleanup(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) { locked = FALSE; // fcb_lock needs to be acquired before fcb->Header.Resource - ExAcquireResourceExclusiveLite(&fcb->Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(fcb->Vcb); Status = delete_fileref(fileref, FileObject, Irp, &rollback); if (!NT_SUCCESS(Status)) { ERR("delete_fileref returned %08x\n", Status); do_rollback(fcb->Vcb, &rollback); - ExReleaseResourceLite(&fcb->Vcb->fcb_lock); + release_fcb_lock(fcb->Vcb); ExReleaseResourceLite(&fcb->Vcb->tree_lock); goto exit; } - ExReleaseResourceLite(&fcb->Vcb->fcb_lock); + release_fcb_lock(fcb->Vcb); locked = FALSE; @@ -4522,19 +4548,19 @@ exit2: if (Vcb->root_file) ObDereferenceObject(Vcb->root_file); else if (Vcb->root_fileref) { - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, Vcb->root_fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); } else if (root_fcb) { - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fcb(Vcb, root_fcb); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); } if (Vcb->volume_fcb) { - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fcb(Vcb, Vcb->volume_fcb); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); } ExDeleteResourceLite(&Vcb->tree_lock); diff --git a/drivers/filesystems/btrfs/btrfs.rc b/drivers/filesystems/btrfs/btrfs.rc index f18e6ef56ab..d79da1aa156 100644 --- a/drivers/filesystems/btrfs/btrfs.rc +++ b/drivers/filesystems/btrfs/btrfs.rc @@ -53,8 +53,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,1 - PRODUCTVERSION 1,0,0,1 + FILEVERSION 1,0,1,0 + PRODUCTVERSION 1,0,1,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -70,12 +70,12 @@ BEGIN BLOCK "080904b0" BEGIN VALUE "FileDescription", "WinBtrfs" - VALUE "FileVersion", "1.0" + VALUE "FileVersion", "1.0.1" VALUE "InternalName", "btrfs" VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-17" VALUE "OriginalFilename", "btrfs.sys" VALUE "ProductName", "WinBtrfs" - VALUE "ProductVersion", "1.0" + VALUE "ProductVersion", "1.0.1" END END BLOCK "VarFileInfo" diff --git a/drivers/filesystems/btrfs/btrfs_drv.h b/drivers/filesystems/btrfs/btrfs_drv.h index b658726f9a2..1cb50cbfa4b 100644 --- a/drivers/filesystems/btrfs/btrfs_drv.h +++ b/drivers/filesystems/btrfs/btrfs_drv.h @@ -170,6 +170,9 @@ typedef struct _FSCTL_SET_INTEGRITY_INFORMATION_BUFFER { #define _Create_lock_level_(a) #define _Lock_level_order_(a,b) #define _Has_lock_level_(a) +#define _Requires_lock_not_held_(a) +#define _Acquires_exclusive_lock_(a) +#define _Acquires_shared_lock_(a) #endif #endif @@ -634,6 +637,9 @@ typedef struct { UINT64 create_total_time; UINT64 open_fcb_calls; UINT64 open_fcb_time; + UINT64 open_fileref_child_calls; + UINT64 open_fileref_child_time; + UINT64 fcb_lock_time; } debug_stats; #endif @@ -890,6 +896,52 @@ typedef struct { LIST_ENTRY list_entry; } name_bit; +_Requires_lock_not_held_(Vcb->fcb_lock) +_Acquires_shared_lock_(Vcb->fcb_lock) +static __inline void acquire_fcb_lock_shared(device_extension* Vcb) { +#ifdef DEBUG_STATS + LARGE_INTEGER time1, time2; + + if (ExAcquireResourceSharedLite(&Vcb->fcb_lock, FALSE)) + return; + + time1 = KeQueryPerformanceCounter(NULL); +#endif + + ExAcquireResourceSharedLite(&Vcb->fcb_lock, TRUE); + +#ifdef DEBUG_STATS + time2 = KeQueryPerformanceCounter(NULL); + Vcb->stats.fcb_lock_time += time2.QuadPart - time1.QuadPart; +#endif +} + +_Requires_lock_not_held_(Vcb->fcb_lock) +_Acquires_exclusive_lock_(Vcb->fcb_lock) +static __inline void acquire_fcb_lock_exclusive(device_extension* Vcb) { +#ifdef DEBUG_STATS + LARGE_INTEGER time1, time2; + + if (ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, FALSE)) + return; + + time1 = KeQueryPerformanceCounter(NULL); +#endif + + ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + +#ifdef DEBUG_STATS + time2 = KeQueryPerformanceCounter(NULL); + Vcb->stats.fcb_lock_time += time2.QuadPart - time1.QuadPart; +#endif +} + +_Requires_lock_held_(Vcb->fcb_lock) +_Releases_lock_(Vcb->fcb_lock) +static __inline void release_fcb_lock(device_extension* Vcb) { + ExReleaseResourceLite(&Vcb->fcb_lock); +} + static __inline void* map_user_buffer(PIRP Irp, ULONG priority) { if (!Irp->MdlAddress) { return Irp->UserBuffer; @@ -1043,7 +1095,7 @@ WCHAR* file_desc(_In_ PFILE_OBJECT FileObject); WCHAR* file_desc_fileref(_In_ file_ref* fileref); void mark_fcb_dirty(_In_ fcb* fcb); void mark_fileref_dirty(_In_ file_ref* fileref); -NTSTATUS delete_fileref(_In_ file_ref* fileref, _In_ PFILE_OBJECT FileObject, _In_opt_ PIRP Irp, _In_ LIST_ENTRY* rollback); +NTSTATUS delete_fileref(_In_ file_ref* fileref, _In_opt_ PFILE_OBJECT FileObject, _In_opt_ PIRP Irp, _In_ LIST_ENTRY* rollback); void chunk_lock_range(_In_ device_extension* Vcb, _In_ chunk* c, _In_ UINT64 start, _In_ UINT64 length); void chunk_unlock_range(_In_ device_extension* Vcb, _In_ chunk* c, _In_ UINT64 start, _In_ UINT64 length); void init_device(_In_ device_extension* Vcb, _Inout_ device* dev, _In_ BOOL get_nums); diff --git a/drivers/filesystems/btrfs/create.c b/drivers/filesystems/btrfs/create.c index 0ea66bb8db6..15728de757f 100644 --- a/drivers/filesystems/btrfs/create.c +++ b/drivers/filesystems/btrfs/create.c @@ -1418,6 +1418,13 @@ NTSTATUS open_fileref(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusiv return STATUS_OBJECT_PATH_NOT_FOUND; } + // if path starts with two backslashes, ignore one of them + if (fnus2.Length >= 2 * sizeof(WCHAR) && fnus2.Buffer[1] == '\\') { + fnus2.Buffer++; + fnus2.Length -= sizeof(WCHAR); + fnus2.MaximumLength -= sizeof(WCHAR); + } + if (fnus2.Length == sizeof(WCHAR)) { if (Vcb->root_fileref->open_count == 0 && !(Vcb->Vpb->Flags & VPB_MOUNTED)) // don't allow root to be opened on unmounted FS return STATUS_DEVICE_NOT_READY; @@ -1487,8 +1494,19 @@ NTSTATUS open_fileref(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusiv name_bit* nb = CONTAINING_RECORD(le, name_bit, list_entry); BOOL lastpart = le->Flink == &parts || (has_stream && le->Flink->Flink == &parts); BOOL streampart = has_stream && le->Flink == &parts; +#ifdef DEBUG_STATS + LARGE_INTEGER time1, time2; +#endif +#ifdef DEBUG_STATS + time1 = KeQueryPerformanceCounter(NULL); +#endif Status = open_fileref_child(Vcb, sf, &nb->us, case_sensitive, lastpart, streampart, pooltype, &sf2, Irp); +#ifdef DEBUG_STATS + time2 = KeQueryPerformanceCounter(NULL); + Vcb->stats.open_fileref_child_calls++; + Vcb->stats.open_fileref_child_time += time2.QuadPart - time1.QuadPart; +#endif if (!NT_SUCCESS(Status)) { if (Status == STATUS_OBJECT_PATH_NOT_FOUND || Status == STATUS_OBJECT_NAME_NOT_FOUND) TRACE("open_fileref_child returned %08x\n", Status); @@ -1655,6 +1673,9 @@ static NTSTATUS file_create2(_In_ PIRP Irp, _Requires_exclusive_lock_held_(_Curr if (parfileref->fcb == Vcb->dummy_fcb) return STATUS_ACCESS_DENIED; + if (options & FILE_DIRECTORY_FILE && IrpSp->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_TEMPORARY) + return STATUS_INVALID_PARAMETER; + Status = RtlUnicodeToUTF8N(NULL, 0, &utf8len, fpus->Buffer, fpus->Length); if (!NT_SUCCESS(Status)) { ERR("RtlUnicodeToUTF8N returned %08x\n", Status); @@ -1701,9 +1722,7 @@ static NTSTATUS file_create2(_In_ PIRP Irp, _Requires_exclusive_lock_held_(_Curr TRACE("requested attributes = %x\n", IrpSp->Parameters.Create.FileAttributes); - IrpSp->Parameters.Create.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE; - - defda = FILE_ATTRIBUTE_ARCHIVE; + defda = 0; if (utf8[0] == '.') defda |= FILE_ATTRIBUTE_HIDDEN; @@ -1714,6 +1733,11 @@ static NTSTATUS file_create2(_In_ PIRP Irp, _Requires_exclusive_lock_held_(_Curr } else IrpSp->Parameters.Create.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY; + if (!(IrpSp->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + IrpSp->Parameters.Create.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE; + defda |= FILE_ATTRIBUTE_ARCHIVE; + } + TRACE("defda = %x\n", defda); if (IrpSp->Parameters.Create.FileAttributes == FILE_ATTRIBUTE_NORMAL) @@ -2235,7 +2259,7 @@ static NTSTATUS create_stream(_Requires_lock_held_(_Curr_->tree_lock) _Requires_ *pfileref = fileref; - send_notification_fileref(parfileref, options & FILE_DIRECTORY_FILE ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_ADDED, &fileref->dc->name); + send_notification_fileref(parfileref, FILE_NOTIFY_CHANGE_STREAM_NAME, FILE_ACTION_ADDED_STREAM, &fileref->dc->name); return STATUS_SUCCESS; } @@ -2279,6 +2303,9 @@ static NTSTATUS file_create(PIRP Irp, _Requires_lock_held_(_Curr_->tree_lock) _R if (Vcb->readonly) return STATUS_MEDIA_WRITE_PROTECTED; + if (options & FILE_DELETE_ON_CLOSE && IrpSp->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_READONLY) + return STATUS_CANNOT_DELETE; + dsus.Buffer = datasuf; dsus.Length = dsus.MaximumLength = (USHORT)wcslen(datasuf) * sizeof(WCHAR); fpus.Buffer = NULL; @@ -2836,7 +2863,7 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur goto exit; } - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); if (options & FILE_OPEN_BY_FILE_ID) { if (fn.Length == sizeof(UINT64) && related && RequestedDisposition == FILE_OPEN) { @@ -2857,13 +2884,13 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur } else { WARN("FILE_OPEN_BY_FILE_ID only supported for inodes\n"); Status = STATUS_NOT_IMPLEMENTED; - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } } else { if (related && fn.Length != 0 && fn.Buffer[0] == '\\') { - Status = STATUS_OBJECT_NAME_INVALID; - ExReleaseResourceLite(&Vcb->fcb_lock); + Status = STATUS_INVALID_PARAMETER; + release_fcb_lock(Vcb); goto exit; } @@ -2922,7 +2949,7 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur Irp->Tail.Overlay.AuxiliaryBuffer = (void*)data; free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } @@ -2937,23 +2964,23 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur Status = STATUS_OBJECT_NAME_COLLISION; free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } } else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) { if (RequestedDisposition == FILE_OPEN || RequestedDisposition == FILE_OVERWRITE) { TRACE("file doesn't exist, returning STATUS_OBJECT_NAME_NOT_FOUND\n"); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } } else if (Status == STATUS_OBJECT_PATH_NOT_FOUND) { TRACE("open_fileref returned %08x\n", Status); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } else { ERR("open_fileref returned %08x\n", Status); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } @@ -2961,7 +2988,7 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur file_ref* sf; BOOL readonly; - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); if (RequestedDisposition == FILE_SUPERSEDE || RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF) { LARGE_INTEGER zero; @@ -2972,9 +2999,9 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur if (fileref->fcb->type == BTRFS_TYPE_DIRECTORY || is_subvol_readonly(fileref->fcb->subvol, Irp)) { Status = STATUS_ACCESS_DENIED; - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } @@ -2982,9 +3009,9 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur if (Vcb->readonly) { Status = STATUS_MEDIA_WRITE_PROTECTED; - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } @@ -2993,9 +3020,9 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur if (!MmCanFileBeTruncated(&fileref->fcb->nonpaged->segment_object, &zero)) { Status = STATUS_USER_MAPPED_FILE; - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } @@ -3012,9 +3039,9 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur SeUnlockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext); TRACE("SeAccessCheck failed, returning %08x\n", Status); - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } @@ -3031,9 +3058,9 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur TRACE("could not open as deletion pending\n"); Status = STATUS_DELETE_PENDING; - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } @@ -3043,6 +3070,16 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur readonly = (!fileref->fcb->ads && fileref->fcb->atts & FILE_ATTRIBUTE_READONLY) || (fileref->fcb->ads && fileref->parent->fcb->atts & FILE_ATTRIBUTE_READONLY) || is_subvol_readonly(fileref->fcb->subvol, Irp) || fileref->fcb == Vcb->dummy_fcb || Vcb->readonly; + if (options & FILE_DELETE_ON_CLOSE && (fileref == Vcb->root_fileref || readonly)) { + Status = STATUS_CANNOT_DELETE; + + acquire_fcb_lock_exclusive(Vcb); + free_fileref(Vcb, fileref); + release_fcb_lock(Vcb); + + goto exit; + } + if (readonly) { ACCESS_MASK allowed; @@ -3070,25 +3107,14 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur } else if (granted_access & ~allowed) { Status = Vcb->readonly ? STATUS_MEDIA_WRITE_PROTECTED : STATUS_ACCESS_DENIED; - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } } - if (options & FILE_DELETE_ON_CLOSE && (fileref == Vcb->root_fileref || Vcb->readonly || - is_subvol_readonly(fileref->fcb->subvol, Irp) || readonly)) { - Status = STATUS_CANNOT_DELETE; - - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); - free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); - - goto exit; - } - if ((fileref->fcb->type == BTRFS_TYPE_SYMLINK || fileref->fcb->atts & FILE_ATTRIBUTE_REPARSE_POINT) && !(options & FILE_OPEN_REPARSE_POINT)) { REPARSE_DATA_BUFFER* data; @@ -3112,9 +3138,9 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur Irp->Tail.Overlay.AuxiliaryBuffer = (void*)data; - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } @@ -3124,9 +3150,9 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur if (options & FILE_NON_DIRECTORY_FILE && !(fileref->fcb->atts & FILE_ATTRIBUTE_REPARSE_POINT)) { Status = STATUS_FILE_IS_A_DIRECTORY; - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } @@ -3134,9 +3160,9 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur TRACE("returning STATUS_NOT_A_DIRECTORY (type = %u, %S)\n", fileref->fcb->type, file_desc_fileref(fileref)); Status = STATUS_NOT_A_DIRECTORY; - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } @@ -3150,9 +3176,9 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur else WARN("IoCheckShareAccess failed, returning %08x\n", Status); - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } @@ -3167,9 +3193,9 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } @@ -3186,13 +3212,24 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } + if (!fileref->fcb->ads && (IrpSp->Parameters.Create.FileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != ((fileref->fcb->atts & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))) { + IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); + + acquire_fcb_lock_exclusive(Vcb); + free_fileref(Vcb, fileref); + release_fcb_lock(Vcb); + + Status = STATUS_ACCESS_DENIED; + goto exit; + } + if (fileref->fcb->ads) { Status = stream_set_end_of_file_information(Vcb, 0, fileref->fcb, fileref, FALSE); if (!NT_SUCCESS(Status)) { @@ -3200,9 +3237,9 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } @@ -3213,9 +3250,9 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } @@ -3229,15 +3266,17 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } } if (!fileref->fcb->ads) { + LIST_ENTRY* le; + if (Irp->AssociatedIrp.SystemBuffer && IrpSp->Parameters.Create.EaLength > 0) { ULONG offset; FILE_FULL_EA_INFORMATION* eainfo; @@ -3248,9 +3287,9 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } @@ -3285,9 +3324,9 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } @@ -3304,6 +3343,41 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur fileref->fcb->ealen = 0; } } + + // remove streams and send notifications + le = fileref->fcb->dir_children_index.Flink; + while (le != &fileref->fcb->dir_children_index) { + dir_child* dc = CONTAINING_RECORD(le, dir_child, list_entry_index); + LIST_ENTRY* le2 = le->Flink; + + if (dc->index == 0) { + if (!dc->fileref) { + file_ref* fr2; + + Status = open_fileref_child(Vcb, fileref, &dc->name, TRUE, TRUE, TRUE, PagedPool, &fr2, NULL); + if (!NT_SUCCESS(Status)) + WARN("open_fileref_child returned %08x\n", Status); + } + + if (dc->fileref) { + send_notification_fcb(fileref, FILE_NOTIFY_CHANGE_STREAM_NAME, FILE_ACTION_REMOVED_STREAM, &dc->name); + + Status = delete_fileref(dc->fileref, NULL, NULL, rollback); + if (!NT_SUCCESS(Status)) { + ERR("delete_fileref returned %08x\n", Status); + + acquire_fcb_lock_exclusive(Vcb); + free_fileref(Vcb, fileref); + release_fcb_lock(Vcb); + + goto exit; + } + } + } else + break; + + le = le2; + } } KeQuerySystemTime(&time); @@ -3355,9 +3429,9 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } @@ -3379,9 +3453,9 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fileref); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto exit; } @@ -3467,8 +3541,8 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur #ifdef DEBUG_STATS open_type = 2; #endif - Status = file_create(Irp, DeviceObject->DeviceExtension, FileObject, related, loaded_related, &fn, RequestedDisposition, options, rollback); - ExReleaseResourceLite(&Vcb->fcb_lock); + Status = file_create(Irp, Vcb, FileObject, related, loaded_related, &fn, RequestedDisposition, options, rollback); + release_fcb_lock(Vcb); Irp->IoStatus.Information = NT_SUCCESS(Status) ? FILE_CREATED : 0; } @@ -3478,9 +3552,9 @@ static NTSTATUS open_file(PDEVICE_OBJECT DeviceObject, _Requires_lock_held_(_Cur exit: if (loaded_related) { - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, related); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); } if (Status == STATUS_SUCCESS) { diff --git a/drivers/filesystems/btrfs/dirctrl.c b/drivers/filesystems/btrfs/dirctrl.c index 5c78146153a..0ae95d636c8 100644 --- a/drivers/filesystems/btrfs/dirctrl.c +++ b/drivers/filesystems/btrfs/dirctrl.c @@ -628,7 +628,7 @@ static NTSTATUS query_directory(PIRP Irp) { return STATUS_NO_MORE_FILES; ExAcquireResourceSharedLite(&Vcb->tree_lock, TRUE); - ExAcquireResourceSharedLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_shared(Vcb); TRACE("%S\n", file_desc(IrpSp->FileObject)); @@ -658,8 +658,6 @@ static NTSTATUS query_directory(PIRP Irp) { TRACE(" unknown flags: %u\n", flags); } - initial = !ccb->query_string.Buffer; - if (IrpSp->Flags & SL_RESTART_SCAN) { ccb->query_dir_offset = 0; @@ -667,8 +665,13 @@ static NTSTATUS query_directory(PIRP Irp) { RtlFreeUnicodeString(&ccb->query_string); ccb->query_string.Buffer = NULL; } + + ccb->has_wildcard = FALSE; + ccb->specific_file = FALSE; } + initial = !ccb->query_string.Buffer; + if (IrpSp->Parameters.QueryDirectory.FileName && IrpSp->Parameters.QueryDirectory.FileName->Length > 1) { TRACE("QD filename: %.*S\n", IrpSp->Parameters.QueryDirectory.FileName->Length / sizeof(WCHAR), IrpSp->Parameters.QueryDirectory.FileName->Buffer); @@ -906,7 +909,7 @@ end: ExReleaseResourceLite(&fileref->fcb->nonpaged->dir_children_lock); end2: - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); ExReleaseResourceLite(&Vcb->tree_lock); TRACE("returning %08x\n", Status); diff --git a/drivers/filesystems/btrfs/fileinfo.c b/drivers/filesystems/btrfs/fileinfo.c index e79f4535119..9f736671da4 100644 --- a/drivers/filesystems/btrfs/fileinfo.c +++ b/drivers/filesystems/btrfs/fileinfo.c @@ -188,7 +188,7 @@ static NTSTATUS set_disposition_information(device_extension* Vcb, PIRP Irp, PFI if (!fileref) return STATUS_INVALID_PARAMETER; - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); ExAcquireResourceExclusiveLite(fcb->Header.Resource, TRUE); @@ -235,7 +235,7 @@ static NTSTATUS set_disposition_information(device_extension* Vcb, PIRP Irp, PFI end: ExReleaseResourceLite(fcb->Header.Resource); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); // send notification that directory is about to be deleted if (NT_SUCCESS(Status) && fdi->DeleteFile && fcb->type == BTRFS_TYPE_DIRECTORY) { @@ -1348,7 +1348,7 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB } ExAcquireResourceSharedLite(&Vcb->tree_lock, TRUE); - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); ExAcquireResourceExclusiveLite(fcb->Header.Resource, TRUE); if (fcb->ads) { @@ -1885,7 +1885,7 @@ end: do_rollback(Vcb, &rollback); ExReleaseResourceLite(fcb->Header.Resource); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); ExReleaseResourceLite(&Vcb->tree_lock); return Status; @@ -1913,7 +1913,7 @@ NTSTATUS stream_set_end_of_file_information(device_extension* Vcb, UINT16 end, f TRACE("extending stream to %llx bytes\n", end); if (end > fcb->adsmaxlen) { - ERR("error - xattr too long (%llu > %u)\n", end, fcb->adsmaxlen); + ERR("error - xattr too long (%u > %u)\n", end, fcb->adsmaxlen); return STATUS_DISK_FULL; } @@ -2009,7 +2009,7 @@ static NTSTATUS set_end_of_file_information(device_extension* Vcb, PIRP Irp, PFI set_size = TRUE; } - filter = FILE_NOTIFY_CHANGE_SIZE; + filter = FILE_NOTIFY_CHANGE_STREAM_SIZE; if (!ccb->user_set_write_time) { KeQuerySystemTime(&time); @@ -2020,7 +2020,7 @@ static NTSTATUS set_end_of_file_information(device_extension* Vcb, PIRP Irp, PFI mark_fcb_dirty(fileref->parent->fcb); } - send_notification_fcb(fileref->parent, filter, FILE_ACTION_MODIFIED, &fileref->dc->name); + send_notification_fcb(fileref->parent, filter, FILE_ACTION_MODIFIED_STREAM, &fileref->dc->name); goto end; } @@ -2182,7 +2182,7 @@ static NTSTATUS set_link_information(device_extension* Vcb, PIRP Irp, PFILE_OBJE } ExAcquireResourceSharedLite(&Vcb->tree_lock, TRUE); - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); ExAcquireResourceExclusiveLite(fcb->Header.Resource, TRUE); if (fcb->type == BTRFS_TYPE_DIRECTORY) { @@ -2451,7 +2451,7 @@ end: do_rollback(Vcb, &rollback); ExReleaseResourceLite(fcb->Header.Resource); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); ExReleaseResourceLite(&Vcb->tree_lock); return Status; @@ -3472,7 +3472,7 @@ static NTSTATUS fill_in_hard_link_information(FILE_LINKS_INFORMATION* fli, file_ len = bytes_needed; } } else { - ExAcquireResourceExclusiveLite(&fcb->Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(fcb->Vcb); if (IsListEmpty(&fcb->hardlinks)) { bytes_needed += sizeof(FILE_LINK_ENTRY_INFORMATION) + fileref->dc->name.Length - sizeof(WCHAR); @@ -3565,7 +3565,7 @@ static NTSTATUS fill_in_hard_link_information(FILE_LINKS_INFORMATION* fli, file_ } } - ExReleaseResourceLite(&fcb->Vcb->fcb_lock); + release_fcb_lock(fcb->Vcb); } fli->BytesNeeded = bytes_needed; diff --git a/drivers/filesystems/btrfs/flushthread.c b/drivers/filesystems/btrfs/flushthread.c index aa3d9b6b0f8..ceb37c5a2ae 100644 --- a/drivers/filesystems/btrfs/flushthread.c +++ b/drivers/filesystems/btrfs/flushthread.c @@ -7289,6 +7289,8 @@ NTSTATUS do_write(device_extension* Vcb, PIRP Irp) { #ifdef DEBUG_STATS static void print_stats(device_extension* Vcb) { + LARGE_INTEGER freq; + ERR("READ STATS:\n"); ERR("number of reads: %llu\n", Vcb->stats.num_reads); ERR("data read: %llu bytes\n", Vcb->stats.data_read); @@ -7297,7 +7299,9 @@ static void print_stats(device_extension* Vcb) { ERR("disk time taken: %llu\n", Vcb->stats.read_disk_time); ERR("other time taken: %llu\n", Vcb->stats.read_total_time - Vcb->stats.read_csum_time - Vcb->stats.read_disk_time); - ERR("OPEN STATS:\n"); + KeQueryPerformanceCounter(&freq); + + ERR("OPEN STATS (freq = %llu):\n", freq.QuadPart); ERR("number of opens: %llu\n", Vcb->stats.num_opens); ERR("total time taken: %llu\n", Vcb->stats.open_total_time); ERR("number of overwrites: %llu\n", Vcb->stats.num_overwrites); @@ -7305,6 +7309,9 @@ static void print_stats(device_extension* Vcb) { ERR("number of creates: %llu\n", Vcb->stats.num_creates); ERR("calls to open_fcb: %llu\n", Vcb->stats.open_fcb_calls); ERR("time spent in open_fcb: %llu\n", Vcb->stats.open_fcb_time); + ERR("calls to open_fileref_child: %llu\n", Vcb->stats.open_fileref_child_calls); + ERR("time spent in open_fileref_child: %llu\n", Vcb->stats.open_fileref_child_time); + ERR("time spent waiting for fcb_lock: %llu\n", Vcb->stats.fcb_lock_time); ERR("total time taken: %llu\n", Vcb->stats.create_total_time); RtlZeroMemory(&Vcb->stats, sizeof(debug_stats)); diff --git a/drivers/filesystems/btrfs/fsctl.c b/drivers/filesystems/btrfs/fsctl.c index 8e0fb3437b8..87556c47e15 100644 --- a/drivers/filesystems/btrfs/fsctl.c +++ b/drivers/filesystems/btrfs/fsctl.c @@ -1002,10 +1002,10 @@ static NTSTATUS create_subvol(device_extension* Vcb, PFILE_OBJECT FileObject, vo rootfcb->inode_item_changed = TRUE; - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); InsertTailList(&r->fcbs, &rootfcb->list_entry); InsertTailList(&Vcb->all_fcbs, &rootfcb->list_entry_all); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); rootfcb->Header.IsFastIoPossible = fast_io_possible(rootfcb); rootfcb->Header.AllocationSize.QuadPart = 0; @@ -1049,9 +1049,9 @@ static NTSTATUS create_subvol(device_extension* Vcb, PFILE_OBJECT FileObject, vo if (!fr) { ERR("out of memory\n"); - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fcb(Vcb, rootfcb); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); Status = STATUS_INSUFFICIENT_RESOURCES; goto end; @@ -1073,9 +1073,9 @@ 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"); - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fr); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); Status = STATUS_INSUFFICIENT_RESOURCES; goto end; } @@ -1085,9 +1085,9 @@ 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"); - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fr); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); Status = STATUS_INSUFFICIENT_RESOURCES; goto end; } @@ -1155,9 +1155,9 @@ end: end2: if (fr) { - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_exclusive(Vcb); free_fileref(Vcb, fr); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); } return Status; @@ -2194,15 +2194,15 @@ static NTSTATUS lock_volume(device_extension* Vcb, PIRP Irp) { if (Vcb->locked) return STATUS_SUCCESS; - ExAcquireResourceExclusiveLite(&Vcb->fcb_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; - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); goto end; } - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); if (Vcb->balance.thread && KeReadStateEvent(&Vcb->balance.event)) { ExAcquireResourceExclusiveLite(&Vcb->tree_lock, TRUE); @@ -2377,6 +2377,7 @@ static NTSTATUS invalidate_volumes(PIRP Irp) { if (!NT_SUCCESS(Status)) { ERR("do_write returned %08x\n", Status); ExReleaseResourceLite(&Vcb->tree_lock); + ExFreePool(newvpb); goto end; } @@ -3742,7 +3743,7 @@ static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data name.Length = name.MaximumLength = bmn->namelen; name.Buffer = bmn->name; - ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE); + 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) { @@ -3982,7 +3983,7 @@ static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data Status = STATUS_SUCCESS; end: - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); ExFreePool(utf8.Buffer); @@ -4429,11 +4430,11 @@ static NTSTATUS get_subvol_path(device_extension* Vcb, UINT64 id, WCHAR* out, UL return STATUS_INTERNAL_ERROR; } - ExAcquireResourceSharedLite(&Vcb->fcb_lock, TRUE); + acquire_fcb_lock_shared(Vcb); Status = open_fileref_by_inode(Vcb, r, r->root_item.objid, &fr, Irp); if (!NT_SUCCESS(Status)) { - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); ERR("open_fileref_by_inode returned %08x\n", Status); return Status; } @@ -4451,7 +4452,7 @@ static NTSTATUS get_subvol_path(device_extension* Vcb, UINT64 id, WCHAR* out, UL free_fileref(Vcb, fr); - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); return Status; } diff --git a/drivers/filesystems/btrfs/pnp.c b/drivers/filesystems/btrfs/pnp.c index aac3ea3a54e..34997cfd592 100644 --- a/drivers/filesystems/btrfs/pnp.c +++ b/drivers/filesystems/btrfs/pnp.c @@ -161,7 +161,7 @@ static NTSTATUS pnp_cancel_remove_device(PDEVICE_OBJECT DeviceObject) { ExAcquireResourceSharedLite(&Vcb->tree_lock, TRUE); - ExAcquireResourceExclusiveLite(&Vcb->fcb_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; @@ -175,7 +175,7 @@ static NTSTATUS pnp_cancel_remove_device(PDEVICE_OBJECT DeviceObject) { } end: - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); ExReleaseResourceLite(&Vcb->tree_lock); return STATUS_SUCCESS; @@ -187,7 +187,7 @@ NTSTATUS pnp_query_remove_device(PDEVICE_OBJECT DeviceObject, PIRP Irp) { ExAcquireResourceExclusiveLite(&Vcb->tree_lock, TRUE); - ExAcquireResourceExclusiveLite(&Vcb->fcb_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; @@ -216,7 +216,7 @@ NTSTATUS pnp_query_remove_device(PDEVICE_OBJECT DeviceObject, PIRP Irp) { Status = STATUS_SUCCESS; end: - ExReleaseResourceLite(&Vcb->fcb_lock); + release_fcb_lock(Vcb); ExReleaseResourceLite(&Vcb->tree_lock); diff --git a/drivers/filesystems/btrfs/read.c b/drivers/filesystems/btrfs/read.c index 4fda6504029..ddeea66c7aa 100644 --- a/drivers/filesystems/btrfs/read.c +++ b/drivers/filesystems/btrfs/read.c @@ -3209,17 +3209,6 @@ NTSTATUS do_read(PIRP Irp, BOOLEAN wait, ULONG* bytes_read) { return STATUS_PENDING; } - if (!(Irp->Flags & IRP_PAGING_IO) && FileObject->SectionObjectPointer->DataSectionObject) { - IO_STATUS_BLOCK iosb; - - CcFlushCache(FileObject->SectionObjectPointer, &IrpSp->Parameters.Read.ByteOffset, length, &iosb); - - if (!NT_SUCCESS(iosb.Status)) { - ERR("CcFlushCache returned %08x\n", iosb.Status); - return iosb.Status; - } - } - if (fcb->ads) Status = read_stream(fcb, data, start, length, bytes_read); else @@ -3325,6 +3314,16 @@ NTSTATUS drv_read(PDEVICE_OBJECT DeviceObject, PIRP Irp) { if (Irp->Flags & IRP_PAGING_IO) wait = TRUE; + if (!(Irp->Flags & IRP_PAGING_IO) && FileObject->SectionObjectPointer->DataSectionObject) { + IO_STATUS_BLOCK iosb; + + CcFlushCache(FileObject->SectionObjectPointer, &IrpSp->Parameters.Read.ByteOffset, IrpSp->Parameters.Read.Length, &iosb); + if (!NT_SUCCESS(iosb.Status)) { + ERR("CcFlushCache returned %08x\n", iosb.Status); + return iosb.Status; + } + } + if (!ExIsResourceAcquiredSharedLite(fcb->Header.Resource)) { if (!ExAcquireResourceSharedLite(fcb->Header.Resource, wait)) { Status = STATUS_PENDING; diff --git a/drivers/filesystems/btrfs/reparse.c b/drivers/filesystems/btrfs/reparse.c index 440894323c7..8e8d319b584 100644 --- a/drivers/filesystems/btrfs/reparse.c +++ b/drivers/filesystems/btrfs/reparse.c @@ -289,6 +289,10 @@ NTSTATUS set_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp) { return STATUS_INVALID_PARAMETER; } + // IFSTest insists on this, for some reason... + if (Irp->UserBuffer) + return STATUS_INVALID_PARAMETER; + fcb = FileObject->FsContext; ccb = FileObject->FsContext2; @@ -297,9 +301,7 @@ NTSTATUS set_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp) { return STATUS_INVALID_PARAMETER; } - // It isn't documented what permissions FSCTL_SET_REPARSE_POINT needs, but CreateSymbolicLinkW - // creates a file with FILE_WRITE_ATTRIBUTES | DELETE | SYNCHRONIZE. - if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_WRITE_ATTRIBUTES)) { + if (Irp->RequestorMode == UserMode && !(ccb->access & (FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA))) { WARN("insufficient privileges\n"); return STATUS_ACCESS_DENIED; } @@ -333,7 +335,13 @@ NTSTATUS set_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp) { if (buflen < sizeof(ULONG)) { WARN("buffer was not long enough to hold tag\n"); - Status = STATUS_INVALID_PARAMETER; + Status = STATUS_INVALID_BUFFER_SIZE; + goto end; + } + + Status = FsRtlValidateReparsePointBuffer(buflen, rdb); + if (!NT_SUCCESS(Status)) { + ERR("FsRtlValidateReparsePointBuffer returned %08x\n", Status); goto end; } diff --git a/drivers/filesystems/btrfs/search.c b/drivers/filesystems/btrfs/search.c index 6f3dd62a2bb..bec1aba420e 100644 --- a/drivers/filesystems/btrfs/search.c +++ b/drivers/filesystems/btrfs/search.c @@ -913,8 +913,7 @@ void mountmgr_thread(_In_ void* context) { if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) ERR("IOCTL_MOUNTMGR_QUERY_POINTS 1 returned %08x\n", Status); - - if (mmps.Size > 0) { + else if (mmps.Size > 0) { MOUNTMGR_MOUNT_POINTS* mmps2; mmps2 = ExAllocatePoolWithTag(NonPagedPool, mmps.Size, ALLOC_TAG); diff --git a/drivers/filesystems/btrfs/volume.c b/drivers/filesystems/btrfs/volume.c index eff7f07c4cd..5f7516a5c28 100755 --- a/drivers/filesystems/btrfs/volume.c +++ b/drivers/filesystems/btrfs/volume.c @@ -983,9 +983,9 @@ static BOOL allow_degraded_mount(BTRFS_UUID* uuid) { ZwClose(h); +end: ExFreePool(kvfi); -end: ExFreePool(path.Buffer); return degraded; diff --git a/drivers/filesystems/btrfs/write.c b/drivers/filesystems/btrfs/write.c index 95e6397424d..c3a8fb74760 100644 --- a/drivers/filesystems/btrfs/write.c +++ b/drivers/filesystems/btrfs/write.c @@ -4335,6 +4335,11 @@ NTSTATUS write_file2(device_extension* Vcb, PIRP Irp, LARGE_INTEGER offset, void Status = _SEH2_GetExceptionCode(); } _SEH2_END; + if (changed_length) { + send_notification_fcb(fcb->ads ? fileref->parent : fileref, fcb->ads ? FILE_NOTIFY_CHANGE_STREAM_SIZE : FILE_NOTIFY_CHANGE_SIZE, + fcb->ads ? FILE_ACTION_MODIFIED_STREAM : FILE_ACTION_MODIFIED, fcb->ads && fileref->dc ? &fileref->dc->name : NULL); + } + goto end; } @@ -4553,7 +4558,9 @@ NTSTATUS write_file2(device_extension* Vcb, PIRP Irp, LARGE_INTEGER offset, void fileref->parent->fcb->inode_item_changed = TRUE; if (changed_length) - filter |= FILE_NOTIFY_CHANGE_SIZE; + filter |= FILE_NOTIFY_CHANGE_STREAM_SIZE; + + filter |= FILE_NOTIFY_CHANGE_STREAM_WRITE; } if (!ccb->user_set_write_time) { @@ -4585,7 +4592,8 @@ NTSTATUS write_file2(device_extension* Vcb, PIRP Irp, LARGE_INTEGER offset, void Status = STATUS_SUCCESS; if (filter != 0) - send_notification_fcb(fcb->ads ? fileref->parent : fileref, filter, FILE_ACTION_MODIFIED, fcb->ads && fileref->dc ? &fileref->dc->name : NULL); + send_notification_fcb(fcb->ads ? fileref->parent : fileref, filter, fcb->ads ? FILE_ACTION_MODIFIED_STREAM : FILE_ACTION_MODIFIED, + fcb->ads && fileref->dc ? &fileref->dc->name : NULL); end: if (NT_SUCCESS(Status) && FileObject->Flags & FO_SYNCHRONOUS_IO && !paging_io) {