ReactOS.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
February
List overview
Download
Ros-diffs
May 2022
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
ros-diffs@reactos.org
31 participants
165 discussions
Start a n
N
ew thread
[reactos] 05/10: [BTRFS][UBTRFS][SHELLBTRFS] Upgrade to 1.7.7 (#4417)
by Vincent Franchomme
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=98654b54b43c77662ea7f…
commit 98654b54b43c77662ea7f290409f0a93a1cb0523 Author: Vincent Franchomme <franchomme.vincent(a)gmail.com> AuthorDate: Thu Apr 28 21:35:05 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.7 (#4417) v1.7.7 (2021-04-12): - Fixed deadlock on high load - Fixed free space issue when installing Genshin Impact - Fixed issue when copying files with wildcards in command prompt - Increased speed of directory lookups --- dll/shellext/shellbtrfs/shellbtrfs.rc | 8 ++++---- dll/shellext/shellbtrfs/volpropsheet.cpp | 2 +- dll/win32/ubtrfs/ubtrfs.rc | 8 ++++---- drivers/filesystems/btrfs/btrfs.inf | 4 ++-- drivers/filesystems/btrfs/btrfs.rc | 8 ++++---- drivers/filesystems/btrfs/create.c | 11 +++++++++-- drivers/filesystems/btrfs/dirctrl.c | 19 ++++++++++--------- drivers/filesystems/btrfs/fastio.c | 7 ------- drivers/filesystems/btrfs/volume.c | 3 +++ 9 files changed, 37 insertions(+), 33 deletions(-) diff --git a/dll/shellext/shellbtrfs/shellbtrfs.rc b/dll/shellext/shellbtrfs/shellbtrfs.rc index 845d8bc7844..26d3d6aa67e 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,6,0 - PRODUCTVERSION 1,7,6,0 + FILEVERSION 1,7,7,0 + PRODUCTVERSION 1,7,7,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -78,12 +78,12 @@ BEGIN BLOCK "080904b0" BEGIN VALUE "FileDescription", "WinBtrfs shell extension" - VALUE "FileVersion", "1.7.6" + VALUE "FileVersion", "1.7.7" VALUE "InternalName", "btrfs" VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-21" VALUE "OriginalFilename", "shellbtrfs.dll" VALUE "ProductName", "WinBtrfs" - VALUE "ProductVersion", "1.7.6" + VALUE "ProductVersion", "1.7.7" END END BLOCK "VarFileInfo" diff --git a/dll/shellext/shellbtrfs/volpropsheet.cpp b/dll/shellext/shellbtrfs/volpropsheet.cpp index 128ac8e42b5..a2f50fac2aa 100644 --- a/dll/shellext/shellbtrfs/volpropsheet.cpp +++ b/dll/shellext/shellbtrfs/volpropsheet.cpp @@ -1476,7 +1476,7 @@ HRESULT __stdcall BtrfsVolPropSheet::ReplacePage(UINT uPageID, LPFNADDPROPSHEETP void BtrfsChangeDriveLetter::do_change(HWND hwndDlg) { unsigned int sel = (unsigned int)SendDlgItemMessageW(hwndDlg, IDC_DRIVE_LETTER_COMBO, CB_GETCURSEL, 0, 0); - if (sel >= 0 && sel < letters.size()) { + if (sel < letters.size()) { wstring dd; if (fn.length() == 3 && fn[1] == L':' && fn[2] == L'\\') { diff --git a/dll/win32/ubtrfs/ubtrfs.rc b/dll/win32/ubtrfs/ubtrfs.rc index 27eef7a7c0b..c12381e9f56 100644 --- a/dll/win32/ubtrfs/ubtrfs.rc +++ b/dll/win32/ubtrfs/ubtrfs.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,7,6,0 - PRODUCTVERSION 1,7,6,0 + FILEVERSION 1,7,7,0 + PRODUCTVERSION 1,7,7,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -68,12 +68,12 @@ BEGIN BLOCK "080904b0" BEGIN VALUE "FileDescription", "Btrfs utility DLL" - VALUE "FileVersion", "1.7.6" + VALUE "FileVersion", "1.7.7" VALUE "InternalName", "ubtrfs" VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-21" VALUE "OriginalFilename", "ubtrfs.dll" VALUE "ProductName", "WinBtrfs" - VALUE "ProductVersion", "1.7.6" + VALUE "ProductVersion", "1.7.7" END END BLOCK "VarFileInfo" diff --git a/drivers/filesystems/btrfs/btrfs.inf b/drivers/filesystems/btrfs/btrfs.inf index 42a3e97068c..e0f6148cdae 100644 --- a/drivers/filesystems/btrfs/btrfs.inf +++ b/drivers/filesystems/btrfs/btrfs.inf @@ -2,7 +2,7 @@ ;;; WinBtrfs ;;; ;;; -;;; Copyright (c) 2016-20 Mark Harmstone +;;; Copyright (c) 2016-21 Mark Harmstone ;;; [Version] @@ -10,7 +10,7 @@ Signature = "$Windows NT$" Class = Volume ClassGuid = {71a27cdd-812a-11d0-bec7-08002be2092f} Provider = %Me% -DriverVer = 01/14/2021,1.7.6.0 +DriverVer = 04/12/2021,1.7.7.0 CatalogFile = btrfs.cat [DestinationDirs] diff --git a/drivers/filesystems/btrfs/btrfs.rc b/drivers/filesystems/btrfs/btrfs.rc index 198fcc4e8a9..b4358b2419d 100644 --- a/drivers/filesystems/btrfs/btrfs.rc +++ b/drivers/filesystems/btrfs/btrfs.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,7,6,0 - PRODUCTVERSION 1,7,6,0 + FILEVERSION 1,7,7,0 + PRODUCTVERSION 1,7,7,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -68,12 +68,12 @@ BEGIN BLOCK "080904b0" BEGIN VALUE "FileDescription", "WinBtrfs" - VALUE "FileVersion", "1.7.6" + VALUE "FileVersion", "1.7.7" VALUE "InternalName", "btrfs" VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-21" VALUE "OriginalFilename", "btrfs.sys" VALUE "ProductName", "WinBtrfs" - VALUE "ProductVersion", "1.7.6" + VALUE "ProductVersion", "1.7.7" END END BLOCK "VarFileInfo" diff --git a/drivers/filesystems/btrfs/create.c b/drivers/filesystems/btrfs/create.c index e678a096167..a5a8a2316a2 100644 --- a/drivers/filesystems/btrfs/create.c +++ b/drivers/filesystems/btrfs/create.c @@ -195,6 +195,10 @@ NTSTATUS find_file_in_dir(PUNICODE_STRING filename, fcb* fcb, root** subvol, uin } else fnus = *filename; + Status = check_file_name_valid(filename, false, false); + if (!NT_SUCCESS(Status)) + return Status; + hash = calc_crc32c(0xffffffff, (uint8_t*)fnus.Buffer, fnus.Length); c = hash >> 24; @@ -1604,6 +1608,9 @@ NTSTATUS open_fileref_child(_Requires_lock_held_(_Curr_->tree_lock) _Requires_ex TRACE("could not find %.*S\n", (int)(name->Length / sizeof(WCHAR)), name->Buffer); return lastpart ? STATUS_OBJECT_NAME_NOT_FOUND : STATUS_OBJECT_PATH_NOT_FOUND; + } else if (Status == STATUS_OBJECT_NAME_INVALID) { + TRACE("invalid filename: %.*S\n", (int)(name->Length / sizeof(WCHAR)), name->Buffer); + return Status; } else if (!NT_SUCCESS(Status)) { ERR("find_file_in_dir returned %08lx\n", Status); return Status; @@ -1804,7 +1811,7 @@ NTSTATUS open_fileref(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusiv Status = open_fileref_child(Vcb, sf, &nb->us, cs, lastpart, streampart, pooltype, &sf2, Irp); if (!NT_SUCCESS(Status)) { - if (Status == STATUS_OBJECT_PATH_NOT_FOUND || Status == STATUS_OBJECT_NAME_NOT_FOUND) + if (Status == STATUS_OBJECT_PATH_NOT_FOUND || Status == STATUS_OBJECT_NAME_NOT_FOUND || Status == STATUS_OBJECT_NAME_INVALID) TRACE("open_fileref_child returned %08lx\n", Status); else ERR("open_fileref_child returned %08lx\n", Status); @@ -4668,7 +4675,7 @@ loaded: TRACE("file doesn't exist, returning STATUS_OBJECT_NAME_NOT_FOUND\n"); goto exit; } - } else if (Status == STATUS_OBJECT_PATH_NOT_FOUND) { + } else if (Status == STATUS_OBJECT_PATH_NOT_FOUND || Status == STATUS_OBJECT_NAME_INVALID) { TRACE("open_fileref returned %08lx\n", Status); goto exit; } else { diff --git a/drivers/filesystems/btrfs/dirctrl.c b/drivers/filesystems/btrfs/dirctrl.c index b13dd2a22ff..a7f7f0c0953 100644 --- a/drivers/filesystems/btrfs/dirctrl.c +++ b/drivers/filesystems/btrfs/dirctrl.c @@ -326,7 +326,7 @@ static NTSTATUS query_dir_item(fcb* fcb, ccb* ccb, void* buf, LONG* len, PIRP Ir TRACE("FileBothDirectoryInformation\n"); - needed = sizeof(FILE_BOTH_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length; + needed = offsetof(FILE_BOTH_DIR_INFORMATION, FileName) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %li > %lu\n", needed, *len); @@ -366,7 +366,7 @@ static NTSTATUS query_dir_item(fcb* fcb, ccb* ccb, void* buf, LONG* len, PIRP Ir TRACE("FileDirectoryInformation\n"); - needed = sizeof(FILE_DIRECTORY_INFORMATION) - sizeof(WCHAR) + de->name.Length; + needed = offsetof(FILE_DIRECTORY_INFORMATION, FileName) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %li > %lu\n", needed, *len); @@ -404,7 +404,7 @@ static NTSTATUS query_dir_item(fcb* fcb, ccb* ccb, void* buf, LONG* len, PIRP Ir TRACE("FileFullDirectoryInformation\n"); - needed = sizeof(FILE_FULL_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length; + needed = offsetof(FILE_FULL_DIR_INFORMATION, FileName) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %li > %lu\n", needed, *len); @@ -443,7 +443,7 @@ static NTSTATUS query_dir_item(fcb* fcb, ccb* ccb, void* buf, LONG* len, PIRP Ir TRACE("FileIdBothDirectoryInformation\n"); - needed = sizeof(FILE_ID_BOTH_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length; + needed = offsetof(FILE_ID_BOTH_DIR_INFORMATION, FileName) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %li > %lu\n", needed, *len); @@ -484,7 +484,7 @@ static NTSTATUS query_dir_item(fcb* fcb, ccb* ccb, void* buf, LONG* len, PIRP Ir TRACE("FileIdFullDirectoryInformation\n"); - needed = sizeof(FILE_ID_FULL_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length; + needed = offsetof(FILE_ID_FULL_DIR_INFORMATION, FileName) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %li > %lu\n", needed, *len); @@ -529,7 +529,7 @@ static NTSTATUS query_dir_item(fcb* fcb, ccb* ccb, void* buf, LONG* len, PIRP Ir TRACE("FileIdExtdDirectoryInformation\n"); - needed = offsetof(FILE_ID_EXTD_DIR_INFORMATION, FileName[0]) + de->name.Length; + needed = offsetof(FILE_ID_EXTD_DIR_INFORMATION, FileName) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %li > %lu\n", needed, *len); @@ -572,7 +572,7 @@ static NTSTATUS query_dir_item(fcb* fcb, ccb* ccb, void* buf, LONG* len, PIRP Ir TRACE("FileIdExtdBothDirectoryInformation\n"); - needed = offsetof(FILE_ID_EXTD_BOTH_DIR_INFORMATION, FileName[0]) + de->name.Length; + needed = offsetof(FILE_ID_EXTD_BOTH_DIR_INFORMATION, FileName) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %li > %lu\n", needed, *len); @@ -622,7 +622,7 @@ static NTSTATUS query_dir_item(fcb* fcb, ccb* ccb, void* buf, LONG* len, PIRP Ir TRACE("FileNamesInformation\n"); - needed = sizeof(FILE_NAMES_INFORMATION) - sizeof(WCHAR) + de->name.Length; + needed = offsetof(FILE_NAMES_INFORMATION, FileName) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %li > %lu\n", needed, *len); @@ -839,7 +839,8 @@ static NTSTATUS query_directory(PIRP Irp) { if (FsRtlDoesNameContainWildCards(IrpSp->Parameters.QueryDirectory.FileName)) { has_wildcard = true; specific_file = false; - } + } else if (!initial) + return STATUS_NO_MORE_FILES; } if (ccb->query_string.Buffer) diff --git a/drivers/filesystems/btrfs/fastio.c b/drivers/filesystems/btrfs/fastio.c index 2c768895f8d..a5f577efb93 100644 --- a/drivers/filesystems/btrfs/fastio.c +++ b/drivers/filesystems/btrfs/fastio.c @@ -354,18 +354,11 @@ static BOOLEAN __stdcall fast_io_write(PFILE_OBJECT FileObject, PLARGE_INTEGER F return false; } - if (!ExAcquireResourceExclusiveLite(fcb->Header.Resource, Wait)) { - ExReleaseResourceLite(&fcb->Vcb->tree_lock); - FsRtlExitFileSystem(); - return false; - } - ret = FsRtlCopyWrite(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject); if (ret) fcb->inode_item.st_size = fcb->Header.FileSize.QuadPart; - ExReleaseResourceLite(fcb->Header.Resource); ExReleaseResourceLite(&fcb->Vcb->tree_lock); FsRtlExitFileSystem(); diff --git a/drivers/filesystems/btrfs/volume.c b/drivers/filesystems/btrfs/volume.c index 3ee63ed29f6..2cf660a903c 100644 --- a/drivers/filesystems/btrfs/volume.c +++ b/drivers/filesystems/btrfs/volume.c @@ -307,6 +307,9 @@ static NTSTATUS vol_query_device_name(volume_device_extension* vde, PIRP Irp) { PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PMOUNTDEV_NAME name; + if (IrpSp->FileObject && IrpSp->FileObject->FsContext) + return STATUS_INVALID_PARAMETER; + if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTDEV_NAME)) { Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME); return STATUS_BUFFER_TOO_SMALL;
2 years, 7 months
1
0
0
0
[reactos] 04/10: [BTRFS][UBTRFS][SHELLBTRFS] Upgrade to 1.7.6 (#4417)
by Vincent Franchomme
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c982533ea9ede11a71992…
commit c982533ea9ede11a719925731c9c1b2fc5b5d347 Author: Vincent Franchomme <franchomme.vincent(a)gmail.com> AuthorDate: Thu Apr 28 21:34:48 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.6 (#4417) v1.7.6 (2021-01-14): - Fixed race condition when booting with Quibble - No longer need to restart Windows after initial installation - Forced maximum file name to 255 UTF-8 characters, to match Linux driver - Fixed issue where directories could be created with trailing backslash - Fixed potential deadlock when Windows calls NtCreateSection during flush - Miscellaneous bug fixes --- dll/shellext/shellbtrfs/shellbtrfs.rc | 10 +- dll/win32/ubtrfs/ubtrfs.rc | 10 +- drivers/filesystems/btrfs/boot.c | 360 +++------------------- drivers/filesystems/btrfs/btrfs.c | 49 ++- drivers/filesystems/btrfs/btrfs.inf | 2 +- drivers/filesystems/btrfs/btrfs.rc | 10 +- drivers/filesystems/btrfs/btrfs_drv.h | 12 +- drivers/filesystems/btrfs/create.c | 529 +++++++++++++++++++-------------- drivers/filesystems/btrfs/fastio.c | 46 +++ drivers/filesystems/btrfs/fileinfo.c | 132 +++++--- drivers/filesystems/btrfs/free-space.c | 3 + drivers/filesystems/btrfs/fsctl.c | 103 +++++-- drivers/filesystems/btrfs/pnp.c | 12 + drivers/filesystems/btrfs/reparse.c | 10 +- drivers/filesystems/btrfs/search.c | 2 +- drivers/filesystems/btrfs/security.c | 2 +- drivers/filesystems/btrfs/treefuncs.c | 6 + drivers/filesystems/btrfs/write.c | 15 +- sdk/lib/fslib/btrfslib/btrfslib.c | 7 - 19 files changed, 657 insertions(+), 663 deletions(-) diff --git a/dll/shellext/shellbtrfs/shellbtrfs.rc b/dll/shellext/shellbtrfs/shellbtrfs.rc index 4852681751d..845d8bc7844 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,5,0 - PRODUCTVERSION 1,7,5,0 + FILEVERSION 1,7,6,0 + PRODUCTVERSION 1,7,6,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -78,12 +78,12 @@ BEGIN BLOCK "080904b0" BEGIN VALUE "FileDescription", "WinBtrfs shell extension" - VALUE "FileVersion", "1.7.5" + VALUE "FileVersion", "1.7.6" VALUE "InternalName", "btrfs" - VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-20" + VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-21" VALUE "OriginalFilename", "shellbtrfs.dll" VALUE "ProductName", "WinBtrfs" - VALUE "ProductVersion", "1.7.5" + VALUE "ProductVersion", "1.7.6" END END BLOCK "VarFileInfo" diff --git a/dll/win32/ubtrfs/ubtrfs.rc b/dll/win32/ubtrfs/ubtrfs.rc index 686e30e7b3c..27eef7a7c0b 100644 --- a/dll/win32/ubtrfs/ubtrfs.rc +++ b/dll/win32/ubtrfs/ubtrfs.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,7,5,0 - PRODUCTVERSION 1,7,5,0 + FILEVERSION 1,7,6,0 + PRODUCTVERSION 1,7,6,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -68,12 +68,12 @@ BEGIN BLOCK "080904b0" BEGIN VALUE "FileDescription", "Btrfs utility DLL" - VALUE "FileVersion", "1.7.5" + VALUE "FileVersion", "1.7.6" VALUE "InternalName", "ubtrfs" - VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-20" + VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-21" VALUE "OriginalFilename", "ubtrfs.dll" VALUE "ProductName", "WinBtrfs" - VALUE "ProductVersion", "1.7.5" + VALUE "ProductVersion", "1.7.6" END END BLOCK "VarFileInfo" diff --git a/drivers/filesystems/btrfs/boot.c b/drivers/filesystems/btrfs/boot.c index 43486cfad33..011fd544c80 100644 --- a/drivers/filesystems/btrfs/boot.c +++ b/drivers/filesystems/btrfs/boot.c @@ -46,20 +46,7 @@ typedef struct { ULONG ExtensionFlags; } DEVOBJ_EXTENSION2; -typedef enum { - system_root_unknown, - system_root_partition, - system_root_btrfs -} system_root_type; - -typedef struct { - uint32_t disk_num; - uint32_t partition_num; - BTRFS_UUID uuid; - system_root_type type; -} system_root; - -static void get_system_root(system_root* sr) { +static bool get_system_root() { NTSTATUS Status; HANDLE h; UNICODE_STRING us, target; @@ -69,8 +56,6 @@ static void get_system_root(system_root* sr) { static const WCHAR system_root[] = L"\\SystemRoot"; static const WCHAR boot_device[] = L"\\Device\\BootDevice"; - static const WCHAR arc_prefix[] = L"\\ArcName\\multi(0)disk(0)rdisk("; - static const WCHAR arc_middle[] = L")partition("; static const WCHAR arc_btrfs_prefix[] = L"\\ArcName\\btrfs("; us.Buffer = (WCHAR*)system_root; @@ -82,7 +67,7 @@ static void get_system_root(system_root* sr) { Status = ZwOpenSymbolicLinkObject(&h, GENERIC_READ, &objatt); if (!NT_SUCCESS(Status)) { ERR("ZwOpenSymbolicLinkObject returned %08lx\n", Status); - return; + return false; } target.Length = target.MaximumLength = 0; @@ -91,19 +76,19 @@ static void get_system_root(system_root* sr) { if (Status != STATUS_BUFFER_TOO_SMALL) { ERR("ZwQuerySymbolicLinkObject returned %08lx\n", Status); NtClose(h); - return; + return false; } if (retlen == 0) { NtClose(h); - return; + return false; } target.Buffer = ExAllocatePoolWithTag(NonPagedPool, retlen, ALLOC_TAG); if (!target.Buffer) { ERR("out of memory\n"); NtClose(h); - return; + return false; } target.Length = target.MaximumLength = (USHORT)retlen; @@ -113,7 +98,7 @@ static void get_system_root(system_root* sr) { ERR("ZwQuerySymbolicLinkObject returned %08lx\n", Status); NtClose(h); ExFreePool(target.Buffer); - return; + return false; } NtClose(h); @@ -136,85 +121,33 @@ static void get_system_root(system_root* sr) { break; } - sr->type = system_root_unknown; - - if (target.Length >= sizeof(arc_prefix) - sizeof(WCHAR) && - RtlCompareMemory(target.Buffer, arc_prefix, sizeof(arc_prefix) - sizeof(WCHAR)) == sizeof(arc_prefix) - sizeof(WCHAR)) { - WCHAR* s = &target.Buffer[(sizeof(arc_prefix) / sizeof(WCHAR)) - 1]; - ULONG left = ((target.Length - sizeof(arc_prefix)) / sizeof(WCHAR)) + 1; - - if (left == 0 || s[0] < '0' || s[0] > '9') { - ExFreePool(target.Buffer); - return; - } - - sr->disk_num = 0; - - while (left > 0 && s[0] >= '0' && s[0] <= '9') { - sr->disk_num *= 10; - sr->disk_num += s[0] - '0'; - s++; - left--; - } - - if (left <= (sizeof(arc_middle) / sizeof(WCHAR)) - 1 || - RtlCompareMemory(s, arc_middle, sizeof(arc_middle) - sizeof(WCHAR)) != sizeof(arc_middle) - sizeof(WCHAR)) { - ExFreePool(target.Buffer); - return; - } - - s = &s[(sizeof(arc_middle) / sizeof(WCHAR)) - 1]; - left -= (sizeof(arc_middle) / sizeof(WCHAR)) - 1; - - if (left == 0 || s[0] < '0' || s[0] > '9') { - ExFreePool(target.Buffer); - return; - } - - sr->partition_num = 0; - - while (left > 0 && s[0] >= '0' && s[0] <= '9') { - sr->partition_num *= 10; - sr->partition_num += s[0] - '0'; - s++; - left--; - } - - sr->type = system_root_partition; - } else if (target.Length >= sizeof(arc_btrfs_prefix) - sizeof(WCHAR) && + if (target.Length >= sizeof(arc_btrfs_prefix) - sizeof(WCHAR) && RtlCompareMemory(target.Buffer, arc_btrfs_prefix, sizeof(arc_btrfs_prefix) - sizeof(WCHAR)) == sizeof(arc_btrfs_prefix) - sizeof(WCHAR)) { WCHAR* s = &target.Buffer[(sizeof(arc_btrfs_prefix) / sizeof(WCHAR)) - 1]; -#ifdef __REACTOS__ - unsigned int i; -#endif // __REACTOS__ -#ifndef __REACTOS__ for (unsigned int i = 0; i < 16; i++) { -#else - for (i = 0; i < 16; i++) { -#endif // __REACTOS__ if (*s >= '0' && *s <= '9') - sr->uuid.uuid[i] = (*s - '0') << 4; + boot_uuid.uuid[i] = (*s - '0') << 4; else if (*s >= 'a' && *s <= 'f') - sr->uuid.uuid[i] = (*s - 'a' + 0xa) << 4; + boot_uuid.uuid[i] = (*s - 'a' + 0xa) << 4; else if (*s >= 'A' && *s <= 'F') - sr->uuid.uuid[i] = (*s - 'A' + 0xa) << 4; + boot_uuid.uuid[i] = (*s - 'A' + 0xa) << 4; else { ExFreePool(target.Buffer); - return; + return false; } s++; if (*s >= '0' && *s <= '9') - sr->uuid.uuid[i] |= *s - '0'; + boot_uuid.uuid[i] |= *s - '0'; else if (*s >= 'a' && *s <= 'f') - sr->uuid.uuid[i] |= *s - 'a' + 0xa; + boot_uuid.uuid[i] |= *s - 'a' + 0xa; else if (*s >= 'A' && *s <= 'F') - sr->uuid.uuid[i] |= *s - 'A' + 0xa; + boot_uuid.uuid[i] |= *s - 'A' + 0xa; else { ExFreePool(target.Buffer); - return; + return false; } s++; @@ -222,7 +155,7 @@ static void get_system_root(system_root* sr) { if (i == 3 || i == 5 || i == 7 || i == 9) { if (*s != '-') { ExFreePool(target.Buffer); - return; + return false; } s++; @@ -231,97 +164,17 @@ static void get_system_root(system_root* sr) { if (*s != ')') { ExFreePool(target.Buffer); - return; + return false; } - sr->type = system_root_btrfs; - } - - 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]; + ExFreePool(target.Buffer); - while (n > 0) { - *ptr = L'0' + (n % 10); - ptr--; - n /= 10; + return true; } - 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; - WCHAR symlink[60], target[(sizeof(BTRFS_VOLUME_PREFIX) / sizeof(WCHAR)) + 36], *w; -#ifdef __REACTOS__ - unsigned int i; -#endif - - static const WCHAR dev_path1[] = L"\\Device\\Harddisk"; - static const WCHAR dev_path2[] = L"\\Partition"; - - us.Buffer = symlink; - us.Length = sizeof(dev_path1) - sizeof(WCHAR); - us.MaximumLength = sizeof(symlink); - - 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)) - ERR("IoDeleteSymbolicLink returned %08lx\n", Status); - - RtlCopyMemory(target, BTRFS_VOLUME_PREFIX, sizeof(BTRFS_VOLUME_PREFIX) - sizeof(WCHAR)); - - w = &target[(sizeof(BTRFS_VOLUME_PREFIX) / sizeof(WCHAR)) - 1]; - -#ifndef __REACTOS__ - for (unsigned int i = 0; i < 16; i++) { -#else - for (i = 0; i < 16; i++) { -#endif - *w = hex_digit(uuid->uuid[i] >> 4); w++; - *w = hex_digit(uuid->uuid[i] & 0xf); w++; - - if (i == 3 || i == 5 || i == 7 || i == 9) { - *w = L'-'; - w++; - } - } - - *w = L'}'; - - us2.Buffer = target; - us2.Length = us2.MaximumLength = sizeof(target); + ExFreePool(target.Buffer); - Status = IoCreateSymbolicLink(&us, &us2); - if (!NT_SUCCESS(Status)) - ERR("IoCreateSymbolicLink returned %08lx\n", Status); + return false; } static void mountmgr_notification(BTRFS_UUID* uuid) { @@ -332,9 +185,6 @@ static void mountmgr_notification(BTRFS_UUID* uuid) { ULONG mmtnlen; MOUNTMGR_TARGET_NAME* mmtn; WCHAR* w; -#ifdef __REACTOS__ - unsigned int i; -#endif RtlInitUnicodeString(&mmdevpath, MOUNTMGR_DEVICE_NAME); Status = IoGetDeviceObjectPointer(&mmdevpath, FILE_READ_ATTRIBUTES, &FileObject, &mountmgr); @@ -357,11 +207,7 @@ static void mountmgr_notification(BTRFS_UUID* uuid) { w = &mmtn->DeviceName[(sizeof(BTRFS_VOLUME_PREFIX) / sizeof(WCHAR)) - 1]; -#ifndef __REACTOS__ for (unsigned int i = 0; i < 16; i++) { -#else - for (i = 0; i < 16; i++) { -#endif *w = hex_digit(uuid->uuid[i] >> 4); w++; *w = hex_digit(uuid->uuid[i] & 0xf); w++; @@ -487,166 +333,52 @@ void boot_add_device(DEVICE_OBJECT* pdo) { mountmgr_notification(&pdode->uuid); } -/* If booting from Btrfs, Windows will pass the device object for the raw partition to - * mount_vol - which is no good to us, as we only use the \Device\Btrfs{} devices we - * create so that RAID works correctly. - * At the time check_system_root gets called, \SystemRoot is a symlink to the ARC device, - * e.g. \ArcName\multi(0)disk(0)rdisk(0)partition(1)\Windows. We can't change the symlink, - * as it gets clobbered by IopReassignSystemRoot shortly afterwards, and we can't touch - * the \ArcName symlinks as they haven't been created yet. Instead, we need to change the - * symlink \Device\HarddiskX\PartitionY, which is what the ArcName symlink will shortly - * point to. - */ -void __stdcall check_system_root(PDRIVER_OBJECT DriverObject, PVOID Context, ULONG Count) { - system_root sr; +void check_system_root() { LIST_ENTRY* le; - bool done = false; PDEVICE_OBJECT pdo_to_add = NULL; - volume_child* boot_vc = NULL; - - TRACE("(%p, %p, %lu)\n", DriverObject, Context, Count); - UNUSED(DriverObject); - UNUSED(Context); - UNUSED(Count); + TRACE("()\n"); // wait for any PNP notifications in progress to finish ExAcquireResourceExclusiveLite(&boot_lock, TRUE); ExReleaseResourceLite(&boot_lock); - get_system_root(&sr); - - if (sr.type == system_root_partition) { - TRACE("system boot partition is disk %u, partition %u\n", sr.disk_num, sr.partition_num); - - ExAcquireResourceSharedLite(&pdo_list_lock, true); - - le = pdo_list.Flink; - while (le != &pdo_list) { - LIST_ENTRY* le2; - pdo_device_extension* pdode = CONTAINING_RECORD(le, pdo_device_extension, list_entry); - - ExAcquireResourceSharedLite(&pdode->child_lock, true); - - le2 = pdode->children.Flink; - - while (le2 != &pdode->children) { - volume_child* vc = CONTAINING_RECORD(le2, volume_child, list_entry); - - if (vc->disk_num == sr.disk_num && vc->part_num == sr.partition_num) { - change_symlink(sr.disk_num, sr.partition_num, &pdode->uuid); - done = true; - - vc->boot_volume = true; - boot_uuid = pdode->uuid; - - if (!pdode->vde) - pdo_to_add = pdode->pdo; - - boot_vc = vc; - - break; - } - - le2 = le2->Flink; - } - - if (done) { - le2 = pdode->children.Flink; - - while (le2 != &pdode->children) { - volume_child* vc = CONTAINING_RECORD(le2, volume_child, list_entry); - - /* On Windows 7 we need to clear the DO_SYSTEM_BOOT_PARTITION flag of - * all of our underlying partition objects - otherwise IopMountVolume - * will bugcheck with UNMOUNTABLE_BOOT_VOLUME when it tries and fails - * to mount one. */ - if (vc->devobj) { - PDEVICE_OBJECT dev = vc->devobj; - - ObReferenceObject(dev); - - while (dev) { - PDEVICE_OBJECT dev2 = IoGetLowerDeviceObject(dev); - - dev->Flags &= ~DO_SYSTEM_BOOT_PARTITION; - - ObDereferenceObject(dev); - - dev = dev2; - } - } - - le2 = le2->Flink; - } - - ExReleaseResourceLite(&pdode->child_lock); - - break; - } - - ExReleaseResourceLite(&pdode->child_lock); + if (!get_system_root()) + return; - le = le->Flink; - } + ExAcquireResourceSharedLite(&pdo_list_lock, true); - ExReleaseResourceLite(&pdo_list_lock); - } else if (sr.type == system_root_btrfs) { - boot_uuid = sr.uuid; + le = pdo_list.Flink; + while (le != &pdo_list) { + pdo_device_extension* pdode = CONTAINING_RECORD(le, pdo_device_extension, list_entry); - ExAcquireResourceSharedLite(&pdo_list_lock, true); + if (RtlCompareMemory(&pdode->uuid, &boot_uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) { + if (!pdode->vde) + pdo_to_add = pdode->pdo; + else if (pdode->vde->device && !(pdode->vde->device->Flags & DO_SYSTEM_BOOT_PARTITION)) { // AddDevice has beaten us to it + NTSTATUS Status; - le = pdo_list.Flink; - while (le != &pdo_list) { - pdo_device_extension* pdode = CONTAINING_RECORD(le, pdo_device_extension, list_entry); + pdode->vde->device->Flags |= DO_SYSTEM_BOOT_PARTITION; + pdode->pdo->Flags |= DO_SYSTEM_BOOT_PARTITION; - if (RtlCompareMemory(&pdode->uuid, &sr.uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) { - if (!pdode->vde) - pdo_to_add = pdode->pdo; + Status = IoSetDeviceInterfaceState(&pdode->vde->bus_name, false); + if (!NT_SUCCESS(Status)) + ERR("IoSetDeviceInterfaceState returned %08lx\n", Status); - break; + Status = IoSetDeviceInterfaceState(&pdode->vde->bus_name, true); + if (!NT_SUCCESS(Status)) + ERR("IoSetDeviceInterfaceState returned %08lx\n", Status); } - le = le->Flink; + break; } - ExReleaseResourceLite(&pdo_list_lock); + le = le->Flink; } - if (boot_vc) { - NTSTATUS Status; - UNICODE_STRING name; - - /* On Windows 8, mountmgr!MountMgrFindBootVolume returns the first volume in its database - * with the DO_SYSTEM_BOOT_PARTITION flag set. We've cleared the bit on the underlying devices, - * but as it caches it we need to disable and re-enable the volume so mountmgr receives a PNP - * notification to refresh its list. */ - - static const WCHAR prefix[] = L"\\??"; - - name.Length = name.MaximumLength = boot_vc->pnp_name.Length + sizeof(prefix) - sizeof(WCHAR); - - name.Buffer = ExAllocatePoolWithTag(PagedPool, name.MaximumLength, ALLOC_TAG); - if (!name.Buffer) - ERR("out of memory\n"); - else { - RtlCopyMemory(name.Buffer, prefix, sizeof(prefix) - sizeof(WCHAR)); - RtlCopyMemory(&name.Buffer[(sizeof(prefix) / sizeof(WCHAR)) - 1], boot_vc->pnp_name.Buffer, boot_vc->pnp_name.Length); - - Status = IoSetDeviceInterfaceState(&name, false); - if (!NT_SUCCESS(Status)) - ERR("IoSetDeviceInterfaceState returned %08lx\n", Status); - - Status = IoSetDeviceInterfaceState(&name, true); - if (!NT_SUCCESS(Status)) - ERR("IoSetDeviceInterfaceState returned %08lx\n", Status); - - ExFreePool(name.Buffer); - } - } + ExReleaseResourceLite(&pdo_list_lock); - if (sr.type == system_root_btrfs || boot_vc) - check_boot_options(); + check_boot_options(); // If our FS depends on volumes that aren't there when we do our IoRegisterPlugPlayNotification calls // in DriverEntry, bus_query_device_relations won't get called until it's too late. We need to do our diff --git a/drivers/filesystems/btrfs/btrfs.c b/drivers/filesystems/btrfs/btrfs.c index 2f2932f1205..6c821f12534 100644 --- a/drivers/filesystems/btrfs/btrfs.c +++ b/drivers/filesystems/btrfs/btrfs.c @@ -667,6 +667,9 @@ static bool lie_about_fs_type() { INIT_UNICODE_STRING(fsutil, L"FSUTIL.EXE"); INIT_UNICODE_STRING(storsvc, L"STORSVC.DLL"); + /* Not doing a Volkswagen, honest! Some IFS tests won't run if not recognized FS. */ + INIT_UNICODE_STRING(ifstest, L"IFSTEST.EXE"); + if (!PsGetCurrentProcess()) return false; @@ -733,6 +736,15 @@ static bool lie_about_fs_type() { blacklist = FsRtlAreNamesEqual(&name, &usstorsvc, true, NULL); } + if (!blacklist && entry->FullDllName.Length >= usifstest.Length) { + UNICODE_STRING name; + + name.Buffer = &entry->FullDllName.Buffer[(entry->FullDllName.Length - usifstest.Length) / sizeof(WCHAR)]; + name.Length = name.MaximumLength = usifstest.Length; + + blacklist = FsRtlAreNamesEqual(&name, &usifstest, true, NULL); + } + if (blacklist) { void** frames; ULONG i, num_frames; @@ -1833,10 +1845,6 @@ void reap_fileref(device_extension* Vcb, file_ref* fr) { // FIXME - do delete if needed - ExDeleteResourceLite(&fr->nonpaged->fileref_lock); - - ExFreeToNPagedLookasideList(&Vcb->fileref_np_lookaside, fr->nonpaged); - // FIXME - throw error if children not empty if (fr->fcb->fileref == fr) @@ -2161,7 +2169,6 @@ void uninit(_In_ device_extension* Vcb) { ExDeletePagedLookasideList(&Vcb->fcb_lookaside); ExDeletePagedLookasideList(&Vcb->name_bit_lookaside); ExDeleteNPagedLookasideList(&Vcb->range_lock_lookaside); - ExDeleteNPagedLookasideList(&Vcb->fileref_np_lookaside); ExDeleteNPagedLookasideList(&Vcb->fcb_np_lookaside); ZwClose(Vcb->flush_thread_handle); @@ -4709,7 +4716,6 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) { ExInitializePagedLookasideList(&Vcb->fcb_lookaside, NULL, NULL, 0, sizeof(fcb), ALLOC_TAG, 0); ExInitializePagedLookasideList(&Vcb->name_bit_lookaside, NULL, NULL, 0, sizeof(name_bit), ALLOC_TAG, 0); ExInitializeNPagedLookasideList(&Vcb->range_lock_lookaside, NULL, NULL, 0, sizeof(range_lock), ALLOC_TAG, 0); - ExInitializeNPagedLookasideList(&Vcb->fileref_np_lookaside, NULL, NULL, 0, sizeof(file_ref_nonpaged), ALLOC_TAG, 0); ExInitializeNPagedLookasideList(&Vcb->fcb_np_lookaside, NULL, NULL, 0, sizeof(fcb_nonpaged), ALLOC_TAG, 0); init_lookaside = true; @@ -5027,7 +5033,6 @@ exit2: ExDeletePagedLookasideList(&Vcb->fcb_lookaside); ExDeletePagedLookasideList(&Vcb->name_bit_lookaside); ExDeleteNPagedLookasideList(&Vcb->range_lock_lookaside); - ExDeleteNPagedLookasideList(&Vcb->fileref_np_lookaside); ExDeleteNPagedLookasideList(&Vcb->fcb_np_lookaside); } @@ -5764,27 +5769,43 @@ exit: return Status; } -bool is_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream) { +NTSTATUS check_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream) { ULONG i; if (us->Length < sizeof(WCHAR)) - return false; + return STATUS_OBJECT_NAME_INVALID; if (us->Length > 255 * sizeof(WCHAR)) - return false; + return STATUS_OBJECT_NAME_INVALID; for (i = 0; i < us->Length / sizeof(WCHAR); i++) { if (us->Buffer[i] == '/' || us->Buffer[i] == 0 || (!posix && (us->Buffer[i] == '/' || us->Buffer[i] == ':')) || (!posix && !stream && (us->Buffer[i] == '<' || us->Buffer[i] == '>' || us->Buffer[i] == '"' || us->Buffer[i] == '|' || us->Buffer[i] == '?' || us->Buffer[i] == '*' || (us->Buffer[i] >= 1 && us->Buffer[i] <= 31)))) - return false; + return STATUS_OBJECT_NAME_INVALID; } if (us->Buffer[0] == '.' && (us->Length == sizeof(WCHAR) || (us->Length == 2 * sizeof(WCHAR) && us->Buffer[1] == '.'))) - return false; + return STATUS_OBJECT_NAME_INVALID; - return true; + /* The Linux driver expects filenames with a maximum length of 255 bytes - make sure + * that our UTF-8 length won't be longer than that. */ + if (us->Length >= 85 * sizeof(WCHAR)) { + NTSTATUS Status; + ULONG utf8len; + + Status = utf16_to_utf8(NULL, 0, &utf8len, us->Buffer, us->Length); + if (!NT_SUCCESS(Status)) + return Status; + + if (utf8len > 255) + return STATUS_OBJECT_NAME_INVALID; + else if (stream && utf8len > 250) // minus five bytes for "user." + return STATUS_OBJECT_NAME_INVALID; + } + + return STATUS_SUCCESS; } void chunk_lock_range(_In_ device_extension* Vcb, _In_ chunk* c, _In_ uint64_t start, _In_ uint64_t length) { @@ -6519,7 +6540,7 @@ NTSTATUS __stdcall DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_S IoRegisterFileSystem(DeviceObject); - IoRegisterBootDriverReinitialization(DriverObject, check_system_root, NULL); + check_system_root(); return STATUS_SUCCESS; } diff --git a/drivers/filesystems/btrfs/btrfs.inf b/drivers/filesystems/btrfs/btrfs.inf index ac8ff69dc4d..42a3e97068c 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 = 10/31/2020,1.7.5.0 +DriverVer = 01/14/2021,1.7.6.0 CatalogFile = btrfs.cat [DestinationDirs] diff --git a/drivers/filesystems/btrfs/btrfs.rc b/drivers/filesystems/btrfs/btrfs.rc index e7a7ad6c280..198fcc4e8a9 100644 --- a/drivers/filesystems/btrfs/btrfs.rc +++ b/drivers/filesystems/btrfs/btrfs.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,7,5,0 - PRODUCTVERSION 1,7,5,0 + FILEVERSION 1,7,6,0 + PRODUCTVERSION 1,7,6,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -68,12 +68,12 @@ BEGIN BLOCK "080904b0" BEGIN VALUE "FileDescription", "WinBtrfs" - VALUE "FileVersion", "1.7.5" + VALUE "FileVersion", "1.7.6" VALUE "InternalName", "btrfs" - VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-20" + VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-21" VALUE "OriginalFilename", "btrfs.sys" VALUE "ProductName", "WinBtrfs" - VALUE "ProductVersion", "1.7.5" + VALUE "ProductVersion", "1.7.6" END END BLOCK "VarFileInfo" diff --git a/drivers/filesystems/btrfs/btrfs_drv.h b/drivers/filesystems/btrfs/btrfs_drv.h index 0e2554adbc3..106332d77c4 100644 --- a/drivers/filesystems/btrfs/btrfs_drv.h +++ b/drivers/filesystems/btrfs/btrfs_drv.h @@ -338,10 +338,6 @@ typedef struct _fcb { LIST_ENTRY list_entry_dirty; } fcb; -typedef struct { - ERESOURCE fileref_lock; -} file_ref_nonpaged; - typedef struct _file_ref { fcb* fcb; ANSI_STRING oldutf8; @@ -350,7 +346,6 @@ typedef struct _file_ref { bool posix_delete; bool deleted; bool created; - file_ref_nonpaged* nonpaged; LIST_ENTRY children; LONG refcount; LONG open_count; @@ -832,7 +827,6 @@ typedef struct _device_extension { PAGED_LOOKASIDE_LIST fcb_lookaside; PAGED_LOOKASIDE_LIST name_bit_lookaside; NPAGED_LOOKASIDE_LIST range_lock_lookaside; - NPAGED_LOOKASIDE_LIST fileref_np_lookaside; NPAGED_LOOKASIDE_LIST fcb_np_lookaside; LIST_ENTRY list_entry; } device_extension; @@ -1122,7 +1116,7 @@ NTSTATUS create_root(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) devi void uninit(_In_ device_extension* Vcb); NTSTATUS dev_ioctl(_In_ PDEVICE_OBJECT DeviceObject, _In_ ULONG ControlCode, _In_reads_bytes_opt_(InputBufferSize) PVOID InputBuffer, _In_ ULONG InputBufferSize, _Out_writes_bytes_opt_(OutputBufferSize) PVOID OutputBuffer, _In_ ULONG OutputBufferSize, _In_ bool Override, _Out_opt_ IO_STATUS_BLOCK* iosb); -bool is_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream); +NTSTATUS check_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream); void send_notification_fileref(_In_ file_ref* fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream); void queue_notification_fcb(_In_ file_ref* fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream); @@ -1419,6 +1413,8 @@ NTSTATUS stream_set_end_of_file_information(device_extension* Vcb, uint16_t end, NTSTATUS fileref_get_filename(file_ref* fileref, PUNICODE_STRING fn, USHORT* name_offset, ULONG* preqlen); void insert_dir_child_into_hash_lists(fcb* fcb, dir_child* dc); void remove_dir_child_from_hash_lists(fcb* fcb, dir_child* dc); +void add_fcb_to_subvol(_In_ _Requires_exclusive_lock_held_(_Curr_->Vcb->fcb_lock) fcb* fcb); +void remove_fcb_from_subvol(_In_ _Requires_exclusive_lock_held_(_Curr_->Vcb->fcb_lock) fcb* fcb); // in reparse.c NTSTATUS get_reparse_point(PFILE_OBJECT FileObject, void* buffer, DWORD buflen, ULONG_PTR* retlen); @@ -1626,7 +1622,7 @@ NTSTATUS read_send_buffer(device_extension* Vcb, PFILE_OBJECT FileObject, void* NTSTATUS __stdcall compat_FsRtlValidateReparsePointBuffer(IN ULONG BufferLength, IN PREPARSE_DATA_BUFFER ReparseBuffer); // in boot.c -void __stdcall check_system_root(PDRIVER_OBJECT DriverObject, PVOID Context, ULONG Count); +void check_system_root(); void boot_add_device(DEVICE_OBJECT* pdo); extern BTRFS_UUID boot_uuid; diff --git a/drivers/filesystems/btrfs/create.c b/drivers/filesystems/btrfs/create.c index 25b0b975e53..e678a096167 100644 --- a/drivers/filesystems/btrfs/create.c +++ b/drivers/filesystems/btrfs/create.c @@ -80,6 +80,12 @@ static const GUID GUID_ECP_ATOMIC_CREATE = { 0x4720bd83, 0x52ac, 0x4104, { 0xa1, static const GUID GUID_ECP_QUERY_ON_CREATE = { 0x1aca62e9, 0xabb4, 0x4ff2, { 0xbb, 0x5c, 0x1c, 0x79, 0x02, 0x5e, 0x41, 0x7f } }; static const GUID GUID_ECP_CREATE_REDIRECTION = { 0x188d6bd6, 0xa126, 0x4fa8, { 0xbd, 0xf2, 0x1c, 0xcd, 0xf8, 0x96, 0xf3, 0xe0 } }; +typedef struct { + device_extension* Vcb; + ACCESS_MASK granted_access; + file_ref* fileref; +} oplock_context; + fcb* create_fcb(device_extension* Vcb, POOL_TYPE pool_type) { fcb* fcb; @@ -160,13 +166,6 @@ file_ref* create_fileref(device_extension* Vcb) { RtlZeroMemory(fr, sizeof(file_ref)); - fr->nonpaged = ExAllocateFromNPagedLookasideList(&Vcb->fileref_np_lookaside); - if (!fr->nonpaged) { - ERR("out of memory\n"); - ExFreeToPagedLookasideList(&Vcb->fileref_lookaside, fr); - return NULL; - } - fr->refcount = 1; #ifdef DEBUG_FCB_REFCOUNTS @@ -175,8 +174,6 @@ file_ref* create_fileref(device_extension* Vcb) { InitializeListHead(&fr->children); - ExInitializeResourceLite(&fr->nonpaged->fileref_lock); - return fr; } @@ -1596,7 +1593,7 @@ NTSTATUS open_fileref_child(_Requires_lock_held_(_Curr_->tree_lock) _Requires_ex ExReleaseResourceLite(&sf->fcb->nonpaged->dir_children_lock); if (duff_fr) - reap_fileref(Vcb, duff_fr); + ExFreeToPagedLookasideList(&Vcb->fileref_lookaside, duff_fr); } else { root* subvol; uint64_t inode; @@ -1652,9 +1649,6 @@ NTSTATUS open_fileref_child(_Requires_lock_held_(_Curr_->tree_lock) _Requires_ex sf2->fcb = fcb; - if (dc->type == BTRFS_TYPE_DIRECTORY) - fcb->fileref = sf2; - ExAcquireResourceExclusiveLite(&sf->fcb->nonpaged->dir_children_lock, true); if (!dc->fileref) { @@ -1663,6 +1657,9 @@ NTSTATUS open_fileref_child(_Requires_lock_held_(_Curr_->tree_lock) _Requires_ex dc->fileref = sf2; InsertTailList(&sf->children, &sf2->list_entry); increase_fileref_refcount(sf); + + if (dc->type == BTRFS_TYPE_DIRECTORY) + fcb->fileref = sf2; } else { duff_fr = sf2; sf2 = dc->fileref; @@ -2654,9 +2651,6 @@ static NTSTATUS create_stream(_Requires_lock_held_(_Curr_->tree_lock) _Requires_ #ifdef DEBUG_FCB_REFCOUNTS LONG rc; #endif -#ifdef __REACTOS__ - LIST_ENTRY* le; -#endif TRACE("fpus = %.*S\n", (int)(fpus->Length / sizeof(WCHAR)), fpus->Buffer); TRACE("stream = %.*S\n", (int)(stream->Length / sizeof(WCHAR)), stream->Buffer); @@ -2671,8 +2665,9 @@ static NTSTATUS create_stream(_Requires_lock_held_(_Curr_->tree_lock) _Requires_ if (Status == STATUS_OBJECT_NAME_NOT_FOUND) { UNICODE_STRING fpus2; - if (!is_file_name_valid(fpus, false, true)) - return STATUS_OBJECT_NAME_INVALID; + Status = check_file_name_valid(fpus, false, true); + if (!NT_SUCCESS(Status)) + return Status; fpus2.Length = fpus2.MaximumLength = fpus->Length; fpus2.Buffer = ExAllocatePoolWithTag(pool_type, fpus2.MaximumLength, ALLOC_TAG); @@ -2775,6 +2770,7 @@ static NTSTATUS create_stream(_Requires_lock_held_(_Curr_->tree_lock) _Requires_ #endif fcb->subvol = parfileref->fcb->subvol; fcb->inode = parfileref->fcb->inode; + fcb->hash = parfileref->fcb->hash; fcb->type = parfileref->fcb->type; fcb->ads = true; @@ -2913,11 +2909,7 @@ static NTSTATUS create_stream(_Requires_lock_held_(_Curr_->tree_lock) _Requires_ ExAcquireResourceExclusiveLite(&parfileref->fcb->nonpaged->dir_children_lock, true); -#ifndef __REACTOS__ LIST_ENTRY* le = parfileref->fcb->dir_children_index.Flink; -#else - le = parfileref->fcb->dir_children_index.Flink; -#endif while (le != &parfileref->fcb->dir_children_index) { dir_child* dc2 = CONTAINING_RECORD(le, dir_child, list_entry_index); @@ -3143,10 +3135,9 @@ static NTSTATUS file_create(PIRP Irp, _Requires_lock_held_(_Curr_->tree_lock) _R } else { ACCESS_MASK granted_access; - if (!is_file_name_valid(&fpus, false, false)) { - Status = STATUS_OBJECT_NAME_INVALID; + Status = check_file_name_valid(&fpus, false, false); + if (!NT_SUCCESS(Status)) goto end; - } SeLockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext); @@ -3581,168 +3572,18 @@ end: fcb->csum_loaded = true; } -static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, POOL_TYPE pool_type, file_ref* fileref, ACCESS_MASK* granted_access, - PFILE_OBJECT FileObject, UNICODE_STRING* fn, ULONG options, PIRP Irp, LIST_ENTRY* rollback) { +static NTSTATUS open_file3(device_extension* Vcb, PIRP Irp, ACCESS_MASK granted_access, file_ref* fileref, LIST_ENTRY* rollback) { NTSTATUS Status; - file_ref* sf; - bool readonly; - ccb* ccb; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + ULONG options = IrpSp->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS; + ULONG RequestedDisposition = ((IrpSp->Parameters.Create.Options >> 24) & 0xff); + PFILE_OBJECT FileObject = IrpSp->FileObject; + POOL_TYPE pool_type = IrpSp->Flags & SL_OPEN_PAGING_FILE ? NonPagedPool : PagedPool; + ccb* ccb; - if (RequestedDisposition == FILE_SUPERSEDE || RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF) { - LARGE_INTEGER zero; - - if (fileref->fcb->type == BTRFS_TYPE_DIRECTORY || is_subvol_readonly(fileref->fcb->subvol, Irp)) { - Status = STATUS_ACCESS_DENIED; - goto end; - } - - if (Vcb->readonly) { - Status = STATUS_MEDIA_WRITE_PROTECTED; - goto end; - } - - zero.QuadPart = 0; - if (!MmCanFileBeTruncated(&fileref->fcb->nonpaged->segment_object, &zero)) { - Status = STATUS_USER_MAPPED_FILE; - goto end; - } - } - - if (IrpSp->Parameters.Create.SecurityContext->DesiredAccess != 0) { - SeLockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext); - - if (!SeAccessCheck((fileref->fcb->ads || fileref->fcb == Vcb->dummy_fcb) ? fileref->parent->fcb->sd : fileref->fcb->sd, - &IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext, - true, IrpSp->Parameters.Create.SecurityContext->DesiredAccess, 0, NULL, - IoGetFileObjectGenericMapping(), IrpSp->Flags & SL_FORCE_ACCESS_CHECK ? UserMode : Irp->RequestorMode, - granted_access, &Status)) { - SeUnlockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext); - TRACE("SeAccessCheck failed, returning %08lx\n", Status); - goto end; - } - - SeUnlockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext); - } else - *granted_access = 0; - - TRACE("deleted = %s\n", fileref->deleted ? "true" : "false"); - - sf = fileref; - while (sf) { - if (sf->delete_on_close) { - TRACE("could not open as deletion pending\n"); - Status = STATUS_DELETE_PENDING; - goto end; - } - sf = sf->parent; - } - - 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)) { - Status = STATUS_CANNOT_DELETE; - goto end; - } - - if (readonly) { - ACCESS_MASK allowed; - - allowed = READ_CONTROL | SYNCHRONIZE | ACCESS_SYSTEM_SECURITY | FILE_READ_DATA | - FILE_READ_EA | FILE_READ_ATTRIBUTES | FILE_EXECUTE | FILE_LIST_DIRECTORY | - FILE_TRAVERSE; - - if (!Vcb->readonly && (fileref->fcb == Vcb->dummy_fcb || fileref->fcb->inode == SUBVOL_ROOT_INODE)) - allowed |= DELETE; - - if (fileref->fcb != Vcb->dummy_fcb && !is_subvol_readonly(fileref->fcb->subvol, Irp) && !Vcb->readonly) { - allowed |= DELETE | WRITE_OWNER | WRITE_DAC | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES; - - if (!fileref->fcb->ads && fileref->fcb->type == BTRFS_TYPE_DIRECTORY) - allowed |= FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE | FILE_DELETE_CHILD; - } else if (fileref->fcb->inode == SUBVOL_ROOT_INODE && is_subvol_readonly(fileref->fcb->subvol, Irp) && !Vcb->readonly) { - // We allow a subvolume root to be opened read-write even if its readonly flag is set, so it can be cleared - - allowed |= FILE_WRITE_ATTRIBUTES; - } - - if (IrpSp->Parameters.Create.SecurityContext->DesiredAccess & MAXIMUM_ALLOWED) { - *granted_access &= allowed; - IrpSp->Parameters.Create.SecurityContext->AccessState->PreviouslyGrantedAccess &= allowed; - } else if (*granted_access & ~allowed) { - Status = Vcb->readonly ? STATUS_MEDIA_WRITE_PROTECTED : STATUS_ACCESS_DENIED; - goto end; - } - } - - if ((fileref->fcb->type == BTRFS_TYPE_SYMLINK || fileref->fcb->atts & FILE_ATTRIBUTE_REPARSE_POINT) && !(options & FILE_OPEN_REPARSE_POINT)) { - REPARSE_DATA_BUFFER* data; - - /* How reparse points work from the point of view of the filesystem appears to - * undocumented. When returning STATUS_REPARSE, MSDN encourages us to return - * IO_REPARSE in Irp->IoStatus.Information, but that means we have to do our own - * translation. If we instead return the reparse tag in Information, and store - * a pointer to the reparse data buffer in Irp->Tail.Overlay.AuxiliaryBuffer, - * IopSymlinkProcessReparse will do the translation for us. */ - - Status = get_reparse_block(fileref->fcb, (uint8_t**)&data); - if (!NT_SUCCESS(Status)) { - ERR("get_reparse_block returned %08lx\n", Status); - Status = STATUS_SUCCESS; - } else { - Irp->IoStatus.Information = data->ReparseTag; - - if (fn->Buffer[(fn->Length / sizeof(WCHAR)) - 1] == '\\') - data->Reserved = sizeof(WCHAR); - - Irp->Tail.Overlay.AuxiliaryBuffer = (void*)data; - - Status = STATUS_REPARSE; - goto end; - } - } - - if (fileref->fcb->type == BTRFS_TYPE_DIRECTORY && !fileref->fcb->ads) { - if (options & FILE_NON_DIRECTORY_FILE && !(fileref->fcb->atts & FILE_ATTRIBUTE_REPARSE_POINT)) { - Status = STATUS_FILE_IS_A_DIRECTORY; - goto end; - } - } else if (options & FILE_DIRECTORY_FILE) { - TRACE("returning STATUS_NOT_A_DIRECTORY (type = %u)\n", fileref->fcb->type); - Status = STATUS_NOT_A_DIRECTORY; - goto end; - } - - if (fileref->open_count > 0) { - Status = IoCheckShareAccess(*granted_access, IrpSp->Parameters.Create.ShareAccess, FileObject, &fileref->fcb->share_access, false); - - if (!NT_SUCCESS(Status)) { - if (Status == STATUS_SHARING_VIOLATION) - TRACE("IoCheckShareAccess failed, returning %08lx\n", Status); - else - WARN("IoCheckShareAccess failed, returning %08lx\n", Status); - - goto end; - } - - IoUpdateShareAccess(FileObject, &fileref->fcb->share_access); - } else - IoSetShareAccess(*granted_access, IrpSp->Parameters.Create.ShareAccess, FileObject, &fileref->fcb->share_access); - - if (*granted_access & FILE_WRITE_DATA || options & FILE_DELETE_ON_CLOSE) { - if (!MmFlushImageSection(&fileref->fcb->nonpaged->segment_object, MmFlushForWrite)) { - Status = (options & FILE_DELETE_ON_CLOSE) ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION; - goto end2; - } - } - - // FIXME - this can block waiting for network IO, while we're holding fileref_lock and tree_lock - Status = FsRtlCheckOplock(fcb_oplock(fileref->fcb), Irp, NULL, NULL, NULL); - if (!NT_SUCCESS(Status)) { - WARN("FsRtlCheckOplock returned %08lx\n", Status); - goto end2; + if (granted_access & FILE_WRITE_DATA || options & FILE_DELETE_ON_CLOSE) { + if (!MmFlushImageSection(&fileref->fcb->nonpaged->segment_object, MmFlushForWrite)) + return (options & FILE_DELETE_ON_CLOSE) ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION; } if (RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF || RequestedDisposition == FILE_SUPERSEDE) { @@ -3750,28 +3591,20 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO LARGE_INTEGER time; BTRFS_TIME now; - if ((RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF) && readonly) { - WARN("cannot overwrite readonly file\n"); - Status = STATUS_ACCESS_DENIED; - goto end2; - } - - if (!fileref->fcb->ads && (IrpSp->Parameters.Create.FileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != ((fileref->fcb->atts & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))) { - Status = STATUS_ACCESS_DENIED; - goto end2; - } + if (!fileref->fcb->ads && (IrpSp->Parameters.Create.FileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != ((fileref->fcb->atts & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))) + return STATUS_ACCESS_DENIED; if (fileref->fcb->ads) { Status = stream_set_end_of_file_information(Vcb, 0, fileref->fcb, fileref, false); if (!NT_SUCCESS(Status)) { ERR("stream_set_end_of_file_information returned %08lx\n", Status); - goto end2; + return Status; } } else { Status = truncate_file(fileref->fcb, 0, Irp, rollback); if (!NT_SUCCESS(Status)) { ERR("truncate_file returned %08lx\n", Status); - goto end2; + return Status; } } @@ -3780,7 +3613,7 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO if (!NT_SUCCESS(Status)) { ERR("extend_file returned %08lx\n", Status); - goto end2; + return Status; } } @@ -3794,7 +3627,7 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO Status = IoCheckEaBufferValidity(Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.Create.EaLength, &offset); if (!NT_SUCCESS(Status)) { ERR("IoCheckEaBufferValidity returned %08lx (error at offset %lu)\n", Status, offset); - goto end2; + return Status; } fileref->fcb->ealen = 4; @@ -3823,8 +3656,7 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO fileref->fcb->ea_xattr.Buffer = ExAllocatePoolWithTag(pool_type, IrpSp->Parameters.Create.EaLength, ALLOC_TAG); if (!fileref->fcb->ea_xattr.Buffer) { ERR("out of memory\n"); - Status = STATUS_INSUFFICIENT_RESOURCES; - goto end2; + return STATUS_INSUFFICIENT_RESOURCES; } fileref->fcb->ea_xattr.Length = fileref->fcb->ea_xattr.MaximumLength = (USHORT)IrpSp->Parameters.Create.EaLength; @@ -3861,7 +3693,7 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO Status = delete_fileref(dc->fileref, NULL, false, NULL, rollback); if (!NT_SUCCESS(Status)) { ERR("delete_fileref returned %08lx\n", Status); - goto end2; + return Status; } } } else @@ -3917,8 +3749,7 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO if (ffei->Flags & FILE_NEED_EA) { WARN("returning STATUS_ACCESS_DENIED as no EA knowledge\n"); - Status = STATUS_ACCESS_DENIED; - goto end2; + return STATUS_ACCESS_DENIED; } if (ffei->NextEntryOffset == 0) @@ -3935,8 +3766,7 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO if (!ccb) { ERR("out of memory\n"); - Status = STATUS_INSUFFICIENT_RESOURCES; - goto end2; + return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(ccb, sizeof(*ccb)); @@ -3949,7 +3779,7 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO RtlInitUnicodeString(&ccb->query_string, NULL); ccb->has_wildcard = false; ccb->specific_file = false; - ccb->access = *granted_access; + ccb->access = granted_access; ccb->case_sensitive = IrpSp->Flags & SL_CASE_SENSITIVE; ccb->reserving = false; ccb->lxss = called_from_lxss(); @@ -4014,9 +3844,264 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO #endif InterlockedIncrement(&Vcb->open_files); - Status = STATUS_SUCCESS; + return STATUS_SUCCESS; +} + +static void oplock_complete(PVOID Context, PIRP Irp) { + NTSTATUS Status; + LIST_ENTRY rollback; + bool skip_lock; + oplock_context* ctx = Context; + device_extension* Vcb = ctx->Vcb; + + TRACE("(%p, %p)\n", Context, Irp); + + InitializeListHead(&rollback); + + skip_lock = ExIsResourceAcquiredExclusiveLite(&Vcb->tree_lock); + + if (!skip_lock) + ExAcquireResourceSharedLite(&Vcb->tree_lock, true); + + ExAcquireResourceSharedLite(&Vcb->fileref_lock, true); + + // FIXME - trans + Status = open_file3(Vcb, Irp, ctx->granted_access, ctx->fileref, &rollback); + + if (!NT_SUCCESS(Status)) { + free_fileref(ctx->fileref); + do_rollback(ctx->Vcb, &rollback); + } else + clear_rollback(&rollback); + + ExReleaseResourceLite(&Vcb->fileref_lock); + + if (Status == STATUS_SUCCESS) { + fcb* fcb2; + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + PFILE_OBJECT FileObject = IrpSp->FileObject; + bool skip_fcb_lock; + + IrpSp->Parameters.Create.SecurityContext->AccessState->PreviouslyGrantedAccess |= ctx->granted_access; + IrpSp->Parameters.Create.SecurityContext->AccessState->RemainingDesiredAccess &= ~(ctx->granted_access | MAXIMUM_ALLOWED); + + if (!FileObject->Vpb) + FileObject->Vpb = Vcb->devobj->Vpb; + + fcb2 = FileObject->FsContext; + + if (fcb2->ads) { + struct _ccb* ccb2 = FileObject->FsContext2; + + fcb2 = ccb2->fileref->parent->fcb; + } + + skip_fcb_lock = ExIsResourceAcquiredExclusiveLite(fcb2->Header.Resource); + + if (!skip_fcb_lock) + ExAcquireResourceExclusiveLite(fcb2->Header.Resource, true); + + fcb_load_csums(Vcb, fcb2, Irp); + + if (!skip_fcb_lock) + ExReleaseResourceLite(fcb2->Header.Resource); + } + + if (!skip_lock) + ExReleaseResourceLite(&Vcb->tree_lock); + + // FIXME - call free_trans if failed and within transaction + + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT); + + ExFreePool(ctx); +} + +static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, file_ref* fileref, ACCESS_MASK* granted_access, + PFILE_OBJECT FileObject, UNICODE_STRING* fn, ULONG options, PIRP Irp, LIST_ENTRY* rollback) { + NTSTATUS Status; + file_ref* sf; + bool readonly; + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + + if (RequestedDisposition == FILE_SUPERSEDE || RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF) { + LARGE_INTEGER zero; + + if (fileref->fcb->type == BTRFS_TYPE_DIRECTORY || is_subvol_readonly(fileref->fcb->subvol, Irp)) { + Status = STATUS_ACCESS_DENIED; + goto end; + } + + if (Vcb->readonly) { + Status = STATUS_MEDIA_WRITE_PROTECTED; + goto end; + } + + zero.QuadPart = 0; + if (!MmCanFileBeTruncated(&fileref->fcb->nonpaged->segment_object, &zero)) { + Status = STATUS_USER_MAPPED_FILE; + goto end; + } + } + + if (IrpSp->Parameters.Create.SecurityContext->DesiredAccess != 0) { + SeLockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext); + + if (!SeAccessCheck((fileref->fcb->ads || fileref->fcb == Vcb->dummy_fcb) ? fileref->parent->fcb->sd : fileref->fcb->sd, + &IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext, + true, IrpSp->Parameters.Create.SecurityContext->DesiredAccess, 0, NULL, + IoGetFileObjectGenericMapping(), IrpSp->Flags & SL_FORCE_ACCESS_CHECK ? UserMode : Irp->RequestorMode, + granted_access, &Status)) { + SeUnlockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext); + TRACE("SeAccessCheck failed, returning %08lx\n", Status); + goto end; + } + + SeUnlockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext); + } else + *granted_access = 0; + + TRACE("deleted = %s\n", fileref->deleted ? "true" : "false"); + + sf = fileref; + while (sf) { + if (sf->delete_on_close) { + TRACE("could not open as deletion pending\n"); + Status = STATUS_DELETE_PENDING; + goto end; + } + sf = sf->parent; + } + + 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)) { + Status = STATUS_CANNOT_DELETE; + goto end; + } + + if (readonly) { + ACCESS_MASK allowed; + + allowed = READ_CONTROL | SYNCHRONIZE | ACCESS_SYSTEM_SECURITY | FILE_READ_DATA | + FILE_READ_EA | FILE_READ_ATTRIBUTES | FILE_EXECUTE | FILE_LIST_DIRECTORY | + FILE_TRAVERSE; + + if (!Vcb->readonly && (fileref->fcb == Vcb->dummy_fcb || fileref->fcb->inode == SUBVOL_ROOT_INODE)) + allowed |= DELETE; + + if (fileref->fcb != Vcb->dummy_fcb && !is_subvol_readonly(fileref->fcb->subvol, Irp) && !Vcb->readonly) { + allowed |= DELETE | WRITE_OWNER | WRITE_DAC | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES; + + if (!fileref->fcb->ads && fileref->fcb->type == BTRFS_TYPE_DIRECTORY) + allowed |= FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE | FILE_DELETE_CHILD; + } else if (fileref->fcb->inode == SUBVOL_ROOT_INODE && is_subvol_readonly(fileref->fcb->subvol, Irp) && !Vcb->readonly) { + // We allow a subvolume root to be opened read-write even if its readonly flag is set, so it can be cleared + + allowed |= FILE_WRITE_ATTRIBUTES; + } + + if (IrpSp->Parameters.Create.SecurityContext->DesiredAccess & MAXIMUM_ALLOWED) { + *granted_access &= allowed; + IrpSp->Parameters.Create.SecurityContext->AccessState->PreviouslyGrantedAccess &= allowed; + } else if (*granted_access & ~allowed) { + Status = Vcb->readonly ? STATUS_MEDIA_WRITE_PROTECTED : STATUS_ACCESS_DENIED; + goto end; + } + + if (RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF) { + WARN("cannot overwrite readonly file\n"); + Status = STATUS_ACCESS_DENIED; + goto end; + } + } + + if ((fileref->fcb->type == BTRFS_TYPE_SYMLINK || fileref->fcb->atts & FILE_ATTRIBUTE_REPARSE_POINT) && !(options & FILE_OPEN_REPARSE_POINT)) { + REPARSE_DATA_BUFFER* data; + + /* How reparse points work from the point of view of the filesystem appears to + * undocumented. When returning STATUS_REPARSE, MSDN encourages us to return + * IO_REPARSE in Irp->IoStatus.Information, but that means we have to do our own + * translation. If we instead return the reparse tag in Information, and store + * a pointer to the reparse data buffer in Irp->Tail.Overlay.AuxiliaryBuffer, + * IopSymlinkProcessReparse will do the translation for us. */ + + Status = get_reparse_block(fileref->fcb, (uint8_t**)&data); + if (!NT_SUCCESS(Status)) { + ERR("get_reparse_block returned %08lx\n", Status); + Status = STATUS_SUCCESS; + } else { + Irp->IoStatus.Information = data->ReparseTag; + + if (fn->Buffer[(fn->Length / sizeof(WCHAR)) - 1] == '\\') + data->Reserved = sizeof(WCHAR); + + Irp->Tail.Overlay.AuxiliaryBuffer = (void*)data; + + Status = STATUS_REPARSE; + goto end; + } + } + + if (fileref->fcb->type == BTRFS_TYPE_DIRECTORY && !fileref->fcb->ads) { + if (options & FILE_NON_DIRECTORY_FILE && !(fileref->fcb->atts & FILE_ATTRIBUTE_REPARSE_POINT)) { + Status = STATUS_FILE_IS_A_DIRECTORY; + goto end; + } + } else if (options & FILE_DIRECTORY_FILE) { + TRACE("returning STATUS_NOT_A_DIRECTORY (type = %u)\n", fileref->fcb->type); + Status = STATUS_NOT_A_DIRECTORY; + goto end; + } + + if (fileref->open_count > 0) { + oplock_context* ctx; + + Status = IoCheckShareAccess(*granted_access, IrpSp->Parameters.Create.ShareAccess, FileObject, &fileref->fcb->share_access, false); + + if (!NT_SUCCESS(Status)) { + if (Status == STATUS_SHARING_VIOLATION) + TRACE("IoCheckShareAccess failed, returning %08lx\n", Status); + else + WARN("IoCheckShareAccess failed, returning %08lx\n", Status); + + goto end; + } + + ctx = ExAllocatePoolWithTag(NonPagedPool, sizeof(oplock_context), ALLOC_TAG); + if (!ctx) { + ERR("out of memory\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto end; + } + + ctx->Vcb = Vcb; + ctx->granted_access = *granted_access; + ctx->fileref = fileref; +#ifdef __REACTOS__ + Status = FsRtlCheckOplock(fcb_oplock(fileref->fcb), Irp, ctx, (POPLOCK_WAIT_COMPLETE_ROUTINE) oplock_complete, NULL); +#else + Status = FsRtlCheckOplock(fcb_oplock(fileref->fcb), Irp, ctx, oplock_complete, NULL); +#endif /* __REACTOS__ */ + if (Status == STATUS_PENDING) + return Status; + + ExFreePool(ctx); + + if (!NT_SUCCESS(Status)) { + WARN("FsRtlCheckOplock returned %08lx\n", Status); + goto end; + } + + IoUpdateShareAccess(FileObject, &fileref->fcb->share_access); + } else + IoSetShareAccess(*granted_access, IrpSp->Parameters.Create.ShareAccess, FileObject, &fileref->fcb->share_access); + + Status = open_file3(Vcb, Irp, *granted_access, fileref, rollback); -end2: if (!NT_SUCCESS(Status)) IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); @@ -4106,9 +4191,6 @@ NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) if (tp.item->key.obj_id == fcb->inode) { if (tp.item->key.obj_type == TYPE_INODE_REF) { INODE_REF* ir = (INODE_REF*)tp.item->data; -#ifdef __REACTOS__ - ULONG stringlen; -#endif if (tp.item->size < offsetof(INODE_REF, name[0]) || tp.item->size < offsetof(INODE_REF, name[0]) + ir->n) { ERR("INODE_REF was too short\n"); @@ -4116,9 +4198,7 @@ NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) return STATUS_INTERNAL_ERROR; } -#ifndef __REACTOS__ ULONG stringlen; -#endif Status = utf8_to_utf16(NULL, 0, &stringlen, ir->name, ir->n); if (!NT_SUCCESS(Status)) { @@ -4156,9 +4236,6 @@ NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) break; } else if (tp.item->key.obj_type == TYPE_INODE_EXTREF) { INODE_EXTREF* ier = (INODE_EXTREF*)tp.item->data; -#ifdef __REACTOS__ - ULONG stringlen; -#endif if (tp.item->size < offsetof(INODE_EXTREF, name[0]) || tp.item->size < offsetof(INODE_EXTREF, name[0]) + ier->n) { ERR("INODE_EXTREF was too short\n"); @@ -4166,9 +4243,7 @@ NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) return STATUS_INTERNAL_ERROR; } -#ifndef __REACTOS__ ULONG stringlen; -#endif Status = utf8_to_utf16(NULL, 0, &stringlen, ier->name, ier->n); if (!NT_SUCCESS(Status)) { @@ -4601,11 +4676,9 @@ loaded: goto exit; } - if (NT_SUCCESS(Status)) { // file already exists - Status = open_file2(Vcb, RequestedDisposition, pool_type, fileref, &granted_access, FileObject, &fn, options, Irp, rollback); - if (!NT_SUCCESS(Status)) - goto exit; - } else { + if (NT_SUCCESS(Status)) // file already exists + Status = open_file2(Vcb, RequestedDisposition, fileref, &granted_access, FileObject, &fn, options, Irp, rollback); + else { file_ref* existing_file = NULL; Status = file_create(Irp, Vcb, FileObject, related, loaded_related, &fn, RequestedDisposition, options, &existing_file, rollback); @@ -4613,9 +4686,7 @@ loaded: if (Status == STATUS_OBJECT_NAME_COLLISION) { // already exists fileref = existing_file; - Status = open_file2(Vcb, RequestedDisposition, pool_type, fileref, &granted_access, FileObject, &fn, options, Irp, rollback); - if (!NT_SUCCESS(Status)) - goto exit; + Status = open_file2(Vcb, RequestedDisposition, fileref, &granted_access, FileObject, &fn, options, Irp, rollback); } else { Irp->IoStatus.Information = NT_SUCCESS(Status) ? FILE_CREATED : 0; granted_access = IrpSp->Parameters.Create.SecurityContext->DesiredAccess; @@ -4928,7 +4999,11 @@ NTSTATUS __stdcall drv_create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { exit: Irp->IoStatus.Status = Status; - IoCompleteRequest( Irp, NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT ); + + if (Status == STATUS_PENDING) + IoMarkIrpPending(Irp); + else + IoCompleteRequest(Irp, NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT); TRACE("create returning %08lx\n", Status); diff --git a/drivers/filesystems/btrfs/fastio.c b/drivers/filesystems/btrfs/fastio.c index e073f3f9b1d..2c768895f8d 100644 --- a/drivers/filesystems/btrfs/fastio.c +++ b/drivers/filesystems/btrfs/fastio.c @@ -499,6 +499,50 @@ static BOOLEAN __stdcall fast_io_unlock_all_by_key(PFILE_OBJECT FileObject, PVOI return true; } +#ifdef __REACTOS__ +_Function_class_(FAST_IO_ACQUIRE_FILE) +static void __stdcall fast_io_acquire_for_create_section(_In_ PFILE_OBJECT FileObject) { +#else +static void fast_io_acquire_for_create_section(_In_ PFILE_OBJECT FileObject) { +#endif /* __REACTOS__ */ + fcb* fcb; + + TRACE("(%p)\n", FileObject); + + if (!FileObject) + return; + + fcb = FileObject->FsContext; + + if (!fcb) + return; + + ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, true); + ExAcquireResourceExclusiveLite(fcb->Header.Resource, true); +} + +#ifdef __REACTOS__ +_Function_class_(FAST_IO_RELEASE_FILE) +static void __stdcall fast_io_release_for_create_section(_In_ PFILE_OBJECT FileObject) { +#else +static void fast_io_release_for_create_section(_In_ PFILE_OBJECT FileObject) { +#endif /* __REACTOS__ */ + fcb* fcb; + + TRACE("(%p)\n", FileObject); + + if (!FileObject) + return; + + fcb = FileObject->FsContext; + + if (!fcb) + return; + + ExReleaseResourceLite(fcb->Header.Resource); + ExReleaseResourceLite(&fcb->Vcb->tree_lock); +} + void init_fast_io_dispatch(FAST_IO_DISPATCH** fiod) { RtlZeroMemory(&FastIoDispatch, sizeof(FastIoDispatch)); @@ -513,6 +557,8 @@ void init_fast_io_dispatch(FAST_IO_DISPATCH** fiod) { FastIoDispatch.FastIoUnlockSingle = fast_io_unlock_single; FastIoDispatch.FastIoUnlockAll = fast_io_unlock_all; FastIoDispatch.FastIoUnlockAllByKey = fast_io_unlock_all_by_key; + FastIoDispatch.AcquireFileForNtCreateSection = fast_io_acquire_for_create_section; + FastIoDispatch.ReleaseFileForNtCreateSection = fast_io_release_for_create_section; FastIoDispatch.FastIoQueryNetworkOpenInfo = fast_io_query_network_open_info; FastIoDispatch.AcquireForModWrite = fast_io_acquire_for_mod_write; FastIoDispatch.MdlRead = FsRtlMdlReadDev; diff --git a/drivers/filesystems/btrfs/fileinfo.c b/drivers/filesystems/btrfs/fileinfo.c index 4bebfda1904..df8652823e7 100644 --- a/drivers/filesystems/btrfs/fileinfo.c +++ b/drivers/filesystems/btrfs/fileinfo.c @@ -801,6 +801,7 @@ static NTSTATUS create_directory_fcb(device_extension* Vcb, root* r, fcb* parfcb fcb->subvol = r; fcb->inode = InterlockedIncrement64(&r->lastinode); + fcb->hash = calc_crc32c(0xffffffff, (uint8_t*)&fcb->inode, sizeof(uint64_t)); fcb->type = BTRFS_TYPE_DIRECTORY; fcb->inode_item.generation = Vcb->superblock.generation; @@ -872,7 +873,7 @@ static NTSTATUS create_directory_fcb(device_extension* Vcb, root* r, fcb* parfcb RtlZeroMemory(fcb->hash_ptrs_uc, sizeof(LIST_ENTRY*) * 256); acquire_fcb_lock_exclusive(Vcb); - InsertTailList(&r->fcbs, &fcb->list_entry); + add_fcb_to_subvol(fcb); InsertTailList(&Vcb->all_fcbs, &fcb->list_entry_all); r->fcbs_version++; release_fcb_lock(Vcb); @@ -884,6 +885,68 @@ static NTSTATUS create_directory_fcb(device_extension* Vcb, root* r, fcb* parfcb return STATUS_SUCCESS; } +void add_fcb_to_subvol(_In_ _Requires_exclusive_lock_held_(_Curr_->Vcb->fcb_lock) fcb* fcb) { + LIST_ENTRY* lastle = NULL; + uint32_t hash = fcb->hash; + + if (fcb->subvol->fcbs_ptrs[hash >> 24]) { + LIST_ENTRY* le = fcb->subvol->fcbs_ptrs[hash >> 24]; + + while (le != &fcb->subvol->fcbs) { + struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry); + + if (fcb2->hash > hash) { + lastle = le->Blink; + break; + } + + le = le->Flink; + } + } + + if (!lastle) { + uint8_t c = hash >> 24; + + if (c != 0xff) { + uint8_t d = c + 1; + + do { + if (fcb->subvol->fcbs_ptrs[d]) { + lastle = fcb->subvol->fcbs_ptrs[d]->Blink; + break; + } + + d++; + } while (d != 0); + } + } + + if (lastle) { + InsertHeadList(lastle, &fcb->list_entry); + + if (lastle == &fcb->subvol->fcbs || (CONTAINING_RECORD(lastle, struct _fcb, list_entry)->hash >> 24) != (hash >> 24)) + fcb->subvol->fcbs_ptrs[hash >> 24] = &fcb->list_entry; + } else { + InsertTailList(&fcb->subvol->fcbs, &fcb->list_entry); + + if (fcb->list_entry.Blink == &fcb->subvol->fcbs || (CONTAINING_RECORD(fcb->list_entry.Blink, struct _fcb, list_entry)->hash >> 24) != (hash >> 24)) + fcb->subvol->fcbs_ptrs[hash >> 24] = &fcb->list_entry; + } +} + +void remove_fcb_from_subvol(_In_ _Requires_exclusive_lock_held_(_Curr_->Vcb->fcb_lock) fcb* fcb) { + uint8_t c = fcb->hash >> 24; + + if (fcb->subvol->fcbs_ptrs[c] == &fcb->list_entry) { + if (fcb->list_entry.Flink != &fcb->subvol->fcbs && (CONTAINING_RECORD(fcb->list_entry.Flink, struct _fcb, list_entry)->hash >> 24) == c) + fcb->subvol->fcbs_ptrs[c] = fcb->list_entry.Flink; + else + fcb->subvol->fcbs_ptrs[c] = NULL; + } + + RemoveEntryList(&fcb->list_entry); +} + static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destdir, PANSI_STRING utf8, PUNICODE_STRING fnus, PIRP Irp, LIST_ENTRY* rollback) { NTSTATUS Status; LIST_ENTRY move_list, *le; @@ -930,6 +993,7 @@ static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destd if (!NT_SUCCESS(Status)) { ERR("add_children_to_move_list returned %08lx\n", Status); + ExReleaseResourceLite(me->fileref->fcb->Header.Resource); goto end; } } @@ -950,8 +1014,6 @@ static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destd if (me->fileref->fcb->inode != SUBVOL_ROOT_INODE && me->fileref->fcb != fileref->fcb->Vcb->dummy_fcb) { if (!me->dummyfcb) { ULONG defda; - bool inserted = false; - LIST_ENTRY* le3; ExAcquireResourceExclusiveLite(me->fileref->fcb->Header.Resource, true); @@ -964,6 +1026,7 @@ static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destd me->dummyfcb->subvol = me->fileref->fcb->subvol; me->dummyfcb->inode = me->fileref->fcb->inode; + me->dummyfcb->hash = me->fileref->fcb->hash; if (!me->dummyfcb->ads) { me->dummyfcb->sd_dirty = me->fileref->fcb->sd_dirty; @@ -983,6 +1046,7 @@ static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destd me->fileref->fcb->subvol = destdir->fcb->subvol; me->fileref->fcb->inode = InterlockedIncrement64(&destdir->fcb->subvol->lastinode); + me->fileref->fcb->hash = calc_crc32c(0xffffffff, (uint8_t*)&me->fileref->fcb->inode, sizeof(uint64_t)); me->fileref->fcb->inode_item.st_nlink = 1; defda = get_file_attributes(me->fileref->fcb->Vcb, me->fileref->fcb->subvol, me->fileref->fcb->inode, @@ -1042,31 +1106,20 @@ static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destd le2 = le2->Flink; } + + add_fcb_to_subvol(me->dummyfcb); + remove_fcb_from_subvol(me->fileref->fcb); + add_fcb_to_subvol(me->fileref->fcb); } else { me->fileref->fcb->subvol = me->parent->fileref->fcb->subvol; me->fileref->fcb->inode = me->parent->fileref->fcb->inode; - } - - me->fileref->fcb->created = true; - - InsertHeadList(&me->fileref->fcb->list_entry, &me->dummyfcb->list_entry); - RemoveEntryList(&me->fileref->fcb->list_entry); - - le3 = destdir->fcb->subvol->fcbs.Flink; - while (le3 != &destdir->fcb->subvol->fcbs) { - fcb* fcb = CONTAINING_RECORD(le3, struct _fcb, list_entry); - - if (fcb->inode > me->fileref->fcb->inode) { - InsertHeadList(le3->Blink, &me->fileref->fcb->list_entry); - inserted = true; - break; - } + me->fileref->fcb->hash = me->parent->fileref->fcb->hash; - le3 = le3->Flink; + // put stream after parent in FCB list + InsertHeadList(&me->parent->fileref->fcb->list_entry, &me->fileref->fcb->list_entry); } - if (!inserted) - InsertTailList(&destdir->fcb->subvol->fcbs, &me->fileref->fcb->list_entry); + me->fileref->fcb->created = true; InsertTailList(&me->fileref->fcb->Vcb->all_fcbs, &me->dummyfcb->list_entry_all); @@ -1159,7 +1212,7 @@ static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destd if (le == move_list.Flink && (me->fileref->dc->utf8.Length != utf8->Length || RtlCompareMemory(me->fileref->dc->utf8.Buffer, utf8->Buffer, utf8->Length) != utf8->Length)) name_changed = true; - if ((le == move_list.Flink || me->fileref->fcb->inode == SUBVOL_ROOT_INODE) && !me->dummyfileref->oldutf8.Buffer) { + if (!me->dummyfileref->oldutf8.Buffer) { me->dummyfileref->oldutf8.Buffer = ExAllocatePoolWithTag(PagedPool, me->fileref->dc->utf8.Length, ALLOC_TAG); if (!me->dummyfileref->oldutf8.Buffer) { ERR("out of memory\n"); @@ -1773,11 +1826,18 @@ static NTSTATUS rename_stream_to_file(device_extension* Vcb, file_ref* fileref, dummyfcb->Vcb = Vcb; dummyfcb->subvol = fileref->fcb->subvol; dummyfcb->inode = fileref->fcb->inode; + dummyfcb->hash = fileref->fcb->hash; dummyfcb->adsxattr = fileref->fcb->adsxattr; dummyfcb->adshash = fileref->fcb->adshash; dummyfcb->ads = true; dummyfcb->deleted = true; + acquire_fcb_lock_exclusive(Vcb); + add_fcb_to_subvol(dummyfcb); + InsertTailList(&Vcb->all_fcbs, &dummyfcb->list_entry_all); + dummyfcb->subvol->fcbs_version++; + release_fcb_lock(Vcb); + // FIXME - dummyfileref as well? mark_fcb_dirty(dummyfcb); @@ -1839,9 +1899,10 @@ static NTSTATUS rename_stream(device_extension* Vcb, file_ref* fileref, ccb* ccb if (fn.Length == 0) return rename_stream_to_file(Vcb, fileref, ccb, flags, Irp, rollback); - if (!is_file_name_valid(&fn, false, true)) { + Status = check_file_name_valid(&fn, false, true); + if (!NT_SUCCESS(Status)) { WARN("invalid stream name %.*S\n", (int)(fn.Length / sizeof(WCHAR)), fn.Buffer); - return STATUS_OBJECT_NAME_INVALID; + return Status; } if (!(flags & FILE_RENAME_IGNORE_READONLY_ATTRIBUTE) && fileref->parent->fcb->atts & FILE_ATTRIBUTE_READONLY) { @@ -1989,11 +2050,18 @@ static NTSTATUS rename_stream(device_extension* Vcb, file_ref* fileref, ccb* ccb dummyfcb->Vcb = Vcb; dummyfcb->subvol = fileref->fcb->subvol; dummyfcb->inode = fileref->fcb->inode; + dummyfcb->hash = fileref->fcb->hash; dummyfcb->adsxattr = fileref->fcb->adsxattr; dummyfcb->adshash = fileref->fcb->adshash; dummyfcb->ads = true; dummyfcb->deleted = true; + acquire_fcb_lock_exclusive(Vcb); + add_fcb_to_subvol(dummyfcb); + InsertTailList(&Vcb->all_fcbs, &dummyfcb->list_entry_all); + dummyfcb->subvol->fcbs_version++; + release_fcb_lock(Vcb); + mark_fcb_dirty(dummyfcb); free_fcb(dummyfcb); @@ -2078,9 +2146,10 @@ static NTSTATUS rename_file_to_stream(device_extension* Vcb, file_ref* fileref, return STATUS_INVALID_PARAMETER; } - if (!is_file_name_valid(&fn, false, true)) { + Status = check_file_name_valid(&fn, false, true); + if (!NT_SUCCESS(Status)) { WARN("invalid stream name %.*S\n", (int)(fn.Length / sizeof(WCHAR)), fn.Buffer); - return STATUS_OBJECT_NAME_INVALID; + return Status; } if (!(flags & FILE_RENAME_IGNORE_READONLY_ATTRIBUTE) && fileref->fcb->atts & FILE_ATTRIBUTE_READONLY) { @@ -2468,9 +2537,6 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB SECURITY_SUBJECT_CONTEXT subjcont; ACCESS_MASK access; ULONG flags; -#ifdef __REACTOS__ - unsigned int i; -#endif InitializeListHead(&rollback); @@ -2504,7 +2570,7 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB for (i = fnlen - 1; i >= 0; i--) { if (fri->FileName[i] == '\\' || fri->FileName[i] == '/') { fn = &fri->FileName[i+1]; - fnlen = (fri->FileNameLength / sizeof(WCHAR)) - i - 1; + fnlen -= i + 1; break; } } @@ -2555,11 +2621,7 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB TRACE("fnus = %.*S\n", (int)(fnus.Length / sizeof(WCHAR)), fnus.Buffer); -#ifndef __REACTOS__ for (unsigned int i = 0 ; i < fnus.Length / sizeof(WCHAR); i++) { -#else - for (i = 0 ; i < fnus.Length / sizeof(WCHAR); i++) { -#endif if (fnus.Buffer[i] == ':') { TRACE("colon in filename\n"); Status = STATUS_OBJECT_NAME_INVALID; diff --git a/drivers/filesystems/btrfs/free-space.c b/drivers/filesystems/btrfs/free-space.c index c2fc0c1ae12..50b8141ee6f 100644 --- a/drivers/filesystems/btrfs/free-space.c +++ b/drivers/filesystems/btrfs/free-space.c @@ -1150,6 +1150,7 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, bool* chan c->cache->subvol = Vcb->root_root; c->cache->inode = InterlockedIncrement64(&Vcb->root_root->lastinode); + c->cache->hash = calc_crc32c(0xffffffff, (uint8_t*)&c->cache->inode, sizeof(uint64_t)); c->cache->type = BTRFS_TYPE_FILE; c->cache->created = true; @@ -1214,6 +1215,8 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, bool* chan c->cache->extents_changed = true; InsertTailList(&Vcb->all_fcbs, &c->cache->list_entry_all); + add_fcb_to_subvol(c->cache); + Status = flush_fcb(c->cache, true, batchlist, Irp); if (!NT_SUCCESS(Status)) { ERR("flush_fcb returned %08lx\n", Status); diff --git a/drivers/filesystems/btrfs/fsctl.c b/drivers/filesystems/btrfs/fsctl.c index f1bb68c22a0..8ad58df883f 100644 --- a/drivers/filesystems/btrfs/fsctl.c +++ b/drivers/filesystems/btrfs/fsctl.c @@ -601,8 +601,9 @@ static NTSTATUS create_snapshot(device_extension* Vcb, PFILE_OBJECT FileObject, if (is_subvol_readonly(fcb->subvol, Irp)) return STATUS_ACCESS_DENIED; - if (!is_file_name_valid(&nameus, posix, false)) - return STATUS_OBJECT_NAME_INVALID; + Status = check_file_name_valid(&nameus, posix, false); + if (!NT_SUCCESS(Status)) + return Status; utf8.Buffer = NULL; @@ -823,8 +824,9 @@ static NTSTATUS create_subvol(device_extension* Vcb, PFILE_OBJECT FileObject, vo nameus.Length = nameus.MaximumLength = bcs->namelen; nameus.Buffer = bcs->name; - if (!is_file_name_valid(&nameus, bcs->posix, false)) - return STATUS_OBJECT_NAME_INVALID; + Status = check_file_name_valid(&nameus, bcs->posix, false); + if (!NT_SUCCESS(Status)) + return Status; utf8.Buffer = NULL; @@ -961,8 +963,9 @@ static NTSTATUS create_subvol(device_extension* Vcb, PFILE_OBJECT FileObject, vo rootfcb->Vcb = Vcb; rootfcb->subvol = r; - rootfcb->inode = SUBVOL_ROOT_INODE; rootfcb->type = BTRFS_TYPE_DIRECTORY; + rootfcb->inode = SUBVOL_ROOT_INODE; + rootfcb->hash = calc_crc32c(0xffffffff, (uint8_t*)&rootfcb->inode, sizeof(uint64_t)); // FIXME - we can hardcode this rootfcb->inode_item.generation = Vcb->superblock.generation; rootfcb->inode_item.transid = Vcb->superblock.generation; @@ -1006,7 +1009,7 @@ static NTSTATUS create_subvol(device_extension* Vcb, PFILE_OBJECT FileObject, vo rootfcb->inode_item_changed = true; acquire_fcb_lock_exclusive(Vcb); - InsertTailList(&r->fcbs, &rootfcb->list_entry); + add_fcb_to_subvol(rootfcb); InsertTailList(&Vcb->all_fcbs, &rootfcb->list_entry_all); r->fcbs_version++; release_fcb_lock(Vcb); @@ -3693,6 +3696,44 @@ end: return Status; } +static NTSTATUS check_inode_used(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, + _In_ root* subvol, _In_ uint64_t inode, _In_ uint32_t hash, _In_opt_ PIRP Irp) { + KEY searchkey; + traverse_ptr tp; + NTSTATUS Status; + uint8_t c = hash >> 24; + + if (subvol->fcbs_ptrs[c]) { + LIST_ENTRY* le = subvol->fcbs_ptrs[c]; + + while (le != &subvol->fcbs) { + struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry); + + if (fcb2->inode == inode) + return STATUS_SUCCESS; + else if (fcb2->hash > hash) + break; + + le = le->Flink; + } + } + + searchkey.obj_id = inode; + searchkey.obj_type = TYPE_INODE_ITEM; + searchkey.offset = 0xffffffffffffffff; + + Status = find_item(Vcb, subvol, &tp, &searchkey, false, Irp); + if (!NT_SUCCESS(Status)) { + ERR("find_item returned %08lx\n", Status); + return Status; + } + + if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) + return STATUS_SUCCESS; + + return STATUS_NOT_FOUND; +} + static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data, ULONG datalen, PIRP Irp) { NTSTATUS Status; btrfs_mknod* bmn; @@ -3705,7 +3746,6 @@ static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data dir_child* dc; LARGE_INTEGER time; BTRFS_TIME now; - LIST_ENTRY* lastle; ANSI_STRING utf8; ULONG len, i; SECURITY_SUBJECT_CONTEXT subjcont; @@ -3925,35 +3965,33 @@ static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data acquire_fcb_lock_exclusive(Vcb); if (bmn->inode == 0) { - inode = InterlockedIncrement64(&parfcb->subvol->lastinode); - lastle = parfcb->subvol->fcbs.Blink; + fcb->inode = InterlockedIncrement64(&parfcb->subvol->lastinode); + fcb->hash = calc_crc32c(0xffffffff, (uint8_t*)&fcb->inode, sizeof(uint64_t)); } else { if (bmn->inode > (uint64_t)parfcb->subvol->lastinode) { - inode = parfcb->subvol->lastinode = bmn->inode; - lastle = parfcb->subvol->fcbs.Blink; + fcb->inode = parfcb->subvol->lastinode = bmn->inode; + fcb->hash = calc_crc32c(0xffffffff, (uint8_t*)&fcb->inode, sizeof(uint64_t)); } else { - LIST_ENTRY* le = parfcb->subvol->fcbs.Flink; + uint32_t hash = calc_crc32c(0xffffffff, (uint8_t*)&bmn->inode, sizeof(uint64_t)); - lastle = parfcb->subvol->fcbs.Blink;; - while (le != &parfcb->subvol->fcbs) { - struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry); + Status = check_inode_used(Vcb, subvol, bmn->inode, hash, Irp); + if (NT_SUCCESS(Status)) { // STATUS_SUCCESS means inode found + release_fcb_lock(Vcb); + ExReleaseResourceLite(&Vcb->fileref_lock); - if (fcb2->inode == bmn->inode && !fcb2->deleted) { - release_fcb_lock(Vcb); - ExReleaseResourceLite(&Vcb->fileref_lock); - - WARN("inode collision\n"); - Status = STATUS_INVALID_PARAMETER; - goto end; - } else if (fcb2->inode > bmn->inode) { - lastle = fcb2->list_entry.Blink; - break; - } + WARN("inode collision\n"); + Status = STATUS_INVALID_PARAMETER; + goto end; + } else if (Status != STATUS_NOT_FOUND) { + ERR("check_inode_used returned %08lx\n", Status); - le = le->Flink; + release_fcb_lock(Vcb); + ExReleaseResourceLite(&Vcb->fileref_lock); + goto end; } - inode = bmn->inode; + fcb->inode = bmn->inode; + fcb->hash = hash; } } @@ -4025,7 +4063,7 @@ static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data RtlZeroMemory(fcb->hash_ptrs_uc, sizeof(LIST_ENTRY*) * 256); } - InsertHeadList(lastle, &fcb->list_entry); + add_fcb_to_subvol(fcb); InsertTailList(&Vcb->all_fcbs, &fcb->list_entry_all); if (bmn->type == BTRFS_TYPE_DIRECTORY) @@ -4924,10 +4962,10 @@ static NTSTATUS fsctl_oplock(device_extension* Vcb, PIRP* Pirp) { ExAcquireResourceSharedLite(&Vcb->tree_lock, true); + ExAcquireResourceExclusiveLite(fcb->Header.Resource, true); + if (fsctl == FSCTL_REQUEST_OPLOCK_LEVEL_1 || fsctl == FSCTL_REQUEST_BATCH_OPLOCK || fsctl == FSCTL_REQUEST_FILTER_OPLOCK || fsctl == FSCTL_REQUEST_OPLOCK_LEVEL_2 || oplock_request) { - ExAcquireResourceExclusiveLite(fcb->Header.Resource, true); - if (shared_request) { if (fcb->type == BTRFS_TYPE_FILE) { if (fFsRtlCheckLockForOplockRequest) @@ -4939,8 +4977,7 @@ static NTSTATUS fsctl_oplock(device_extension* Vcb, PIRP* Pirp) { } } else oplock_count = fileref->open_count; - } else - ExAcquireResourceSharedLite(fcb->Header.Resource, true); + } #if (NTDDI_VERSION >= NTDDI_WIN7) if ((fsctl == FSCTL_REQUEST_FILTER_OPLOCK || fsctl == FSCTL_REQUEST_BATCH_OPLOCK || diff --git a/drivers/filesystems/btrfs/pnp.c b/drivers/filesystems/btrfs/pnp.c index 02314ba7a1f..54426102b9b 100644 --- a/drivers/filesystems/btrfs/pnp.c +++ b/drivers/filesystems/btrfs/pnp.c @@ -188,6 +188,18 @@ static NTSTATUS bus_pnp(bus_device_extension* bde, PIRP Irp) { bool handled = false; switch (IrpSp->MinorFunction) { + case IRP_MN_START_DEVICE: + case IRP_MN_CANCEL_REMOVE_DEVICE: + case IRP_MN_SURPRISE_REMOVAL: + case IRP_MN_REMOVE_DEVICE: + Status = STATUS_SUCCESS; + handled = true; + break; + + case IRP_MN_QUERY_REMOVE_DEVICE: + Status = STATUS_UNSUCCESSFUL; + handled = true; + break; case IRP_MN_QUERY_CAPABILITIES: Status = bus_query_capabilities(Irp); handled = true; diff --git a/drivers/filesystems/btrfs/reparse.c b/drivers/filesystems/btrfs/reparse.c index 03708228d46..4e473149d26 100644 --- a/drivers/filesystems/btrfs/reparse.c +++ b/drivers/filesystems/btrfs/reparse.c @@ -317,6 +317,11 @@ NTSTATUS set_reparse_point2(fcb* fcb, REPARSE_DATA_BUFFER* rdb, ULONG buflen, cc // FIXME - die if not file or directory + if (fcb->type == BTRFS_TYPE_DIRECTORY && fcb->inode_item.st_size > 0) { + TRACE("directory not empty\n"); + return STATUS_DIRECTORY_NOT_EMPTY; + } + if (buflen < sizeof(ULONG)) { WARN("buffer was not long enough to hold tag\n"); return STATUS_INVALID_BUFFER_SIZE; @@ -328,7 +333,10 @@ NTSTATUS set_reparse_point2(fcb* fcb, REPARSE_DATA_BUFFER* rdb, ULONG buflen, cc return Status; } - RtlCopyMemory(&tag, rdb, sizeof(ULONG)); + tag = *(ULONG*)rdb; + + if (tag == IO_REPARSE_TAG_MOUNT_POINT && fcb->type != BTRFS_TYPE_DIRECTORY) + return STATUS_NOT_A_DIRECTORY; if (fcb->type == BTRFS_TYPE_FILE && ((tag == IO_REPARSE_TAG_SYMLINK && rdb->SymbolicLinkReparseBuffer.Flags & SYMLINK_FLAG_RELATIVE) || tag == IO_REPARSE_TAG_LX_SYMLINK)) { diff --git a/drivers/filesystems/btrfs/search.c b/drivers/filesystems/btrfs/search.c index c44e95f7c79..e604cc99814 100644 --- a/drivers/filesystems/btrfs/search.c +++ b/drivers/filesystems/btrfs/search.c @@ -903,7 +903,7 @@ void __stdcall mountmgr_thread(_In_ void* context) { break; } - Status = dev_ioctl(mountmgr, IOCTL_MOUNTMGR_QUERY_POINTS, &mmp, sizeof(MOUNTMGR_MOUNT_POINTS), mmps2, mmps.Size, + Status = dev_ioctl(mountmgr, IOCTL_MOUNTMGR_QUERY_POINTS, &mmp, sizeof(MOUNTMGR_MOUNT_POINT), mmps2, mmps.Size, false, NULL); if (!NT_SUCCESS(Status)) ERR("IOCTL_MOUNTMGR_QUERY_POINTS returned %08lx\n", Status); diff --git a/drivers/filesystems/btrfs/security.c b/drivers/filesystems/btrfs/security.c index 2761c63a915..c1183de2465 100644 --- a/drivers/filesystems/btrfs/security.c +++ b/drivers/filesystems/btrfs/security.c @@ -95,7 +95,7 @@ void add_user_mapping(WCHAR* sidstring, ULONG sidstringlength, uint32_t uid) { while (sidstringlength > 0) { val = 0; i = 0; - while (sidstring[i] != '-' && i < sidstringlength) { + while (i < sidstringlength && sidstring[i] != '-') { if (sidstring[i] >= '0' && sidstring[i] <= '9') { val *= 10; val += sidstring[i] - '0'; diff --git a/drivers/filesystems/btrfs/treefuncs.c b/drivers/filesystems/btrfs/treefuncs.c index 4e5502fce2f..3b9483a7b08 100644 --- a/drivers/filesystems/btrfs/treefuncs.c +++ b/drivers/filesystems/btrfs/treefuncs.c @@ -2177,6 +2177,9 @@ static NTSTATUS commit_batch_list_root(_Requires_exclusive_lock_held_(_Curr_->tr Status = handle_batch_collision(Vcb, bi, tp.tree, tp.item, td, &br->items, &ignore); if (!NT_SUCCESS(Status)) { ERR("handle_batch_collision returned %08lx\n", Status); +#ifdef _DEBUG + int3; +#endif if (td) ExFreeToPagedLookasideList(&Vcb->tree_data_lookaside, td); @@ -2258,6 +2261,9 @@ static NTSTATUS commit_batch_list_root(_Requires_exclusive_lock_held_(_Curr_->tr Status = handle_batch_collision(Vcb, bi2, tp.tree, td2, td, &br->items, &ignore); if (!NT_SUCCESS(Status)) { ERR("handle_batch_collision returned %08lx\n", Status); +#ifdef _DEBUG + int3; +#endif return Status; } } diff --git a/drivers/filesystems/btrfs/write.c b/drivers/filesystems/btrfs/write.c index 0d63ac01cec..f4661598400 100644 --- a/drivers/filesystems/btrfs/write.c +++ b/drivers/filesystems/btrfs/write.c @@ -3476,7 +3476,7 @@ NTSTATUS extend_file(fcb* fcb, file_ref* fileref, uint64_t end, bool prealloc, P Status = insert_prealloc_extent(fcb, oldalloc, newalloc - oldalloc, rollback); - if (!NT_SUCCESS(Status)) { + if (!NT_SUCCESS(Status) && Status != STATUS_DISK_FULL) { ERR("insert_prealloc_extent returned %08lx\n", Status); return Status; } @@ -3503,7 +3503,7 @@ NTSTATUS extend_file(fcb* fcb, file_ref* fileref, uint64_t end, bool prealloc, P if (prealloc) { Status = insert_prealloc_extent(fcb, 0, newalloc, rollback); - if (!NT_SUCCESS(Status)) { + if (!NT_SUCCESS(Status) && Status != STATUS_DISK_FULL) { ERR("insert_prealloc_extent returned %08lx\n", Status); return Status; } @@ -4285,16 +4285,19 @@ NTSTATUS write_file2(device_extension* Vcb, PIRP Irp, LARGE_INTEGER offset, void Status = Irp->IoStatus.Status; goto end; } else { + /* We have to wait in CcCopyWrite - if we return STATUS_PENDING and add this to the work queue, + * it can result in CcFlushCache being called before the job has run. See ifstest ReadWriteTest. */ + if (fCcCopyWriteEx) { - TRACE("CcCopyWriteEx(%p, %I64x, %lx, %u, %p, %p)\n", FileObject, off64, *length, wait, buf, Irp->Tail.Overlay.Thread); - if (!fCcCopyWriteEx(FileObject, &offset, *length, wait, buf, Irp->Tail.Overlay.Thread)) { + TRACE("CcCopyWriteEx(%p, %I64x, %lx, %u, %p, %p)\n", FileObject, off64, *length, true, buf, Irp->Tail.Overlay.Thread); + if (!fCcCopyWriteEx(FileObject, &offset, *length, true, buf, Irp->Tail.Overlay.Thread)) { Status = STATUS_PENDING; goto end; } TRACE("CcCopyWriteEx finished\n"); } else { - TRACE("CcCopyWrite(%p, %I64x, %lx, %u, %p)\n", FileObject, off64, *length, wait, buf); - if (!CcCopyWrite(FileObject, &offset, *length, wait, buf)) { + TRACE("CcCopyWrite(%p, %I64x, %lx, %u, %p)\n", FileObject, off64, *length, true, buf); + if (!CcCopyWrite(FileObject, &offset, *length, true, buf)) { Status = STATUS_PENDING; goto end; } diff --git a/sdk/lib/fslib/btrfslib/btrfslib.c b/sdk/lib/fslib/btrfslib/btrfslib.c index d176204b2a2..7c07cdc1d63 100644 --- a/sdk/lib/fslib/btrfslib/btrfslib.c +++ b/sdk/lib/fslib/btrfslib/btrfslib.c @@ -1263,13 +1263,6 @@ static bool is_mounted_multi_device(HANDLE h, uint32_t sector_size) { bfs = malloc(bfssize); Status = NtDeviceIoControlFile(h2, NULL, NULL, NULL, &iosb, IOCTL_BTRFS_QUERY_FILESYSTEMS, NULL, 0, bfs, bfssize); - if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) { -#ifdef __REACTOS__ - if (bfs) free(bfs); -#endif - NtClose(h2); - return false; - } } while (Status == STATUS_BUFFER_OVERFLOW); if (!NT_SUCCESS(Status))
2 years, 7 months
1
0
0
0
[reactos] 03/10: [BTRFS][UBTRFS][SHELLBTRFS] Upgrade to 1.7.5 (#4417)
by Vincent Franchomme
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b826992ab257331294e02…
commit b826992ab257331294e02aab698182634eff2b90 Author: Vincent Franchomme <franchomme.vincent(a)gmail.com> AuthorDate: Thu Apr 28 21:34:24 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.5 (#4417) v1.7.5 (2020-10-31): - Fixed text display issue in shell extension - Added support for mingw 8 - Fixed LXSS permissions not working in new versions of Windows - Fixed issue where truncating an inline file wouldn't change its size - Fixed crash with Quibble where driver would try to use AVX2 before Windows had enabled it --- dll/shellext/shellbtrfs/balance.cpp | 22 ++--- dll/shellext/shellbtrfs/devices.cpp | 10 +-- dll/shellext/shellbtrfs/propsheet.cpp | 68 ++++++++------ dll/shellext/shellbtrfs/recv.cpp | 4 +- dll/shellext/shellbtrfs/send.cpp | 4 +- dll/shellext/shellbtrfs/shellbtrfs.rc | 8 +- dll/shellext/shellbtrfs/volpropsheet.cpp | 30 +++---- dll/win32/ubtrfs/ubtrfs.rc | 8 +- drivers/filesystems/btrfs/btrfs.c | 24 +++-- drivers/filesystems/btrfs/btrfs.inf | 2 +- drivers/filesystems/btrfs/btrfs.rc | 8 +- drivers/filesystems/btrfs/btrfs_drv.h | 9 -- drivers/filesystems/btrfs/create.c | 150 ++++++++++--------------------- drivers/filesystems/btrfs/fileinfo.c | 6 +- drivers/filesystems/btrfs/write.c | 8 ++ 15 files changed, 166 insertions(+), 195 deletions(-) diff --git a/dll/shellext/shellbtrfs/balance.cpp b/dll/shellext/shellbtrfs/balance.cpp index baa2d07ce38..345583eb0e8 100644 --- a/dll/shellext/shellbtrfs/balance.cpp +++ b/dll/shellext/shellbtrfs/balance.cpp @@ -42,7 +42,9 @@ #include <shlwapi.h> #include <uxtheme.h> -static uint64_t convtypes2[] = { BLOCK_FLAG_SINGLE, BLOCK_FLAG_DUPLICATE, BLOCK_FLAG_RAID0, BLOCK_FLAG_RAID1, BLOCK_FLAG_RAID5, BLOCK_FLAG_RAID6, BLOCK_FLAG_RAID10 }; +static uint64_t convtypes2[] = { BLOCK_FLAG_SINGLE, BLOCK_FLAG_DUPLICATE, BLOCK_FLAG_RAID0, BLOCK_FLAG_RAID1, + BLOCK_FLAG_RAID5, BLOCK_FLAG_RAID1C3, BLOCK_FLAG_RAID6, BLOCK_FLAG_RAID10, + BLOCK_FLAG_RAID1C4 }; static WCHAR hex_digit(uint8_t u) { if (u >= 0xa && u <= 0xf) @@ -245,7 +247,7 @@ void BtrfsBalance::RefreshBalanceDlg(HWND hwndDlg, bool first) { CheckDlgButton(hwndDlg, IDC_METADATA, BST_UNCHECKED); CheckDlgButton(hwndDlg, IDC_SYSTEM, BST_UNCHECKED); - SendMessage(GetDlgItem(hwndDlg, IDC_BALANCE_PROGRESS), PBM_SETPOS, 0, 0); + SendMessageW(GetDlgItem(hwndDlg, IDC_BALANCE_PROGRESS), PBM_SETPOS, 0, 0); } EnableWindow(GetDlgItem(hwndDlg, IDC_DATA_OPTIONS), IsDlgButtonChecked(hwndDlg, IDC_DATA) == BST_CHECKED ? true : false); @@ -566,10 +568,10 @@ INT_PTR CALLBACK BtrfsBalance::BalanceOptsDlgProc(HWND hwndDlg, UINT uMsg, WPARA wstring_sprintf(t, u, bd->dev_id, s.c_str()); - SendMessage(devcb, CB_ADDSTRING, 0, (LPARAM)t.c_str()); + SendMessageW(devcb, CB_ADDSTRING, 0, (LPARAM)t.c_str()); if (opts->devid == bd->dev_id) - SendMessage(devcb, CB_SETCURSEL, num_devices, 0); + SendMessageW(devcb, CB_SETCURSEL, num_devices, 0); num_devices++; @@ -592,10 +594,10 @@ INT_PTR CALLBACK BtrfsBalance::BalanceOptsDlgProc(HWND hwndDlg, UINT uMsg, WPARA if (!load_string(module, convtypes[i], s)) throw last_error(GetLastError()); - SendMessage(convcb, CB_ADDSTRING, 0, (LPARAM)s.c_str()); + SendMessageW(convcb, CB_ADDSTRING, 0, (LPARAM)s.c_str()); if (opts->convert == convtypes2[i]) - SendMessage(convcb, CB_SETCURSEL, i, 0); + SendMessageW(convcb, CB_SETCURSEL, i, 0); i++; @@ -839,10 +841,10 @@ static INT_PTR CALLBACK stub_BalanceOptsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM BtrfsBalance* bb; if (uMsg == WM_INITDIALOG) { - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); + SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); bb = (BtrfsBalance*)lParam; } else { - bb = (BtrfsBalance*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + bb = (BtrfsBalance*)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA); } if (bb) @@ -964,10 +966,10 @@ static INT_PTR CALLBACK stub_BalanceDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wPar BtrfsBalance* bb; if (uMsg == WM_INITDIALOG) { - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); + SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); bb = (BtrfsBalance*)lParam; } else { - bb = (BtrfsBalance*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + bb = (BtrfsBalance*)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA); } if (bb) diff --git a/dll/shellext/shellbtrfs/devices.cpp b/dll/shellext/shellbtrfs/devices.cpp index e95cace5c52..26613ba1707 100644 --- a/dll/shellext/shellbtrfs/devices.cpp +++ b/dll/shellext/shellbtrfs/devices.cpp @@ -75,7 +75,7 @@ static void find_devices(HWND hwnd, const GUID* guid, const mountmgr& mm, vector static const wstring dosdevices = L"\\DosDevices\\"; - h = SetupDiGetClassDevs(guid, nullptr, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); + h = SetupDiGetClassDevsW(guid, nullptr, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); if (h != INVALID_HANDLE_VALUE) { DWORD index = 0; @@ -629,10 +629,10 @@ static INT_PTR CALLBACK stub_DeviceAddDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wP BtrfsDeviceAdd* bda; if (uMsg == WM_INITDIALOG) { - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); + SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); bda = (BtrfsDeviceAdd*)lParam; } else { - bda = (BtrfsDeviceAdd*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + bda = (BtrfsDeviceAdd*)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA); } if (bda) @@ -824,10 +824,10 @@ static INT_PTR CALLBACK stub_DeviceResizeDlgProc(HWND hwndDlg, UINT uMsg, WPARAM BtrfsDeviceResize* bdr; if (uMsg == WM_INITDIALOG) { - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); + SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); bdr = (BtrfsDeviceResize*)lParam; } else - bdr = (BtrfsDeviceResize*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + bdr = (BtrfsDeviceResize*)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA); if (bdr) return bdr->DeviceResizeDlgProc(hwndDlg, uMsg, wParam, lParam); diff --git a/dll/shellext/shellbtrfs/propsheet.cpp b/dll/shellext/shellbtrfs/propsheet.cpp index 90ee53b27d2..faa7194e664 100644 --- a/dll/shellext/shellbtrfs/propsheet.cpp +++ b/dll/shellext/shellbtrfs/propsheet.cpp @@ -435,11 +435,11 @@ void BtrfsPropSheet::set_cmdline(const wstring& cmdline) { OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); if (h == INVALID_HANDLE_VALUE) - return; + throw last_error(GetLastError()); Status = NtQueryInformationFile(h, &iosb, &fai, sizeof(FILE_ACCESS_INFORMATION), FileAccessInformation); if (!NT_SUCCESS(Status)) - return; + throw ntstatus_error(Status); if (fai.AccessFlags & FILE_READ_ATTRIBUTES) can_change_perms = fai.AccessFlags & WRITE_DAC; @@ -453,7 +453,10 @@ void BtrfsPropSheet::set_cmdline(const wstring& cmdline) { Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_INODE_INFO, nullptr, 0, &bii2, sizeof(btrfs_inode_info)); - if (NT_SUCCESS(Status) && !bii2.top) { + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + + if (!bii2.top) { LARGE_INTEGER filesize; subvol = bii2.subvol; @@ -740,7 +743,7 @@ void BtrfsPropSheet::set_size_on_disk(HWND hwndDlg) { if (cr != old_text) SetDlgItemTextW(hwndDlg, IDC_COMPRESSION_RATIO, cr.c_str()); - uint64_t extent_size = (allocsize - sparsesize - sizes[0]) / sector_size; + uint64_t extent_size = (allocsize - sparsesize - sizes[0]) / (sector_size == 0 ? 4096 : sector_size); if (num_extents == 0 || extent_size <= 1) ratio = 0.0f; @@ -751,7 +754,6 @@ void BtrfsPropSheet::set_size_on_disk(HWND hwndDlg) { GetDlgItemTextW(hwndDlg, IDC_FRAGMENTATION, old_text, sizeof(old_text) / sizeof(WCHAR)); - if (frag != old_text) SetDlgItemTextW(hwndDlg, IDC_FRAGMENTATION, frag.c_str()); } @@ -813,7 +815,7 @@ static INT_PTR CALLBACK SizeDetailsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wPara { BtrfsPropSheet* bps = (BtrfsPropSheet*)lParam; - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)bps); + SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)bps); bps->update_size_details_dialog(hwndDlg); @@ -832,7 +834,7 @@ static INT_PTR CALLBACK SizeDetailsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wPara case WM_TIMER: { - BtrfsPropSheet* bps = (BtrfsPropSheet*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + BtrfsPropSheet* bps = (BtrfsPropSheet*)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA); if (bps) { bps->update_size_details_dialog(hwndDlg); @@ -853,18 +855,18 @@ static INT_PTR CALLBACK SizeDetailsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wPara static void set_check_box(HWND hwndDlg, ULONG id, uint64_t min, uint64_t max) { if (min && max) { - SendDlgItemMessage(hwndDlg, id, BM_SETCHECK, BST_CHECKED, 0); + SendDlgItemMessageW(hwndDlg, id, BM_SETCHECK, BST_CHECKED, 0); } else if (!min && !max) { - SendDlgItemMessage(hwndDlg, id, BM_SETCHECK, BST_UNCHECKED, 0); + SendDlgItemMessageW(hwndDlg, id, BM_SETCHECK, BST_UNCHECKED, 0); } else { LONG_PTR style; - style = GetWindowLongPtr(GetDlgItem(hwndDlg, id), GWL_STYLE); + style = GetWindowLongPtrW(GetDlgItem(hwndDlg, id), GWL_STYLE); style &= ~BS_AUTOCHECKBOX; style |= BS_AUTO3STATE; - SetWindowLongPtr(GetDlgItem(hwndDlg, id), GWL_STYLE, style); + SetWindowLongPtrW(GetDlgItem(hwndDlg, id), GWL_STYLE, style); - SendDlgItemMessage(hwndDlg, id, BM_SETCHECK, BST_INDETERMINATE, 0); + SendDlgItemMessageW(hwndDlg, id, BM_SETCHECK, BST_INDETERMINATE, 0); } } @@ -995,13 +997,13 @@ void BtrfsPropSheet::init_propsheet(HWND hwndDlg) { comptype = GetDlgItem(hwndDlg, IDC_COMPRESS_TYPE); - while (SendMessage(comptype, CB_GETCOUNT, 0, 0) > 0) { - SendMessage(comptype, CB_DELETESTRING, 0, 0); + while (SendMessageW(comptype, CB_GETCOUNT, 0, 0) > 0) { + SendMessageW(comptype, CB_DELETESTRING, 0, 0); } if (min_compression_type != max_compression_type) { - SendMessage(comptype, CB_ADDSTRING, 0, (LPARAM)L""); - SendMessage(comptype, CB_SETCURSEL, 0, 0); + SendMessageW(comptype, CB_ADDSTRING, 0, (LPARAM)L""); + SendMessageW(comptype, CB_SETCURSEL, 0, 0); } i = 0; @@ -1011,13 +1013,13 @@ void BtrfsPropSheet::init_propsheet(HWND hwndDlg) { if (!load_string(module, comp_types[i], t)) throw last_error(GetLastError()); - SendMessage(comptype, CB_ADDSTRING, 0, (LPARAM)t.c_str()); + SendMessageW(comptype, CB_ADDSTRING, 0, (LPARAM)t.c_str()); i++; } if (min_compression_type == max_compression_type) { - SendMessage(comptype, CB_SETCURSEL, min_compression_type, 0); + SendMessageW(comptype, CB_SETCURSEL, min_compression_type, 0); compress_type = min_compression_type; } @@ -1087,12 +1089,12 @@ static INT_PTR CALLBACK PropSheetDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, switch (uMsg) { case WM_INITDIALOG: { - PROPSHEETPAGE* psp = (PROPSHEETPAGE*)lParam; + PROPSHEETPAGEW* psp = (PROPSHEETPAGEW*)lParam; BtrfsPropSheet* bps = (BtrfsPropSheet*)psp->lParam; EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)bps); + SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)bps); bps->init_propsheet(hwndDlg); @@ -1101,7 +1103,7 @@ static INT_PTR CALLBACK PropSheetDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, case WM_COMMAND: { - BtrfsPropSheet* bps = (BtrfsPropSheet*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + BtrfsPropSheet* bps = (BtrfsPropSheet*)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA); if (bps && !bps->readonly) { switch (HIWORD(wParam)) { @@ -1256,7 +1258,7 @@ static INT_PTR CALLBACK PropSheetDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, break; case PSN_APPLY: { - BtrfsPropSheet* bps = (BtrfsPropSheet*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + BtrfsPropSheet* bps = (BtrfsPropSheet*)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA); bps->apply_changes(hwndDlg); SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); @@ -1269,7 +1271,7 @@ static INT_PTR CALLBACK PropSheetDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, PNMLINK pNMLink = (PNMLINK)lParam; if (pNMLink->item.iLink == 0) - DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_SIZE_DETAILS), hwndDlg, SizeDetailsDlgProc, GetWindowLongPtr(hwndDlg, GWLP_USERDATA)); + DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_SIZE_DETAILS), hwndDlg, SizeDetailsDlgProc, GetWindowLongPtrW(hwndDlg, GWLP_USERDATA)); } break; } @@ -1278,7 +1280,7 @@ static INT_PTR CALLBACK PropSheetDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, case WM_TIMER: { - BtrfsPropSheet* bps = (BtrfsPropSheet*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + BtrfsPropSheet* bps = (BtrfsPropSheet*)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA); if (bps) { bps->set_size_on_disk(hwndDlg); @@ -1299,7 +1301,7 @@ static INT_PTR CALLBACK PropSheetDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, HRESULT __stdcall BtrfsPropSheet::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam) { try { - PROPSHEETPAGE psp; + PROPSHEETPAGEW psp; HPROPSHEETPAGE hPage; INITCOMMONCONTROLSEX icex; @@ -1315,15 +1317,15 @@ HRESULT __stdcall BtrfsPropSheet::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPAR psp.dwSize = sizeof(psp); psp.dwFlags = PSP_USEREFPARENT | PSP_USETITLE; psp.hInstance = module; - psp.pszTemplate = MAKEINTRESOURCE(IDD_PROP_SHEET); + psp.pszTemplate = MAKEINTRESOURCEW(IDD_PROP_SHEET); psp.hIcon = 0; - psp.pszTitle = MAKEINTRESOURCE(IDS_PROP_SHEET_TITLE); + psp.pszTitle = MAKEINTRESOURCEW(IDS_PROP_SHEET_TITLE); psp.pfnDlgProc = (DLGPROC)PropSheetDlgProc; psp.pcRefParent = (UINT*)&objs_loaded; psp.pfnCallback = nullptr; psp.lParam = (LPARAM)this; - hPage = CreatePropertySheetPage(&psp); + hPage = CreatePropertySheetPageW(&psp); if (hPage) { if (pfnAddPage(hPage, lParam)) { @@ -1353,6 +1355,7 @@ void CALLBACK ShowPropSheetW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int BtrfsPropSheet bps; PROPSHEETPAGEW psp; PROPSHEETHEADERW psh; + INITCOMMONCONTROLSEX icex; wstring title; set_dpi_aware(); @@ -1361,6 +1364,12 @@ void CALLBACK ShowPropSheetW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int bps.set_cmdline(lpszCmdLine); + icex.dwSize = sizeof(icex); + icex.dwICC = ICC_LINK_CLASS; + + if (!InitCommonControlsEx(&icex)) + throw string_error(IDS_INITCOMMONCONTROLSEX_FAILED); + psp.dwSize = sizeof(psp); psp.dwFlags = PSP_USETITLE; psp.hInstance = module; @@ -1381,7 +1390,8 @@ void CALLBACK ShowPropSheetW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int psh.nPages = 1; psh.ppsp = &psp; - PropertySheetW(&psh); + if (PropertySheetW(&psh) < 0) + throw last_error(GetLastError()); } catch (const exception& e) { error_message(hwnd, e.what()); } diff --git a/dll/shellext/shellbtrfs/recv.cpp b/dll/shellext/shellbtrfs/recv.cpp index 0c1ff3ef589..0dc3bf859bb 100644 --- a/dll/shellext/shellbtrfs/recv.cpp +++ b/dll/shellext/shellbtrfs/recv.cpp @@ -1513,10 +1513,10 @@ static INT_PTR CALLBACK stub_RecvProgressDlgProc(HWND hwndDlg, UINT uMsg, WPARAM BtrfsRecv* br; if (uMsg == WM_INITDIALOG) { - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); + SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); br = (BtrfsRecv*)lParam; } else { - br = (BtrfsRecv*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + br = (BtrfsRecv*)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA); } if (br) diff --git a/dll/shellext/shellbtrfs/send.cpp b/dll/shellext/shellbtrfs/send.cpp index 74ba33774e0..b4f242f73c1 100644 --- a/dll/shellext/shellbtrfs/send.cpp +++ b/dll/shellext/shellbtrfs/send.cpp @@ -514,10 +514,10 @@ static INT_PTR CALLBACK stub_SendDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, BtrfsSend* bs; if (uMsg == WM_INITDIALOG) { - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); + SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); bs = (BtrfsSend*)lParam; } else - bs = (BtrfsSend*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + bs = (BtrfsSend*)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA); if (bs) return bs->SendDlgProc(hwndDlg, uMsg, wParam, lParam); diff --git a/dll/shellext/shellbtrfs/shellbtrfs.rc b/dll/shellext/shellbtrfs/shellbtrfs.rc index 4b6bbe2e883..4852681751d 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,4,0 - PRODUCTVERSION 1,7,4,0 + FILEVERSION 1,7,5,0 + PRODUCTVERSION 1,7,5,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -78,12 +78,12 @@ BEGIN BLOCK "080904b0" BEGIN VALUE "FileDescription", "WinBtrfs shell extension" - VALUE "FileVersion", "1.7.4" + VALUE "FileVersion", "1.7.5" VALUE "InternalName", "btrfs" VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-20" VALUE "OriginalFilename", "shellbtrfs.dll" VALUE "ProductName", "WinBtrfs" - VALUE "ProductVersion", "1.7.4" + VALUE "ProductVersion", "1.7.5" END END BLOCK "VarFileInfo" diff --git a/dll/shellext/shellbtrfs/volpropsheet.cpp b/dll/shellext/shellbtrfs/volpropsheet.cpp index ddc7dc24af0..128ac8e42b5 100644 --- a/dll/shellext/shellbtrfs/volpropsheet.cpp +++ b/dll/shellext/shellbtrfs/volpropsheet.cpp @@ -567,10 +567,10 @@ static INT_PTR CALLBACK stub_UsageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam BtrfsVolPropSheet* bvps; if (uMsg == WM_INITDIALOG) { - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); + SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); bvps = (BtrfsVolPropSheet*)lParam; } else { - bvps = (BtrfsVolPropSheet*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + bvps = (BtrfsVolPropSheet*)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA); } if (bvps) @@ -943,10 +943,10 @@ static INT_PTR CALLBACK stub_StatsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam BtrfsVolPropSheet* bvps; if (uMsg == WM_INITDIALOG) { - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); + SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); bvps = (BtrfsVolPropSheet*)lParam; } else { - bvps = (BtrfsVolPropSheet*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + bvps = (BtrfsVolPropSheet*)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA); } if (bvps) @@ -1250,10 +1250,10 @@ static INT_PTR CALLBACK stub_DeviceDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wPara BtrfsVolPropSheet* bvps; if (uMsg == WM_INITDIALOG) { - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); + SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); bvps = (BtrfsVolPropSheet*)lParam; } else { - bvps = (BtrfsVolPropSheet*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + bvps = (BtrfsVolPropSheet*)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA); } if (bvps) @@ -1331,13 +1331,13 @@ static INT_PTR CALLBACK PropSheetDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, switch (uMsg) { case WM_INITDIALOG: { - PROPSHEETPAGE* psp = (PROPSHEETPAGE*)lParam; + PROPSHEETPAGEW* psp = (PROPSHEETPAGEW*)lParam; BtrfsVolPropSheet* bps = (BtrfsVolPropSheet*)psp->lParam; btrfs_device* bd; EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)bps); + SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)bps); bps->readonly = true; bd = bps->devices; @@ -1386,7 +1386,7 @@ static INT_PTR CALLBACK PropSheetDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, case WM_COMMAND: { - BtrfsVolPropSheet* bps = (BtrfsVolPropSheet*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + BtrfsVolPropSheet* bps = (BtrfsVolPropSheet*)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA); if (bps) { switch (HIWORD(wParam)) { @@ -1428,7 +1428,7 @@ static INT_PTR CALLBACK PropSheetDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, HRESULT __stdcall BtrfsVolPropSheet::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam) { try { - PROPSHEETPAGE psp; + PROPSHEETPAGEW psp; HPROPSHEETPAGE hPage; INITCOMMONCONTROLSEX icex; @@ -1444,15 +1444,15 @@ HRESULT __stdcall BtrfsVolPropSheet::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, L psp.dwSize = sizeof(psp); psp.dwFlags = PSP_USEREFPARENT | PSP_USETITLE; psp.hInstance = module; - psp.pszTemplate = MAKEINTRESOURCE(IDD_VOL_PROP_SHEET); + psp.pszTemplate = MAKEINTRESOURCEW(IDD_VOL_PROP_SHEET); psp.hIcon = 0; - psp.pszTitle = MAKEINTRESOURCE(IDS_VOL_PROP_SHEET_TITLE); + psp.pszTitle = MAKEINTRESOURCEW(IDS_VOL_PROP_SHEET_TITLE); psp.pfnDlgProc = (DLGPROC)PropSheetDlgProc; psp.pcRefParent = (UINT*)&objs_loaded; psp.pfnCallback = nullptr; psp.lParam = (LPARAM)this; - hPage = CreatePropertySheetPage(&psp); + hPage = CreatePropertySheetPageW(&psp); if (hPage) { if (pfnAddPage(hPage, lParam)) { @@ -1594,10 +1594,10 @@ static INT_PTR __stdcall dlg_proc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM BtrfsChangeDriveLetter* bcdl; if (uMsg == WM_INITDIALOG) { - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); + SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); bcdl = (BtrfsChangeDriveLetter*)lParam; } else - bcdl = (BtrfsChangeDriveLetter*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + bcdl = (BtrfsChangeDriveLetter*)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA); return bcdl->DlgProc(hwndDlg, uMsg, wParam, lParam); } diff --git a/dll/win32/ubtrfs/ubtrfs.rc b/dll/win32/ubtrfs/ubtrfs.rc index 903edb0c9a5..686e30e7b3c 100644 --- a/dll/win32/ubtrfs/ubtrfs.rc +++ b/dll/win32/ubtrfs/ubtrfs.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,7,4,0 - PRODUCTVERSION 1,7,4,0 + FILEVERSION 1,7,5,0 + PRODUCTVERSION 1,7,5,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -68,12 +68,12 @@ BEGIN BLOCK "080904b0" BEGIN VALUE "FileDescription", "Btrfs utility DLL" - VALUE "FileVersion", "1.7.4" + VALUE "FileVersion", "1.7.5" VALUE "InternalName", "ubtrfs" VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-20" VALUE "OriginalFilename", "ubtrfs.dll" VALUE "ProductName", "WinBtrfs" - VALUE "ProductVersion", "1.7.4" + VALUE "ProductVersion", "1.7.5" END END BLOCK "VarFileInfo" diff --git a/drivers/filesystems/btrfs/btrfs.c b/drivers/filesystems/btrfs/btrfs.c index 4824af9c87b..2f2932f1205 100644 --- a/drivers/filesystems/btrfs/btrfs.c +++ b/drivers/filesystems/btrfs/btrfs.c @@ -5923,7 +5923,7 @@ static void check_cpu() { #ifndef _MSC_VER { - uint32_t eax, ebx, ecx, edx, xcr0; + uint32_t eax, ebx, ecx, edx; __cpuid(1, eax, ebx, ecx, edx); @@ -5935,10 +5935,17 @@ static void check_cpu() { if (__get_cpuid_count(7, 0, &eax, &ebx, &ecx, &edx)) have_avx2 = ebx & bit_AVX2; - if (have_avx2) { // check if supported by OS - __asm__("xgetbv" : "=a" (xcr0) : "c" (0) : "edx" ); + if (have_avx2) { + // check Windows has enabled AVX2 - Windows 10 doesn't immediately + + if (__readcr4() & (1 << 18)) { + uint32_t xcr0; + + __asm__("xgetbv" : "=a" (xcr0) : "c" (0) : "edx" ); - if ((xcr0 & 6) != 6) + if ((xcr0 & 6) != 6) + have_avx2 = false; + } else have_avx2 = false; } } @@ -5954,9 +5961,14 @@ static void check_cpu() { have_avx2 = cpu_info[1] & (1 << 5); if (have_avx2) { - uint32_t xcr0 = (uint32_t)_xgetbv(0); + // check Windows has enabled AVX2 - Windows 10 doesn't immediately + + if (__readcr4() & (1 << 18)) { + uint32_t xcr0 = (uint32_t)_xgetbv(0); - if ((xcr0 & 6) != 6) + if ((xcr0 & 6) != 6) + have_avx2 = false; + } else have_avx2 = false; } } diff --git a/drivers/filesystems/btrfs/btrfs.inf b/drivers/filesystems/btrfs/btrfs.inf index 695bc76f0ed..ac8ff69dc4d 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 = 05/24/2020,1.7.3.0 +DriverVer = 10/31/2020,1.7.5.0 CatalogFile = btrfs.cat [DestinationDirs] diff --git a/drivers/filesystems/btrfs/btrfs.rc b/drivers/filesystems/btrfs/btrfs.rc index 8a0116a2646..e7a7ad6c280 100644 --- a/drivers/filesystems/btrfs/btrfs.rc +++ b/drivers/filesystems/btrfs/btrfs.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,7,4,0 - PRODUCTVERSION 1,7,4,0 + FILEVERSION 1,7,5,0 + PRODUCTVERSION 1,7,5,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -68,12 +68,12 @@ BEGIN BLOCK "080904b0" BEGIN VALUE "FileDescription", "WinBtrfs" - VALUE "FileVersion", "1.7.4" + VALUE "FileVersion", "1.7.5" VALUE "InternalName", "btrfs" VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-20" VALUE "OriginalFilename", "btrfs.sys" VALUE "ProductName", "WinBtrfs" - VALUE "ProductVersion", "1.7.4" + VALUE "ProductVersion", "1.7.5" END END BLOCK "VarFileInfo" diff --git a/drivers/filesystems/btrfs/btrfs_drv.h b/drivers/filesystems/btrfs/btrfs_drv.h index 17c58e4e5d5..0e2554adbc3 100644 --- a/drivers/filesystems/btrfs/btrfs_drv.h +++ b/drivers/filesystems/btrfs/btrfs_drv.h @@ -201,17 +201,8 @@ typedef struct _FSCTL_SET_INTEGRITY_INFORMATION_BUFFER { #ifndef __REACTOS__ #ifndef _MSC_VER #define __drv_aliasesMem -#define _Requires_lock_held_(a) -#define _Requires_exclusive_lock_held_(a) -#define _Releases_lock_(a) -#define _Releases_exclusive_lock_(a) #define _Dispatch_type_(a) -#define _Create_lock_level_(a) #define _Lock_level_order_(a,b) -#define _Has_lock_level_(a) -#define _Requires_lock_not_held_(a) -#define _Acquires_exclusive_lock_(a) -#define _Acquires_shared_lock_(a) #endif #endif // __REACTOS__ diff --git a/drivers/filesystems/btrfs/create.c b/drivers/filesystems/btrfs/create.c index 699228e95a1..25b0b975e53 100644 --- a/drivers/filesystems/btrfs/create.c +++ b/drivers/filesystems/btrfs/create.c @@ -3593,22 +3593,19 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO LARGE_INTEGER zero; if (fileref->fcb->type == BTRFS_TYPE_DIRECTORY || is_subvol_readonly(fileref->fcb->subvol, Irp)) { - free_fileref(fileref); - - return STATUS_ACCESS_DENIED; + Status = STATUS_ACCESS_DENIED; + goto end; } if (Vcb->readonly) { - free_fileref(fileref); - - return STATUS_MEDIA_WRITE_PROTECTED; + Status = STATUS_MEDIA_WRITE_PROTECTED; + goto end; } zero.QuadPart = 0; if (!MmCanFileBeTruncated(&fileref->fcb->nonpaged->segment_object, &zero)) { - free_fileref(fileref); - - return STATUS_USER_MAPPED_FILE; + Status = STATUS_USER_MAPPED_FILE; + goto end; } } @@ -3622,10 +3619,7 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO granted_access, &Status)) { SeUnlockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext); TRACE("SeAccessCheck failed, returning %08lx\n", Status); - - free_fileref(fileref); - - return Status; + goto end; } SeUnlockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext); @@ -3638,10 +3632,8 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO while (sf) { if (sf->delete_on_close) { TRACE("could not open as deletion pending\n"); - - free_fileref(fileref); - - return STATUS_DELETE_PENDING; + Status = STATUS_DELETE_PENDING; + goto end; } sf = sf->parent; } @@ -3651,9 +3643,8 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO 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); - - return STATUS_CANNOT_DELETE; + Status = STATUS_CANNOT_DELETE; + goto end; } if (readonly) { @@ -3681,9 +3672,8 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO *granted_access &= allowed; IrpSp->Parameters.Create.SecurityContext->AccessState->PreviouslyGrantedAccess &= allowed; } else if (*granted_access & ~allowed) { - free_fileref(fileref); - - return Vcb->readonly ? STATUS_MEDIA_WRITE_PROTECTED : STATUS_ACCESS_DENIED; + Status = Vcb->readonly ? STATUS_MEDIA_WRITE_PROTECTED : STATUS_ACCESS_DENIED; + goto end; } } @@ -3709,24 +3699,20 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO Irp->Tail.Overlay.AuxiliaryBuffer = (void*)data; - free_fileref(fileref); - - return STATUS_REPARSE; + Status = STATUS_REPARSE; + goto end; } } if (fileref->fcb->type == BTRFS_TYPE_DIRECTORY && !fileref->fcb->ads) { if (options & FILE_NON_DIRECTORY_FILE && !(fileref->fcb->atts & FILE_ATTRIBUTE_REPARSE_POINT)) { - free_fileref(fileref); - - return STATUS_FILE_IS_A_DIRECTORY; + Status = STATUS_FILE_IS_A_DIRECTORY; + goto end; } } else if (options & FILE_DIRECTORY_FILE) { TRACE("returning STATUS_NOT_A_DIRECTORY (type = %u)\n", fileref->fcb->type); - - free_fileref(fileref); - - return STATUS_NOT_A_DIRECTORY; + Status = STATUS_NOT_A_DIRECTORY; + goto end; } if (fileref->open_count > 0) { @@ -3738,9 +3724,7 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO else WARN("IoCheckShareAccess failed, returning %08lx\n", Status); - free_fileref(fileref); - - return Status; + goto end; } IoUpdateShareAccess(FileObject, &fileref->fcb->share_access); @@ -3749,12 +3733,8 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO if (*granted_access & FILE_WRITE_DATA || options & FILE_DELETE_ON_CLOSE) { if (!MmFlushImageSection(&fileref->fcb->nonpaged->segment_object, MmFlushForWrite)) { - - IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - - free_fileref(fileref); - - return (options & FILE_DELETE_ON_CLOSE) ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION; + Status = (options & FILE_DELETE_ON_CLOSE) ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION; + goto end2; } } @@ -3762,9 +3742,7 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO Status = FsRtlCheckOplock(fcb_oplock(fileref->fcb), Irp, NULL, NULL, NULL); if (!NT_SUCCESS(Status)) { WARN("FsRtlCheckOplock returned %08lx\n", Status); - free_fileref(fileref); - - return Status; + goto end2; } if (RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF || RequestedDisposition == FILE_SUPERSEDE) { @@ -3774,43 +3752,26 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO if ((RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF) && readonly) { WARN("cannot overwrite readonly file\n"); - - IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - - free_fileref(fileref); - - return STATUS_ACCESS_DENIED; + Status = STATUS_ACCESS_DENIED; + goto end2; } if (!fileref->fcb->ads && (IrpSp->Parameters.Create.FileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != ((fileref->fcb->atts & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))) { - IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - - free_fileref(fileref); - - return STATUS_ACCESS_DENIED; + Status = STATUS_ACCESS_DENIED; + goto end2; } if (fileref->fcb->ads) { Status = stream_set_end_of_file_information(Vcb, 0, fileref->fcb, fileref, false); if (!NT_SUCCESS(Status)) { ERR("stream_set_end_of_file_information returned %08lx\n", Status); - - IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - - free_fileref(fileref); - - return Status; + goto end2; } } else { Status = truncate_file(fileref->fcb, 0, Irp, rollback); if (!NT_SUCCESS(Status)) { ERR("truncate_file returned %08lx\n", Status); - - IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - - free_fileref(fileref); - - return Status; + goto end2; } } @@ -3819,12 +3780,7 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO if (!NT_SUCCESS(Status)) { ERR("extend_file returned %08lx\n", Status); - - IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - - free_fileref(fileref); - - return Status; + goto end2; } } @@ -3838,12 +3794,7 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO Status = IoCheckEaBufferValidity(Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.Create.EaLength, &offset); if (!NT_SUCCESS(Status)) { ERR("IoCheckEaBufferValidity returned %08lx (error at offset %lu)\n", Status, offset); - - IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - - free_fileref(fileref); - - return Status; + goto end2; } fileref->fcb->ealen = 4; @@ -3872,12 +3823,8 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO fileref->fcb->ea_xattr.Buffer = ExAllocatePoolWithTag(pool_type, IrpSp->Parameters.Create.EaLength, ALLOC_TAG); if (!fileref->fcb->ea_xattr.Buffer) { ERR("out of memory\n"); - - IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - - free_fileref(fileref); - - return STATUS_INSUFFICIENT_RESOURCES; + Status = STATUS_INSUFFICIENT_RESOURCES; + goto end2; } fileref->fcb->ea_xattr.Length = fileref->fcb->ea_xattr.MaximumLength = (USHORT)IrpSp->Parameters.Create.EaLength; @@ -3914,10 +3861,7 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO Status = delete_fileref(dc->fileref, NULL, false, NULL, rollback); if (!NT_SUCCESS(Status)) { ERR("delete_fileref returned %08lx\n", Status); - - free_fileref(fileref); - - return Status; + goto end2; } } } else @@ -3973,11 +3917,8 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO if (ffei->Flags & FILE_NEED_EA) { WARN("returning STATUS_ACCESS_DENIED as no EA knowledge\n"); - IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - - free_fileref(fileref); - - return STATUS_ACCESS_DENIED; + Status = STATUS_ACCESS_DENIED; + goto end2; } if (ffei->NextEntryOffset == 0) @@ -3994,11 +3935,8 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO if (!ccb) { ERR("out of memory\n"); - IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); - - free_fileref(fileref); - - return STATUS_INSUFFICIENT_RESOURCES; + Status = STATUS_INSUFFICIENT_RESOURCES; + goto end2; } RtlZeroMemory(ccb, sizeof(*ccb)); @@ -4076,7 +4014,17 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO #endif InterlockedIncrement(&Vcb->open_files); - return STATUS_SUCCESS; + Status = STATUS_SUCCESS; + +end2: + if (!NT_SUCCESS(Status)) + IoRemoveShareAccess(FileObject, &fileref->fcb->share_access); + +end: + if (!NT_SUCCESS(Status)) + free_fileref(fileref); + + return Status; } NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension* Vcb, diff --git a/drivers/filesystems/btrfs/fileinfo.c b/drivers/filesystems/btrfs/fileinfo.c index 85006b55fc5..4bebfda1904 100644 --- a/drivers/filesystems/btrfs/fileinfo.c +++ b/drivers/filesystems/btrfs/fileinfo.c @@ -5807,7 +5807,7 @@ NTSTATUS __stdcall drv_set_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { goto end2; } - if (Irp->RequestorMode == KernelMode) { + if (Irp->RequestorMode == KernelMode || ccb->access & FILE_WRITE_ATTRIBUTES) { RtlCopyMemory(&fcb->inode_item.st_uid, item->value.Buffer, sizeof(uint32_t)); fcb->sd_dirty = true; fcb->sd_deleted = false; @@ -5822,7 +5822,7 @@ NTSTATUS __stdcall drv_set_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { goto end2; } - if (Irp->RequestorMode == KernelMode) + if (Irp->RequestorMode == KernelMode || ccb->access & FILE_WRITE_ATTRIBUTES) RtlCopyMemory(&fcb->inode_item.st_gid, item->value.Buffer, sizeof(uint32_t)); RemoveEntryList(&item->list_entry); @@ -5834,7 +5834,7 @@ NTSTATUS __stdcall drv_set_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { goto end2; } - if (Irp->RequestorMode == KernelMode) { + if (Irp->RequestorMode == KernelMode || ccb->access & FILE_WRITE_ATTRIBUTES) { uint32_t allowed = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH | S_ISGID | S_ISVTX | S_ISUID; uint32_t val; diff --git a/drivers/filesystems/btrfs/write.c b/drivers/filesystems/btrfs/write.c index e8e354280c3..0d63ac01cec 100644 --- a/drivers/filesystems/btrfs/write.c +++ b/drivers/filesystems/btrfs/write.c @@ -3298,6 +3298,14 @@ NTSTATUS truncate_file(fcb* fcb, uint64_t end, PIRP Irp, LIST_ENTRY* rollback) { } fcb->inode_item.st_blocks += end; + + fcb->inode_item.st_size = end; + fcb->inode_item_changed = true; + TRACE("setting st_size to %I64x\n", end); + + fcb->Header.AllocationSize.QuadPart = sector_align(fcb->inode_item.st_size, fcb->Vcb->superblock.sector_size); + fcb->Header.FileSize.QuadPart = fcb->inode_item.st_size; + fcb->Header.ValidDataLength.QuadPart = fcb->inode_item.st_size; } ExFreePool(buf);
2 years, 7 months
1
0
0
0
[reactos] 02/10: [BTRFS][UBTRFS][SHELLBTRFS] Upgrade to 1.7.4 (#4417)
by Vincent Franchomme
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=060427353554079bdae3d…
commit 060427353554079bdae3d94cb8e53924d3c3cb16 Author: Vincent Franchomme <franchomme.vincent(a)gmail.com> AuthorDate: Thu Apr 28 21:33:48 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.4 (#4417) v1.7.4 (2020-08-23): - Fixed issue when running compressed EXEs - Changed build system to cmake - Upgraded zstd to version 1.4.5 - Added support for FSCTL_GET_RETRIEVAL_POINTERS - Miscellaneous bug fixes --- dll/shellext/shellbtrfs/CMakeLists.txt | 9 +- dll/shellext/shellbtrfs/balance.cpp | 14 +- dll/shellext/shellbtrfs/contextmenu.cpp | 12 +- dll/shellext/shellbtrfs/main.cpp | 4 +- dll/shellext/shellbtrfs/recv.cpp | 170 +- dll/shellext/shellbtrfs/scrub.cpp | 14 +- dll/shellext/shellbtrfs/send.cpp | 22 +- dll/shellext/shellbtrfs/shellbtrfs.rc | 8 +- dll/shellext/shellbtrfs/volpropsheet.cpp | 21 +- dll/win32/ubtrfs/ubtrfs.rc | 8 +- drivers/filesystems/btrfs/CMakeLists.txt | 47 +- drivers/filesystems/btrfs/boot.c | 4 + drivers/filesystems/btrfs/btrfs.c | 147 +- drivers/filesystems/btrfs/btrfs.rc | 8 +- drivers/filesystems/btrfs/btrfs_drv.h | 87 +- drivers/filesystems/btrfs/btrfsioctl.h | 8 + drivers/filesystems/btrfs/compress.c | 17 +- drivers/filesystems/btrfs/crc32c-amd64.S | 113 - .../filesystems/btrfs/{crc32c-x86.S => crc32c.S} | 100 +- drivers/filesystems/btrfs/crc32c.h | 8 + drivers/filesystems/btrfs/create.c | 8 +- drivers/filesystems/btrfs/dirctrl.c | 2 +- drivers/filesystems/btrfs/fastio.c | 16 + drivers/filesystems/btrfs/fileinfo.c | 8 +- drivers/filesystems/btrfs/flushthread.c | 5 +- drivers/filesystems/btrfs/fsctl.c | 369 +- drivers/filesystems/btrfs/pnp.c | 2 + drivers/filesystems/btrfs/read.c | 75 +- drivers/filesystems/btrfs/reparse.c | 19 +- drivers/filesystems/btrfs/scrub.c | 19 +- drivers/filesystems/btrfs/security.c | 4 +- drivers/filesystems/btrfs/volume.c | 94 +- drivers/filesystems/btrfs/write.c | 6 +- drivers/filesystems/btrfs/xor.S | 342 ++ drivers/filesystems/btrfs/zstd/bitstream.h | 81 +- drivers/filesystems/btrfs/zstd/compiler.h | 78 +- drivers/filesystems/btrfs/zstd/cpu.h | 4 +- drivers/filesystems/btrfs/zstd/debug.h | 75 +- drivers/filesystems/btrfs/zstd/entropy_common.c | 46 +- drivers/filesystems/btrfs/zstd/error_private.c | 9 +- drivers/filesystems/btrfs/zstd/error_private.h | 8 +- drivers/filesystems/btrfs/zstd/fse.h | 50 +- drivers/filesystems/btrfs/zstd/fse_compress.c | 90 +- drivers/filesystems/btrfs/zstd/fse_decompress.c | 48 +- drivers/filesystems/btrfs/zstd/hist.c | 88 +- drivers/filesystems/btrfs/zstd/hist.h | 63 +- drivers/filesystems/btrfs/zstd/huf.h | 78 +- drivers/filesystems/btrfs/zstd/huf_compress.c | 271 +- drivers/filesystems/btrfs/zstd/huf_decompress.c | 414 ++- drivers/filesystems/btrfs/zstd/mem.h | 77 +- drivers/filesystems/btrfs/zstd/zstd.h | 2168 +++++++----- drivers/filesystems/btrfs/zstd/zstd_common.c | 6 +- drivers/filesystems/btrfs/zstd/zstd_compress.c | 3690 +++++++++++--------- .../btrfs/zstd/zstd_compress_internal.h | 495 ++- .../btrfs/zstd/zstd_compress_literals.c | 158 + .../btrfs/zstd/zstd_compress_literals.h | 29 + .../btrfs/zstd/zstd_compress_sequences.c | 419 +++ .../btrfs/zstd/zstd_compress_sequences.h | 54 + .../btrfs/zstd/zstd_compress_superblock.c | 845 +++++ .../btrfs/zstd/zstd_compress_superblock.h | 32 + drivers/filesystems/btrfs/zstd/zstd_cwksp.h | 525 +++ drivers/filesystems/btrfs/zstd/zstd_ddict.c | 244 ++ drivers/filesystems/btrfs/zstd/zstd_ddict.h | 44 + drivers/filesystems/btrfs/zstd/zstd_decompress.c | 2513 ++++--------- .../filesystems/btrfs/zstd/zstd_decompress_block.c | 1432 ++++++++ .../filesystems/btrfs/zstd/zstd_decompress_block.h | 59 + .../btrfs/zstd/zstd_decompress_internal.h | 189 + drivers/filesystems/btrfs/zstd/zstd_double_fast.c | 116 +- drivers/filesystems/btrfs/zstd/zstd_double_fast.h | 2 +- drivers/filesystems/btrfs/zstd/zstd_errors.h | 4 +- drivers/filesystems/btrfs/zstd/zstd_fast.c | 443 ++- drivers/filesystems/btrfs/zstd/zstd_fast.h | 2 +- drivers/filesystems/btrfs/zstd/zstd_internal.h | 236 +- drivers/filesystems/btrfs/zstd/zstd_lazy.c | 159 +- drivers/filesystems/btrfs/zstd/zstd_lazy.h | 4 +- drivers/filesystems/btrfs/zstd/zstd_ldm.c | 127 +- drivers/filesystems/btrfs/zstd/zstd_ldm.h | 15 +- drivers/filesystems/btrfs/zstd/zstd_opt.c | 402 ++- drivers/filesystems/btrfs/zstd/zstd_opt.h | 10 +- sdk/lib/fslib/btrfslib/CMakeLists.txt | 9 +- 80 files changed, 11286 insertions(+), 6415 deletions(-) diff --git a/dll/shellext/shellbtrfs/CMakeLists.txt b/dll/shellext/shellbtrfs/CMakeLists.txt index 6cbd3b04271..8fe8aa4d7ae 100644 --- a/dll/shellext/shellbtrfs/CMakeLists.txt +++ b/dll/shellext/shellbtrfs/CMakeLists.txt @@ -22,10 +22,17 @@ list(APPEND SOURCE volpropsheet.cpp) list(APPEND PCH_SKIP_SOURCE - guid.c) + guid.c + ${REACTOS_SOURCE_DIR}/drivers/filesystems/btrfs/crc32c.c) + +if((ARCH STREQUAL "i386") OR (ARCH STREQUAL "amd64")) + list(APPEND ASM_SOURCE ${REACTOS_SOURCE_DIR}/drivers/filesystems/btrfs/crc32c.S) + add_asm_files(btrfs_asm ${ASM_SOURCE}) +endif() add_library(shellbtrfs MODULE ${SOURCE} + ${btrfs_asm} ${PCH_SKIP_SOURCE} shellbtrfs.rc ${CMAKE_CURRENT_BINARY_DIR}/shellbtrfs.def) diff --git a/dll/shellext/shellbtrfs/balance.cpp b/dll/shellext/shellbtrfs/balance.cpp index b73978167fc..baa2d07ce38 100644 --- a/dll/shellext/shellbtrfs/balance.cpp +++ b/dll/shellext/shellbtrfs/balance.cpp @@ -1061,11 +1061,7 @@ static void unserialize(void* data, ULONG len, WCHAR* s) { } } -#ifdef __REACTOS__ -extern "C" { -#endif - -void CALLBACK StartBalanceW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { +extern "C" void CALLBACK StartBalanceW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { try { WCHAR *s, *vol, *block; win_handle h, token; @@ -1126,7 +1122,7 @@ void CALLBACK StartBalanceW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int } } -void CALLBACK PauseBalanceW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { +extern "C" void CALLBACK PauseBalanceW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { try { win_handle h, token; TOKEN_PRIVILEGES tp; @@ -1173,7 +1169,7 @@ void CALLBACK PauseBalanceW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int } } -void CALLBACK StopBalanceW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { +extern "C" void CALLBACK StopBalanceW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { try { win_handle h, token; TOKEN_PRIVILEGES tp; @@ -1217,7 +1213,3 @@ void CALLBACK StopBalanceW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int n error_message(hwnd, e.what()); } } - -#ifdef __REACTOS__ -} /* extern "C" */ -#endif diff --git a/dll/shellext/shellbtrfs/contextmenu.cpp b/dll/shellext/shellbtrfs/contextmenu.cpp index 3fbca1cb7c2..004ac00057c 100644 --- a/dll/shellext/shellbtrfs/contextmenu.cpp +++ b/dll/shellext/shellbtrfs/contextmenu.cpp @@ -1643,11 +1643,7 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws } } -#ifdef __REACTOS__ -extern "C" { -#endif - -void CALLBACK ReflinkCopyW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { +extern "C" void CALLBACK ReflinkCopyW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { vector<wstring> args; command_line_to_args(lpszCmdLine, args); @@ -1719,8 +1715,4 @@ void CALLBACK ReflinkCopyW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int n } } } -} - -#ifdef __REACTOS__ -} /* extern "C" */ -#endif +} \ No newline at end of file diff --git a/dll/shellext/shellbtrfs/main.cpp b/dll/shellext/shellbtrfs/main.cpp index 9ba209ab664..55b4121a090 100644 --- a/dll/shellext/shellbtrfs/main.cpp +++ b/dll/shellext/shellbtrfs/main.cpp @@ -309,7 +309,7 @@ static void write_reg_key(HKEY root, const wstring& keyname, const WCHAR* val, c static void register_clsid(const GUID clsid, const WCHAR* description) { WCHAR* clsidstring; - wstring inproc, progid, clsidkeyname; + wstring inproc, clsidkeyname; WCHAR dllpath[MAX_PATH]; StringFromCLSID(clsid, &clsidstring); @@ -317,11 +317,9 @@ static void register_clsid(const GUID clsid, const WCHAR* description) { try { #ifndef __REACTOS__ inproc = L"CLSID\\"s + clsidstring + L"\\InprocServer32"s; - progid = L"CLSID\\"s + clsidstring + L"\\ProgId"s; clsidkeyname = L"CLSID\\"s + clsidstring; #else inproc = wstring(L"CLSID\\") + clsidstring + wstring(L"\\InprocServer32"); - progid = wstring(L"CLSID\\") + clsidstring + wstring(L"\\ProgId"); clsidkeyname = wstring(L"CLSID\\") + clsidstring; #endif diff --git a/dll/shellext/shellbtrfs/recv.cpp b/dll/shellext/shellbtrfs/recv.cpp index c18b5c92627..0c1ff3ef589 100644 --- a/dll/shellext/shellbtrfs/recv.cpp +++ b/dll/shellext/shellbtrfs/recv.cpp @@ -23,16 +23,15 @@ #include <iostream> #include "recv.h" #include "resource.h" +#include "crc32c.h" + -#ifndef __REACTOS__ #ifndef _MSC_VER #include <cpuid.h> #else #include <intrin.h> #endif -#include <smmintrin.h> -#endif const string EA_NTACL = "security.NTACL"; const string EA_DOSATTRIB = "user.DOSATTRIB"; @@ -40,118 +39,6 @@ const string EA_REPARSE = "user.reparse"; const string EA_EA = "user.EA"; const string XATTR_USER = "user."; -#ifndef __REACTOS__ -bool have_sse42 = false; -#endif - -static const uint32_t crctable[] = { - 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, 0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb, - 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b, 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24, - 0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b, 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384, - 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, 0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b, - 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a, 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35, - 0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5, 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa, - 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, 0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a, - 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a, 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595, - 0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48, 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957, - 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, 0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198, - 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927, 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38, - 0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8, 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7, - 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, 0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789, - 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859, 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46, - 0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9, 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6, - 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, 0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829, - 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c, 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93, - 0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043, 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c, - 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, 0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc, - 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c, 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033, - 0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652, 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d, - 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, 0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982, - 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d, 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622, - 0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2, 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed, - 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, 0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f, - 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff, 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0, - 0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f, 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540, - 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, 0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f, - 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee, 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1, - 0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321, 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e, - 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, 0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e, - 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e, 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351, -}; - -// HW code taken from
https://github.com/rurban/smhasher/blob/master/crc32_hw.c
-#define ALIGN_SIZE 0x08UL -#define ALIGN_MASK (ALIGN_SIZE - 1) -#define CALC_CRC(op, crc, type, buf, len) \ -do { \ - for (; (len) >= sizeof (type); (len) -= (ULONG)sizeof(type), buf += sizeof (type)) { \ - (crc) = (uint32_t)op((crc), *(type *) (buf)); \ - } \ -} while(0) - -#ifndef __REACTOS__ -static uint32_t crc32c_hw(const void *input, ULONG len, uint32_t crc) { - const char* buf = (const char*)input; - - // Annoyingly, the CRC32 intrinsics don't work properly in modern versions of MSVC - - // it compiles _mm_crc32_u8 as if it was _mm_crc32_u32. And because we're apparently - // not allowed to use inline asm on amd64, there's no easy way to fix this! - - for (; (len > 0) && ((size_t)buf & ALIGN_MASK); len--, buf++) { -#ifdef _MSC_VER - crc = crctable[(crc ^ *buf) & 0xff] ^ (crc >> 8); -#else - crc = _mm_crc32_u8(crc, *buf); -#endif - } - -#ifdef _AMD64_ -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4244) // _mm_crc32_u64 wants to return uint64_t(!) -#pragma warning(disable:4242) -#endif - CALC_CRC(_mm_crc32_u64, crc, uint64_t, buf, len); -#ifdef _MSC_VER -#pragma warning(pop) -#endif -#endif - CALC_CRC(_mm_crc32_u32, crc, uint32_t, buf, len); - -#ifdef _MSC_VER - for (; len > 0; len--, buf++) { - crc = crctable[(crc ^ *buf) & 0xff] ^ (crc >> 8); - } -#else - CALC_CRC(_mm_crc32_u16, crc, uint16_t, buf, len); - CALC_CRC(_mm_crc32_u8, crc, uint8_t, buf, len); -#endif - - return crc; -} -#endif - -static uint32_t calc_crc32c(uint32_t seed, uint8_t* msg, ULONG msglen) { -#ifndef __REACTOS__ - if (have_sse42) - return crc32c_hw(msg, msglen, seed); - else { -#endif - uint32_t rem; - ULONG i; - - rem = seed; - - for (i = 0; i < msglen; i++) { - rem = crctable[(rem ^ msg[i]) & 0xff] ^ (rem >> 8); - } - - return rem; -#ifndef __REACTOS__ - } -#endif -} - bool BtrfsRecv::find_tlv(uint8_t* data, ULONG datalen, uint16_t type, void** value, ULONG* len) { size_t off = 0; @@ -1473,6 +1360,33 @@ void BtrfsRecv::do_recv(const win_handle& f, uint64_t* pos, uint64_t size, const } } +#if defined(_X86_) || defined(_AMD64_) +static void check_cpu() { + bool have_sse42 = false; + +#ifndef _MSC_VER + { + uint32_t eax, ebx, ecx, edx; + + __cpuid(1, eax, ebx, ecx, edx); + + if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) + have_sse42 = ecx & bit_SSE4_2; + } +#else + { + int cpu_info[4]; + + __cpuid(cpu_info, 1); + have_sse42 = (unsigned int)cpu_info[2] & (1 << 20); + } +#endif + + if (have_sse42) + calc_crc32c = calc_crc32c_hw; +} +#endif + DWORD BtrfsRecv::recv_thread() { LARGE_INTEGER size; uint64_t pos = 0; @@ -1612,22 +1526,12 @@ static INT_PTR CALLBACK stub_RecvProgressDlgProc(HWND hwndDlg, UINT uMsg, WPARAM } void BtrfsRecv::Open(HWND hwnd, const wstring& file, const wstring& path, bool quiet) { -#ifndef __REACTOS__ - uint32_t cpuInfo[4]; -#endif - streamfile = file; dirpath = path; subvolpath = L""; -#ifndef __REACTOS__ -#ifndef _MSC_VER - __get_cpuid(1, &cpuInfo[0], &cpuInfo[1], &cpuInfo[2], &cpuInfo[3]); - have_sse42 = cpuInfo[2] & bit_SSE4_2; -#else - __cpuid((int*)cpuInfo, 1); - have_sse42 = cpuInfo[2] & (1 << 20); -#endif +#if defined(_X86_) || defined(_AMD64_) + check_cpu(); #endif if (quiet) @@ -1638,11 +1542,7 @@ void BtrfsRecv::Open(HWND hwnd, const wstring& file, const wstring& path, bool q } } -#ifdef __REACTOS__ -extern "C" { -#endif - -void CALLBACK RecvSubvolGUIW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { +extern "C" void CALLBACK RecvSubvolGUIW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { try { OPENFILENAMEW ofn; WCHAR file[MAX_PATH]; @@ -1714,7 +1614,7 @@ void CALLBACK RecvSubvolGUIW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int } } -void CALLBACK RecvSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { +extern "C" void CALLBACK RecvSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { try { vector<wstring> args; @@ -1774,7 +1674,3 @@ void CALLBACK RecvSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nC cerr << "Error: " << e.what() << endl; } } - -#ifdef __REACTOS__ -} /* extern "C" */ -#endif diff --git a/dll/shellext/shellbtrfs/scrub.cpp b/dll/shellext/shellbtrfs/scrub.cpp index c0b39c0ad4b..f04091851d8 100644 --- a/dll/shellext/shellbtrfs/scrub.cpp +++ b/dll/shellext/shellbtrfs/scrub.cpp @@ -483,11 +483,7 @@ static INT_PTR CALLBACK stub_ScrubDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam return false; } -#ifdef __REACTOS__ -extern "C" { -#endif - -void CALLBACK ShowScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { +extern "C" void CALLBACK ShowScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { try { win_handle token; TOKEN_PRIVILEGES tp; @@ -516,7 +512,7 @@ void CALLBACK ShowScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCm } } -void CALLBACK StartScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { +extern "C" void CALLBACK StartScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { vector<wstring> args; command_line_to_args(lpszCmdLine, args); @@ -552,7 +548,7 @@ void CALLBACK StartScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nC } } -void CALLBACK StopScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { +extern "C" void CALLBACK StopScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { vector<wstring> args; command_line_to_args(lpszCmdLine, args); @@ -587,7 +583,3 @@ void CALLBACK StopScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCm } } } - -#ifdef __REACTOS__ -} /* extern "C" */ -#endif diff --git a/dll/shellext/shellbtrfs/send.cpp b/dll/shellext/shellbtrfs/send.cpp index f61e7510c3e..74ba33774e0 100644 --- a/dll/shellext/shellbtrfs/send.cpp +++ b/dll/shellext/shellbtrfs/send.cpp @@ -532,11 +532,7 @@ void BtrfsSend::Open(HWND hwnd, LPWSTR path) { throw last_error(GetLastError()); } -#ifdef __REACTOS__ -extern "C" { -#endif - -void CALLBACK SendSubvolGUIW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { +extern "C" void CALLBACK SendSubvolGUIW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { try { win_handle token; TOKEN_PRIVILEGES tp; @@ -565,10 +561,6 @@ void CALLBACK SendSubvolGUIW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int } } -#ifdef __REACTOS__ -} /* extern "C" */ -#endif - static void send_subvol(const wstring& subvol, const wstring& file, const wstring& parent, const vector<wstring>& clones) { char* buf; win_handle dirh, stream; @@ -682,11 +674,7 @@ static void send_subvol(const wstring& subvol, const wstring& file, const wstrin free(buf); } -#ifdef __REACTOS__ -extern "C" { -#endif - -void CALLBACK SendSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { +extern "C" void CALLBACK SendSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { vector<wstring> args; wstring subvol = L"", parent = L"", file = L""; vector<wstring> clones; @@ -741,8 +729,4 @@ void CALLBACK SendSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nC } } } -} - -#ifdef __REACTOS__ -} /* extern "C" */ -#endif +} \ No newline at end of file diff --git a/dll/shellext/shellbtrfs/shellbtrfs.rc b/dll/shellext/shellbtrfs/shellbtrfs.rc index efc8aa1e581..4b6bbe2e883 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,3,0 - PRODUCTVERSION 1,7,3,0 + FILEVERSION 1,7,4,0 + PRODUCTVERSION 1,7,4,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -78,12 +78,12 @@ BEGIN BLOCK "080904b0" BEGIN VALUE "FileDescription", "WinBtrfs shell extension" - VALUE "FileVersion", "1.7.3" + VALUE "FileVersion", "1.7.4" VALUE "InternalName", "btrfs" VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-20" VALUE "OriginalFilename", "shellbtrfs.dll" VALUE "ProductName", "WinBtrfs" - VALUE "ProductVersion", "1.7.3" + VALUE "ProductVersion", "1.7.4" END END BLOCK "VarFileInfo" diff --git a/dll/shellext/shellbtrfs/volpropsheet.cpp b/dll/shellext/shellbtrfs/volpropsheet.cpp index 97de35ae3e1..ddc7dc24af0 100644 --- a/dll/shellext/shellbtrfs/volpropsheet.cpp +++ b/dll/shellext/shellbtrfs/volpropsheet.cpp @@ -1590,9 +1590,7 @@ INT_PTR BtrfsChangeDriveLetter::DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, return false; } -#ifdef __REACTOS__ -INT_PTR CALLBACK VolPropSheetDlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ +static INT_PTR __stdcall dlg_proc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { BtrfsChangeDriveLetter* bcdl; if (uMsg == WM_INITDIALOG) { @@ -1603,24 +1601,9 @@ INT_PTR CALLBACK VolPropSheetDlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPA return bcdl->DlgProc(hwndDlg, uMsg, wParam, lParam); } -#endif void BtrfsChangeDriveLetter::show() { -#ifndef __REACTOS__ - DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_DRIVE_LETTER), hwnd, [](HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - BtrfsChangeDriveLetter* bcdl; - - if (uMsg == WM_INITDIALOG) { - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); - bcdl = (BtrfsChangeDriveLetter*)lParam; - } else - bcdl = (BtrfsChangeDriveLetter*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - - return bcdl->DlgProc(hwndDlg, uMsg, wParam, lParam); - }, (LPARAM)this); -#else - DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_DRIVE_LETTER), hwnd, VolPropSheetDlgproc, (LPARAM)this); -#endif + DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_DRIVE_LETTER), hwnd, dlg_proc, (LPARAM)this); } #ifdef __cplusplus diff --git a/dll/win32/ubtrfs/ubtrfs.rc b/dll/win32/ubtrfs/ubtrfs.rc index add9d0a5752..903edb0c9a5 100644 --- a/dll/win32/ubtrfs/ubtrfs.rc +++ b/dll/win32/ubtrfs/ubtrfs.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,7,3,0 - PRODUCTVERSION 1,7,3,0 + FILEVERSION 1,7,4,0 + PRODUCTVERSION 1,7,4,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -68,12 +68,12 @@ BEGIN BLOCK "080904b0" BEGIN VALUE "FileDescription", "Btrfs utility DLL" - VALUE "FileVersion", "1.7.3" + VALUE "FileVersion", "1.7.4" VALUE "InternalName", "ubtrfs" VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-20" VALUE "OriginalFilename", "ubtrfs.dll" VALUE "ProductName", "WinBtrfs" - VALUE "ProductVersion", "1.7.3" + VALUE "ProductVersion", "1.7.4" END END BLOCK "VarFileInfo" diff --git a/drivers/filesystems/btrfs/CMakeLists.txt b/drivers/filesystems/btrfs/CMakeLists.txt index b86b210542e..bbe29b2b838 100644 --- a/drivers/filesystems/btrfs/CMakeLists.txt +++ b/drivers/filesystems/btrfs/CMakeLists.txt @@ -3,6 +3,28 @@ include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/drivers ${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/zlib inc) +set(ZSTD_SRC_FILES + zstd/entropy_common.c + zstd/error_private.c + zstd/fse_compress.c + zstd/fse_decompress.c + zstd/hist.c + zstd/huf_compress.c + zstd/huf_decompress.c + zstd/zstd_common.c + zstd/zstd_compress.c + zstd/zstd_compress_literals.c + zstd/zstd_compress_sequences.c + zstd/zstd_compress_superblock.c + zstd/zstd_ddict.c + zstd/zstd_decompress.c + zstd/zstd_decompress_block.c + zstd/zstd_double_fast.c + zstd/zstd_fast.c + zstd/zstd_lazy.c + zstd/zstd_ldm.c + zstd/zstd_opt.c) + list(APPEND SOURCE balance.c blake2b-ref.c @@ -38,31 +60,14 @@ list(APPEND SOURCE worker-thread.c write.c xxhash.c - zstd/entropy_common.c - zstd/fse_compress.c - zstd/hist.c - zstd/huf_decompress.c - zstd/zstd_common.c - zstd/zstd_decompress.c - zstd/zstd_fast.c - zstd/zstd_ldm.c - zstd/error_private.c - zstd/fse_decompress.c - zstd/huf_compress.c - zstd/zstd_compress.c - zstd/zstd_double_fast.c - zstd/zstd_lazy.c - zstd/zstd_opt.c + ${ZSTD_SRC_FILES} btrfs_drv.h) -if(ARCH STREQUAL "i386") - list(APPEND ASM_SOURCE crc32c-x86.S) -elseif(ARCH STREQUAL "amd64") - list(APPEND ASM_SOURCE crc32c-amd64.S) +if((ARCH STREQUAL "i386") OR (ARCH STREQUAL "amd64")) + list(APPEND ASM_SOURCE crc32c.S xor.S) + add_asm_files(btrfs_asm ${ASM_SOURCE}) endif() -add_asm_files(btrfs_asm ${ASM_SOURCE}) - add_library(btrfs MODULE ${SOURCE} ${btrfs_asm} btrfs.rc) if(MSVC) diff --git a/drivers/filesystems/btrfs/boot.c b/drivers/filesystems/btrfs/boot.c index 810717e9da1..43486cfad33 100644 --- a/drivers/filesystems/btrfs/boot.c +++ b/drivers/filesystems/btrfs/boot.c @@ -506,6 +506,10 @@ void __stdcall check_system_root(PDRIVER_OBJECT DriverObject, PVOID Context, ULO TRACE("(%p, %p, %lu)\n", DriverObject, Context, Count); + UNUSED(DriverObject); + UNUSED(Context); + UNUSED(Count); + // wait for any PNP notifications in progress to finish ExAcquireResourceExclusiveLite(&boot_lock, TRUE); ExReleaseResourceLite(&boot_lock); diff --git a/drivers/filesystems/btrfs/btrfs.c b/drivers/filesystems/btrfs/btrfs.c index 227e5d438c6..4824af9c87b 100644 --- a/drivers/filesystems/btrfs/btrfs.c +++ b/drivers/filesystems/btrfs/btrfs.c @@ -63,9 +63,6 @@ DEFINE_GUID(BtrfsBusInterface, 0x4d414874, 0x6865, 0x6761, 0x6d, 0x65, 0x83, 0x6 PDRIVER_OBJECT drvobj; PDEVICE_OBJECT master_devobj, busobj; -#ifndef __REACTOS__ -bool have_sse2 = false; -#endif uint64_t num_reads = 0; LIST_ENTRY uid_map_list, gid_map_list; LIST_ENTRY VcbList; @@ -123,6 +120,9 @@ static void init_serial(bool first_time); #endif static NTSTATUS close_file(_In_ PFILE_OBJECT FileObject, _In_ PIRP Irp); +static void __stdcall do_xor_basic(uint8_t* buf1, uint8_t* buf2, uint32_t len); + +xor_func do_xor = do_xor_basic; typedef struct { KEVENT Event; @@ -282,6 +282,49 @@ bool is_top_level(_In_ PIRP Irp) { return false; } +static void __stdcall do_xor_basic(uint8_t* buf1, uint8_t* buf2, uint32_t len) { + uint32_t j; + +#if defined(_ARM_) || defined(_ARM64_) + uint64x2_t x1, x2; + + if (((uintptr_t)buf1 & 0xf) == 0 && ((uintptr_t)buf2 & 0xf) == 0) { + while (len >= 16) { + x1 = vld1q_u64((const uint64_t*)buf1); + x2 = vld1q_u64((const uint64_t*)buf2); + x1 = veorq_u64(x1, x2); + vst1q_u64((uint64_t*)buf1, x1); + + buf1 += 16; + buf2 += 16; + len -= 16; + } + } +#endif + +#if defined(_AMD64_) || defined(_ARM64_) + while (len > 8) { + *(uint64_t*)buf1 ^= *(uint64_t*)buf2; + buf1 += 8; + buf2 += 8; + len -= 8; + } +#endif + + while (len > 4) { + *(uint32_t*)buf1 ^= *(uint32_t*)buf2; + buf1 += 4; + buf2 += 4; + len -= 4; + } + + for (j = 0; j < len; j++) { + *buf1 ^= *buf2; + buf1++; + buf2++; + } +} + _Function_class_(DRIVER_UNLOAD) static void __stdcall DriverUnload(_In_ PDRIVER_OBJECT DriverObject) { UNICODE_STRING dosdevice_nameW; @@ -520,7 +563,7 @@ static NTSTATUS __stdcall drv_flush_buffers(_In_ PDEVICE_OBJECT DeviceObject, _I top_level = is_top_level(Irp); if (Vcb && Vcb->type == VCB_TYPE_VOLUME) { - Status = vol_flush_buffers(DeviceObject, Irp); + Status = STATUS_SUCCESS; goto end; } else if (!Vcb || Vcb->type != VCB_TYPE_FS) { Status = STATUS_SUCCESS; @@ -726,14 +769,8 @@ NTSTATUS utf8_to_utf16(WCHAR* dest, ULONG dest_max, ULONG* dest_len, char* src, uint8_t* in = (uint8_t*)src; uint16_t* out = (uint16_t*)dest; ULONG needed = 0, left = dest_max / sizeof(uint16_t); -#ifdef __REACTOS__ - ULONG i; - - for (i = 0; i < src_len; ++i) { -#else for (ULONG i = 0; i < src_len; i++) { -#endif uint32_t cp; if (!(in[i] & 0x80)) @@ -816,14 +853,8 @@ NTSTATUS utf16_to_utf8(char* dest, ULONG dest_max, ULONG* dest_len, WCHAR* src, uint8_t* out = (uint8_t*)dest; ULONG in_len = src_len / sizeof(uint16_t); ULONG needed = 0, left = dest_max; -#ifdef __REACTOS__ - ULONG i = 0; - - for (i = 0; i < in_len; i++) { -#else for (ULONG i = 0; i < in_len; i++) { -#endif uint32_t cp = *in; in++; @@ -934,7 +965,7 @@ static NTSTATUS __stdcall drv_query_volume_information(_In_ PDEVICE_OBJECT Devic top_level = is_top_level(Irp); if (Vcb && Vcb->type == VCB_TYPE_VOLUME) { - Status = vol_query_volume_information(DeviceObject, Irp); + Status = STATUS_INVALID_DEVICE_REQUEST; goto end; } else if (!Vcb || Vcb->type != VCB_TYPE_FS) { Status = STATUS_INVALID_PARAMETER; @@ -1091,9 +1122,9 @@ static NTSTATUS __stdcall drv_query_volume_information(_In_ PDEVICE_OBJECT Devic orig_label_len = label_len; - if (IrpSp->Parameters.QueryVolume.Length < sizeof(FILE_FS_VOLUME_INFORMATION) - sizeof(WCHAR) + label_len) { - if (IrpSp->Parameters.QueryVolume.Length > sizeof(FILE_FS_VOLUME_INFORMATION) - sizeof(WCHAR)) - label_len = IrpSp->Parameters.QueryVolume.Length - sizeof(FILE_FS_VOLUME_INFORMATION) + sizeof(WCHAR); + if (IrpSp->Parameters.QueryVolume.Length < offsetof(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + label_len) { + if (IrpSp->Parameters.QueryVolume.Length > offsetof(FILE_FS_VOLUME_INFORMATION, VolumeLabel)) + label_len = IrpSp->Parameters.QueryVolume.Length - offsetof(FILE_FS_VOLUME_INFORMATION, VolumeLabel); else label_len = 0; @@ -1102,12 +1133,12 @@ static NTSTATUS __stdcall drv_query_volume_information(_In_ PDEVICE_OBJECT Devic TRACE("label_len = %lu\n", label_len); - ffvi.VolumeCreationTime.QuadPart = 0; // FIXME + RtlZeroMemory(&ffvi, offsetof(FILE_FS_VOLUME_INFORMATION, VolumeLabel)); + ffvi.VolumeSerialNumber = Vcb->superblock.uuid.uuid[12] << 24 | Vcb->superblock.uuid.uuid[13] << 16 | Vcb->superblock.uuid.uuid[14] << 8 | Vcb->superblock.uuid.uuid[15]; ffvi.VolumeLabelLength = orig_label_len; - ffvi.SupportsObjects = false; - RtlCopyMemory(data, &ffvi, min(sizeof(FILE_FS_VOLUME_INFORMATION) - sizeof(WCHAR), IrpSp->Parameters.QueryVolume.Length)); + RtlCopyMemory(data, &ffvi, min(offsetof(FILE_FS_VOLUME_INFORMATION, VolumeLabel), IrpSp->Parameters.QueryVolume.Length)); if (label_len > 0) { ULONG bytecount; @@ -1124,7 +1155,7 @@ static NTSTATUS __stdcall drv_query_volume_information(_In_ PDEVICE_OBJECT Devic ExReleaseResourceLite(&Vcb->tree_lock); - BytesCopied = sizeof(FILE_FS_VOLUME_INFORMATION) - sizeof(WCHAR) + label_len; + BytesCopied = offsetof(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + label_len; Status = overflow ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS; break; } @@ -1384,7 +1415,7 @@ static NTSTATUS __stdcall drv_set_volume_information(_In_ PDEVICE_OBJECT DeviceO top_level = is_top_level(Irp); if (Vcb && Vcb->type == VCB_TYPE_VOLUME) { - Status = vol_set_volume_information(DeviceObject, Irp); + Status = STATUS_INVALID_DEVICE_REQUEST; goto end; } else if (!Vcb || Vcb->type != VCB_TYPE_FS) { Status = STATUS_INVALID_PARAMETER; @@ -1779,12 +1810,8 @@ void reap_fcbs(device_extension* Vcb) { } void free_fileref(_Inout_ file_ref* fr) { - LONG rc; - - rc = InterlockedDecrement(&fr->refcount); -#ifdef __REACTOS__ - (void)rc; -#endif +#if defined(_DEBUG) || defined(DEBUG_FCB_REFCOUNTS) + LONG rc = InterlockedDecrement(&fr->refcount); #ifdef DEBUG_FCB_REFCOUNTS ERR("fileref %p: refcount now %i\n", fr, rc); @@ -1796,6 +1823,9 @@ void free_fileref(_Inout_ file_ref* fr) { int3; } #endif +#else + InterlockedDecrement(&fr->refcount); +#endif } void reap_fileref(device_extension* Vcb, file_ref* fr) { @@ -2383,7 +2413,8 @@ static NTSTATUS __stdcall drv_cleanup(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIR top_level = is_top_level(Irp); if (Vcb && Vcb->type == VCB_TYPE_VOLUME) { - Status = vol_cleanup(DeviceObject, Irp); + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; goto exit; } else if (DeviceObject == master_devobj) { TRACE("closing file system\n"); @@ -5215,7 +5246,7 @@ static NTSTATUS __stdcall drv_file_system_control(_In_ PDEVICE_OBJECT DeviceObje top_level = is_top_level(Irp); if (Vcb && Vcb->type == VCB_TYPE_VOLUME) { - Status = vol_file_system_control(DeviceObject, Irp); + Status = STATUS_INVALID_DEVICE_REQUEST; goto end; } else if (!Vcb || (Vcb->type != VCB_TYPE_FS && Vcb->type != VCB_TYPE_CONTROL)) { Status = STATUS_INVALID_PARAMETER; @@ -5295,7 +5326,7 @@ static NTSTATUS __stdcall drv_lock_control(_In_ PDEVICE_OBJECT DeviceObject, _In top_level = is_top_level(Irp); if (Vcb && Vcb->type == VCB_TYPE_VOLUME) { - Status = vol_lock_control(DeviceObject, Irp); + Status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); @@ -5460,7 +5491,7 @@ static NTSTATUS __stdcall drv_shutdown(_In_ PDEVICE_OBJECT DeviceObject, _In_ PI top_level = is_top_level(Irp); if (Vcb && Vcb->type == VCB_TYPE_VOLUME) { - Status = vol_shutdown(DeviceObject, Irp); + Status = STATUS_INVALID_DEVICE_REQUEST; goto end; } @@ -5888,15 +5919,28 @@ static void init_serial(bool first_time) { #if !defined(__REACTOS__) && (defined(_X86_) || defined(_AMD64_)) static void check_cpu() { - bool have_sse42; + bool have_sse2 = false, have_sse42 = false, have_avx2 = false; #ifndef _MSC_VER { - uint32_t eax, ebx, ecx, edx; + uint32_t eax, ebx, ecx, edx, xcr0; __cpuid(1, eax, ebx, ecx, edx); - have_sse42 = ecx & bit_SSE4_2; - have_sse2 = edx & bit_SSE2; + + if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) { + have_sse42 = ecx & bit_SSE4_2; + have_sse2 = edx & bit_SSE2; + } + + if (__get_cpuid_count(7, 0, &eax, &ebx, &ecx, &edx)) + have_avx2 = ebx & bit_AVX2; + + if (have_avx2) { // check if supported by OS + __asm__("xgetbv" : "=a" (xcr0) : "c" (0) : "edx" ); + + if ((xcr0 & 6) != 6) + have_avx2 = false; + } } #else { @@ -5905,6 +5949,16 @@ static void check_cpu() { __cpuid(cpu_info, 1); have_sse42 = cpu_info[2] & (1 << 20); have_sse2 = cpu_info[3] & (1 << 26); + + __cpuidex(cpu_info, 7, 0); + have_avx2 = cpu_info[1] & (1 << 5); + + if (have_avx2) { + uint32_t xcr0 = (uint32_t)_xgetbv(0); + + if ((xcr0 & 6) != 6) + have_avx2 = false; + } } #endif @@ -5914,10 +5968,19 @@ static void check_cpu() { } else TRACE("SSE4.2 not supported\n"); - if (have_sse2) + if (have_sse2) { TRACE("SSE2 is supported\n"); - else + + if (!have_avx2) + do_xor = do_xor_sse2; + } else TRACE("SSE2 is not supported\n"); + + if (have_avx2) { + TRACE("AVX2 is supported\n"); + do_xor = do_xor_avx2; + } else + TRACE("AVX2 is not supported\n"); } #endif @@ -6047,6 +6110,8 @@ NTSTATUS __stdcall AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT Physica TRACE("(%p, %p)\n", DriverObject, PhysicalDeviceObject); + UNUSED(DriverObject); + ExAcquireResourceSharedLite(&pdo_list_lock, true); le = pdo_list.Flink; diff --git a/drivers/filesystems/btrfs/btrfs.rc b/drivers/filesystems/btrfs/btrfs.rc index 44920b9aeee..8a0116a2646 100644 --- a/drivers/filesystems/btrfs/btrfs.rc +++ b/drivers/filesystems/btrfs/btrfs.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,7,3,0 - PRODUCTVERSION 1,7,3,0 + FILEVERSION 1,7,4,0 + PRODUCTVERSION 1,7,4,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -68,12 +68,12 @@ BEGIN BLOCK "080904b0" BEGIN VALUE "FileDescription", "WinBtrfs" - VALUE "FileVersion", "1.7.3" + VALUE "FileVersion", "1.7.4" VALUE "InternalName", "btrfs" VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-20" VALUE "OriginalFilename", "btrfs.sys" VALUE "ProductName", "WinBtrfs" - VALUE "ProductVersion", "1.7.3" + VALUE "ProductVersion", "1.7.4" END END BLOCK "VarFileInfo" diff --git a/drivers/filesystems/btrfs/btrfs_drv.h b/drivers/filesystems/btrfs/btrfs_drv.h index 8b92af9ea83..17c58e4e5d5 100644 --- a/drivers/filesystems/btrfs/btrfs_drv.h +++ b/drivers/filesystems/btrfs/btrfs_drv.h @@ -66,10 +66,6 @@ #include "btrfs.h" #include "btrfsioctl.h" -#if !defined(__REACTOS__) && (defined(_X86_) || defined(_AMD64_)) -#include <emmintrin.h> -#endif - #ifdef __REACTOS__ C_ASSERT(sizeof(bool) == 1); #endif @@ -134,14 +130,16 @@ C_ASSERT(sizeof(bool) == 1); #define try __try #define except __except #define finally __finally +#define leave __leave #else #define try if (1) #define except(x) if (0 && (x)) #define finally if (1) +#define leave #endif #ifndef __REACTOS__ -#ifdef __GNUC__ +#ifndef InterlockedIncrement64 #define InterlockedIncrement64(a) __sync_add_and_fetch(a, 1) #endif #endif // __REACTOS__ @@ -1102,6 +1100,12 @@ __inline static uint32_t get_extent_data_refcount(uint8_t type, void* data) { } } +// in xor-gas.S +#if defined(_X86_) || defined(_AMD64_) +void __stdcall do_xor_sse2(uint8_t* buf1, uint8_t* buf2, uint32_t len); +void __stdcall do_xor_avx2(uint8_t* buf1, uint8_t* buf2, uint32_t len); +#endif + // in btrfs.c _Ret_maybenull_ device* find_device_from_uuid(_In_ device_extension* Vcb, _In_ BTRFS_UUID* uuid); @@ -1131,6 +1135,10 @@ bool is_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stre void send_notification_fileref(_In_ file_ref* fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream); void queue_notification_fcb(_In_ file_ref* fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream); +typedef void (__stdcall *xor_func)(uint8_t* buf1, uint8_t* buf2, uint32_t len); + +extern xor_func do_xor; + #ifdef DEBUG_CHUNK_LOCKS #define acquire_chunk_lock(c, Vcb) { ExAcquireResourceExclusiveLite(&c->lock, true); InterlockedIncrement(&Vcb->chunk_locks_held); } #define release_chunk_lock(c, Vcb) { InterlockedDecrement(&Vcb->chunk_locks_held); ExReleaseResourceLite(&c->lock); } @@ -1176,8 +1184,6 @@ bool check_superblock_checksum(superblock* sb); #define funcname __func__ #endif -extern bool have_sse2; - extern uint32_t mount_compress; extern uint32_t mount_compress_force; extern uint32_t mount_compress_type; @@ -1229,8 +1235,8 @@ void _debug_message(_In_ const char* func, _In_ char* s, ...) __attribute__((for #else -#define TRACE(s, ...) -#define WARN(s, ...) +#define TRACE(s, ...) do { } while(0) +#define WARN(s, ...) do { } while(0) #define FIXME(s, ...) DbgPrint("Btrfs FIXME : %s : " s, funcname, ##__VA_ARGS__) #define ERR(s, ...) DbgPrint("Btrfs ERR : %s : " s, funcname, ##__VA_ARGS__) @@ -1424,10 +1430,10 @@ void insert_dir_child_into_hash_lists(fcb* fcb, dir_child* dc); void remove_dir_child_from_hash_lists(fcb* fcb, dir_child* dc); // in reparse.c -NTSTATUS get_reparse_point(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject, void* buffer, DWORD buflen, ULONG_PTR* retlen); +NTSTATUS get_reparse_point(PFILE_OBJECT FileObject, void* buffer, DWORD buflen, ULONG_PTR* retlen); NTSTATUS set_reparse_point2(fcb* fcb, REPARSE_DATA_BUFFER* rdb, ULONG buflen, ccb* ccb, file_ref* fileref, PIRP Irp, LIST_ENTRY* rollback); -NTSTATUS set_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp); -NTSTATUS delete_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS set_reparse_point(PIRP Irp); +NTSTATUS delete_reparse_point(PIRP Irp); // in create.c @@ -1605,21 +1611,7 @@ NTSTATUS vol_create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); NTSTATUS vol_close(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); NTSTATUS vol_read(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); NTSTATUS vol_write(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); -NTSTATUS vol_query_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); -NTSTATUS vol_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); -NTSTATUS vol_query_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); -NTSTATUS vol_set_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); -NTSTATUS vol_flush_buffers(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); -NTSTATUS vol_query_volume_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); -NTSTATUS vol_set_volume_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); -NTSTATUS vol_cleanup(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); -NTSTATUS vol_directory_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); -NTSTATUS vol_file_system_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); -NTSTATUS vol_lock_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); NTSTATUS vol_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); -NTSTATUS vol_shutdown(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); -NTSTATUS vol_query_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); -NTSTATUS vol_set_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); void add_volume_device(superblock* sb, PUNICODE_STRING devpath, uint64_t length, ULONG disk_num, ULONG part_num); NTSTATUS mountmgr_add_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath); @@ -1734,49 +1726,6 @@ static __inline bool write_fcb_compressed(fcb* fcb) { return false; } -static __inline void do_xor(uint8_t* buf1, uint8_t* buf2, uint32_t len) { - uint32_t j; -#ifndef __REACTOS__ -#if defined(_X86_) || defined(_AMD64_) - __m128i x1, x2; - - if (have_sse2 && ((uintptr_t)buf1 & 0xf) == 0 && ((uintptr_t)buf2 & 0xf) == 0) { - while (len >= 16) { - x1 = _mm_load_si128((__m128i*)buf1); - x2 = _mm_load_si128((__m128i*)buf2); - x1 = _mm_xor_si128(x1, x2); - _mm_store_si128((__m128i*)buf1, x1); - - buf1 += 16; - buf2 += 16; - len -= 16; - } - } -#elif defined(_ARM_) || defined(_ARM64_) - uint64x2_t x1, x2; - - if (((uintptr_t)buf1 & 0xf) == 0 && ((uintptr_t)buf2 & 0xf) == 0) { - while (len >= 16) { - x1 = vld1q_u64((const uint64_t*)buf1); - x2 = vld1q_u64((const uint64_t*)buf2); - x1 = veorq_u64(x1, x2); - vst1q_u64((uint64_t*)buf1, x1); - - buf1 += 16; - buf2 += 16; - len -= 16; - } - } -#endif -#endif // __REACTOS__ - - for (j = 0; j < len; j++) { - *buf1 ^= *buf2; - buf1++; - buf2++; - } -} - #ifdef DEBUG_FCB_REFCOUNTS #ifdef DEBUG_LONG_MESSAGES #define increase_fileref_refcount(fileref) {\ diff --git a/drivers/filesystems/btrfs/btrfsioctl.h b/drivers/filesystems/btrfs/btrfsioctl.h index 0ba18cf837a..dc1cccd89fe 100644 --- a/drivers/filesystems/btrfs/btrfsioctl.h +++ b/drivers/filesystems/btrfs/btrfsioctl.h @@ -37,6 +37,7 @@ #define FSCTL_BTRFS_READ_SEND_BUFFER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x847, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) #define FSCTL_BTRFS_RESIZE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x848, METHOD_IN_DIRECT, FILE_ANY_ACCESS) #define IOCTL_BTRFS_UNLOAD CTL_CODE(FILE_DEVICE_UNKNOWN, 0x849, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_BTRFS_GET_CSUM_INFO CTL_CODE(FILE_DEVICE_UNKNOWN, 0x84a, METHOD_BUFFERED, FILE_READ_ACCESS) typedef struct { uint64_t subvol; @@ -279,3 +280,10 @@ typedef struct { uint64_t device; uint64_t size; } btrfs_resize; + +typedef struct { + uint8_t csum_type; + uint8_t csum_length; + uint64_t num_sectors; + uint8_t data[1]; +} btrfs_csum_info; diff --git a/drivers/filesystems/btrfs/compress.c b/drivers/filesystems/btrfs/compress.c index 786bca33254..d5d229905b6 100644 --- a/drivers/filesystems/btrfs/compress.c +++ b/drivers/filesystems/btrfs/compress.c @@ -703,13 +703,18 @@ NTSTATUS zstd_decompress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32 output.size = outlen; output.pos = 0; - read = ZSTD_decompressStream(stream, &output, &input); + do { + read = ZSTD_decompressStream(stream, &output, &input); - if (ZSTD_isError(read)) { - ERR("ZSTD_decompressStream failed: %s\n", ZSTD_getErrorName(read)); - Status = STATUS_INTERNAL_ERROR; - goto end; - } + if (ZSTD_isError(read)) { + ERR("ZSTD_decompressStream failed: %s\n", ZSTD_getErrorName(read)); + Status = STATUS_INTERNAL_ERROR; + goto end; + } + + if (output.pos == output.size) + break; + } while (read != 0); Status = STATUS_SUCCESS; diff --git a/drivers/filesystems/btrfs/crc32c-amd64.S b/drivers/filesystems/btrfs/crc32c-amd64.S deleted file mode 100644 index dbe035487c7..00000000000 --- a/drivers/filesystems/btrfs/crc32c-amd64.S +++ /dev/null @@ -1,113 +0,0 @@ -/* Copyright (c) Mark Harmstone 2020 - * - * This file is part of WinBtrfs. - * - * WinBtrfs is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public Licence as published by - * the Free Software Foundation, either version 3 of the Licence, or - * (at your option) any later version. - * - * WinBtrfs is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public Licence for more details. - * - * You should have received a copy of the GNU Lesser General Public Licence - * along with WinBtrfs. If not, see <
http://www.gnu.org/licenses/
>. */ - -#include <asm.inc> - -EXTERN crctable:QWORD - -.code64 - - -/* uint32_t __stdcall calc_crc32c_sw(uint32_t seed, uint8_t* msg, uint32_t msglen); */ - -PUBLIC calc_crc32c_sw -calc_crc32c_sw: - -/* rax = crc / seed - * rdx = buf - * r8 = len - * rcx = tmp - * r10 = tmp2 */ - -mov rax, rcx - -crcloop: -test r8, r8 -jz crcend - -mov rcx, rax -shr rcx, 8 -mov r10b, byte ptr [rdx] -xor al, r10b -and rax, 255 -shl rax, 2 -lea r10, [rip+crctable] -mov eax, dword ptr [r10 + rax] -xor rax, rcx - -inc rdx -dec r8 - -jmp crcloop - -crcend: -ret - -/****************************************************/ - -/* uint32_t __stdcall calc_crc32c_hw(uint32_t seed, uint8_t* msg, uint32_t msglen); */ - -PUBLIC calc_crc32c_hw -calc_crc32c_hw: - -/* rax = crc / seed - * rdx = buf - * r8 = len */ - -mov rax, rcx - -crchw_loop: -cmp r8, 8 -jl crchw_stragglers - -crc32 rax, qword ptr [rdx] - -add rdx, 8 -sub r8, 8 -jmp crchw_loop - -crchw_stragglers: -cmp r8, 4 -jl crchw_stragglers2 - -crc32 eax, dword ptr [rdx] - -add rdx, 4 -sub r8, 4 - -crchw_stragglers2: -cmp r8, 2 -jl crchw_stragglers3 - -crc32 eax, word ptr [rdx] - -add rdx, 2 -sub r8, 2 - -crchw_stragglers3: -test r8, r8 -jz crchw_end - -crc32 eax, byte ptr [rdx] -inc rdx -dec r8 -jmp crchw_stragglers3 - -crchw_end: -ret - -END diff --git a/drivers/filesystems/btrfs/crc32c-x86.S b/drivers/filesystems/btrfs/crc32c.S similarity index 62% rename from drivers/filesystems/btrfs/crc32c-x86.S rename to drivers/filesystems/btrfs/crc32c.S index 991eec8dc57..516a911d18c 100644 --- a/drivers/filesystems/btrfs/crc32c-x86.S +++ b/drivers/filesystems/btrfs/crc32c.S @@ -17,8 +17,105 @@ #include <asm.inc> -EXTERN _crctable:DWORD +#ifdef __x86_64__ + +EXTERN crctable:QWORD + +.code64 + +/* uint32_t __stdcall calc_crc32c_sw(uint32_t seed, uint8_t* msg, uint32_t msglen); */ + +PUBLIC calc_crc32c_sw +calc_crc32c_sw: + +/* rax = crc / seed + * rdx = buf + * r8 = len + * rcx = tmp + * r10 = tmp2 */ + +mov rax, rcx + +crcloop: +test r8, r8 +jz crcend + +mov rcx, rax +shr rcx, 8 +mov r10b, byte ptr [rdx] +xor al, r10b +and rax, 255 +shl rax, 2 +lea r10, [rip+crctable] +mov eax, dword ptr [r10 + rax] +xor rax, rcx + +inc rdx +dec r8 + +jmp crcloop + +crcend: +ret + +/****************************************************/ + +/* uint32_t __stdcall calc_crc32c_hw(uint32_t seed, uint8_t* msg, uint32_t msglen); */ + +PUBLIC calc_crc32c_hw + +calc_crc32c_hw: + +/* rax = crc / seed + * rdx = buf + * r8 = len */ +mov rax, rcx + +crchw_loop: +cmp r8, 8 +jl crchw_stragglers + +crc32 rax, qword ptr [rdx] + +add rdx, 8 +sub r8, 8 +jmp crchw_loop + +crchw_stragglers: +cmp r8, 4 +jl crchw_stragglers2 + +crc32 eax, dword ptr [rdx] + +add rdx, 4 +sub r8, 4 + +crchw_stragglers2: +cmp r8, 2 +jl crchw_stragglers3 + +crc32 eax, word ptr [rdx] + +add rdx, 2 +sub r8, 2 + +crchw_stragglers3: +test r8, r8 +jz crchw_end + +crc32 eax, byte ptr [rdx] +inc rdx +dec r8 +jmp crchw_stragglers3 + +crchw_end: +ret + +END +#elif defined(_X86_) + +EXTERN _crctable:DWORD .code /* uint32_t __stdcall calc_crc32c_sw(uint32_t seed, uint8_t* msg, uint32_t msglen); */ @@ -120,3 +217,4 @@ pop ebp ret 12 END +#endif diff --git a/drivers/filesystems/btrfs/crc32c.h b/drivers/filesystems/btrfs/crc32c.h index 73bd9697af3..c012642159f 100644 --- a/drivers/filesystems/btrfs/crc32c.h +++ b/drivers/filesystems/btrfs/crc32c.h @@ -2,6 +2,10 @@ #include <stdint.h> +#ifdef __cplusplus +extern "C" { +#endif + #if defined(_X86_) || defined(_AMD64_) uint32_t __stdcall calc_crc32c_hw(uint32_t seed, uint8_t* msg, uint32_t msglen); #endif @@ -11,3 +15,7 @@ uint32_t __stdcall calc_crc32c_sw(uint32_t seed, uint8_t* msg, uint32_t msglen); typedef uint32_t (__stdcall *crc_func)(uint32_t seed, uint8_t* msg, uint32_t msglen); extern crc_func calc_crc32c; + +#ifdef __cplusplus +} +#endif diff --git a/drivers/filesystems/btrfs/create.c b/drivers/filesystems/btrfs/create.c index 0dee14dc7fd..699228e95a1 100644 --- a/drivers/filesystems/btrfs/create.c +++ b/drivers/filesystems/btrfs/create.c @@ -387,7 +387,7 @@ static NTSTATUS split_path(device_extension* Vcb, PUNICODE_STRING path, LIST_ENT if (nb->us.Buffer[i] == ':') { name_bit* nb2; - if (nb->us.Buffer[i+1] == 0) { + if (i + 1 == nb->us.Length / sizeof(WCHAR)) { WARN("zero-length stream name\n"); Status = STATUS_OBJECT_NAME_INVALID; goto cleanup; @@ -709,7 +709,7 @@ NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lo bool atts_set = false, sd_set = false, no_data; LIST_ENTRY* lastle = NULL; EXTENT_DATA* ed = NULL; - uint64_t fcbs_version; + uint64_t fcbs_version = 0; uint32_t hash; hash = calc_crc32c(0xffffffff, (uint8_t*)&inode, sizeof(uint64_t)); @@ -1687,7 +1687,7 @@ NTSTATUS open_fileref(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusiv UNICODE_STRING fnus2; file_ref *dir, *sf, *sf2; LIST_ENTRY parts; - bool has_stream; + bool has_stream = false; NTSTATUS Status; LIST_ENTRY* le; @@ -4658,7 +4658,7 @@ loaded: if (!NT_SUCCESS(Status)) goto exit; } else { - file_ref* existing_file; + file_ref* existing_file = NULL; Status = file_create(Irp, Vcb, FileObject, related, loaded_related, &fn, RequestedDisposition, options, &existing_file, rollback); diff --git a/drivers/filesystems/btrfs/dirctrl.c b/drivers/filesystems/btrfs/dirctrl.c index 2d0a5fdb351..b13dd2a22ff 100644 --- a/drivers/filesystems/btrfs/dirctrl.c +++ b/drivers/filesystems/btrfs/dirctrl.c @@ -1174,7 +1174,7 @@ NTSTATUS __stdcall drv_directory_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP top_level = is_top_level(Irp); if (Vcb && Vcb->type == VCB_TYPE_VOLUME) { - Status = vol_directory_control(DeviceObject, Irp); + Status = STATUS_INVALID_DEVICE_REQUEST; goto end; } else if (!Vcb || Vcb->type != VCB_TYPE_FS) { Status = STATUS_INVALID_PARAMETER; diff --git a/drivers/filesystems/btrfs/fastio.c b/drivers/filesystems/btrfs/fastio.c index 465e191dfa6..e073f3f9b1d 100644 --- a/drivers/filesystems/btrfs/fastio.c +++ b/drivers/filesystems/btrfs/fastio.c @@ -25,6 +25,8 @@ static BOOLEAN __stdcall fast_query_basic_info(PFILE_OBJECT FileObject, BOOLEAN fcb* fcb; ccb* ccb; + UNUSED(DeviceObject); + FsRtlEnterFileSystem(); TRACE("(%p, %u, %p, %p, %p)\n", FileObject, wait, fbi, IoStatus, DeviceObject); @@ -99,6 +101,8 @@ static BOOLEAN __stdcall fast_query_standard_info(PFILE_OBJECT FileObject, BOOLE bool ads; ULONG adssize; + UNUSED(DeviceObject); + FsRtlEnterFileSystem(); TRACE("(%p, %u, %p, %p, %p)\n", FileObject, wait, fsi, IoStatus, DeviceObject); @@ -198,6 +202,10 @@ static BOOLEAN __stdcall fast_io_query_network_open_info(PFILE_OBJECT FileObject ccb* ccb; file_ref* fileref; + UNUSED(Wait); + UNUSED(IoStatus); // FIXME - really? What about IoStatus->Information? + UNUSED(DeviceObject); + FsRtlEnterFileSystem(); TRACE("(%p, %u, %p, %p, %p)\n", FileObject, Wait, fnoi, IoStatus, DeviceObject); @@ -372,6 +380,8 @@ static BOOLEAN __stdcall fast_io_lock(PFILE_OBJECT FileObject, PLARGE_INTEGER Fi BOOLEAN ret; fcb* fcb = FileObject->FsContext; + UNUSED(DeviceObject); + TRACE("(%p, %I64x, %I64x, %p, %lx, %u, %u, %p, %p)\n", FileObject, FileOffset ? FileOffset->QuadPart : 0, Length ? Length->QuadPart : 0, ProcessId, Key, FailImmediately, ExclusiveLock, IoStatus, DeviceObject); @@ -402,6 +412,8 @@ static BOOLEAN __stdcall fast_io_unlock_single(PFILE_OBJECT FileObject, PLARGE_I ULONG Key, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) { fcb* fcb = FileObject->FsContext; + UNUSED(DeviceObject); + TRACE("(%p, %I64x, %I64x, %p, %lx, %p, %p)\n", FileObject, FileOffset ? FileOffset->QuadPart : 0, Length ? Length->QuadPart : 0, ProcessId, Key, IoStatus, DeviceObject); @@ -428,6 +440,8 @@ _Function_class_(FAST_IO_UNLOCK_ALL) static BOOLEAN __stdcall fast_io_unlock_all(PFILE_OBJECT FileObject, PEPROCESS ProcessId, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) { fcb* fcb = FileObject->FsContext; + UNUSED(DeviceObject); + TRACE("(%p, %p, %p, %p)\n", FileObject, ProcessId, IoStatus, DeviceObject); IoStatus->Information = 0; @@ -458,6 +472,8 @@ static BOOLEAN __stdcall fast_io_unlock_all_by_key(PFILE_OBJECT FileObject, PVOI PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) { fcb* fcb = FileObject->FsContext; + UNUSED(DeviceObject); + TRACE("(%p, %p, %lx, %p, %p)\n", FileObject, ProcessId, Key, IoStatus, DeviceObject); IoStatus->Information = 0; diff --git a/drivers/filesystems/btrfs/fileinfo.c b/drivers/filesystems/btrfs/fileinfo.c index 81c0f06816a..85006b55fc5 100644 --- a/drivers/filesystems/btrfs/fileinfo.c +++ b/drivers/filesystems/btrfs/fileinfo.c @@ -3826,7 +3826,7 @@ NTSTATUS __stdcall drv_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP I Irp->IoStatus.Information = 0; if (Vcb && Vcb->type == VCB_TYPE_VOLUME) { - Status = vol_set_information(DeviceObject, Irp); + Status = STATUS_INVALID_DEVICE_REQUEST; goto end; } else if (!Vcb || Vcb->type != VCB_TYPE_FS) { Status = STATUS_INVALID_PARAMETER; @@ -5345,7 +5345,7 @@ NTSTATUS __stdcall drv_query_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP top_level = is_top_level(Irp); if (Vcb && Vcb->type == VCB_TYPE_VOLUME) { - Status = vol_query_information(DeviceObject, Irp); + Status = STATUS_INVALID_DEVICE_REQUEST; goto end; } else if (!Vcb || Vcb->type != VCB_TYPE_FS) { Status = STATUS_INVALID_PARAMETER; @@ -5399,7 +5399,7 @@ NTSTATUS __stdcall drv_query_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { top_level = is_top_level(Irp); if (Vcb && Vcb->type == VCB_TYPE_VOLUME) { - Status = vol_query_ea(DeviceObject, Irp); + Status = STATUS_INVALID_DEVICE_REQUEST; goto end; } else if (!Vcb || Vcb->type != VCB_TYPE_FS) { Status = STATUS_INVALID_PARAMETER; @@ -5635,7 +5635,7 @@ NTSTATUS __stdcall drv_set_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { top_level = is_top_level(Irp); if (Vcb && Vcb->type == VCB_TYPE_VOLUME) { - Status = vol_set_ea(DeviceObject, Irp); + Status = STATUS_INVALID_DEVICE_REQUEST; goto end; } else if (!Vcb || Vcb->type != VCB_TYPE_FS) { Status = STATUS_INVALID_PARAMETER; diff --git a/drivers/filesystems/btrfs/flushthread.c b/drivers/filesystems/btrfs/flushthread.c index 6495859ab63..e6354b36822 100644 --- a/drivers/filesystems/btrfs/flushthread.c +++ b/drivers/filesystems/btrfs/flushthread.c @@ -5816,6 +5816,8 @@ static NTSTATUS partial_stripe_read(device_extension* Vcb, chunk* c, partial_str } i = (parity + 1) % c->chunk_item->num_stripes; + logstripe = (c->chunk_item->num_stripes + c->chunk_item->num_stripes - 1 - parity + stripe) % c->chunk_item->num_stripes; + for (k = 0; k < c->chunk_item->num_stripes; k++) { if (i != stripe) { if (c->devices[i]->devobj) { @@ -5835,8 +5837,7 @@ static NTSTATUS partial_stripe_read(device_extension* Vcb, chunk* c, partial_str ExFreePool(scratch); return STATUS_UNEXPECTED_IO_ERROR; } - } else - logstripe = k; + } i = (i + 1) % c->chunk_item->num_stripes; } diff --git a/drivers/filesystems/btrfs/fsctl.c b/drivers/filesystems/btrfs/fsctl.c index 70a954d04aa..f1bb68c22a0 100644 --- a/drivers/filesystems/btrfs/fsctl.c +++ b/drivers/filesystems/btrfs/fsctl.c @@ -17,6 +17,7 @@ #include "btrfs_drv.h" #include "btrfsioctl.h" +#include "crc32c.h" #include <ntddstor.h> #include <ntdddisk.h> #ifndef __REACTOS__ @@ -2179,10 +2180,10 @@ end: return Status; } -static NTSTATUS get_object_id(device_extension* Vcb, PFILE_OBJECT FileObject, FILE_OBJECTID_BUFFER* buf, ULONG buflen, ULONG_PTR* retlen) { +static NTSTATUS get_object_id(PFILE_OBJECT FileObject, FILE_OBJECTID_BUFFER* buf, ULONG buflen, ULONG_PTR* retlen) { fcb* fcb; - TRACE("(%p, %p, %p, %lx, %p)\n", Vcb, FileObject, buf, buflen, retlen); + TRACE("(%p, %p, %lx, %p)\n", FileObject, buf, buflen, retlen); if (!FileObject) { ERR("FileObject was NULL\n"); @@ -4965,6 +4966,343 @@ static NTSTATUS fsctl_oplock(device_extension* Vcb, PIRP* Pirp) { return Status; } +static NTSTATUS get_retrieval_pointers(device_extension* Vcb, PFILE_OBJECT FileObject, STARTING_VCN_INPUT_BUFFER* in, + ULONG inlen, RETRIEVAL_POINTERS_BUFFER* out, ULONG outlen, ULONG_PTR* retlen) { + NTSTATUS Status; + fcb* fcb; + + TRACE("get_retrieval_pointers(%p, %p, %p, %lx, %p, %lx, %p)\n", Vcb, FileObject, in, inlen, + out, outlen, retlen); + + if (!FileObject) + return STATUS_INVALID_PARAMETER; + + fcb = FileObject->FsContext; + + if (!fcb) + return STATUS_INVALID_PARAMETER; + + if (inlen < sizeof(STARTING_VCN_INPUT_BUFFER) || in->StartingVcn.QuadPart < 0) + return STATUS_INVALID_PARAMETER; + + if (!out) + return STATUS_INVALID_PARAMETER; + + if (outlen < offsetof(RETRIEVAL_POINTERS_BUFFER, Extents[0])) + return STATUS_BUFFER_TOO_SMALL; + + ExAcquireResourceSharedLite(fcb->Header.Resource, true); + + try { + LIST_ENTRY* le = fcb->extents.Flink; + extent* first_ext = NULL; + unsigned int num_extents = 0, first_extent_num = 0, i; + uint64_t num_sectors, last_off = 0; + + num_sectors = (fcb->inode_item.st_size + Vcb->superblock.sector_size - 1) >> Vcb->sector_shift; + + while (le != &fcb->extents) { + extent* ext = CONTAINING_RECORD(le, extent, list_entry); + + if (ext->ignore || ext->extent_data.type == EXTENT_TYPE_INLINE) { + le = le->Flink; + continue; + } + + if (ext->offset > last_off) + num_extents++; + + if ((ext->offset >> Vcb->sector_shift) <= (uint64_t)in->StartingVcn.QuadPart && + (ext->offset + ext->extent_data.decoded_size) >> Vcb->sector_shift > (uint64_t)in->StartingVcn.QuadPart) { + first_ext = ext; + first_extent_num = num_extents; + } + + num_extents++; + + last_off = ext->offset + ext->extent_data.decoded_size; + + le = le->Flink; + } + + if (num_sectors > last_off >> Vcb->sector_shift) + num_extents++; + + if (!first_ext) { + Status = STATUS_END_OF_FILE; + leave; + } + + out->ExtentCount = num_extents - first_extent_num; + out->StartingVcn.QuadPart = first_ext->offset >> Vcb->sector_shift; + outlen -= offsetof(RETRIEVAL_POINTERS_BUFFER, Extents[0]); + *retlen = offsetof(RETRIEVAL_POINTERS_BUFFER, Extents[0]); + + le = &first_ext->list_entry; + i = 0; + last_off = 0; + + while (le != &fcb->extents) { + extent* ext = CONTAINING_RECORD(le, extent, list_entry); + + if (ext->ignore || ext->extent_data.type == EXTENT_TYPE_INLINE) { + le = le->Flink; + continue; + } + + if (ext->offset > last_off) { + if (outlen < sizeof(LARGE_INTEGER) + sizeof(LARGE_INTEGER)) { + Status = STATUS_BUFFER_OVERFLOW; + leave; + } + + out->Extents[i].NextVcn.QuadPart = ext->offset >> Vcb->sector_shift; + out->Extents[i].Lcn.QuadPart = -1; + + outlen -= sizeof(LARGE_INTEGER) + sizeof(LARGE_INTEGER); + *retlen += sizeof(LARGE_INTEGER) + sizeof(LARGE_INTEGER); + i++; + } + + if (outlen < sizeof(LARGE_INTEGER) + sizeof(LARGE_INTEGER)) { + Status = STATUS_BUFFER_OVERFLOW; + leave; + } + + out->Extents[i].NextVcn.QuadPart = (ext->offset + ext->extent_data.decoded_size) >> Vcb->sector_shift; + + if (ext->extent_data.compression == BTRFS_COMPRESSION_NONE) { + EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ext->extent_data.data; + + out->Extents[i].Lcn.QuadPart = (ed2->address + ed2->offset) >> Vcb->sector_shift; + } else + out->Extents[i].Lcn.QuadPart = -1; + + outlen -= sizeof(LARGE_INTEGER) + sizeof(LARGE_INTEGER); + *retlen += sizeof(LARGE_INTEGER) + sizeof(LARGE_INTEGER); + i++; + + le = le->Flink; + } + + if (num_sectors << Vcb->sector_shift > last_off) { + if (outlen < sizeof(LARGE_INTEGER) + sizeof(LARGE_INTEGER)) { + Status = STATUS_BUFFER_OVERFLOW; + leave; + } + + out->Extents[i].NextVcn.QuadPart = num_sectors; + out->Extents[i].Lcn.QuadPart = -1; + + outlen -= sizeof(LARGE_INTEGER) + sizeof(LARGE_INTEGER); + *retlen += sizeof(LARGE_INTEGER) + sizeof(LARGE_INTEGER); + } + + Status = STATUS_SUCCESS; + } finally { + ExReleaseResourceLite(fcb->Header.Resource); + } + + return Status; +} + +static NTSTATUS add_csum_sparse_extents(device_extension* Vcb, uint64_t sparse_extents, uint8_t** ptr, bool found, void* hash_ptr) { + if (!found) { + uint8_t* sector = ExAllocatePoolWithTag(PagedPool, Vcb->superblock.sector_size, ALLOC_TAG); + + if (!sector) { + ERR("out of memory\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + memset(sector, 0, Vcb->superblock.sector_size); + + get_sector_csum(Vcb, sector, hash_ptr); + + ExFreePool(sector); + } + + switch (Vcb->superblock.csum_type) { + case CSUM_TYPE_CRC32C: { + uint32_t* csum = (uint32_t*)*ptr; + uint32_t sparse_hash = *(uint32_t*)hash_ptr; + + for (uint64_t i = 0; i < sparse_extents; i++) { + csum[i] = sparse_hash; + } + + break; + } + + case CSUM_TYPE_XXHASH: { + uint64_t* csum = (uint64_t*)*ptr; + uint64_t sparse_hash = *(uint64_t*)hash_ptr; + + for (uint64_t i = 0; i < sparse_extents; i++) { + csum[i] = sparse_hash; + } + + break; + } + + case CSUM_TYPE_SHA256: + case CSUM_TYPE_BLAKE2: { + uint8_t* csum = (uint8_t*)*ptr; + + for (uint64_t i = 0; i < sparse_extents; i++) { + memcpy(csum, hash_ptr, 32); + csum += 32; + } + + break; + } + + default: + ERR("unrecognized hash type %x\n", Vcb->superblock.csum_type); + return STATUS_INTERNAL_ERROR; + } + + *ptr += sparse_extents * Vcb->csum_size; + + return STATUS_SUCCESS; +} + +static NTSTATUS get_csum_info(device_extension* Vcb, PFILE_OBJECT FileObject, btrfs_csum_info* buf, ULONG buflen, + ULONG_PTR* retlen, KPROCESSOR_MODE processor_mode) { + NTSTATUS Status; + fcb* fcb; + ccb* ccb; + + TRACE("get_csum_info(%p, %p, %p, %lx, %p, %x)\n", Vcb, FileObject, buf, buflen, retlen, processor_mode); + + if (!FileObject) + return STATUS_INVALID_PARAMETER; + + fcb = FileObject->FsContext; + ccb = FileObject->FsContext2; + + if (!fcb || !ccb) + return STATUS_INVALID_PARAMETER; + + if (!buf) + return STATUS_INVALID_PARAMETER; + + if (buflen < offsetof(btrfs_csum_info, data[0])) + return STATUS_BUFFER_TOO_SMALL; + + + if (processor_mode == UserMode && !(ccb->access & (FILE_READ_DATA | FILE_WRITE_DATA))) { + WARN("insufficient privileges\n"); + return STATUS_ACCESS_DENIED; + } + + ExAcquireResourceSharedLite(fcb->Header.Resource, true); + + try { + LIST_ENTRY* le; + uint8_t* ptr; + uint64_t last_off; + uint8_t sparse_hash[MAX_HASH_SIZE]; + bool sparse_hash_found = false; + + if (fcb->ads) { + Status = STATUS_INVALID_DEVICE_REQUEST; + leave; + } + + if (fcb->type == BTRFS_TYPE_DIRECTORY) { + Status = STATUS_FILE_IS_A_DIRECTORY; + leave; + } + + if (fcb->inode_item.flags & BTRFS_INODE_NODATASUM) { + Status = STATUS_INVALID_DEVICE_REQUEST; + leave; + } + + buf->csum_type = Vcb->superblock.csum_type; + buf->csum_length = Vcb->csum_size; + + le = fcb->extents.Flink; + while (le != &fcb->extents) { + extent* ext = CONTAINING_RECORD(le, extent, list_entry); + + if (ext->ignore) { + le = le->Flink; + continue; + } + + if (ext->extent_data.type == EXTENT_TYPE_INLINE) { + buf->num_sectors = 0; + *retlen = offsetof(btrfs_csum_info, data[0]); + Status = STATUS_SUCCESS; + leave; + } + + le = le->Flink; + } + + buf->num_sectors = (fcb->inode_item.st_size + Vcb->superblock.sector_size - 1) >> Vcb->sector_shift; + + if (buflen < offsetof(btrfs_csum_info, data[0]) + (buf->csum_length * buf->num_sectors)) { + Status = STATUS_BUFFER_OVERFLOW; + *retlen = offsetof(btrfs_csum_info, data[0]); + leave; + } + + ptr = buf->data; + last_off = 0; + + le = fcb->extents.Flink; + while (le != &fcb->extents) { + extent* ext = CONTAINING_RECORD(le, extent, list_entry); + EXTENT_DATA2* ed2; + + if (ext->ignore || ext->extent_data.type == EXTENT_TYPE_INLINE) { + le = le->Flink; + continue; + } + + if (ext->offset > last_off) { + uint64_t sparse_extents = (ext->offset - last_off) >> Vcb->sector_shift; + + add_csum_sparse_extents(Vcb, sparse_extents, &ptr, sparse_hash_found, sparse_hash); + sparse_hash_found = true; + } + + ed2 = (EXTENT_DATA2*)ext->extent_data.data; + + if (ext->extent_data.compression != BTRFS_COMPRESSION_NONE) + memset(ptr, 0, (ed2->num_bytes >> Vcb->sector_shift) * Vcb->csum_size); // dummy value for compressed extents + else { + if (ext->csum) + memcpy(ptr, ext->csum, (ed2->num_bytes >> Vcb->sector_shift) * Vcb->csum_size); + else + memset(ptr, 0, (ed2->num_bytes >> Vcb->sector_shift) * Vcb->csum_size); + + ptr += (ed2->num_bytes >> Vcb->sector_shift) * Vcb->csum_size; + } + + last_off = ext->offset + ed2->num_bytes; + + le = le->Flink; + } + + if (buf->num_sectors > last_off >> Vcb->sector_shift) { + uint64_t sparse_extents = buf->num_sectors - (last_off >> Vcb->sector_shift); + + add_csum_sparse_extents(Vcb, sparse_extents, &ptr, sparse_hash_found, sparse_hash); + } + + *retlen = offsetof(btrfs_csum_info, data[0]) + (buf->csum_length * buf->num_sectors); + Status = STATUS_SUCCESS; + } finally { + ExReleaseResourceLite(fcb->Header.Resource); + } + + return Status; +} + NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP* Pirp, uint32_t type) { PIRP Irp = *Pirp; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); @@ -5065,8 +5403,11 @@ NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP* Pirp, uint32_t type) { break; case FSCTL_GET_RETRIEVAL_POINTERS: - WARN("STUB: FSCTL_GET_RETRIEVAL_POINTERS\n"); - Status = STATUS_INVALID_DEVICE_REQUEST; + Status = get_retrieval_pointers(DeviceObject->DeviceExtension, IrpSp->FileObject, + IrpSp->Parameters.FileSystemControl.Type3InputBuffer, + IrpSp->Parameters.FileSystemControl.InputBufferLength, + Irp->UserBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength, + &Irp->IoStatus.Information); break; case FSCTL_MOVE_FILE: @@ -5093,8 +5434,8 @@ NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP* Pirp, uint32_t type) { break; case FSCTL_GET_OBJECT_ID: - Status = get_object_id(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->UserBuffer, - IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information); + Status = get_object_id(IrpSp->FileObject, Irp->UserBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength, + &Irp->IoStatus.Information); break; case FSCTL_DELETE_OBJECT_ID: @@ -5103,16 +5444,16 @@ NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP* Pirp, uint32_t type) { break; case FSCTL_SET_REPARSE_POINT: - Status = set_reparse_point(DeviceObject, Irp); + Status = set_reparse_point(Irp); break; case FSCTL_GET_REPARSE_POINT: - Status = get_reparse_point(DeviceObject, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer, + Status = get_reparse_point(IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information); break; case FSCTL_DELETE_REPARSE_POINT: - Status = delete_reparse_point(DeviceObject, Irp); + Status = delete_reparse_point(Irp); break; case FSCTL_ENUM_USN_DATA: @@ -5136,8 +5477,8 @@ NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP* Pirp, uint32_t type) { break; case FSCTL_CREATE_OR_GET_OBJECT_ID: - Status = get_object_id(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->UserBuffer, - IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information); + Status = get_object_id(IrpSp->FileObject, Irp->UserBuffer, IrpSp->Parameters.FileSystemControl.OutputBufferLength, + &Irp->IoStatus.Information); break; case FSCTL_SET_SPARSE: @@ -5558,6 +5899,12 @@ NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP* Pirp, uint32_t type) { IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp); break; + case FSCTL_BTRFS_GET_CSUM_INFO: + Status = get_csum_info(DeviceObject->DeviceExtension, IrpSp->FileObject, Irp->AssociatedIrp.SystemBuffer, + IrpSp->Parameters.FileSystemControl.OutputBufferLength, &Irp->IoStatus.Information, + Irp->RequestorMode); + break; + default: WARN("unknown control code %lx (DeviceType = %lx, Access = %lx, Function = %lx, Method = %lx)\n", IrpSp->Parameters.FileSystemControl.FsControlCode, (IrpSp->Parameters.FileSystemControl.FsControlCode & 0xff0000) >> 16, diff --git a/drivers/filesystems/btrfs/pnp.c b/drivers/filesystems/btrfs/pnp.c index 96401908fba..02314ba7a1f 100644 --- a/drivers/filesystems/btrfs/pnp.c +++ b/drivers/filesystems/btrfs/pnp.c @@ -79,6 +79,8 @@ NTSTATUS pnp_surprise_removal(PDEVICE_OBJECT DeviceObject, PIRP Irp) { TRACE("(%p, %p)\n", DeviceObject, Irp); + UNUSED(Irp); + if (DeviceObject->Vpb->Flags & VPB_MOUNTED) { ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true); diff --git a/drivers/filesystems/btrfs/read.c b/drivers/filesystems/btrfs/read.c index 091a0b0b7fe..824a1c17b29 100644 --- a/drivers/filesystems/btrfs/read.c +++ b/drivers/filesystems/btrfs/read.c @@ -466,7 +466,7 @@ 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) { - uint16_t stripe; + uint16_t stripe = 0; NTSTATUS Status; bool checksum_error = false; CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&ci[1]; @@ -653,7 +653,7 @@ static NTSTATUS read_data_raid5(device_extension* Vcb, uint8_t* buf, uint64_t ad NTSTATUS Status; bool checksum_error = false; CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&ci[1]; - uint16_t j, stripe; + uint16_t j, stripe = 0; bool no_success = true; for (j = 0; j < ci->num_stripes; j++) { @@ -950,7 +950,7 @@ void raid6_recover2(uint8_t* sectors, uint16_t num_stripes, ULONG sector_size, u if (missing != 0) galois_divpower(out, (uint8_t)missing, sector_size); } else { // reconstruct from p and q - uint16_t x, y, stripe; + uint16_t x = missing1, y = missing2, stripe; uint8_t gyx, gx, denom, a, b, *p, *q, *pxy, *qxy; uint32_t j; @@ -962,11 +962,6 @@ void raid6_recover2(uint8_t* sectors, uint16_t num_stripes, ULONG sector_size, u if (stripe == missing1 || stripe == missing2) { RtlZeroMemory(qxy, sector_size); RtlZeroMemory(pxy, sector_size); - - if (stripe == missing1) - x = stripe; - else - y = stripe; } else { RtlCopyMemory(qxy, sectors + (stripe * sector_size), sector_size); RtlCopyMemory(pxy, sectors + (stripe * sector_size), sector_size); @@ -980,10 +975,7 @@ void raid6_recover2(uint8_t* sectors, uint16_t num_stripes, ULONG sector_size, u if (stripe != missing1 && stripe != missing2) { do_xor(qxy, sectors + (stripe * sector_size), sector_size); do_xor(pxy, sectors + (stripe * sector_size), sector_size); - } else if (stripe == missing1) - x = stripe; - else if (stripe == missing2) - y = stripe; + } } while (stripe > 0); gyx = gpow2(y > x ? (y-x) : (255-x+y)); @@ -1015,7 +1007,7 @@ static NTSTATUS read_data_raid6(device_extension* Vcb, uint8_t* buf, uint64_t ad NTSTATUS Status; bool checksum_error = false; CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&ci[1]; - uint16_t stripe, j; + uint16_t stripe = 0, j; bool no_success = true; for (j = 0; j < ci->num_stripes; j++) { @@ -1117,7 +1109,7 @@ static NTSTATUS read_data_raid6(device_extension* Vcb, uint8_t* buf, uint64_t ad if (context->tree) { uint8_t* sector; - uint16_t k, physstripe, parity1, parity2, error_stripe; + uint16_t k, physstripe, parity1, parity2, error_stripe = 0; uint64_t off; bool recovered = false, failed = false; ULONG num_errors = 0; @@ -1321,7 +1313,7 @@ static NTSTATUS read_data_raid6(device_extension* Vcb, uint8_t* buf, uint64_t ad physstripe = (parity2 + stripe + 1) % ci->num_stripes; if (!devices[physstripe] || !devices[physstripe]->devobj || (context->csum && !check_sector_csum(Vcb, buf + (i << Vcb->sector_shift), ptr))) { - uint16_t error_stripe; + uint16_t error_stripe = 0; bool recovered = false, failed = false; ULONG num_errors = 0; @@ -2018,7 +2010,7 @@ NTSTATUS read_data(_In_ device_extension* Vcb, _In_ uint64_t addr, _In_ uint32_t uint16_t endoffstripe, parity; uint32_t *stripeoff, pos; PMDL master_mdl; - PFN_NUMBER *pfns, dummy; + PFN_NUMBER *pfns, dummy = 0; bool need_dummy = false; get_raid0_offset(addr - offset, ci->stripe_length, ci->num_stripes - 1, &startoff, &startoffstripe); @@ -2277,7 +2269,7 @@ NTSTATUS read_data(_In_ device_extension* Vcb, _In_ uint64_t addr, _In_ uint32_t uint16_t endoffstripe, parity1; uint32_t *stripeoff, pos; PMDL master_mdl; - PFN_NUMBER *pfns, dummy; + PFN_NUMBER *pfns, dummy = 0; bool need_dummy = false; get_raid0_offset(addr - offset, ci->stripe_length, ci->num_stripes - 2, &startoff, &startoffstripe); @@ -3243,48 +3235,49 @@ nextitem: inpageoff = inoff % LZO_PAGE_SIZE; } - if (off2 != 0) { - outlen = off2 + min(rp->read, (uint32_t)(rp->extents[i].ed_num_bytes - rp->extents[i].off)); + /* Previous versions of this code decompressed directly into the destination buffer, + * but unfortunately that can't be relied on - Windows likes to use dummy pages sometimes + * when mmap-ing, which breaks the backtracking used by e.g. zstd. */ - decomp = ExAllocatePoolWithTag(pool_type, outlen, ALLOC_TAG); - if (!decomp) { - ERR("out of memory\n"); - Status = STATUS_INSUFFICIENT_RESOURCES; - goto exit; - } - } else + if (off2 != 0) + outlen = off2 + min(rp->read, (uint32_t)(rp->extents[i].ed_num_bytes - rp->extents[i].off)); + else outlen = min(rp->read, (uint32_t)(rp->extents[i].ed_num_bytes - rp->extents[i].off)); + decomp = ExAllocatePoolWithTag(pool_type, outlen, ALLOC_TAG); + if (!decomp) { + ERR("out of memory\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } + ccj = (comp_calc_job*)ExAllocatePoolWithTag(pool_type, sizeof(comp_calc_job), ALLOC_TAG); if (!ccj) { ERR("out of memory\n"); - if (decomp) - ExFreePool(decomp); + ExFreePool(decomp); Status = STATUS_INSUFFICIENT_RESOURCES; goto exit; } - Status = add_calc_job_decomp(fcb->Vcb, rp->compression, buf2, inlen, decomp ? decomp : rp->data, outlen, + ccj->data = rp->data; + ccj->decomp = decomp; + + ccj->offset = off2; + ccj->length = (size_t)min(rp->read, rp->extents[i].ed_num_bytes - rp->extents[i].off); + + Status = add_calc_job_decomp(fcb->Vcb, rp->compression, buf2, inlen, decomp, outlen, inpageoff, &ccj->cj); if (!NT_SUCCESS(Status)) { ERR("add_calc_job_decomp returned %08lx\n", Status); - if (decomp) - ExFreePool(decomp); - + ExFreePool(decomp); ExFreePool(ccj); goto exit; } - ccj->data = rp->data; - ccj->decomp = decomp; - - ccj->offset = off2; - ccj->length = (size_t)min(rp->read, rp->extents[i].ed_num_bytes - rp->extents[i].off); - InsertTailList(&calc_jobs, &ccj->list_entry); buf += rp->extents[i].ed_size; @@ -3317,10 +3310,8 @@ nextitem: if (!NT_SUCCESS(ccj->cj->Status)) Status = ccj->cj->Status; - if (ccj->decomp) { - RtlCopyMemory(ccj->data, (uint8_t*)ccj->decomp + ccj->offset, ccj->length); - ExFreePool(ccj->decomp); - } + RtlCopyMemory(ccj->data, (uint8_t*)ccj->decomp + ccj->offset, ccj->length); + ExFreePool(ccj->decomp); ExFreePool(ccj); } diff --git a/drivers/filesystems/btrfs/reparse.c b/drivers/filesystems/btrfs/reparse.c index e6a8145b0d3..03708228d46 100644 --- a/drivers/filesystems/btrfs/reparse.c +++ b/drivers/filesystems/btrfs/reparse.c @@ -24,7 +24,7 @@ typedef struct { 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) { +NTSTATUS get_reparse_point(PFILE_OBJECT FileObject, void* buffer, DWORD buflen, ULONG_PTR* retlen) { USHORT subnamelen, printnamelen, i; ULONG stringlen; DWORD reqlen; @@ -33,7 +33,7 @@ NTSTATUS get_reparse_point(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject, ccb* ccb = FileObject->FsContext2; NTSTATUS Status; - TRACE("(%p, %p, %p, %lx, %p)\n", DeviceObject, FileObject, buffer, buflen, retlen); + TRACE("(%p, %p, %lx, %p)\n", FileObject, buffer, buflen, retlen); if (!ccb) return STATUS_INVALID_PARAMETER; @@ -234,15 +234,16 @@ static NTSTATUS set_symlink(PIRP Irp, file_ref* fileref, fcb* fcb, ccb* ccb, REP 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); + WARN("buffer was less than expected length (%lu < %lu)\n", buflen, + (unsigned long)(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)); + WARN("buffer was less than minimum length (%u < %lu)\n", rdb->ReparseDataLength, + (unsigned long)(offsetof(REPARSE_DATA_BUFFER_LX_SYMLINK, name))); return STATUS_INVALID_PARAMETER; } @@ -397,7 +398,7 @@ NTSTATUS set_reparse_point2(fcb* fcb, REPARSE_DATA_BUFFER* rdb, ULONG buflen, cc return STATUS_SUCCESS; } -NTSTATUS set_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp) { +NTSTATUS set_reparse_point(PIRP Irp) { PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PFILE_OBJECT FileObject = IrpSp->FileObject; void* buffer = Irp->AssociatedIrp.SystemBuffer; @@ -409,7 +410,7 @@ NTSTATUS set_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp) { file_ref* fileref; LIST_ENTRY rollback; - TRACE("(%p, %p)\n", DeviceObject, Irp); + TRACE("(%p)\n", Irp); InitializeListHead(&rollback); @@ -470,7 +471,7 @@ end: return Status; } -NTSTATUS delete_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp) { +NTSTATUS delete_reparse_point(PIRP Irp) { PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PFILE_OBJECT FileObject = IrpSp->FileObject; REPARSE_DATA_BUFFER* rdb = Irp->AssociatedIrp.SystemBuffer; @@ -481,7 +482,7 @@ NTSTATUS delete_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp) { file_ref* fileref; LIST_ENTRY rollback; - TRACE("(%p, %p)\n", DeviceObject, Irp); + TRACE("(%p)\n", Irp); InitializeListHead(&rollback); diff --git a/drivers/filesystems/btrfs/scrub.c b/drivers/filesystems/btrfs/scrub.c index 40938a38077..01160f73654 100644 --- a/drivers/filesystems/btrfs/scrub.c +++ b/drivers/filesystems/btrfs/scrub.c @@ -1377,7 +1377,7 @@ static NTSTATUS scrub_extent(device_extension* Vcb, chunk* c, ULONG type, uint64 scrub_context context; CHUNK_ITEM_STRIPE* cis; NTSTATUS Status; - uint16_t startoffstripe, num_missing, allowed_missing; + uint16_t startoffstripe = 0, num_missing, allowed_missing; TRACE("(%p, %p, %lx, %I64x, %x, %p)\n", Vcb, c, type, offset, size, csum); @@ -1788,8 +1788,8 @@ static void scrub_raid5_stripe(device_extension* Vcb, chunk* c, scrub_context_ra return; for (ULONG i = 0; i < sectors_per_stripe; i++) { - ULONG num_errors = 0, bad_off; - uint64_t bad_stripe; + ULONG num_errors = 0, bad_off = 0; + uint64_t bad_stripe = 0; bool alloc = false; stripe = (parity + 1) % c->chunk_item->num_stripes; @@ -2006,8 +2006,8 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra for (ULONG i = 0; i < sectors_per_stripe; i++) { ULONG num_errors = 0; - uint64_t bad_stripe1, bad_stripe2; - ULONG bad_off1, bad_off2; + uint64_t bad_stripe1 = 0, bad_stripe2 = 0; + ULONG bad_off1 = 0, bad_off2 = 0; bool alloc = false; stripe = (parity1 + 2) % c->chunk_item->num_stripes; @@ -2071,7 +2071,6 @@ 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->sector_shift); uint8_t* scratch; @@ -2091,6 +2090,8 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra stripe = parity1 == 0 ? (c->chunk_item->num_stripes - 1) : (parity1 - 1); if (c->devices[parity2]->devobj) { + uint16_t stripe_num, bad_stripe_num = 0; + stripe_num = c->chunk_item->num_stripes - 3; while (stripe != parity2) { galois_double(scratch, len); @@ -2275,7 +2276,7 @@ static void scrub_raid6_stripe(device_extension* Vcb, chunk* c, scrub_context_ra ExFreePool(scratch); } else if (num_errors == 2 && missing_devices == 0) { - uint16_t x, y, k; + uint16_t x = 0, y = 0, k; uint64_t addr; uint32_t len = (RtlCheckBit(&context->is_tree, bad_off1) || RtlCheckBit(&context->is_tree, bad_off2)) ? Vcb->superblock.node_size : Vcb->superblock.sector_size; uint8_t gyx, gx, denom, a, b, *p, *q, *pxy, *qxy; @@ -2837,7 +2838,7 @@ static NTSTATUS scrub_chunk_raid56(device_extension* Vcb, chunk* c, uint64_t* of KEY searchkey; traverse_ptr tp; bool b; - uint64_t full_stripe_len, stripe, stripe_start, stripe_end, total_data = 0; + uint64_t full_stripe_len, stripe, stripe_start = 0, stripe_end = 0, total_data = 0; ULONG num_extents = 0, num_parity_stripes = c->chunk_item->type & BLOCK_FLAG_RAID6 ? 2 : 1; full_stripe_len = (c->chunk_item->num_stripes - num_parity_stripes) * c->chunk_item->stripe_length; @@ -2925,7 +2926,7 @@ static NTSTATUS scrub_chunk(device_extension* Vcb, chunk* c, uint64_t* offset, b traverse_ptr tp; bool b = false, tree_run = false; ULONG type, num_extents = 0; - uint64_t total_data = 0, tree_run_start, tree_run_end; + uint64_t total_data = 0, tree_run_start = 0, tree_run_end = 0; TRACE("chunk %I64x\n", c->offset); diff --git a/drivers/filesystems/btrfs/security.c b/drivers/filesystems/btrfs/security.c index f6769d05606..2761c63a915 100644 --- a/drivers/filesystems/btrfs/security.c +++ b/drivers/filesystems/btrfs/security.c @@ -678,7 +678,7 @@ NTSTATUS __stdcall drv_query_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Ir top_level = is_top_level(Irp); if (Vcb && Vcb->type == VCB_TYPE_VOLUME) { - Status = vol_query_security(DeviceObject, Irp); + Status = STATUS_INVALID_DEVICE_REQUEST; goto end; } else if (!Vcb || Vcb->type != VCB_TYPE_FS) { Status = STATUS_INVALID_PARAMETER; @@ -842,7 +842,7 @@ NTSTATUS __stdcall drv_set_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) top_level = is_top_level(Irp); if (Vcb && Vcb->type == VCB_TYPE_VOLUME) { - Status = vol_set_security(DeviceObject, Irp); + Status = STATUS_INVALID_DEVICE_REQUEST; goto end; } else if (!Vcb || Vcb->type != VCB_TYPE_FS) { Status = STATUS_INVALID_PARAMETER; diff --git a/drivers/filesystems/btrfs/volume.c b/drivers/filesystems/btrfs/volume.c index e89b6154d31..3ee63ed29f6 100644 --- a/drivers/filesystems/btrfs/volume.c +++ b/drivers/filesystems/btrfs/volume.c @@ -303,74 +303,6 @@ end: return Status; } -NTSTATUS vol_query_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - TRACE("(%p, %p)\n", DeviceObject, Irp); - - return STATUS_INVALID_DEVICE_REQUEST; -} - -NTSTATUS vol_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - TRACE("(%p, %p)\n", DeviceObject, Irp); - - return STATUS_INVALID_DEVICE_REQUEST; -} - -NTSTATUS vol_query_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - TRACE("(%p, %p)\n", DeviceObject, Irp); - - return STATUS_INVALID_DEVICE_REQUEST; -} - -NTSTATUS vol_set_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - TRACE("(%p, %p)\n", DeviceObject, Irp); - - return STATUS_INVALID_DEVICE_REQUEST; -} - -NTSTATUS vol_flush_buffers(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - TRACE("(%p, %p)\n", DeviceObject, Irp); - - return STATUS_SUCCESS; -} - -NTSTATUS vol_query_volume_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - TRACE("(%p, %p)\n", DeviceObject, Irp); - - return STATUS_INVALID_DEVICE_REQUEST; -} - -NTSTATUS vol_set_volume_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - TRACE("(%p, %p)\n", DeviceObject, Irp); - - return STATUS_INVALID_DEVICE_REQUEST; -} - -NTSTATUS vol_cleanup(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - TRACE("(%p, %p)\n", DeviceObject, Irp); - - Irp->IoStatus.Information = 0; - - return STATUS_SUCCESS; -} - -NTSTATUS vol_directory_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - TRACE("(%p, %p)\n", DeviceObject, Irp); - - return STATUS_INVALID_DEVICE_REQUEST; -} - -NTSTATUS vol_file_system_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - TRACE("(%p, %p)\n", DeviceObject, Irp); - - return STATUS_INVALID_DEVICE_REQUEST; -} - -NTSTATUS vol_lock_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - TRACE("(%p, %p)\n", DeviceObject, Irp); - - return STATUS_INVALID_DEVICE_REQUEST; -} - static NTSTATUS vol_query_device_name(volume_device_extension* vde, PIRP Irp) { PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PMOUNTDEV_NAME name; @@ -877,17 +809,15 @@ NTSTATUS vol_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { return vol_get_disk_extents(vde, Irp); default: { // pass ioctl through if only one child device - ULONG code = IrpSp->Parameters.DeviceIoControl.IoControlCode; NTSTATUS Status = vol_ioctl_passthrough(vde, Irp); - -#ifdef __REACTOS__ - &code; -#endif +#ifdef _DEBUG + ULONG code = IrpSp->Parameters.DeviceIoControl.IoControlCode; if (NT_SUCCESS(Status)) TRACE("passing through ioctl %lx (returning %08lx)\n", code, Status); else WARN("passing through ioctl %lx (returning %08lx)\n", code, Status); +#endif return Status; } @@ -896,24 +826,6 @@ NTSTATUS vol_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { return STATUS_INVALID_DEVICE_REQUEST; } -NTSTATUS vol_shutdown(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - TRACE("(%p, %p)\n", DeviceObject, Irp); - - return STATUS_INVALID_DEVICE_REQUEST; -} - -NTSTATUS vol_query_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - TRACE("(%p, %p)\n", DeviceObject, Irp); - - return STATUS_INVALID_DEVICE_REQUEST; -} - -NTSTATUS vol_set_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - TRACE("(%p, %p)\n", DeviceObject, Irp); - - return STATUS_INVALID_DEVICE_REQUEST; -} - NTSTATUS mountmgr_add_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath) { NTSTATUS Status; ULONG mmdltsize; diff --git a/drivers/filesystems/btrfs/write.c b/drivers/filesystems/btrfs/write.c index b73c17d689c..e8e354280c3 100644 --- a/drivers/filesystems/btrfs/write.c +++ b/drivers/filesystems/btrfs/write.c @@ -552,9 +552,7 @@ NTSTATUS alloc_chunk(device_extension* Vcb, uint64_t flags, chunk** pc, bool ful } } - if (type == 0 || type == BLOCK_FLAG_DUPLICATE || type == BLOCK_FLAG_RAID1 || type == BLOCK_FLAG_RAID1C3 || type == BLOCK_FLAG_RAID1C4) - factor = 1; - else if (type == BLOCK_FLAG_RAID0) + if (type == BLOCK_FLAG_RAID0) factor = num_stripes; else if (type == BLOCK_FLAG_RAID10) factor = num_stripes / sub_stripes; @@ -562,6 +560,8 @@ NTSTATUS alloc_chunk(device_extension* Vcb, uint64_t flags, chunk** pc, bool ful factor = num_stripes - 1; else if (type == BLOCK_FLAG_RAID6) factor = num_stripes - 2; + else + factor = 1; // SINGLE, DUPLICATE, RAID1, RAID1C3, RAID1C4 if (stripe_size * factor > max_chunk_size) stripe_size = max_chunk_size / factor; diff --git a/drivers/filesystems/btrfs/xor.S b/drivers/filesystems/btrfs/xor.S new file mode 100644 index 00000000000..0a2b7e21580 --- /dev/null +++ b/drivers/filesystems/btrfs/xor.S @@ -0,0 +1,342 @@ +/* Copyright (c) Mark Harmstone 2020 + * + * This file is part of WinBtrfs. + * + * WinBtrfs is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public Licence as published by + * the Free Software Foundation, either version 3 of the Licence, or + * (at your option) any later version. + * + * WinBtrfs is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public Licence for more details. + * + * You should have received a copy of the GNU Lesser General Public Licence + * along with WinBtrfs. If not, see <
http://www.gnu.org/licenses/
>. */ + +#include <asm.inc> + +#ifdef __x86_64__ + +.code64 + +/* void do_xor_sse2(uint8_t* buf1, uint8_t* buf2, uint32_t len); */ +PUBLIC do_xor_sse2 +do_xor_sse2: + /* rcx = buf1 + * rdx = buf2 + * r8d = len + * rax = tmp1 + * r9 = tmp2 + * xmm0 = tmp3 + * xmm1 = tmp4 */ + + mov rax, rcx + and rax, 15 + cmp rax, 0 + jne stragglers2 + + mov rax, rdx + and rax, 15 + cmp rax, 0 + jne stragglers2 + +do_xor_sse2_loop: + cmp r8d, 16 + jl stragglers2 + + movdqa xmm0, [rcx] + movdqa xmm1, [rdx] + pxor xmm0, xmm1 + movdqa [rcx], xmm0 + + add rcx, 16 + add rdx, 16 + sub r8d, 16 + + jmp do_xor_sse2_loop + +stragglers2: + + cmp r8d, 8 + jl stragglers + + mov rax, [rcx] + mov r9, [rdx] + xor rax, r9 + mov [rcx], rax + + add rcx, 8 + add rdx, 8 + sub r8d, 8 + + jmp stragglers2 + +stragglers: + + cmp r8d, 0 + je do_xor_sse2_end + + mov al, [rcx] + mov r9b, [rdx] + xor al, r9b + mov [rcx], al + + inc rcx + inc rdx + dec r8d + + jmp stragglers + +do_xor_sse2_end: + ret + +/* void do_xor_avx2(uint8_t* buf1, uint8_t* buf2, uint32_t len); */ +PUBLIC do_xor_avx2 +do_xor_avx2: + /* rcx = buf1 + * rdx = buf2 + * r8d = len + * rax = tmp1 + * r9 = tmp2 + * xmm0 = tmp3 + * xmm1 = tmp4 */ + + mov rax, rcx + and rax, 31 + cmp rax, 0 + jne stragglers4 + + mov rax, rdx + and rax, 31 + cmp rax, 0 + jne stragglers4 + +do_xor_avx2_loop: + cmp r8d, 32 + jl stragglers4 + + vmovdqa ymm0, YMMWORD PTR[rcx] + vmovdqa ymm1, YMMWORD PTR[rdx] + vpxor ymm0, ymm0, ymm1 + vmovdqa YMMWORD PTR[rcx], ymm0 + + add rcx, 32 + add rdx, 32 + sub r8d, 32 + + jmp do_xor_avx2_loop + +stragglers4: + + cmp r8d, 8 + jl stragglers3 + + mov rax, [rcx] + mov r9, [rdx] + xor rax, r9 + mov [rcx], rax + + add rcx, 8 + add rdx, 8 + sub r8d, 8 + + jmp stragglers4 + +stragglers3: + + cmp r8d, 0 + je do_xor_avx2_end + + mov al, [rcx] + mov r9b, [rdx] + xor al, r9b + mov [rcx], al + + inc rcx + inc rdx + dec r8d + + jmp stragglers3 + +do_xor_avx2_end: + ret +END +#else + +.code + +/* void __stdcall do_xor_sse2(uint8_t* buf1, uint8_t* buf2, uint32_t len); */ +PUBLIC _do_xor_sse2@12 +_do_xor_sse2@12: + /* edi = buf1 + * edx = buf2 + * esi = len + * eax = tmp1 + * ecx = tmp2 + * xmm0 = tmp3 + * xmm1 = tmp4 */ + + push ebp + mov ebp, esp + + push esi + push edi + + mov edi, [ebp+8] + mov edx, [ebp+12] + mov esi, [ebp+16] + + mov eax, edi + and eax, 15 + cmp eax, 0 + jne stragglers2 + + mov eax, edx + and eax, 15 + cmp eax, 0 + jne stragglers2 + +do_xor_sse2_loop: + cmp esi, 16 + jl stragglers2 + + movdqa xmm0, [edi] + movdqa xmm1, [edx] + pxor xmm0, xmm1 + movdqa [edi], xmm0 + + add edi, 16 + add edx, 16 + sub esi, 16 + + jmp do_xor_sse2_loop + +stragglers2: + + cmp esi, 4 + jl stragglers + + mov eax, [edi] + mov ecx, [edx] + xor eax, ecx + mov [edi], eax + + add edi, 4 + add edx, 4 + sub esi, 4 + + jmp stragglers2 + +stragglers: + + cmp esi, 0 + je do_xor_sse2_end + + mov al, [edi] + mov cl, [edx] + xor al, cl + mov [edi], al + + inc edi + inc edx + dec esi + + jmp stragglers + +do_xor_sse2_end: + pop edi + pop esi + pop ebp + + ret 12 + +/* void __stdcall do_xor_avx2(uint8_t* buf1, uint8_t* buf2, uint32_t len); */ +PUBLIC _do_xor_avx2@12 +_do_xor_avx2@12: + /* edi = buf1 + * edx = buf2 + * esi = len + * eax = tmp1 + * ecx = tmp2 + * xmm0 = tmp3 + * xmm1 = tmp4 */ + + push ebp + mov ebp, esp + + push esi + push edi + + mov edi, [ebp+8] + mov edx, [ebp+12] + mov esi, [ebp+16] + + mov eax, edi + and eax, 31 + cmp eax, 0 + jne stragglers4 + + mov eax, edx + and eax, 31 + cmp eax, 0 + jne stragglers4 + +do_xor_avx2_loop: + cmp esi, 32 + jl stragglers4 + + vmovdqa ymm0, YMMWORD PTR[edi] + vmovdqa ymm1, YMMWORD PTR[edx] + vpxor ymm0, ymm0, ymm1 + vmovdqa YMMWORD PTR[edi], ymm0 + + add edi, 32 + add edx, 32 + sub esi, 32 + + jmp do_xor_avx2_loop + +stragglers4: + + cmp esi, 4 + jl stragglers3 + + mov eax, [edi] + mov ecx, [edx] + xor eax, ecx + mov [edi], eax + + add edi, 4 + add edx, 4 + sub esi, 4 + + jmp stragglers4 + +stragglers3: + + cmp esi, 0 + je do_xor_avx2_end + + mov al, [edi] + mov cl, [edx] + xor al, cl + mov [edi], al + + inc edi + inc edx + dec esi + + jmp stragglers3 + +do_xor_avx2_end: + pop edi + pop esi + pop ebp + + ret 12 + +END + +#endif diff --git a/drivers/filesystems/btrfs/zstd/bitstream.h b/drivers/filesystems/btrfs/zstd/bitstream.h index ef89b9878e2..37b99c01eed 100644 --- a/drivers/filesystems/btrfs/zstd/bitstream.h +++ b/drivers/filesystems/btrfs/zstd/bitstream.h @@ -1,35 +1,15 @@ /* ****************************************************************** - bitstream - Part of FSE library - Copyright (C) 2013-present, Yann Collet. - - BSD 2-Clause License (
http://www.opensource.org/licenses/bsd-license.php
) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - Source repository :
https://github.com/Cyan4973/FiniteStateEntropy
+ * bitstream + * Part of FSE library + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - Source repository :
https://github.com/Cyan4973/FiniteStateEntropy
+ * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ #ifndef BITSTREAM_H_MODULE #define BITSTREAM_H_MODULE @@ -48,6 +28,7 @@ extern "C" { * Dependencies ******************************************/ #include "mem.h" /* unaligned access routines */ +#include "compiler.h" /* UNLIKELY() */ #include "debug.h" /* assert(), DEBUGLOG(), RAWLOG() */ #include "error_private.h" /* error codes and messages */ @@ -57,6 +38,8 @@ extern "C" { =========================================*/ #if defined(__BMI__) && defined(__GNUC__) # include <immintrin.h> /* support for bextr (experimental) */ +#elif defined(__ICCARM__) +# include <intrinsics.h> #endif #define STREAM_ACCUMULATOR_MIN_32 25 @@ -159,10 +142,11 @@ MEM_STATIC unsigned BIT_highbit32 (U32 val) { # if defined(_MSC_VER) /* Visual */ unsigned long r=0; - _BitScanReverse ( &r, val ); - return (unsigned) r; + return _BitScanReverse ( &r, val ) ? (unsigned)r : 0; # elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */ - return 31 - __builtin_clz (val); + return __builtin_clz (val) ^ 31; +# elif defined(__ICCARM__) /* IAR Intrinsic */ + return 31 - __CLZ(val); # else /* Software version */ static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, @@ -240,9 +224,9 @@ MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC) { size_t const nbBytes = bitC->bitPos >> 3; assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8); + assert(bitC->ptr <= bitC->endPtr); MEM_writeLEST(bitC->ptr, bitC->bitContainer); bitC->ptr += nbBytes; - assert(bitC->ptr <= bitC->endPtr); bitC->bitPos &= 7; bitC->bitContainer >>= nbBytes*8; } @@ -256,6 +240,7 @@ MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC) { size_t const nbBytes = bitC->bitPos >> 3; assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8); + assert(bitC->ptr <= bitC->endPtr); MEM_writeLEST(bitC->ptr, bitC->bitContainer); bitC->ptr += nbBytes; if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr; @@ -389,7 +374,7 @@ MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits) * Read (consume) next n bits from local register and update. * Pay attention to not read more than nbBits contained into local register. * @return : extracted value. */ -MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits) +MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits) { size_t const value = BIT_lookBits(bitD, nbBits); BIT_skipBits(bitD, nbBits); @@ -398,7 +383,7 @@ MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits) /*! BIT_readBitsFast() : * unsafe version; only works only if nbBits >= 1 */ -MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits) +MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits) { size_t const value = BIT_lookBitsFast(bitD, nbBits); assert(nbBits >= 1); @@ -406,6 +391,23 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits) return value; } +/*! BIT_reloadDStreamFast() : + * Similar to BIT_reloadDStream(), but with two differences: + * 1. bitsConsumed <= sizeof(bitD->bitContainer)*8 must hold! + * 2. Returns BIT_DStream_overflow when bitD->ptr < bitD->limitPtr, at this + * point you must use BIT_reloadDStream() to reload. + */ +MEM_STATIC BIT_DStream_status BIT_reloadDStreamFast(BIT_DStream_t* bitD) +{ + if (UNLIKELY(bitD->ptr < bitD->limitPtr)) + return BIT_DStream_overflow; + assert(bitD->bitsConsumed <= sizeof(bitD->bitContainer)*8); + bitD->ptr -= bitD->bitsConsumed >> 3; + bitD->bitsConsumed &= 7; + bitD->bitContainer = MEM_readLEST(bitD->ptr); + return BIT_DStream_unfinished; +} + /*! BIT_reloadDStream() : * Refill `bitD` from buffer previously set in BIT_initDStream() . * This function is safe, it guarantees it will not read beyond src buffer. @@ -417,10 +419,7 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD) return BIT_DStream_overflow; if (bitD->ptr >= bitD->limitPtr) { - bitD->ptr -= bitD->bitsConsumed >> 3; - bitD->bitsConsumed &= 7; - bitD->bitContainer = MEM_readLEST(bitD->ptr); - return BIT_DStream_unfinished; + return BIT_reloadDStreamFast(bitD); } if (bitD->ptr == bitD->start) { if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer; diff --git a/drivers/filesystems/btrfs/zstd/compiler.h b/drivers/filesystems/btrfs/zstd/compiler.h index 07f875e4d38..95e9483521d 100644 --- a/drivers/filesystems/btrfs/zstd/compiler.h +++ b/drivers/filesystems/btrfs/zstd/compiler.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -15,13 +15,15 @@ * Compiler specifics *********************************************************/ /* force inlining */ -#if defined (__GNUC__) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ + +#if !defined(ZSTD_NO_INLINE) +#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ # define INLINE_KEYWORD inline #else # define INLINE_KEYWORD #endif -#if defined(__GNUC__) +#if defined(__GNUC__) || defined(__ICCARM__) # define FORCE_INLINE_ATTR __attribute__((always_inline)) #elif defined(_MSC_VER) # define FORCE_INLINE_ATTR __forceinline @@ -29,9 +31,16 @@ # define FORCE_INLINE_ATTR #endif +#else + +#define INLINE_KEYWORD +#define FORCE_INLINE_ATTR + +#endif + /** * FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant - * parameters. They must be inlined for the compiler to elimininate the constant + * parameters. They must be inlined for the compiler to eliminate the constant * branches. */ #define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR @@ -52,11 +61,18 @@ # define HINT_INLINE static INLINE_KEYWORD FORCE_INLINE_ATTR #endif +/* UNUSED_ATTR tells the compiler it is okay if the function is unused. */ +#if defined(__GNUC__) +# define UNUSED_ATTR __attribute__((unused)) +#else +# define UNUSED_ATTR +#endif + /* force no inlining */ #ifdef _MSC_VER # define FORCE_NOINLINE static __declspec(noinline) #else -# ifdef __GNUC__ +# if defined(__GNUC__) || defined(__ICCARM__) # define FORCE_NOINLINE static __attribute__((__noinline__)) # else # define FORCE_NOINLINE static @@ -67,7 +83,7 @@ #ifndef __has_attribute #define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ #endif -#if defined(__GNUC__) +#if defined(__GNUC__) || defined(__ICCARM__) # define TARGET_ATTRIBUTE(target) __attribute__((__target__(target))) #else # define TARGET_ATTRIBUTE(target) @@ -89,23 +105,24 @@ #endif /* prefetch - * can be disabled, by declaring NO_PREFETCH macro - * All prefetch invocations use a single default locality 2, - * generating instruction prefetcht1, - * which, according to Intel, means "load data into L2 cache". - * This is a good enough "middle ground" for the time being, - * though in theory, it would be better to specialize locality depending on data being prefetched. - * Tests could not determine any sensible difference based on locality value. */ + * can be disabled, by declaring NO_PREFETCH build macro */ #if defined(NO_PREFETCH) -# define PREFETCH(ptr) (void)(ptr) /* disabled */ +# define PREFETCH_L1(ptr) (void)(ptr) /* disabled */ +# define PREFETCH_L2(ptr) (void)(ptr) /* disabled */ #else # if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) /* _mm_prefetch() is not defined outside of x86/x64 */ # include <mmintrin.h> /*
https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx
*/ -# define PREFETCH(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T1) +# define PREFETCH_L1(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0) +# define PREFETCH_L2(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T1) +# elif defined(__aarch64__) +# define PREFETCH_L1(ptr) __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr))) +# define PREFETCH_L2(ptr) __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr))) # elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) ) -# define PREFETCH(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */) +# define PREFETCH_L1(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */) +# define PREFETCH_L2(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */) # else -# define PREFETCH(ptr) (void)(ptr) /* disabled */ +# define PREFETCH_L1(ptr) (void)(ptr) /* disabled */ +# define PREFETCH_L2(ptr) (void)(ptr) /* disabled */ # endif #endif /* NO_PREFETCH */ @@ -116,10 +133,35 @@ size_t const _size = (size_t)(s); \ size_t _pos; \ for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) { \ - PREFETCH(_ptr + _pos); \ + PREFETCH_L2(_ptr + _pos); \ } \ } +/* vectorization + * older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax */ +#if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__) +# if (__GNUC__ == 4 && __GNUC_MINOR__ > 3) || (__GNUC__ >= 5) +# define DONT_VECTORIZE __attribute__((optimize("no-tree-vectorize"))) +# else +# define DONT_VECTORIZE _Pragma("GCC optimize(\"no-tree-vectorize\")") +# endif +#else +# define DONT_VECTORIZE +#endif + +/* Tell the compiler that a branch is likely or unlikely. + * Only use these macros if it causes the compiler to generate better code. + * If you can remove a LIKELY/UNLIKELY annotation without speed changes in gcc + * and clang, please do. + */ +#if defined(__GNUC__) +#define LIKELY(x) (__builtin_expect((x), 1)) +#define UNLIKELY(x) (__builtin_expect((x), 0)) +#else +#define LIKELY(x) (x) +#define UNLIKELY(x) (x) +#endif + /* disable warnings */ #ifdef _MSC_VER /* Visual Studio */ # include <intrin.h> /* For Visual 2005 */ diff --git a/drivers/filesystems/btrfs/zstd/cpu.h b/drivers/filesystems/btrfs/zstd/cpu.h index eeb428ad5f6..6e8a974f62d 100644 --- a/drivers/filesystems/btrfs/zstd/cpu.h +++ b/drivers/filesystems/btrfs/zstd/cpu.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) 2018-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -78,7 +78,7 @@ MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) { __asm__( "pushl %%ebx\n\t" "cpuid\n\t" - "movl %%ebx, %%eax\n\r" + "movl %%ebx, %%eax\n\t" "popl %%ebx" : "=a"(f7b), "=c"(f7c) : "a"(7), "c"(0) diff --git a/drivers/filesystems/btrfs/zstd/debug.h b/drivers/filesystems/btrfs/zstd/debug.h index 0c04ad2cc98..ac6224888d8 100644 --- a/drivers/filesystems/btrfs/zstd/debug.h +++ b/drivers/filesystems/btrfs/zstd/debug.h @@ -1,35 +1,15 @@ /* ****************************************************************** - debug - Part of FSE library - Copyright (C) 2013-present, Yann Collet. - - BSD 2-Clause License (
http://www.opensource.org/licenses/bsd-license.php
) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - Source repository :
https://github.com/Cyan4973/FiniteStateEntropy
+ * debug + * Part of FSE library + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - Source repository :
https://github.com/Cyan4973/FiniteStateEntropy
+ * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ @@ -57,9 +37,9 @@ extern "C" { #endif -/* static assert is triggered at compile time, leaving no runtime artefact, - * but can only work with compile-time constants. - * This variant can only be used inside a function. */ +/* static assert is triggered at compile time, leaving no runtime artefact. + * static assert only works with compile-time constants. + * Also, this variant can only be used inside a function. */ #define DEBUG_STATIC_ASSERT(c) (void)sizeof(char[(c) ? 1 : -1]) @@ -70,9 +50,19 @@ extern "C" { # define DEBUGLEVEL 0 #endif + +/* DEBUGFILE can be defined externally, + * typically through compiler command line. + * note : currently useless. + * Value must be stderr or stdout */ +#ifndef DEBUGFILE +# define DEBUGFILE stderr +#endif + + /* recommended values for DEBUGLEVEL : - * 0 : no debug, all run-time functions disabled - * 1 : no display, enables assert() only + * 0 : release mode, no debug, all run-time checks disabled + * 1 : enables assert() only, no display * 2 : reserved, for currently active debug path * 3 : events once per object lifetime (CCtx, CDict, etc.) * 4 : events once per frame @@ -81,7 +71,7 @@ extern "C" { * 7+: events at every position (*very* verbose) * * It's generally inconvenient to output traces > 5. - * In which case, it's possible to selectively enable higher verbosity levels + * In which case, it's possible to selectively trigger high verbosity levels * by modifying g_debug_level. */ @@ -95,11 +85,12 @@ extern "C" { #if (DEBUGLEVEL>=2) # include <stdio.h> -extern int g_debuglevel; /* here, this variable is only declared, - it actually lives in debug.c, - and is shared by the whole process. - It's typically used to enable very verbose levels - on selective conditions (such as position in src) */ +extern int g_debuglevel; /* the variable is only declared, + it actually lives in debug.c, + and is shared by the whole process. + It's not thread-safe. + It's useful when enabling very verbose levels + on selective conditions (such as position in src) */ # define RAWLOG(l, ...) { \ if (l<=g_debuglevel) { \ diff --git a/drivers/filesystems/btrfs/zstd/entropy_common.c b/drivers/filesystems/btrfs/zstd/entropy_common.c index b12944e1de9..9d3e4e8e36a 100644 --- a/drivers/filesystems/btrfs/zstd/entropy_common.c +++ b/drivers/filesystems/btrfs/zstd/entropy_common.c @@ -1,36 +1,16 @@ -/* - Common functions of New Generation Entropy library - Copyright (C) 2016, Yann Collet. - - BSD 2-Clause License (
http://www.opensource.org/licenses/bsd-license.php
) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE+HUF source repository :
https://github.com/Cyan4973/FiniteStateEntropy
- - Public forum :
https://groups.google.com/forum/#!forum/lz4c
-*************************************************************************** */ +/* ****************************************************************** + * Common functions of New Generation Entropy library + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - FSE+HUF source repository :
https://github.com/Cyan4973/FiniteStateEntropy
+ * - Public forum :
https://groups.google.com/forum/#!forum/lz4c
+ * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. +****************************************************************** */ /* ************************************* * Dependencies diff --git a/drivers/filesystems/btrfs/zstd/error_private.c b/drivers/filesystems/btrfs/zstd/error_private.c index d004ee636c6..cd437529c12 100644 --- a/drivers/filesystems/btrfs/zstd/error_private.c +++ b/drivers/filesystems/btrfs/zstd/error_private.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -14,6 +14,10 @@ const char* ERR_getErrorString(ERR_enum code) { +#ifdef ZSTD_STRIP_ERROR_STRINGS + (void)code; + return "Error strings stripped"; +#else static const char* const notErrorCode = "Unspecified error code"; switch( code ) { @@ -39,10 +43,13 @@ const char* ERR_getErrorString(ERR_enum code) case PREFIX(dictionaryCreation_failed): return "Cannot create Dictionary from provided samples"; case PREFIX(dstSize_tooSmall): return "Destination buffer is too small"; case PREFIX(srcSize_wrong): return "Src size is incorrect"; + case PREFIX(dstBuffer_null): return "Operation on NULL destination buffer"; /* following error codes are not stable and may be removed or changed in a future version */ case PREFIX(frameIndex_tooLarge): return "Frame index is too large"; case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking"; + case PREFIX(dstBuffer_wrong): return "Destination buffer is wrong"; case PREFIX(maxCode): default: return notErrorCode; } +#endif } diff --git a/drivers/filesystems/btrfs/zstd/error_private.h b/drivers/filesystems/btrfs/zstd/error_private.h index 0d2fa7e34b0..982cf8e9fe6 100644 --- a/drivers/filesystems/btrfs/zstd/error_private.h +++ b/drivers/filesystems/btrfs/zstd/error_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -49,7 +49,7 @@ typedef ZSTD_ErrorCode ERR_enum; /*-**************************************** * Error codes handling ******************************************/ -#undef ERROR /* reported already defined on VS 2015 (Rich Geldreich) */ +#undef ERROR /* already defined on Visual Studio */ #define ERROR(name) ZSTD_ERROR(name) #define ZSTD_ERROR(name) ((size_t)-PREFIX(name)) @@ -57,6 +57,10 @@ ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); } ERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); } +/* check and forward error code */ +#define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e +#define CHECK_F(f) { CHECK_V_F(_var_err__, f); } + /*-**************************************** * Error Strings diff --git a/drivers/filesystems/btrfs/zstd/fse.h b/drivers/filesystems/btrfs/zstd/fse.h index a5a6b6d4db7..ff54e70ea75 100644 --- a/drivers/filesystems/btrfs/zstd/fse.h +++ b/drivers/filesystems/btrfs/zstd/fse.h @@ -1,35 +1,15 @@ /* ****************************************************************** - FSE : Finite State Entropy codec - Public Prototypes declaration - Copyright (C) 2013-2016, Yann Collet. - - BSD 2-Clause License (
http://www.opensource.org/licenses/bsd-license.php
) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - Source repository :
https://github.com/Cyan4973/FiniteStateEntropy
+ * FSE : Finite State Entropy codec + * Public Prototypes declaration + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - Source repository :
https://github.com/Cyan4973/FiniteStateEntropy
+ * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ #if defined (__cplusplus) @@ -308,7 +288,7 @@ If there is an error, the function will return an error code, which can be teste *******************************************/ /* FSE buffer bounds */ #define FSE_NCOUNTBOUND 512 -#define FSE_BLOCKBOUND(size) (size + (size>>7)) +#define FSE_BLOCKBOUND(size) (size + (size>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */) #define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ /* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */ @@ -358,7 +338,7 @@ size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size typedef enum { FSE_repeat_none, /**< Cannot use the previous table */ FSE_repeat_check, /**< Can use the previous table but it must be checked */ - FSE_repeat_valid /**< Can use the previous table and it is asumed to be valid */ + FSE_repeat_valid /**< Can use the previous table and it is assumed to be valid */ } FSE_repeat; /* ***************************************** @@ -512,7 +492,7 @@ MEM_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct) const U32 tableLog = MEM_read16(ptr); statePtr->value = (ptrdiff_t)1<<tableLog; statePtr->stateTable = u16ptr+2; - statePtr->symbolTT = ((const U32*)ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1)); + statePtr->symbolTT = ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1); statePtr->stateLog = tableLog; } @@ -531,7 +511,7 @@ MEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U3 } } -MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, U32 symbol) +MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, unsigned symbol) { FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol]; const U16* const stateTable = (const U16*)(statePtr->stateTable); diff --git a/drivers/filesystems/btrfs/zstd/fse_compress.c b/drivers/filesystems/btrfs/zstd/fse_compress.c index c84f1d87ec9..419ad23b090 100644 --- a/drivers/filesystems/btrfs/zstd/fse_compress.c +++ b/drivers/filesystems/btrfs/zstd/fse_compress.c @@ -1,35 +1,15 @@ /* ****************************************************************** - FSE : Finite State Entropy encoder - Copyright (C) 2013-present, Yann Collet. - - BSD 2-Clause License (
http://www.opensource.org/licenses/bsd-license.php
) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE source repository :
https://github.com/Cyan4973/FiniteStateEntropy
- - Public forum :
https://groups.google.com/forum/#!forum/lz4c
+ * FSE : Finite State Entropy encoder + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - FSE source repository :
https://github.com/Cyan4973/FiniteStateEntropy
+ * - Public forum :
https://groups.google.com/forum/#!forum/lz4c
+ * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ /* ************************************************************** @@ -118,7 +98,7 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct, /* symbol start positions */ { U32 u; cumul[0] = 0; - for (u=1; u<=maxSymbolValue+1; u++) { + for (u=1; u <= maxSymbolValue+1; u++) { if (normalizedCounter[u-1]==-1) { /* Low proba symbol */ cumul[u] = cumul[u-1] + 1; tableSymbol[highThreshold--] = (FSE_FUNCTION_TYPE)(u-1); @@ -132,9 +112,9 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct, { U32 position = 0; U32 symbol; for (symbol=0; symbol<=maxSymbolValue; symbol++) { - int nbOccurences; + int nbOccurrences; int const freq = normalizedCounter[symbol]; - for (nbOccurences=0; nbOccurences<freq; nbOccurences++) { + for (nbOccurrences=0; nbOccurrences<freq; nbOccurrences++) { tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol; position = (position + step) & tableMask; while (position > highThreshold) @@ -194,17 +174,8 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct, size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) { - FSE_FUNCTION_TYPE* tableSymbol = ExAllocatePoolWithTag(NonPagedPool, sizeof(FSE_FUNCTION_TYPE) * FSE_MAX_TABLESIZE, FSEC_ALLOC_TAG); - size_t ret; - - if (!tableSymbol) - return 0; - - ret = FSE_buildCTable_wksp(ct, normalizedCounter, maxSymbolValue, tableLog, tableSymbol, sizeof(FSE_FUNCTION_TYPE) * FSE_MAX_TABLESIZE); - - ExFreePool(tableSymbol); - - return ret; + FSE_FUNCTION_TYPE tableSymbol[FSE_MAX_TABLESIZE]; /* memset() is not necessary, even if static analyzer complain about it */ + return FSE_buildCTable_wksp(ct, normalizedCounter, maxSymbolValue, tableLog, tableSymbol, sizeof(tableSymbol)); } @@ -657,9 +628,6 @@ size_t FSE_compress_usingCTable (void* dst, size_t dstSize, size_t FSE_compressBound(size_t size) { return FSE_COMPRESSBOUND(size); } -#define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e -#define CHECK_F(f) { CHECK_V_F(_var_err__, f); } - /* FSE_compress_wksp() : * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`). * `wkspSize` size must be `(1<<tableLog)`. @@ -670,7 +638,7 @@ size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t src BYTE* op = ostart; BYTE* const oend = ostart + dstSize; - U32 count[FSE_MAX_SYMBOL_VALUE+1]; + unsigned count[FSE_MAX_SYMBOL_VALUE+1]; S16 norm[FSE_MAX_SYMBOL_VALUE+1]; FSE_CTable* CTable = (FSE_CTable*)workSpace; size_t const CTableSize = FSE_CTABLE_SIZE_U32(tableLog, maxSymbolValue); @@ -684,7 +652,7 @@ size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t src if (!tableLog) tableLog = FSE_DEFAULT_TABLELOG; /* Scan input and build symbol stats */ - { CHECK_V_F(maxCount, HIST_count_wksp(count, &maxSymbolValue, src, srcSize, (unsigned*)scratchBuffer) ); + { CHECK_V_F(maxCount, HIST_count_wksp(count, &maxSymbolValue, src, srcSize, scratchBuffer, scratchBufferSize) ); if (maxCount == srcSize) return 1; /* only a single symbol in src : rle */ if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */ if (maxCount < (srcSize >> 7)) return 0; /* Heuristic : not compressible enough */ @@ -718,24 +686,10 @@ typedef struct { size_t FSE_compress2 (void* dst, size_t dstCapacity, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog) { - fseWkspMax_t* scratchBuffer; - size_t ret; - - DEBUG_STATIC_ASSERT(sizeof(fseWkspMax_t) >= FSE_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)); /* compilation failures here means scratchBuffer is not large enough */ - - if (tableLog > FSE_MAX_TABLELOG) - return ERROR(tableLog_tooLarge); - - scratchBuffer = ExAllocatePoolWithTag(NonPagedPool, sizeof(fseWkspMax_t), FSEC_ALLOC_TAG); - - if (!scratchBuffer) - return 0; - - ret = FSE_compress_wksp(dst, dstCapacity, src, srcSize, maxSymbolValue, tableLog, scratchBuffer, sizeof(fseWkspMax_t)); - - ExFreePool(scratchBuffer); - - return ret; + fseWkspMax_t scratchBuffer; + DEBUG_STATIC_ASSERT(sizeof(scratchBuffer) >= FSE_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)); /* compilation failures here means scratchBuffer is not large enough */ + if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); + return FSE_compress_wksp(dst, dstCapacity, src, srcSize, maxSymbolValue, tableLog, &scratchBuffer, sizeof(scratchBuffer)); } size_t FSE_compress (void* dst, size_t dstCapacity, const void* src, size_t srcSize) diff --git a/drivers/filesystems/btrfs/zstd/fse_decompress.c b/drivers/filesystems/btrfs/zstd/fse_decompress.c index 987813eb97e..aabf08abc69 100644 --- a/drivers/filesystems/btrfs/zstd/fse_decompress.c +++ b/drivers/filesystems/btrfs/zstd/fse_decompress.c @@ -1,35 +1,15 @@ /* ****************************************************************** - FSE : Finite State Entropy decoder - Copyright (C) 2013-2015, Yann Collet. - - BSD 2-Clause License (
http://www.opensource.org/licenses/bsd-license.php
) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE source repository :
https://github.com/Cyan4973/FiniteStateEntropy
- - Public forum :
https://groups.google.com/forum/#!forum/lz4c
+ * FSE : Finite State Entropy decoder + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - FSE source repository :
https://github.com/Cyan4973/FiniteStateEntropy
+ * - Public forum :
https://groups.google.com/forum/#!forum/lz4c
+ * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ @@ -53,9 +33,6 @@ #define FSE_isError ERR_isError #define FSE_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) /* use only *after* variable declarations */ -/* check and forward error code */ -#define CHECK_F(f) { size_t const e = f; if (FSE_isError(e)) return e; } - /* ************************************************************** * Templates @@ -81,7 +58,6 @@ #define FSED_ALLOC_TAG 0x64455346 // "FSEd" - /* Function templates */ FSE_DTable* FSE_createDTable (unsigned tableLog) { @@ -289,7 +265,7 @@ size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size /* normal FSE decoding mode */ size_t const NCountLength = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize); if (FSE_isError(NCountLength)) return NCountLength; - //if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size; supposed to be already checked in NCountLength, only remaining case : NCountLength==cSrcSize */ + /* if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); */ /* too small input size; supposed to be already checked in NCountLength, only remaining case : NCountLength==cSrcSize */ if (tableLog > maxLog) return ERROR(tableLog_tooLarge); ip += NCountLength; cSrcSize -= NCountLength; diff --git a/drivers/filesystems/btrfs/zstd/hist.c b/drivers/filesystems/btrfs/zstd/hist.c index 714a27e8d07..c17b9725f0d 100644 --- a/drivers/filesystems/btrfs/zstd/hist.c +++ b/drivers/filesystems/btrfs/zstd/hist.c @@ -1,36 +1,16 @@ /* ****************************************************************** - hist : Histogram functions - part of Finite State Entropy project - Copyright (C) 2013-present, Yann Collet. - - BSD 2-Clause License (
http://www.opensource.org/licenses/bsd-license.php
) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE source repository :
https://github.com/Cyan4973/FiniteStateEntropy
- - Public forum :
https://groups.google.com/forum/#!forum/lz4c
+ * hist : Histogram functions + * part of Finite State Entropy project + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - FSE source repository :
https://github.com/Cyan4973/FiniteStateEntropy
+ * - Public forum :
https://groups.google.com/forum/#!forum/lz4c
+ * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ /* --- dependencies --- */ @@ -38,10 +18,7 @@ #include "debug.h" /* assert, DEBUGLOG */ #include "error_private.h" /* ERROR */ #include "hist.h" -#include <ntifs.h> -#include <ntddk.h> -#define HIST_ALLOC_TAG 0x54534948 // "HIST" /* --- Error management --- */ unsigned HIST_isError(size_t code) { return ERR_isError(code); } @@ -76,6 +53,7 @@ unsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr, return largestCount; } +typedef enum { trustInput, checkMaxSymbolValue } HIST_checkInput_e; /* HIST_count_parallel_wksp() : * store histogram into 4 intermediate tables, recombined at the end. @@ -88,8 +66,8 @@ unsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr, static size_t HIST_count_parallel_wksp( unsigned* count, unsigned* maxSymbolValuePtr, const void* source, size_t sourceSize, - unsigned checkMax, - unsigned* const workSpace) + HIST_checkInput_e check, + U32* const workSpace) { const BYTE* ip = (const BYTE*)source; const BYTE* const iend = ip+sourceSize; @@ -140,7 +118,7 @@ static size_t HIST_count_parallel_wksp( /* finish last symbols */ while (ip<iend) Counting1[*ip++]++; - if (checkMax) { /* verify stats will fit into destination table */ + if (check) { /* verify stats will fit into destination table */ U32 s; for (s=255; s>maxSymbolValue; s--) { Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s]; if (Counting1[s]) return ERROR(maxSymbolValue_tooSmall); @@ -160,48 +138,46 @@ static size_t HIST_count_parallel_wksp( /* HIST_countFast_wksp() : * Same as HIST_countFast(), but using an externally provided scratch buffer. - * `workSpace` size must be table of >= HIST_WKSP_SIZE_U32 unsigned */ + * `workSpace` is a writable buffer which must be 4-bytes aligned, + * `workSpaceSize` must be >= HIST_WKSP_SIZE + */ size_t HIST_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr, const void* source, size_t sourceSize, - unsigned* workSpace) + void* workSpace, size_t workSpaceSize) { if (sourceSize < 1500) /* heuristic threshold */ return HIST_count_simple(count, maxSymbolValuePtr, source, sourceSize); - return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, 0, workSpace); + if ((size_t)workSpace & 3) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ + if (workSpaceSize < HIST_WKSP_SIZE) return ERROR(workSpace_tooSmall); + return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, trustInput, (U32*)workSpace); } /* fast variant (unsafe : won't check if src contains values beyond count[] limit) */ size_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr, const void* source, size_t sourceSize) { - unsigned* tmpCounters = ExAllocatePoolWithTag(NonPagedPool, sizeof(unsigned) * HIST_WKSP_SIZE_U32, HIST_ALLOC_TAG); - size_t ret; - - if (!tmpCounters) - return 0; - - ret = HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, tmpCounters); - - ExFreePool(tmpCounters); - - return ret; + unsigned tmpCounters[HIST_WKSP_SIZE_U32]; + return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, tmpCounters, sizeof(tmpCounters)); } /* HIST_count_wksp() : * Same as HIST_count(), but using an externally provided scratch buffer. * `workSpace` size must be table of >= HIST_WKSP_SIZE_U32 unsigned */ size_t HIST_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr, - const void* source, size_t sourceSize, unsigned* workSpace) + const void* source, size_t sourceSize, + void* workSpace, size_t workSpaceSize) { + if ((size_t)workSpace & 3) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ + if (workSpaceSize < HIST_WKSP_SIZE) return ERROR(workSpace_tooSmall); if (*maxSymbolValuePtr < 255) - return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, 1, workSpace); + return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, checkMaxSymbolValue, (U32*)workSpace); *maxSymbolValuePtr = 255; - return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, workSpace); + return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, workSpace, workSpaceSize); } size_t HIST_count(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize) { unsigned tmpCounters[HIST_WKSP_SIZE_U32]; - return HIST_count_wksp(count, maxSymbolValuePtr, src, srcSize, tmpCounters); + return HIST_count_wksp(count, maxSymbolValuePtr, src, srcSize, tmpCounters, sizeof(tmpCounters)); } diff --git a/drivers/filesystems/btrfs/zstd/hist.h b/drivers/filesystems/btrfs/zstd/hist.h index 8b1991a90bd..77e3ec4fb19 100644 --- a/drivers/filesystems/btrfs/zstd/hist.h +++ b/drivers/filesystems/btrfs/zstd/hist.h @@ -1,36 +1,16 @@ /* ****************************************************************** - hist : Histogram functions - part of Finite State Entropy project - Copyright (C) 2013-present, Yann Collet. - - BSD 2-Clause License (
http://www.opensource.org/licenses/bsd-license.php
) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE source repository :
https://github.com/Cyan4973/FiniteStateEntropy
- - Public forum :
https://groups.google.com/forum/#!forum/lz4c
+ * hist : Histogram functions + * part of Finite State Entropy project + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - FSE source repository :
https://github.com/Cyan4973/FiniteStateEntropy
+ * - Public forum :
https://groups.google.com/forum/#!forum/lz4c
+ * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ /* --- dependencies --- */ @@ -41,11 +21,11 @@ /*! HIST_count(): * Provides the precise count of each byte within a table 'count'. - * 'count' is a table of unsigned int, of minimum size (*maxSymbolValuePtr+1). + * 'count' is a table of unsigned int, of minimum size (*maxSymbolValuePtr+1). * Updates *maxSymbolValuePtr with actual largest symbol value detected. - * @return : count of the most frequent symbol (which isn't identified). - * or an error code, which can be tested using HIST_isError(). - * note : if return == srcSize, there is only one symbol. + * @return : count of the most frequent symbol (which isn't identified). + * or an error code, which can be tested using HIST_isError(). + * note : if return == srcSize, there is only one symbol. */ size_t HIST_count(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize); @@ -56,14 +36,16 @@ unsigned HIST_isError(size_t code); /**< tells if a return value is an error co /* --- advanced histogram functions --- */ #define HIST_WKSP_SIZE_U32 1024 +#define HIST_WKSP_SIZE (HIST_WKSP_SIZE_U32 * sizeof(unsigned)) /** HIST_count_wksp() : * Same as HIST_count(), but using an externally provided scratch buffer. * Benefit is this function will use very little stack space. - * `workSpace` must be a table of unsigned of size >= HIST_WKSP_SIZE_U32 + * `workSpace` is a writable buffer which must be 4-bytes aligned, + * `workSpaceSize` must be >= HIST_WKSP_SIZE */ size_t HIST_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, - unsigned* workSpace); + void* workSpace, size_t workSpaceSize); /** HIST_countFast() : * same as HIST_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr. @@ -74,11 +56,12 @@ size_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr, /** HIST_countFast_wksp() : * Same as HIST_countFast(), but using an externally provided scratch buffer. - * `workSpace` must be a table of unsigned of size >= HIST_WKSP_SIZE_U32 + * `workSpace` is a writable buffer which must be 4-bytes aligned, + * `workSpaceSize` must be >= HIST_WKSP_SIZE */ size_t HIST_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, - unsigned* workSpace); + void* workSpace, size_t workSpaceSize); /*! HIST_count_simple() : * Same as HIST_countFast(), this function is unsafe, diff --git a/drivers/filesystems/btrfs/zstd/huf.h b/drivers/filesystems/btrfs/zstd/huf.h index dc84f7ab114..ef432685dac 100644 --- a/drivers/filesystems/btrfs/zstd/huf.h +++ b/drivers/filesystems/btrfs/zstd/huf.h @@ -1,35 +1,15 @@ /* ****************************************************************** - huff0 huffman codec, - part of Finite State Entropy library - Copyright (C) 2013-present, Yann Collet. - - BSD 2-Clause License (
http://www.opensource.org/licenses/bsd-license.php
) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - Source repository :
https://github.com/Cyan4973/FiniteStateEntropy
+ * huff0 huffman codec, + * part of Finite State Entropy library + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - Source repository :
https://github.com/Cyan4973/FiniteStateEntropy
+ * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ #if defined (__cplusplus) @@ -110,7 +90,7 @@ HUF_PUBLIC_API size_t HUF_compress2 (void* dst, size_t dstCapacity, /** HUF_compress4X_wksp() : * Same as HUF_compress2(), but uses externally allocated `workSpace`. * `workspace` must have minimum alignment of 4, and be at least as large as HUF_WORKSPACE_SIZE */ -#define HUF_WORKSPACE_SIZE (6 << 10) +#define HUF_WORKSPACE_SIZE ((6 << 10) + 256) #define HUF_WORKSPACE_SIZE_U32 (HUF_WORKSPACE_SIZE / sizeof(U32)) HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity, const void* src, size_t srcSize, @@ -163,21 +143,29 @@ HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity, /* static allocation of HUF's DTable */ typedef U32 HUF_DTable; #define HUF_DTABLE_SIZE(maxTableLog) (1 + (1<<(maxTableLog))) +#define HUF_CREATE_STATIC_DTABLEX1(DTable, maxTableLog) \ + HUF_DTable DTable[HUF_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1) * 0x01000001) } +#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \ + HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog) * 0x01000001) } /* **************************************** * Advanced decompression functions ******************************************/ size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */ +#ifndef HUF_FORCE_DECOMPRESS_X1 size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */ +#endif size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< decodes RLE and uncompressed */ size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< considers RLE and uncompressed as errors */ size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< considers RLE and uncompressed as errors */ size_t HUF_decompress4X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */ size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< single-symbol decoder */ +#ifndef HUF_FORCE_DECOMPRESS_X1 size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */ size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< double-symbols decoder */ +#endif /* **************************************** @@ -200,6 +188,8 @@ typedef struct HUF_CElt_s HUF_CElt; /* incomplete type */ size_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits); /* @return : maxNbBits; CTable and count can overlap. In which case, CTable will overwrite count content */ size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog); size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable); +size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue); +int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue); typedef enum { HUF_repeat_none, /**< Cannot use the previous table */ @@ -224,7 +214,7 @@ size_t HUF_compress4X_repeat(void* dst, size_t dstSize, #define HUF_CTABLE_WORKSPACE_SIZE_U32 (2*HUF_SYMBOLVALUE_MAX +1 +1) #define HUF_CTABLE_WORKSPACE_SIZE (HUF_CTABLE_WORKSPACE_SIZE_U32 * sizeof(unsigned)) size_t HUF_buildCTable_wksp (HUF_CElt* tree, - const U32* count, U32 maxSymbolValue, U32 maxNbBits, + const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize); /*! HUF_readStats() : @@ -238,7 +228,7 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, /** HUF_readCTable() : * Loading a CTable saved with HUF_writeCTable() */ -size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize); +size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned *hasZeroWeights); /** HUF_getNbBits() : * Read nbBits from CTable symbolTable, for symbol `symbolValue` presumed <= HUF_SYMBOLVALUE_MAX @@ -273,14 +263,22 @@ U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize); #define HUF_DECOMPRESS_WORKSPACE_SIZE (2 << 10) #define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32)) +#ifndef HUF_FORCE_DECOMPRESS_X2 size_t HUF_readDTableX1 (HUF_DTable* DTable, const void* src, size_t srcSize); size_t HUF_readDTableX1_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize); +#endif +#ifndef HUF_FORCE_DECOMPRESS_X1 size_t HUF_readDTableX2 (HUF_DTable* DTable, const void* src, size_t srcSize); size_t HUF_readDTableX2_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize); +#endif size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); +#ifndef HUF_FORCE_DECOMPRESS_X2 size_t HUF_decompress4X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); +#endif +#ifndef HUF_FORCE_DECOMPRESS_X1 size_t HUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); +#endif /* ====================== */ @@ -302,24 +300,36 @@ size_t HUF_compress1X_repeat(void* dst, size_t dstSize, HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2); size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */ +#ifndef HUF_FORCE_DECOMPRESS_X1 size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbol decoder */ +#endif size_t HUF_decompress1X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); size_t HUF_decompress1X_DCtx_wksp (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); +#ifndef HUF_FORCE_DECOMPRESS_X2 size_t HUF_decompress1X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */ size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< single-symbol decoder */ +#endif +#ifndef HUF_FORCE_DECOMPRESS_X1 size_t HUF_decompress1X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */ size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< double-symbols decoder */ +#endif size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); /**< automatic selection of sing or double symbol decoder, based on DTable */ +#ifndef HUF_FORCE_DECOMPRESS_X2 size_t HUF_decompress1X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); +#endif +#ifndef HUF_FORCE_DECOMPRESS_X1 size_t HUF_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); +#endif /* BMI2 variants. * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0. */ size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2); +#ifndef HUF_FORCE_DECOMPRESS_X2 size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2); +#endif size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2); size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2); diff --git a/drivers/filesystems/btrfs/zstd/huf_compress.c b/drivers/filesystems/btrfs/zstd/huf_compress.c index 1510fda2db9..4efffbb542a 100644 --- a/drivers/filesystems/btrfs/zstd/huf_compress.c +++ b/drivers/filesystems/btrfs/zstd/huf_compress.c @@ -1,35 +1,15 @@ /* ****************************************************************** - Huffman encoder, part of New Generation Entropy library - Copyright (C) 2013-2016, Yann Collet. - - BSD 2-Clause License (
http://www.opensource.org/licenses/bsd-license.php
) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE+HUF source repository :
https://github.com/Cyan4973/FiniteStateEntropy
- - Public forum :
https://groups.google.com/forum/#!forum/lz4c
+ * Huffman encoder, part of New Generation Entropy library + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - FSE+HUF source repository :
https://github.com/Cyan4973/FiniteStateEntropy
+ * - Public forum :
https://groups.google.com/forum/#!forum/lz4c
+ * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ /* ************************************************************** @@ -53,10 +33,6 @@ #define HUF_STATIC_LINKING_ONLY #include "huf.h" #include "error_private.h" -#include <ntifs.h> -#include <ntddk.h> - -#define HUFC_ALLOC_TAG 0x63465548 // "HUFc" /* ************************************************************** @@ -64,8 +40,6 @@ ****************************************************************/ #define HUF_isError ERR_isError #define HUF_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) /* use only *after* variable declarations */ -#define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e -#define CHECK_F(f) { CHECK_V_F(_var_err__, f); } /* ************************************************************** @@ -92,13 +66,13 @@ static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weight BYTE* op = ostart; BYTE* const oend = ostart + dstSize; - U32 maxSymbolValue = HUF_TABLELOG_MAX; + unsigned maxSymbolValue = HUF_TABLELOG_MAX; U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER; FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)]; BYTE scratchBuffer[1<<MAX_FSE_TABLELOG_FOR_HUFF_HEADER]; - U32 count[HUF_TABLELOG_MAX+1]; + unsigned count[HUF_TABLELOG_MAX+1]; S16 norm[HUF_TABLELOG_MAX+1]; /* init conditions */ @@ -114,18 +88,18 @@ static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weight CHECK_F( FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue) ); /* Write table description header */ - { CHECK_V_F(hSize, FSE_writeNCount(op, oend-op, norm, maxSymbolValue, tableLog) ); + { CHECK_V_F(hSize, FSE_writeNCount(op, (size_t)(oend-op), norm, maxSymbolValue, tableLog) ); op += hSize; } /* Compress */ CHECK_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, sizeof(scratchBuffer)) ); - { CHECK_V_F(cSize, FSE_compress_usingCTable(op, oend - op, weightTable, wtSize, CTable) ); + { CHECK_V_F(cSize, FSE_compress_usingCTable(op, (size_t)(oend - op), weightTable, wtSize, CTable) ); if (cSize == 0) return 0; /* not enough space for compressed data */ op += cSize; } - return op-ostart; + return (size_t)(op-ostart); } @@ -138,7 +112,7 @@ struct HUF_CElt_s { `CTable` : Huffman tree to save, using huf representation. @return : size of saved CTable */ size_t HUF_writeCTable (void* dst, size_t maxDstSize, - const HUF_CElt* CTable, U32 maxSymbolValue, U32 huffLog) + const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog) { BYTE bitsToWeight[HUF_TABLELOG_MAX + 1]; /* precomputed conversion table */ BYTE huffWeight[HUF_SYMBOLVALUE_MAX]; @@ -173,7 +147,7 @@ size_t HUF_writeCTable (void* dst, size_t maxDstSize, } -size_t HUF_readCTable (HUF_CElt* CTable, U32* maxSymbolValuePtr, const void* src, size_t srcSize) +size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned* hasZeroWeights) { BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; /* init not required, even though some static analyzer may complain */ U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */ @@ -196,9 +170,11 @@ size_t HUF_readCTable (HUF_CElt* CTable, U32* maxSymbolValuePtr, const void* src } } /* fill nbBits */ + *hasZeroWeights = 0; { U32 n; for (n=0; n<nbSymbols; n++) { const U32 w = huffWeight[n]; - CTable[n].nbBits = (BYTE)(tableLog + 1 - w); + *hasZeroWeights |= (w == 0); + CTable[n].nbBits = (BYTE)(tableLog + 1 - w) & -(w != 0); } } /* fill val */ @@ -244,7 +220,7 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) /* there are several too large elements (at least >= 2) */ { int totalCost = 0; const U32 baseCost = 1 << (largestBits - maxNbBits); - U32 n = lastNonNull; + int n = (int)lastNonNull; while (huffNode[n].nbBits > maxNbBits) { totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits)); @@ -259,22 +235,22 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) /* repay normalized cost */ { U32 const noSymbol = 0xF0F0F0F0; U32 rankLast[HUF_TABLELOG_MAX+2]; - int pos; /* Get pos of last (smallest) symbol per rank */ memset(rankLast, 0xF0, sizeof(rankLast)); { U32 currentNbBits = maxNbBits; + int pos; for (pos=n ; pos >= 0; pos--) { if (huffNode[pos].nbBits >= currentNbBits) continue; currentNbBits = huffNode[pos].nbBits; /* < maxNbBits */ - rankLast[maxNbBits-currentNbBits] = pos; + rankLast[maxNbBits-currentNbBits] = (U32)pos; } } while (totalCost > 0) { - U32 nBitsToDecrease = BIT_highbit32(totalCost) + 1; + U32 nBitsToDecrease = BIT_highbit32((U32)totalCost) + 1; for ( ; nBitsToDecrease > 1; nBitsToDecrease--) { - U32 highPos = rankLast[nBitsToDecrease]; - U32 lowPos = rankLast[nBitsToDecrease-1]; + U32 const highPos = rankLast[nBitsToDecrease]; + U32 const lowPos = rankLast[nBitsToDecrease-1]; if (highPos == noSymbol) continue; if (lowPos == noSymbol) break; { U32 const highTotal = huffNode[highPos].count; @@ -301,7 +277,8 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) if (rankLast[1] == noSymbol) { /* special case : no rank 1 symbol (using maxNbBits-1); let's create one from largest rank 0 (using maxNbBits) */ while (huffNode[n].nbBits == maxNbBits) n--; huffNode[n+1].nbBits--; - rankLast[1] = n+1; + assert(n >= 0); + rankLast[1] = (U32)(n+1); totalCost++; continue; } @@ -313,29 +290,36 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) return maxNbBits; } - typedef struct { U32 base; U32 current; } rankPos; -static void HUF_sort(nodeElt* huffNode, const U32* count, U32 maxSymbolValue) +typedef nodeElt huffNodeTable[HUF_CTABLE_WORKSPACE_SIZE_U32]; + +#define RANK_POSITION_TABLE_SIZE 32 + +typedef struct { + huffNodeTable huffNodeTbl; + rankPos rankPosition[RANK_POSITION_TABLE_SIZE]; +} HUF_buildCTable_wksp_tables; + +static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValue, rankPos* rankPosition) { - rankPos rank[32]; U32 n; - memset(rank, 0, sizeof(rank)); + memset(rankPosition, 0, sizeof(*rankPosition) * RANK_POSITION_TABLE_SIZE); for (n=0; n<=maxSymbolValue; n++) { U32 r = BIT_highbit32(count[n] + 1); - rank[r].base ++; + rankPosition[r].base ++; } - for (n=30; n>0; n--) rank[n-1].base += rank[n].base; - for (n=0; n<32; n++) rank[n].current = rank[n].base; + for (n=30; n>0; n--) rankPosition[n-1].base += rankPosition[n].base; + for (n=0; n<32; n++) rankPosition[n].current = rankPosition[n].base; for (n=0; n<=maxSymbolValue; n++) { U32 const c = count[n]; U32 const r = BIT_highbit32(c+1) + 1; - U32 pos = rank[r].current++; - while ((pos > rank[r].base) && (c > huffNode[pos-1].count)) { + U32 pos = rankPosition[r].current++; + while ((pos > rankPosition[r].base) && (c > huffNode[pos-1].count)) { huffNode[pos] = huffNode[pos-1]; pos--; } @@ -347,45 +331,48 @@ static void HUF_sort(nodeElt* huffNode, const U32* count, U32 maxSymbolValue) /** HUF_buildCTable_wksp() : * Same as HUF_buildCTable(), but using externally allocated scratch buffer. - * `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of HUF_CTABLE_WORKSPACE_SIZE_U32 unsigned. + * `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as sizeof(HUF_buildCTable_wksp_tables). */ #define STARTNODE (HUF_SYMBOLVALUE_MAX+1) -typedef nodeElt huffNodeTable[HUF_CTABLE_WORKSPACE_SIZE_U32]; -size_t HUF_buildCTable_wksp (HUF_CElt* tree, const U32* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize) + +size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize) { - nodeElt* const huffNode0 = (nodeElt*)workSpace; + HUF_buildCTable_wksp_tables* const wksp_tables = (HUF_buildCTable_wksp_tables*)workSpace; + nodeElt* const huffNode0 = wksp_tables->huffNodeTbl; nodeElt* const huffNode = huffNode0+1; - U32 n, nonNullRank; + int nonNullRank; int lowS, lowN; - U16 nodeNb = STARTNODE; - U32 nodeRoot; + int nodeNb = STARTNODE; + int n, nodeRoot; /* safety checks */ if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ - if (wkspSize < sizeof(huffNodeTable)) return ERROR(workSpace_tooSmall); + if (wkspSize < sizeof(HUF_buildCTable_wksp_tables)) + return ERROR(workSpace_tooSmall); if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT; - if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge); + if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) + return ERROR(maxSymbolValue_tooLarge); memset(huffNode0, 0, sizeof(huffNodeTable)); /* sort, decreasing order */ - HUF_sort(huffNode, count, maxSymbolValue); + HUF_sort(huffNode, count, maxSymbolValue, wksp_tables->rankPosition); /* init for parents */ - nonNullRank = maxSymbolValue; + nonNullRank = (int)maxSymbolValue; while(huffNode[nonNullRank].count == 0) nonNullRank--; lowS = nonNullRank; nodeRoot = nodeNb + lowS - 1; lowN = nodeNb; huffNode[nodeNb].count = huffNode[lowS].count + huffNode[lowS-1].count; - huffNode[lowS].parent = huffNode[lowS-1].parent = nodeNb; + huffNode[lowS].parent = huffNode[lowS-1].parent = (U16)nodeNb; nodeNb++; lowS-=2; for (n=nodeNb; n<=nodeRoot; n++) huffNode[n].count = (U32)(1U<<30); huffNode0[0].count = (U32)(1U<<31); /* fake entry, strong barrier */ /* create parents */ while (nodeNb <= nodeRoot) { - U32 n1 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; - U32 n2 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; + int const n1 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; + int const n2 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; huffNode[nodeNb].count = huffNode[n1].count + huffNode[n2].count; - huffNode[n1].parent = huffNode[n2].parent = nodeNb; + huffNode[n1].parent = huffNode[n2].parent = (U16)nodeNb; nodeNb++; } @@ -397,24 +384,25 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const U32* count, U32 maxSymbolValu huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1; /* enforce maxTableLog */ - maxNbBits = HUF_setMaxHeight(huffNode, nonNullRank, maxNbBits); + maxNbBits = HUF_setMaxHeight(huffNode, (U32)nonNullRank, maxNbBits); /* fill result into tree (val, nbBits) */ { U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0}; U16 valPerRank[HUF_TABLELOG_MAX+1] = {0}; + int const alphabetSize = (int)(maxSymbolValue + 1); if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC); /* check fit into table */ for (n=0; n<=nonNullRank; n++) nbPerRank[huffNode[n].nbBits]++; /* determine stating value per rank */ { U16 min = 0; - for (n=maxNbBits; n>0; n--) { + for (n=(int)maxNbBits; n>0; n--) { valPerRank[n] = min; /* get starting value within each rank */ min += nbPerRank[n]; min >>= 1; } } - for (n=0; n<=maxSymbolValue; n++) + for (n=0; n<alphabetSize; n++) tree[huffNode[n].byte].nbBits = huffNode[n].nbBits; /* push nbBits per symbol, symbol order */ - for (n=0; n<=maxSymbolValue; n++) + for (n=0; n<alphabetSize; n++) tree[n].val = valPerRank[tree[n].nbBits]++; /* assign value within rank, symbol order */ } @@ -425,22 +413,13 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const U32* count, U32 maxSymbolValu * @return : maxNbBits * Note : count is used before tree is written, so they can safely overlap */ -size_t HUF_buildCTable (HUF_CElt* tree, const U32* count, U32 maxSymbolValue, U32 maxNbBits) +size_t HUF_buildCTable (HUF_CElt* tree, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits) { - huffNodeTable* nodeTable = ExAllocatePoolWithTag(NonPagedPool, sizeof(huffNodeTable), HUFC_ALLOC_TAG); - size_t ret; - - if (!nodeTable) - return 0; - - ret = HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, nodeTable, sizeof(huffNodeTable)); - - ExFreePool(nodeTable); - - return ret; + HUF_buildCTable_wksp_tables workspace; + return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, &workspace, sizeof(workspace)); } -static size_t HUF_estimateCompressedSize(HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) +size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) { size_t nbBits = 0; int s; @@ -450,7 +429,7 @@ static size_t HUF_estimateCompressedSize(HUF_CElt* CTable, const unsigned* count return nbBits >> 3; } -static int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) { +int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) { int bad = 0; int s; for (s = 0; s <= (int)maxSymbolValue; ++s) { @@ -489,7 +468,7 @@ HUF_compress1X_usingCTable_internal_body(void* dst, size_t dstSize, /* init */ if (dstSize < 8) return 0; /* not enough space to compress */ - { size_t const initErr = BIT_initCStream(&bitC, op, oend-op); + { size_t const initErr = BIT_initCStream(&bitC, op, (size_t)(oend-op)); if (HUF_isError(initErr)) return 0; } n = srcSize & ~3; /* join to mod 4 */ @@ -586,7 +565,8 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize, if (srcSize < 12) return 0; /* no saving possible : too small input */ op += 6; /* jumpTable */ - { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, segmentSize, CTable, bmi2) ); + assert(op <= oend); + { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) ); if (cSize==0) return 0; assert(cSize <= 65535); MEM_writeLE16(ostart, (U16)cSize); @@ -594,7 +574,8 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize, } ip += segmentSize; - { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, segmentSize, CTable, bmi2) ); + assert(op <= oend); + { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) ); if (cSize==0) return 0; assert(cSize <= 65535); MEM_writeLE16(ostart+2, (U16)cSize); @@ -602,7 +583,8 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize, } ip += segmentSize; - { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, segmentSize, CTable, bmi2) ); + assert(op <= oend); + { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) ); if (cSize==0) return 0; assert(cSize <= 65535); MEM_writeLE16(ostart+4, (U16)cSize); @@ -610,12 +592,14 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize, } ip += segmentSize; - { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, iend-ip, CTable, bmi2) ); + assert(op <= oend); + assert(ip <= iend); + { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, (size_t)(iend-ip), CTable, bmi2) ); if (cSize==0) return 0; op += cSize; } - return op-ostart; + return (size_t)(op-ostart); } size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable) @@ -623,48 +607,52 @@ size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, si return HUF_compress4X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, /* bmi2 */ 0); } +typedef enum { HUF_singleStream, HUF_fourStreams } HUF_nbStreams_e; static size_t HUF_compressCTable_internal( BYTE* const ostart, BYTE* op, BYTE* const oend, const void* src, size_t srcSize, - unsigned singleStream, const HUF_CElt* CTable, const int bmi2) + HUF_nbStreams_e nbStreams, const HUF_CElt* CTable, const int bmi2) { - size_t const cSize = singleStream ? - HUF_compress1X_usingCTable_internal(op, oend - op, src, srcSize, CTable, bmi2) : - HUF_compress4X_usingCTable_internal(op, oend - op, src, srcSize, CTable, bmi2); + size_t const cSize = (nbStreams==HUF_singleStream) ? + HUF_compress1X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, bmi2) : + HUF_compress4X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, bmi2); if (HUF_isError(cSize)) { return cSize; } if (cSize==0) { return 0; } /* uncompressible */ op += cSize; /* check compressibility */ + assert(op >= ostart); if ((size_t)(op-ostart) >= srcSize-1) { return 0; } - return op-ostart; + return (size_t)(op-ostart); } typedef struct { - U32 count[HUF_SYMBOLVALUE_MAX + 1]; + unsigned count[HUF_SYMBOLVALUE_MAX + 1]; HUF_CElt CTable[HUF_SYMBOLVALUE_MAX + 1]; - huffNodeTable nodeTable; + HUF_buildCTable_wksp_tables buildCTable_wksp; } HUF_compress_tables_t; /* HUF_compress_internal() : * `workSpace` must a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */ -static size_t HUF_compress_internal ( - void* dst, size_t dstSize, - const void* src, size_t srcSize, - unsigned maxSymbolValue, unsigned huffLog, - unsigned singleStream, - void* workSpace, size_t wkspSize, - HUF_CElt* oldHufTable, HUF_repeat* repeat, int preferRepeat, - const int bmi2) +static size_t +HUF_compress_internal (void* dst, size_t dstSize, + const void* src, size_t srcSize, + unsigned maxSymbolValue, unsigned huffLog, + HUF_nbStreams_e nbStreams, + void* workSpace, size_t wkspSize, + HUF_CElt* oldHufTable, HUF_repeat* repeat, int preferRepeat, + const int bmi2) { HUF_compress_tables_t* const table = (HUF_compress_tables_t*)workSpace; BYTE* const ostart = (BYTE*)dst; BYTE* const oend = ostart + dstSize; BYTE* op = ostart; + HUF_STATIC_ASSERT(sizeof(*table) <= HUF_WORKSPACE_SIZE); + /* checks & inits */ if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ - if (wkspSize < sizeof(*table)) return ERROR(workSpace_tooSmall); + if (wkspSize < HUF_WORKSPACE_SIZE) return ERROR(workSpace_tooSmall); if (!srcSize) return 0; /* Uncompressed */ if (!dstSize) return 0; /* cannot fit anything within dst budget */ if (srcSize > HUF_BLOCKSIZE_MAX) return ERROR(srcSize_wrong); /* current block size limit */ @@ -677,11 +665,11 @@ static size_t HUF_compress_internal ( if (preferRepeat && repeat && *repeat == HUF_repeat_valid) { return HUF_compressCTable_internal(ostart, op, oend, src, srcSize, - singleStream, oldHufTable, bmi2); + nbStreams, oldHufTable, bmi2); } /* Scan input and build symbol stats */ - { CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, table->count) ); + { CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, workSpace, wkspSize) ); if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; } /* single symbol, rle */ if (largest <= (srcSize >> 7)+4) return 0; /* heuristic : probably not compressible enough */ } @@ -696,14 +684,15 @@ static size_t HUF_compress_internal ( if (preferRepeat && repeat && *repeat != HUF_repeat_none) { return HUF_compressCTable_internal(ostart, op, oend, src, srcSize, - singleStream, oldHufTable, bmi2); + nbStreams, oldHufTable, bmi2); } /* Build Huffman Tree */ huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue); - { CHECK_V_F(maxBits, HUF_buildCTable_wksp(table->CTable, table->count, - maxSymbolValue, huffLog, - table->nodeTable, sizeof(table->nodeTable)) ); + { size_t const maxBits = HUF_buildCTable_wksp(table->CTable, table->count, + maxSymbolValue, huffLog, + &table->buildCTable_wksp, sizeof(table->buildCTable_wksp)); + CHECK_F(maxBits); huffLog = (U32)maxBits; /* Zero unused symbols in CTable, so we can check it for validity */ memset(table->CTable + (maxSymbolValue + 1), 0, @@ -719,7 +708,7 @@ static size_t HUF_compress_internal ( if (oldSize <= hSize + newSize || hSize + 12 >= srcSize) { return HUF_compressCTable_internal(ostart, op, oend, src, srcSize, - singleStream, oldHufTable, bmi2); + nbStreams, oldHufTable, bmi2); } } /* Use the new huffman table */ @@ -731,7 +720,7 @@ static size_t HUF_compress_internal ( } return HUF_compressCTable_internal(ostart, op, oend, src, srcSize, - singleStream, table->CTable, bmi2); + nbStreams, table->CTable, bmi2); } @@ -741,7 +730,7 @@ size_t HUF_compress1X_wksp (void* dst, size_t dstSize, void* workSpace, size_t wkspSize) { return HUF_compress_internal(dst, dstSize, src, srcSize, - maxSymbolValue, huffLog, 1 /*single stream*/, + maxSymbolValue, huffLog, HUF_singleStream, workSpace, wkspSize, NULL, NULL, 0, 0 /*bmi2*/); } @@ -753,7 +742,7 @@ size_t HUF_compress1X_repeat (void* dst, size_t dstSize, HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2) { return HUF_compress_internal(dst, dstSize, src, srcSize, - maxSymbolValue, huffLog, 1 /*single stream*/, + maxSymbolValue, huffLog, HUF_singleStream, workSpace, wkspSize, hufTable, repeat, preferRepeat, bmi2); } @@ -762,17 +751,8 @@ size_t HUF_compress1X (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned huffLog) { - unsigned* workSpace = ExAllocatePoolWithTag(NonPagedPool, sizeof(unsigned) * HUF_WORKSPACE_SIZE_U32, HUFC_ALLOC_TAG); - size_t ret; - - if (!workSpace) - return 0; - - ret = HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(unsigned) * HUF_WORKSPACE_SIZE_U32); - - ExFreePool(workSpace); - - return ret; + unsigned workSpace[HUF_WORKSPACE_SIZE_U32]; + return HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace)); } /* HUF_compress4X_repeat(): @@ -784,7 +764,7 @@ size_t HUF_compress4X_wksp (void* dst, size_t dstSize, void* workSpace, size_t wkspSize) { return HUF_compress_internal(dst, dstSize, src, srcSize, - maxSymbolValue, huffLog, 0 /*4 streams*/, + maxSymbolValue, huffLog, HUF_fourStreams, workSpace, wkspSize, NULL, NULL, 0, 0 /*bmi2*/); } @@ -799,7 +779,7 @@ size_t HUF_compress4X_repeat (void* dst, size_t dstSize, HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2) { return HUF_compress_internal(dst, dstSize, src, srcSize, - maxSymbolValue, huffLog, 0 /* 4 streams */, + maxSymbolValue, huffLog, HUF_fourStreams, workSpace, wkspSize, hufTable, repeat, preferRepeat, bmi2); } @@ -808,17 +788,8 @@ size_t HUF_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned huffLog) { - unsigned* workSpace = ExAllocatePoolWithTag(NonPagedPool, sizeof(unsigned) * HUF_WORKSPACE_SIZE_U32, HUFC_ALLOC_TAG); - size_t ret; - - if (!workSpace) - return 0; - - ret = HUF_compress4X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(unsigned) * HUF_WORKSPACE_SIZE_U32); - - ExFreePool(workSpace); - - return ret; + unsigned workSpace[HUF_WORKSPACE_SIZE_U32]; + return HUF_compress4X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace)); } size_t HUF_compress (void* dst, size_t maxDstSize, const void* src, size_t srcSize) diff --git a/drivers/filesystems/btrfs/zstd/huf_decompress.c b/drivers/filesystems/btrfs/zstd/huf_decompress.c index 51bb417f179..ab5db481c36 100644 --- a/drivers/filesystems/btrfs/zstd/huf_decompress.c +++ b/drivers/filesystems/btrfs/zstd/huf_decompress.c @@ -1,35 +1,15 @@ /* ****************************************************************** - huff0 huffman decoder, - part of Finite State Entropy library - Copyright (C) 2013-present, Yann Collet. - - BSD 2-Clause License (
http://www.opensource.org/licenses/bsd-license.php
) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ... 19742 lines suppressed ...
2 years, 7 months
1
0
0
0
[reactos] 01/10: [BTRFS][UBTRFS][SHELLBTRFS] Upgrade to 1.7.3 (#4417)
by Vincent Franchomme
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 ...
2 years, 7 months
1
0
0
0
[reactos] 01/01: [BROWSEUI_APITEST] Addendum to 7e22dc05.
by Hermès Bélusca-Maïto
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7ba5f703d2d52c6e78cfd…
commit 7ba5f703d2d52c6e78cfd37055d24e6c2ae98e4a Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> AuthorDate: Tue May 3 17:29:39 2022 +0200 Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> CommitDate: Tue May 3 17:29:39 2022 +0200 [BROWSEUI_APITEST] Addendum to 7e22dc05. --- modules/rostests/apitests/browseui/SHExplorerParseCmdLine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/rostests/apitests/browseui/SHExplorerParseCmdLine.c b/modules/rostests/apitests/browseui/SHExplorerParseCmdLine.c index c6a97bcb874..408d9574343 100644 --- a/modules/rostests/apitests/browseui/SHExplorerParseCmdLine.c +++ b/modules/rostests/apitests/browseui/SHExplorerParseCmdLine.c @@ -23,7 +23,7 @@ #define TEST_PATHA "C:\\SHExplorerParseCmdLine.test" #define TEST_PATHW WIDEN(TEST_PATHA) -typedef UINT_PTR (WINAPI * SHExplorerParseCmdLine_Type)(PEXPLORER_CMDLINE_PARSE_RESULTS); +typedef UINT_PTR (WINAPI *SHExplorerParseCmdLine_Type)(PEXPLORER_CMDLINE_PARSE_RESULTS); static SHExplorerParseCmdLine_Type pSHExplorerParseCmdLine; #define PIDL_IS_UNTOUCHED -1
2 years, 7 months
1
0
0
0
[reactos] 01/01: [BROWSEUI][BROWSEUI_APITEST] SHExplorerParseCmdLine(): Sync and improve (#3231)
by Serge Gautherie
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7e22dc05ca3c5ede81790…
commit 7e22dc05ca3c5ede8179053d0341c456e183efcc Author: Serge Gautherie <32623169+SergeGautherie(a)users.noreply.github.com> AuthorDate: Tue May 3 16:32:14 2022 +0200 Commit: GitHub <noreply(a)github.com> CommitDate: Tue May 3 16:32:14 2022 +0200 [BROWSEUI][BROWSEUI_APITEST] SHExplorerParseCmdLine(): Sync and improve (#3231) ROSTESTS-302 - SHCreateFromDesktop(): Sync declaration and spec. - SHExplorerParseCmdLine(): Sync declaration, header and spec. - SHExplorerParseCmdLine: Enforce 'UINT_PTR' return type. Addendum to e39876d and 0f8439a. - SHExplorerParseCmdLine: Replace '*EXPLORER_INFO' - SHExplorerParseCmdLine: Fix x64 support; Fix some results. --- dll/win32/browseui/browseui.spec | 4 +- dll/win32/browseui/desktopipc.cpp | 2 +- dll/win32/browseui/parsecmdline.cpp | 5 +- .../apitests/browseui/SHExplorerParseCmdLine.c | 140 +++++++++++---------- sdk/include/reactos/browseui_undoc.h | 15 ++- 5 files changed, 87 insertions(+), 79 deletions(-) diff --git a/dll/win32/browseui/browseui.spec b/dll/win32/browseui/browseui.spec index 64a561e89ff..23b1a69de24 100644 --- a/dll/win32/browseui/browseui.spec +++ b/dll/win32/browseui/browseui.spec @@ -3,8 +3,8 @@ 103 stdcall -noname SHOpenNewFrame(ptr ptr long long) @ stdcall -private DllCanUnloadNow() 105 stdcall -noname SHCreateSavedWindows() -106 stdcall -noname SHCreateFromDesktop(long) -107 stdcall -noname SHExplorerParseCmdLine(wstr) +106 stdcall -noname SHCreateFromDesktop(ptr) +107 stdcall -noname SHExplorerParseCmdLine(ptr) @ stdcall -private DllGetClassObject(ptr ptr ptr) @ stdcall -private DllGetVersion(ptr) @ stdcall -private DllInstall(long wstr) diff --git a/dll/win32/browseui/desktopipc.cpp b/dll/win32/browseui/desktopipc.cpp index fe5d5c2a8b8..ba5d168a2a3 100644 --- a/dll/win32/browseui/desktopipc.cpp +++ b/dll/win32/browseui/desktopipc.cpp @@ -609,7 +609,7 @@ extern "C" HRESULT WINAPI SHOpenNewFrame(LPITEMIDLIST pidl, IUnknown *paramC, lo * SHCreateFromDesktop [BROWSEUI.106] * parameter is a FolderInfo */ -BOOL WINAPI SHCreateFromDesktop(ExplorerCommandLineParseResults * parseResults) +BOOL WINAPI SHCreateFromDesktop(_In_ PEXPLORER_CMDLINE_PARSE_RESULTS parseResults) { TRACE("SHCreateFromDesktop\n"); diff --git a/dll/win32/browseui/parsecmdline.cpp b/dll/win32/browseui/parsecmdline.cpp index 4ea538a4b91..720b3084c5a 100644 --- a/dll/win32/browseui/parsecmdline.cpp +++ b/dll/win32/browseui/parsecmdline.cpp @@ -225,10 +225,11 @@ static LPITEMIDLIST _GetDocumentsPidl() /************************************************************************* * SHExplorerParseCmdLine [BROWSEUI.107] */ +// Returns FALSE, TRUE or an address. extern "C" UINT_PTR WINAPI -SHExplorerParseCmdLine(ExplorerCommandLineParseResults * pInfo) +SHExplorerParseCmdLine(_Out_ PEXPLORER_CMDLINE_PARSE_RESULTS pInfo) { WCHAR strField[MAX_PATH]; WCHAR strDir[MAX_PATH]; @@ -246,7 +247,7 @@ SHExplorerParseCmdLine(ExplorerCommandLineParseResults * pInfo) PathStripToRootW(strDir); pInfo->pidlPath = ILCreateFromPathW(strDir); } - return (LONG_PTR)(pInfo->pidlPath); + return (UINT_PTR)pInfo->pidlPath; } PCWSTR strNextArg = _FindFirstField(strFieldArray); diff --git a/modules/rostests/apitests/browseui/SHExplorerParseCmdLine.c b/modules/rostests/apitests/browseui/SHExplorerParseCmdLine.c index ea45c95d18f..c6a97bcb874 100644 --- a/modules/rostests/apitests/browseui/SHExplorerParseCmdLine.c +++ b/modules/rostests/apitests/browseui/SHExplorerParseCmdLine.c @@ -11,6 +11,7 @@ //#define UNICODE #include <strsafe.h> #include <shlobj.h> +#include <browseui_undoc.h> // Macro parameters are only expanded in the second nesting... #define _WIDEN(x) L##x @@ -22,21 +23,8 @@ #define TEST_PATHA "C:\\SHExplorerParseCmdLine.test" #define TEST_PATHW WIDEN(TEST_PATHA) -#define PADDING_SIZE 0x100 - -typedef struct _EXPLORER_INFO -{ - PWSTR FileName; - PIDLIST_ABSOLUTE pidl; - DWORD dwFlags; - ULONG Unknown1[5]; - PIDLIST_ABSOLUTE pidlRoot; - CLSID clsid; - GUID guidInproc; - ULONG Padding[PADDING_SIZE]; -} EXPLORER_INFO, *PEXPLORER_INFO; - -UINT_PTR (WINAPI *SHExplorerParseCmdLine)(_Out_ PEXPLORER_INFO Info); +typedef UINT_PTR (WINAPI * SHExplorerParseCmdLine_Type)(PEXPLORER_CMDLINE_PARSE_RESULTS); +static SHExplorerParseCmdLine_Type pSHExplorerParseCmdLine; #define PIDL_IS_UNTOUCHED -1 #define PIDL_IS_NULL -2 @@ -46,6 +34,7 @@ UINT_PTR (WINAPI *SHExplorerParseCmdLine)(_Out_ PEXPLORER_INFO Info); #define InvalidPointer ((PVOID)0x5555555555555555ULL) +static DWORD ReplaceSubstr( _Out_ PWCHAR OutputStr, _In_ DWORD OutputLen, @@ -81,7 +70,7 @@ static VOID TestCommandLine( _In_ ULONG TestLine, -_In_ INT ExpectedRet, +_In_ UINT_PTR ExpectedRet, _In_ INT ExpectedCsidl, _In_ DWORD ExpectedFlags, _In_ PCWSTR ExpectedFileName, @@ -89,46 +78,58 @@ _In_ PCWSTR PidlPath, _In_ PCWSTR pclsid, _Out_opt_ PUINT PWriteEnd) { - EXPLORER_INFO Info; + EXPLORER_CMDLINE_PARSE_RESULTS Info; UINT_PTR Ret; ULONG i; PDWORD InfoWords = (PDWORD) &Info; FillMemory(&Info, sizeof(Info), 0x55); Info.dwFlags = 0x00000000; - Ret = SHExplorerParseCmdLine(&Info); + Ret = pSHExplorerParseCmdLine(&Info); // Special case for empty cmdline: Ret is the PIDL for the selected folder. if (ExpectedRet == -1) - ok((LPITEMIDLIST) Ret == Info.pidl, "Line %lu: Ret = %x, expected %p\n", TestLine, Ret, Info.pidl); + { + ok(Ret == (UINT_PTR)Info.pidlPath, "Line %lu: Ret = %p, expected %p\n", TestLine, (PVOID)Ret, Info.pidlPath); + } else - ok(Ret == ExpectedRet, "Line %lu: Ret = %x, expected %08x\n", TestLine, Ret, ExpectedRet); + { + ok(Ret == ExpectedRet, "Line %lu: Ret = 0x%Ix, expected 0x%Ix\n", TestLine, Ret, ExpectedRet); + } if (ExpectedFileName == NULL) - ok(Info.FileName == InvalidPointer, "Line %lu: FileName = %p\n", TestLine, Info.FileName); + { + ok(Info.strPath == InvalidPointer, "Line %lu: strPath = %p\n", TestLine, Info.strPath); + } else { - ok(Info.FileName != NULL && Info.FileName != InvalidPointer, "Line %lu: FileName = %p\n", TestLine, Info.FileName); - if (Info.FileName != NULL && Info.FileName != InvalidPointer) + ok(Info.strPath != InvalidPointer, "Line %lu: strPath = InvalidPointer\n", TestLine); + ok(Info.strPath != NULL, "Line %lu: strPath = NULL\n", TestLine); + if (Info.strPath != NULL && Info.strPath != InvalidPointer) { - ok(!wcscmp(Info.FileName, ExpectedFileName), "Line %lu: FileName = %ls, expected %ls\n", TestLine, Info.FileName, ExpectedFileName); - LocalFree(Info.FileName); + ok(!wcscmp(Info.strPath, ExpectedFileName), "Line %lu: strPath = %ls, expected %ls\n", TestLine, Info.strPath, ExpectedFileName); + LocalFree(Info.strPath); } } ok(Info.dwFlags == ExpectedFlags, "Line %lu: dwFlags = %08lx, expected %08lx\n", TestLine, Info.dwFlags, ExpectedFlags); if (ExpectedCsidl == PIDL_IS_UNTOUCHED) - ok(Info.pidl == InvalidPointer, "Line %lu: pidl = %p\n", TestLine, Info.pidl); + { + ok(Info.pidlPath == InvalidPointer, "Line %lu: pidlPath = %p\n", TestLine, Info.pidlPath); + } else if (ExpectedCsidl == PIDL_IS_NULL) - ok(Info.pidl == NULL, "Line %lu: pidl = %p\n", TestLine, Info.pidl); + { + ok(Info.pidlPath == NULL, "Line %lu: pidlPath = %p\n", TestLine, Info.pidlPath); + } else { PIDLIST_ABSOLUTE ExpectedPidl; HRESULT hr; - ok(Info.pidl != NULL, "Line %lu: pidl = %p\n", TestLine, Info.pidl); - if (Info.pidl != NULL && Info.pidl != InvalidPointer) + ok(Info.pidlPath != InvalidPointer, "Line %lu: pidlPath = InvalidPointer\n", TestLine); + ok(Info.pidlPath != NULL, "Line %lu: pidlPath = NULL\n", TestLine); + if (Info.pidlPath != NULL && Info.pidlPath != InvalidPointer) { WCHAR pidlPathName[MAX_PATH] = L""; WCHAR pidlPathTest[MAX_PATH] = L""; @@ -159,10 +160,7 @@ _Out_opt_ PUINT PWriteEnd) } } - if (Info.pidl != NULL && Info.pidl != (LPITEMIDLIST) 0x55555555) - { - SHGetPathFromIDListW(Info.pidl, pidlPathName); - } + SHGetPathFromIDListW(Info.pidlPath, pidlPathName); if (ExpectedCsidl == PIDL_PATH_EQUALS_PATH) { @@ -181,7 +179,7 @@ _Out_opt_ PUINT PWriteEnd) ok(ExpectedPidl != NULL, "Line %lu: SHSimpleIDListFromPath(%S) failed. pidlPathName=%S\n", TestLine, pidlPathTest, pidlPathName); if (SUCCEEDED(hr)) { - ok(ILIsEqual(Info.pidl, ExpectedPidl), "Line %lu: Unexpected pidl value %p; pidlPathName=%S pidlPathTest=%S\n", TestLine, Info.pidl, pidlPathName, pidlPathTest); + ok(ILIsEqual(Info.pidlPath, ExpectedPidl), "Line %lu: Unexpected pidlPath value %p; pidlPathName=%S pidlPathTest=%S\n", TestLine, Info.pidlPath, pidlPathName, pidlPathTest); ILFree(ExpectedPidl); } } @@ -191,34 +189,40 @@ _Out_opt_ PUINT PWriteEnd) ok(hr == S_OK, "Line %lu: SHGetFolderLocation returned %08lx\n", TestLine, hr); if (SUCCEEDED(hr)) { - BOOL eq = ILIsEqual(Info.pidl, ExpectedPidl); + BOOL eq = ILIsEqual(Info.pidlPath, ExpectedPidl); ILFree(ExpectedPidl); - ok(eq, "Line %lu: Unexpected pidl value %p; pidlPathName=%S CSIDL=%d\n", TestLine, Info.pidl, pidlPathName, ExpectedCsidl); + ok(eq, "Line %lu: Unexpected pidlPath value %p; pidlPathName=%S CSIDL=%d\n", TestLine, Info.pidlPath, pidlPathName, ExpectedCsidl); } } } - if (Info.pidl != NULL && Info.pidl != (LPITEMIDLIST) 0x55555555) - ILFree(Info.pidl); + ILFree(Info.pidlPath); } } for (i = 0; i < sizeof(Info) / sizeof(DWORD); i++) { - switch (i*4) + switch (i * sizeof(DWORD)) { - case 0x00: // FileName - case 0x04: // pidl - case 0x08: // dwFlags - case 0x20: // pidlRoot - case 0x34: // guidInproc (1/4) - case 0x38: // guidInproc (2/4) - case 0x3C: // guidInproc (3/4) - case 0x40: // guidInproc (4/4) - break; - default: - ok(InfoWords[i] == 0x55555555, "Line %lu: Word 0x%02lx has been set to 0x%08lx\n", TestLine, i * 4, InfoWords[i]); + case FIELD_OFFSET(EXPLORER_CMDLINE_PARSE_RESULTS, strPath): + case FIELD_OFFSET(EXPLORER_CMDLINE_PARSE_RESULTS, pidlPath): + case FIELD_OFFSET(EXPLORER_CMDLINE_PARSE_RESULTS, dwFlags): + // TODO: 'case FIELD_OFFSET(EXPLORER_CMDLINE_PARSE_RESULTS, nCmdShow):'? + case FIELD_OFFSET(EXPLORER_CMDLINE_PARSE_RESULTS, pidlRoot): + // TODO: 'case FIELD_OFFSET(EXPLORER_CMDLINE_PARSE_RESULTS, clsid):'? + case FIELD_OFFSET(EXPLORER_CMDLINE_PARSE_RESULTS, guidInproc) + (0 * sizeof(DWORD)): + case FIELD_OFFSET(EXPLORER_CMDLINE_PARSE_RESULTS, guidInproc) + (1 * sizeof(DWORD)): + case FIELD_OFFSET(EXPLORER_CMDLINE_PARSE_RESULTS, guidInproc) + (2 * sizeof(DWORD)): + case FIELD_OFFSET(EXPLORER_CMDLINE_PARSE_RESULTS, guidInproc) + (3 * sizeof(DWORD)): +#ifdef _WIN64 + case FIELD_OFFSET(EXPLORER_CMDLINE_PARSE_RESULTS, strPath) + sizeof(DWORD): + case FIELD_OFFSET(EXPLORER_CMDLINE_PARSE_RESULTS, pidlPath) + sizeof(DWORD): + case FIELD_OFFSET(EXPLORER_CMDLINE_PARSE_RESULTS, pidlRoot) + sizeof(DWORD): +#endif + break; + default: + ok(InfoWords[i] == 0x55555555, "Line %lu: Word 0x%02lx has been set to 0x%08lx\n", TestLine, i * sizeof(DWORD), InfoWords[i]); } } @@ -262,7 +266,7 @@ START_TEST(SHExplorerParseCmdLine) { INT TestLine; PCWSTR CommandLine; - INT ExpectedRet; + UINT_PTR ExpectedRet; INT ExpectedCsidl; DWORD ExpectedFlags; PCWSTR ExpectedFileName; @@ -309,17 +313,17 @@ START_TEST(SHExplorerParseCmdLine) { __LINE__, L"\"c:\\\" program files", TRUE, PIDL_IS_NULL, 0x02000000, L"c:\\ program files"}, { __LINE__, L"\"c:\\\", \"c:\\program files\"", TRUE, PIDL_IS_PATH, 0x00000200, NULL, L"C:\\Program Files" }, { __LINE__, L"c:\\,c:\\program files", TRUE, PIDL_IS_PATH, 0x00000200, NULL, L"C:\\Program Files" }, - { __LINE__, L"/root", 0, CSIDL_MYDOCUMENTS, 0x00000000}, - { __LINE__, L"\"/root\"", 0, CSIDL_MYDOCUMENTS, 0x00000000}, - { __LINE__, L"/root,", TRUE, CSIDL_MYDOCUMENTS, 0x00000000}, - { __LINE__, L"/root,c", TRUE, CSIDL_MYDOCUMENTS, 0x00000000}, - { __LINE__, L"/root,\"\"", TRUE, CSIDL_MYDOCUMENTS, 0x00000000}, - { __LINE__, L"/root,wrong", TRUE, CSIDL_MYDOCUMENTS, 0x00000000}, - { __LINE__, L"/root,0", TRUE, CSIDL_MYDOCUMENTS, 0x00000000}, + { __LINE__, L"/root", FALSE, PIDL_IS_UNTOUCHED, 0x00000000 }, + { __LINE__, L"\"/root\"", FALSE, PIDL_IS_UNTOUCHED, 0x00000000 }, + { __LINE__, L"/root,", TRUE, PIDL_IS_UNTOUCHED, 0x00000000 }, + { __LINE__, L"/root,c", TRUE, PIDL_IS_UNTOUCHED, 0x00000000 }, + { __LINE__, L"/root,\"\"", TRUE, PIDL_IS_UNTOUCHED, 0x00000000 }, + { __LINE__, L"/root,wrong", TRUE, PIDL_IS_UNTOUCHED, 0x00000000 }, + { __LINE__, L"/root,0", TRUE, PIDL_IS_UNTOUCHED, 0x00000000 }, { __LINE__, L"/root,c:\\", TRUE, PIDL_PATH_EQUALS_PATH, 0x00000000, NULL, L"c:\\" }, { __LINE__, L"/root,\"c:\\\"", TRUE, PIDL_PATH_EQUALS_PATH, 0x00000000, NULL, L"c:\\" }, { __LINE__, L"/root \"c:\\\"", TRUE, PIDL_IS_NULL, 0x02000000, L"/root c:\\"}, - { __LINE__, L"/root,\"c:\\\"\"program files\"", TRUE, PIDL_IS_PATH, 0x00000000}, + { __LINE__, L"/root,\"c:\\\"\"program files\"", TRUE, PIDL_IS_UNTOUCHED, 0x00000000 }, { __LINE__, L"/root,\"c:\\\"program files", TRUE, PIDL_PATH_EQUALS_PATH, 0x00000000, NULL, L"c:\\Program Files" }, { __LINE__, L"/root,c:\\,c:\\Program Files", TRUE, PIDL_IS_PATH, 0x00000200, NULL, L"C:\\Program Files" }, { __LINE__, L"/root,c:\\,Program Files", TRUE, PIDL_IS_NULL, 0x02000000, L"Program Files"}, @@ -328,7 +332,7 @@ START_TEST(SHExplorerParseCmdLine) // { __LINE__, L"a:\\,/root,c:\\", TRUE, PIDL_PATH_EQUALS_PATH, 0x00000200, NULL, L"c:\\" }, // { __LINE__, L"a:\\,/root,c", TRUE, PIDL_IS_PATH, 0x00000200, NULL, L"A:\\" }, { __LINE__, L"c:\\,/root,c", TRUE, PIDL_IS_PATH, 0x00000200, NULL, L"C:\\" }, - { __LINE__, L"/select", TRUE, CSIDL_MYDOCUMENTS, 0x00000040}, + { __LINE__, L"/select", TRUE, PIDL_IS_UNTOUCHED, 0x00000040 }, { __LINE__, L"/select,", TRUE, CSIDL_DRIVES, 0x00000240 }, { __LINE__, L"/select,c", TRUE, PIDL_IS_NULL, 0x02000040, L"c"}, { __LINE__, L"/select,0", TRUE, PIDL_IS_NULL, 0x02000040, L"0"}, @@ -345,7 +349,7 @@ START_TEST(SHExplorerParseCmdLine) // { __LINE__, L"a:\\,/select,c:\\", TRUE, PIDL_IS_PATH, 0x00000240, NULL, L"C:\\" }, { __LINE__, L"a:\\,/select,c", TRUE, PIDL_IS_NULL, 0x02000040, L"c"}, { __LINE__, L"c:\\,/select,c", TRUE, PIDL_IS_NULL, 0x02000240, L"c"}, - { __LINE__, L"/e", TRUE, CSIDL_MYDOCUMENTS, 0x00000008}, + { __LINE__, L"/e", TRUE, PIDL_IS_UNTOUCHED, 0x00000008 }, { __LINE__, L"/e,", TRUE, CSIDL_DRIVES, 0x00000208 }, { __LINE__, L"/e,\"", TRUE, CSIDL_DRIVES, 0x00000208 }, { __LINE__, L"/e,\"\"", TRUE, CSIDL_DRIVES, 0x00000208 }, @@ -365,7 +369,7 @@ START_TEST(SHExplorerParseCmdLine) { __LINE__, L"http:\\\\www.reactos.org", TRUE, PIDL_IS_NULL, 0x02000000, L"http:\\\\www.reactos.org"}, { __LINE__, L"/e,http:\\\\www.reactos.org", TRUE, PIDL_IS_NULL, 0x02000008, L"http:\\\\www.reactos.org"}, { __LINE__, L"/root,c:\\,http:\\\\www.reactos.org", TRUE, PIDL_IS_NULL, 0x02000000, L"http:\\\\www.reactos.org"}, - { __LINE__, L"/separate ", TRUE, CSIDL_MYDOCUMENTS, 0x00020000}, + { __LINE__, L"/separate ", TRUE, PIDL_IS_UNTOUCHED, 0x00020000 }, { __LINE__, L"/separate,c:\\ program files", TRUE, PIDL_IS_NULL, 0x02020000, L"c:\\ program files"}, { __LINE__, L"/separate, c:\\program files", TRUE, PIDL_IS_PATH, 0x00020200, NULL, L"C:\\Program Files" }, { __LINE__, L"/separate, c:\\program files ,/e", TRUE, PIDL_IS_PATH, 0x00020208, NULL, L"C:\\Program Files" }, @@ -411,10 +415,10 @@ START_TEST(SHExplorerParseCmdLine) { __LINE__, L"\"\"\"", TRUE, PIDL_IS_NULL, 0x02000000, L"\""}, { __LINE__, L"\"\"\"\"", TRUE, PIDL_IS_NULL, 0x02000000, L"\""}, { __LINE__, L"\"\"\"\"\"", TRUE, PIDL_IS_NULL, 0x02000000, L"\"\""}, - { __LINE__, L"/s", TRUE, CSIDL_MYDOCUMENTS, 0x00000002}, - { __LINE__, L"/noui", TRUE, CSIDL_MYDOCUMENTS, 0x00001000}, + { __LINE__, L"/s", TRUE, PIDL_IS_UNTOUCHED, 0x00000002 }, + { __LINE__, L"/noui", TRUE, PIDL_IS_UNTOUCHED, 0x00001000 }, { __LINE__, L"/idlist", TRUE, PIDL_IS_UNTOUCHED, 0x00000000}, - { __LINE__, L"-embedding", TRUE, CSIDL_MYDOCUMENTS, 0x00000080 }, + { __LINE__, L"-embedding", TRUE, PIDL_IS_UNTOUCHED, 0x00000080 }, { __LINE__, L"/inproc", FALSE, PIDL_IS_UNTOUCHED, 0x00000000 }, { __LINE__, L"/inproc,1", FALSE, PIDL_IS_UNTOUCHED, 0x00000000 }, { __LINE__, L"/inproc,a", FALSE, PIDL_IS_UNTOUCHED, 0x00000000 }, @@ -433,10 +437,10 @@ START_TEST(SHExplorerParseCmdLine) WCHAR winDir[MAX_PATH]; HMODULE browseui = LoadLibraryA("browseui.dll"); - SHExplorerParseCmdLine = (UINT_PTR (__stdcall *)(PEXPLORER_INFO))GetProcAddress(browseui, MAKEINTRESOURCEA(107)); - if (!SHExplorerParseCmdLine) + pSHExplorerParseCmdLine = (SHExplorerParseCmdLine_Type)GetProcAddress(browseui, MAKEINTRESOURCEA(107)); + if (!pSHExplorerParseCmdLine) { - skip("SHExplorerParseCmdLine not found, NT 6.0?\n"); + skip("SHExplorerParseCmdLine not found, as on NT6+\n"); return; } diff --git a/sdk/include/reactos/browseui_undoc.h b/sdk/include/reactos/browseui_undoc.h index e1017bd7d97..bc0b455588f 100644 --- a/sdk/include/reactos/browseui_undoc.h +++ b/sdk/include/reactos/browseui_undoc.h @@ -98,16 +98,19 @@ typedef struct IEThreadParamBlock typedef struct ExplorerCommandLineParseResults { LPWSTR strPath; + // TODO: PIDLIST_ABSOLUTE? LPITEMIDLIST pidlPath; DWORD dwFlags; int nCmdShow; - DWORD offset10; - DWORD offset14; - DWORD offset18; - DWORD offset1C; + DWORD offset10_18; + DWORD offset14_1C; + DWORD offset18_20; + DWORD offset1C_24; + // TODO: PIDLIST_ABSOLUTE? LPITEMIDLIST pidlRoot; CLSID clsid; GUID guidInproc; + // TODO: 'ULONG Padding[0x100];'? } EXPLORER_CMDLINE_PARSE_RESULTS, *PEXPLORER_CMDLINE_PARSE_RESULTS; #define SH_EXPLORER_CMDLINE_FLAG_ONE 0x00000001 @@ -143,8 +146,8 @@ typedef struct ExplorerCommandLineParseResults void WINAPI InitOCHostClass(long param8); long WINAPI SHOpenFolderWindow(PIE_THREAD_PARAM_BLOCK parameters); void WINAPI SHCreateSavedWindows(void); -BOOL WINAPI SHCreateFromDesktop(PEXPLORER_CMDLINE_PARSE_RESULTS parseResults); -UINT_PTR WINAPI SHExplorerParseCmdLine(PEXPLORER_CMDLINE_PARSE_RESULTS pParseResults); +BOOL WINAPI SHCreateFromDesktop(_In_ PEXPLORER_CMDLINE_PARSE_RESULTS parseResults); +UINT_PTR WINAPI SHExplorerParseCmdLine(_Out_ PEXPLORER_CMDLINE_PARSE_RESULTS pInfo); void WINAPI UEMRegisterNotify(long param8, long paramC); HRESULT WINAPI SHCreateBandForPidl(LPCITEMIDLIST param8, IUnknown *paramC, BOOL param10); HRESULT WINAPI SHPidlFromDataObject(IDataObject *param8, long *paramC, long param10, FILEDESCRIPTORW *param14);
2 years, 7 months
1
0
0
0
[reactos] 01/01: [NEWDEV] Stop update driver wizard from changing device class (#4480)
by Olaf Schmerse
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=25019525f821fb1786e77…
commit 25019525f821fb1786e77bab4b1e5531fef8c200 Author: Olaf Schmerse <olase23(a)yahoo.de> AuthorDate: Tue May 3 16:13:37 2022 +0200 Commit: GitHub <noreply(a)github.com> CommitDate: Tue May 3 16:13:37 2022 +0200 [NEWDEV] Stop update driver wizard from changing device class (#4480) CORE-18166 The update driver wizard should not change the device class by default, especially when there is already a class set. This is the case when the wizard gets called from the device manager. --- dll/win32/newdev/wizard.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/dll/win32/newdev/wizard.c b/dll/win32/newdev/wizard.c index 28e3053356b..7cdd4df3960 100644 --- a/dll/win32/newdev/wizard.c +++ b/dll/win32/newdev/wizard.c @@ -255,11 +255,13 @@ FindDriverProc( } else { - /* Update device configuration */ - SetFailedInstall(DevInstData->hDevInfo, - &DevInstData->devInfoData, - TRUE); - + if (!DevInstData->bUpdate) + { + /* Update device configuration */ + SetFailedInstall(DevInstData->hDevInfo, + &DevInstData->devInfoData, + TRUE); + } PostMessage(DevInstData->hDialog, WM_SEARCH_FINISHED, 0, 0); } return 0; @@ -518,9 +520,12 @@ WelcomeDlgProc( (WPARAM)TRUE, (LPARAM)0); - SetFailedInstall(DevInstData->hDevInfo, - &DevInstData->devInfoData, - TRUE); + if (!DevInstData->bUpdate) + { + SetFailedInstall(DevInstData->hDevInfo, + &DevInstData->devInfoData, + TRUE); + } break; }
2 years, 7 months
1
0
0
0
[reactos] 01/01: [DISKPART] Fixed Volume Number & Label Issue (#4471)
by Sahil Shahane
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3e6b2972a948bb62d7810…
commit 3e6b2972a948bb62d781095a48714938c13c1170 Author: Sahil Shahane <57249267+sahilbest999(a)users.noreply.github.com> AuthorDate: Tue May 3 19:36:02 2022 +0530 Commit: GitHub <noreply(a)github.com> CommitDate: Tue May 3 16:06:02 2022 +0200 [DISKPART] Fixed Volume Number & Label Issue (#4471) CORE-18138 - Made Volume label to output only 11 characters at max. - Made Volume numbering left-padded. --- base/system/diskpart/lang/en-US.rc | 2 +- base/system/diskpart/lang/pl-PL.rc | 2 +- base/system/diskpart/lang/pt-PT.rc | 2 +- base/system/diskpart/lang/ro-RO.rc | 2 +- base/system/diskpart/lang/ru-RU.rc | 2 +- base/system/diskpart/lang/sq-AL.rc | 2 +- base/system/diskpart/lang/tr-TR.rc | 2 +- base/system/diskpart/lang/zh-CN.rc | 2 +- base/system/diskpart/lang/zh-TW.rc | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/base/system/diskpart/lang/en-US.rc b/base/system/diskpart/lang/en-US.rc index 74903f7fe86..7729fa17897 100644 --- a/base/system/diskpart/lang/en-US.rc +++ b/base/system/diskpart/lang/en-US.rc @@ -51,7 +51,7 @@ BEGIN IDS_LIST_PARTITION_NO_DISK "\nThere is no disk to list partitions.\nPlease select a disk and try again.\n\n" IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label FS Type Size Status Info\n" IDS_LIST_VOLUME_LINE " ---------- --- ----------- ----- ---------- ------- ------- --------\n" - IDS_LIST_VOLUME_FORMAT " Volume %3lu %c %-11s %-5s %10u %4I64u %-2s\n" + IDS_LIST_VOLUME_FORMAT " Volume %-3lu %c %-11.11s %-5s %10u %4I64u %-2s\n" END /* RESCAN command string */ diff --git a/base/system/diskpart/lang/pl-PL.rc b/base/system/diskpart/lang/pl-PL.rc index eadb120b3f6..1f2ac08dcbb 100644 --- a/base/system/diskpart/lang/pl-PL.rc +++ b/base/system/diskpart/lang/pl-PL.rc @@ -51,7 +51,7 @@ BEGIN IDS_LIST_PARTITION_NO_DISK "\nNie wybrano dysku do wyświetlenia partycji.\nWybierz dysk i spróbuj ponownie.\n\n" IDS_LIST_VOLUME_HEAD " Wolumin ### Lit Etykieta FS Typ Rozmiar Stan Info\n" IDS_LIST_VOLUME_LINE " ----------- --- ----------- ----- ---------- ------- ------- --------\n" - IDS_LIST_VOLUME_FORMAT " Wolumin %3lu %c %-11s %-5s %10u %4I64u %-2s\n" + IDS_LIST_VOLUME_FORMAT " Wolumin %-3lu %c %-11.11s %-5s %10u %4I64u %-2s\n" END /* RESCAN command string */ diff --git a/base/system/diskpart/lang/pt-PT.rc b/base/system/diskpart/lang/pt-PT.rc index 5b72edf5949..9ebb2892010 100644 --- a/base/system/diskpart/lang/pt-PT.rc +++ b/base/system/diskpart/lang/pt-PT.rc @@ -53,7 +53,7 @@ BEGIN IDS_LIST_PARTITION_NO_DISK "\nSem discos para listar Partições.\nPor favor seleccione um disco e tente novamente.\n\n" IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label FS Type Size Status Info\n" IDS_LIST_VOLUME_LINE " ---------- --- ----------- ----- ---------- ------- ------- --------\n" - IDS_LIST_VOLUME_FORMAT " Volume %3lu %c %-11s %-5s %10u %4I64u %-2s\n" + IDS_LIST_VOLUME_FORMAT " Volume %-3lu %c %-11.11s %-5s %10u %4I64u %-2s\n" END /* RESCAN command string */ diff --git a/base/system/diskpart/lang/ro-RO.rc b/base/system/diskpart/lang/ro-RO.rc index a20e0bef12c..d4bc92c9a29 100644 --- a/base/system/diskpart/lang/ro-RO.rc +++ b/base/system/diskpart/lang/ro-RO.rc @@ -53,7 +53,7 @@ BEGIN IDS_LIST_PARTITION_NO_DISK "\nNu există niciun disc pentru a afișa partiții.\nSelectați un disc apoi reîncercați.\n\n" IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label FS Type Size Status Info\n" IDS_LIST_VOLUME_LINE " ---------- --- ----------- ----- ---------- ------- ------- --------\n" - IDS_LIST_VOLUME_FORMAT " Volume %3lu %c %-11s %-5s %10u %4I64u %-2s\n" + IDS_LIST_VOLUME_FORMAT " Volume %-3lu %c %-11.11s %-5s %10u %4I64u %-2s\n" END /* RESCAN command string */ diff --git a/base/system/diskpart/lang/ru-RU.rc b/base/system/diskpart/lang/ru-RU.rc index 31d7108d0e3..383f83d8051 100644 --- a/base/system/diskpart/lang/ru-RU.rc +++ b/base/system/diskpart/lang/ru-RU.rc @@ -53,7 +53,7 @@ BEGIN IDS_LIST_PARTITION_NO_DISK "\nДиск с разметкой элементов не выбран.\nУкажите диск и повторите попытку.\n\n" IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label FS Type Size Status Info\n" IDS_LIST_VOLUME_LINE " ---------- --- ----------- ----- ---------- ------- ------- --------\n" - IDS_LIST_VOLUME_FORMAT " Volume %3lu %c %-11s %-5s %10u %4I64u %-2s\n" + IDS_LIST_VOLUME_FORMAT " Volume %-3lu %c %-11.11s %-5s %10u %4I64u %-2s\n" END /* RESCAN command string */ diff --git a/base/system/diskpart/lang/sq-AL.rc b/base/system/diskpart/lang/sq-AL.rc index f646db5d868..86dcab4a0b4 100644 --- a/base/system/diskpart/lang/sq-AL.rc +++ b/base/system/diskpart/lang/sq-AL.rc @@ -55,7 +55,7 @@ BEGIN IDS_LIST_PARTITION_NO_DISK "\nThere is no disk to list partitions.\nPlease select a disk and try again.\n\n" IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label FS Type Size Status Info\n" IDS_LIST_VOLUME_LINE " ---------- --- ----------- ----- ---------- ------- ------- --------\n" - IDS_LIST_VOLUME_FORMAT " Volume %3lu %c %-11s %-5s %10u %4I64u %-2s\n" + IDS_LIST_VOLUME_FORMAT " Volume %-3lu %c %-11.11s %-5s %10u %4I64u %-2s\n" END /* RESCAN command string */ diff --git a/base/system/diskpart/lang/tr-TR.rc b/base/system/diskpart/lang/tr-TR.rc index e127fe49cd2..ced828b78c9 100644 --- a/base/system/diskpart/lang/tr-TR.rc +++ b/base/system/diskpart/lang/tr-TR.rc @@ -53,7 +53,7 @@ BEGIN IDS_LIST_PARTITION_NO_DISK "\nBölümleri listelemek için bir disk yok.\nLütfen bir disk seçiniz ve yeniden deneyiniz.\n\n" IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label FS Type Size Status Info\n" IDS_LIST_VOLUME_LINE " ---------- --- ----------- ----- ---------- ------- ------- --------\n" - IDS_LIST_VOLUME_FORMAT " Volume %3lu %c %-11s %-5s %10u %4I64u %-2s\n" + IDS_LIST_VOLUME_FORMAT " Volume %-3lu %c %-11.11s %-5s %10u %4I64u %-2s\n" END /* RESCAN command string */ diff --git a/base/system/diskpart/lang/zh-CN.rc b/base/system/diskpart/lang/zh-CN.rc index bf86aaa3d42..b6e12caf0ef 100644 --- a/base/system/diskpart/lang/zh-CN.rc +++ b/base/system/diskpart/lang/zh-CN.rc @@ -60,7 +60,7 @@ BEGIN IDS_LIST_PARTITION_NO_DISK "\n这里没有要列出分区的磁盘。\n请选择一个磁盘,再试一次。\n\n" IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label FS Type Size Status Info\n" IDS_LIST_VOLUME_LINE " ---------- --- ----------- ----- ---------- ------- ------- --------\n" - IDS_LIST_VOLUME_FORMAT " Volume %3lu %c %-11s %-5s %10u %4I64u %-2s\n" + IDS_LIST_VOLUME_FORMAT " Volume %-3lu %c %-11.11s %-5s %10u %4I64u %-2s\n" END /* RESCAN command string */ diff --git a/base/system/diskpart/lang/zh-TW.rc b/base/system/diskpart/lang/zh-TW.rc index b31db8129f3..eaf56a4f356 100644 --- a/base/system/diskpart/lang/zh-TW.rc +++ b/base/system/diskpart/lang/zh-TW.rc @@ -54,7 +54,7 @@ BEGIN IDS_LIST_PARTITION_NO_DISK "\n沒有可列出分區的磁碟。\n請選擇一個磁碟,再試一次。\n\n" IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label FS Type Size Status Info\n" IDS_LIST_VOLUME_LINE " ---------- --- ----------- ----- ---------- ------- ------- --------\n" - IDS_LIST_VOLUME_FORMAT " Volume %3lu %c %-11s %-5s %10u %4I64u %-2s\n" + IDS_LIST_VOLUME_FORMAT " Volume %-3lu %c %-11.11s %-5s %10u %4I64u %-2s\n" END /* RESCAN command string */
2 years, 7 months
1
0
0
0
[reactos] 01/01: [SHELL32] Show system control applet in taskbar (#4437)
by Raymond Czerny
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1461ca403f81cc419b501…
commit 1461ca403f81cc419b5011da5d7b5a1048e8e4ec Author: Raymond Czerny <102076097+RaymondCzerny(a)users.noreply.github.com> AuthorDate: Tue May 3 16:02:58 2022 +0200 Commit: GitHub <noreply(a)github.com> CommitDate: Tue May 3 16:02:58 2022 +0200 [SHELL32] Show system control applet in taskbar (#4437) Display the control panel applet in the taskbar to allow better navigation between programs. CORE-18137 This is proceeded by manipulating the window of the current instance of 'rundll32.exe': - Set title text - Set icon - Show window (minimal) - Engaging the corresponding button in the Taskbar. --- dll/win32/shell32/wine/control.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/dll/win32/shell32/wine/control.c b/dll/win32/shell32/wine/control.c index 385f985b0f3..6044b736fdb 100644 --- a/dll/win32/shell32/wine/control.c +++ b/dll/win32/shell32/wine/control.c @@ -29,6 +29,8 @@ #define NO_SHLWAPI_REG #include <shlwapi.h> #include <shellapi.h> +#define COBJMACROS +#include <shobjidl.h> #include <wine/debug.h> #include <strsafe.h> @@ -804,6 +806,43 @@ Control_EnumWinProc( } return TRUE; // continue enumeration } + +/** + * This function makes the system control applet accessible via the taskbar. + * + * @param applet + * Pointer of system control applet. + * + * @param index + * Number of applet in a system control library. + */ +static void +Control_ShowAppletInTaskbar(CPlApplet* applet, UINT index) +{ + ITaskbarList* pTaskbar = NULL; + + SetWindowTextW(applet->hWnd, applet->info[index].name); + SendMessageW(applet->hWnd, WM_SETICON, ICON_SMALL, (LPARAM)applet->info[index].icon); + + /* Add button to the taskbar */ + ShowWindow(applet->hWnd, SW_SHOWMINNOACTIVE); + + /* Activate the corresponding button in the taskbar */ + CoInitialize(NULL); + if (CoCreateInstance(&CLSID_TaskbarList, + NULL, CLSCTX_INPROC_SERVER, + &IID_ITaskbarList, + (LPVOID*)&pTaskbar) == S_OK) + { + if (ITaskbarList_HrInit(pTaskbar) == S_OK) + { + ITaskbarList_ActivateTab(pTaskbar, applet->hWnd); + } + ITaskbarList_Release(pTaskbar); + } + CoUninitialize(); +} + #endif /* __REACTOS__ */ static void Control_DoLaunch(CPanel* panel, HWND hWnd, LPCWSTR wszCmd) @@ -956,6 +995,7 @@ static void Control_DoLaunch(CPanel* panel, HWND hWnd, LPCWSTR wszCmd) { SetPropW(applet->hWnd, (LPTSTR)MAKEINTATOM(aCPLName), (HANDLE)MAKEINTATOM(aCPLPath)); SetPropW(applet->hWnd, (LPTSTR)MAKEINTATOM(aCPLFlags), UlongToHandle(sp + 1)); + Control_ShowAppletInTaskbar(applet, sp); #endif if (!applet->proc(applet->hWnd, CPL_STARTWPARMSW, sp, (LPARAM)extraPmts))
2 years, 7 months
1
0
0
0
← Newer
1
...
13
14
15
16
17
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Results per page:
10
25
50
100
200