https://git.reactos.org/?p=reactos.git;a=commitdiff;h=174dfab6678fd87b0872b3...
commit 174dfab6678fd87b0872b3592fcec956778134b1 Author: Vincent Franchomme franchomme.vincent@gmail.com AuthorDate: Thu Apr 28 21:31:44 2022 +0200 Commit: Hermès BÉLUSCA - MAÏTO hermes.belusca-maito@reactos.org CommitDate: Tue May 3 17:30:11 2022 +0200
[BTRFS][UBTRFS][SHELLBTRFS] Upgrade to 1.7.3 (#4417)
v1.7.3 (2020-05-24):
- Fixed crash when sending file change notifications - Improved symlink handling with LXSS - Added support for undocumented flag SL_IGNORE_READONLY_ATTRIBUTE - Fixed corruption caused by edge case, where address allocated and freed in same flush - Improved handling of free space tree - Improved handling of very full volumes - Fixed spurious warnings raised by GCC 10 static analyser - Replaced multiplications and divisions with bit shift operations where appropriate - Fixed combobox stylings in shell extension --- dll/shellext/shellbtrfs/shellbtrfs.rc | 14 +- dll/win32/ubtrfs/ubtrfs.rc | 14 +- drivers/filesystems/btrfs/balance.c | 60 +++--- drivers/filesystems/btrfs/boot.c | 50 ++++- drivers/filesystems/btrfs/btrfs.c | 257 ++++++++++++---------- drivers/filesystems/btrfs/btrfs.inf | 2 +- drivers/filesystems/btrfs/btrfs.rc | 14 +- drivers/filesystems/btrfs/btrfs_drv.h | 86 ++++---- drivers/filesystems/btrfs/compress.c | 14 +- drivers/filesystems/btrfs/create.c | 51 +++-- drivers/filesystems/btrfs/extent-tree.c | 10 +- drivers/filesystems/btrfs/fileinfo.c | 4 +- drivers/filesystems/btrfs/flushthread.c | 163 +++++++------- drivers/filesystems/btrfs/free-space.c | 364 ++++++++++++++++++++++++-------- drivers/filesystems/btrfs/fsctl.c | 18 +- drivers/filesystems/btrfs/pnp.c | 185 +--------------- drivers/filesystems/btrfs/read.c | 300 ++++++++++++++------------ drivers/filesystems/btrfs/reparse.c | 95 ++++++--- drivers/filesystems/btrfs/scrub.c | 332 +++++++++++++++-------------- drivers/filesystems/btrfs/send.c | 8 +- drivers/filesystems/btrfs/treefuncs.c | 146 +++++++++---- drivers/filesystems/btrfs/volume.c | 2 +- drivers/filesystems/btrfs/write.c | 122 +++++++---- 23 files changed, 1282 insertions(+), 1029 deletions(-)
diff --git a/dll/shellext/shellbtrfs/shellbtrfs.rc b/dll/shellext/shellbtrfs/shellbtrfs.rc index cf13a2bbe65..efc8aa1e581 100644 --- a/dll/shellext/shellbtrfs/shellbtrfs.rc +++ b/dll/shellext/shellbtrfs/shellbtrfs.rc @@ -61,8 +61,8 @@ IDI_ICON1 ICON "subvol.ico" //
VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,7,2,0 - PRODUCTVERSION 1,7,2,0 + FILEVERSION 1,7,3,0 + PRODUCTVERSION 1,7,3,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -78,12 +78,12 @@ BEGIN BLOCK "080904b0" BEGIN VALUE "FileDescription", "WinBtrfs shell extension" - VALUE "FileVersion", "1.7.2" + VALUE "FileVersion", "1.7.3" VALUE "InternalName", "btrfs" VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-20" VALUE "OriginalFilename", "shellbtrfs.dll" VALUE "ProductName", "WinBtrfs" - VALUE "ProductVersion", "1.7.2" + VALUE "ProductVersion", "1.7.3" END END BLOCK "VarFileInfo" @@ -221,7 +221,7 @@ BEGIN CONTROL "",IDC_USAGE_END_SPINNER,"msctls_updown32",UDS_SETBUDDYINT | UDS_AUTOBUDDY | UDS_ARROWKEYS,77,94,11,14 LTEXT "% to",IDC_STATIC,39,97,16,8 CONTROL "&Device:",IDC_DEVID,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,104,6,34,10 - COMBOBOX IDC_DEVID_COMBO,141,6,155,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_DEVID_COMBO,141,6,155,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "%",IDC_STATIC,91,97,8,8 CONTROL "Device &range:",IDC_DRANGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,104,19,59,10 EDITTEXT IDC_DRANGE_END,159,32,40,14,ES_AUTOHSCROLL | ES_NUMBER @@ -244,7 +244,7 @@ BEGIN CONTROL "",IDC_STRIPES_END_SPINNER,"msctls_updown32",UDS_SETBUDDYINT | UDS_AUTOBUDDY | UDS_ARROWKEYS,272,32,11,14 LTEXT "to",IDC_STATIC,242,35,8,8 CONTROL "&Convert:",IDC_CONVERT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,210,49,36,10 - COMBOBOX IDC_CONVERT_COMBO,248,49,48,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_CONVERT_COMBO,248,49,48,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "So&ft",IDC_SOFT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,210,64,28,10 END
@@ -376,7 +376,7 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "OK",IDOK,7,40,50,14 PUSHBUTTON "Cancel",IDCANCEL,74,40,50,14 - COMBOBOX IDC_DRIVE_LETTER_COMBO,64,17,60,30,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_DRIVE_LETTER_COMBO,64,17,60,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP LTEXT "Drive letter:",IDC_STATIC,15,19,45,8 END
diff --git a/dll/win32/ubtrfs/ubtrfs.rc b/dll/win32/ubtrfs/ubtrfs.rc index e43daf348e7..add9d0a5752 100644 --- a/dll/win32/ubtrfs/ubtrfs.rc +++ b/dll/win32/ubtrfs/ubtrfs.rc @@ -25,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" @@ -51,8 +51,8 @@ END //
VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,7,2,0 - PRODUCTVERSION 1,7,2,0 + FILEVERSION 1,7,3,0 + PRODUCTVERSION 1,7,3,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -68,12 +68,12 @@ BEGIN BLOCK "080904b0" BEGIN VALUE "FileDescription", "Btrfs utility DLL" - VALUE "FileVersion", "1.7.2" + VALUE "FileVersion", "1.7.3" VALUE "InternalName", "ubtrfs" VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-20" VALUE "OriginalFilename", "ubtrfs.dll" VALUE "ProductName", "WinBtrfs" - VALUE "ProductVersion", "1.7.2" + VALUE "ProductVersion", "1.7.3" END END BLOCK "VarFileInfo" diff --git a/drivers/filesystems/btrfs/balance.c b/drivers/filesystems/btrfs/balance.c index fc47f97f608..6f2b5e55091 100644 --- a/drivers/filesystems/btrfs/balance.c +++ b/drivers/filesystems/btrfs/balance.c @@ -750,7 +750,7 @@ static NTSTATUS write_metadata_items(_Requires_exclusive_lock_held_(_Curr_->tree
if (newchunk->chunk_item->type == flags && find_metadata_address_in_chunk(Vcb, newchunk, &mr->new_address)) { newchunk->used += Vcb->superblock.node_size; - space_list_subtract(newchunk, false, mr->new_address, Vcb->superblock.node_size, rollback); + space_list_subtract(newchunk, mr->new_address, Vcb->superblock.node_size, rollback); done = true; }
@@ -770,7 +770,7 @@ static NTSTATUS write_metadata_items(_Requires_exclusive_lock_held_(_Curr_->tree if ((c2->chunk_item->size - c2->used) >= Vcb->superblock.node_size) { if (find_metadata_address_in_chunk(Vcb, c2, &mr->new_address)) { c2->used += Vcb->superblock.node_size; - space_list_subtract(c2, false, mr->new_address, Vcb->superblock.node_size, rollback); + space_list_subtract(c2, mr->new_address, Vcb->superblock.node_size, rollback); release_chunk_lock(c2, Vcb); newchunk = c2; done = true; @@ -806,7 +806,7 @@ static NTSTATUS write_metadata_items(_Requires_exclusive_lock_held_(_Curr_->tree goto end; } else { newchunk->used += Vcb->superblock.node_size; - space_list_subtract(newchunk, false, mr->new_address, Vcb->superblock.node_size, rollback); + space_list_subtract(newchunk, mr->new_address, Vcb->superblock.node_size, rollback); }
release_chunk_lock(newchunk, Vcb); @@ -1767,7 +1767,7 @@ static NTSTATUS balance_data_chunk(device_extension* Vcb, chunk* c, bool* change
if (find_data_address_in_chunk(Vcb, newchunk, dr->size, &dr->new_address)) { newchunk->used += dr->size; - space_list_subtract(newchunk, false, dr->new_address, dr->size, &rollback); + space_list_subtract(newchunk, dr->new_address, dr->size, &rollback); done = true; }
@@ -1787,7 +1787,7 @@ static NTSTATUS balance_data_chunk(device_extension* Vcb, chunk* c, bool* change if ((c2->chunk_item->size - c2->used) >= dr->size) { if (find_data_address_in_chunk(Vcb, c2, dr->size, &dr->new_address)) { c2->used += dr->size; - space_list_subtract(c2, false, dr->new_address, dr->size, &rollback); + space_list_subtract(c2, dr->new_address, dr->size, &rollback); release_chunk_lock(c2, Vcb); newchunk = c2; done = true; @@ -1823,7 +1823,7 @@ static NTSTATUS balance_data_chunk(device_extension* Vcb, chunk* c, bool* change goto end; } else { newchunk->used += dr->size; - space_list_subtract(newchunk, false, dr->new_address, dr->size, &rollback); + space_list_subtract(newchunk, dr->new_address, dr->size, &rollback); }
release_chunk_lock(newchunk, Vcb); @@ -1834,7 +1834,7 @@ static NTSTATUS balance_data_chunk(device_extension* Vcb, chunk* c, bool* change
dr->newchunk = newchunk;
- bmplen = (ULONG)(dr->size / Vcb->superblock.sector_size); + bmplen = (ULONG)(dr->size >> Vcb->sector_shift);
bmparr = ExAllocatePoolWithTag(PagedPool, (ULONG)sector_align(bmplen + 1, sizeof(ULONG)), ALLOC_TAG); if (!bmparr) { @@ -1843,7 +1843,7 @@ static NTSTATUS balance_data_chunk(device_extension* Vcb, chunk* c, bool* change goto end; }
- csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(dr->size * Vcb->csum_size / Vcb->superblock.sector_size), ALLOC_TAG); + csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((dr->size * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG); if (!csum) { ERR("out of memory\n"); ExFreePool(bmparr); @@ -1873,15 +1873,15 @@ static NTSTATUS balance_data_chunk(device_extension* Vcb, chunk* c, bool* change if (tp.item->key.obj_type == TYPE_EXTENT_CSUM) { if (tp.item->key.offset >= dr->address + dr->size) break; - else if (tp.item->size >= Vcb->csum_size && tp.item->key.offset + (tp.item->size * Vcb->superblock.sector_size / Vcb->csum_size) >= dr->address) { + else if (tp.item->size >= Vcb->csum_size && tp.item->key.offset + (((unsigned int)tp.item->size << Vcb->sector_shift) / Vcb->csum_size) >= dr->address) { uint64_t cs = max(dr->address, tp.item->key.offset); - uint64_t ce = min(dr->address + dr->size, tp.item->key.offset + (tp.item->size * Vcb->superblock.sector_size / Vcb->csum_size)); + uint64_t ce = min(dr->address + dr->size, tp.item->key.offset + (((unsigned int)tp.item->size << Vcb->sector_shift) / Vcb->csum_size));
- RtlCopyMemory((uint8_t*)csum + ((cs - dr->address) * Vcb->csum_size / Vcb->superblock.sector_size), - tp.item->data + ((cs - tp.item->key.offset) * Vcb->csum_size / Vcb->superblock.sector_size), - (ULONG)((ce - cs) * Vcb->csum_size / Vcb->superblock.sector_size)); + RtlCopyMemory((uint8_t*)csum + (((cs - dr->address) * Vcb->csum_size) >> Vcb->sector_shift), + tp.item->data + (((cs - tp.item->key.offset) * Vcb->csum_size) >> Vcb->sector_shift), + (ULONG)(((ce - cs) * Vcb->csum_size) >> Vcb->sector_shift));
- RtlClearBits(&bmp, (ULONG)((cs - dr->address) / Vcb->superblock.sector_size), (ULONG)((ce - cs) / Vcb->superblock.sector_size)); + RtlClearBits(&bmp, (ULONG)((cs - dr->address) >> Vcb->sector_shift), (ULONG)((ce - cs) >> Vcb->sector_shift));
if (ce == dr->address + dr->size) break; @@ -1917,12 +1917,12 @@ static NTSTATUS balance_data_chunk(device_extension* Vcb, chunk* c, bool* change do { ULONG rl;
- if (size * Vcb->superblock.sector_size > BALANCE_UNIT) - rl = BALANCE_UNIT / Vcb->superblock.sector_size; + if (size << Vcb->sector_shift > BALANCE_UNIT) + rl = BALANCE_UNIT >> Vcb->sector_shift; else rl = size;
- Status = read_data(Vcb, dr->address + (off * Vcb->superblock.sector_size), rl * Vcb->superblock.sector_size, NULL, false, data, + Status = read_data(Vcb, dr->address + (off << Vcb->sector_shift), rl << Vcb->sector_shift, NULL, false, data, c, NULL, NULL, 0, false, NormalPagePriority); if (!NT_SUCCESS(Status)) { ERR("read_data returned %08lx\n", Status); @@ -1931,7 +1931,7 @@ static NTSTATUS balance_data_chunk(device_extension* Vcb, chunk* c, bool* change goto end; }
- Status = write_data_complete(Vcb, dr->new_address + (off * Vcb->superblock.sector_size), data, rl * Vcb->superblock.sector_size, + Status = write_data_complete(Vcb, dr->new_address + (off << Vcb->sector_shift), data, rl << Vcb->sector_shift, NULL, newchunk, false, 0, NormalPagePriority); if (!NT_SUCCESS(Status)) { ERR("write_data_complete returned %08lx\n", Status); @@ -1945,19 +1945,19 @@ static NTSTATUS balance_data_chunk(device_extension* Vcb, chunk* c, bool* change } while (size > 0); }
- add_checksum_entry(Vcb, dr->new_address + (index * Vcb->superblock.sector_size), runlength, (uint8_t*)csum + (index * Vcb->csum_size), NULL); - add_checksum_entry(Vcb, dr->address + (index * Vcb->superblock.sector_size), runlength, NULL, NULL); + add_checksum_entry(Vcb, dr->new_address + (index << Vcb->sector_shift), runlength, (uint8_t*)csum + (index * Vcb->csum_size), NULL); + add_checksum_entry(Vcb, dr->address + (index << Vcb->sector_shift), runlength, NULL, NULL);
// handle csum run do { ULONG rl;
- if (runlength * Vcb->superblock.sector_size > BALANCE_UNIT) - rl = BALANCE_UNIT / Vcb->superblock.sector_size; + if (runlength << Vcb->sector_shift > BALANCE_UNIT) + rl = BALANCE_UNIT >> Vcb->sector_shift; else rl = runlength;
- Status = read_data(Vcb, dr->address + (index * Vcb->superblock.sector_size), rl * Vcb->superblock.sector_size, + Status = read_data(Vcb, dr->address + (index << Vcb->sector_shift), rl << Vcb->sector_shift, (uint8_t*)csum + (index * Vcb->csum_size), false, data, c, NULL, NULL, 0, false, NormalPagePriority); if (!NT_SUCCESS(Status)) { ERR("read_data returned %08lx\n", Status); @@ -1966,7 +1966,7 @@ static NTSTATUS balance_data_chunk(device_extension* Vcb, chunk* c, bool* change goto end; }
- Status = write_data_complete(Vcb, dr->new_address + (index * Vcb->superblock.sector_size), data, rl * Vcb->superblock.sector_size, + Status = write_data_complete(Vcb, dr->new_address + (index << Vcb->sector_shift), data, rl << Vcb->sector_shift, NULL, newchunk, false, 0, NormalPagePriority); if (!NT_SUCCESS(Status)) { ERR("write_data_complete returned %08lx\n", Status); @@ -1987,26 +1987,26 @@ static NTSTATUS balance_data_chunk(device_extension* Vcb, chunk* c, bool* change ExFreePool(bmparr);
// handle final nocsum run - if (lastoff < dr->size / Vcb->superblock.sector_size) { + if (lastoff < dr->size >> Vcb->sector_shift) { ULONG off = lastoff; - ULONG size = (ULONG)((dr->size / Vcb->superblock.sector_size) - lastoff); + ULONG size = (ULONG)((dr->size >> Vcb->sector_shift) - lastoff);
do { ULONG rl;
- if (size * Vcb->superblock.sector_size > BALANCE_UNIT) - rl = BALANCE_UNIT / Vcb->superblock.sector_size; + if (size << Vcb->sector_shift > BALANCE_UNIT) + rl = BALANCE_UNIT >> Vcb->sector_shift; else rl = size;
- Status = read_data(Vcb, dr->address + (off * Vcb->superblock.sector_size), rl * Vcb->superblock.sector_size, NULL, false, data, + Status = read_data(Vcb, dr->address + (off << Vcb->sector_shift), rl << Vcb->sector_shift, NULL, false, data, c, NULL, NULL, 0, false, NormalPagePriority); if (!NT_SUCCESS(Status)) { ERR("read_data returned %08lx\n", Status); goto end; }
- Status = write_data_complete(Vcb, dr->new_address + (off * Vcb->superblock.sector_size), data, rl * Vcb->superblock.sector_size, + Status = write_data_complete(Vcb, dr->new_address + (off << Vcb->sector_shift), data, rl << Vcb->sector_shift, NULL, newchunk, false, 0, NormalPagePriority); if (!NT_SUCCESS(Status)) { ERR("write_data_complete returned %08lx\n", Status); diff --git a/drivers/filesystems/btrfs/boot.c b/drivers/filesystems/btrfs/boot.c index aa5a4373df2..810717e9da1 100644 --- a/drivers/filesystems/btrfs/boot.c +++ b/drivers/filesystems/btrfs/boot.c @@ -33,10 +33,6 @@ extern PDRIVER_OBJECT drvobj; BTRFS_UUID boot_uuid; // initialized to 0 uint64_t boot_subvol = 0;
-#ifndef _MSC_VER -NTSTATUS RtlUnicodeStringPrintf(PUNICODE_STRING DestinationString, const WCHAR* pszFormat, ...); // not in mingw -#endif - // Not in any headers? Windbg knows about it though. #define DOE_START_PENDING 0x10
@@ -244,6 +240,34 @@ static void get_system_root(system_root* sr) { ExFreePool(target.Buffer); }
+static void append_int_to_us(UNICODE_STRING* us, unsigned int n) { + unsigned int num, digits = 0; + WCHAR* ptr; + + if (n == 0) { + us->Buffer[us->Length / sizeof(WCHAR)] = '0'; + us->Length += sizeof(WCHAR); + return; + } + + num = n; + + while (num > 0) { + digits++; + num /= 10; + } + + ptr = &us->Buffer[(us->Length / sizeof(WCHAR)) + digits - 1]; + + while (n > 0) { + *ptr = L'0' + (n % 10); + ptr--; + n /= 10; + } + + us->Length += digits * sizeof(WCHAR); +} + static void change_symlink(uint32_t disk_num, uint32_t partition_num, BTRFS_UUID* uuid) { NTSTATUS Status; UNICODE_STRING us, us2; @@ -252,15 +276,21 @@ static void change_symlink(uint32_t disk_num, uint32_t partition_num, BTRFS_UUID unsigned int i; #endif
+ static const WCHAR dev_path1[] = L"\Device\Harddisk"; + static const WCHAR dev_path2[] = L"\Partition"; + us.Buffer = symlink; - us.Length = 0; + us.Length = sizeof(dev_path1) - sizeof(WCHAR); us.MaximumLength = sizeof(symlink);
- Status = RtlUnicodeStringPrintf(&us, L"\Device\Harddisk%u\Partition%u", disk_num, partition_num); - if (!NT_SUCCESS(Status)) { - ERR("RtlUnicodeStringPrintf returned %08lx\n", Status); - return; - } + RtlCopyMemory(symlink, dev_path1, sizeof(dev_path1) - sizeof(WCHAR)); + + append_int_to_us(&us, disk_num); + + RtlCopyMemory(&us.Buffer[us.Length / sizeof(WCHAR)], dev_path2, sizeof(dev_path2) - sizeof(WCHAR)); + us.Length += sizeof(dev_path2) - sizeof(WCHAR); + + append_int_to_us(&us, partition_num);
Status = IoDeleteSymbolicLink(&us); if (!NT_SUCCESS(Status)) diff --git a/drivers/filesystems/btrfs/btrfs.c b/drivers/filesystems/btrfs/btrfs.c index 2f3858cd1c6..227e5d438c6 100644 --- a/drivers/filesystems/btrfs/btrfs.c +++ b/drivers/filesystems/btrfs/btrfs.c @@ -48,11 +48,7 @@ #undef INITGUID #endif
-#ifdef _MSC_VER #include <ntstrsafe.h> -#else -NTSTATUS RtlStringCbVPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, va_list argList); // not in mingw -#endif
#define INCOMPAT_SUPPORTED (BTRFS_INCOMPAT_FLAGS_MIXED_BACKREF | BTRFS_INCOMPAT_FLAGS_DEFAULT_SUBVOL | BTRFS_INCOMPAT_FLAGS_MIXED_GROUPS | \ BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO | BTRFS_INCOMPAT_FLAGS_BIG_METADATA | BTRFS_INCOMPAT_FLAGS_RAID56 | \ @@ -113,6 +109,7 @@ bool degraded_wait = true; KEVENT mountmgr_thread_event; bool shutting_down = false; ERESOURCE boot_lock; +bool is_windows_8; extern uint64_t boot_subvol;
#ifdef _DEBUG @@ -597,9 +594,9 @@ static void calculate_total_space(_In_ device_extension* Vcb, _Out_ uint64_t* to dfactor = 1; }
- sectors_used = (Vcb->superblock.bytes_used / Vcb->superblock.sector_size) * nfactor / dfactor; + sectors_used = (Vcb->superblock.bytes_used >> Vcb->sector_shift) * nfactor / dfactor;
- *totalsize = (Vcb->superblock.total_bytes / Vcb->superblock.sector_size) * nfactor / dfactor; + *totalsize = (Vcb->superblock.total_bytes >> Vcb->sector_shift) * nfactor / dfactor; *freespace = sectors_used > *totalsize ? 0 : (*totalsize - sectors_used); }
@@ -1200,7 +1197,6 @@ NTSTATUS create_root(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) devi _Out_ root** rootptr, _In_ bool no_tree, _In_ uint64_t offset, _In_opt_ PIRP Irp) { NTSTATUS Status; root* r; - tree* t = NULL; ROOT_ITEM* ri; traverse_ptr tp;
@@ -1217,29 +1213,10 @@ NTSTATUS create_root(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) devi return STATUS_INSUFFICIENT_RESOURCES; }
- if (!no_tree) { - t = ExAllocatePoolWithTag(PagedPool, sizeof(tree), ALLOC_TAG); - if (!t) { - ERR("out of memory\n"); - ExFreePool(r->nonpaged); - ExFreePool(r); - return STATUS_INSUFFICIENT_RESOURCES; - } - - t->nonpaged = NULL; - - t->is_unique = true; - t->uniqueness_determined = true; - t->buf = NULL; - } - ri = ExAllocatePoolWithTag(PagedPool, sizeof(ROOT_ITEM), ALLOC_TAG); if (!ri) { ERR("out of memory\n");
- if (t) - ExFreePool(t); - ExFreePool(r->nonpaged); ExFreePool(r); return STATUS_INSUFFICIENT_RESOURCES; @@ -1248,7 +1225,7 @@ NTSTATUS create_root(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) devi r->id = id; r->treeholder.address = 0; r->treeholder.generation = Vcb->superblock.generation; - r->treeholder.tree = t; + r->treeholder.tree = NULL; r->lastinode = 0; r->dirty = false; r->received = false; @@ -1272,10 +1249,6 @@ NTSTATUS create_root(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) devi if (!NT_SUCCESS(Status)) { ERR("insert_tree_item returned %08lx\n", Status); ExFreePool(ri); - - if (t) - ExFreePool(t); - ExFreePool(r->nonpaged); ExFreePool(r); return Status; @@ -1286,6 +1259,26 @@ NTSTATUS create_root(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) devi InsertTailList(&Vcb->roots, &r->list_entry);
if (!no_tree) { + tree* t = ExAllocatePoolWithTag(PagedPool, sizeof(tree), ALLOC_TAG); + if (!t) { + ERR("out of memory\n"); + + delete_tree_item(Vcb, &tp); + + ExFreePool(r->nonpaged); + ExFreePool(r); + ExFreePool(ri); + return STATUS_INSUFFICIENT_RESOURCES; + } + + t->nonpaged = NULL; + + t->is_unique = true; + t->uniqueness_determined = true; + t->buf = NULL; + + r->treeholder.tree = t; + RtlZeroMemory(&t->header, sizeof(tree_header)); t->header.fs_uuid = tp.tree->header.fs_uuid; t->header.address = 0; @@ -1493,7 +1486,9 @@ static void send_notification_fcb(_In_ file_ref* fileref, _In_ ULONG filter_matc
// no point looking for hardlinks if st_nlink == 1 if (fileref->fcb->inode_item.st_nlink == 1) { + ExAcquireResourceExclusiveLite(&fcb->Vcb->fileref_lock, true); send_notification_fileref(fileref, filter_match, action, stream); + ExReleaseResourceLite(&fcb->Vcb->fileref_lock); return; }
@@ -2417,7 +2412,6 @@ static NTSTATUS __stdcall drv_cleanup(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIR // messages belonging to other devices.
if (FileObject && FileObject->FsContext) { - LONG oc; ccb* ccb; file_ref* fileref; bool locked = true; @@ -2439,13 +2433,6 @@ static NTSTATUS __stdcall drv_cleanup(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIR if (ccb) FsRtlNotifyCleanup(fcb->Vcb->NotifySync, &fcb->Vcb->DirNotifyList, ccb);
- if (fileref) { - oc = InterlockedDecrement(&fileref->open_count); -#ifdef DEBUG_FCB_REFCOUNTS - ERR("fileref %p: open_count now %i\n", fileref, oc); -#endif - } - if (ccb && ccb->options & FILE_DELETE_ON_CLOSE && fileref) fileref->delete_on_close = true;
@@ -2464,84 +2451,91 @@ static NTSTATUS __stdcall drv_cleanup(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIR // FIXME - flush all of subvol's fcbs }
- if (fileref && (oc == 0 || (fileref->delete_on_close && fileref->posix_delete))) { - if (!fcb->Vcb->removing) { - if (oc == 0 && fileref->fcb->inode_item.st_nlink == 0 && fileref != fcb->Vcb->root_fileref && - fcb != fcb->Vcb->volume_fcb && !fcb->ads) { // last handle closed on POSIX-deleted file - LIST_ENTRY rollback; + if (fileref) { + LONG oc = InterlockedDecrement(&fileref->open_count); +#ifdef DEBUG_FCB_REFCOUNTS + ERR("fileref %p: open_count now %i\n", fileref, oc); +#endif
- InitializeListHead(&rollback); + if (oc == 0 || (fileref->delete_on_close && fileref->posix_delete)) { + if (!fcb->Vcb->removing) { + if (oc == 0 && fileref->fcb->inode_item.st_nlink == 0 && fileref != fcb->Vcb->root_fileref && + fcb != fcb->Vcb->volume_fcb && !fcb->ads) { // last handle closed on POSIX-deleted file + LIST_ENTRY rollback; + + InitializeListHead(&rollback); + + Status = delete_fileref_fcb(fileref, FileObject, Irp, &rollback); + if (!NT_SUCCESS(Status)) { + ERR("delete_fileref_fcb returned %08lx\n", Status); + do_rollback(fcb->Vcb, &rollback); + ExReleaseResourceLite(fileref->fcb->Header.Resource); + ExReleaseResourceLite(&fcb->Vcb->tree_lock); + goto exit; + }
- Status = delete_fileref_fcb(fileref, FileObject, Irp, &rollback); - if (!NT_SUCCESS(Status)) { - ERR("delete_fileref_fcb returned %08lx\n", Status); - do_rollback(fcb->Vcb, &rollback); - ExReleaseResourceLite(fileref->fcb->Header.Resource); - ExReleaseResourceLite(&fcb->Vcb->tree_lock); - goto exit; - } + clear_rollback(&rollback);
- clear_rollback(&rollback); + mark_fcb_dirty(fileref->fcb); + } else if (fileref->delete_on_close && fileref != fcb->Vcb->root_fileref && fcb != fcb->Vcb->volume_fcb) { + LIST_ENTRY rollback;
- mark_fcb_dirty(fileref->fcb); - } else if (fileref->delete_on_close && fileref != fcb->Vcb->root_fileref && fcb != fcb->Vcb->volume_fcb) { - LIST_ENTRY rollback; + InitializeListHead(&rollback);
- InitializeListHead(&rollback); + if (!fileref->fcb->ads || fileref->dc) { + if (fileref->fcb->ads) { + send_notification_fileref(fileref->parent, fcb->type == BTRFS_TYPE_DIRECTORY ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, + FILE_ACTION_REMOVED, &fileref->dc->name); + } else + send_notification_fileref(fileref, fcb->type == BTRFS_TYPE_DIRECTORY ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_REMOVED, NULL); + }
- if (!fileref->fcb->ads || fileref->dc) { - if (fileref->fcb->ads) { - send_notification_fileref(fileref->parent, fcb->type == BTRFS_TYPE_DIRECTORY ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, - FILE_ACTION_REMOVED, &fileref->dc->name); - } else - send_notification_fileref(fileref, fcb->type == BTRFS_TYPE_DIRECTORY ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_REMOVED, NULL); - } + ExReleaseResourceLite(fcb->Header.Resource); + locked = false;
- ExReleaseResourceLite(fcb->Header.Resource); - locked = false; + // fileref_lock needs to be acquired before fcb->Header.Resource + ExAcquireResourceExclusiveLite(&fcb->Vcb->fileref_lock, true);
- // fileref_lock needs to be acquired before fcb->Header.Resource - ExAcquireResourceExclusiveLite(&fcb->Vcb->fileref_lock, true); + Status = delete_fileref(fileref, FileObject, oc > 0 && fileref->posix_delete, Irp, &rollback); + if (!NT_SUCCESS(Status)) { + ERR("delete_fileref returned %08lx\n", Status); + do_rollback(fcb->Vcb, &rollback); + ExReleaseResourceLite(&fcb->Vcb->fileref_lock); + ExReleaseResourceLite(&fcb->Vcb->tree_lock); + goto exit; + }
- Status = delete_fileref(fileref, FileObject, oc > 0 && fileref->posix_delete, Irp, &rollback); - if (!NT_SUCCESS(Status)) { - ERR("delete_fileref returned %08lx\n", Status); - do_rollback(fcb->Vcb, &rollback); ExReleaseResourceLite(&fcb->Vcb->fileref_lock); - ExReleaseResourceLite(&fcb->Vcb->tree_lock); - goto exit; - } - - ExReleaseResourceLite(&fcb->Vcb->fileref_lock);
- clear_rollback(&rollback); - } else if (FileObject->Flags & FO_CACHE_SUPPORTED && FileObject->SectionObjectPointer->DataSectionObject) { - IO_STATUS_BLOCK iosb; + clear_rollback(&rollback); + } else if (FileObject->Flags & FO_CACHE_SUPPORTED && FileObject->SectionObjectPointer->DataSectionObject) { + IO_STATUS_BLOCK iosb;
- if (locked) { - ExReleaseResourceLite(fcb->Header.Resource); - locked = false; - } + if (locked) { + ExReleaseResourceLite(fcb->Header.Resource); + locked = false; + }
- CcFlushCache(FileObject->SectionObjectPointer, NULL, 0, &iosb); + CcFlushCache(FileObject->SectionObjectPointer, NULL, 0, &iosb);
- if (!NT_SUCCESS(iosb.Status)) - ERR("CcFlushCache returned %08lx\n", iosb.Status); + if (!NT_SUCCESS(iosb.Status)) + ERR("CcFlushCache returned %08lx\n", iosb.Status);
- if (!ExIsResourceAcquiredSharedLite(fcb->Header.PagingIoResource)) { - ExAcquireResourceExclusiveLite(fcb->Header.PagingIoResource, true); - ExReleaseResourceLite(fcb->Header.PagingIoResource); - } + if (!ExIsResourceAcquiredSharedLite(fcb->Header.PagingIoResource)) { + ExAcquireResourceExclusiveLite(fcb->Header.PagingIoResource, true); + ExReleaseResourceLite(fcb->Header.PagingIoResource); + }
- CcPurgeCacheSection(FileObject->SectionObjectPointer, NULL, 0, false); + CcPurgeCacheSection(FileObject->SectionObjectPointer, NULL, 0, false);
- TRACE("flushed cache on close (FileObject = %p, fcb = %p, AllocationSize = %I64x, FileSize = %I64x, ValidDataLength = %I64x)\n", - FileObject, fcb, fcb->Header.AllocationSize.QuadPart, fcb->Header.FileSize.QuadPart, fcb->Header.ValidDataLength.QuadPart); + TRACE("flushed cache on close (FileObject = %p, fcb = %p, AllocationSize = %I64x, FileSize = %I64x, ValidDataLength = %I64x)\n", + FileObject, fcb, fcb->Header.AllocationSize.QuadPart, fcb->Header.FileSize.QuadPart, fcb->Header.ValidDataLength.QuadPart); + } } - }
- if (fcb->Vcb && fcb != fcb->Vcb->volume_fcb) - CcUninitializeCacheMap(FileObject, NULL, NULL); + if (fcb->Vcb && fcb != fcb->Vcb->volume_fcb) + CcUninitializeCacheMap(FileObject, NULL, NULL); + } }
if (locked) @@ -2860,6 +2854,8 @@ static NTSTATUS read_superblock(_In_ device_extension* Vcb, _In_ PDEVICE_OBJECT
if (sb->sector_size == 0) WARN("superblock sector size was 0\n"); + else if (sb->sector_size & (sb->sector_size - 1)) + WARN("superblock sector size was not power of 2\n"); else if (sb->node_size < sizeof(tree_header) + sizeof(internal_node) || sb->node_size > 0x10000) WARN("invalid node size %x\n", sb->node_size); else if ((sb->node_size % sb->sector_size) != 0) @@ -3715,7 +3711,7 @@ void protect_superblocks(_Inout_ chunk* c) { // I realize this confuses physical and logical addresses, but this is what btrfs-progs does - // evidently Linux assumes the chunk at 0 is always SINGLE. if (c->offset < superblock_addrs[0]) - space_list_subtract(c, false, c->offset, superblock_addrs[0] - c->offset, NULL); + space_list_subtract(c, c->offset, superblock_addrs[0] - c->offset, NULL);
while (superblock_addrs[i] != 0) { CHUNK_ITEM* ci = c->chunk_item; @@ -3746,7 +3742,7 @@ void protect_superblocks(_Inout_ chunk* c) { TRACE("startoff = %I64x, superblock = %I64x\n", startoff + cis[j].offset, superblock_addrs[i]); #endif
- space_list_subtract(c, false, c->offset + off_start, off_end - off_start, NULL); + space_list_subtract(c, c->offset + off_start, off_end - off_start, NULL); } } } else if (ci->type & BLOCK_FLAG_RAID5) { @@ -3765,7 +3761,7 @@ void protect_superblocks(_Inout_ chunk* c) {
TRACE("cutting out %I64x, size %I64x\n", c->offset + off_start, off_end - off_start);
- space_list_subtract(c, false, c->offset + off_start, off_end - off_start, NULL); + space_list_subtract(c, c->offset + off_start, off_end - off_start, NULL); } } } else if (ci->type & BLOCK_FLAG_RAID6) { @@ -3784,7 +3780,7 @@ void protect_superblocks(_Inout_ chunk* c) {
TRACE("cutting out %I64x, size %I64x\n", c->offset + off_start, off_end - off_start);
- space_list_subtract(c, false, c->offset + off_start, off_end - off_start, NULL); + space_list_subtract(c, c->offset + off_start, off_end - off_start, NULL); } } } else { // SINGLE, DUPLICATE, RAID1, RAID1C3, RAID1C4 @@ -3797,7 +3793,7 @@ void protect_superblocks(_Inout_ chunk* c) { off_start = ((superblock_addrs[i] - cis[j].offset) / c->chunk_item->stripe_length) * c->chunk_item->stripe_length; off_end = sector_align(superblock_addrs[i] - cis[j].offset + sizeof(superblock), c->chunk_item->stripe_length);
- space_list_subtract(c, false, c->offset + off_start, off_end - off_start, NULL); + space_list_subtract(c, c->offset + off_start, off_end - off_start, NULL); } } } @@ -4320,6 +4316,17 @@ static bool still_has_superblock(_In_ PDEVICE_OBJECT device, _In_ PFILE_OBJECT f return true; }
+static void calculate_sector_shift(device_extension* Vcb) { + uint32_t ss = Vcb->superblock.sector_size; + + Vcb->sector_shift = 0; + + while (!(ss & 1)) { + Vcb->sector_shift++; + ss >>= 1; + } +} + static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) { PIO_STACK_LOCATION IrpSp; PDEVICE_OBJECT NewDeviceObject = NULL; @@ -4561,6 +4568,8 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) { if (Vcb->options.readonly) Vcb->readonly = true;
+ calculate_sector_shift(Vcb); + Vcb->superblock.generation++; Vcb->superblock.incompat_flags |= BTRFS_INCOMPAT_FLAGS_MIXED_BACKREF;
@@ -5150,6 +5159,8 @@ static NTSTATUS verify_volume(_In_ PDEVICE_OBJECT devobj) { return STATUS_WRONG_VOLUME; }
+ Status = STATUS_SUCCESS; + InterlockedIncrement(&Vcb->open_files); // so pnp_surprise_removal doesn't uninit the device while we're still using it
le = Vcb->devices.Flink; @@ -5877,17 +5888,24 @@ static void init_serial(bool first_time) {
#if !defined(__REACTOS__) && (defined(_X86_) || defined(_AMD64_)) static void check_cpu() { - unsigned int cpuInfo[4]; bool have_sse42;
#ifndef _MSC_VER - __get_cpuid(1, &cpuInfo[0], &cpuInfo[1], &cpuInfo[2], &cpuInfo[3]); - have_sse42 = cpuInfo[2] & bit_SSE4_2; - have_sse2 = cpuInfo[3] & bit_SSE2; + { + uint32_t eax, ebx, ecx, edx; + + __cpuid(1, eax, ebx, ecx, edx); + have_sse42 = ecx & bit_SSE4_2; + have_sse2 = edx & bit_SSE2; + } #else - __cpuid(cpuInfo, 1); - have_sse42 = cpuInfo[2] & (1 << 20); - have_sse2 = cpuInfo[3] & (1 << 26); + { + unsigned int cpu_info[4]; + + __cpuid(cpu_info, 1); + have_sse42 = cpu_info[2] & (1 << 20); + have_sse2 = cpu_info[3] & (1 << 26); + } #endif
if (have_sse42) { @@ -6091,7 +6109,7 @@ NTSTATUS __stdcall AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT Physica *anp = ')';
Status = IoCreateDevice(drvobj, sizeof(volume_device_extension), &volname, FILE_DEVICE_DISK, - WdmlibRtlIsNtDdiVersionAvailable(NTDDI_WIN8) ? FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL : 0, false, &voldev); + is_windows_8 ? FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL : 0, false, &voldev); if (!NT_SUCCESS(Status)) { ERR("IoCreateDevice returned %08lx\n", Status); goto end2; @@ -6162,6 +6180,17 @@ NTSTATUS __stdcall DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_S HANDLE regh; OBJECT_ATTRIBUTES oa, system_thread_attributes; ULONG dispos; + RTL_OSVERSIONINFOW ver; + + ver.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW); + + Status = RtlGetVersion(&ver); + if (!NT_SUCCESS(Status)) { + ERR("RtlGetVersion returned %08lx\n", Status); + return Status; + } + + is_windows_8 = ver.dwMajorVersion > 6 || (ver.dwMajorVersion == 6 && ver.dwMinorVersion >= 2);
InitializeListHead(&uid_map_list); InitializeListHead(&gid_map_list); @@ -6201,7 +6230,7 @@ NTSTATUS __stdcall DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_S check_cpu(); #endif
- if (WdmlibRtlIsNtDdiVersionAvailable(NTDDI_WIN8)) { + if (ver.dwMajorVersion > 6 || (ver.dwMajorVersion == 6 && ver.dwMinorVersion >= 2)) { // Windows 8 or above UNICODE_STRING name; tPsIsDiskCountersEnabled fPsIsDiskCountersEnabled;
@@ -6241,7 +6270,7 @@ NTSTATUS __stdcall DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_S fFsRtlCheckLockForOplockRequest = NULL; }
- if (WdmlibRtlIsNtDdiVersionAvailable(NTDDI_WIN7)) { + if (ver.dwMajorVersion > 6 || (ver.dwMajorVersion == 6 && ver.dwMinorVersion >= 1)) { // Windows 7 or above UNICODE_STRING name;
RtlInitUnicodeString(&name, L"IoUnregisterPlugPlayNotificationEx"); @@ -6254,7 +6283,7 @@ NTSTATUS __stdcall DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_S fFsRtlAreThereCurrentOrInProgressFileLocks = NULL; }
- if (WdmlibRtlIsNtDdiVersionAvailable(NTDDI_VISTA)) { + if (ver.dwMajorVersion >= 6) { // Windows Vista or above UNICODE_STRING name;
RtlInitUnicodeString(&name, L"FsRtlGetEcpListFromIrp"); diff --git a/drivers/filesystems/btrfs/btrfs.inf b/drivers/filesystems/btrfs/btrfs.inf index 08ef7f9106a..695bc76f0ed 100644 --- a/drivers/filesystems/btrfs/btrfs.inf +++ b/drivers/filesystems/btrfs/btrfs.inf @@ -10,7 +10,7 @@ Signature = "$Windows NT$" Class = Volume ClassGuid = {71a27cdd-812a-11d0-bec7-08002be2092f} Provider = %Me% -DriverVer = 04/10/2020,1.7.2.0 +DriverVer = 05/24/2020,1.7.3.0 CatalogFile = btrfs.cat
[DestinationDirs] diff --git a/drivers/filesystems/btrfs/btrfs.rc b/drivers/filesystems/btrfs/btrfs.rc index 759ad42a474..44920b9aeee 100644 --- a/drivers/filesystems/btrfs/btrfs.rc +++ b/drivers/filesystems/btrfs/btrfs.rc @@ -25,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" @@ -51,8 +51,8 @@ END //
VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,7,2,0 - PRODUCTVERSION 1,7,2,0 + FILEVERSION 1,7,3,0 + PRODUCTVERSION 1,7,3,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -68,12 +68,12 @@ BEGIN BLOCK "080904b0" BEGIN VALUE "FileDescription", "WinBtrfs" - VALUE "FileVersion", "1.7.2" + VALUE "FileVersion", "1.7.3" VALUE "InternalName", "btrfs" VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-20" VALUE "OriginalFilename", "btrfs.sys" VALUE "ProductName", "WinBtrfs" - VALUE "ProductVersion", "1.7.2" + VALUE "ProductVersion", "1.7.3" END END BLOCK "VarFileInfo" diff --git a/drivers/filesystems/btrfs/btrfs_drv.h b/drivers/filesystems/btrfs/btrfs_drv.h index 344223ebb53..8b92af9ea83 100644 --- a/drivers/filesystems/btrfs/btrfs_drv.h +++ b/drivers/filesystems/btrfs/btrfs_drv.h @@ -775,6 +775,7 @@ typedef struct _device_extension { #endif uint64_t devices_loaded; superblock superblock; + unsigned int sector_shift; unsigned int csum_size; bool readonly; bool removing; @@ -1291,25 +1292,30 @@ static const char lxdev[] = "$LXDEV";
// in treefuncs.c 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 find_item_to_level(device_extension* Vcb, root* r, traverse_ptr* tp, const KEY* searchkey, bool ignore, uint8_t level, PIRP Irp); -bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, const traverse_ptr* tp, traverse_ptr* next_tp, bool ignore, PIRP Irp); -bool find_prev_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, const traverse_ptr* tp, traverse_ptr* prev_tp, PIRP Irp); -void free_trees(device_extension* Vcb); + _In_ const KEY* searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1,2,3,4))); +NTSTATUS find_item_to_level(device_extension* Vcb, root* r, traverse_ptr* tp, const KEY* searchkey, bool ignore, + uint8_t level, PIRP Irp) __attribute__((nonnull(1,2,3,4))); +bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, const traverse_ptr* tp, + traverse_ptr* next_tp, bool ignore, PIRP Irp) __attribute__((nonnull(1,2,3))); +bool find_prev_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, const traverse_ptr* tp, + traverse_ptr* prev_tp, PIRP Irp) __attribute__((nonnull(1,2,3))); +void free_trees(device_extension* Vcb) __attribute__((nonnull(1))); NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_ root* r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >= 0, __drv_aliasesMem) void* data, - _In_ uint16_t 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); -void free_tree(tree* t); -NTSTATUS load_tree(device_extension* Vcb, uint64_t addr, uint8_t* 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); -void add_rollback(_In_ LIST_ENTRY* rollback, _In_ enum rollback_type type, _In_ __drv_aliasesMem void* ptr); -NTSTATUS commit_batch_list(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, LIST_ENTRY* batchlist, PIRP Irp); -void clear_batch_list(device_extension* Vcb, LIST_ENTRY* batchlist); -NTSTATUS skip_to_difference(device_extension* Vcb, traverse_ptr* tp, traverse_ptr* tp2, bool* ended1, bool* ended2); + _In_ uint16_t size, _Out_opt_ traverse_ptr* ptp, _In_opt_ PIRP Irp) __attribute__((nonnull(1,2))); +NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, + _Inout_ traverse_ptr* tp) __attribute__((nonnull(1,2))); +void free_tree(tree* t) __attribute__((nonnull(1))); +NTSTATUS load_tree(device_extension* Vcb, uint64_t addr, uint8_t* buf, root* r, tree** pt) __attribute__((nonnull(1,3,4,5))); +NTSTATUS do_load_tree(device_extension* Vcb, tree_holder* th, root* r, tree* t, tree_data* td, PIRP Irp) __attribute__((nonnull(1,2,3))); +void clear_rollback(LIST_ENTRY* rollback) __attribute__((nonnull(1))); +void do_rollback(device_extension* Vcb, LIST_ENTRY* rollback) __attribute__((nonnull(1,2))); +void free_trees_root(device_extension* Vcb, root* r) __attribute__((nonnull(1,2))); +void add_rollback(_In_ LIST_ENTRY* rollback, _In_ enum rollback_type type, _In_ __drv_aliasesMem void* ptr) __attribute__((nonnull(1,3))); +NTSTATUS commit_batch_list(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, + LIST_ENTRY* batchlist, PIRP Irp) __attribute__((nonnull(1,2))); +void clear_batch_list(device_extension* Vcb, LIST_ENTRY* batchlist) __attribute__((nonnull(1,2))); +NTSTATUS skip_to_difference(device_extension* Vcb, traverse_ptr* tp, traverse_ptr* tp2, bool* ended1, bool* ended2) __attribute__((nonnull(1,2,3,4,5)));
// in search.c NTSTATUS remove_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath); @@ -1335,35 +1341,36 @@ void init_cache(); extern CACHE_MANAGER_CALLBACKS cache_callbacks;
// in write.c -NTSTATUS write_file(device_extension* Vcb, PIRP Irp, bool wait, bool deferred_write); +NTSTATUS write_file(device_extension* Vcb, PIRP Irp, bool wait, bool deferred_write) __attribute__((nonnull(1,2))); NTSTATUS write_file2(device_extension* Vcb, PIRP Irp, LARGE_INTEGER offset, void* buf, ULONG* length, bool paging_io, bool no_cache, - bool wait, bool deferred_write, bool write_irp, LIST_ENTRY* rollback); -NTSTATUS truncate_file(fcb* fcb, uint64_t end, PIRP Irp, LIST_ENTRY* rollback); -NTSTATUS extend_file(fcb* fcb, file_ref* fileref, uint64_t end, bool prealloc, PIRP Irp, LIST_ENTRY* rollback); -NTSTATUS excise_extents(device_extension* Vcb, fcb* fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY* rollback); -chunk* get_chunk_from_address(device_extension* Vcb, uint64_t address); -NTSTATUS alloc_chunk(device_extension* Vcb, uint64_t flags, chunk** pc, bool full_size); + bool wait, bool deferred_write, bool write_irp, LIST_ENTRY* rollback) __attribute__((nonnull(1,2,4,5,11))); +NTSTATUS truncate_file(fcb* fcb, uint64_t end, PIRP Irp, LIST_ENTRY* rollback) __attribute__((nonnull(1,4))); +NTSTATUS extend_file(fcb* fcb, file_ref* fileref, uint64_t end, bool prealloc, PIRP Irp, LIST_ENTRY* rollback) __attribute__((nonnull(1,6))); +NTSTATUS excise_extents(device_extension* Vcb, fcb* fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY* rollback) __attribute__((nonnull(1,2,6))); +chunk* get_chunk_from_address(device_extension* Vcb, uint64_t address) __attribute__((nonnull(1))); +NTSTATUS alloc_chunk(device_extension* Vcb, uint64_t flags, chunk** pc, bool full_size) __attribute__((nonnull(1,3))); NTSTATUS write_data(_In_ device_extension* Vcb, _In_ uint64_t address, _In_reads_bytes_(length) void* data, _In_ uint32_t length, _In_ write_data_context* wtc, - _In_opt_ PIRP Irp, _In_opt_ chunk* c, _In_ bool file_write, _In_ uint64_t irp_offset, _In_ ULONG priority); -NTSTATUS write_data_complete(device_extension* Vcb, uint64_t address, void* data, uint32_t length, PIRP Irp, chunk* c, bool file_write, uint64_t irp_offset, ULONG priority); -void free_write_data_stripes(write_data_context* wtc); + _In_opt_ PIRP Irp, _In_opt_ chunk* c, _In_ bool file_write, _In_ uint64_t irp_offset, _In_ ULONG priority) __attribute__((nonnull(1,3,5))); +NTSTATUS write_data_complete(device_extension* Vcb, uint64_t address, void* data, uint32_t length, PIRP Irp, chunk* c, bool file_write, + uint64_t irp_offset, ULONG priority) __attribute__((nonnull(1,3))); +void free_write_data_stripes(write_data_context* wtc) __attribute__((nonnull(1)));
_Dispatch_type_(IRP_MJ_WRITE) _Function_class_(DRIVER_DISPATCH) -NTSTATUS __stdcall drv_write(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); +NTSTATUS __stdcall drv_write(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) __attribute__((nonnull(1,2)));
_Requires_lock_held_(c->lock) _When_(return != 0, _Releases_lock_(c->lock)) -bool insert_extent_chunk(_In_ device_extension* Vcb, _In_ fcb* fcb, _In_ chunk* c, _In_ uint64_t start_data, _In_ uint64_t length, _In_ bool prealloc, _In_opt_ void* data, - _In_opt_ PIRP Irp, _In_ LIST_ENTRY* rollback, _In_ uint8_t compression, _In_ uint64_t decoded_size, _In_ bool file_write, _In_ uint64_t irp_offset); +bool insert_extent_chunk(_In_ device_extension* Vcb, _In_ fcb* fcb, _In_ chunk* c, _In_ uint64_t start_data, _In_ uint64_t length, _In_ bool prealloc, + _In_opt_ void* data, _In_opt_ PIRP Irp, _In_ LIST_ENTRY* rollback, _In_ uint8_t compression, _In_ uint64_t decoded_size, + _In_ bool file_write, _In_ uint64_t irp_offset) __attribute__((nonnull(1,2,3,9)));
-NTSTATUS do_write_file(fcb* fcb, uint64_t start_data, uint64_t end_data, void* data, PIRP Irp, bool file_write, uint32_t irp_offset, LIST_ENTRY* rollback); -bool find_data_address_in_chunk(device_extension* Vcb, chunk* c, uint64_t length, uint64_t* address); -void get_raid56_lock_range(chunk* c, uint64_t address, uint64_t length, uint64_t* lockaddr, uint64_t* locklen); -void add_insert_extent_rollback(LIST_ENTRY* rollback, fcb* fcb, extent* ext); +NTSTATUS do_write_file(fcb* fcb, uint64_t start_data, uint64_t end_data, void* data, PIRP Irp, bool file_write, uint32_t irp_offset, LIST_ENTRY* rollback) __attribute__((nonnull(1, 4))); +bool find_data_address_in_chunk(device_extension* Vcb, chunk* c, uint64_t length, uint64_t* address) __attribute__((nonnull(1, 2, 4))); +void get_raid56_lock_range(chunk* c, uint64_t address, uint64_t length, uint64_t* lockaddr, uint64_t* locklen) __attribute__((nonnull(1,4,5))); NTSTATUS add_extent_to_fcb(_In_ fcb* fcb, _In_ uint64_t offset, _In_reads_bytes_(edsize) EXTENT_DATA* ed, _In_ uint16_t edsize, - _In_ bool unique, _In_opt_ _When_(return >= 0, __drv_aliasesMem) void* csum, _In_ LIST_ENTRY* rollback); -void add_extent(_In_ fcb* fcb, _In_ LIST_ENTRY* prevextle, _In_ __drv_aliasesMem extent* newext); + _In_ bool unique, _In_opt_ _When_(return >= 0, __drv_aliasesMem) void* csum, _In_ LIST_ENTRY* rollback) __attribute__((nonnull(1,3,7))); +void add_extent(_In_ fcb* fcb, _In_ LIST_ENTRY* prevextle, _In_ __drv_aliasesMem extent* newext) __attribute__((nonnull(1,2,3)));
// in dirctrl.c
@@ -1483,8 +1490,8 @@ NTSTATUS __stdcall drv_read(PDEVICE_OBJECT DeviceObject, PIRP Irp); NTSTATUS read_data(_In_ device_extension* Vcb, _In_ uint64_t addr, _In_ uint32_t length, _In_reads_bytes_opt_(length*sizeof(uint32_t)/Vcb->superblock.sector_size) void* csum, _In_ bool is_tree, _Out_writes_bytes_(length) uint8_t* buf, _In_opt_ chunk* c, _Out_opt_ chunk** pc, _In_opt_ PIRP Irp, _In_ uint64_t generation, _In_ bool file_read, _In_ ULONG priority); -NTSTATUS read_file(fcb* fcb, uint8_t* data, uint64_t start, uint64_t length, ULONG* pbr, PIRP Irp); -NTSTATUS read_stream(fcb* fcb, uint8_t* data, uint64_t start, ULONG length, ULONG* pbr); +NTSTATUS read_file(fcb* fcb, uint8_t* data, uint64_t start, uint64_t length, ULONG* pbr, PIRP Irp) __attribute__((nonnull(1, 2))); +NTSTATUS read_stream(fcb* fcb, uint8_t* data, uint64_t start, ULONG length, ULONG* pbr) __attribute__((nonnull(1, 2))); NTSTATUS do_read(PIRP Irp, bool wait, ULONG* bytes_read); NTSTATUS check_csum(device_extension* Vcb, uint8_t* data, uint32_t sectors, void* csum); void raid6_recover2(uint8_t* sectors, uint16_t num_stripes, ULONG sector_size, uint16_t missing1, uint16_t missing2, uint8_t* out); @@ -1511,8 +1518,9 @@ NTSTATUS update_chunk_caches_tree(device_extension* Vcb, PIRP Irp); NTSTATUS add_space_entry(LIST_ENTRY* list, LIST_ENTRY* list_size, uint64_t offset, uint64_t size); void space_list_add(chunk* c, uint64_t address, uint64_t length, LIST_ENTRY* rollback); void space_list_add2(LIST_ENTRY* list, LIST_ENTRY* list_size, uint64_t address, uint64_t length, chunk* c, LIST_ENTRY* rollback); -void space_list_subtract(chunk* c, bool deleting, uint64_t address, uint64_t length, LIST_ENTRY* rollback); +void space_list_subtract(chunk* c, uint64_t address, uint64_t length, LIST_ENTRY* rollback); void space_list_subtract2(LIST_ENTRY* list, LIST_ENTRY* list_size, uint64_t address, uint64_t length, chunk* c, LIST_ENTRY* rollback); +void space_list_merge(LIST_ENTRY* spacelist, LIST_ENTRY* spacelist_size, LIST_ENTRY* deleting); NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c, bool load_only, PIRP Irp);
// in extent-tree.c diff --git a/drivers/filesystems/btrfs/compress.c b/drivers/filesystems/btrfs/compress.c index ee9b89a74cb..786bca33254 100644 --- a/drivers/filesystems/btrfs/compress.c +++ b/drivers/filesystems/btrfs/compress.c @@ -993,7 +993,7 @@ NTSTATUS write_compressed(fcb* fcb, uint64_t start_data, uint64_t end_data, void else if (type == BTRFS_COMPRESSION_ZSTD) fcb->Vcb->superblock.incompat_flags |= BTRFS_INCOMPAT_FLAGS_COMPRESS_ZSTD;
- if ((parts[i].outlen % fcb->Vcb->superblock.sector_size) != 0) { + if ((parts[i].outlen & (fcb->Vcb->superblock.sector_size - 1)) != 0) { unsigned int newlen = (unsigned int)sector_align(parts[i].outlen, fcb->Vcb->superblock.sector_size);
RtlZeroMemory(parts[i].buf + parts[i].outlen, newlen - parts[i].outlen); @@ -1083,7 +1083,7 @@ NTSTATUS write_compressed(fcb* fcb, uint64_t start_data, uint64_t end_data, void if (find_data_address_in_chunk(fcb->Vcb, c2, buflen, &address)) { c = c2; c->used += buflen; - space_list_subtract(c, false, address, buflen, rollback); + space_list_subtract(c, address, buflen, rollback); release_chunk_lock(c2, fcb->Vcb); break; } @@ -1118,7 +1118,7 @@ NTSTATUS write_compressed(fcb* fcb, uint64_t start_data, uint64_t end_data, void if (find_data_address_in_chunk(fcb->Vcb, c2, buflen, &address)) { c = c2; c->used += buflen; - space_list_subtract(c, false, address, buflen, rollback); + space_list_subtract(c, address, buflen, rollback); }
release_chunk_lock(c2, fcb->Vcb); @@ -1149,7 +1149,7 @@ NTSTATUS write_compressed(fcb* fcb, uint64_t start_data, uint64_t end_data, void // calculate csums if necessary
if (!(fcb->inode_item.flags & BTRFS_INODE_NODATASUM)) { - unsigned int sl = buflen / fcb->Vcb->superblock.sector_size; + unsigned int sl = buflen >> fcb->Vcb->sector_shift;
csum = ExAllocatePoolWithTag(PagedPool, sl * fcb->Vcb->csum_size, ALLOC_TAG); if (!csum) { @@ -1198,7 +1198,7 @@ NTSTATUS write_compressed(fcb* fcb, uint64_t start_data, uint64_t end_data, void ed2->num_bytes = parts[i].inlen;
if (csum) { - csum2 = ExAllocatePoolWithTag(PagedPool, parts[i].outlen * fcb->Vcb->csum_size / fcb->Vcb->superblock.sector_size, ALLOC_TAG); + csum2 = ExAllocatePoolWithTag(PagedPool, (parts[i].outlen * fcb->Vcb->csum_size) >> fcb->Vcb->sector_shift, ALLOC_TAG); if (!csum2) { ERR("out of memory\n"); ExFreePool(ed); @@ -1207,8 +1207,8 @@ NTSTATUS write_compressed(fcb* fcb, uint64_t start_data, uint64_t end_data, void return STATUS_INSUFFICIENT_RESOURCES; }
- RtlCopyMemory(csum2, (uint8_t*)csum + ((extaddr - address) * fcb->Vcb->csum_size / fcb->Vcb->superblock.sector_size), - parts[i].outlen * fcb->Vcb->csum_size / fcb->Vcb->superblock.sector_size); + RtlCopyMemory(csum2, (uint8_t*)csum + (((extaddr - address) * fcb->Vcb->csum_size) >> fcb->Vcb->sector_shift), + (parts[i].outlen * fcb->Vcb->csum_size) >> fcb->Vcb->sector_shift); } else csum2 = NULL;
diff --git a/drivers/filesystems/btrfs/create.c b/drivers/filesystems/btrfs/create.c index 082159053bb..0dee14dc7fd 100644 --- a/drivers/filesystems/btrfs/create.c +++ b/drivers/filesystems/btrfs/create.c @@ -43,6 +43,10 @@ static const WCHAR root_dir_utf16[] = L"$Root"; #define ATOMIC_CREATE_ECP_IN_OP_FLAG_CASE_SENSITIVE_FLAGS_SPECIFIED 1 #define ATOMIC_CREATE_ECP_OUT_OP_FLAG_CASE_SENSITIVE_FLAGS_SET 1
+#ifndef SL_IGNORE_READONLY_ATTRIBUTE +#define SL_IGNORE_READONLY_ATTRIBUTE 0x40 // introduced in Windows 10, not in mingw +#endif + typedef struct _FILE_TIMESTAMPS { LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; @@ -469,10 +473,10 @@ NTSTATUS load_csum(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb if (start < tp.item->key.offset) j = 0; else - j = ((start - tp.item->key.offset) / Vcb->superblock.sector_size) + i; + j = ((start - tp.item->key.offset) >> Vcb->sector_shift) + i;
- if (j * Vcb->csum_size > tp.item->size || tp.item->key.offset > start + (i * Vcb->superblock.sector_size)) { - ERR("checksum not found for %I64x\n", start + (i * Vcb->superblock.sector_size)); + if (j * Vcb->csum_size > tp.item->size || tp.item->key.offset > start + (i << Vcb->sector_shift)) { + ERR("checksum not found for %I64x\n", start + (i << Vcb->sector_shift)); return STATUS_INTERNAL_ERROR; }
@@ -2046,23 +2050,29 @@ static NTSTATUS file_create_parse_ea(fcb* fcb, FILE_FULL_EA_INFORMATION* ea) { goto end; }
- RtlCopyMemory(&val, item->value.Buffer, sizeof(uint32_t)); - - if (fcb->type != BTRFS_TYPE_DIRECTORY) - allowed |= __S_IFIFO | __S_IFCHR | __S_IFBLK | __S_IFSOCK; + val = *(uint32_t*)item->value.Buffer;
fcb->inode_item.st_mode &= ~allowed; fcb->inode_item.st_mode |= val & allowed;
if (fcb->type != BTRFS_TYPE_DIRECTORY) { - if ((fcb->inode_item.st_mode & __S_IFCHR) == __S_IFCHR) + if (__S_ISTYPE(val, __S_IFCHR)) { fcb->type = BTRFS_TYPE_CHARDEV; - else if ((fcb->inode_item.st_mode & __S_IFBLK) == __S_IFBLK) + fcb->inode_item.st_mode &= ~__S_IFMT; + fcb->inode_item.st_mode |= __S_IFCHR; + } else if (__S_ISTYPE(val, __S_IFBLK)) { fcb->type = BTRFS_TYPE_BLOCKDEV; - else if ((fcb->inode_item.st_mode & __S_IFIFO) == __S_IFIFO) + fcb->inode_item.st_mode &= ~__S_IFMT; + fcb->inode_item.st_mode |= __S_IFBLK; + } else if (__S_ISTYPE(val, __S_IFIFO)) { fcb->type = BTRFS_TYPE_FIFO; - else if ((fcb->inode_item.st_mode & __S_IFSOCK) == __S_IFSOCK) + fcb->inode_item.st_mode &= ~__S_IFMT; + fcb->inode_item.st_mode |= __S_IFIFO; + } else if (__S_ISTYPE(val, __S_IFSOCK)) { fcb->type = BTRFS_TYPE_SOCKET; + fcb->inode_item.st_mode &= ~__S_IFMT; + fcb->inode_item.st_mode |= __S_IFSOCK; + } }
RemoveEntryList(&item->list_entry); @@ -2718,7 +2728,7 @@ static NTSTATUS create_stream(_Requires_lock_held_(_Curr_->tree_lock) _Requires_ return STATUS_INVALID_PARAMETER; }
- if (parfileref->fcb->atts & FILE_ATTRIBUTE_READONLY) { + if (parfileref->fcb->atts & FILE_ATTRIBUTE_READONLY && !(IrpSp->Flags & SL_IGNORE_READONLY_ATTRIBUTE)) { free_fileref(parfileref); return STATUS_ACCESS_DENIED; } @@ -3011,8 +3021,10 @@ 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) + if (options & FILE_DELETE_ON_CLOSE && IrpSp->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_READONLY && + !(IrpSp->Flags & SL_IGNORE_READONLY_ATTRIBUTE)) { return STATUS_CANNOT_DELETE; + }
if (fFsRtlGetEcpListFromIrp && fFsRtlGetNextExtraCreateParameter) { if (NT_SUCCESS(fFsRtlGetEcpListFromIrp(Irp, &ecp_list)) && ecp_list) { @@ -3228,6 +3240,7 @@ static NTSTATUS file_create(PIRP Irp, _Requires_lock_held_(_Curr_->tree_lock) _R if (acec->ReparseBufferLength > sizeof(uint32_t) && *(uint32_t*)acec->ReparseBuffer == IO_REPARSE_TAG_SYMLINK) { fileref->fcb->inode_item.st_mode &= ~(__S_IFIFO | __S_IFCHR | __S_IFBLK | __S_IFSOCK); fileref->fcb->type = BTRFS_TYPE_FILE; + fileref->fcb->atts &= ~FILE_ATTRIBUTE_DIRECTORY; }
if (fileref->fcb->type == BTRFS_TYPE_SOCKET || fileref->fcb->type == BTRFS_TYPE_FIFO || @@ -3545,7 +3558,7 @@ static void fcb_load_csums(_Requires_lock_held_(_Curr_->tree_lock) device_extens EXTENT_DATA2* ed2 = (EXTENT_DATA2*)&ext->extent_data.data[0]; uint64_t len;
- len = (ext->extent_data.compression == BTRFS_COMPRESSION_NONE ? ed2->num_bytes : ed2->size) / Vcb->superblock.sector_size; + len = (ext->extent_data.compression == BTRFS_COMPRESSION_NONE ? ed2->num_bytes : ed2->size) >> Vcb->sector_shift;
ext->csum = ExAllocatePoolWithTag(NonPagedPool, (ULONG)(len * Vcb->csum_size), ALLOC_TAG); if (!ext->csum) { @@ -3633,8 +3646,9 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO sf = sf->parent; }
- 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; + readonly = (!fileref->fcb->ads && fileref->fcb->atts & FILE_ATTRIBUTE_READONLY && !(IrpSp->Flags & SL_IGNORE_READONLY_ATTRIBUTE)) || + (fileref->fcb->ads && fileref->parent->fcb->atts & FILE_ATTRIBUTE_READONLY && !(IrpSp->Flags & SL_IGNORE_READONLY_ATTRIBUTE)) || + 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)) { free_fileref(fileref); @@ -4847,6 +4861,11 @@ NTSTATUS __stdcall drv_create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { flags &= ~SL_STOP_ON_SYMLINK; }
+ if (flags & SL_IGNORE_READONLY_ATTRIBUTE) { + TRACE("SL_IGNORE_READONLY_ATTRIBUTE\n"); + flags &= ~SL_IGNORE_READONLY_ATTRIBUTE; + } + if (flags) WARN("unknown flags: %x\n", flags); } else { diff --git a/drivers/filesystems/btrfs/extent-tree.c b/drivers/filesystems/btrfs/extent-tree.c index 1e03af7bdbc..9df2a33a685 100644 --- a/drivers/filesystems/btrfs/extent-tree.c +++ b/drivers/filesystems/btrfs/extent-tree.c @@ -1024,7 +1024,7 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, uint64_t address, uint6 }
if (!superseded) - add_checksum_entry(Vcb, address, (ULONG)(size / Vcb->superblock.sector_size), NULL, Irp); + add_checksum_entry(Vcb, address, (ULONG)(size >> Vcb->sector_shift), NULL, Irp);
return STATUS_SUCCESS; } @@ -1090,7 +1090,7 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, uint64_t address, uint6 }
if (!superseded) - add_checksum_entry(Vcb, address, (ULONG)(size / Vcb->superblock.sector_size), NULL, Irp); + add_checksum_entry(Vcb, address, (ULONG)(size >> Vcb->sector_shift), NULL, Irp);
return STATUS_SUCCESS; } @@ -1296,7 +1296,7 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, uint64_t address, uint6 }
if (!superseded) - add_checksum_entry(Vcb, address, (ULONG)(size / Vcb->superblock.sector_size), NULL, Irp); + add_checksum_entry(Vcb, address, (ULONG)(size >> Vcb->sector_shift), NULL, Irp);
return STATUS_SUCCESS; } @@ -1379,7 +1379,7 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, uint64_t address, uint6 }
if (!superseded) - add_checksum_entry(Vcb, address, (ULONG)(size / Vcb->superblock.sector_size), NULL, Irp); + add_checksum_entry(Vcb, address, (ULONG)(size >> Vcb->sector_shift), NULL, Irp);
return STATUS_SUCCESS; } @@ -1505,7 +1505,7 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, uint64_t address, uint6 }
if (!superseded) - add_checksum_entry(Vcb, address, (ULONG)(size / Vcb->superblock.sector_size), NULL, Irp); + add_checksum_entry(Vcb, address, (ULONG)(size >> Vcb->sector_shift), NULL, Irp);
return STATUS_SUCCESS; } diff --git a/drivers/filesystems/btrfs/fileinfo.c b/drivers/filesystems/btrfs/fileinfo.c index 70ce2061c81..81c0f06816a 100644 --- a/drivers/filesystems/btrfs/fileinfo.c +++ b/drivers/filesystems/btrfs/fileinfo.c @@ -566,7 +566,7 @@ static NTSTATUS duplicate_fcb(fcb* oldfcb, fcb** pfcb) { else len = (ULONG)ed2->size;
- len = len * sizeof(uint32_t) / Vcb->superblock.sector_size; + len = (len * sizeof(uint32_t)) >> Vcb->sector_shift;
ext2->csum = ExAllocatePoolWithTag(PagedPool, len, ALLOC_TAG); if (!ext2->csum) { @@ -1719,7 +1719,7 @@ static NTSTATUS rename_stream_to_file(device_extension* Vcb, file_ref* fileref, }
ExFreePool(ed); - } else if (adsdata.Length % Vcb->superblock.sector_size) { + } else if (adsdata.Length & (Vcb->superblock.sector_size - 1)) { char* newbuf = ExAllocatePoolWithTag(PagedPool, (uint16_t)sector_align(adsdata.Length, Vcb->superblock.sector_size), ALLOC_TAG); if (!newbuf) { ERR("out of memory\n"); diff --git a/drivers/filesystems/btrfs/flushthread.c b/drivers/filesystems/btrfs/flushthread.c index 42d45332e94..6495859ab63 100644 --- a/drivers/filesystems/btrfs/flushthread.c +++ b/drivers/filesystems/btrfs/flushthread.c @@ -164,33 +164,33 @@ static void add_trim_entry(device* dev, uint64_t address, uint64_t size) { }
static void clean_space_cache_chunk(device_extension* Vcb, chunk* c) { + LIST_ENTRY* le; ULONG type;
- if (Vcb->trim && !Vcb->options.no_trim) { - if (c->chunk_item->type & BLOCK_FLAG_DUPLICATE) - type = BLOCK_FLAG_DUPLICATE; - else if (c->chunk_item->type & BLOCK_FLAG_RAID0) - type = BLOCK_FLAG_RAID0; - else if (c->chunk_item->type & BLOCK_FLAG_RAID1) - type = BLOCK_FLAG_DUPLICATE; - else if (c->chunk_item->type & BLOCK_FLAG_RAID10) - type = BLOCK_FLAG_RAID10; - else if (c->chunk_item->type & BLOCK_FLAG_RAID5) - type = BLOCK_FLAG_RAID5; - else if (c->chunk_item->type & BLOCK_FLAG_RAID6) - type = BLOCK_FLAG_RAID6; - else if (c->chunk_item->type & BLOCK_FLAG_RAID1C3) - type = BLOCK_FLAG_DUPLICATE; - else if (c->chunk_item->type & BLOCK_FLAG_RAID1C4) - type = BLOCK_FLAG_DUPLICATE; - else // SINGLE - type = BLOCK_FLAG_DUPLICATE; - } + if (c->chunk_item->type & BLOCK_FLAG_DUPLICATE) + type = BLOCK_FLAG_DUPLICATE; + else if (c->chunk_item->type & BLOCK_FLAG_RAID0) + type = BLOCK_FLAG_RAID0; + else if (c->chunk_item->type & BLOCK_FLAG_RAID1) + type = BLOCK_FLAG_DUPLICATE; + else if (c->chunk_item->type & BLOCK_FLAG_RAID10) + type = BLOCK_FLAG_RAID10; + else if (c->chunk_item->type & BLOCK_FLAG_RAID5) + type = BLOCK_FLAG_RAID5; + else if (c->chunk_item->type & BLOCK_FLAG_RAID6) + type = BLOCK_FLAG_RAID6; + else if (c->chunk_item->type & BLOCK_FLAG_RAID1C3) + type = BLOCK_FLAG_DUPLICATE; + else if (c->chunk_item->type & BLOCK_FLAG_RAID1C4) + type = BLOCK_FLAG_DUPLICATE; + else // SINGLE + type = BLOCK_FLAG_DUPLICATE;
- while (!IsListEmpty(&c->deleting)) { - space* s = CONTAINING_RECORD(c->deleting.Flink, space, list_entry); + le = c->deleting.Flink; + while (le != &c->deleting) { + space* s = CONTAINING_RECORD(le, space, list_entry);
- if (Vcb->trim && !Vcb->options.no_trim && (!Vcb->options.no_barrier || !(c->chunk_item->type & BLOCK_FLAG_METADATA))) { + if (!Vcb->options.no_barrier || !(c->chunk_item->type & BLOCK_FLAG_METADATA)) { CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&c->chunk_item[1];
if (type == BLOCK_FLAG_DUPLICATE) { @@ -270,8 +270,7 @@ static void clean_space_cache_chunk(device_extension* Vcb, chunk* c) { // FIXME - RAID5(?), RAID6(?) }
- RemoveEntryList(&s->list_entry); - ExFreePool(s); + le = le->Flink; } }
@@ -414,8 +413,18 @@ static void clean_space_cache(device_extension* Vcb) { if (c->space_changed) { acquire_chunk_lock(c, Vcb);
- if (c->space_changed) - clean_space_cache_chunk(Vcb, c); + if (c->space_changed) { + if (Vcb->trim && !Vcb->options.no_trim) + clean_space_cache_chunk(Vcb, c); + + space_list_merge(&c->space, &c->space_size, &c->deleting); + + while (!IsListEmpty(&c->deleting)) { + space* s = CONTAINING_RECORD(RemoveHeadList(&c->deleting), space, list_entry); + + ExFreePool(s); + } + }
c->space_changed = false;
@@ -725,7 +734,7 @@ static bool insert_tree_extent_skinny(device_extension* Vcb, uint8_t level, uint
acquire_chunk_lock(c, Vcb);
- space_list_subtract(c, false, address, Vcb->superblock.node_size, rollback); + space_list_subtract(c, address, Vcb->superblock.node_size, rollback);
release_chunk_lock(c, Vcb);
@@ -857,7 +866,7 @@ static bool insert_tree_extent(device_extension* Vcb, uint8_t level, uint64_t ro
acquire_chunk_lock(c, Vcb);
- space_list_subtract(c, false, address, Vcb->superblock.node_size, rollback); + space_list_subtract(c, address, Vcb->superblock.node_size, rollback);
release_chunk_lock(c, Vcb);
@@ -2639,7 +2648,7 @@ void add_checksum_entry(device_extension* Vcb, uint64_t address, ULONG length, v length2 -= il;
if (length2 > 0) { - off += il * Vcb->superblock.sector_size; + off += (uint64_t)il << Vcb->sector_shift; data = (uint8_t*)data + (il * Vcb->csum_size); } } while (length2 > 0); @@ -2653,14 +2662,14 @@ void add_checksum_entry(device_extension* Vcb, uint64_t address, ULONG length, v
// FIXME - check entry is TYPE_EXTENT_CSUM?
- if (tp.item->key.offset < address && tp.item->key.offset + (tp.item->size * Vcb->superblock.sector_size / Vcb->csum_size) >= address) + if (tp.item->key.offset < address && tp.item->key.offset + (((uint64_t)tp.item->size << Vcb->sector_shift) / Vcb->csum_size) >= address) startaddr = tp.item->key.offset; else startaddr = address;
searchkey.obj_id = EXTENT_CSUM_ID; searchkey.obj_type = TYPE_EXTENT_CSUM; - searchkey.offset = address + (length * Vcb->superblock.sector_size); + searchkey.offset = address + (length << Vcb->sector_shift);
Status = find_item(Vcb, Vcb->checksum_root, &tp, &searchkey, false, Irp); if (!NT_SUCCESS(Status)) { @@ -2670,16 +2679,16 @@ void add_checksum_entry(device_extension* Vcb, uint64_t address, ULONG length, v
tplen = tp.item->size / Vcb->csum_size;
- if (tp.item->key.offset + (tplen * Vcb->superblock.sector_size) >= address + (length * Vcb->superblock.sector_size)) - endaddr = tp.item->key.offset + (tplen * Vcb->superblock.sector_size); + if (tp.item->key.offset + (tplen << Vcb->sector_shift) >= address + (length << Vcb->sector_shift)) + endaddr = tp.item->key.offset + (tplen << Vcb->sector_shift); else - endaddr = address + (length * Vcb->superblock.sector_size); + endaddr = address + (length << Vcb->sector_shift);
TRACE("cs starts at %I64x (%lx sectors)\n", address, length); TRACE("startaddr = %I64x\n", startaddr); TRACE("endaddr = %I64x\n", endaddr);
- len = (ULONG)((endaddr - startaddr) / Vcb->superblock.sector_size); + len = (ULONG)((endaddr - startaddr) >> Vcb->sector_shift);
checksums = ExAllocatePoolWithTag(PagedPool, Vcb->csum_size * len, ALLOC_TAG); if (!checksums) { @@ -2714,11 +2723,11 @@ void add_checksum_entry(device_extension* Vcb, uint64_t address, ULONG length, v while (tp.item->key.offset < endaddr) { if (tp.item->key.offset >= startaddr) { if (tp.item->size > 0) { - ULONG itemlen = (ULONG)min((len - (tp.item->key.offset - startaddr) / Vcb->superblock.sector_size) * Vcb->csum_size, tp.item->size); + ULONG itemlen = (ULONG)min((len - ((tp.item->key.offset - startaddr) >> Vcb->sector_shift)) * Vcb->csum_size, tp.item->size);
- RtlCopyMemory((uint8_t*)checksums + ((tp.item->key.offset - startaddr) * Vcb->csum_size / Vcb->superblock.sector_size), + RtlCopyMemory((uint8_t*)checksums + (((tp.item->key.offset - startaddr) * Vcb->csum_size) >> Vcb->sector_shift), tp.item->data, itemlen); - RtlClearBits(&bmp, (ULONG)((tp.item->key.offset - startaddr) / Vcb->superblock.sector_size), itemlen / Vcb->csum_size); + RtlClearBits(&bmp, (ULONG)((tp.item->key.offset - startaddr) >> Vcb->sector_shift), itemlen / Vcb->csum_size); }
Status = delete_tree_item(Vcb, &tp); @@ -2737,11 +2746,11 @@ void add_checksum_entry(device_extension* Vcb, uint64_t address, ULONG length, v }
if (!csum) { // deleted - RtlSetBits(&bmp, (ULONG)((address - startaddr) / Vcb->superblock.sector_size), length); + RtlSetBits(&bmp, (ULONG)((address - startaddr) >> Vcb->sector_shift), length); } else { - RtlCopyMemory((uint8_t*)checksums + ((address - startaddr) * Vcb->csum_size / Vcb->superblock.sector_size), + RtlCopyMemory((uint8_t*)checksums + (((address - startaddr) * Vcb->csum_size) >> Vcb->sector_shift), csum, length * Vcb->csum_size); - RtlClearBits(&bmp, (ULONG)((address - startaddr) / Vcb->superblock.sector_size), length); + RtlClearBits(&bmp, (ULONG)((address - startaddr) >> Vcb->sector_shift), length); }
runlength = RtlFindFirstRunClear(&bmp, &index); @@ -2777,7 +2786,7 @@ void add_checksum_entry(device_extension* Vcb, uint64_t address, ULONG length, v
RtlCopyMemory(data, (uint8_t*)checksums + (Vcb->csum_size * index), Vcb->csum_size * rl);
- off = startaddr + UInt32x32To64(index, Vcb->superblock.sector_size); + off = startaddr + ((uint64_t)index << Vcb->sector_shift);
Status = insert_tree_item(Vcb, Vcb->checksum_root, EXTENT_CSUM_ID, TYPE_EXTENT_CSUM, off, data, Vcb->csum_size * rl, NULL, Irp); if (!NT_SUCCESS(Status)) { @@ -3661,7 +3670,7 @@ static NTSTATUS update_tree_extents_recursive(device_extension* Vcb, tree* t, PI
static NTSTATUS do_splits(device_extension* Vcb, PIRP Irp, LIST_ENTRY* rollback) { ULONG level, max_level; - uint32_t min_size; + uint32_t min_size, min_size_fst; bool empty, done_deletions = false; NTSTATUS Status; tree* t; @@ -3770,6 +3779,7 @@ static NTSTATUS do_splits(device_extension* Vcb, PIRP Irp, LIST_ENTRY* rollback) }
min_size = (Vcb->superblock.node_size - sizeof(tree_header)) / 2; + min_size_fst = (Vcb->superblock.node_size - sizeof(tree_header)) / 4;
for (level = 0; level <= max_level; level++) { LIST_ENTRY* le; @@ -3779,8 +3789,9 @@ static NTSTATUS do_splits(device_extension* Vcb, PIRP Irp, LIST_ENTRY* rollback) while (le != &Vcb->trees) { t = CONTAINING_RECORD(le, tree, list_entry);
- if (t->write && t->header.level == level && t->header.num_items > 0 && t->parent && t->size < min_size && - t->root->id != BTRFS_ROOT_FREE_SPACE && is_tree_unique(Vcb, t, Irp)) { + if (t->write && t->header.level == level && t->header.num_items > 0 && t->parent && + ((t->size < min_size && t->root->id != BTRFS_ROOT_FREE_SPACE) || (t->size < min_size_fst && t->root->id == BTRFS_ROOT_FREE_SPACE)) && + is_tree_unique(Vcb, t, Irp)) { bool done;
do { @@ -4649,7 +4660,7 @@ cont: }
if (!(fcb->inode_item.flags & BTRFS_INODE_NODATASUM)) - add_checksum_entry(fcb->Vcb, er->address, (ULONG)(er->skip_start / fcb->Vcb->superblock.sector_size), NULL, NULL); + add_checksum_entry(fcb->Vcb, er->address, (ULONG)(er->skip_start >> fcb->Vcb->sector_shift), NULL, NULL);
acquire_chunk_lock(er->chunk, fcb->Vcb);
@@ -4703,7 +4714,7 @@ cont: }
if (!(fcb->inode_item.flags & BTRFS_INODE_NODATASUM)) - add_checksum_entry(fcb->Vcb, er->address + er->length - er->skip_end, (ULONG)(er->skip_end / fcb->Vcb->superblock.sector_size), NULL, NULL); + add_checksum_entry(fcb->Vcb, er->address + er->length - er->skip_end, (ULONG)(er->skip_end >> fcb->Vcb->sector_shift), NULL, NULL);
acquire_chunk_lock(er->chunk, fcb->Vcb);
@@ -4902,9 +4913,9 @@ NTSTATUS flush_fcb(fcb* fcb, bool cache, LIST_ENTRY* batchlist, PIRP Irp) {
if (ed2->size > 0) { // not sparse if (ext->extent_data.compression == BTRFS_COMPRESSION_NONE) - add_checksum_entry(fcb->Vcb, ed2->address + ed2->offset, (ULONG)(ed2->num_bytes / fcb->Vcb->superblock.sector_size), ext->csum, Irp); + add_checksum_entry(fcb->Vcb, ed2->address + ed2->offset, (ULONG)(ed2->num_bytes >> fcb->Vcb->sector_shift), ext->csum, Irp); else - add_checksum_entry(fcb->Vcb, ed2->address, (ULONG)(ed2->size / fcb->Vcb->superblock.sector_size), ext->csum, Irp); + add_checksum_entry(fcb->Vcb, ed2->address, (ULONG)(ed2->size >> fcb->Vcb->sector_shift), ext->csum, Irp); } }
@@ -4933,7 +4944,7 @@ NTSTATUS flush_fcb(fcb* fcb, bool cache, LIST_ENTRY* batchlist, PIRP Irp) { chunk* c;
if (ext->extent_data.compression == BTRFS_COMPRESSION_NONE && ext->csum) { - ULONG len = (ULONG)((ed2->num_bytes + ned2->num_bytes) / fcb->Vcb->superblock.sector_size); + ULONG len = (ULONG)((ed2->num_bytes + ned2->num_bytes) >> fcb->Vcb->sector_shift); void* csum;
csum = ExAllocatePoolWithTag(NonPagedPool, len * fcb->Vcb->csum_size, ALLOC_TAG); @@ -4943,9 +4954,9 @@ NTSTATUS flush_fcb(fcb* fcb, bool cache, LIST_ENTRY* batchlist, PIRP Irp) { goto end; }
- RtlCopyMemory(csum, ext->csum, (ULONG)(ed2->num_bytes * fcb->Vcb->csum_size / fcb->Vcb->superblock.sector_size)); - RtlCopyMemory((uint8_t*)csum + (ed2->num_bytes * fcb->Vcb->csum_size / fcb->Vcb->superblock.sector_size), nextext->csum, - (ULONG)(ned2->num_bytes * fcb->Vcb->csum_size / fcb->Vcb->superblock.sector_size)); + RtlCopyMemory(csum, ext->csum, (ULONG)((ed2->num_bytes * fcb->Vcb->csum_size) >> fcb->Vcb->sector_shift)); + RtlCopyMemory((uint8_t*)csum + ((ed2->num_bytes * fcb->Vcb->csum_size) >> fcb->Vcb->sector_shift), nextext->csum, + (ULONG)((ned2->num_bytes * fcb->Vcb->csum_size) >> fcb->Vcb->sector_shift));
ExFreePool(ext->csum); ext->csum = csum; @@ -5738,7 +5749,7 @@ static NTSTATUS drop_chunk(device_extension* Vcb, chunk* c, LIST_ENTRY* batchlis
static NTSTATUS partial_stripe_read(device_extension* Vcb, chunk* c, partial_stripe* ps, uint64_t startoff, uint16_t parity, ULONG offset, ULONG len) { NTSTATUS Status; - ULONG sl = (ULONG)(c->chunk_item->stripe_length / Vcb->superblock.sector_size); + ULONG sl = (ULONG)(c->chunk_item->stripe_length >> Vcb->sector_shift); CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&c->chunk_item[1];
while (len > 0) { @@ -5748,8 +5759,8 @@ static NTSTATUS partial_stripe_read(device_extension* Vcb, chunk* c, partial_str stripe = (parity + (offset / sl) + 1) % c->chunk_item->num_stripes;
if (c->devices[stripe]->devobj) { - Status = sync_read_phys(c->devices[stripe]->devobj, c->devices[stripe]->fileobj, cis[stripe].offset + startoff + ((offset % sl) * Vcb->superblock.sector_size), - readlen * Vcb->superblock.sector_size, ps->data + (offset * Vcb->superblock.sector_size), false); + Status = sync_read_phys(c->devices[stripe]->devobj, c->devices[stripe]->fileobj, cis[stripe].offset + startoff + ((offset % sl) << Vcb->sector_shift), + readlen << Vcb->sector_shift, ps->data + (offset << Vcb->sector_shift), false); if (!NT_SUCCESS(Status)) { ERR("sync_read_phys returned %08lx\n", Status); return Status; @@ -5758,7 +5769,7 @@ static NTSTATUS partial_stripe_read(device_extension* Vcb, chunk* c, partial_str uint16_t i; uint8_t* scratch;
- scratch = ExAllocatePoolWithTag(NonPagedPool, readlen * Vcb->superblock.sector_size, ALLOC_TAG); + scratch = ExAllocatePoolWithTag(NonPagedPool, readlen << Vcb->sector_shift, ALLOC_TAG); if (!scratch) { ERR("out of memory\n"); return STATUS_INSUFFICIENT_RESOURCES; @@ -5772,23 +5783,23 @@ static NTSTATUS partial_stripe_read(device_extension* Vcb, chunk* c, partial_str }
if (i == 0 || (stripe == 0 && i == 1)) { - Status = sync_read_phys(c->devices[i]->devobj, c->devices[i]->fileobj, cis[i].offset + startoff + ((offset % sl) * Vcb->superblock.sector_size), - readlen * Vcb->superblock.sector_size, ps->data + (offset * Vcb->superblock.sector_size), false); + Status = sync_read_phys(c->devices[i]->devobj, c->devices[i]->fileobj, cis[i].offset + startoff + ((offset % sl) << Vcb->sector_shift), + readlen << Vcb->sector_shift, ps->data + (offset << Vcb->sector_shift), false); if (!NT_SUCCESS(Status)) { ERR("sync_read_phys returned %08lx\n", Status); ExFreePool(scratch); return Status; } } else { - Status = sync_read_phys(c->devices[i]->devobj, c->devices[i]->fileobj, cis[i].offset + startoff + ((offset % sl) * Vcb->superblock.sector_size), - readlen * Vcb->superblock.sector_size, scratch, false); + Status = sync_read_phys(c->devices[i]->devobj, c->devices[i]->fileobj, cis[i].offset + startoff + ((offset % sl) << Vcb->sector_shift), + readlen << Vcb->sector_shift, scratch, false); if (!NT_SUCCESS(Status)) { ERR("sync_read_phys returned %08lx\n", Status); ExFreePool(scratch); return Status; }
- do_xor(ps->data + (offset * Vcb->superblock.sector_size), scratch, readlen * Vcb->superblock.sector_size); + do_xor(ps->data + (offset << Vcb->sector_shift), scratch, readlen << Vcb->sector_shift); } } } @@ -5798,7 +5809,7 @@ static NTSTATUS partial_stripe_read(device_extension* Vcb, chunk* c, partial_str uint8_t* scratch; uint16_t k, i, logstripe, error_stripe, num_errors = 0;
- scratch = ExAllocatePoolWithTag(NonPagedPool, (c->chunk_item->num_stripes + 2) * readlen * Vcb->superblock.sector_size, ALLOC_TAG); + scratch = ExAllocatePoolWithTag(NonPagedPool, (c->chunk_item->num_stripes + 2) * readlen << Vcb->sector_shift, ALLOC_TAG); if (!scratch) { ERR("out of memory\n"); return STATUS_INSUFFICIENT_RESOURCES; @@ -5808,8 +5819,8 @@ static NTSTATUS partial_stripe_read(device_extension* Vcb, chunk* c, partial_str for (k = 0; k < c->chunk_item->num_stripes; k++) { if (i != stripe) { if (c->devices[i]->devobj) { - Status = sync_read_phys(c->devices[i]->devobj, c->devices[i]->fileobj, cis[i].offset + startoff + ((offset % sl) * Vcb->superblock.sector_size), - readlen * Vcb->superblock.sector_size, scratch + (k * readlen * Vcb->superblock.sector_size), false); + Status = sync_read_phys(c->devices[i]->devobj, c->devices[i]->fileobj, cis[i].offset + startoff + ((offset % sl) << Vcb->sector_shift), + readlen << Vcb->sector_shift, scratch + (k * readlen << Vcb->sector_shift), false); if (!NT_SUCCESS(Status)) { ERR("sync_read_phys returned %08lx\n", Status); num_errors++; @@ -5834,20 +5845,20 @@ static NTSTATUS partial_stripe_read(device_extension* Vcb, chunk* c, partial_str for (k = 0; k < c->chunk_item->num_stripes - 1; k++) { if (k != logstripe) { if (k == 0 || (k == 1 && logstripe == 0)) { - RtlCopyMemory(ps->data + (offset * Vcb->superblock.sector_size), scratch + (k * readlen * Vcb->superblock.sector_size), - readlen * Vcb->superblock.sector_size); + RtlCopyMemory(ps->data + (offset << Vcb->sector_shift), scratch + (k * readlen << Vcb->sector_shift), + readlen << Vcb->sector_shift); } else { - do_xor(ps->data + (offset * Vcb->superblock.sector_size), scratch + (k * readlen * Vcb->superblock.sector_size), - readlen * Vcb->superblock.sector_size); + do_xor(ps->data + (offset << Vcb->sector_shift), scratch + (k * readlen << Vcb->sector_shift), + readlen << Vcb->sector_shift); } } } } else { - raid6_recover2(scratch, c->chunk_item->num_stripes, readlen * Vcb->superblock.sector_size, logstripe, - error_stripe, scratch + (c->chunk_item->num_stripes * readlen * Vcb->superblock.sector_size)); + raid6_recover2(scratch, c->chunk_item->num_stripes, readlen << Vcb->sector_shift, logstripe, + error_stripe, scratch + (c->chunk_item->num_stripes * readlen << Vcb->sector_shift));
- RtlCopyMemory(ps->data + (offset * Vcb->superblock.sector_size), scratch + (c->chunk_item->num_stripes * readlen * Vcb->superblock.sector_size), - readlen * Vcb->superblock.sector_size); + RtlCopyMemory(ps->data + (offset << Vcb->sector_shift), scratch + (c->chunk_item->num_stripes * readlen << Vcb->sector_shift), + readlen << Vcb->sector_shift); }
ExFreePool(scratch); @@ -5907,8 +5918,8 @@ NTSTATUS flush_partial_stripe(device_extension* Vcb, chunk* c, partial_stripe* p runlength = RtlFindNextForwardRunClear(&ps->bmp, index + runlength, &index); }
- if (last1 < ps_length / Vcb->superblock.sector_size) { - Status = partial_stripe_read(Vcb, c, ps, startoff, parity2, last1, (ULONG)((ps_length / Vcb->superblock.sector_size) - last1)); + if (last1 < ps_length >> Vcb->sector_shift) { + Status = partial_stripe_read(Vcb, c, ps, startoff, parity2, last1, (ULONG)((ps_length >> Vcb->sector_shift) - last1)); if (!NT_SUCCESS(Status)) { ERR("partial_stripe_read returned %08lx\n", Status); return Status; diff --git a/drivers/filesystems/btrfs/free-space.c b/drivers/filesystems/btrfs/free-space.c index 62a912f2a6c..c2fc0c1ae12 100644 --- a/drivers/filesystems/btrfs/free-space.c +++ b/drivers/filesystems/btrfs/free-space.c @@ -285,8 +285,8 @@ static void load_free_space_bitmap(device_extension* Vcb, chunk* c, uint64_t off break; }
- addr = offset + (index * Vcb->superblock.sector_size); - length = Vcb->superblock.sector_size * runlength; + addr = offset + (index << Vcb->sector_shift); + length = runlength << Vcb->sector_shift;
add_space_entry(&c->space, &c->space_size, addr, length); index += runlength; @@ -470,7 +470,7 @@ NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c, bool load uint64_t inode, *generation; uint8_t* data; NTSTATUS Status; - uint32_t *checksums, crc32, i, num_sectors, num_valid_sectors, size; + uint32_t *checksums, crc32, num_sectors, num_valid_sectors, size; FREE_SPACE_ENTRY* fse; uint64_t num_entries, num_bitmaps, extent_length, bmpnum, off, total_space = 0, superblock_size; LIST_ENTRY *le, rollback; @@ -563,7 +563,7 @@ NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c, bool load if (size > c->cache->inode_item.st_size) RtlZeroMemory(&data[c->cache->inode_item.st_size], (ULONG)(size - c->cache->inode_item.st_size));
- num_sectors = size / Vcb->superblock.sector_size; + num_sectors = size >> Vcb->sector_shift;
generation = (uint64_t*)(data + (num_sectors * sizeof(uint32_t)));
@@ -574,7 +574,7 @@ NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c, bool load
extent_length = (num_sectors * sizeof(uint32_t)) + sizeof(uint64_t) + (num_entries * sizeof(FREE_SPACE_ENTRY));
- num_valid_sectors = (ULONG)((sector_align(extent_length, Vcb->superblock.sector_size) / Vcb->superblock.sector_size) + num_bitmaps); + num_valid_sectors = (ULONG)((sector_align(extent_length, Vcb->superblock.sector_size) >> Vcb->sector_shift) + num_bitmaps);
if (num_valid_sectors > num_sectors) { ERR("free space cache for %I64x was %u sectors, expected at least %u\n", c->offset, num_sectors, num_valid_sectors); @@ -583,13 +583,13 @@ NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c, bool load
checksums = (uint32_t*)data;
- for (i = 0; i < num_valid_sectors; i++) { - if (i * Vcb->superblock.sector_size > sizeof(uint32_t) * num_sectors) - crc32 = ~calc_crc32c(0xffffffff, &data[i * Vcb->superblock.sector_size], Vcb->superblock.sector_size); - else if ((i + 1) * Vcb->superblock.sector_size < sizeof(uint32_t) * num_sectors) + for (uint32_t i = 0; i < num_valid_sectors; i++) { + if (i << Vcb->sector_shift > sizeof(uint32_t) * num_sectors) + crc32 = ~calc_crc32c(0xffffffff, &data[i << Vcb->sector_shift], Vcb->superblock.sector_size); + else if ((i + 1) << Vcb->sector_shift < sizeof(uint32_t) * num_sectors) crc32 = 0; // FIXME - test this else - crc32 = ~calc_crc32c(0xffffffff, &data[sizeof(uint32_t) * num_sectors], ((i + 1) * Vcb->superblock.sector_size) - (sizeof(uint32_t) * num_sectors)); + crc32 = ~calc_crc32c(0xffffffff, &data[sizeof(uint32_t) * num_sectors], ((i + 1) << Vcb->sector_shift) - (sizeof(uint32_t) * num_sectors));
if (crc32 != checksums[i]) { WARN("checksum %u was %08x, expected %08x\n", i, crc32, checksums[i]); @@ -600,8 +600,8 @@ NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c, bool load off = (sizeof(uint32_t) * num_sectors) + sizeof(uint64_t);
bmpnum = 0; - for (i = 0; i < num_entries; i++) { - if ((off + sizeof(FREE_SPACE_ENTRY)) / Vcb->superblock.sector_size != off / Vcb->superblock.sector_size) + for (uint32_t i = 0; i < num_entries; i++) { + if ((off + sizeof(FREE_SPACE_ENTRY)) >> Vcb->sector_shift != off >> Vcb->sector_shift) off = sector_align(off, Vcb->superblock.sector_size);
fse = (FREE_SPACE_ENTRY*)&data[off]; @@ -623,18 +623,18 @@ NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c, bool load }
if (num_bitmaps > 0) { - bmpnum = sector_align(off, Vcb->superblock.sector_size) / Vcb->superblock.sector_size; + bmpnum = sector_align(off, Vcb->superblock.sector_size) >> Vcb->sector_shift; off = (sizeof(uint32_t) * num_sectors) + sizeof(uint64_t);
- for (i = 0; i < num_entries; i++) { - if ((off + sizeof(FREE_SPACE_ENTRY)) / Vcb->superblock.sector_size != off / Vcb->superblock.sector_size) + for (uint32_t i = 0; i < num_entries; i++) { + if ((off + sizeof(FREE_SPACE_ENTRY)) >> Vcb->sector_shift != off >> Vcb->sector_shift) off = sector_align(off, Vcb->superblock.sector_size);
fse = (FREE_SPACE_ENTRY*)&data[off];
if (fse->type == FREE_SPACE_BITMAP) { // FIXME - make sure we don't overflow the buffer here - load_free_space_bitmap(Vcb, c, fse->offset, &data[bmpnum * Vcb->superblock.sector_size], &total_space); + load_free_space_bitmap(Vcb, c, fse->offset, &data[bmpnum << Vcb->sector_shift], &total_space); bmpnum++; }
@@ -778,7 +778,7 @@ static NTSTATUS load_stored_free_space_tree(device_extension* Vcb, chunk* c, PIR uint64_t lastoff; ULONG bmpl;
- explen = (ULONG)(tp.item->key.offset / (Vcb->superblock.sector_size * 8)); + explen = (ULONG)(tp.item->key.offset >> Vcb->sector_shift) / 8;
if (tp.item->size < explen) { WARN("(%I64x,%x,%I64x) was %u bytes, expected %lu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, explen); @@ -803,7 +803,7 @@ static NTSTATUS load_stored_free_space_tree(device_extension* Vcb, chunk* c, PIR // We copy the bitmap because it supposedly has to be ULONG-aligned RtlCopyMemory(bmparr, tp.item->data, tp.item->size);
- bmpl = (ULONG)tp.item->key.offset / Vcb->superblock.sector_size; + bmpl = (ULONG)tp.item->key.offset >> Vcb->sector_shift;
RtlInitializeBitMap(&bmp, bmparr, bmpl);
@@ -824,8 +824,8 @@ static NTSTATUS load_stored_free_space_tree(device_extension* Vcb, chunk* c, PIR break; }
- runstart = tp.item->key.obj_id + (index * Vcb->superblock.sector_size); - runend = runstart + (runlength * Vcb->superblock.sector_size); + runstart = tp.item->key.obj_id + (index << Vcb->sector_shift); + runend = runstart + (runlength << Vcb->sector_shift);
if (runstart > lastoff) { Status = add_space_entry(&c->space, &c->space_size, lastoff, runstart - lastoff); @@ -1077,20 +1077,20 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, bool* chan
new_cache_size = sizeof(uint64_t) + (num_entries * sizeof(FREE_SPACE_ENTRY));
- num_sectors = (uint32_t)sector_align(new_cache_size, Vcb->superblock.sector_size) / Vcb->superblock.sector_size; + num_sectors = (uint32_t)sector_align(new_cache_size, Vcb->superblock.sector_size) >> Vcb->sector_shift; num_sectors = (uint32_t)sector_align(num_sectors, CACHE_INCREMENTS);
// adjust for padding // FIXME - there must be a more efficient way of doing this new_cache_size = sizeof(uint64_t) + (sizeof(uint32_t) * num_sectors); for (i = 0; i < num_entries; i++) { - if ((new_cache_size / Vcb->superblock.sector_size) != ((new_cache_size + sizeof(FREE_SPACE_ENTRY)) / Vcb->superblock.sector_size)) + if ((new_cache_size >> Vcb->sector_shift) != ((new_cache_size + sizeof(FREE_SPACE_ENTRY)) >> Vcb->sector_shift)) new_cache_size = sector_align(new_cache_size, Vcb->superblock.sector_size);
new_cache_size += sizeof(FREE_SPACE_ENTRY); }
- new_cache_size = sector_align(new_cache_size, CACHE_INCREMENTS * Vcb->superblock.sector_size); + new_cache_size = sector_align(new_cache_size, CACHE_INCREMENTS << Vcb->sector_shift);
TRACE("chunk %I64x: cache_size = %I64x, new_cache_size = %I64x\n", c->offset, c->cache ? c->cache->inode_item.st_size : 0, new_cache_size);
@@ -1651,19 +1651,41 @@ void space_list_add2(LIST_ENTRY* list, LIST_ENTRY* list_size, uint64_t address, add_rollback_space(rollback, true, list, list_size, address, length, c); }
-static void space_list_merge(LIST_ENTRY* spacelist, LIST_ENTRY* spacelist_size, LIST_ENTRY* deleting) { - LIST_ENTRY* le; +void space_list_merge(LIST_ENTRY* spacelist, LIST_ENTRY* spacelist_size, LIST_ENTRY* deleting) { + LIST_ENTRY* le = deleting->Flink;
- if (!IsListEmpty(deleting)) { - le = deleting->Flink; - while (le != deleting) { - space* s = CONTAINING_RECORD(le, space, list_entry); + while (le != deleting) { + space* s = CONTAINING_RECORD(le, space, list_entry);
- space_list_add2(spacelist, spacelist_size, s->address, s->size, NULL, NULL); + space_list_add2(spacelist, spacelist_size, s->address, s->size, NULL, NULL);
- le = le->Flink; + le = le->Flink; + } +} + +static NTSTATUS copy_space_list(LIST_ENTRY* old_list, LIST_ENTRY* new_list) { + LIST_ENTRY* le; + + le = old_list->Flink; + while (le != old_list) { + space* s = CONTAINING_RECORD(le, space, list_entry); + space* s2; + + s2 = ExAllocatePoolWithTag(PagedPool, sizeof(space), ALLOC_TAG); + if (!s2) { + ERR("out of memory\n"); + return STATUS_INSUFFICIENT_RESOURCES; } + + s2->address = s->address; + s2->size = s->size; + + InsertTailList(new_list, &s2->list_entry); + + le = le->Flink; } + + return STATUS_SUCCESS; }
static NTSTATUS update_chunk_cache(device_extension* Vcb, chunk* c, BTRFS_TIME* now, LIST_ENTRY* batchlist, PIRP Irp, LIST_ENTRY* rollback) { @@ -1673,10 +1695,8 @@ static NTSTATUS update_chunk_cache(device_extension* Vcb, chunk* c, BTRFS_TIME* FREE_SPACE_ITEM* fsi; void* data; uint64_t num_entries, *cachegen, off; - uint32_t *checksums, num_sectors, i; - LIST_ENTRY* le; - - space_list_merge(&c->space, &c->space_size, &c->deleting); + uint32_t *checksums, num_sectors; + LIST_ENTRY space_list, deleting;
data = ExAllocatePoolWithTag(NonPagedPool, (ULONG)c->cache->inode_item.st_size, ALLOC_TAG); if (!data) { @@ -1686,17 +1706,38 @@ static NTSTATUS update_chunk_cache(device_extension* Vcb, chunk* c, BTRFS_TIME*
RtlZeroMemory(data, (ULONG)c->cache->inode_item.st_size);
+ InitializeListHead(&space_list); + InitializeListHead(&deleting); + + Status = copy_space_list(&c->space, &space_list); + if (!NT_SUCCESS(Status)) { + ERR("copy_space_list returned %08lx\n", Status); + goto end; + } + + Status = copy_space_list(&c->deleting, &deleting); + if (!NT_SUCCESS(Status)) { + ERR("copy_space_list returned %08lx\n", Status); + + while (!IsListEmpty(&space_list)) { + ExFreePool(CONTAINING_RECORD(RemoveHeadList(&space_list), space, list_entry)); + } + + goto end; + } + + space_list_merge(&space_list, NULL, &deleting); + num_entries = 0; - num_sectors = (uint32_t)(c->cache->inode_item.st_size / Vcb->superblock.sector_size); + num_sectors = (uint32_t)(c->cache->inode_item.st_size >> Vcb->sector_shift); off = (sizeof(uint32_t) * num_sectors) + sizeof(uint64_t);
- le = c->space.Flink; - while (le != &c->space) { + while (!IsListEmpty(&space_list)) { FREE_SPACE_ENTRY* fse;
- space* s = CONTAINING_RECORD(le, space, list_entry); + space* s = CONTAINING_RECORD(RemoveHeadList(&space_list), space, list_entry);
- if ((off + sizeof(FREE_SPACE_ENTRY)) / Vcb->superblock.sector_size != off / Vcb->superblock.sector_size) + if ((off + sizeof(FREE_SPACE_ENTRY)) >> Vcb->sector_shift != off >> Vcb->sector_shift) off = sector_align(off, Vcb->superblock.sector_size);
fse = (FREE_SPACE_ENTRY*)((uint8_t*)data + off); @@ -1707,8 +1748,6 @@ static NTSTATUS update_chunk_cache(device_extension* Vcb, chunk* c, BTRFS_TIME* num_entries++;
off += sizeof(FREE_SPACE_ENTRY); - - le = le->Flink; }
// update INODE_ITEM @@ -1765,13 +1804,13 @@ static NTSTATUS update_chunk_cache(device_extension* Vcb, chunk* c, BTRFS_TIME*
// FIXME - if we know sector is fully zeroed, use cached checksum
- for (i = 0; i < num_sectors; i++) { - if (i * Vcb->superblock.sector_size > sizeof(uint32_t) * num_sectors) - checksums[i] = ~calc_crc32c(0xffffffff, (uint8_t*)data + (i * Vcb->superblock.sector_size), Vcb->superblock.sector_size); - else if ((i + 1) * Vcb->superblock.sector_size < sizeof(uint32_t) * num_sectors) + for (uint32_t i = 0; i < num_sectors; i++) { + if (i << Vcb->sector_shift > sizeof(uint32_t) * num_sectors) + checksums[i] = ~calc_crc32c(0xffffffff, (uint8_t*)data + (i << Vcb->sector_shift), Vcb->superblock.sector_size); + else if ((i + 1) << Vcb->sector_shift < sizeof(uint32_t) * num_sectors) checksums[i] = 0; // FIXME - test this else - checksums[i] = ~calc_crc32c(0xffffffff, (uint8_t*)data + (sizeof(uint32_t) * num_sectors), ((i + 1) * Vcb->superblock.sector_size) - (sizeof(uint32_t) * num_sectors)); + checksums[i] = ~calc_crc32c(0xffffffff, (uint8_t*)data + (sizeof(uint32_t) * num_sectors), ((i + 1) << Vcb->sector_shift) - (sizeof(uint32_t) * num_sectors)); }
// write cache @@ -1792,52 +1831,206 @@ end: return Status; }
-static NTSTATUS update_chunk_cache_tree(device_extension* Vcb, chunk* c, LIST_ENTRY* batchlist) { +static NTSTATUS update_chunk_cache_tree(device_extension* Vcb, chunk* c, PIRP Irp) { NTSTATUS Status; - LIST_ENTRY* le; + LIST_ENTRY space_list; FREE_SPACE_INFO* fsi; + KEY searchkey; + traverse_ptr tp; + uint32_t fsi_count = 0;
- fsi = ExAllocatePoolWithTag(PagedPool, sizeof(FREE_SPACE_INFO), ALLOC_TAG); - if (!fsi) { - ERR("out of memory\n"); - return STATUS_INSUFFICIENT_RESOURCES; + InitializeListHead(&space_list); + + Status = copy_space_list(&c->space, &space_list); + if (!NT_SUCCESS(Status)) { + ERR("copy_space_list returned %08lx\n", Status); + return Status; }
- space_list_merge(&c->space, &c->space_size, &c->deleting); + space_list_merge(&space_list, NULL, &c->deleting);
- fsi->count = 0; - fsi->flags = 0; + searchkey.obj_id = c->offset; + searchkey.obj_type = TYPE_FREE_SPACE_EXTENT; + searchkey.offset = 0xffffffffffffffff;
- le = c->space.Flink; - while (le != &c->space) { - space* s = CONTAINING_RECORD(le, space, list_entry); + Status = find_item(Vcb, Vcb->space_root, &tp, &searchkey, false, Irp); + if (Status == STATUS_NOT_FOUND) + goto after_tree_walk; + else if (!NT_SUCCESS(Status)) { + ERR("find_item returned %08lx\n", Status); + + while (!IsListEmpty(&space_list)) { + ExFreePool(CONTAINING_RECORD(RemoveHeadList(&space_list), space, list_entry)); + }
- fsi->count++; + return Status; + }
- Status = insert_tree_item_batch(batchlist, Vcb, Vcb->space_root, s->address, TYPE_FREE_SPACE_EXTENT, s->size, - NULL, 0, Batch_Insert); + while (!IsListEmpty(&space_list) && tp.item->key.obj_id < c->offset + c->chunk_item->size) { + traverse_ptr next_tp; + + if (tp.item->key.obj_type == TYPE_FREE_SPACE_EXTENT) { + space* s = CONTAINING_RECORD(space_list.Flink, space, list_entry); + + if (s->address < tp.item->key.obj_id || (s->address == tp.item->key.obj_id && s->size < tp.item->key.offset)) { + // add entry + + Status = insert_tree_item(Vcb, Vcb->space_root, s->address, TYPE_FREE_SPACE_EXTENT, s->size, NULL, 0, + NULL, Irp); + if (!NT_SUCCESS(Status)) { + ERR("insert_tree_item returned %08lx\n", Status); + + while (!IsListEmpty(&space_list)) { + ExFreePool(CONTAINING_RECORD(RemoveHeadList(&space_list), space, list_entry)); + } + + return Status; + } + + fsi_count++; + + ExFreePool(s); + RemoveHeadList(&space_list); + continue; + } else if (s->address == tp.item->key.obj_id && s->size == tp.item->key.offset) { + // unchanged entry + + fsi_count++; + + ExFreePool(s); + RemoveHeadList(&space_list); + } else { + // remove entry + + Status = delete_tree_item(Vcb, &tp); + if (!NT_SUCCESS(Status)) { + ERR("delete_tree_item returned %08lx\n", Status); + + while (!IsListEmpty(&space_list)) { + ExFreePool(CONTAINING_RECORD(RemoveHeadList(&space_list), space, list_entry)); + } + + return Status; + } + } + } else if (tp.item->key.obj_type == TYPE_FREE_SPACE_BITMAP) { + Status = delete_tree_item(Vcb, &tp); + if (!NT_SUCCESS(Status)) { + ERR("delete_tree_item returned %08lx\n", Status); + + while (!IsListEmpty(&space_list)) { + ExFreePool(CONTAINING_RECORD(RemoveHeadList(&space_list), space, list_entry)); + } + + return Status; + } + } + + if (!find_next_item(Vcb, &tp, &next_tp, false, Irp)) + goto after_tree_walk; + + tp = next_tp; + } + + // after loop, delete remaining tree items for this chunk + + while (tp.item->key.obj_id < c->offset + c->chunk_item->size) { + traverse_ptr next_tp; + + if (tp.item->key.obj_type == TYPE_FREE_SPACE_EXTENT || tp.item->key.obj_type == TYPE_FREE_SPACE_BITMAP) { + Status = delete_tree_item(Vcb, &tp); + if (!NT_SUCCESS(Status)) { + ERR("delete_tree_item returned %08lx\n", Status); + return Status; + } + } + + if (!find_next_item(Vcb, &tp, &next_tp, false, NULL)) + break; + + tp = next_tp; + } + +after_tree_walk: + // after loop, insert remaining space_list entries + + while (!IsListEmpty(&space_list)) { + space* s = CONTAINING_RECORD(RemoveHeadList(&space_list), space, list_entry); + + Status = insert_tree_item(Vcb, Vcb->space_root, s->address, TYPE_FREE_SPACE_EXTENT, s->size, NULL, 0, + NULL, Irp); if (!NT_SUCCESS(Status)) { - ERR("insert_tree_item_batch returned %08lx\n", Status); - ExFreePool(fsi); + ERR("insert_tree_item returned %08lx\n", Status); + + while (!IsListEmpty(&space_list)) { + ExFreePool(CONTAINING_RECORD(RemoveHeadList(&space_list), space, list_entry)); + } + return Status; }
- le = le->Flink; + fsi_count++; + + ExFreePool(s); }
- Status = insert_tree_item_batch(batchlist, Vcb, Vcb->space_root, c->offset, TYPE_FREE_SPACE_INFO, c->chunk_item->size, - NULL, 0, Batch_DeleteFreeSpace); - if (!NT_SUCCESS(Status)) { - ERR("insert_tree_item_batch returned %08lx\n", Status); - ExFreePool(fsi); + // change TYPE_FREE_SPACE_INFO in place if present, and insert otherwise + + searchkey.obj_id = c->offset; + searchkey.obj_type = TYPE_FREE_SPACE_INFO; + searchkey.offset = c->chunk_item->size; + + Status = find_item(Vcb, Vcb->space_root, &tp, &searchkey, false, Irp); + if (!NT_SUCCESS(Status) && Status != STATUS_NOT_FOUND) { + ERR("find_item returned %08lx\n", Status); return Status; }
- Status = insert_tree_item_batch(batchlist, Vcb, Vcb->space_root, c->offset, TYPE_FREE_SPACE_INFO, c->chunk_item->size, - fsi, sizeof(FREE_SPACE_INFO), Batch_Insert); + if (NT_SUCCESS(Status) && !keycmp(tp.item->key, searchkey)) { + if (tp.item->size == sizeof(FREE_SPACE_INFO)) { + tree* t; + + // change in place if possible + + fsi = (FREE_SPACE_INFO*)tp.item->data; + + fsi->count = fsi_count; + fsi->flags = 0; + + tp.tree->write = true; + + t = tp.tree; + while (t) { + if (t->paritem && t->paritem->ignore) { + t->paritem->ignore = false; + t->parent->header.num_items++; + t->parent->size += sizeof(internal_node); + } + + t->header.generation = Vcb->superblock.generation; + t = t->parent; + } + + return STATUS_SUCCESS; + } else + delete_tree_item(Vcb, &tp); + } + + // insert FREE_SPACE_INFO + + fsi = ExAllocatePoolWithTag(PagedPool, sizeof(FREE_SPACE_INFO), ALLOC_TAG); + if (!fsi) { + ERR("out of memory\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + fsi->count = fsi_count; + fsi->flags = 0; + + Status = insert_tree_item(Vcb, Vcb->space_root, c->offset, TYPE_FREE_SPACE_INFO, c->chunk_item->size, fsi, sizeof(fsi), + NULL, Irp); if (!NT_SUCCESS(Status)) { - ERR("insert_tree_item_batch returned %08lx\n", Status); - ExFreePool(fsi); + ERR("insert_tree_item returned %08lx\n", Status); return Status; }
@@ -1915,14 +2108,12 @@ NTSTATUS update_chunk_caches(device_extension* Vcb, PIRP Irp, LIST_ENTRY* rollba }
NTSTATUS update_chunk_caches_tree(device_extension* Vcb, PIRP Irp) { - LIST_ENTRY *le, batchlist; + LIST_ENTRY *le; NTSTATUS Status; chunk* c;
Vcb->superblock.compat_ro_flags |= BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE_VALID;
- InitializeListHead(&batchlist); - ExAcquireResourceSharedLite(&Vcb->chunk_lock, true);
le = Vcb->chunks.Flink; @@ -1931,13 +2122,12 @@ NTSTATUS update_chunk_caches_tree(device_extension* Vcb, PIRP Irp) {
if (c->space_changed) { acquire_chunk_lock(c, Vcb); - Status = update_chunk_cache_tree(Vcb, c, &batchlist); + Status = update_chunk_cache_tree(Vcb, c, Irp); release_chunk_lock(c, Vcb);
if (!NT_SUCCESS(Status)) { ERR("update_chunk_cache_tree(%I64x) returned %08lx\n", c->offset, Status); ExReleaseResourceLite(&Vcb->chunk_lock); - clear_batch_list(Vcb, &batchlist); return Status; } } @@ -1947,12 +2137,6 @@ NTSTATUS update_chunk_caches_tree(device_extension* Vcb, PIRP Irp) {
ExReleaseResourceLite(&Vcb->chunk_lock);
- Status = commit_batch_list(Vcb, &batchlist, Irp); - if (!NT_SUCCESS(Status)) { - ERR("commit_batch_list returned %08lx\n", Status); - return Status; - } - return STATUS_SUCCESS; }
@@ -2044,13 +2228,11 @@ void space_list_subtract2(LIST_ENTRY* list, LIST_ENTRY* list_size, uint64_t addr } }
-void space_list_subtract(chunk* c, bool deleting, uint64_t address, uint64_t length, LIST_ENTRY* rollback) { - LIST_ENTRY* list; - - list = deleting ? &c->deleting : &c->space; - +void space_list_subtract(chunk* c, uint64_t address, uint64_t length, LIST_ENTRY* rollback) { c->changed = true; c->space_changed = true;
- space_list_subtract2(list, deleting ? NULL : &c->space_size, address, length, c, rollback); + space_list_subtract2(&c->space, &c->space_size, address, length, c, rollback); + + space_list_subtract2(&c->deleting, NULL, address, length, c, rollback); } diff --git a/drivers/filesystems/btrfs/fsctl.c b/drivers/filesystems/btrfs/fsctl.c index b5c8861bed0..70a954d04aa 100644 --- a/drivers/filesystems/btrfs/fsctl.c +++ b/drivers/filesystems/btrfs/fsctl.c @@ -2008,7 +2008,7 @@ static NTSTATUS set_zero_data(device_extension* Vcb, PFILE_OBJECT FileObject, vo if ((uint64_t)fzdi->BeyondFinalZero.QuadPart > fcb->inode_item.st_size) end = sector_align(fcb->inode_item.st_size, Vcb->superblock.sector_size); else - end = (fzdi->BeyondFinalZero.QuadPart / Vcb->superblock.sector_size) * Vcb->superblock.sector_size; + end = (fzdi->BeyondFinalZero.QuadPart >> Vcb->sector_shift) << Vcb->sector_shift;
if (end <= start) { Status = zero_data(Vcb, fcb, fzdi->FileOffset.QuadPart, fzdi->BeyondFinalZero.QuadPart - fzdi->FileOffset.QuadPart, Irp, &rollback); @@ -3385,7 +3385,7 @@ static NTSTATUS duplicate_extents(device_extension* Vcb, PFILE_OBJECT FileObject dataoff = 0; datalen2 = (ULONG)ded->ByteCount.QuadPart; } else { - dataoff = ded->TargetFileOffset.QuadPart % Vcb->superblock.sector_size; + dataoff = ded->TargetFileOffset.QuadPart & (Vcb->superblock.sector_size - 1); datalen2 = (ULONG)sector_align(ded->ByteCount.QuadPart + dataoff, Vcb->superblock.sector_size); }
@@ -3469,7 +3469,7 @@ static NTSTATUS duplicate_extents(device_extension* Vcb, PFILE_OBJECT FileObject
fcb->inode_item.st_blocks += datalen2; } else { - uint64_t start = ded->TargetFileOffset.QuadPart - (ded->TargetFileOffset.QuadPart % Vcb->superblock.sector_size); + uint64_t start = ded->TargetFileOffset.QuadPart - (ded->TargetFileOffset.QuadPart & (Vcb->superblock.sector_size - 1));
Status = do_write_file(fcb, start, start + datalen2, data2, Irp, false, 0, &rollback); if (!NT_SUCCESS(Status)) { @@ -3543,7 +3543,7 @@ static NTSTATUS duplicate_extents(device_extension* Vcb, PFILE_OBJECT FileObject
if (ext->csum) { if (ext->extent_data.compression == BTRFS_COMPRESSION_NONE) { - ext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2d->num_bytes * Vcb->csum_size / Vcb->superblock.sector_size), ALLOC_TAG); + ext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((ed2d->num_bytes * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG); if (!ext2->csum) { ERR("out of memory\n"); Status = STATUS_INSUFFICIENT_RESOURCES; @@ -3551,10 +3551,10 @@ static NTSTATUS duplicate_extents(device_extension* Vcb, PFILE_OBJECT FileObject goto end; }
- RtlCopyMemory(ext2->csum, (uint8_t*)ext->csum + ((ed2d->offset - ed2s->offset) * Vcb->csum_size / Vcb->superblock.sector_size), - (ULONG)(ed2d->num_bytes * Vcb->csum_size / Vcb->superblock.sector_size)); + RtlCopyMemory(ext2->csum, (uint8_t*)ext->csum + (((ed2d->offset - ed2s->offset) * Vcb->csum_size) >> Vcb->sector_shift), + (ULONG)((ed2d->num_bytes * Vcb->csum_size) >> Vcb->sector_shift)); } else { - ext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(ed2d->size * Vcb->csum_size / Vcb->superblock.sector_size), ALLOC_TAG); + ext2->csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((ed2d->size * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG); if (!ext2->csum) { ERR("out of memory\n"); Status = STATUS_INSUFFICIENT_RESOURCES; @@ -3562,7 +3562,7 @@ static NTSTATUS duplicate_extents(device_extension* Vcb, PFILE_OBJECT FileObject goto end; }
- RtlCopyMemory(ext2->csum, ext->csum, (ULONG)(ed2s->size * Vcb->csum_size / Vcb->superblock.sector_size)); + RtlCopyMemory(ext2->csum, ext->csum, (ULONG)((ed2s->size * Vcb->csum_size) >> Vcb->sector_shift)); } } else ext2->csum = NULL; @@ -4674,7 +4674,7 @@ static NTSTATUS resize_device(device_extension* Vcb, void* data, ULONG len, PIRP
TRACE("(%p, %p, %lu)\n", Vcb, data, len);
- if (!data || len < sizeof(btrfs_resize) || (br->size % Vcb->superblock.sector_size) != 0) + if (!data || len < sizeof(btrfs_resize) || (br->size & (Vcb->superblock.sector_size - 1)) != 0) return STATUS_INVALID_PARAMETER;
if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), Irp->RequestorMode)) diff --git a/drivers/filesystems/btrfs/pnp.c b/drivers/filesystems/btrfs/pnp.c index bae4c2ffccd..96401908fba 100644 --- a/drivers/filesystems/btrfs/pnp.c +++ b/drivers/filesystems/btrfs/pnp.c @@ -17,171 +17,15 @@
#include "btrfs_drv.h"
-struct pnp_context; - -typedef struct { - struct pnp_context* context; - PIRP Irp; - IO_STATUS_BLOCK iosb; - NTSTATUS Status; - device* dev; -} pnp_stripe; - -typedef struct { - KEVENT Event; - NTSTATUS Status; - LONG left; - pnp_stripe* stripes; -} pnp_context; - extern ERESOURCE pdo_list_lock; extern LIST_ENTRY pdo_list;
-_Function_class_(IO_COMPLETION_ROUTINE) -static NTSTATUS __stdcall pnp_completion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID conptr) { - pnp_stripe* stripe = conptr; - pnp_context* context = (pnp_context*)stripe->context; - - UNUSED(DeviceObject); - - stripe->Status = Irp->IoStatus.Status; - - InterlockedDecrement(&context->left); - - if (context->left == 0) - KeSetEvent(&context->Event, 0, false); - - return STATUS_MORE_PROCESSING_REQUIRED; -} - -static NTSTATUS send_disks_pnp_message(device_extension* Vcb, UCHAR minor) { - pnp_context context; - ULONG num_devices, i; - NTSTATUS Status; - LIST_ENTRY* le; - - RtlZeroMemory(&context, sizeof(pnp_context)); - KeInitializeEvent(&context.Event, NotificationEvent, false); - - num_devices = (ULONG)min(0xffffffff, Vcb->superblock.num_devices); - - context.stripes = ExAllocatePoolWithTag(NonPagedPool, sizeof(pnp_stripe) * num_devices, ALLOC_TAG); - if (!context.stripes) { - ERR("out of memory\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlZeroMemory(context.stripes, sizeof(pnp_stripe) * num_devices); - - i = 0; - le = Vcb->devices.Flink; - - while (le != &Vcb->devices) { - PIO_STACK_LOCATION IrpSp; - device* dev = CONTAINING_RECORD(le, device, list_entry); - - if (dev->devobj) { - context.stripes[i].context = (struct pnp_context*)&context; - - context.stripes[i].Irp = IoAllocateIrp(dev->devobj->StackSize, false); - - if (!context.stripes[i].Irp) { - uint64_t j; - - ERR("IoAllocateIrp failed\n"); - - for (j = 0; j < i; j++) { - if (context.stripes[j].dev->devobj) { - IoFreeIrp(context.stripes[j].Irp); - } - } - ExFreePool(context.stripes); - - return STATUS_INSUFFICIENT_RESOURCES; - } - - IrpSp = IoGetNextIrpStackLocation(context.stripes[i].Irp); - IrpSp->MajorFunction = IRP_MJ_PNP; - IrpSp->MinorFunction = minor; - IrpSp->FileObject = dev->fileobj; - - context.stripes[i].Irp->UserIosb = &context.stripes[i].iosb; - - IoSetCompletionRoutine(context.stripes[i].Irp, pnp_completion, &context.stripes[i], true, true, true); - - context.stripes[i].Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - context.stripes[i].dev = dev; - - context.left++; - } - - le = le->Flink; - } - - if (context.left == 0) { - Status = STATUS_SUCCESS; - goto end; - } - - for (i = 0; i < num_devices; i++) { - if (context.stripes[i].Irp) { - IoCallDriver(context.stripes[i].dev->devobj, context.stripes[i].Irp); - } - } - - KeWaitForSingleObject(&context.Event, Executive, KernelMode, false, NULL); - - Status = STATUS_SUCCESS; - - for (i = 0; i < num_devices; i++) { - if (context.stripes[i].Irp) { - if (context.stripes[i].Status != STATUS_SUCCESS) - Status = context.stripes[i].Status; - } - } - -end: - for (i = 0; i < num_devices; i++) { - if (context.stripes[i].Irp) { - IoFreeIrp(context.stripes[i].Irp); - } - } - - ExFreePool(context.stripes); - - return Status; -} - -static NTSTATUS pnp_cancel_remove_device(PDEVICE_OBJECT DeviceObject) { - device_extension* Vcb = DeviceObject->DeviceExtension; - NTSTATUS Status; - - ExAcquireResourceSharedLite(&Vcb->tree_lock, true); - - 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; - goto end; - } - - Status = send_disks_pnp_message(Vcb, IRP_MN_CANCEL_REMOVE_DEVICE); - if (!NT_SUCCESS(Status)) { - WARN("send_disks_pnp_message returned %08lx\n", Status); - goto end; - } - -end: - ExReleaseResourceLite(&Vcb->fileref_lock); - ExReleaseResourceLite(&Vcb->tree_lock); - - return STATUS_SUCCESS; -} - NTSTATUS pnp_query_remove_device(PDEVICE_OBJECT DeviceObject, PIRP Irp) { device_extension* Vcb = DeviceObject->DeviceExtension; NTSTATUS Status;
+ // We might be going away imminently - do a flush so we're not caught out + ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
if (Vcb->root_fileref && Vcb->root_fileref->fcb && (Vcb->root_fileref->open_count > 0 || has_open_children(Vcb->root_fileref))) { @@ -189,15 +33,6 @@ NTSTATUS pnp_query_remove_device(PDEVICE_OBJECT DeviceObject, PIRP Irp) { return STATUS_ACCESS_DENIED; }
- Status = send_disks_pnp_message(Vcb, IRP_MN_QUERY_REMOVE_DEVICE); - if (!NT_SUCCESS(Status)) { - WARN("send_disks_pnp_message returned %08lx\n", Status); - ExReleaseResourceLite(&Vcb->tree_lock); - return Status; - } - - Vcb->removing = true; - if (Vcb->need_write && !Vcb->readonly) { Status = do_write(Vcb, Irp);
@@ -212,25 +47,13 @@ NTSTATUS pnp_query_remove_device(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
ExReleaseResourceLite(&Vcb->tree_lock);
- if (Vcb->open_files == 0) - uninit(Vcb); - - return STATUS_SUCCESS; + return STATUS_UNSUCCESSFUL; }
static NTSTATUS pnp_remove_device(PDEVICE_OBJECT DeviceObject) { device_extension* Vcb = DeviceObject->DeviceExtension; NTSTATUS Status;
- ExAcquireResourceSharedLite(&Vcb->tree_lock, true); - - Status = send_disks_pnp_message(Vcb, IRP_MN_REMOVE_DEVICE); - - if (!NT_SUCCESS(Status)) - WARN("send_disks_pnp_message returned %08lx\n", Status); - - ExReleaseResourceLite(&Vcb->tree_lock); - if (DeviceObject->Vpb->Flags & VPB_MOUNTED) { Status = FsRtlNotifyVolumeEvent(Vcb->root_file, FSRTL_VOLUME_DISMOUNT); if (!NT_SUCCESS(Status)) { @@ -649,7 +472,7 @@ NTSTATUS __stdcall drv_pnp(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
switch (IrpSp->MinorFunction) { case IRP_MN_CANCEL_REMOVE_DEVICE: - Status = pnp_cancel_remove_device(DeviceObject); + Status = STATUS_SUCCESS; break;
case IRP_MN_QUERY_REMOVE_DEVICE: diff --git a/drivers/filesystems/btrfs/read.c b/drivers/filesystems/btrfs/read.c index ab3e96eaf47..091a0b0b7fe 100644 --- a/drivers/filesystems/btrfs/read.c +++ b/drivers/filesystems/btrfs/read.c @@ -235,7 +235,6 @@ bool check_sector_csum(device_extension* Vcb, void* buf, void* csum) {
static NTSTATUS read_data_dup(device_extension* Vcb, uint8_t* buf, uint64_t addr, read_data_context* context, CHUNK_ITEM* ci, device** devices, uint64_t generation) { - ULONG i; bool checksum_error = false; uint16_t j, stripe = 0; NTSTATUS Status; @@ -334,7 +333,7 @@ static NTSTATUS read_data_dup(device_extension* Vcb, uint8_t* buf, uint64_t addr
ExFreePool(t2); } else { - ULONG sectors = (ULONG)context->stripes[stripe].Irp->IoStatus.Information / Vcb->superblock.sector_size; + ULONG sectors = (ULONG)context->stripes[stripe].Irp->IoStatus.Information >> Vcb->sector_shift; uint8_t* sector; void* ptr = context->csum;
@@ -344,27 +343,27 @@ static NTSTATUS read_data_dup(device_extension* Vcb, uint8_t* buf, uint64_t addr return STATUS_INSUFFICIENT_RESOURCES; }
- for (i = 0; i < sectors; i++) { - if (!check_sector_csum(Vcb, buf + (i * Vcb->superblock.sector_size), ptr)) { + for (ULONG i = 0; i < sectors; i++) { + if (!check_sector_csum(Vcb, buf + (i << Vcb->sector_shift), ptr)) { bool recovered = false;
for (j = 0; j < ci->num_stripes; j++) { if (j != stripe && devices[j] && devices[j]->devobj) { Status = sync_read_phys(devices[j]->devobj, devices[j]->fileobj, - cis[j].offset + context->stripes[stripe].stripestart + UInt32x32To64(i, Vcb->superblock.sector_size), + cis[j].offset + context->stripes[stripe].stripestart + ((uint64_t)i << Vcb->sector_shift), Vcb->superblock.sector_size, sector, false); if (!NT_SUCCESS(Status)) { WARN("sync_read_phys returned %08lx\n", Status); log_device_error(Vcb, devices[j], BTRFS_DEV_STAT_READ_ERRORS); } else { if (check_sector_csum(Vcb, sector, ptr)) { - RtlCopyMemory(buf + (i * Vcb->superblock.sector_size), sector, Vcb->superblock.sector_size); - ERR("recovering from checksum error at %I64x, device %I64x\n", addr + UInt32x32To64(i, Vcb->superblock.sector_size), devices[stripe]->devitem.dev_id); + RtlCopyMemory(buf + (i << Vcb->sector_shift), sector, Vcb->superblock.sector_size); + ERR("recovering from checksum error at %I64x, device %I64x\n", addr + ((uint64_t)i << Vcb->sector_shift), devices[stripe]->devitem.dev_id); recovered = true;
if (!Vcb->readonly && !devices[stripe]->readonly) { // write good data over bad Status = write_data_phys(devices[stripe]->devobj, devices[stripe]->fileobj, - cis[stripe].offset + context->stripes[stripe].stripestart + UInt32x32To64(i, Vcb->superblock.sector_size), + cis[stripe].offset + context->stripes[stripe].stripestart + ((uint64_t)i << Vcb->sector_shift), sector, Vcb->superblock.sector_size); if (!NT_SUCCESS(Status)) { WARN("write_data_phys returned %08lx\n", Status); @@ -380,7 +379,7 @@ static NTSTATUS read_data_dup(device_extension* Vcb, uint8_t* buf, uint64_t addr }
if (!recovered) { - ERR("unrecoverable checksum error at %I64x\n", addr + UInt32x32To64(i, Vcb->superblock.sector_size)); + ERR("unrecoverable checksum error at %I64x\n", addr + ((uint64_t)i << Vcb->sector_shift)); ExFreePool(sector); return STATUS_CRC_ERROR; } @@ -397,11 +396,9 @@ static NTSTATUS read_data_dup(device_extension* Vcb, uint8_t* buf, uint64_t addr
static NTSTATUS read_data_raid0(device_extension* Vcb, uint8_t* buf, uint64_t addr, uint32_t length, read_data_context* context, CHUNK_ITEM* ci, device** devices, uint64_t generation, uint64_t offset) { - uint64_t i; - - for (i = 0; i < ci->num_stripes; i++) { + for (uint16_t i = 0; i < ci->num_stripes; i++) { if (context->stripes[i].status == ReadDataStatus_Error) { - WARN("stripe %I64u returned error %08lx\n", i, context->stripes[i].iosb.Status); + WARN("stripe %u returned error %08lx\n", i, context->stripes[i].iosb.Status); log_device_error(Vcb, devices[i], BTRFS_DEV_STAT_READ_ERRORS); return context->stripes[i].iosb.Status; } @@ -435,17 +432,17 @@ static NTSTATUS read_data_raid0(device_extension* Vcb, uint8_t* buf, uint64_t ad } else if (context->csum) { NTSTATUS Status;
- Status = check_csum(Vcb, buf, length / Vcb->superblock.sector_size, context->csum); + Status = check_csum(Vcb, buf, length >> Vcb->sector_shift, context->csum);
if (Status == STATUS_CRC_ERROR) { void* ptr = context->csum;
- for (i = 0; i < length / Vcb->superblock.sector_size; i++) { - if (!check_sector_csum(Vcb, buf + (i * Vcb->superblock.sector_size), ptr)) { + for (uint32_t i = 0; i < length >> Vcb->sector_shift; i++) { + if (!check_sector_csum(Vcb, buf + (i << Vcb->sector_shift), ptr)) { uint64_t off; uint16_t stripe;
- get_raid0_offset(addr - offset + UInt32x32To64(i, Vcb->superblock.sector_size), ci->stripe_length, ci->num_stripes, &off, &stripe); + get_raid0_offset(addr - offset + ((uint64_t)i << Vcb->sector_shift), ci->stripe_length, ci->num_stripes, &off, &stripe);
ERR("unrecoverable checksum error at %I64x, device %I64x\n", addr, devices[stripe]->devitem.dev_id);
@@ -469,13 +466,12 @@ static NTSTATUS read_data_raid0(device_extension* Vcb, uint8_t* buf, uint64_t ad
static NTSTATUS read_data_raid10(device_extension* Vcb, uint8_t* buf, uint64_t addr, uint32_t length, read_data_context* context, CHUNK_ITEM* ci, device** devices, uint64_t generation, uint64_t offset) { - uint64_t i; - uint16_t j, stripe; + uint16_t stripe; NTSTATUS Status; bool checksum_error = false; CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&ci[1];
- for (j = 0; j < ci->num_stripes; j++) { + for (uint16_t j = 0; j < ci->num_stripes; j++) { if (context->stripes[j].status == ReadDataStatus_Error) { WARN("stripe %u returned error %08lx\n", j, context->stripes[j].iosb.Status); log_device_error(Vcb, devices[j], BTRFS_DEV_STAT_READ_ERRORS); @@ -500,7 +496,7 @@ static NTSTATUS read_data_raid10(device_extension* Vcb, uint8_t* buf, uint64_t a log_device_error(Vcb, devices[stripe], BTRFS_DEV_STAT_GENERATION_ERRORS); } } else if (context->csum) { - Status = check_csum(Vcb, buf, length / Vcb->superblock.sector_size, context->csum); + Status = check_csum(Vcb, buf, length >> Vcb->sector_shift, context->csum);
if (Status == STATUS_CRC_ERROR) checksum_error = true; @@ -529,14 +525,14 @@ static NTSTATUS read_data_raid10(device_extension* Vcb, uint8_t* buf, uint64_t a
stripe *= ci->sub_stripes;
- for (j = 0; j < ci->sub_stripes; j++) { + for (uint16_t j = 0; j < ci->sub_stripes; j++) { if (context->stripes[stripe + j].status == ReadDataStatus_Success) { badsubstripe = j; break; } }
- for (j = 0; j < ci->sub_stripes; j++) { + for (uint16_t j = 0; j < ci->sub_stripes; j++) { if (context->stripes[stripe + j].status != ReadDataStatus_Success && devices[stripe + j] && devices[stripe + j]->devobj) { Status = sync_read_phys(devices[stripe + j]->devobj, devices[stripe + j]->fileobj, cis[stripe + j].offset + off, Vcb->superblock.node_size, (uint8_t*)t2, false); @@ -577,7 +573,7 @@ static NTSTATUS read_data_raid10(device_extension* Vcb, uint8_t* buf, uint64_t a
ExFreePool(t2); } else { - ULONG sectors = length / Vcb->superblock.sector_size; + ULONG sectors = length >> Vcb->sector_shift; uint8_t* sector; void* ptr = context->csum;
@@ -587,18 +583,18 @@ static NTSTATUS read_data_raid10(device_extension* Vcb, uint8_t* buf, uint64_t a return STATUS_INSUFFICIENT_RESOURCES; }
- for (i = 0; i < sectors; i++) { - if (!check_sector_csum(Vcb, buf + (i * Vcb->superblock.sector_size), ptr)) { + for (ULONG i = 0; i < sectors; i++) { + if (!check_sector_csum(Vcb, buf + (i << Vcb->sector_shift), ptr)) { uint64_t off; uint16_t stripe2, badsubstripe = 0; bool recovered = false;
- get_raid0_offset(addr - offset + UInt32x32To64(i, Vcb->superblock.sector_size), ci->stripe_length, + get_raid0_offset(addr - offset + ((uint64_t)i << Vcb->sector_shift), ci->stripe_length, ci->num_stripes / ci->sub_stripes, &off, &stripe2);
stripe2 *= ci->sub_stripes;
- for (j = 0; j < ci->sub_stripes; j++) { + for (uint16_t j = 0; j < ci->sub_stripes; j++) { if (context->stripes[stripe2 + j].status == ReadDataStatus_Success) { badsubstripe = j; break; @@ -607,7 +603,7 @@ static NTSTATUS read_data_raid10(device_extension* Vcb, uint8_t* buf, uint64_t a
log_device_error(Vcb, devices[stripe2 + badsubstripe], BTRFS_DEV_STAT_CORRUPTION_ERRORS);
- for (j = 0; j < ci->sub_stripes; j++) { + for (uint16_t j = 0; j < ci->sub_stripes; j++) { if (context->stripes[stripe2 + j].status != ReadDataStatus_Success && devices[stripe2 + j] && devices[stripe2 + j]->devobj) { Status = sync_read_phys(devices[stripe2 + j]->devobj, devices[stripe2 + j]->fileobj, cis[stripe2 + j].offset + off, Vcb->superblock.sector_size, sector, false); @@ -616,8 +612,8 @@ static NTSTATUS read_data_raid10(device_extension* Vcb, uint8_t* buf, uint64_t a log_device_error(Vcb, devices[stripe2 + j], BTRFS_DEV_STAT_READ_ERRORS); } else { if (check_sector_csum(Vcb, sector, ptr)) { - RtlCopyMemory(buf + (i * Vcb->superblock.sector_size), sector, Vcb->superblock.sector_size); - ERR("recovering from checksum error at %I64x, device %I64x\n", addr + UInt32x32To64(i, Vcb->superblock.sector_size), devices[stripe2 + j]->devitem.dev_id); + RtlCopyMemory(buf + (i << Vcb->sector_shift), sector, Vcb->superblock.sector_size); + ERR("recovering from checksum error at %I64x, device %I64x\n", addr + ((uint64_t)i << Vcb->sector_shift), devices[stripe2 + j]->devitem.dev_id); recovered = true;
if (!Vcb->readonly && !devices[stripe2 + badsubstripe]->readonly && devices[stripe2 + badsubstripe]->devobj) { // write good data over bad @@ -637,7 +633,7 @@ static NTSTATUS read_data_raid10(device_extension* Vcb, uint8_t* buf, uint64_t a }
if (!recovered) { - ERR("unrecoverable checksum error at %I64x\n", addr + UInt32x32To64(i, Vcb->superblock.sector_size)); + ERR("unrecoverable checksum error at %I64x\n", addr + ((uint64_t)i << Vcb->sector_shift)); ExFreePool(sector); return STATUS_CRC_ERROR; } @@ -654,7 +650,6 @@ static NTSTATUS read_data_raid10(device_extension* Vcb, uint8_t* buf, uint64_t a
static NTSTATUS read_data_raid5(device_extension* Vcb, uint8_t* buf, uint64_t addr, uint32_t length, read_data_context* context, CHUNK_ITEM* ci, device** devices, uint64_t offset, uint64_t generation, chunk* c, bool degraded) { - ULONG i; NTSTATUS Status; bool checksum_error = false; CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&ci[1]; @@ -700,15 +695,14 @@ static NTSTATUS read_data_raid5(device_extension* Vcb, uint8_t* buf, uint64_t ad if (runlength == 0) break; } - #ifndef __REACTOS__ - uint64_t runstart = ps->address + (index * Vcb->superblock.sector_size); - uint64_t runend = runstart + (runlength * Vcb->superblock.sector_size); + uint64_t runstart = ps->address + (index << Vcb->sector_shift); + uint64_t runend = runstart + (runlength << Vcb->sector_shift); uint64_t start = max(runstart, addr); uint64_t end = min(runend, addr + length); #else - runstart = ps->address + (index * Vcb->superblock.sector_size); - runend = runstart + (runlength * Vcb->superblock.sector_size); + runstart = ps->address + (index * Vcb->sector_shift); + runend = runstart + (runlength * Vcb->sector_shift); start = max(runstart, addr); end = min(runend, addr + length); #endif @@ -740,7 +734,7 @@ static NTSTATUS read_data_raid5(device_extension* Vcb, uint8_t* buf, uint64_t ad log_device_error(Vcb, devices[stripe], BTRFS_DEV_STAT_GENERATION_ERRORS); } } else if (context->csum) { - Status = check_csum(Vcb, buf, length / Vcb->superblock.sector_size, context->csum); + Status = check_csum(Vcb, buf, length >> Vcb->sector_shift, context->csum);
if (Status == STATUS_CRC_ERROR) { if (!degraded) @@ -834,7 +828,7 @@ static NTSTATUS read_data_raid5(device_extension* Vcb, uint8_t* buf, uint64_t ad
ExFreePool(t2); } else { - ULONG sectors = length / Vcb->superblock.sector_size; + ULONG sectors = length >> Vcb->sector_shift; uint8_t* sector; void* ptr = context->csum;
@@ -844,18 +838,18 @@ static NTSTATUS read_data_raid5(device_extension* Vcb, uint8_t* buf, uint64_t ad return STATUS_INSUFFICIENT_RESOURCES; }
- for (i = 0; i < sectors; i++) { + for (ULONG i = 0; i < sectors; i++) { uint16_t parity; uint64_t off;
- get_raid0_offset(addr - offset + UInt32x32To64(i, Vcb->superblock.sector_size), ci->stripe_length, + get_raid0_offset(addr - offset + ((uint64_t)i << Vcb->sector_shift), ci->stripe_length, ci->num_stripes - 1, &off, &stripe);
- parity = (((addr - offset + UInt32x32To64(i, Vcb->superblock.sector_size)) / ((ci->num_stripes - 1) * ci->stripe_length)) + ci->num_stripes - 1) % ci->num_stripes; + parity = (((addr - offset + ((uint64_t)i << Vcb->sector_shift)) / ((ci->num_stripes - 1) * ci->stripe_length)) + ci->num_stripes - 1) % ci->num_stripes;
stripe = (parity + stripe + 1) % ci->num_stripes;
- if (!devices[stripe] || !devices[stripe]->devobj || (ptr && !check_sector_csum(Vcb, buf + (i * Vcb->superblock.sector_size), ptr))) { + if (!devices[stripe] || !devices[stripe]->devobj || (ptr && !check_sector_csum(Vcb, buf + (i << Vcb->sector_shift), ptr))) { bool recovered = false, first = true, failed = false;
if (devices[stripe] && devices[stripe]->devobj) @@ -895,10 +889,10 @@ static NTSTATUS read_data_raid5(device_extension* Vcb, uint8_t* buf, uint64_t ad
if (!failed) { if (!ptr || check_sector_csum(Vcb, sector, ptr)) { - RtlCopyMemory(buf + (i * Vcb->superblock.sector_size), sector, Vcb->superblock.sector_size); + RtlCopyMemory(buf + (i << Vcb->sector_shift), sector, Vcb->superblock.sector_size);
if (!degraded) - ERR("recovering from checksum error at %I64x, device %I64x\n", addr + UInt32x32To64(i, Vcb->superblock.sector_size), devices[stripe]->devitem.dev_id); + ERR("recovering from checksum error at %I64x, device %I64x\n", addr + ((uint64_t)i << Vcb->sector_shift), devices[stripe]->devitem.dev_id);
recovered = true;
@@ -914,7 +908,7 @@ static NTSTATUS read_data_raid5(device_extension* Vcb, uint8_t* buf, uint64_t ad }
if (!recovered) { - ERR("unrecoverable checksum error at %I64x\n", addr + UInt32x32To64(i, Vcb->superblock.sector_size)); + ERR("unrecoverable checksum error at %I64x\n", addr + ((uint64_t)i << Vcb->sector_shift)); ExFreePool(sector); return STATUS_CRC_ERROR; } @@ -1019,7 +1013,6 @@ void raid6_recover2(uint8_t* sectors, uint16_t num_stripes, ULONG sector_size, u static NTSTATUS read_data_raid6(device_extension* Vcb, uint8_t* buf, uint64_t addr, uint32_t length, read_data_context* context, CHUNK_ITEM* ci, device** devices, uint64_t offset, uint64_t generation, chunk* c, bool degraded) { NTSTATUS Status; - ULONG i; bool checksum_error = false; CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&ci[1]; uint16_t stripe, j; @@ -1068,13 +1061,13 @@ static NTSTATUS read_data_raid6(device_extension* Vcb, uint8_t* buf, uint64_t ad }
#ifndef __REACTOS__ - uint64_t runstart = ps->address + (index * Vcb->superblock.sector_size); - uint64_t runend = runstart + (runlength * Vcb->superblock.sector_size); + uint64_t runstart = ps->address + (index << Vcb->sector_shift); + uint64_t runend = runstart + (runlength << Vcb->sector_shift); uint64_t start = max(runstart, addr); uint64_t end = min(runend, addr + length); #else - runstart = ps->address + (index * Vcb->superblock.sector_size); - runend = runstart + (runlength * Vcb->superblock.sector_size); + runstart = ps->address + (index * Vcb->sector_shift); + runend = runstart + (runlength * Vcb->sector_shift); start = max(runstart, addr); end = min(runend, addr + length); #endif @@ -1106,7 +1099,7 @@ static NTSTATUS read_data_raid6(device_extension* Vcb, uint8_t* buf, uint64_t ad log_device_error(Vcb, devices[stripe], BTRFS_DEV_STAT_GENERATION_ERRORS); } } else if (context->csum) { - Status = check_csum(Vcb, buf, length / Vcb->superblock.sector_size, context->csum); + Status = check_csum(Vcb, buf, length >> Vcb->sector_shift, context->csum);
if (Status == STATUS_CRC_ERROR) { if (!degraded) @@ -1305,30 +1298,30 @@ static NTSTATUS read_data_raid6(device_extension* Vcb, uint8_t* buf, uint64_t ad
ExFreePool(sector); } else { - ULONG sectors = length / Vcb->superblock.sector_size; + ULONG sectors = length >> Vcb->sector_shift; uint8_t* sector; void* ptr = context->csum;
- sector = ExAllocatePoolWithTag(NonPagedPool, Vcb->superblock.sector_size * (ci->num_stripes + 2), ALLOC_TAG); + sector = ExAllocatePoolWithTag(NonPagedPool, (ci->num_stripes + 2) << Vcb->sector_shift, ALLOC_TAG); if (!sector) { ERR("out of memory\n"); return STATUS_INSUFFICIENT_RESOURCES; }
- for (i = 0; i < sectors; i++) { + for (ULONG i = 0; i < sectors; i++) { uint64_t off; uint16_t physstripe, parity1, parity2;
- get_raid0_offset(addr - offset + UInt32x32To64(i, Vcb->superblock.sector_size), ci->stripe_length, + get_raid0_offset(addr - offset + ((uint64_t)i << Vcb->sector_shift), ci->stripe_length, ci->num_stripes - 2, &off, &stripe);
- parity1 = (((addr - offset + UInt32x32To64(i, Vcb->superblock.sector_size)) / ((ci->num_stripes - 2) * ci->stripe_length)) + ci->num_stripes - 2) % ci->num_stripes; + parity1 = (((addr - offset + ((uint64_t)i << Vcb->sector_shift)) / ((ci->num_stripes - 2) * ci->stripe_length)) + ci->num_stripes - 2) % ci->num_stripes; parity2 = (parity1 + 1) % ci->num_stripes;
physstripe = (parity2 + stripe + 1) % ci->num_stripes;
- if (!devices[physstripe] || !devices[physstripe]->devobj || (context->csum && !check_sector_csum(Vcb, buf + (i * Vcb->superblock.sector_size), ptr))) { - uint16_t k, error_stripe; + if (!devices[physstripe] || !devices[physstripe]->devobj || (context->csum && !check_sector_csum(Vcb, buf + (i << Vcb->sector_shift), ptr))) { + uint16_t error_stripe; bool recovered = false, failed = false; ULONG num_errors = 0;
@@ -1337,11 +1330,11 @@ static NTSTATUS read_data_raid6(device_extension* Vcb, uint8_t* buf, uint64_t ad
j = (parity2 + 1) % ci->num_stripes;
- for (k = 0; k < ci->num_stripes - 1; k++) { + for (uint16_t k = 0; k < ci->num_stripes - 1; k++) { if (j != physstripe) { if (devices[j] && devices[j]->devobj) { Status = sync_read_phys(devices[j]->devobj, devices[j]->fileobj, cis[j].offset + off, Vcb->superblock.sector_size, - sector + (k * Vcb->superblock.sector_size), false); + sector + ((ULONG)k << Vcb->sector_shift), false); if (!NT_SUCCESS(Status)) { ERR("sync_read_phys returned %08lx\n", Status); log_device_error(Vcb, devices[j], BTRFS_DEV_STAT_READ_ERRORS); @@ -1369,25 +1362,25 @@ static NTSTATUS read_data_raid6(device_extension* Vcb, uint8_t* buf, uint64_t ad
if (!failed) { if (num_errors == 0) { - RtlCopyMemory(sector + (stripe * Vcb->superblock.sector_size), sector + ((ci->num_stripes - 2) * Vcb->superblock.sector_size), Vcb->superblock.sector_size); + RtlCopyMemory(sector + ((unsigned int)stripe << Vcb->sector_shift), sector + ((unsigned int)(ci->num_stripes - 2) << Vcb->sector_shift), Vcb->superblock.sector_size);
for (j = 0; j < ci->num_stripes - 2; j++) { if (j != stripe) - do_xor(sector + (stripe * Vcb->superblock.sector_size), sector + (j * Vcb->superblock.sector_size), Vcb->superblock.sector_size); + do_xor(sector + ((unsigned int)stripe << Vcb->sector_shift), sector + ((unsigned int)j << Vcb->sector_shift), Vcb->superblock.sector_size); }
- if (!ptr || check_sector_csum(Vcb, sector + (stripe * Vcb->superblock.sector_size), ptr)) { - RtlCopyMemory(buf + (i * Vcb->superblock.sector_size), sector + (stripe * Vcb->superblock.sector_size), Vcb->superblock.sector_size); + if (!ptr || check_sector_csum(Vcb, sector + ((unsigned int)stripe << Vcb->sector_shift), ptr)) { + RtlCopyMemory(buf + (i << Vcb->sector_shift), sector + ((unsigned int)stripe << Vcb->sector_shift), Vcb->superblock.sector_size);
if (devices[physstripe] && devices[physstripe]->devobj) - ERR("recovering from checksum error at %I64x, device %I64x\n", addr + UInt32x32To64(i, Vcb->superblock.sector_size), + ERR("recovering from checksum error at %I64x, device %I64x\n", addr + ((uint64_t)i << Vcb->sector_shift), devices[physstripe]->devitem.dev_id);
recovered = true;
if (!Vcb->readonly && devices[physstripe] && devices[physstripe]->devobj && !devices[physstripe]->readonly) { // write good data over bad Status = write_data_phys(devices[physstripe]->devobj, devices[physstripe]->fileobj, cis[physstripe].offset + off, - sector + (stripe * Vcb->superblock.sector_size), Vcb->superblock.sector_size); + sector + ((unsigned int)stripe << Vcb->sector_shift), Vcb->superblock.sector_size); if (!NT_SUCCESS(Status)) { WARN("write_data_phys returned %08lx\n", Status); log_device_error(Vcb, devices[physstripe], BTRFS_DEV_STAT_WRITE_ERRORS); @@ -1401,7 +1394,7 @@ static NTSTATUS read_data_raid6(device_extension* Vcb, uint8_t* buf, uint64_t ad
if (devices[parity2] && devices[parity2]->devobj) { Status = sync_read_phys(devices[parity2]->devobj, devices[parity2]->fileobj, cis[parity2].offset + off, - Vcb->superblock.sector_size, sector + ((ci->num_stripes - 1) * Vcb->superblock.sector_size), false); + Vcb->superblock.sector_size, sector + ((unsigned int)(ci->num_stripes - 1) << Vcb->sector_shift), false); if (!NT_SUCCESS(Status)) { ERR("sync_read_phys returned %08lx\n", Status); log_device_error(Vcb, devices[parity2], BTRFS_DEV_STAT_READ_ERRORS); @@ -1411,18 +1404,18 @@ static NTSTATUS read_data_raid6(device_extension* Vcb, uint8_t* buf, uint64_t ad
if (read_q) { if (num_errors == 1) { - raid6_recover2(sector, ci->num_stripes, Vcb->superblock.sector_size, stripe, error_stripe, sector + (ci->num_stripes * Vcb->superblock.sector_size)); + raid6_recover2(sector, ci->num_stripes, Vcb->superblock.sector_size, stripe, error_stripe, sector + ((unsigned int)ci->num_stripes << Vcb->sector_shift));
if (!devices[physstripe] || !devices[physstripe]->devobj) recovered = true; else - recovered = check_sector_csum(Vcb, sector + (ci->num_stripes * Vcb->superblock.sector_size), ptr); + recovered = check_sector_csum(Vcb, sector + ((unsigned int)ci->num_stripes << Vcb->sector_shift), ptr); } else { for (j = 0; j < ci->num_stripes - 1; j++) { if (j != stripe) { - raid6_recover2(sector, ci->num_stripes, Vcb->superblock.sector_size, stripe, j, sector + (ci->num_stripes * Vcb->superblock.sector_size)); + raid6_recover2(sector, ci->num_stripes, Vcb->superblock.sector_size, stripe, j, sector + ((unsigned int)ci->num_stripes << Vcb->sector_shift));
- if (check_sector_csum(Vcb, sector + (ci->num_stripes * Vcb->superblock.sector_size), ptr)) { + if (check_sector_csum(Vcb, sector + ((unsigned int)ci->num_stripes << Vcb->sector_shift), ptr)) { recovered = true; error_stripe = j; break; @@ -1437,13 +1430,13 @@ static NTSTATUS read_data_raid6(device_extension* Vcb, uint8_t* buf, uint64_t ad
if (devices[physstripe] && devices[physstripe]->devobj) ERR("recovering from checksum error at %I64x, device %I64x\n", - addr + UInt32x32To64(i, Vcb->superblock.sector_size), devices[physstripe]->devitem.dev_id); + addr + ((uint64_t)i << Vcb->sector_shift), devices[physstripe]->devitem.dev_id);
- RtlCopyMemory(buf + (i * Vcb->superblock.sector_size), sector + (ci->num_stripes * Vcb->superblock.sector_size), Vcb->superblock.sector_size); + RtlCopyMemory(buf + (i << Vcb->sector_shift), sector + ((unsigned int)ci->num_stripes << Vcb->sector_shift), Vcb->superblock.sector_size);
if (!Vcb->readonly && devices[physstripe] && devices[physstripe]->devobj && !devices[physstripe]->readonly) { // write good data over bad Status = write_data_phys(devices[physstripe]->devobj, devices[physstripe]->fileobj, cis[physstripe].offset + off, - sector + (ci->num_stripes * Vcb->superblock.sector_size), Vcb->superblock.sector_size); + sector + ((unsigned int)ci->num_stripes << Vcb->sector_shift), Vcb->superblock.sector_size); if (!NT_SUCCESS(Status)) { WARN("write_data_phys returned %08lx\n", Status); log_device_error(Vcb, devices[physstripe], BTRFS_DEV_STAT_WRITE_ERRORS); @@ -1452,37 +1445,37 @@ static NTSTATUS read_data_raid6(device_extension* Vcb, uint8_t* buf, uint64_t ad
if (devices[error_stripe_phys] && devices[error_stripe_phys]->devobj) { if (error_stripe == ci->num_stripes - 2) { - ERR("recovering from parity error at %I64x, device %I64x\n", addr + UInt32x32To64(i, Vcb->superblock.sector_size), + ERR("recovering from parity error at %I64x, device %I64x\n", addr + ((uint64_t)i << Vcb->sector_shift), devices[error_stripe_phys]->devitem.dev_id);
log_device_error(Vcb, devices[error_stripe_phys], BTRFS_DEV_STAT_CORRUPTION_ERRORS);
- RtlZeroMemory(sector + ((ci->num_stripes - 2) * Vcb->superblock.sector_size), Vcb->superblock.sector_size); + RtlZeroMemory(sector + ((unsigned int)(ci->num_stripes - 2) << Vcb->sector_shift), Vcb->superblock.sector_size);
for (j = 0; j < ci->num_stripes - 2; j++) { if (j == stripe) { - do_xor(sector + ((ci->num_stripes - 2) * Vcb->superblock.sector_size), sector + (ci->num_stripes * Vcb->superblock.sector_size), + do_xor(sector + ((unsigned int)(ci->num_stripes - 2) << Vcb->sector_shift), sector + ((unsigned int)ci->num_stripes << Vcb->sector_shift), Vcb->superblock.sector_size); } else { - do_xor(sector + ((ci->num_stripes - 2) * Vcb->superblock.sector_size), sector + (j * Vcb->superblock.sector_size), + do_xor(sector + ((unsigned int)(ci->num_stripes - 2) << Vcb->sector_shift), sector + ((unsigned int)j << Vcb->sector_shift), Vcb->superblock.sector_size); } } } else { ERR("recovering from checksum error at %I64x, device %I64x\n", - addr + UInt32x32To64(i, Vcb->superblock.sector_size) + ((error_stripe - stripe) * ci->stripe_length), + addr + ((uint64_t)i << Vcb->sector_shift) + ((error_stripe - stripe) * ci->stripe_length), devices[error_stripe_phys]->devitem.dev_id);
log_device_error(Vcb, devices[error_stripe_phys], BTRFS_DEV_STAT_CORRUPTION_ERRORS);
- RtlCopyMemory(sector + (error_stripe * Vcb->superblock.sector_size), - sector + ((ci->num_stripes + 1) * Vcb->superblock.sector_size), Vcb->superblock.sector_size); + RtlCopyMemory(sector + ((unsigned int)error_stripe << Vcb->sector_shift), + sector + ((unsigned int)(ci->num_stripes + 1) << Vcb->sector_shift), Vcb->superblock.sector_size); } }
if (!Vcb->readonly && devices[error_stripe_phys] && devices[error_stripe_phys]->devobj && !devices[error_stripe_phys]->readonly) { // write good data over bad Status = write_data_phys(devices[error_stripe_phys]->devobj, devices[error_stripe_phys]->fileobj, cis[error_stripe_phys].offset + off, - sector + (error_stripe * Vcb->superblock.sector_size), Vcb->superblock.sector_size); + sector + ((unsigned int)error_stripe << Vcb->sector_shift), Vcb->superblock.sector_size); if (!NT_SUCCESS(Status)) { WARN("write_data_phys returned %08lx\n", Status); log_device_error(Vcb, devices[error_stripe_phys], BTRFS_DEV_STAT_WRITE_ERRORS); @@ -1493,7 +1486,7 @@ static NTSTATUS read_data_raid6(device_extension* Vcb, uint8_t* buf, uint64_t ad }
if (!recovered) { - ERR("unrecoverable checksum error at %I64x\n", addr + UInt32x32To64(i, Vcb->superblock.sector_size)); + ERR("unrecoverable checksum error at %I64x\n", addr + ((uint64_t)i << Vcb->sector_shift)); ExFreePool(sector); return STATUS_CRC_ERROR; } @@ -1796,9 +1789,9 @@ NTSTATUS read_data(_In_ device_extension* Vcb, _In_ uint64_t addr, _In_ uint32_t } else context.va = buf;
- context.firstoff = (uint16_t)((startoff % ci->stripe_length) / Vcb->superblock.sector_size); + context.firstoff = (uint16_t)((startoff % ci->stripe_length) >> Vcb->sector_shift); context.startoffstripe = startoffstripe; - context.sectors_per_stripe = (uint16_t)(ci->stripe_length / Vcb->superblock.sector_size); + context.sectors_per_stripe = (uint16_t)(ci->stripe_length >> Vcb->sector_shift);
startoffstripe *= ci->sub_stripes; endoffstripe *= ci->sub_stripes; @@ -2761,6 +2754,7 @@ exit: return Status; }
+__attribute__((nonnull(1, 2))) NTSTATUS read_stream(fcb* fcb, uint8_t* data, uint64_t start, ULONG length, ULONG* pbr) { ULONG readlen;
@@ -2825,6 +2819,7 @@ typedef struct { size_t length; } comp_calc_job;
+__attribute__((nonnull(1, 2))) NTSTATUS read_file(fcb* fcb, uint8_t* data, uint64_t start, uint64_t length, ULONG* pbr, PIRP Irp) { NTSTATUS Status; uint32_t bytes_read = 0; @@ -2853,14 +2848,16 @@ NTSTATUS read_file(fcb* fcb, uint8_t* data, uint64_t start, uint64_t length, ULO last_end = start;
while (le != &fcb->extents) { - uint64_t len; extent* ext = CONTAINING_RECORD(le, extent, list_entry);
if (!ext->ignore) { EXTENT_DATA* ed = &ext->extent_data; - EXTENT_DATA2* ed2 = (ed->type == EXTENT_TYPE_REGULAR || ed->type == EXTENT_TYPE_PREALLOC) ? (EXTENT_DATA2*)ed->data : NULL; + uint64_t len;
- len = ed2 ? ed2->num_bytes : ed->decoded_size; + if (ed->type == EXTENT_TYPE_REGULAR || ed->type == EXTENT_TYPE_PREALLOC) + len = ((EXTENT_DATA2*)ed->data)->num_bytes; + else + len = ed->decoded_size;
if (ext->offset + len <= start) { last_end = ext->offset + len; @@ -2976,6 +2973,7 @@ NTSTATUS read_file(fcb* fcb, uint8_t* data, uint64_t start, uint64_t length, ULO
case EXTENT_TYPE_REGULAR: { + EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ed->data; read_part* rp;
rp = ExAllocatePoolWithTag(pool_type, sizeof(read_part), ALLOC_TAG); @@ -2998,8 +2996,8 @@ NTSTATUS read_file(fcb* fcb, uint8_t* data, uint64_t start, uint64_t length, ULO rp->addr = ed2->address + ed2->offset + rp->extents[0].off; rp->to_read = (uint32_t)sector_align(rp->read, fcb->Vcb->superblock.sector_size);
- if (rp->addr % fcb->Vcb->superblock.sector_size > 0) { - rp->bumpoff = rp->addr % fcb->Vcb->superblock.sector_size; + if (rp->addr & (fcb->Vcb->superblock.sector_size - 1)) { + rp->bumpoff = rp->addr & (fcb->Vcb->superblock.sector_size - 1); rp->addr -= rp->bumpoff; rp->to_read = (uint32_t)sector_align(rp->read + rp->bumpoff, fcb->Vcb->superblock.sector_size); } @@ -3008,8 +3006,8 @@ NTSTATUS read_file(fcb* fcb, uint8_t* data, uint64_t start, uint64_t length, ULO rp->to_read = (uint32_t)sector_align(ed2->size, fcb->Vcb->superblock.sector_size); }
- if (ed->compression == BTRFS_COMPRESSION_NONE && start % fcb->Vcb->superblock.sector_size == 0 && - length % fcb->Vcb->superblock.sector_size == 0) { + if (ed->compression == BTRFS_COMPRESSION_NONE && (start & (fcb->Vcb->superblock.sector_size - 1)) == 0 && + (length & (fcb->Vcb->superblock.sector_size - 1)) == 0) { rp->buf = data + bytes_read; rp->buf_free = false; } else { @@ -3036,12 +3034,13 @@ NTSTATUS read_file(fcb* fcb, uint8_t* data, uint64_t start, uint64_t length, ULO
ExFreePool(rp);
+ Status = STATUS_INTERNAL_ERROR; goto exit; }
if (ext->csum) { if (ed->compression == BTRFS_COMPRESSION_NONE) { - rp->csum = (uint8_t*)ext->csum + (fcb->Vcb->csum_size * (rp->extents[0].off / fcb->Vcb->superblock.sector_size)); + rp->csum = (uint8_t*)ext->csum + (fcb->Vcb->csum_size * (rp->extents[0].off >> fcb->Vcb->sector_shift)); } else rp->csum = ext->csum; } else @@ -3114,7 +3113,7 @@ nextitem: rp2->csum_free = false;
if (last_rp->csum) { - uint32_t sectors = (last_rp->to_read + rp->to_read) / fcb->Vcb->superblock.sector_size; + uint32_t sectors = (last_rp->to_read + rp->to_read) >> fcb->Vcb->sector_shift;
rp2->csum = ExAllocatePoolWithTag(pool_type, sectors * fcb->Vcb->csum_size, ALLOC_TAG); if (!rp2->csum) { @@ -3124,9 +3123,9 @@ nextitem: goto exit; }
- RtlCopyMemory(rp2->csum, last_rp->csum, last_rp->to_read * fcb->Vcb->csum_size / fcb->Vcb->superblock.sector_size); - RtlCopyMemory((uint8_t*)rp2->csum + (last_rp->to_read * fcb->Vcb->csum_size / fcb->Vcb->superblock.sector_size), rp->csum, - rp->to_read * fcb->Vcb->csum_size / fcb->Vcb->superblock.sector_size); + RtlCopyMemory(rp2->csum, last_rp->csum, (last_rp->to_read * fcb->Vcb->csum_size) >> fcb->Vcb->sector_shift); + RtlCopyMemory((uint8_t*)rp2->csum + ((last_rp->to_read * fcb->Vcb->csum_size) >> fcb->Vcb->sector_shift), rp->csum, + (rp->to_read * fcb->Vcb->csum_size) >> fcb->Vcb->sector_shift);
rp2->csum_free = true; } else @@ -3189,7 +3188,7 @@ nextitem: read_part* rp = CONTAINING_RECORD(le, read_part, list_entry);
Status = read_data(fcb->Vcb, rp->addr, rp->to_read, rp->csum, false, rp->buf, rp->c, NULL, Irp, 0, rp->mdl, - fcb && fcb->Header.Flags2 & FSRTL_FLAG2_IS_PAGING_FILE ? HighPagePriority : NormalPagePriority); + fcb->Header.Flags2 & FSRTL_FLAG2_IS_PAGING_FILE ? HighPagePriority : NormalPagePriority); if (!NT_SUCCESS(Status)) { ERR("read_data returned %08lx\n", Status); goto exit; @@ -3395,26 +3394,53 @@ NTSTATUS do_read(PIRP Irp, bool wait, ULONG* bytes_read) {
TRACE("FileObject %p fcb %p FileSize = %I64x st_size = %I64x (%p)\n", FileObject, fcb, fcb->Header.FileSize.QuadPart, fcb->inode_item.st_size, &fcb->inode_item.st_size);
- if (Irp->Flags & IRP_NOCACHE || !(IrpSp->MinorFunction & IRP_MN_MDL)) { - data = map_user_buffer(Irp, fcb->Header.Flags2 & FSRTL_FLAG2_IS_PAGING_FILE ? HighPagePriority : NormalPagePriority); + if (!(Irp->Flags & IRP_NOCACHE) && IrpSp->MinorFunction & IRP_MN_MDL) { + NTSTATUS Status = STATUS_SUCCESS;
- if (Irp->MdlAddress && !data) { - ERR("MmGetSystemAddressForMdlSafe returned NULL\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } + _SEH2_TRY { + if (!FileObject->PrivateCacheMap) { + CC_FILE_SIZES ccfs;
- if (start >= (uint64_t)fcb->Header.ValidDataLength.QuadPart) { - length = (ULONG)min(length, min(start + length, (uint64_t)fcb->Header.FileSize.QuadPart) - fcb->Header.ValidDataLength.QuadPart); - RtlZeroMemory(data, length); - Irp->IoStatus.Information = *bytes_read = length; - return STATUS_SUCCESS; - } + ccfs.AllocationSize = fcb->Header.AllocationSize; + ccfs.FileSize = fcb->Header.FileSize; + ccfs.ValidDataLength = fcb->Header.ValidDataLength;
- if (length + start > (uint64_t)fcb->Header.ValidDataLength.QuadPart) { - addon = (ULONG)(min(start + length, (uint64_t)fcb->Header.FileSize.QuadPart) - fcb->Header.ValidDataLength.QuadPart); - RtlZeroMemory(data + (fcb->Header.ValidDataLength.QuadPart - start), addon); - length = (ULONG)(fcb->Header.ValidDataLength.QuadPart - start); - } + init_file_cache(FileObject, &ccfs); + } + + CcMdlRead(FileObject, &IrpSp->Parameters.Read.ByteOffset, length, &Irp->MdlAddress, &Irp->IoStatus); + } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { + Status = _SEH2_GetExceptionCode(); + } _SEH2_END; + + if (NT_SUCCESS(Status)) { + Status = Irp->IoStatus.Status; + Irp->IoStatus.Information += addon; + *bytes_read = (ULONG)Irp->IoStatus.Information; + } else + ERR("EXCEPTION - %08lx\n", Status); + + return Status; + } + + data = map_user_buffer(Irp, fcb->Header.Flags2 & FSRTL_FLAG2_IS_PAGING_FILE ? HighPagePriority : NormalPagePriority); + + if (Irp->MdlAddress && !data) { + ERR("MmGetSystemAddressForMdlSafe returned NULL\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + if (start >= (uint64_t)fcb->Header.ValidDataLength.QuadPart) { + length = (ULONG)min(length, min(start + length, (uint64_t)fcb->Header.FileSize.QuadPart) - fcb->Header.ValidDataLength.QuadPart); + RtlZeroMemory(data, length); + Irp->IoStatus.Information = *bytes_read = length; + return STATUS_SUCCESS; + } + + if (length + start > (uint64_t)fcb->Header.ValidDataLength.QuadPart) { + addon = (ULONG)(min(start + length, (uint64_t)fcb->Header.FileSize.QuadPart) - fcb->Header.ValidDataLength.QuadPart); + RtlZeroMemory(data + (fcb->Header.ValidDataLength.QuadPart - start), addon); + length = (ULONG)(fcb->Header.ValidDataLength.QuadPart - start); }
if (!(Irp->Flags & IRP_NOCACHE)) { @@ -3431,31 +3457,27 @@ NTSTATUS do_read(PIRP Irp, bool wait, ULONG* bytes_read) { init_file_cache(FileObject, &ccfs); }
- if (IrpSp->MinorFunction & IRP_MN_MDL) { - CcMdlRead(FileObject,&IrpSp->Parameters.Read.ByteOffset, length, &Irp->MdlAddress, &Irp->IoStatus); + if (fCcCopyReadEx) { + TRACE("CcCopyReadEx(%p, %I64x, %lx, %u, %p, %p, %p)\n", FileObject, IrpSp->Parameters.Read.ByteOffset.QuadPart, + length, wait, data, &Irp->IoStatus, Irp->Tail.Overlay.Thread); + TRACE("sizes = %I64x, %I64x, %I64x\n", fcb->Header.AllocationSize.QuadPart, fcb->Header.FileSize.QuadPart, fcb->Header.ValidDataLength.QuadPart); + if (!fCcCopyReadEx(FileObject, &IrpSp->Parameters.Read.ByteOffset, length, wait, data, &Irp->IoStatus, Irp->Tail.Overlay.Thread)) { + TRACE("CcCopyReadEx could not wait\n"); + + IoMarkIrpPending(Irp); + return STATUS_PENDING; + } + TRACE("CcCopyReadEx finished\n"); } else { - if (fCcCopyReadEx) { - TRACE("CcCopyReadEx(%p, %I64x, %lx, %u, %p, %p, %p)\n", FileObject, IrpSp->Parameters.Read.ByteOffset.QuadPart, - length, wait, data, &Irp->IoStatus, Irp->Tail.Overlay.Thread); - TRACE("sizes = %I64x, %I64x, %I64x\n", fcb->Header.AllocationSize.QuadPart, fcb->Header.FileSize.QuadPart, fcb->Header.ValidDataLength.QuadPart); - if (!fCcCopyReadEx(FileObject, &IrpSp->Parameters.Read.ByteOffset, length, wait, data, &Irp->IoStatus, Irp->Tail.Overlay.Thread)) { - TRACE("CcCopyReadEx could not wait\n"); - - IoMarkIrpPending(Irp); - return STATUS_PENDING; - } - TRACE("CcCopyReadEx finished\n"); - } else { - TRACE("CcCopyRead(%p, %I64x, %lx, %u, %p, %p)\n", FileObject, IrpSp->Parameters.Read.ByteOffset.QuadPart, length, wait, data, &Irp->IoStatus); - TRACE("sizes = %I64x, %I64x, %I64x\n", fcb->Header.AllocationSize.QuadPart, fcb->Header.FileSize.QuadPart, fcb->Header.ValidDataLength.QuadPart); - if (!CcCopyRead(FileObject, &IrpSp->Parameters.Read.ByteOffset, length, wait, data, &Irp->IoStatus)) { - TRACE("CcCopyRead could not wait\n"); + TRACE("CcCopyRead(%p, %I64x, %lx, %u, %p, %p)\n", FileObject, IrpSp->Parameters.Read.ByteOffset.QuadPart, length, wait, data, &Irp->IoStatus); + TRACE("sizes = %I64x, %I64x, %I64x\n", fcb->Header.AllocationSize.QuadPart, fcb->Header.FileSize.QuadPart, fcb->Header.ValidDataLength.QuadPart); + if (!CcCopyRead(FileObject, &IrpSp->Parameters.Read.ByteOffset, length, wait, data, &Irp->IoStatus)) { + TRACE("CcCopyRead could not wait\n");
- IoMarkIrpPending(Irp); - return STATUS_PENDING; - } - TRACE("CcCopyRead finished\n"); + IoMarkIrpPending(Irp); + return STATUS_PENDING; } + TRACE("CcCopyRead finished\n"); } } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); diff --git a/drivers/filesystems/btrfs/reparse.c b/drivers/filesystems/btrfs/reparse.c index 8112c4a2143..e6a8145b0d3 100644 --- a/drivers/filesystems/btrfs/reparse.c +++ b/drivers/filesystems/btrfs/reparse.c @@ -19,6 +19,11 @@
extern tFsRtlValidateReparsePointBuffer fFsRtlValidateReparsePointBuffer;
+typedef struct { + uint32_t unknown; + char name[1]; +} REPARSE_DATA_BUFFER_LX_SYMLINK; + NTSTATUS get_reparse_point(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject, void* buffer, DWORD buflen, ULONG_PTR* retlen) { USHORT subnamelen, printnamelen, i; ULONG stringlen; @@ -171,17 +176,18 @@ end: return Status; }
-static NTSTATUS set_symlink(PIRP Irp, file_ref* fileref, fcb* fcb, ccb* ccb, REPARSE_DATA_BUFFER* rdb, ULONG buflen, bool write, LIST_ENTRY* rollback) { +static NTSTATUS set_symlink(PIRP Irp, file_ref* fileref, fcb* fcb, ccb* ccb, REPARSE_DATA_BUFFER* rdb, ULONG buflen, LIST_ENTRY* rollback) { NTSTATUS Status; - ULONG minlen; ULONG tlength; - UNICODE_STRING subname; ANSI_STRING target; + bool target_alloc = false; LARGE_INTEGER offset, time; BTRFS_TIME now; - USHORT i;
- if (write) { + if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) { + UNICODE_STRING subname; + ULONG minlen, len; + minlen = offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + sizeof(WCHAR); if (buflen < minlen) { WARN("buffer was less than minimum length (%lu < %lu)\n", buflen, minlen); @@ -197,54 +203,81 @@ static NTSTATUS set_symlink(PIRP Irp, file_ref* fileref, fcb* fcb, ccb* ccb, REP subname.MaximumLength = subname.Length = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength;
TRACE("substitute name = %.*S\n", (int)(subname.Length / sizeof(WCHAR)), subname.Buffer); - }
- fcb->type = BTRFS_TYPE_SYMLINK; - fcb->inode_item.st_mode |= __S_IFLNK; - fcb->inode_item.generation = fcb->Vcb->superblock.generation; // so we don't confuse btrfs send on Linux - - if (fileref && fileref->dc) - fileref->dc->type = fcb->type; - - if (write) { - Status = truncate_file(fcb, 0, Irp, rollback); - if (!NT_SUCCESS(Status)) { - ERR("truncate_file returned %08lx\n", Status); - return Status; - } - - Status = utf16_to_utf8(NULL, 0, (PULONG)&target.Length, subname.Buffer, subname.Length); + Status = utf16_to_utf8(NULL, 0, &len, subname.Buffer, subname.Length); if (!NT_SUCCESS(Status)) { ERR("utf16_to_utf8 1 failed with error %08lx\n", Status); return Status; }
- target.MaximumLength = target.Length; + target.MaximumLength = target.Length = (USHORT)len; target.Buffer = ExAllocatePoolWithTag(PagedPool, target.MaximumLength, ALLOC_TAG); if (!target.Buffer) { ERR("out of memory\n"); return STATUS_INSUFFICIENT_RESOURCES; }
- Status = utf16_to_utf8(target.Buffer, target.Length, (PULONG)&target.Length, subname.Buffer, subname.Length); + target_alloc = true; + + Status = utf16_to_utf8(target.Buffer, target.Length, &len, subname.Buffer, subname.Length); if (!NT_SUCCESS(Status)) { ERR("utf16_to_utf8 2 failed with error %08lx\n", Status); ExFreePool(target.Buffer); return Status; }
- for (i = 0; i < target.MaximumLength; i++) { + for (USHORT i = 0; i < target.Length; i++) { if (target.Buffer[i] == '\') target.Buffer[i] = '/'; } + } else if (rdb->ReparseTag == IO_REPARSE_TAG_LX_SYMLINK) { + REPARSE_DATA_BUFFER_LX_SYMLINK* buf; + + if (buflen < offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + rdb->ReparseDataLength) { + WARN("buffer was less than expected length (%lu < %u)\n", buflen, + offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + rdb->ReparseDataLength); + return STATUS_INVALID_PARAMETER; + } + + buf = (REPARSE_DATA_BUFFER_LX_SYMLINK*)rdb->GenericReparseBuffer.DataBuffer; + + if (buflen < offsetof(REPARSE_DATA_BUFFER_LX_SYMLINK, name)) { + WARN("buffer was less than minimum length (%u < %u)\n", rdb->ReparseDataLength, offsetof(REPARSE_DATA_BUFFER_LX_SYMLINK, name)); + return STATUS_INVALID_PARAMETER; + } + + target.Buffer = buf->name; + target.Length = target.MaximumLength = rdb->ReparseDataLength - offsetof(REPARSE_DATA_BUFFER_LX_SYMLINK, name); + } else { + ERR("unexpected reparse tag %08lx\n", rdb->ReparseTag); + return STATUS_INTERNAL_ERROR; + }
- offset.QuadPart = 0; - tlength = target.Length; - Status = write_file2(fcb->Vcb, Irp, offset, target.Buffer, &tlength, false, true, - true, false, false, rollback); + fcb->type = BTRFS_TYPE_SYMLINK; + fcb->inode_item.st_mode &= ~__S_IFMT; + fcb->inode_item.st_mode |= __S_IFLNK; + fcb->inode_item.generation = fcb->Vcb->superblock.generation; // so we don't confuse btrfs send on Linux + + if (fileref && fileref->dc) + fileref->dc->type = fcb->type; + + Status = truncate_file(fcb, 0, Irp, rollback); + if (!NT_SUCCESS(Status)) { + ERR("truncate_file returned %08lx\n", Status); + + if (target_alloc) + ExFreePool(target.Buffer); + + return Status; + } + + offset.QuadPart = 0; + tlength = target.Length; + Status = write_file2(fcb->Vcb, Irp, offset, target.Buffer, &tlength, false, true, + true, false, false, rollback); + + if (target_alloc) ExFreePool(target.Buffer); - } else - Status = STATUS_SUCCESS;
KeQuerySystemTime(&time); win_time_to_unix(time, &now); @@ -298,7 +331,7 @@ NTSTATUS set_reparse_point2(fcb* fcb, REPARSE_DATA_BUFFER* rdb, ULONG buflen, cc
if (fcb->type == BTRFS_TYPE_FILE && ((tag == IO_REPARSE_TAG_SYMLINK && rdb->SymbolicLinkReparseBuffer.Flags & SYMLINK_FLAG_RELATIVE) || tag == IO_REPARSE_TAG_LX_SYMLINK)) { - Status = set_symlink(Irp, fileref, fcb, ccb, rdb, buflen, tag == IO_REPARSE_TAG_SYMLINK, rollback); + Status = set_symlink(Irp, fileref, fcb, ccb, rdb, buflen, rollback); fcb->atts |= FILE_ATTRIBUTE_REPARSE_POINT; } else { LARGE_INTEGER offset, time; diff --git a/drivers/filesystems/btrfs/scrub.c b/drivers/filesystems/btrfs/scrub.c index 40588c2f935..40938a38077 100644 --- a/drivers/filesystems/btrfs/scrub.c +++ b/drivers/filesystems/btrfs/scrub.c @@ -687,7 +687,7 @@ static NTSTATUS scrub_extent_dup(device_extension* Vcb, chunk* c, uint64_t offse log_device_error(Vcb, c->devices[i], BTRFS_DEV_STAT_CORRUPTION_ERRORS); } } else { - Status = check_csum(Vcb, context->stripes[i].buf, context->stripes[i].length / Vcb->superblock.sector_size, csum); + Status = check_csum(Vcb, context->stripes[i].buf, context->stripes[i].length >> Vcb->sector_shift, csum); if (Status == STATUS_CRC_ERROR) { context->stripes[i].csum_error = true; csum_error = true; @@ -741,17 +741,17 @@ static NTSTATUS scrub_extent_dup(device_extension* Vcb, chunk* c, uint64_t offse for (i = 0; i < c->chunk_item->num_stripes; i++) { if (context->stripes[i].csum_error) { if (csum) { - context->stripes[i].bad_csums = ExAllocatePoolWithTag(PagedPool, context->stripes[i].length * Vcb->csum_size / Vcb->superblock.sector_size, ALLOC_TAG); + context->stripes[i].bad_csums = ExAllocatePoolWithTag(PagedPool, (context->stripes[i].length * Vcb->csum_size) >> Vcb->sector_shift, ALLOC_TAG); if (!context->stripes[i].bad_csums) { ERR("out of memory\n"); return STATUS_INSUFFICIENT_RESOURCES; }
- do_calc_job(Vcb, context->stripes[i].buf, context->stripes[i].length / Vcb->superblock.sector_size, context->stripes[i].bad_csums); + do_calc_job(Vcb, context->stripes[i].buf, context->stripes[i].length >> Vcb->sector_shift, context->stripes[i].bad_csums); } else { ULONG j;
- context->stripes[i].bad_csums = ExAllocatePoolWithTag(PagedPool, context->stripes[i].length * Vcb->csum_size / Vcb->superblock.node_size, ALLOC_TAG); + context->stripes[i].bad_csums = ExAllocatePoolWithTag(PagedPool, (context->stripes[i].length * Vcb->csum_size) >> Vcb->sector_shift, ALLOC_TAG); if (!context->stripes[i].bad_csums) { ERR("out of memory\n"); return STATUS_INSUFFICIENT_RESOURCES; @@ -784,9 +784,9 @@ static NTSTATUS scrub_extent_dup(device_extension* Vcb, chunk* c, uint64_t offse ULONG j;
if (csum) { - for (j = 0; j < context->stripes[i].length / Vcb->superblock.sector_size; j++) { + for (j = 0; j < context->stripes[i].length >> Vcb->sector_shift; j++) { if (RtlCompareMemory((uint8_t*)context->stripes[i].bad_csums + (j * Vcb->csum_size), (uint8_t*)csum + (j + Vcb->csum_size), Vcb->csum_size) != Vcb->csum_size) { - uint64_t addr = offset + UInt32x32To64(j, Vcb->superblock.sector_size); + uint64_t addr = offset + ((uint64_t)j << Vcb->sector_shift);
log_error(Vcb, addr, c->devices[i]->devitem.dev_id, false, true, false); log_device_error(Vcb, c->devices[i], BTRFS_DEV_STAT_CORRUPTION_ERRORS); @@ -827,14 +827,12 @@ static NTSTATUS scrub_extent_dup(device_extension* Vcb, chunk* c, uint64_t offse // if csum errors on all stripes, check sector by sector
for (i = 0; i < c->chunk_item->num_stripes; i++) { - ULONG j; - if (c->devices[i]->devobj) { if (csum) { - for (j = 0; j < context->stripes[i].length / Vcb->superblock.sector_size; j++) { + for (ULONG j = 0; j < context->stripes[i].length >> Vcb->sector_shift; j++) { if (RtlCompareMemory((uint8_t*)context->stripes[i].bad_csums + (j * Vcb->csum_size), (uint8_t*)csum + (j * Vcb->csum_size), Vcb->csum_size) != Vcb->csum_size) { ULONG k; - uint64_t addr = offset + UInt32x32To64(j, Vcb->superblock.sector_size); + uint64_t addr = offset + ((uint64_t)j << Vcb->sector_shift); bool recovered = false;
for (k = 0; k < c->chunk_item->num_stripes; k++) { @@ -844,8 +842,8 @@ static NTSTATUS scrub_extent_dup(device_extension* Vcb, chunk* c, uint64_t offse log_error(Vcb, addr, c->devices[i]->devitem.dev_id, false, true, false); log_device_error(Vcb, c->devices[i], BTRFS_DEV_STAT_CORRUPTION_ERRORS);
- RtlCopyMemory(context->stripes[i].buf + (j * Vcb->superblock.sector_size), - context->stripes[k].buf + (j * Vcb->superblock.sector_size), Vcb->superblock.sector_size); + RtlCopyMemory(context->stripes[i].buf + (j << Vcb->sector_shift), + context->stripes[k].buf + (j << Vcb->sector_shift), Vcb->superblock.sector_size);
recovered = true; break; @@ -859,7 +857,7 @@ static NTSTATUS scrub_extent_dup(device_extension* Vcb, chunk* c, uint64_t offse } } } else { - for (j = 0; j < context->stripes[i].length / Vcb->superblock.node_size; j++) { + for (ULONG j = 0; j < context->stripes[i].length / Vcb->superblock.node_size; j++) { tree_header* th = (tree_header*)&context->stripes[i].buf[j * Vcb->superblock.node_size]; uint64_t addr = offset + UInt32x32To64(j, Vcb->superblock.node_size);
@@ -915,9 +913,9 @@ static NTSTATUS scrub_extent_dup(device_extension* Vcb, chunk* c, uint64_t offse ULONG j;
if (csum) { - for (j = 0; j < context->stripes[i].length / Vcb->superblock.sector_size; j++) { + for (j = 0; j < context->stripes[i].length >> Vcb->sector_shift; j++) { if (RtlCompareMemory((uint8_t*)context->stripes[i].bad_csums + (j * Vcb->csum_size), (uint8_t*)csum + (j + Vcb->csum_size), Vcb->csum_size) != Vcb->csum_size) { - uint64_t addr = offset + UInt32x32To64(j, Vcb->superblock.sector_size); + uint64_t addr = offset + ((uint64_t)j << Vcb->sector_shift);
log_error(Vcb, addr, c->devices[i]->devitem.dev_id, false, false, false); } @@ -962,7 +960,7 @@ static NTSTATUS scrub_extent_raid0(device_extension* Vcb, chunk* c, uint64_t off
if (csum) { for (j = 0; j < readlen; j += Vcb->superblock.sector_size) { - if (!check_sector_csum(Vcb, context->stripes[stripe].buf + stripeoff[stripe], (uint8_t*)csum + (pos * Vcb->csum_size / Vcb->superblock.sector_size))) { + if (!check_sector_csum(Vcb, context->stripes[stripe].buf + stripeoff[stripe], (uint8_t*)csum + ((pos * Vcb->csum_size) >> Vcb->sector_shift))) { uint64_t addr = offset + pos;
log_error(Vcb, addr, c->devices[stripe]->devitem.dev_id, false, false, false); @@ -1039,7 +1037,7 @@ static NTSTATUS scrub_extent_raid10(device_extension* Vcb, chunk* c, uint64_t of } else { for (j = 0; j < readlen; j += Vcb->superblock.sector_size) { if (!check_sector_csum(Vcb, context->stripes[(stripe * sub_stripes) + k].buf + stripeoff[stripe] + j, - (uint8_t*)csum + ((pos + j) * Vcb->csum_size / Vcb->superblock.sector_size))) { + (uint8_t*)csum + (((pos + j) * Vcb->csum_size) >> Vcb->sector_shift))) { csum_error = true; context->stripes[(stripe * sub_stripes) + k].csum_error = true; log_device_error(Vcb, c->devices[(stripe * sub_stripes) + k], BTRFS_DEV_STAT_CORRUPTION_ERRORS); @@ -1204,7 +1202,7 @@ static NTSTATUS scrub_extent_raid10(device_extension* Vcb, chunk* c, uint64_t of if (csum) { for (k = 0; k < sub_stripes; k++) { if (c->devices[j + k]->devobj) { - context->stripes[j + k].bad_csums = ExAllocatePoolWithTag(PagedPool, context->stripes[j + k].length * Vcb->csum_size / Vcb->superblock.sector_size, + context->stripes[j + k].bad_csums = ExAllocatePoolWithTag(PagedPool, (context->stripes[j + k].length * Vcb->csum_size) >> Vcb->sector_shift, ALLOC_TAG); if (!context->stripes[j + k].bad_csums) { ERR("out of memory\n"); @@ -1212,7 +1210,7 @@ static NTSTATUS scrub_extent_raid10(device_extension* Vcb, chunk* c, uint64_t of goto end; }
- do_calc_job(Vcb, context->stripes[j + k].buf, context->stripes[j + k].length / Vcb->superblock.sector_size, context->stripes[j + k].bad_csums); + do_calc_job(Vcb, context->stripes[j + k].buf, context->stripes[j + k].length >> Vcb->sector_shift, context->stripes[j + k].bad_csums); } } } else { @@ -1259,8 +1257,8 @@ static NTSTATUS scrub_extent_raid10(device_extension* Vcb, chunk* c, uint64_t of goodstripe = 0xffffffff; for (k = 0; k < sub_stripes; k++) { if (c->devices[j + k]->devobj) { - if (RtlCompareMemory((uint8_t*)context->stripes[j + k].bad_csums + (so * Vcb->csum_size / Vcb->superblock.sector_size), - (uint8_t*)csum + (pos * Vcb->csum_size / Vcb->superblock.sector_size), + if (RtlCompareMemory((uint8_t*)context->stripes[j + k].bad_csums + ((so * Vcb->csum_size) >> Vcb->sector_shift), + (uint8_t*)csum + ((pos * Vcb->csum_size) >> Vcb->sector_shift), Vcb->csum_size) != Vcb->csum_size) { has_error = true; } else @@ -1272,8 +1270,8 @@ static NTSTATUS scrub_extent_raid10(device_extension* Vcb, chunk* c, uint64_t of if (goodstripe != 0xffffffff) { for (k = 0; k < sub_stripes; k++) { if (c->devices[j + k]->devobj && - RtlCompareMemory((uint8_t*)context->stripes[j + k].bad_csums + (so * Vcb->csum_size / Vcb->superblock.sector_size), - (uint8_t*)csum + (pos * Vcb->csum_size / Vcb->superblock.sector_size), + RtlCompareMemory((uint8_t*)context->stripes[j + k].bad_csums + ((so * Vcb->csum_size) >> Vcb->sector_shift), + (uint8_t*)csum + ((pos * Vcb->csum_size) >> Vcb->sector_shift), Vcb->csum_size) != Vcb->csum_size) { uint64_t addr = offset + pos;
@@ -1644,13 +1642,13 @@ static NTSTATUS scrub_data_extent(device_extension* Vcb, chunk* c, uint64_t offs do { ULONG rl;
- if (runlength * Vcb->superblock.sector_size > SCRUB_UNIT) - rl = SCRUB_UNIT / Vcb->superblock.sector_size; + if (runlength << Vcb->sector_shift > SCRUB_UNIT) + rl = SCRUB_UNIT >> Vcb->sector_shift; else rl = runlength;
- Status = scrub_extent(Vcb, c, type, offset + UInt32x32To64(index, Vcb->superblock.sector_size), - rl * Vcb->superblock.sector_size, (uint8_t*)csum + (index * Vcb->csum_size)); + Status = scrub_extent(Vcb, c, type, offset + ((uint64_t)index << Vcb->sector_shift), + rl << Vcb->sector_shift, (uint8_t*)csum + (index * Vcb->csum_size)); if (!NT_SUCCESS(Status)) { ERR("scrub_data_extent_dup returned %08lx\n", Status); return Status; @@ -1707,7 +1705,7 @@ static NTSTATUS __stdcall scrub_read_completion_raid56(PDEVICE_OBJECT DeviceObje
static void scrub_raid5_stripe(device_extension* Vcb, chunk* c, scrub_context_raid56* context, uint64_t stripe_start, uint64_t bit_start, uint64_t num, uint16_t missing_devices) { - ULONG sectors_per_stripe = (ULONG)(c->chunk_item->stripe_length / Vcb->superblock.sector_size), i, off; + ULONG sectors_per_stripe = (ULONG)(c->chunk_item->stripe_length >> Vcb->sector_shift), off; uint16_t stripe, parity = (bit_start + num + c->chunk_item->num_stripes - 1) % c->chunk_item->num_stripes; uint64_t stripeoff;
@@ -1721,32 +1719,32 @@ static void scrub_raid5_stripe(device_extension* Vcb, chunk* c, scrub_context_ra while (stripe != parity) { RtlClearAllBits(&context->stripes[stripe].error);
- for (i = 0; i < sectors_per_stripe; i++) { + for (ULONG i = 0; i < sectors_per_stripe; i++) { if (c->devices[stripe]->devobj && RtlCheckBit(&context->alloc, off)) { if (RtlCheckBit(&context->is_tree, off)) { - tree_header* th = (tree_header*)&context->stripes[stripe].buf[stripeoff * Vcb->superblock.sector_size]; - uint64_t addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 1) * c->chunk_item->stripe_length) + (off * Vcb->superblock.sector_size); + tree_header* th = (tree_header*)&context->stripes[stripe].buf[stripeoff << Vcb->sector_shift]; + uint64_t addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 1) * c->chunk_item->stripe_length) + (off << Vcb->sector_shift);
if (!check_tree_checksum(Vcb, th) || th->address != addr) { - RtlSetBits(&context->stripes[stripe].error, i, Vcb->superblock.node_size / Vcb->superblock.sector_size); + RtlSetBits(&context->stripes[stripe].error, i, Vcb->superblock.node_size >> Vcb->sector_shift); log_device_error(Vcb, c->devices[stripe], BTRFS_DEV_STAT_CORRUPTION_ERRORS);
if (missing_devices > 0) log_error(Vcb, addr, c->devices[stripe]->devitem.dev_id, true, false, false); }
- off += Vcb->superblock.node_size / Vcb->superblock.sector_size; - stripeoff += Vcb->superblock.node_size / Vcb->superblock.sector_size; - i += (Vcb->superblock.node_size / Vcb->superblock.sector_size) - 1; + off += Vcb->superblock.node_size >> Vcb->sector_shift; + stripeoff += Vcb->superblock.node_size >> Vcb->sector_shift; + i += (Vcb->superblock.node_size >> Vcb->sector_shift) - 1;
continue; } else if (RtlCheckBit(&context->has_csum, off)) { - if (!check_sector_csum(Vcb, context->stripes[stripe].buf + (stripeoff * Vcb->superblock.sector_size), (uint8_t*)context->csum + (Vcb->csum_size * off))) { + if (!check_sector_csum(Vcb, context->stripes[stripe].buf + (stripeoff << Vcb->sector_shift), (uint8_t*)context->csum + (Vcb->csum_size * off))) { RtlSetBit(&context->stripes[stripe].error, i); log_device_error(Vcb, c->devices[stripe], BTRFS_DEV_STAT_CORRUPTION_ERRORS);
if (missing_devices > 0) { - uint64_t addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 1) * c->chunk_item->stripe_length) + (off * Vcb->superblock.sector_size); + uint64_t addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 1) * c->chunk_item->stripe_length) + (off << Vcb->sector_shift);
log_error(Vcb, addr, c->devices[stripe]->devitem.dev_id, false, false, false); } @@ -1770,10 +1768,10 @@ static void scrub_raid5_stripe(device_extension* Vcb, chunk* c, scrub_context_ra if (missing_devices == 0) { RtlClearAllBits(&context->stripes[parity].error);
- for (i = 0; i < sectors_per_stripe; i++) { + for (ULONG i = 0; i < sectors_per_stripe; i++) { ULONG o, j;
- o = i * Vcb->superblock.sector_size; + o = i << Vcb->sector_shift; for (j = 0; j < Vcb->superblock.sector_size; j++) { // FIXME - use SSE if (context->parity_scratch[o] != 0) { RtlSetBit(&context->stripes[parity].error, i); @@ -1789,7 +1787,7 @@ static void scrub_raid5_stripe(device_extension* Vcb, chunk* c, scrub_context_ra if (missing_devices > 0) return;
- for (i = 0; i < sectors_per_stripe; i++) { + for (ULONG i = 0; i < sectors_per_stripe; i++) { ULONG num_errors = 0, bad_off; uint64_t bad_stripe; bool alloc = false; @@ -1821,36 +1819,36 @@ static void scrub_raid5_stripe(device_extension* Vcb, chunk* c, scrub_context_ra if (num_errors == 0 && RtlCheckBit(&context->stripes[parity].error, i)) { // parity error uint64_t addr;
- do_xor(&context->stripes[parity].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->parity_scratch[i * Vcb->superblock.sector_size], + do_xor(&context->stripes[parity].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->parity_scratch[i << Vcb->sector_shift], Vcb->superblock.sector_size);
bad_off = (ULONG)((bit_start + num - stripe_start) * sectors_per_stripe * (c->chunk_item->num_stripes - 1)) + i; - addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 1) * c->chunk_item->stripe_length) + (bad_off * Vcb->superblock.sector_size); + addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 1) * c->chunk_item->stripe_length) + (bad_off << Vcb->sector_shift);
context->stripes[parity].rewrite = true;
log_error(Vcb, addr, c->devices[parity]->devitem.dev_id, false, true, true); log_device_error(Vcb, c->devices[parity], BTRFS_DEV_STAT_CORRUPTION_ERRORS); } else if (num_errors == 1) { - uint64_t addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 1) * c->chunk_item->stripe_length) + (bad_off * Vcb->superblock.sector_size); + uint64_t addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 1) * c->chunk_item->stripe_length) + (bad_off << Vcb->sector_shift);
if (RtlCheckBit(&context->is_tree, bad_off)) { tree_header* th;
- do_xor(&context->parity_scratch[i * Vcb->superblock.sector_size], - &context->stripes[bad_stripe].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], + do_xor(&context->parity_scratch[i << Vcb->sector_shift], + &context->stripes[bad_stripe].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], Vcb->superblock.node_size);
- th = (tree_header*)&context->parity_scratch[i * Vcb->superblock.sector_size]; + th = (tree_header*)&context->parity_scratch[i << Vcb->sector_shift];
if (check_tree_checksum(Vcb, th) && th->address == addr) { - RtlCopyMemory(&context->stripes[bad_stripe].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->parity_scratch[i * Vcb->superblock.sector_size], Vcb->superblock.node_size); + RtlCopyMemory(&context->stripes[bad_stripe].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->parity_scratch[i << Vcb->sector_shift], Vcb->superblock.node_size);
context->stripes[bad_stripe].rewrite = true;
- RtlClearBits(&context->stripes[bad_stripe].error, i + 1, (Vcb->superblock.node_size / Vcb->superblock.sector_size) - 1); + RtlClearBits(&context->stripes[bad_stripe].error, i + 1, (Vcb->superblock.node_size >> Vcb->sector_shift) - 1);
log_error(Vcb, addr, c->devices[bad_stripe]->devitem.dev_id, true, true, false); } else @@ -1858,15 +1856,15 @@ static void scrub_raid5_stripe(device_extension* Vcb, chunk* c, scrub_context_ra } else { uint8_t hash[MAX_HASH_SIZE];
- do_xor(&context->parity_scratch[i * Vcb->superblock.sector_size], - &context->stripes[bad_stripe].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], + do_xor(&context->parity_scratch[i << Vcb->sector_shift], + &context->stripes[bad_stripe].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], Vcb->superblock.sector_size);
- get_sector_csum(Vcb, &context->parity_scratch[i * Vcb->superblock.sector_size], hash); + get_sector_csum(Vcb, &context->parity_scratch[i << Vcb->sector_shift], hash);
if (RtlCompareMemory(hash, (uint8_t*)context->csum + (Vcb->csum_size * bad_off), Vcb->csum_size) == Vcb->csum_size) { - RtlCopyMemory(&context->stripes[bad_stripe].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->parity_scratch[i * Vcb->superblock.sector_size], Vcb->superblock.sector_size); + RtlCopyMemory(&context->stripes[bad_stripe].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->parity_scratch[i << Vcb->sector_shift], Vcb->superblock.sector_size);
context->stripes[bad_stripe].rewrite = true;
@@ -1881,7 +1879,7 @@ static void scrub_raid5_stripe(device_extension* Vcb, chunk* c, scrub_context_ra while (stripe != parity) { if (RtlCheckBit(&context->alloc, off)) { if (RtlCheckBit(&context->stripes[stripe].error, i)) { - uint64_t addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 1) * c->chunk_item->stripe_length) + (off * Vcb->superblock.sector_size); + uint64_t addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 1) * c->chunk_item->stripe_length) + (off << Vcb->sector_shift);
log_error(Vcb, addr, c->devices[stripe]->devitem.dev_id, RtlCheckBit(&context->is_tree, off), false, false); } @@ -1896,7 +1894,7 @@ static void scrub_raid5_stripe(device_extension* Vcb, chunk* c, scrub_context_ra
static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_raid56* context, uint64_t stripe_start, uint64_t bit_start, uint64_t num, uint16_t missing_devices) { - ULONG sectors_per_stripe = (ULONG)(c->chunk_item->stripe_length / Vcb->superblock.sector_size), i, off; + ULONG sectors_per_stripe = (ULONG)(c->chunk_item->stripe_length >> Vcb->sector_shift), off; uint16_t stripe, parity1 = (bit_start + num + c->chunk_item->num_stripes - 2) % c->chunk_item->num_stripes; uint16_t parity2 = (parity1 + 1) % c->chunk_item->num_stripes; uint64_t stripeoff; @@ -1914,32 +1912,32 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra while (stripe != parity1) { RtlClearAllBits(&context->stripes[stripe].error);
- for (i = 0; i < sectors_per_stripe; i++) { + for (ULONG i = 0; i < sectors_per_stripe; i++) { if (c->devices[stripe]->devobj && RtlCheckBit(&context->alloc, off)) { if (RtlCheckBit(&context->is_tree, off)) { - tree_header* th = (tree_header*)&context->stripes[stripe].buf[stripeoff * Vcb->superblock.sector_size]; - uint64_t addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 2) * c->chunk_item->stripe_length) + (off * Vcb->superblock.sector_size); + tree_header* th = (tree_header*)&context->stripes[stripe].buf[stripeoff << Vcb->sector_shift]; + uint64_t addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 2) * c->chunk_item->stripe_length) + (off << Vcb->sector_shift);
if (!check_tree_checksum(Vcb, th) || th->address != addr) { - RtlSetBits(&context->stripes[stripe].error, i, Vcb->superblock.node_size / Vcb->superblock.sector_size); + RtlSetBits(&context->stripes[stripe].error, i, Vcb->superblock.node_size >> Vcb->sector_shift); log_device_error(Vcb, c->devices[stripe], BTRFS_DEV_STAT_CORRUPTION_ERRORS);
if (missing_devices == 2) log_error(Vcb, addr, c->devices[stripe]->devitem.dev_id, true, false, false); }
- off += Vcb->superblock.node_size / Vcb->superblock.sector_size; - stripeoff += Vcb->superblock.node_size / Vcb->superblock.sector_size; - i += (Vcb->superblock.node_size / Vcb->superblock.sector_size) - 1; + off += Vcb->superblock.node_size >> Vcb->sector_shift; + stripeoff += Vcb->superblock.node_size >> Vcb->sector_shift; + i += (Vcb->superblock.node_size >> Vcb->sector_shift) - 1;
continue; } else if (RtlCheckBit(&context->has_csum, off)) { uint8_t hash[MAX_HASH_SIZE];
- get_sector_csum(Vcb, context->stripes[stripe].buf + (stripeoff * Vcb->superblock.sector_size), hash); + get_sector_csum(Vcb, context->stripes[stripe].buf + (stripeoff << Vcb->sector_shift), hash);
if (RtlCompareMemory(hash, (uint8_t*)context->csum + (Vcb->csum_size * off), Vcb->csum_size) != Vcb->csum_size) { - uint64_t addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 2) * c->chunk_item->stripe_length) + (off * Vcb->superblock.sector_size); + uint64_t addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 2) * c->chunk_item->stripe_length) + (off << Vcb->sector_shift);
RtlSetBit(&context->stripes[stripe].error, i); log_device_error(Vcb, c->devices[stripe], BTRFS_DEV_STAT_CORRUPTION_ERRORS); @@ -1966,10 +1964,10 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra if (missing_devices == 0 || (missing_devices == 1 && !c->devices[parity2]->devobj)) { // check parity 1
- for (i = 0; i < sectors_per_stripe; i++) { + for (ULONG i = 0; i < sectors_per_stripe; i++) { ULONG o, j;
- o = i * Vcb->superblock.sector_size; + o = i << Vcb->sector_shift; for (j = 0; j < Vcb->superblock.sector_size; j++) { // FIXME - use SSE if (context->parity_scratch[o] != 0) { RtlSetBit(&context->stripes[parity1].error, i); @@ -1994,9 +1992,9 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra stripe = stripe == 0 ? (c->chunk_item->num_stripes - 1) : (stripe - 1); }
- for (i = 0; i < sectors_per_stripe; i++) { - if (RtlCompareMemory(&context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->parity_scratch2[i * Vcb->superblock.sector_size], Vcb->superblock.sector_size) != Vcb->superblock.sector_size) + for (ULONG i = 0; i < sectors_per_stripe; i++) { + if (RtlCompareMemory(&context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->parity_scratch2[i << Vcb->sector_shift], Vcb->superblock.sector_size) != Vcb->superblock.sector_size) RtlSetBit(&context->stripes[parity2].error, i); } } @@ -2006,7 +2004,7 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra
// log and fix errors
- for (i = 0; i < sectors_per_stripe; i++) { + for (ULONG i = 0; i < sectors_per_stripe; i++) { ULONG num_errors = 0; uint64_t bad_stripe1, bad_stripe2; ULONG bad_off1, bad_off2; @@ -2045,12 +2043,12 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra uint64_t addr;
if (RtlCheckBit(&context->stripes[parity1].error, i)) { - do_xor(&context->stripes[parity1].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->parity_scratch[i * Vcb->superblock.sector_size], + do_xor(&context->stripes[parity1].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->parity_scratch[i << Vcb->sector_shift], Vcb->superblock.sector_size);
bad_off1 = (ULONG)((bit_start + num - stripe_start) * sectors_per_stripe * (c->chunk_item->num_stripes - 2)) + i; - addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 2) * c->chunk_item->stripe_length) + (bad_off1 * Vcb->superblock.sector_size); + addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 2) * c->chunk_item->stripe_length) + (bad_off1 << Vcb->sector_shift);
context->stripes[parity1].rewrite = true;
@@ -2059,12 +2057,12 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra }
if (RtlCheckBit(&context->stripes[parity2].error, i)) { - RtlCopyMemory(&context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->parity_scratch2[i * Vcb->superblock.sector_size], + RtlCopyMemory(&context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->parity_scratch2[i << Vcb->sector_shift], Vcb->superblock.sector_size);
bad_off1 = (ULONG)((bit_start + num - stripe_start) * sectors_per_stripe * (c->chunk_item->num_stripes - 2)) + i; - addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 2) * c->chunk_item->stripe_length) + (bad_off1 * Vcb->superblock.sector_size); + addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 2) * c->chunk_item->stripe_length) + (bad_off1 << Vcb->sector_shift);
context->stripes[parity2].rewrite = true;
@@ -2074,10 +2072,10 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra } else if (num_errors == 1) { uint32_t len; uint16_t stripe_num, bad_stripe_num; - uint64_t addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 2) * c->chunk_item->stripe_length) + (bad_off1 * Vcb->superblock.sector_size); + uint64_t addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 2) * c->chunk_item->stripe_length) + (bad_off1 << Vcb->sector_shift); uint8_t* scratch;
- len = RtlCheckBit(&context->is_tree, bad_off1)? Vcb->superblock.node_size : Vcb->superblock.sector_size; + len = RtlCheckBit(&context->is_tree, bad_off1) ? Vcb->superblock.node_size : Vcb->superblock.sector_size;
scratch = ExAllocatePoolWithTag(PagedPool, len, ALLOC_TAG); if (!scratch) { @@ -2087,8 +2085,8 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra
RtlZeroMemory(scratch, len);
- do_xor(&context->parity_scratch[i * Vcb->superblock.sector_size], - &context->stripes[bad_stripe1].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], len); + do_xor(&context->parity_scratch[i << Vcb->sector_shift], + &context->stripes[bad_stripe1].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], len);
stripe = parity1 == 0 ? (c->chunk_item->num_stripes - 1) : (parity1 - 1);
@@ -2098,7 +2096,7 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra galois_double(scratch, len);
if (stripe != bad_stripe1) - do_xor(scratch, &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], len); + do_xor(scratch, &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], len); else bad_stripe_num = stripe_num;
@@ -2106,7 +2104,7 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra stripe_num--; }
- do_xor(scratch, &context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], len); + do_xor(scratch, &context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], len);
if (bad_stripe_num != 0) galois_divpower(scratch, (uint8_t)bad_stripe_num, len); @@ -2118,7 +2116,7 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra tree_header *th1 = NULL, *th2 = NULL;
if (c->devices[parity1]->devobj) { - th1 = (tree_header*)&context->parity_scratch[i * Vcb->superblock.sector_size]; + th1 = (tree_header*)&context->parity_scratch[i << Vcb->sector_shift]; get_tree_checksum(Vcb, th1, hash1); }
@@ -2130,7 +2128,7 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra if ((c->devices[parity1]->devobj && RtlCompareMemory(hash1, th1, Vcb->csum_size) == Vcb->csum_size && th1->address == addr) || (c->devices[parity2]->devobj && RtlCompareMemory(hash2, th2, Vcb->csum_size) == Vcb->csum_size && th2->address == addr)) { if (!c->devices[parity1]->devobj || RtlCompareMemory(hash1, th1, Vcb->csum_size) != Vcb->csum_size || th1->address != addr) { - RtlCopyMemory(&context->stripes[bad_stripe1].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], + RtlCopyMemory(&context->stripes[bad_stripe1].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], scratch, Vcb->superblock.node_size);
if (c->devices[parity1]->devobj) { @@ -2138,15 +2136,15 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra
stripe = (parity1 + 2) % c->chunk_item->num_stripes;
- RtlCopyMemory(&context->stripes[parity1].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], + RtlCopyMemory(&context->stripes[parity1].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], Vcb->superblock.node_size);
stripe = (stripe + 1) % c->chunk_item->num_stripes;
while (stripe != parity1) { - do_xor(&context->stripes[parity1].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], + do_xor(&context->stripes[parity1].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], Vcb->superblock.node_size);
stripe = (stripe + 1) % c->chunk_item->num_stripes; @@ -2158,26 +2156,26 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra log_device_error(Vcb, c->devices[parity1], BTRFS_DEV_STAT_CORRUPTION_ERRORS); } } else { - RtlCopyMemory(&context->stripes[bad_stripe1].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->parity_scratch[i * Vcb->superblock.sector_size], Vcb->superblock.node_size); + RtlCopyMemory(&context->stripes[bad_stripe1].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->parity_scratch[i << Vcb->sector_shift], Vcb->superblock.node_size);
if (!c->devices[parity2]->devobj || RtlCompareMemory(hash2, th2, Vcb->csum_size) != Vcb->csum_size || th2->address != addr) { // fix parity 2 stripe = parity1 == 0 ? (c->chunk_item->num_stripes - 1) : (parity1 - 1);
if (c->devices[parity2]->devobj) { - RtlCopyMemory(&context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - Vcb->superblock.node_size); + RtlCopyMemory(&context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + Vcb->superblock.node_size);
stripe = stripe == 0 ? (c->chunk_item->num_stripes - 1) : (stripe - 1);
while (stripe != parity2) { - galois_double(&context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], Vcb->superblock.node_size); + galois_double(&context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], Vcb->superblock.node_size);
- do_xor(&context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - Vcb->superblock.node_size); + do_xor(&context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + Vcb->superblock.node_size);
stripe = stripe == 0 ? (c->chunk_item->num_stripes - 1) : (stripe - 1); } @@ -2192,7 +2190,7 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra
context->stripes[bad_stripe1].rewrite = true;
- RtlClearBits(&context->stripes[bad_stripe1].error, i + 1, (Vcb->superblock.node_size / Vcb->superblock.sector_size) - 1); + RtlClearBits(&context->stripes[bad_stripe1].error, i + 1, (Vcb->superblock.node_size >> Vcb->sector_shift) - 1);
log_error(Vcb, addr, c->devices[bad_stripe1]->devitem.dev_id, true, true, false); } else @@ -2202,7 +2200,7 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra uint8_t hash2[MAX_HASH_SIZE];
if (c->devices[parity1]->devobj) - get_sector_csum(Vcb, &context->parity_scratch[i * Vcb->superblock.sector_size], hash1); + get_sector_csum(Vcb, &context->parity_scratch[i << Vcb->sector_shift], hash1);
if (c->devices[parity2]->devobj) get_sector_csum(Vcb, scratch, hash2); @@ -2210,7 +2208,7 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra if ((c->devices[parity1]->devobj && RtlCompareMemory(hash1, (uint8_t*)context->csum + (bad_off1 * Vcb->csum_size), Vcb->csum_size) == Vcb->csum_size) || (c->devices[parity2]->devobj && RtlCompareMemory(hash2, (uint8_t*)context->csum + (bad_off1 * Vcb->csum_size), Vcb->csum_size) == Vcb->csum_size)) { if (c->devices[parity2]->devobj && RtlCompareMemory(hash2, (uint8_t*)context->csum + (bad_off1 * Vcb->csum_size), Vcb->csum_size) == Vcb->csum_size) { - RtlCopyMemory(&context->stripes[bad_stripe1].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], + RtlCopyMemory(&context->stripes[bad_stripe1].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], scratch, Vcb->superblock.sector_size);
if (c->devices[parity1]->devobj && RtlCompareMemory(hash1, (uint8_t*)context->csum + (bad_off1 * Vcb->csum_size), Vcb->csum_size) != Vcb->csum_size) { @@ -2218,16 +2216,16 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra
stripe = (parity1 + 2) % c->chunk_item->num_stripes;
- RtlCopyMemory(&context->stripes[parity1].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], + RtlCopyMemory(&context->stripes[parity1].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], Vcb->superblock.sector_size);
stripe = (stripe + 1) % c->chunk_item->num_stripes;
while (stripe != parity1) { - do_xor(&context->stripes[parity1].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - Vcb->superblock.sector_size); + do_xor(&context->stripes[parity1].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + Vcb->superblock.sector_size);
stripe = (stripe + 1) % c->chunk_item->num_stripes; } @@ -2238,24 +2236,24 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra log_device_error(Vcb, c->devices[parity1], BTRFS_DEV_STAT_CORRUPTION_ERRORS); } } else { - RtlCopyMemory(&context->stripes[bad_stripe1].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->parity_scratch[i * Vcb->superblock.sector_size], Vcb->superblock.sector_size); + RtlCopyMemory(&context->stripes[bad_stripe1].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->parity_scratch[i << Vcb->sector_shift], Vcb->superblock.sector_size);
if (c->devices[parity2]->devobj && RtlCompareMemory(hash2, (uint8_t*)context->csum + (bad_off1 * Vcb->csum_size), Vcb->csum_size) != Vcb->csum_size) { // fix parity 2 stripe = parity1 == 0 ? (c->chunk_item->num_stripes - 1) : (parity1 - 1);
- RtlCopyMemory(&context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - Vcb->superblock.sector_size); + RtlCopyMemory(&context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + Vcb->superblock.sector_size);
stripe = stripe == 0 ? (c->chunk_item->num_stripes - 1) : (stripe - 1);
while (stripe != parity2) { - galois_double(&context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], Vcb->superblock.sector_size); + galois_double(&context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], Vcb->superblock.sector_size);
- do_xor(&context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], + do_xor(&context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], Vcb->superblock.sector_size);
stripe = stripe == 0 ? (c->chunk_item->num_stripes - 1) : (stripe - 1); @@ -2290,31 +2288,31 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra
k = c->chunk_item->num_stripes - 3; if (stripe == bad_stripe1 || stripe == bad_stripe2) { - RtlZeroMemory(&context->parity_scratch[i * Vcb->superblock.sector_size], len); - RtlZeroMemory(&context->parity_scratch2[i * Vcb->superblock.sector_size], len); + RtlZeroMemory(&context->parity_scratch[i << Vcb->sector_shift], len); + RtlZeroMemory(&context->parity_scratch2[i << Vcb->sector_shift], len);
if (stripe == bad_stripe1) x = k; else y = k; } else { - RtlCopyMemory(&context->parity_scratch[i * Vcb->superblock.sector_size], - &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], len); - RtlCopyMemory(&context->parity_scratch2[i * Vcb->superblock.sector_size], - &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], len); + RtlCopyMemory(&context->parity_scratch[i << Vcb->sector_shift], + &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], len); + RtlCopyMemory(&context->parity_scratch2[i << Vcb->sector_shift], + &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], len); }
stripe = stripe == 0 ? (c->chunk_item->num_stripes - 1) : (stripe - 1);
k--; do { - galois_double(&context->parity_scratch[i * Vcb->superblock.sector_size], len); + galois_double(&context->parity_scratch[i << Vcb->sector_shift], len);
if (stripe != bad_stripe1 && stripe != bad_stripe2) { - do_xor(&context->parity_scratch[i * Vcb->superblock.sector_size], - &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], len); - do_xor(&context->parity_scratch2[i * Vcb->superblock.sector_size], - &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], len); + do_xor(&context->parity_scratch[i << Vcb->sector_shift], + &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], len); + do_xor(&context->parity_scratch2[i << Vcb->sector_shift], + &context->stripes[stripe].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], len); } else if (stripe == bad_stripe1) x = k; else if (stripe == bad_stripe2) @@ -2331,10 +2329,10 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra a = gmul(gyx, denom); b = gmul(gx, denom);
- p = &context->stripes[parity1].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)]; - q = &context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)]; - pxy = &context->parity_scratch2[i * Vcb->superblock.sector_size]; - qxy = &context->parity_scratch[i * Vcb->superblock.sector_size]; + p = &context->stripes[parity1].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)]; + q = &context->stripes[parity2].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)]; + pxy = &context->parity_scratch2[i << Vcb->sector_shift]; + qxy = &context->parity_scratch[i << Vcb->sector_shift];
for (j = 0; j < len; j++) { *qxy = gmul(a, *p ^ *pxy) ^ gmul(b, *q ^ *qxy); @@ -2345,29 +2343,29 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra qxy++; }
- do_xor(&context->parity_scratch2[i * Vcb->superblock.sector_size], &context->parity_scratch[i * Vcb->superblock.sector_size], len); - do_xor(&context->parity_scratch2[i * Vcb->superblock.sector_size], &context->stripes[parity1].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], len); + do_xor(&context->parity_scratch2[i << Vcb->sector_shift], &context->parity_scratch[i << Vcb->sector_shift], len); + do_xor(&context->parity_scratch2[i << Vcb->sector_shift], &context->stripes[parity1].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], len);
- addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 2) * c->chunk_item->stripe_length) + (bad_off1 * Vcb->superblock.sector_size); + addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 2) * c->chunk_item->stripe_length) + (bad_off1 << Vcb->sector_shift);
if (RtlCheckBit(&context->is_tree, bad_off1)) { - tree_header* th = (tree_header*)&context->parity_scratch[i * Vcb->superblock.sector_size]; + tree_header* th = (tree_header*)&context->parity_scratch[i << Vcb->sector_shift];
if (check_tree_checksum(Vcb, th) && th->address == addr) { - RtlCopyMemory(&context->stripes[bad_stripe1].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->parity_scratch[i * Vcb->superblock.sector_size], Vcb->superblock.node_size); + RtlCopyMemory(&context->stripes[bad_stripe1].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->parity_scratch[i << Vcb->sector_shift], Vcb->superblock.node_size);
context->stripes[bad_stripe1].rewrite = true;
- RtlClearBits(&context->stripes[bad_stripe1].error, i + 1, (Vcb->superblock.node_size / Vcb->superblock.sector_size) - 1); + RtlClearBits(&context->stripes[bad_stripe1].error, i + 1, (Vcb->superblock.node_size >> Vcb->sector_shift) - 1);
log_error(Vcb, addr, c->devices[bad_stripe1]->devitem.dev_id, true, true, false); } else log_error(Vcb, addr, c->devices[bad_stripe1]->devitem.dev_id, true, false, false); } else { - if (check_sector_csum(Vcb, &context->parity_scratch[i * Vcb->superblock.sector_size], (uint8_t*)context->csum + (Vcb->csum_size * bad_off1))) { - RtlCopyMemory(&context->stripes[bad_stripe1].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->parity_scratch[i * Vcb->superblock.sector_size], Vcb->superblock.sector_size); + if (check_sector_csum(Vcb, &context->parity_scratch[i << Vcb->sector_shift], (uint8_t*)context->csum + (Vcb->csum_size * bad_off1))) { + RtlCopyMemory(&context->stripes[bad_stripe1].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->parity_scratch[i << Vcb->sector_shift], Vcb->superblock.sector_size);
context->stripes[bad_stripe1].rewrite = true;
@@ -2376,26 +2374,26 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra log_error(Vcb, addr, c->devices[bad_stripe1]->devitem.dev_id, false, false, false); }
- addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 2) * c->chunk_item->stripe_length) + (bad_off2 * Vcb->superblock.sector_size); + addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 2) * c->chunk_item->stripe_length) + (bad_off2 << Vcb->sector_shift);
if (RtlCheckBit(&context->is_tree, bad_off2)) { - tree_header* th = (tree_header*)&context->parity_scratch2[i * Vcb->superblock.sector_size]; + tree_header* th = (tree_header*)&context->parity_scratch2[i << Vcb->sector_shift];
if (check_tree_checksum(Vcb, th) && th->address == addr) { - RtlCopyMemory(&context->stripes[bad_stripe2].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->parity_scratch2[i * Vcb->superblock.sector_size], Vcb->superblock.node_size); + RtlCopyMemory(&context->stripes[bad_stripe2].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->parity_scratch2[i << Vcb->sector_shift], Vcb->superblock.node_size);
context->stripes[bad_stripe2].rewrite = true;
- RtlClearBits(&context->stripes[bad_stripe2].error, i + 1, (Vcb->superblock.node_size / Vcb->superblock.sector_size) - 1); + RtlClearBits(&context->stripes[bad_stripe2].error, i + 1, (Vcb->superblock.node_size >> Vcb->sector_shift) - 1);
log_error(Vcb, addr, c->devices[bad_stripe2]->devitem.dev_id, true, true, false); } else log_error(Vcb, addr, c->devices[bad_stripe2]->devitem.dev_id, true, false, false); } else { - if (check_sector_csum(Vcb, &context->parity_scratch2[i * Vcb->superblock.sector_size], (uint8_t*)context->csum + (Vcb->csum_size * bad_off2))) { - RtlCopyMemory(&context->stripes[bad_stripe2].buf[(num * c->chunk_item->stripe_length) + (i * Vcb->superblock.sector_size)], - &context->parity_scratch2[i * Vcb->superblock.sector_size], Vcb->superblock.sector_size); + if (check_sector_csum(Vcb, &context->parity_scratch2[i << Vcb->sector_shift], (uint8_t*)context->csum + (Vcb->csum_size * bad_off2))) { + RtlCopyMemory(&context->stripes[bad_stripe2].buf[(num * c->chunk_item->stripe_length) + (i << Vcb->sector_shift)], + &context->parity_scratch2[i << Vcb->sector_shift], Vcb->superblock.sector_size);
context->stripes[bad_stripe2].rewrite = true;
@@ -2410,7 +2408,7 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra while (stripe != parity1) { if (c->devices[stripe]->devobj && RtlCheckBit(&context->alloc, off)) { if (RtlCheckBit(&context->stripes[stripe].error, i)) { - uint64_t addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 2) * c->chunk_item->stripe_length) + (off * Vcb->superblock.sector_size); + uint64_t addr = c->offset + (stripe_start * (c->chunk_item->num_stripes - 2) * c->chunk_item->stripe_length) + (off << Vcb->sector_shift);
log_error(Vcb, addr, c->devices[stripe]->devitem.dev_id, RtlCheckBit(&context->is_tree, off), false, false); } @@ -2451,7 +2449,7 @@ static NTSTATUS scrub_chunk_raid56_stripe_run(device_extension* Vcb, chunk* c, u return Status; }
- num_sectors = (uint32_t)((stripe_end - stripe_start + 1) * full_stripe_len / Vcb->superblock.sector_size); + num_sectors = (uint32_t)(((stripe_end - stripe_start + 1) * full_stripe_len) >> Vcb->sector_shift); arrlen = (ULONG)sector_align((num_sectors / 8) + 1, sizeof(ULONG));
allocarr = ExAllocatePoolWithTag(PagedPool, arrlen, ALLOC_TAG); @@ -2536,7 +2534,7 @@ static NTSTATUS scrub_chunk_raid56_stripe_run(device_extension* Vcb, chunk* c, u uint64_t extent_end = min(tp.item->key.obj_id + size, run_end); bool extent_is_tree = false;
- RtlSetBits(&context.alloc, (ULONG)((extent_start - run_start) / Vcb->superblock.sector_size), (ULONG)((extent_end - extent_start) / Vcb->superblock.sector_size)); + RtlSetBits(&context.alloc, (ULONG)((extent_start - run_start) >> Vcb->sector_shift), (ULONG)((extent_end - extent_start) >> Vcb->sector_shift));
if (tp.item->key.obj_type == TYPE_METADATA_ITEM) extent_is_tree = true; @@ -2554,7 +2552,7 @@ static NTSTATUS scrub_chunk_raid56_stripe_run(device_extension* Vcb, chunk* c, u }
if (extent_is_tree) - RtlSetBits(&context.is_tree, (ULONG)((extent_start - run_start) / Vcb->superblock.sector_size), (ULONG)((extent_end - extent_start) / Vcb->superblock.sector_size)); + RtlSetBits(&context.is_tree, (ULONG)((extent_start - run_start) >> Vcb->sector_shift), (ULONG)((extent_end - extent_start) >> Vcb->sector_shift)); else if (c->chunk_item->type & BLOCK_FLAG_DATA) { traverse_ptr tp2; bool b2; @@ -2577,13 +2575,13 @@ static NTSTATUS scrub_chunk_raid56_stripe_run(device_extension* Vcb, chunk* c, u
if (tp2.item->key.offset >= extent_start) { uint64_t csum_start = max(extent_start, tp2.item->key.offset); - uint64_t csum_end = min(extent_end, tp2.item->key.offset + (tp2.item->size * Vcb->superblock.sector_size / Vcb->csum_size)); + uint64_t csum_end = min(extent_end, tp2.item->key.offset + (((uint64_t)tp2.item->size << Vcb->sector_shift) / Vcb->csum_size));
- RtlSetBits(&context.has_csum, (ULONG)((csum_start - run_start) / Vcb->superblock.sector_size), (ULONG)((csum_end - csum_start) / Vcb->superblock.sector_size)); + RtlSetBits(&context.has_csum, (ULONG)((csum_start - run_start) >> Vcb->sector_shift), (ULONG)((csum_end - csum_start) >> Vcb->sector_shift));
- RtlCopyMemory((uint8_t*)context.csum + ((csum_start - run_start) * Vcb->csum_size / Vcb->superblock.sector_size), - tp2.item->data + ((csum_start - tp2.item->key.offset) * Vcb->csum_size / Vcb->superblock.sector_size), - (ULONG)((csum_end - csum_start) * Vcb->csum_size / Vcb->superblock.sector_size)); + RtlCopyMemory((uint8_t*)context.csum + (((csum_start - run_start) * Vcb->csum_size) >> Vcb->sector_shift), + tp2.item->data + (((csum_start - tp2.item->key.offset) * Vcb->csum_size) >> Vcb->sector_shift), + (ULONG)(((csum_end - csum_start) * Vcb->csum_size) >> Vcb->sector_shift)); }
b2 = find_next_item(Vcb, &tp2, &next_tp2, false, NULL); @@ -2626,7 +2624,7 @@ static NTSTATUS scrub_chunk_raid56_stripe_run(device_extension* Vcb, chunk* c, u goto end; }
- context.stripes[i].errorarr = ExAllocatePoolWithTag(PagedPool, (ULONG)sector_align(((c->chunk_item->stripe_length / Vcb->superblock.sector_size) / 8) + 1, sizeof(ULONG)), ALLOC_TAG); + context.stripes[i].errorarr = ExAllocatePoolWithTag(PagedPool, (ULONG)sector_align(((c->chunk_item->stripe_length >> Vcb->sector_shift) / 8) + 1, sizeof(ULONG)), ALLOC_TAG); if (!context.stripes[i].errorarr) { uint64_t j;
@@ -2643,7 +2641,7 @@ static NTSTATUS scrub_chunk_raid56_stripe_run(device_extension* Vcb, chunk* c, u goto end; }
- RtlInitializeBitMap(&context.stripes[i].error, context.stripes[i].errorarr, (ULONG)(c->chunk_item->stripe_length / Vcb->superblock.sector_size)); + RtlInitializeBitMap(&context.stripes[i].error, context.stripes[i].errorarr, (ULONG)(c->chunk_item->stripe_length >> Vcb->sector_shift));
context.stripes[i].context = &context; context.stripes[i].rewrite = false; @@ -3006,14 +3004,14 @@ static NTSTATUS scrub_chunk(device_extension* Vcb, chunk* c, uint64_t* offset, b if (!is_tree) { traverse_ptr tp2;
- csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(Vcb->csum_size * size / Vcb->superblock.sector_size), ALLOC_TAG); + csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((Vcb->csum_size * size) >> Vcb->sector_shift), ALLOC_TAG); if (!csum) { ERR("out of memory\n"); Status = STATUS_INSUFFICIENT_RESOURCES; goto end; }
- bmplen = (ULONG)(size / Vcb->superblock.sector_size); + bmplen = (ULONG)(size >> Vcb->sector_shift);
bmparr = ExAllocatePoolWithTag(PagedPool, (ULONG)(sector_align((bmplen >> 3) + 1, sizeof(ULONG))), ALLOC_TAG); if (!bmparr) { @@ -3045,15 +3043,15 @@ static NTSTATUS scrub_chunk(device_extension* Vcb, chunk* c, uint64_t* offset, b if (tp2.item->key.obj_type == TYPE_EXTENT_CSUM) { if (tp2.item->key.offset >= tp.item->key.obj_id + size) break; - else if (tp2.item->size >= Vcb->csum_size && tp2.item->key.offset + (tp2.item->size * Vcb->superblock.sector_size / Vcb->csum_size) >= tp.item->key.obj_id) { + else if (tp2.item->size >= Vcb->csum_size && tp2.item->key.offset + (((uint64_t)tp2.item->size << Vcb->sector_shift) / Vcb->csum_size) >= tp.item->key.obj_id) { uint64_t cs = max(tp.item->key.obj_id, tp2.item->key.offset); - uint64_t ce = min(tp.item->key.obj_id + size, tp2.item->key.offset + (tp2.item->size * Vcb->superblock.sector_size / Vcb->csum_size)); + uint64_t ce = min(tp.item->key.obj_id + size, tp2.item->key.offset + (((uint64_t)tp2.item->size << Vcb->sector_shift) / Vcb->csum_size));
- RtlCopyMemory((uint8_t*)csum + ((cs - tp.item->key.obj_id) * Vcb->csum_size / Vcb->superblock.sector_size), - tp2.item->data + ((cs - tp2.item->key.offset) * Vcb->csum_size / Vcb->superblock.sector_size), - (ULONG)((ce - cs) * Vcb->csum_size / Vcb->superblock.sector_size)); + RtlCopyMemory((uint8_t*)csum + (((cs - tp.item->key.obj_id) * Vcb->csum_size) >> Vcb->sector_shift), + tp2.item->data + (((cs - tp2.item->key.offset) * Vcb->csum_size) >> Vcb->sector_shift), + (ULONG)(((ce - cs) * Vcb->csum_size) >> Vcb->sector_shift));
- RtlClearBits(&bmp, (ULONG)((cs - tp.item->key.obj_id) / Vcb->superblock.sector_size), (ULONG)((ce - cs) / Vcb->superblock.sector_size)); + RtlClearBits(&bmp, (ULONG)((cs - tp.item->key.obj_id) >> Vcb->sector_shift), (ULONG)((ce - cs) >> Vcb->sector_shift));
if (ce == tp.item->key.obj_id + size) break; diff --git a/drivers/filesystems/btrfs/send.c b/drivers/filesystems/btrfs/send.c index 5e7a673744f..7db406b150a 100644 --- a/drivers/filesystems/btrfs/send.c +++ b/drivers/filesystems/btrfs/send.c @@ -1988,7 +1988,7 @@ static bool try_clone_edr(send_context* context, send_ext* se, EXTENT_DATA_REF* uint64_t clone_offset = tp.item->key.offset + ed2->offset - seed2->offset; uint64_t clone_len = min(context->lastinode.size - se->offset, ed2->num_bytes);
- if (clone_offset % context->Vcb->superblock.sector_size == 0 && clone_len % context->Vcb->superblock.sector_size == 0) { + if ((clone_offset & (context->Vcb->superblock.sector_size - 1)) == 0 && (clone_len & (context->Vcb->superblock.sector_size - 1)) == 0) { ULONG pos = context->datalen;
send_command(context, BTRFS_SEND_CMD_CLONE); @@ -2323,7 +2323,7 @@ static NTSTATUS flush_extents(send_context* context, traverse_ptr* tp1, traverse } }
- skip_start = addr % context->Vcb->superblock.sector_size; + skip_start = addr & (context->Vcb->superblock.sector_size - 1); addr -= skip_start;
if (context->lastinode.flags & BTRFS_INODE_NODATASUM) @@ -2331,7 +2331,7 @@ static NTSTATUS flush_extents(send_context* context, traverse_ptr* tp1, traverse else { uint32_t len;
- len = (uint32_t)sector_align(length + skip_start, context->Vcb->superblock.sector_size) / context->Vcb->superblock.sector_size; + len = (uint32_t)sector_align(length + skip_start, context->Vcb->superblock.sector_size) >> context->Vcb->sector_shift;
csum = ExAllocatePoolWithTag(PagedPool, len * context->Vcb->csum_size, ALLOC_TAG); if (!csum) { @@ -2410,7 +2410,7 @@ static NTSTATUS flush_extents(send_context* context, traverse_ptr* tp1, traverse else { uint32_t len;
- len = (uint32_t)(ed2->size / context->Vcb->superblock.sector_size); + len = (uint32_t)(ed2->size >> context->Vcb->sector_shift);
csum = ExAllocatePoolWithTag(PagedPool, len * context->Vcb->csum_size, ALLOC_TAG); if (!csum) { diff --git a/drivers/filesystems/btrfs/treefuncs.c b/drivers/filesystems/btrfs/treefuncs.c index c05f7035d45..4e5502fce2f 100644 --- a/drivers/filesystems/btrfs/treefuncs.c +++ b/drivers/filesystems/btrfs/treefuncs.c @@ -18,6 +18,7 @@ #include "btrfs_drv.h" #include "crc32c.h"
+__attribute__((nonnull(1,3,4,5))) NTSTATUS load_tree(device_extension* Vcb, uint64_t addr, uint8_t* buf, root* r, tree** pt) { tree_header* th; tree* t; @@ -191,6 +192,7 @@ NTSTATUS load_tree(device_extension* Vcb, uint64_t addr, uint8_t* buf, root* r, return STATUS_SUCCESS; }
+__attribute__((nonnull(1,2,3,4))) static NTSTATUS do_load_tree2(device_extension* Vcb, tree_holder* th, uint8_t* buf, root* r, tree* t, tree_data* td) { if (!th->tree) { NTSTATUS Status; @@ -216,6 +218,7 @@ static NTSTATUS do_load_tree2(device_extension* Vcb, tree_holder* th, uint8_t* b return STATUS_SUCCESS; }
+__attribute__((nonnull(1,2,3))) NTSTATUS do_load_tree(device_extension* Vcb, tree_holder* th, root* r, tree* t, tree_data* td, PIRP Irp) { NTSTATUS Status; uint8_t* buf; @@ -258,6 +261,7 @@ NTSTATUS do_load_tree(device_extension* Vcb, tree_holder* th, root* r, tree* t, return Status; }
+__attribute__((nonnull(1))) void free_tree(tree* t) { tree* par; root* r = t->root; @@ -314,6 +318,7 @@ void free_tree(tree* t) { ExFreePool(t); }
+__attribute__((nonnull(1))) static __inline tree_data* first_item(tree* t) { LIST_ENTRY* le = t->itemlist.Flink;
@@ -323,6 +328,7 @@ static __inline tree_data* first_item(tree* t) { return CONTAINING_RECORD(le, tree_data, list_entry); }
+__attribute__((nonnull(1,2))) static __inline tree_data* prev_item(tree* t, tree_data* td) { LIST_ENTRY* le = td->list_entry.Blink;
@@ -332,6 +338,7 @@ static __inline tree_data* prev_item(tree* t, tree_data* td) { return CONTAINING_RECORD(le, tree_data, list_entry); }
+__attribute__((nonnull(1,2))) static __inline tree_data* next_item(tree* t, tree_data* td) { LIST_ENTRY* le = td->list_entry.Flink;
@@ -341,6 +348,7 @@ static __inline tree_data* next_item(tree* t, tree_data* td) { return CONTAINING_RECORD(le, tree_data, list_entry); }
+__attribute__((nonnull(1,2,3,4))) static NTSTATUS next_item2(device_extension* Vcb, tree* t, tree_data* td, traverse_ptr* tp) { tree_data* td2 = next_item(t, td); tree* t2; @@ -366,6 +374,7 @@ static NTSTATUS next_item2(device_extension* Vcb, tree* t, tree_data* td, traver return find_item_to_level(Vcb, t2->root, tp, &td2->key, false, t->header.level, NULL); }
+__attribute__((nonnull(1,2,3,4,5))) NTSTATUS skip_to_difference(device_extension* Vcb, traverse_ptr* tp, traverse_ptr* tp2, bool* ended1, bool* ended2) { NTSTATUS Status; tree *t1, *t2; @@ -441,6 +450,7 @@ NTSTATUS skip_to_difference(device_extension* Vcb, traverse_ptr* tp, traverse_pt } }
+__attribute__((nonnull(1,2,3,4))) static NTSTATUS find_item_in_tree(device_extension* Vcb, tree* t, traverse_ptr* tp, const KEY* searchkey, bool ignore, uint8_t level, PIRP Irp) { int cmp; tree_data *td, *lasttd; @@ -546,6 +556,7 @@ static NTSTATUS find_item_in_tree(device_extension* Vcb, tree* t, traverse_ptr* } }
+__attribute__((nonnull(1,2,3,4))) 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; @@ -566,6 +577,7 @@ NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension return Status; }
+__attribute__((nonnull(1,2,3,4))) NTSTATUS find_item_to_level(device_extension* Vcb, root* r, traverse_ptr* tp, const KEY* searchkey, bool ignore, uint8_t level, PIRP Irp) { NTSTATUS Status;
@@ -590,6 +602,7 @@ NTSTATUS find_item_to_level(device_extension* Vcb, root* r, traverse_ptr* tp, co return Status; }
+__attribute__((nonnull(1,2,3))) bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, const traverse_ptr* tp, traverse_ptr* next_tp, bool ignore, PIRP Irp) { tree* t; tree_data *td = NULL, *next; @@ -648,6 +661,9 @@ bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vc
fi = first_item(t);
+ if (!fi) + return false; + if (!fi->treeholder.tree) { Status = do_load_tree(Vcb, &fi->treeholder, t->parent->root, t, fi, Irp); if (!NT_SUCCESS(Status)) { @@ -662,6 +678,9 @@ bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vc next_tp->tree = t; next_tp->item = first_item(t);
+ if (!next_tp->item) + return false; + if (!ignore && next_tp->item->ignore) { traverse_ptr ntp2; bool b; @@ -687,6 +706,7 @@ bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vc return true; }
+__attribute__((nonnull(1))) static __inline tree_data* last_item(tree* t) { LIST_ENTRY* le = t->itemlist.Blink;
@@ -696,6 +716,7 @@ static __inline tree_data* last_item(tree* t) { return CONTAINING_RECORD(le, tree_data, list_entry); }
+__attribute__((nonnull(1,2,3))) bool find_prev_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, const traverse_ptr* tp, traverse_ptr* prev_tp, PIRP Irp) { tree* t; tree_data* td; @@ -754,6 +775,7 @@ bool find_prev_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vc return true; }
+__attribute__((nonnull(1,2))) void free_trees_root(device_extension* Vcb, root* r) { LIST_ENTRY* le; ULONG level; @@ -791,6 +813,7 @@ void free_trees_root(device_extension* Vcb, root* r) { } }
+__attribute__((nonnull(1))) void free_trees(device_extension* Vcb) { LIST_ENTRY* le; ULONG level; @@ -834,6 +857,7 @@ void free_trees(device_extension* Vcb) { #pragma warning(push) #pragma warning(suppress: 28194) #endif +__attribute__((nonnull(1,3))) void add_rollback(_In_ LIST_ENTRY* rollback, _In_ enum rollback_type type, _In_ __drv_aliasesMem void* ptr) { rollback_item* ri;
@@ -855,6 +879,7 @@ void add_rollback(_In_ LIST_ENTRY* rollback, _In_ enum rollback_type type, _In_ #pragma warning(push) #pragma warning(suppress: 28194) #endif +__attribute__((nonnull(1,2))) NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_ root* r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >= 0, __drv_aliasesMem) void* data, _In_ uint16_t size, _Out_opt_ traverse_ptr* ptp, _In_opt_ PIRP Irp) { @@ -877,25 +902,20 @@ NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock)
Status = find_item(Vcb, r, &tp, &searchkey, true, Irp); if (Status == STATUS_NOT_FOUND) { - if (r) { - if (!r->treeholder.tree) { - Status = do_load_tree(Vcb, &r->treeholder, r, NULL, NULL, Irp); - if (!NT_SUCCESS(Status)) { - ERR("do_load_tree returned %08lx\n", Status); - return Status; - } + if (!r->treeholder.tree) { + Status = do_load_tree(Vcb, &r->treeholder, r, NULL, NULL, Irp); + if (!NT_SUCCESS(Status)) { + ERR("do_load_tree returned %08lx\n", Status); + return Status; } + }
- if (r->treeholder.tree && r->treeholder.tree->header.num_items == 0) { - tp.tree = r->treeholder.tree; - tp.item = NULL; - } else { - ERR("error: unable to load tree for root %I64x\n", r->id); - return STATUS_INTERNAL_ERROR; - } + if (r->treeholder.tree && r->treeholder.tree->header.num_items == 0) { + tp.tree = r->treeholder.tree; + tp.item = NULL; } else { - ERR("error: find_item returned %08lx\n", Status); - return Status; + ERR("error: unable to load tree for root %I64x\n", r->id); + return STATUS_INTERNAL_ERROR; } } else if (!NT_SUCCESS(Status)) { ERR("find_item returned %08lx\n", Status); @@ -987,6 +1007,7 @@ NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) #pragma warning(pop) #endif
+__attribute__((nonnull(1,2))) NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _Inout_ traverse_ptr* tp) { tree* t; uint64_t gen; @@ -1026,6 +1047,7 @@ NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) return STATUS_SUCCESS; }
+__attribute__((nonnull(1))) void clear_rollback(LIST_ENTRY* rollback) { while (!IsListEmpty(rollback)) { LIST_ENTRY* le = RemoveHeadList(rollback); @@ -1047,6 +1069,7 @@ void clear_rollback(LIST_ENTRY* rollback) { } }
+__attribute__((nonnull(1,2))) void do_rollback(device_extension* Vcb, LIST_ENTRY* rollback) { NTSTATUS Status; rollback_item* ri; @@ -1062,23 +1085,32 @@ void do_rollback(device_extension* Vcb, LIST_ENTRY* rollback) {
re->ext->ignore = true;
- if (re->ext->extent_data.type == EXTENT_TYPE_REGULAR || re->ext->extent_data.type == EXTENT_TYPE_PREALLOC) { - EXTENT_DATA2* ed2 = (EXTENT_DATA2*)re->ext->extent_data.data; + switch (re->ext->extent_data.type) { + case EXTENT_TYPE_REGULAR: + case EXTENT_TYPE_PREALLOC: { + EXTENT_DATA2* ed2 = (EXTENT_DATA2*)re->ext->extent_data.data;
- if (ed2->size != 0) { - chunk* c = get_chunk_from_address(Vcb, ed2->address); + if (ed2->size != 0) { + chunk* c = get_chunk_from_address(Vcb, ed2->address);
- if (c) { - Status = update_changed_extent_ref(Vcb, c, ed2->address, ed2->size, re->fcb->subvol->id, - re->fcb->inode, re->ext->offset - ed2->offset, -1, - re->fcb->inode_item.flags & BTRFS_INODE_NODATASUM, false, NULL); + if (c) { + Status = update_changed_extent_ref(Vcb, c, ed2->address, ed2->size, re->fcb->subvol->id, + re->fcb->inode, re->ext->offset - ed2->offset, -1, + re->fcb->inode_item.flags & BTRFS_INODE_NODATASUM, false, NULL); + + if (!NT_SUCCESS(Status)) + ERR("update_changed_extent_ref returned %08lx\n", Status); + }
- if (!NT_SUCCESS(Status)) - ERR("update_changed_extent_ref returned %08lx\n", Status); + re->fcb->inode_item.st_blocks -= ed2->num_bytes; }
- re->fcb->inode_item.st_blocks -= ed2->num_bytes; + break; } + + case EXTENT_TYPE_INLINE: + re->fcb->inode_item.st_blocks -= re->ext->extent_data.decoded_size; + break; }
ExFreePool(re); @@ -1091,23 +1123,32 @@ void do_rollback(device_extension* Vcb, LIST_ENTRY* rollback) {
re->ext->ignore = false;
- if (re->ext->extent_data.type == EXTENT_TYPE_REGULAR || re->ext->extent_data.type == EXTENT_TYPE_PREALLOC) { - EXTENT_DATA2* ed2 = (EXTENT_DATA2*)re->ext->extent_data.data; + switch (re->ext->extent_data.type) { + case EXTENT_TYPE_REGULAR: + case EXTENT_TYPE_PREALLOC: { + EXTENT_DATA2* ed2 = (EXTENT_DATA2*)re->ext->extent_data.data;
- if (ed2->size != 0) { - chunk* c = get_chunk_from_address(Vcb, ed2->address); + if (ed2->size != 0) { + chunk* c = get_chunk_from_address(Vcb, ed2->address);
- if (c) { - Status = update_changed_extent_ref(Vcb, c, ed2->address, ed2->size, re->fcb->subvol->id, - re->fcb->inode, re->ext->offset - ed2->offset, 1, - re->fcb->inode_item.flags & BTRFS_INODE_NODATASUM, false, NULL); + if (c) { + Status = update_changed_extent_ref(Vcb, c, ed2->address, ed2->size, re->fcb->subvol->id, + re->fcb->inode, re->ext->offset - ed2->offset, 1, + re->fcb->inode_item.flags & BTRFS_INODE_NODATASUM, false, NULL); + + if (!NT_SUCCESS(Status)) + ERR("update_changed_extent_ref returned %08lx\n", Status); + }
- if (!NT_SUCCESS(Status)) - ERR("update_changed_extent_ref returned %08lx\n", Status); + re->fcb->inode_item.st_blocks += ed2->num_bytes; }
- re->fcb->inode_item.st_blocks += ed2->num_bytes; + break; } + + case EXTENT_TYPE_INLINE: + re->fcb->inode_item.st_blocks += re->ext->extent_data.decoded_size; + break; }
ExFreePool(re); @@ -1175,7 +1216,8 @@ void do_rollback(device_extension* Vcb, LIST_ENTRY* rollback) { } }
-static void find_tree_end(tree* t, KEY* tree_end, bool* no_end) { +__attribute__((nonnull(1,2,3))) +static NTSTATUS find_tree_end(tree* t, KEY* tree_end, bool* no_end) { tree* p;
p = t; @@ -1183,8 +1225,11 @@ static void find_tree_end(tree* t, KEY* tree_end, bool* no_end) { tree_data* pi;
if (!p->parent) { + tree_end->obj_id = 0xffffffffffffffff; + tree_end->obj_type = 0xff; + tree_end->offset = 0xffffffffffffffff; *no_end = true; - return; + return STATUS_SUCCESS; }
pi = p->paritem; @@ -1194,13 +1239,16 @@ static void find_tree_end(tree* t, KEY* tree_end, bool* no_end) {
*tree_end = td->key; *no_end = false; - return; + return STATUS_SUCCESS; }
p = p->parent; } while (p); + + return STATUS_INTERNAL_ERROR; }
+__attribute__((nonnull(1,2))) void clear_batch_list(device_extension* Vcb, LIST_ENTRY* batchlist) { while (!IsListEmpty(batchlist)) { LIST_ENTRY* le = RemoveHeadList(batchlist); @@ -1217,6 +1265,7 @@ void clear_batch_list(device_extension* Vcb, LIST_ENTRY* batchlist) { } }
+__attribute__((nonnull(1,2,3))) static void add_delete_inode_extref(device_extension* Vcb, batch_item* bi, LIST_ENTRY* listhead) { batch_item* bi2; LIST_ENTRY* le; @@ -1265,6 +1314,7 @@ static void add_delete_inode_extref(device_extension* Vcb, batch_item* bi, LIST_ InsertTailList(listhead, &bi2->list_entry); }
+__attribute__((nonnull(1,2,3,4,6,7))) static NTSTATUS handle_batch_collision(device_extension* Vcb, batch_item* bi, tree* t, tree_data* td, tree_data* newtd, LIST_ENTRY* listhead, bool* ignore) { if (bi->operation == Batch_Delete || bi->operation == Batch_SetXattr || bi->operation == Batch_DirItem || bi->operation == Batch_InodeRef || bi->operation == Batch_InodeExtRef || bi->operation == Batch_DeleteDirItem || bi->operation == Batch_DeleteInodeRef || @@ -1849,6 +1899,7 @@ static NTSTATUS handle_batch_collision(device_extension* Vcb, batch_item* bi, tr return STATUS_SUCCESS; }
+__attribute__((nonnull(1,2))) static NTSTATUS commit_batch_list_root(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, batch_root* br, PIRP Irp) { LIST_ENTRY* le; NTSTATUS Status; @@ -1875,7 +1926,11 @@ static NTSTATUS commit_batch_list_root(_Requires_exclusive_lock_held_(_Curr_->tr return Status; }
- find_tree_end(tp.tree, &tree_end, &no_end); + Status = find_tree_end(tp.tree, &tree_end, &no_end); + if (!NT_SUCCESS(Status)) { + ERR("find_tree_end returned %08lx\n", Status); + return Status; + }
if (bi->operation == Batch_DeleteInode) { if (tp.item->key.obj_id == bi->key.obj_id) { @@ -1946,7 +2001,11 @@ static NTSTATUS commit_batch_list_root(_Requires_exclusive_lock_held_(_Curr_->tr if (find_next_item(Vcb, &tp, &tp2, false, Irp)) { if (tp2.item->key.obj_id == bi->key.obj_id && tp2.item->key.obj_type == bi->key.obj_type) { tp = tp2; - find_tree_end(tp.tree, &tree_end, &no_end); + Status = find_tree_end(tp.tree, &tree_end, &no_end); + if (!NT_SUCCESS(Status)) { + ERR("find_tree_end returned %08lx\n", Status); + return Status; + } } } } @@ -2278,6 +2337,7 @@ static NTSTATUS commit_batch_list_root(_Requires_exclusive_lock_held_(_Curr_->tr return STATUS_SUCCESS; }
+__attribute__((nonnull(1,2))) NTSTATUS commit_batch_list(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, LIST_ENTRY* batchlist, PIRP Irp) { NTSTATUS Status;
diff --git a/drivers/filesystems/btrfs/volume.c b/drivers/filesystems/btrfs/volume.c index d78d33712cc..e89b6154d31 100644 --- a/drivers/filesystems/btrfs/volume.c +++ b/drivers/filesystems/btrfs/volume.c @@ -953,7 +953,7 @@ NTSTATUS __stdcall pnp_removal(PVOID NotificationStructure, PVOID Context) { TRACE("GUID_TARGET_DEVICE_QUERY_REMOVE\n");
if (pdode->vde && pdode->vde->mounted_device) - return pnp_query_remove_device(pdode->vde->mounted_device, NULL); + pnp_query_remove_device(pdode->vde->mounted_device, NULL); }
return STATUS_SUCCESS; diff --git a/drivers/filesystems/btrfs/write.c b/drivers/filesystems/btrfs/write.c index 65b8c8d512c..b73c17d689c 100644 --- a/drivers/filesystems/btrfs/write.c +++ b/drivers/filesystems/btrfs/write.c @@ -28,13 +28,14 @@ typedef struct { _Function_class_(IO_COMPLETION_ROUTINE) static NTSTATUS __stdcall write_data_completion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID conptr);
-static void remove_fcb_extent(fcb* fcb, extent* ext, LIST_ENTRY* rollback); +static void remove_fcb_extent(fcb* fcb, extent* ext, LIST_ENTRY* rollback) __attribute__((nonnull(1, 2, 3)));
extern tPsUpdateDiskCounters fPsUpdateDiskCounters; extern tCcCopyWriteEx fCcCopyWriteEx; extern tFsRtlUpdateDiskCounters fFsRtlUpdateDiskCounters; extern bool diskacc;
+__attribute__((nonnull(1, 2, 4))) bool find_data_address_in_chunk(device_extension* Vcb, chunk* c, uint64_t length, uint64_t* address) { LIST_ENTRY* le; space* s; @@ -86,6 +87,7 @@ bool find_data_address_in_chunk(device_extension* Vcb, chunk* c, uint64_t length return false; }
+__attribute__((nonnull(1))) chunk* get_chunk_from_address(device_extension* Vcb, uint64_t address) { LIST_ENTRY* le2;
@@ -113,6 +115,7 @@ typedef struct { device* device; } stripe;
+__attribute__((nonnull(1))) static uint64_t find_new_chunk_address(device_extension* Vcb, uint64_t size) { uint64_t lastaddr; LIST_ENTRY* le; @@ -134,6 +137,7 @@ static uint64_t find_new_chunk_address(device_extension* Vcb, uint64_t size) { return lastaddr; }
+__attribute__((nonnull(1,2))) static bool find_new_dup_stripes(device_extension* Vcb, stripe* stripes, uint64_t max_stripe_size, bool full_size) { uint64_t devusage = 0xffffffffffffffff; space *devdh1 = NULL, *devdh2 = NULL; @@ -245,6 +249,7 @@ static bool find_new_dup_stripes(device_extension* Vcb, stripe* stripes, uint64_ return true; }
+__attribute__((nonnull(1,2))) static bool find_new_stripe(device_extension* Vcb, stripe* stripes, uint16_t i, uint64_t max_stripe_size, bool allow_missing, bool full_size) { uint64_t k, devusage = 0xffffffffffffffff; space* devdh = NULL; @@ -358,6 +363,7 @@ static bool find_new_stripe(device_extension* Vcb, stripe* stripes, uint16_t i, return true; }
+__attribute__((nonnull(1,3))) NTSTATUS alloc_chunk(device_extension* Vcb, uint64_t flags, chunk** pc, bool full_size) { NTSTATUS Status; uint64_t max_stripe_size, max_chunk_size, stripe_size, stripe_length, factor; @@ -703,6 +709,7 @@ end: return Status; }
+__attribute__((nonnull(1,3,5,8))) static NTSTATUS prepare_raid0_write(_Pre_satisfies_(_Curr_->chunk_item->num_stripes>0) _In_ chunk* c, _In_ uint64_t address, _In_reads_bytes_(length) void* data, _In_ uint32_t length, _In_ write_stripe* stripes, _In_ PIRP Irp, _In_ uint64_t irp_offset, _In_ write_data_context* wtc) { uint64_t startoff, endoff; @@ -832,6 +839,7 @@ static NTSTATUS prepare_raid0_write(_Pre_satisfies_(_Curr_->chunk_item->num_stri return STATUS_SUCCESS; }
+__attribute__((nonnull(1,3,5,8))) static NTSTATUS prepare_raid10_write(_Pre_satisfies_(_Curr_->chunk_item->sub_stripes>0&&_Curr_->chunk_item->num_stripes>=_Curr_->chunk_item->sub_stripes) _In_ chunk* c, _In_ uint64_t address, _In_reads_bytes_(length) void* data, _In_ uint32_t length, _In_ write_stripe* stripes, _In_ PIRP Irp, _In_ uint64_t irp_offset, _In_ write_data_context* wtc) { @@ -971,7 +979,8 @@ static NTSTATUS prepare_raid10_write(_Pre_satisfies_(_Curr_->chunk_item->sub_str return STATUS_SUCCESS; }
-static NTSTATUS add_partial_stripe(device_extension* Vcb, chunk *c, uint64_t address, uint32_t length, void* data) { +__attribute__((nonnull(1,2,5))) ... 466 lines suppressed ...