- From 32253fd0cd66b75475ab687c2e3567ca53ada8f1 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Thu, 13 Feb 2025 13:21:26 +0100
- Subject: [PATCH 1/4] sys: Implement |FSCTL_SET_SPARSE|
- Implement |FSCTL_SET_SPARSE|
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- sys/nfs41sys_fsctl.c | 65 ++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 65 insertions(+)
- diff --git a/sys/nfs41sys_fsctl.c b/sys/nfs41sys_fsctl.c
- index ee4c186..6cfa6b3 100644
- --- a/sys/nfs41sys_fsctl.c
- +++ b/sys/nfs41sys_fsctl.c
- @@ -315,6 +315,68 @@ out:
- return status;
- }
- +static
- +NTSTATUS nfs41_SetSparse(
- + IN OUT PRX_CONTEXT RxContext)
- +{
- + NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
- + __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
- + __notnull XXCTL_LOWIO_COMPONENT *FsCtl =
- + &RxContext->LowIoContext.ParamsFor.FsCtl;
- + __notnull PFILE_SET_SPARSE_BUFFER set_parse_buffer =
- + (PFILE_SET_SPARSE_BUFFER)FsCtl->pInputBuffer;
- +
- + DbgEn();
- +
- + /*
- + * Special case: No input buffer, so we treat this as if we got
- + * |set_parse_buffer->SetSparse == TRUE|
- + */
- + if (FsCtl->InputBufferLength == 0) {
- + /*
- + * We treat all files on NFS as sparse files by default,
- + * so setting the flag is just a (valid) NOP
- + */
- + DbgP("nfs41_SetSparse: "
- + "SUCCESS: FsCtl->InputBufferLength==0, "
- + "treating as SetSparse=TRUE for file '%wZ'\n",
- + SrvOpen->pAlreadyPrefixedName);
- + status = STATUS_SUCCESS;
- + goto out;
- + }
- +
- + if (FsCtl->InputBufferLength < sizeof(FILE_SET_SPARSE_BUFFER)) {
- + DbgP("nfs41_SetSparse: Buffer too small\n");
- + status = STATUS_INVALID_PARAMETER;
- + goto out;
- + }
- +
- + if (set_parse_buffer->SetSparse) {
- + /*
- + * We treat all files on NFS as sparse files by default,
- + * so setting the flag is just a (valid) NOP
- + */
- + DbgP("nfs41_SetSparse: "
- + "SUCCESS: SetSparse=TRUE for file '%wZ'\n",
- + SrvOpen->pAlreadyPrefixedName);
- + status = STATUS_SUCCESS;
- + }
- + else {
- + /*
- + * We cannot disable the sparse flag, as we treat all files
- + * on NFS as sparse files
- + */
- + DbgP("nfs41_SetSparse: "
- + "FAIL: Cannot set SetSparse=FALSE for file '%wZ'\n",
- + SrvOpen->pAlreadyPrefixedName);
- + status = STATUS_INVALID_PARAMETER;
- + }
- +
- +out:
- + DbgEx();
- + return status;
- +}
- +
- NTSTATUS nfs41_FsCtl(
- IN OUT PRX_CONTEXT RxContext)
- {
- @@ -336,6 +398,9 @@ NTSTATUS nfs41_FsCtl(
- case FSCTL_QUERY_ALLOCATED_RANGES:
- status = nfs41_QueryAllocatedRanges(RxContext);
- break;
- + case FSCTL_SET_SPARSE:
- + status = nfs41_SetSparse(RxContext);
- + break;
- default:
- break;
- }
- --
- 2.45.1
- From 09a5e6aca0162d7f4f2b1faf17769c9011a304db Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Thu, 13 Feb 2025 13:23:00 +0100
- Subject: [PATCH 2/4] sys: Remove bogus |is_root_directory()| check from
- |check_nfs41_queryallocatedranges_args()|
- Remove bogus |is_root_directory()| check from |check_nfs41_queryallocatedranges_args()|
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- sys/nfs41sys_fsctl.c | 9 ---------
- 1 file changed, 9 deletions(-)
- diff --git a/sys/nfs41sys_fsctl.c b/sys/nfs41sys_fsctl.c
- index 6cfa6b3..1799fe9 100644
- --- a/sys/nfs41sys_fsctl.c
- +++ b/sys/nfs41sys_fsctl.c
- @@ -77,15 +77,6 @@ NTSTATUS check_nfs41_queryallocatedranges_args(
- &RxContext->LowIoContext.ParamsFor.FsCtl;
- const USHORT HeaderLen = sizeof(FILE_ALLOCATED_RANGE_BUFFER);
- - /*
- - * Must have a filename longer than vnetroot name,
- - * or it's trying to operate on the volume itself
- - */
- - if (is_root_directory(RxContext)) {
- - status = STATUS_INVALID_PARAMETER;
- - goto out;
- - }
- -
- if (!FsCtl->pOutputBuffer) {
- status = STATUS_INVALID_USER_BUFFER;
- goto out;
- --
- 2.45.1
- From 368db4039cd801fa745516adb8752b050b743ff5 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Thu, 13 Feb 2025 14:39:27 +0100
- Subject: [PATCH 3/4] daemon: Add more sparse file debug code
- (|debug_list_sparsefile_datasections|)
- Add more sparse file debug code (|debug_list_sparsefile_datasections|)
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- daemon/daemon_debug.c | 84 +++++++++++++++++++++++++++++++++++++++++++
- daemon/daemon_debug.h | 2 ++
- daemon/open.c | 3 +-
- 3 files changed, 88 insertions(+), 1 deletion(-)
- diff --git a/daemon/daemon_debug.c b/daemon/daemon_debug.c
- index 5ca7427..fa0f90c 100644
- --- a/daemon/daemon_debug.c
- +++ b/daemon/daemon_debug.c
- @@ -1304,6 +1304,90 @@ out:
- dprintf_out("<-- debug_list_sparsefile_holes()\n");
- }
- +void debug_list_sparsefile_datasections(nfs41_open_state *state)
- +{
- + uint64_t next_offset = 0ULL;
- + uint64_t data_size = 0ULL;
- + int data_seek_status;
- + bool_t data_seek_sr_eof;
- + uint64_t data_seek_sr_offset;
- + int hole_seek_status;
- + bool_t hole_seek_sr_eof;
- + uint64_t hole_seek_sr_offset;
- + int i;
- +
- + stateid_arg stateid;
- +
- + dprintf_out(
- + "--> debug_list_sparsefile_datasections(state->path.path='%s')\n",
- + state->path.path);
- +
- + nfs41_open_stateid_arg(state, &stateid);
- +
- + next_offset = 0;
- +
- + /*
- + * Limit to 100 cycles to avoid locking-up the client if
- + * something unexpected happen
- + */
- + for (i=0 ; i < 100 ; i++) {
- + data_seek_status = nfs42_seek(state->session,
- + &state->file,
- + &stateid,
- + next_offset,
- + NFS4_CONTENT_DATA,
- + &data_seek_sr_eof,
- + &data_seek_sr_offset);
- + if (data_seek_status) {
- + dprintf_out("SEEK_DATA failed "
- + "OP_SEEK(sa_offset=%llu,sa_what=SEEK_DATA) "
- + "failed with %d(='%s')\n",
- + next_offset,
- + data_seek_status,
- + nfs_error_string(data_seek_status));
- + goto out;
- + }
- +
- + next_offset = data_seek_sr_offset;
- +
- + hole_seek_status = nfs42_seek(state->session,
- + &state->file,
- + &stateid,
- + next_offset,
- + NFS4_CONTENT_HOLE,
- + &hole_seek_sr_eof,
- + &hole_seek_sr_offset);
- + if (hole_seek_status) {
- + dprintf_out("SEEK_HOLE failed "
- + "OP_SEEK(sa_offset=%llu,sa_what=SEEK_HOLE) "
- + "failed with %d(='%s')\n",
- + next_offset,
- + hole_seek_status,
- + nfs_error_string(hole_seek_status));
- + goto out;
- + }
- +
- + next_offset = hole_seek_sr_offset;
- +
- + data_size = hole_seek_sr_offset - data_seek_sr_offset;
- +
- + dprintf_out("data_section: from "
- + "%llu to %llu, size=%llu (data_eof=%d, hole_eof=%d)\n",
- + data_seek_sr_offset,
- + hole_seek_sr_offset,
- + data_size,
- + (int)data_seek_sr_eof,
- + (int)hole_seek_sr_eof);
- +
- + if (data_seek_sr_eof || hole_seek_sr_eof) {
- + break;
- + }
- + }
- +
- +out:
- + dprintf_out("<-- debug_list_sparsefile_datasections()\n");
- +}
- +
- #define NUM_RECENTLY_DELETED 128
- static struct
- {
- diff --git a/daemon/daemon_debug.h b/daemon/daemon_debug.h
- index b39a312..fd0f7b7 100644
- --- a/daemon/daemon_debug.h
- +++ b/daemon/daemon_debug.h
- @@ -155,6 +155,8 @@ const char* secflavorop2name(DWORD sec_flavor);
- void print_nfs41_file_info(const char *label, const void *vinfo);
- typedef struct __nfs41_open_state nfs41_open_state;
- void debug_list_sparsefile_holes(nfs41_open_state *state);
- +void debug_list_sparsefile_datasections(nfs41_open_state *state);
- +
- /* pnfs_debug.c */
- enum pnfs_status;
- diff --git a/daemon/open.c b/daemon/open.c
- index 681c8bf..2fbea48 100644
- --- a/daemon/open.c
- +++ b/daemon/open.c
- @@ -1182,7 +1182,8 @@ create_chgrp_out:
- if ((status == 0) &&
- (info.type == NF4REG) &&
- (state->session->client->root->nfsminorvers >= 2)) {
- - debug_list_sparsefile_holes(state);
- + //debug_list_sparsefile_holes(state);
- + debug_list_sparsefile_datasections(state);
- }
- #endif /* DEBUG_OPEN_SPARSE_FILES */
- --
- 2.45.1
- From 25453b8572671e98bd0567a56bf4eb7760f8abc2 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Thu, 13 Feb 2025 16:50:26 +0100
- Subject: [PATCH 4/4] cygwin,daemon,tests: Implement
- |FSCTL_QUERY_ALLOCATED_RANGES| via NFSv4.2 SEEK
- Implement |FSCTL_QUERY_ALLOCATED_RANGES| via NFSv4.2 SEEK, plus
- add simple test script.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- cygwin/Makefile.install | 2 +
- daemon/fsctl.c | 162 +++++++++++++++++++++-----
- tests/manual_testing.txt | 5 +
- tests/sparsefiles/testsparsefile1.ksh | 118 +++++++++++++++++++
- 4 files changed, 261 insertions(+), 26 deletions(-)
- create mode 100644 tests/sparsefiles/testsparsefile1.ksh
- diff --git a/cygwin/Makefile.install b/cygwin/Makefile.install
- index 8a4b878..98e4235 100644
- --- a/cygwin/Makefile.install
- +++ b/cygwin/Makefile.install
- @@ -36,6 +36,7 @@ installdest:
- mkdir -p $(DESTDIR)/$(CYGWIN_BASEPATH)/usr/share/msnfs41client
- mkdir -p $(DESTDIR)/$(CYGWIN_BASEPATH)/usr/share/msnfs41client/tests
- mkdir -p $(DESTDIR)/$(CYGWIN_BASEPATH)/usr/share/msnfs41client/tests/misc
- + mkdir -p $(DESTDIR)/$(CYGWIN_BASEPATH)/usr/share/msnfs41client/tests/sparsefiles
- cp $(VS_BUILD_DIR)/nfsd.exe $(DESTDIR)/$(CYGWIN_BASEPATH)/sbin/nfsd_debug.exe
- cp $(VS_BUILD_DIR)/nfsd.pdb $(DESTDIR)/$(CYGWIN_BASEPATH)/sbin/nfsd_debug.pdb
- cp $(VS_BUILD_DIR)/nfs_mount.* $(DESTDIR)/$(CYGWIN_BASEPATH)/sbin/.
- @@ -110,6 +111,7 @@ installdest:
- cp "$(PROJECT_BASEDIR_DIR)/tests/ea/nfs_ea.i686.exe" $(DESTDIR)/$(CYGWIN_BASEPATH)/bin/nfs_ea.exe ; \
- fi
- cp $(PROJECT_BASEDIR_DIR)/tests/nfsbuildtest/nfsbuildtest.ksh93 $(DESTDIR)/$(CYGWIN_BASEPATH)/usr/share/msnfs41client/tests/misc/nfsbuildtest.ksh93
- + cp $(PROJECT_BASEDIR_DIR)/tests/sparsefiles/testsparsefile1.ksh $(DESTDIR)/$(CYGWIN_BASEPATH)/usr/share/msnfs41client/tests/sparsefiles/testsparsefile1.ksh
- cp $(PROJECT_BASEDIR_DIR)/tests/fstest_make_numtree1/fstest_make_numtree1.ksh93 $(DESTDIR)/$(CYGWIN_BASEPATH)/usr/share/msnfs41client/tests/misc/fstest_make_numtree1.ksh93
- cp $(PROJECT_BASEDIR_DIR)/tests/wintartests/wintartest_comparewinvsgnu001.bash $(DESTDIR)/$(CYGWIN_BASEPATH)/usr/share/msnfs41client/tests/misc/wintartest_comparewinvsgnu001.bash
- cp $(PROJECT_BASEDIR_DIR)/tests/wintartests/wintartest_seq001.bash $(DESTDIR)/$(CYGWIN_BASEPATH)/usr/share/msnfs41client/tests/misc/wintartest_seq001.bash
- diff --git a/daemon/fsctl.c b/daemon/fsctl.c
- index 2eb85ee..61b9dca 100644
- --- a/daemon/fsctl.c
- +++ b/daemon/fsctl.c
- @@ -27,6 +27,8 @@
- #include "daemon_debug.h"
- #include "util.h"
- +#define QARLVL 2 /* dprintf level for "query allocated ranges" logging */
- +
- static int parse_queryallocatedranges(unsigned char *buffer,
- uint32_t length, nfs41_upcall *upcall)
- {
- @@ -40,7 +42,7 @@ static int parse_queryallocatedranges(unsigned char *buffer,
- status = safe_read(&buffer, &length, &args->outbuffer, sizeof(args->outbuffer));
- if (status) goto out;
- - DPRINTF(0, ("parse_queryallocatedranges: "
- + DPRINTF(QARLVL, ("parse_queryallocatedranges: "
- "parsing '%s' inrange=(FileOffset=%lld Length=%lld) "
- "outbuffersize=%lu outbuffer=0x%p\n",
- opcode2string(upcall->opcode),
- @@ -52,8 +54,113 @@ out:
- return status;
- }
- +static
- +int query_sparsefile_datasections(nfs41_open_state *state,
- + uint64_t start_offset,
- + FILE_ALLOCATED_RANGE_BUFFER *outbuffer,
- + size_t out_maxrecords,
- + size_t *restrict res_num_records)
- +{
- + int status = NO_ERROR;
- + uint64_t next_offset;
- + uint64_t data_size;
- + int data_seek_status;
- + bool_t data_seek_sr_eof;
- + uint64_t data_seek_sr_offset;
- + int hole_seek_status;
- + bool_t hole_seek_sr_eof;
- + uint64_t hole_seek_sr_offset;
- + size_t i;
- +
- + stateid_arg stateid;
- +
- + DPRINTF(QARLVL,
- + ("--> query_sparsefile_datasections(state->path.path='%s')\n",
- + state->path.path));
- +
- + /* NFS SEEK requires NFSv4.2 */
- + if (state->session->client->root->nfsminorvers < 2) {
- + status = ERROR_NOT_SUPPORTED;
- + goto out;
- + }
- -static int handle_queryallocatedranges(void *daemon_context, nfs41_upcall *upcall)
- + nfs41_open_stateid_arg(state, &stateid);
- +
- + next_offset = start_offset;
- + *res_num_records = 0;
- +
- + for (i=0 ; i < out_maxrecords ; i++) {
- + data_seek_status = nfs42_seek(state->session,
- + &state->file,
- + &stateid,
- + next_offset,
- + NFS4_CONTENT_DATA,
- + &data_seek_sr_eof,
- + &data_seek_sr_offset);
- + if (data_seek_status) {
- + status = nfs_to_windows_error(data_seek_status,
- + ERROR_INVALID_PARAMETER);
- + DPRINTF(QARLVL, ("SEEK_DATA failed "
- + "OP_SEEK(sa_offset=%llu,sa_what=SEEK_DATA) "
- + "failed with %d(='%s')\n",
- + next_offset,
- + data_seek_status,
- + nfs_error_string(data_seek_status)));
- + goto out;
- + }
- +
- + next_offset = data_seek_sr_offset;
- +
- + hole_seek_status = nfs42_seek(state->session,
- + &state->file,
- + &stateid,
- + next_offset,
- + NFS4_CONTENT_HOLE,
- + &hole_seek_sr_eof,
- + &hole_seek_sr_offset);
- + if (hole_seek_status) {
- + status = nfs_to_windows_error(hole_seek_status,
- + ERROR_INVALID_PARAMETER);
- + DPRINTF(QARLVL, ("SEEK_HOLE failed "
- + "OP_SEEK(sa_offset=%llu,sa_what=SEEK_HOLE) "
- + "failed with %d(='%s')\n",
- + next_offset,
- + hole_seek_status,
- + nfs_error_string(hole_seek_status)));
- + goto out;
- + }
- +
- + next_offset = hole_seek_sr_offset;
- +
- + data_size = hole_seek_sr_offset - data_seek_sr_offset;
- +
- + DPRINTF(QARLVL, ("data_section: from "
- + "%llu to %llu, size=%llu (data_eof=%d, hole_eof=%d)\n",
- + data_seek_sr_offset,
- + hole_seek_sr_offset,
- + data_size,
- + (int)data_seek_sr_eof,
- + (int)hole_seek_sr_eof));
- +
- + outbuffer[i].FileOffset.QuadPart = data_seek_sr_offset;
- + outbuffer[i].Length.QuadPart = data_size;
- + (*res_num_records)++;
- +
- + if (data_seek_sr_eof || hole_seek_sr_eof) {
- + break;
- + }
- + }
- +
- +out:
- + DPRINTF(QARLVL, ("<-- query_sparsefile_datasections(), status=0x%x\n",
- + status));
- + return status;
- +}
- +
- +
- +static
- +int handle_queryallocatedranges(void *daemon_context,
- + nfs41_upcall *upcall)
- {
- queryallocatedranges_upcall_args *args =
- &upcall->args.queryallocatedranges;
- @@ -61,41 +168,44 @@ static int handle_queryallocatedranges(void *daemon_context, nfs41_upcall *upcal
- PFILE_ALLOCATED_RANGE_BUFFER outbuffer =
- (PFILE_ALLOCATED_RANGE_BUFFER)args->outbuffer;
- int status = ERROR_INVALID_PARAMETER;
- - nfs41_file_info info;
- + size_t num_records;
- - DPRINTF(0,
- + DPRINTF(QARLVL,
- ("--> handle_queryallocatedranges("
- - "state->path.path='%s')\n",
- - state->path.path));
- -
- - DPRINTF(0,
- + "state->path.path='%s', "
- + "args->inrange.FileOffset=%llu, "
- + "args->inrange.Length=%llu)\n",
- + state->path.path,
- + args->inrange.FileOffset.QuadPart,
- + args->inrange.Length.QuadPart));
- +
- + num_records =
- + ((size_t)args->outbuffersize /
- + sizeof(FILE_ALLOCATED_RANGE_BUFFER));
- +
- + DPRINTF(QARLVL,
- ("handle_queryallocatedranges:"
- "got space for %ld records\n",
- - (int)((size_t)args->outbuffersize / sizeof(FILE_ALLOCATED_RANGE_BUFFER))));
- + (int)num_records));
- args->returned_size = 0;
- - (void)memset(&info, 0, sizeof(info));
- + size_t res_num_records = 0;
- - status = nfs41_cached_getattr(state->session,
- - &state->file, &info);
- - if (status)
- - goto out;
- + status = query_sparsefile_datasections(state,
- + args->inrange.FileOffset.QuadPart,
- + outbuffer,
- + num_records,
- + &res_num_records);
- - if (args->outbuffersize < (1*sizeof(FILE_ALLOCATED_RANGE_BUFFER))) {
- - /* FIXME: We should return the size of the required buffer */
- - status = ERROR_INSUFFICIENT_BUFFER;
- - goto out;
- + if (!status) {
- + args->returned_size =
- + (ULONG)res_num_records*sizeof(FILE_ALLOCATED_RANGE_BUFFER);
- }
- - /* return size of file */
- - outbuffer[0].FileOffset.QuadPart = 0;
- - outbuffer[0].Length.QuadPart = info.size;
- - args->returned_size = 1*sizeof(FILE_ALLOCATED_RANGE_BUFFER);
- - status = NO_ERROR;
- -
- -out:
- - DPRINTF(0, ("<-- handle_queryallocatedranges(), status=0x%lx\n", status));
- + DPRINTF(QARLVL,
- + ("<-- handle_queryallocatedranges(), status=0x%lx\n",
- + status));
- return status;
- }
- diff --git a/tests/manual_testing.txt b/tests/manual_testing.txt
- index 75f2053..13b82f6 100644
- --- a/tests/manual_testing.txt
- +++ b/tests/manual_testing.txt
- @@ -582,5 +582,10 @@ $ apt-get upgrade
- # install packages for testing
- $ apt-get install clang gcc gdb nedit emacs vim x11-apps xterm ksh traceroute strace ddd mesa-utils tk xpdf xmpuzzles mwm xutils-dev valgrind crash libhugetlbfs-bin wireguard xtron x11-xserver-utils sunclock moreutils iproute2 inetutils-tools build-essential linux-source libncurses5-dev xvkbd ethtool tshark xmldiff krb5-user krb5-kdc libkrb5-dev keyutils info bc kmod cpio flex libncurses5-dev libelf-dev libssl-dev inkscape xdmx xdmx-tools twm mwm sbuild autoconf automake openbsd-inetd rwho rwhod finger fingerd cronutils at nfs-kernel-server nfs-common nfs4-acl-tools autofs openjdk-17-jdk openjdk-17-demo python talk talkd libcurl4 libc6-dbg sysvbanner powertop iftop acpidump linux-perf ltrace locales task-german task-japanese schroot groff squashfs-tools dpkg-dev devscripts kernel-wedge sbsigntool git-svn apt-file module-assistant dwarves tree net-tools bridge-utils xnest uml-utilities inxi libxaw7-dev whois extrace kexec-tools dos2unix pkg-config libglib2.0-dev libpixman-1-dev qemu qemu-utils qemu-system-\* qemu-system-gui libsixel-bin w3m-img sharutils freerdp2-x11 nscd debconf-utils iotop 'manpages-posix*' konsole lsof
- +#
- +# sparse file (data+hole) tests
- +#
- +ksh93 tests/sparsefiles/testsparsefile1.ksh
- +
- #
- # EOF.
- diff --git a/tests/sparsefiles/testsparsefile1.ksh b/tests/sparsefiles/testsparsefile1.ksh
- new file mode 100644
- index 0000000..ea43f74
- --- /dev/null
- +++ b/tests/sparsefiles/testsparsefile1.ksh
- @@ -0,0 +1,118 @@
- +#!/bin/ksh93
- +
- +#
- +# 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.
- +#
- +
- +#
- +# testsparsefile1.ksh - simple sparsefile test
- +#
- +# Written by Roland Mainz <roland.mainz@nrubsig.org>
- +#
- +
- +
- +
- +PATH='/bin:/usr/bin'
- +
- +builtin rm
- +
- +function test_sparsefile1
- +{
- + set -o errexit
- + set -o nounset
- + #set -o xtrace
- +
- + compound c
- +
- + integer c.fsblocksize=$1
- + integer c.start_data_section=$2
- + integer c.end_data_section=$3
- +
- + integer i
- + compound -a c.filecontent
- +
- + #
- + # generate sparse file layout+contents
- + #
- + for (( i=c.start_data_section ; i < c.end_data_section ; i++ )) ; do
- + c.filecontent[$i]=(
- + integer pos=i*1024*c.fsblocksize
- + typeset data="$(printf "#block %d*1024*%d\n" i c.fsblocksize)"
- + )
- + done
- +
- +
- + #
- + # generate sparse file
- + #
- + rm -f 'mysparsefile'
- + printf '' >'mysparsefile' # trunc
- +
- + for i in ${!c.filecontent[@]} ; do
- + dd of='mysparsefile' bs=1 conv=notrunc seek=${c.filecontent[$i].pos} status=none <<<"${c.filecontent[$i].data}"
- + done
- +
- +
- + #
- + # print results
- + #
- + printf '#\n# Results:\n#\n'
- +
- + ls -l mysparsefile
- +
- + /cygdrive/c/Windows/system32/fsutil sparse queryrange 'mysparsefile'
- +
- + integer fsutil_num_data_sections="$(/cygdrive/c/Windows/system32/fsutil sparse queryrange 'mysparsefile' | wc -l)"
- +
- +
- + #
- + # test whether the file is OK
- + #
- + if (( fsutil_num_data_sections != (c.end_data_section-c.start_data_section) )) ; then
- + printf "# TEST failed, found %d data sections, expceted %d\n" \
- + fsutil_num_data_sections \
- + $((c.end_data_section-c.start_data_section))
- + return 1
- + fi
- +
- + printf "\n#\n# TEST OK, found %d data sections\n#\n" \
- + fsutil_num_data_sections
- + return 0
- +}
- +
- +
- +#
- +# main
- +#
- +set -o errexit
- +test_sparsefile1 1024 0 4
- +test_sparsefile1 1024 1 4
- +test_sparsefile1 1024 0 32
- +test_sparsefile1 1024 2 32
- +
- +# 512 does not work, as Win10 fsutil can only handle 64 data sections
- +# test_sparsefile1 1024 2 512
- +
- +printf '%s: All tests OK\n' "$0"
- +exit 0
- +# EOF.
- --
- 2.45.1
msnfs41client: Patches to implement |FSCTL_QUERY_ALLOCATED_RANGES| via NFSv4.2 SEEK, tests+misc, 2025-02-13
Posted by Anonymous on Thu 13th Feb 2025 16:01
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.