- From b4a3d623216c511b8a9d089c7030d2741e96d158 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Thu, 21 Aug 2025 10:36:04 +0200
- Subject: [PATCH 1/2] cygwin,tests: Add "winoffloadcopyfile" tool to test
- offload data copy
- Add "winoffloadcopyfile" tool to test offload data copy
- (|FSCTL_OFFLOAD_READ|+|FSCTL_OFFLOAD_WRITE|).
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- cygwin/Makefile | 4 +
- cygwin/Makefile.install | 7 +
- tests/sparsefiles/multisparsefiletest.ksh | 36 ++-
- tests/winoffloadcopyfile/Makefile | 23 ++
- tests/winoffloadcopyfile/winoffloadcopyfile.c | 237 ++++++++++++++++++
- 5 files changed, 306 insertions(+), 1 deletion(-)
- create mode 100644 tests/winoffloadcopyfile/Makefile
- create mode 100644 tests/winoffloadcopyfile/winoffloadcopyfile.c
- diff --git a/cygwin/Makefile b/cygwin/Makefile
- index 4cff33b..6fbb7f0 100644
- --- a/cygwin/Makefile
- +++ b/cygwin/Makefile
- @@ -24,6 +24,7 @@ $(PROJECT_BASEDIR_DIR)/tests/ea/nfs_ea.exe \
- $(PROJECT_BASEDIR_DIR)/tests/winfsinfo1/winfsinfo.exe \
- $(PROJECT_BASEDIR_DIR)/tests/filemmaptests/qsortonmmapedfile1.exe \
- $(PROJECT_BASEDIR_DIR)/tests/winclonefile/winclonefile.exe \
- + $(PROJECT_BASEDIR_DIR)/tests/winoffloadcopyfile/winoffloadcopyfile.exe \
- $(PROJECT_BASEDIR_DIR)/tests/winsg/winsg.exe: build_testutils
- #
- @@ -70,6 +71,7 @@ build_testutils:
- (cd "$(PROJECT_BASEDIR_DIR)/tests/winfsinfo1" && make all)
- (cd "$(PROJECT_BASEDIR_DIR)/tests/filemmaptests" && make all)
- (cd "$(PROJECT_BASEDIR_DIR)/tests/winclonefile" && make all)
- + (cd "$(PROJECT_BASEDIR_DIR)/tests/winoffloadcopyfile" && make all)
- (cd "$(PROJECT_BASEDIR_DIR)/tests/winsg" && make all)
- build: build_32bit_release build_32bit_debug build_64bit_release build_64bit_debug build_arm_64bit_debug build_testutils
- @@ -106,6 +108,7 @@ clean:
- (cd "$(PROJECT_BASEDIR_DIR)/tests/winfsinfo1" && make clean)
- (cd "$(PROJECT_BASEDIR_DIR)/tests/filemmaptests" && make clean)
- (cd "$(PROJECT_BASEDIR_DIR)/tests/winclonefile" && make clean)
- + (cd "$(PROJECT_BASEDIR_DIR)/tests/winoffloadcopyfile" && make clean)
- (cd "$(PROJECT_BASEDIR_DIR)/tests/winsg" && make clean)
- installdest_util: \
- @@ -117,6 +120,7 @@ installdest_util: \
- $(PROJECT_BASEDIR_DIR)/tests/winfsinfo1/winfsinfo.exe \
- $(PROJECT_BASEDIR_DIR)/tests/filemmaptests/qsortonmmapedfile1.exe \
- $(PROJECT_BASEDIR_DIR)/tests/winclonefile/winclonefile.exe \
- + $(PROJECT_BASEDIR_DIR)/tests/winoffloadcopyfile/winoffloadcopyfile.exe \
- $(PROJECT_BASEDIR_DIR)/tests/winsg/winsg.exe \
- $(CYGWIN_MAKEFILE_DIR)/devel/msnfs41client.bash
- diff --git a/cygwin/Makefile.install b/cygwin/Makefile.install
- index c361190..2ad96b0 100644
- --- a/cygwin/Makefile.install
- +++ b/cygwin/Makefile.install
- @@ -119,6 +119,13 @@ installdest:
- else \
- (cd $(DESTDIR)/$(CYGWIN_BASEPATH)/bin/ && $(LINKEXE) winclonefile.i686.exe winclonefile.exe) \
- fi
- + cp "$(PROJECT_BASEDIR_DIR)/tests/winoffloadcopyfile/winoffloadcopyfile.x86_64.exe" $(DESTDIR)/$(CYGWIN_BASEPATH)/bin/winoffloadcopyfile.x86_64.exe
- + cp "$(PROJECT_BASEDIR_DIR)/tests/winoffloadcopyfile/winoffloadcopyfile.i686.exe" $(DESTDIR)/$(CYGWIN_BASEPATH)/bin/winoffloadcopyfile.i686.exe
- + if [[ "$(CYGWIN_BASEPATH)" == *64* ]] ; then \
- + (cd $(DESTDIR)/$(CYGWIN_BASEPATH)/bin/ && $(LINKEXE) winoffloadcopyfile.x86_64.exe winoffloadcopyfile.exe) \
- + else \
- + (cd $(DESTDIR)/$(CYGWIN_BASEPATH)/bin/ && $(LINKEXE) winoffloadcopyfile.i686.exe winoffloadcopyfile.exe) \
- + fi
- cp "$(PROJECT_BASEDIR_DIR)/tests/lssparse/lssparse.x86_64.exe" $(DESTDIR)/$(CYGWIN_BASEPATH)/bin/lssparse.x86_64.exe
- if [[ "$(CYGWIN_BASEPATH)" == *64* ]] ; then \
- (cd $(DESTDIR)/$(CYGWIN_BASEPATH)/bin/ && $(LINKEXE) lssparse.x86_64.exe lssparse.exe) \
- diff --git a/tests/sparsefiles/multisparsefiletest.ksh b/tests/sparsefiles/multisparsefiletest.ksh
- index b62f577..0d43585 100644
- --- a/tests/sparsefiles/multisparsefiletest.ksh
- +++ b/tests/sparsefiles/multisparsefiletest.ksh
- @@ -187,7 +187,9 @@ function multisparsefiletest1
- 'sparsefile2.bin' \
- 'sparsefile2_cpsparse.bin' \
- 'sparsefile2_cloned_full.bin' \
- - 'sparsefile2_cloned_1mbchunks.bin'
- + 'sparsefile2_cloned_1mbchunks.bin' \
- + 'sparsefile2_offloadcopy_full.bin' \
- + 'sparsefile2_offloadcopy_1mbchunks.bin'
- c.testlabel=''
- if (( c.i == 0 )) ; then
- @@ -230,6 +232,10 @@ function multisparsefiletest1
- 'cloned_1mbchunks_64bit'
- 'cloned_full_32bit'
- 'cloned_1mbchunks_32bit'
- + 'offloadcopy_full_64bit'
- + 'offloadcopy_1mbchunks_64bit'
- + 'offloadcopy_full_32bit'
- + 'offloadcopy_1mbchunks_32bit'
- )
- ;;
- '32')
- @@ -238,6 +244,8 @@ function multisparsefiletest1
- 'cp_sparseauto'
- 'cloned_full'
- 'cloned_1mbchunks'
- + 'offloadcopy_full'
- + 'offloadcopy_1mbchunks'
- )
- ;;
- *)
- @@ -251,8 +259,10 @@ function multisparsefiletest1
- if [[ "${tstmod}" == *32bit ]] ; then
- winclonefilecmd='winclonefile.i686.exe'
- + winoffloadcopyfilecmd='winoffloadcopyfile.i686.exe'
- else
- winclonefilecmd='winclonefile.exe'
- + winoffloadcopyfilecmd='winoffloadcopyfile.exe'
- fi
- case "${tstmod}" in
- @@ -286,6 +296,29 @@ function multisparsefiletest1
- continue
- fi
- ;;
- + 'offloadcopy_full' | 'offloadcopy_full_64bit' | 'offloadcopy_full_32bit')
- + if $test_cloning ; then
- + ${winoffloadcopyfilecmd} 'sparsefile2.bin' 'sparsefile2_offloadcopy_full.bin' 1>'/dev/null'
- + c.stdout="$(lssparse -H 'sparsefile2_offloadcopy_full.bin')"
- + else
- + printf "# Test '%s' SKIPPED\n" "${c.testlabel}/${tstmod}"
- + (( tests_skipped++ ))
- + continue
- + fi
- + ;;
- + 'offloadcopy_1mbchunks' | 'offloadcopy_1mbchunks_64bit' | 'offloadcopy_1mbchunks_32bit')
- + if $test_cloning ; then
- + ${winoffloadcopyfilecmd} \
- + --clonechunksize $((1024*1024)) \
- + 'sparsefile2.bin' \
- + 'sparsefile2_offloadcopy_1mbchunks.bin' 1>'/dev/null'
- + c.stdout="$(lssparse -H 'sparsefile2_offloadcopy_1mbchunks.bin')"
- + else
- + printf "# Test '%s' SKIPPED\n" "${c.testlabel}/${tstmod}"
- + (( tests_skipped++ ))
- + continue
- + fi
- + ;;
- *)
- print -u2 -f 'Unknown test mod\n'
- ;;
- @@ -330,6 +363,7 @@ builtin wc
- # - tests for sparse files >= 2GB, 4GB, 16GB
- #
- typeset test_cloning=false
- +typeset test_offloadcopy=true
- multisparsefiletest1
- diff --git a/tests/winoffloadcopyfile/Makefile b/tests/winoffloadcopyfile/Makefile
- new file mode 100644
- index 0000000..a429b44
- --- /dev/null
- +++ b/tests/winoffloadcopyfile/Makefile
- @@ -0,0 +1,23 @@
- +#
- +# Makefile for winoffloadcopyfile
- +#
- +
- +# POSIX Makefile
- +
- +all: winoffloadcopyfile.i686.exe winoffloadcopyfile.x86_64.exe winoffloadcopyfile.exe
- +
- +winoffloadcopyfile.i686.exe: winoffloadcopyfile.c
- + clang -target i686-pc-windows-gnu -std=gnu17 -Wall -Wextra -DUNICODE=1 -D_UNICODE=1 -I../../include -g winoffloadcopyfile.c -lntdll -o winoffloadcopyfile.i686.exe
- +
- +winoffloadcopyfile.x86_64.exe: winoffloadcopyfile.c
- + clang -target x86_64-pc-windows-gnu -std=gnu17 -Wall -Wextra -DUNICODE=1 -D_UNICODE=1 -I../../include -g winoffloadcopyfile.c -lntdll -o winoffloadcopyfile.x86_64.exe
- +
- +winoffloadcopyfile.exe: winoffloadcopyfile.x86_64.exe
- + ln -s winoffloadcopyfile.x86_64.exe winoffloadcopyfile.exe
- +
- +clean:
- + rm -fv \
- + winoffloadcopyfile.i686.exe \
- + winoffloadcopyfile.x86_64.exe \
- + winoffloadcopyfile.exe
- +# EOF.
- diff --git a/tests/winoffloadcopyfile/winoffloadcopyfile.c b/tests/winoffloadcopyfile/winoffloadcopyfile.c
- new file mode 100644
- index 0000000..021037b
- --- /dev/null
- +++ b/tests/winoffloadcopyfile/winoffloadcopyfile.c
- @@ -0,0 +1,237 @@
- +/*
- + * MIT License
- + *
- + * Copyright (c) 2025 Roland Mainz <roland.mainz@nrubsig.org>
- + *
- + * Permission is hereby granted, free of charge, to any person obtaining a copy
- + * of this software and associated documentation files (the "Software"), to deal
- + * in the Software without restriction, including without limitation the rights
- + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- + * copies of the Software, and to permit persons to whom the Software is
- + * furnished to do so, subject to the following conditions:
- + *
- + * The above copyright notice and this permission notice shall be included in
- + * all copies or substantial portions of the Software.
- + *
- + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- + * SOFTWARE.
- + */
- +
- +/*
- + * winoffloadcopyfile.c - clone a file
- + *
- + * Written by Roland Mainz <roland.mainz@nrubsig.org>
- + */
- +
- +#define WIN32_LEAN_AND_MEAN 1
- +
- +#include <windows.h>
- +#include <winioctl.h>
- +#include <stdio.h>
- +
- +#define EXIT_USAGE (2)
- +
- +#ifndef OFFLOAD_READ_FLAG_ALL_ZERO_BEYOND_CURRENT_RANGE
- +typedef struct _FSCTL_OFFLOAD_READ_INPUT {
- + DWORD Size;
- + DWORD Flags;
- + DWORD TokenTimeToLive;
- + DWORD Reserved;
- + DWORDLONG FileOffset;
- + DWORDLONG CopyLength;
- +} FSCTL_OFFLOAD_READ_INPUT, *PFSCTL_OFFLOAD_READ_INPUT;
- +
- +typedef struct _FSCTL_OFFLOAD_READ_OUTPUT {
- + DWORD Size;
- + DWORD Flags;
- + DWORDLONG TransferLength;
- + BYTE Token[512];
- +} FSCTL_OFFLOAD_READ_OUTPUT, *PFSCTL_OFFLOAD_READ_OUTPUT;
- +
- +#define OFFLOAD_READ_FLAG_ALL_ZERO_BEYOND_CURRENT_RANGE (1)
- +
- +typedef struct _FSCTL_OFFLOAD_WRITE_INPUT {
- + DWORD Size;
- + DWORD Flags;
- + DWORDLONG FileOffset;
- + DWORDLONG CopyLength;
- + DWORDLONG TransferOffset;
- + BYTE Token[512];
- +} FSCTL_OFFLOAD_WRITE_INPUT, *PFSCTL_OFFLOAD_WRITE_INPUT;
- +
- +typedef struct _FSCTL_OFFLOAD_WRITE_OUTPUT {
- + DWORD Size;
- + DWORD Flags;
- + DWORDLONG LengthWritten;
- +} FSCTL_OFFLOAD_WRITE_OUTPUT, *PFSCTL_OFFLOAD_WRITE_OUTPUT;
- +#endif /* OFFLOAD_READ_FLAG_ALL_ZERO_BEYOND_CURRENT_RANGE */
- +
- +#ifndef STORAGE_OFFLOAD_MAX_TOKEN_LENGTH
- +#define STORAGE_OFFLOAD_MAX_TOKEN_LENGTH (512)
- +#define STORAGE_OFFLOAD_TOKEN_ID_LENGTH (0x1F8)
- +#define STORAGE_OFFLOAD_TOKEN_TYPE_ZERO_DATA (0xFFFF0001)
- +
- +typedef struct _STORAGE_OFFLOAD_TOKEN {
- +
- + BYTE TokenType[4];
- + BYTE Reserved[2];
- + BYTE TokenIdLength[2];
- + union {
- + struct {
- + BYTE Reserved2[STORAGE_OFFLOAD_TOKEN_ID_LENGTH];
- + } StorageOffloadZeroDataToken;
- + BYTE Token[STORAGE_OFFLOAD_TOKEN_ID_LENGTH];
- + } DUMMYUNIONNAME;
- +} STORAGE_OFFLOAD_TOKEN, *PSTORAGE_OFFLOAD_TOKEN;
- +#endif /* STORAGE_OFFLOAD_MAX_TOKEN_LENGTH */
- +
- +int main(int argc, char* argv[])
- +{
- + int retval = EXIT_FAILURE;
- +
- + if (argc != 3) {
- + (void)fprintf(stderr,
- + "Usage: %s <source_file> <destination_file>\n",
- + argv[0]);
- + return EXIT_USAGE;
- + }
- +
- + const char *srcFilename = argv[1];
- + const char *destFilename = argv[2];
- + HANDLE hSrc = INVALID_HANDLE_VALUE;
- + HANDLE hDest = INVALID_HANDLE_VALUE;
- + BOOL bSuccess = FALSE;
- + DWORD ioctlBytesReturned = 0;
- +
- + BYTE tokenBuffer[STORAGE_OFFLOAD_MAX_TOKEN_LENGTH] = { 0 };
- + PSTORAGE_OFFLOAD_TOKEN pToken = (PSTORAGE_OFFLOAD_TOKEN)tokenBuffer;
- +
- + (void)printf("Attempting offloaded copy from '%s' to '%s'\n",
- + srcFilename,
- + destFilename);
- +
- + hSrc = CreateFileA(srcFilename,
- + GENERIC_READ,
- + FILE_SHARE_READ,
- + NULL,
- + OPEN_EXISTING,
- + FILE_ATTRIBUTE_NORMAL,
- + NULL);
- + if (hSrc == INVALID_HANDLE_VALUE) {
- + (void)fprintf(stderr,
- + "Cannot open src file, lasterr=%d\n",
- + (int)GetLastError());
- + goto cleanup;
- + }
- +
- + hDest = CreateFileA(destFilename,
- + GENERIC_ALL,
- + FILE_SHARE_DELETE|FILE_SHARE_WRITE,
- + NULL,
- + CREATE_ALWAYS,
- + FILE_ATTRIBUTE_NORMAL,
- + NULL);
- + if (hDest == INVALID_HANDLE_VALUE) {
- + (void)fprintf(stderr,
- + "Cannot open dst file, lasterr=%d\n",
- + (int)GetLastError());
- + goto cleanup;
- + }
- +
- + LARGE_INTEGER fileSize;
- + if (!GetFileSizeEx(hSrc, &fileSize)) {
- + (void)fprintf(stderr,
- + "Cannot src file size, lasterr=%d\n",
- + (int)GetLastError());
- + goto cleanup;
- + }
- +
- + FSCTL_OFFLOAD_READ_INPUT readInput = { 0 };
- + readInput.Size = sizeof(FSCTL_OFFLOAD_READ_INPUT);
- + readInput.FileOffset = 0;
- + readInput.CopyLength = fileSize.QuadPart;
- +
- + FSCTL_OFFLOAD_READ_OUTPUT readOutput = { 0 };
- + readOutput.Size = sizeof(FSCTL_OFFLOAD_READ_OUTPUT);
- +
- + bSuccess = DeviceIoControl(
- + hSrc,
- + FSCTL_OFFLOAD_READ,
- + &readInput,
- + sizeof(readInput),
- + &readOutput,
- + sizeof(readOutput),
- + &ioctlBytesReturned,
- + NULL);
- +
- + if (!bSuccess) {
- + (void)fprintf(stderr,
- + "FSCTL_OFFLOAD_READ failed, lasterr=%d\n",
- + (int)GetLastError());
- + goto cleanup;
- + }
- +
- + if (!SetFilePointerEx(hDest, fileSize, NULL, FILE_BEGIN)) {
- + (void)fprintf(stderr,
- + "Cannot set dest file pointer, lasterr=%d\n",
- + (int)GetLastError());
- + goto cleanup;
- + }
- +
- + if (!SetEndOfFile(hDest)) {
- + (void)fprintf(stderr,
- + "Cannot set dest file size, lasterr=%d\n",
- + (int)GetLastError());
- + goto cleanup;
- + }
- +
- + (void)memcpy(pToken, readOutput.Token, sizeof(tokenBuffer));
- +
- + FSCTL_OFFLOAD_WRITE_INPUT writeInput = { 0 };
- + writeInput.Size = sizeof(FSCTL_OFFLOAD_WRITE_INPUT);
- + writeInput.FileOffset = 0;
- + writeInput.CopyLength = fileSize.QuadPart;
- + writeInput.TransferOffset = 0;
- + (void)memcpy(writeInput.Token, pToken, sizeof(tokenBuffer));
- +
- + FSCTL_OFFLOAD_WRITE_OUTPUT writeOutput = { 0 };
- + writeOutput.Size = sizeof(FSCTL_OFFLOAD_WRITE_OUTPUT);
- +
- + (void)printf("Performing copy with FSCTL_OFFLOAD_WRITE...\n");
- + bSuccess = DeviceIoControl(
- + hDest,
- + FSCTL_OFFLOAD_WRITE,
- + &writeInput,
- + sizeof(writeInput),
- + &writeOutput,
- + sizeof(writeOutput),
- + &ioctlBytesReturned,
- + NULL);
- +
- + if (!bSuccess) {
- + (void)fprintf(stderr,
- + "FSCTL_OFFLOAD_WRITE failed, lasterr=%d\n",
- + (int)GetLastError());
- + goto cleanup;
- + }
- +
- + (void)printf("Offload write successful. Bytes written: %lld\n",
- + (long long)writeOutput.LengthWritten);
- + (void)printf("Offloaded copy completed successfully!\n");
- + retval = EXIT_SUCCESS;
- +
- +cleanup:
- + if (hSrc != INVALID_HANDLE_VALUE) {
- + (void)CloseHandle(hSrc);
- + }
- + if (hDest != INVALID_HANDLE_VALUE) {
- + (void)CloseHandle(hDest);
- + }
- +
- + return retval;
- +}
- --
- 2.45.1
- From a2b05101926134bdf1d237e1a95e1e4d63246d17 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Thu, 21 Aug 2025 13:06:29 +0200
- Subject: [PATCH 2/2] daemon:
- |FILE_ID_INFORMATION.VolumeSerialNumber|+|FILE_FS_VOLUME_INFORMATION.VolumeSerialNumber|
- should be calculated from |nfs41_fsid|
- |FILE_ID_INFORMATION.VolumeSerialNumber| and
- |FILE_FS_VOLUME_INFORMATION.VolumeSerialNumber| should be calculated from
- |nfs41_fsid|.
- Reported-by: Jeremy Drake <cygwin@jdrake.com>
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- daemon/getattr.c | 8 +++++++-
- daemon/util.h | 25 +++++++++++++++++++++++++
- daemon/volume.c | 8 +++++++-
- 3 files changed, 39 insertions(+), 2 deletions(-)
- diff --git a/daemon/getattr.c b/daemon/getattr.c
- index aa64ad7..f057eab 100644
- --- a/daemon/getattr.c
- +++ b/daemon/getattr.c
- @@ -175,8 +175,14 @@ static int handle_getattr(void *daemon_context, nfs41_upcall *upcall)
- &args->remote_protocol_info);
- break;
- case FileIdInformation:
- + nfs41_superblock *superblock = state->file.fh.superblock;
- nfs41_file_info_to_FILE_ID_128(&info, &args->id_info.FileId);
- - args->id_info.VolumeSerialNumber = 0xBABAFACE; /* 64bit! */
- + /*
- + * |FILE_ID_INFORMATION.VolumeSerialNumber| is a 64bit |ULONGLONG|
- + */
- + args->id_info.VolumeSerialNumber =
- + nfs41_fsid2VolumeSerialNumber64(&superblock->fsid);
- + EASSERT(args->id_info.VolumeSerialNumber != 0ULL);
- break;
- #ifdef NFS41_DRIVER_WSL_SUPPORT
- case FileStatInformation:
- diff --git a/daemon/util.h b/daemon/util.h
- index 8dba1a9..87c2315 100644
- --- a/daemon/util.h
- +++ b/daemon/util.h
- @@ -211,6 +211,31 @@ static __inline int nfs41_fsid_cmp(
- return 0;
- }
- +/*
- + * |nfs41_fsid2VolumeSerialNumber32()| - used for
- + * |FILE_FS_VOLUME_INFORMATION.VolumeSerialNumber|, which is a 32bit |ULONG|
- + */
- +static __inline ULONG nfs41_fsid2VolumeSerialNumber32(
- + IN const nfs41_fsid *restrict fsid)
- +{
- + ULONG vsn;
- +#define XOR_UINT64_WORDS(value) (((value) >> 32UL) ^ ((value) & 0x00000000FFFFFFFF))
- + vsn = (ULONG)(XOR_UINT64_WORDS(fsid->major) ^ XOR_UINT64_WORDS(fsid->minor));
- + return vsn;
- +}
- +
- +/*
- + * |nfs41_fsid2VolumeSerialNumber64()| - used for
- + * |FILE_ID_INFORMATION.VolumeSerialNumber|, which is a 64bit |ULONGLONG|
- + */
- +static __inline ULONGLONG nfs41_fsid2VolumeSerialNumber64(
- + IN const nfs41_fsid *restrict fsid)
- +{
- + ULONGLONG vsn;
- + vsn = fsid->major ^ fsid->minor;
- + return vsn;
- +}
- +
- static __inline void open_delegation4_cpy(
- OUT open_delegation4 *restrict dst,
- IN const open_delegation4 *restrict src)
- diff --git a/daemon/volume.c b/daemon/volume.c
- index dbb2431..3501c6e 100644
- --- a/daemon/volume.c
- +++ b/daemon/volume.c
- @@ -123,9 +123,15 @@ static int handle_volume(void *daemon_context, nfs41_upcall *upcall)
- switch (args->query) {
- case FileFsVolumeInformation:
- PFILE_FS_VOLUME_INFORMATION vi = &args->info.volume_info;
- + nfs41_superblock *superblock = upcall->state_ref->file.fh.superblock;
- vi->VolumeCreationTime.QuadPart = 0LL;
- - vi->VolumeSerialNumber = 0xBABAFACE;
- + /*
- + * |FILE_FS_VOLUME_INFORMATION.VolumeSerialNumber| is a 32bit |ULONG|
- + */
- + vi->VolumeSerialNumber =
- + nfs41_fsid2VolumeSerialNumber32(&superblock->fsid);
- + EASSERT(vi->VolumeSerialNumber != 0UL);
- vi->SupportsObjects = FALSE;
- /*
- --
- 2.45.1
msnfs41client: winoffloadcopyfile, volumeserialnumber from NFS fs_id, misc, 2025-08-21
Posted by Anonymous on Thu 21st Aug 2025 13:44
raw | new post
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.