https://git.reactos.org/?p=reactos.git;a=commitdiff;h=174dfab6678fd87b0872b…
commit 174dfab6678fd87b0872b3592fcec956778134b1
Author: Vincent Franchomme <franchomme.vincent(a)gmail.com>
AuthorDate: Thu Apr 28 21:31:44 2022 +0200
Commit: Hermès BÉLUSCA - MAÏTO <hermes.belusca-maito(a)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 ...