- From fbd361997908b180d03a266b8135ad35c17a208a Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Wed, 12 Feb 2025 17:58:13 +0100
- Subject: [PATCH] build.vc19,daemon,include,sys: Add upcall/downcall for
- |FSCTL_QUERY_ALLOCATED_RANGES|
- Add upcall/downcall for |FSCTL_QUERY_ALLOCATED_RANGES|.
- Note: The dummy implementation in |handle_queryallocatedranges()|
- currently only returns one |FILE_ALLOCATED_RANGE_BUFFER| with
- { 0, filesize } (e.g. this means the file only contains data and no
- holes), and needs to be replaced with a function which uses
- NFSv4.2 SEEK to implement |FSCTL_QUERY_ALLOCATED_RANGES|
- correctly.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- build.vc19/nfsd/nfsd.vcxproj | 1 +
- build.vc19/nfsd/nfsd.vcxproj.filters | 3 +
- daemon/daemon_debug.c | 1 +
- daemon/fsctl.c | 118 ++++++++++++++++
- daemon/upcall.c | 2 +
- daemon/upcall.h | 9 ++
- include/from_kernel.h | 13 ++
- include/nfs41_driver.h | 1 +
- sys/nfs41sys_debug.c | 1 +
- sys/nfs41sys_driver.h | 17 ++-
- sys/nfs41sys_fsctl.c | 204 +++++++++++++++++++++++----
- sys/nfs41sys_updowncall.c | 16 +++
- 12 files changed, 354 insertions(+), 32 deletions(-)
- create mode 100644 daemon/fsctl.c
- diff --git a/build.vc19/nfsd/nfsd.vcxproj b/build.vc19/nfsd/nfsd.vcxproj
- index 3005f90..85ab083 100644
- --- a/build.vc19/nfsd/nfsd.vcxproj
- +++ b/build.vc19/nfsd/nfsd.vcxproj
- @@ -290,6 +290,7 @@
- <ClCompile Include="..\..\daemon\delegation.c" />
- <ClCompile Include="..\..\daemon\ea.c" />
- <ClCompile Include="..\..\daemon\fileinfoutil.c" />
- + <ClCompile Include="..\..\daemon\fsctl.c" />
- <ClCompile Include="..\..\daemon\getattr.c" />
- <ClCompile Include="..\..\daemon\idmap.c" />
- <ClCompile Include="..\..\daemon\idmap_cygwin.c" />
- diff --git a/build.vc19/nfsd/nfsd.vcxproj.filters b/build.vc19/nfsd/nfsd.vcxproj.filters
- index 5190a8e..61891d6 100644
- --- a/build.vc19/nfsd/nfsd.vcxproj.filters
- +++ b/build.vc19/nfsd/nfsd.vcxproj.filters
- @@ -39,6 +39,9 @@
- <ClCompile Include="..\..\daemon\fileinfoutil.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- + <ClCompile Include="..\..\daemon\fsctl.c">
- + <Filter>Source Files</Filter>
- + </ClCompile>
- <ClCompile Include="..\..\daemon\getattr.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- diff --git a/daemon/daemon_debug.c b/daemon/daemon_debug.c
- index f8f7d2e..5ca7427 100644
- --- a/daemon/daemon_debug.c
- +++ b/daemon/daemon_debug.c
- @@ -466,6 +466,7 @@ const char* opcode2string(nfs41_opcodes opcode)
- NFSOPCODE_TO_STRLITERAL(NFS41_SYSOP_VOLUME_QUERY)
- NFSOPCODE_TO_STRLITERAL(NFS41_SYSOP_ACL_QUERY)
- NFSOPCODE_TO_STRLITERAL(NFS41_SYSOP_ACL_SET)
- + NFSOPCODE_TO_STRLITERAL(NFS41_SYSOP_FSCTL_QUERYALLOCATEDRANGES)
- NFSOPCODE_TO_STRLITERAL(NFS41_SYSOP_INVALID_OPCODE1)
- default: break;
- }
- diff --git a/daemon/fsctl.c b/daemon/fsctl.c
- new file mode 100644
- index 0000000..2eb85ee
- --- /dev/null
- +++ b/daemon/fsctl.c
- @@ -0,0 +1,118 @@
- +/* NFSv4.1 client for Windows
- + * Copyright (C) 2024-2025 Roland Mainz <roland.mainz@nrubsig.org>
- + *
- + * Roland Mainz <roland.mainz@nrubsig.org>
- + *
- + * This library is free software; you can redistribute it and/or modify it
- + * under the terms of the GNU Lesser General Public License as published by
- + * the Free Software Foundation; either version 2.1 of the License, or (at
- + * your option) any later version.
- + *
- + * This library 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
- + * License for more details.
- + *
- + * You should have received a copy of the GNU Lesser General Public License
- + * along with this library; if not, write to the Free Software Foundation,
- + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- + */
- +
- +#include <Windows.h>
- +#include <stdio.h>
- +
- +#include "nfs41_ops.h"
- +#include "name_cache.h"
- +#include "upcall.h"
- +#include "daemon_debug.h"
- +#include "util.h"
- +
- +static int parse_queryallocatedranges(unsigned char *buffer,
- + uint32_t length, nfs41_upcall *upcall)
- +{
- + int status;
- + queryallocatedranges_upcall_args *args = &upcall->args.queryallocatedranges;
- +
- + status = safe_read(&buffer, &length, &args->inrange, sizeof(args->inrange));
- + if (status) goto out;
- + status = safe_read(&buffer, &length, &args->outbuffersize, sizeof(args->outbuffersize));
- + if (status) goto out;
- + status = safe_read(&buffer, &length, &args->outbuffer, sizeof(args->outbuffer));
- + if (status) goto out;
- +
- + DPRINTF(0, ("parse_queryallocatedranges: "
- + "parsing '%s' inrange=(FileOffset=%lld Length=%lld) "
- + "outbuffersize=%lu outbuffer=0x%p\n",
- + opcode2string(upcall->opcode),
- + args->inrange.FileOffset.QuadPart,
- + args->inrange.Length.QuadPart,
- + (unsigned long)args->outbuffersize,
- + (void *)args->outbuffer));
- +out:
- + return status;
- +}
- +
- +
- +static int handle_queryallocatedranges(void *daemon_context, nfs41_upcall *upcall)
- +{
- + queryallocatedranges_upcall_args *args =
- + &upcall->args.queryallocatedranges;
- + nfs41_open_state *state = upcall->state_ref;
- + PFILE_ALLOCATED_RANGE_BUFFER outbuffer =
- + (PFILE_ALLOCATED_RANGE_BUFFER)args->outbuffer;
- + int status = ERROR_INVALID_PARAMETER;
- + nfs41_file_info info;
- +
- + DPRINTF(0,
- + ("--> handle_queryallocatedranges("
- + "state->path.path='%s')\n",
- + state->path.path));
- +
- + DPRINTF(0,
- + ("handle_queryallocatedranges:"
- + "got space for %ld records\n",
- + (int)((size_t)args->outbuffersize / sizeof(FILE_ALLOCATED_RANGE_BUFFER))));
- +
- + args->returned_size = 0;
- +
- + (void)memset(&info, 0, sizeof(info));
- +
- + status = nfs41_cached_getattr(state->session,
- + &state->file, &info);
- + if (status)
- + goto out;
- +
- + 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;
- + }
- +
- + /* 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));
- + return status;
- +}
- +
- +static int marshall_queryallocatedranges(unsigned char *buffer,
- + uint32_t *length, nfs41_upcall *upcall)
- +{
- + int status;
- + queryallocatedranges_upcall_args *args = &upcall->args.queryallocatedranges;
- +
- + status = safe_write(&buffer, length, &args->returned_size, sizeof(args->returned_size));
- +
- + return status;
- +}
- +
- +const nfs41_upcall_op nfs41_op_queryallocatedranges = {
- + .parse = parse_queryallocatedranges,
- + .handle = handle_queryallocatedranges,
- + .marshall = marshall_queryallocatedranges,
- + .arg_size = sizeof(queryallocatedranges_upcall_args)
- +};
- diff --git a/daemon/upcall.c b/daemon/upcall.c
- index 11863cb..f6216fc 100644
- --- a/daemon/upcall.c
- +++ b/daemon/upcall.c
- @@ -49,6 +49,7 @@ extern const nfs41_upcall_op nfs41_op_symlink_set;
- extern const nfs41_upcall_op nfs41_op_volume;
- extern const nfs41_upcall_op nfs41_op_getacl;
- extern const nfs41_upcall_op nfs41_op_setacl;
- +extern const nfs41_upcall_op nfs41_op_queryallocatedranges;
- /* |_nfs41_opcodes| and |g_upcall_op_table| must be in sync! */
- static const nfs41_upcall_op *g_upcall_op_table[] = {
- @@ -72,6 +73,7 @@ static const nfs41_upcall_op *g_upcall_op_table[] = {
- &nfs41_op_volume,
- &nfs41_op_getacl,
- &nfs41_op_setacl,
- + &nfs41_op_queryallocatedranges,
- NULL,
- NULL
- };
- diff --git a/daemon/upcall.h b/daemon/upcall.h
- index e2ba48f..2fe50ba 100644
- --- a/daemon/upcall.h
- +++ b/daemon/upcall.h
- @@ -190,6 +190,14 @@ typedef struct __setacl_upcall_args {
- ULONGLONG ctime;
- } setacl_upcall_args;
- +typedef struct __queryallocatedranges_upcall_args {
- + FILE_ALLOCATED_RANGE_BUFFER inrange;
- + HANDLE outbuffer;
- + ULONG outbuffersize;
- + ULONG returned_size;
- +} queryallocatedranges_upcall_args;
- +
- +
- typedef union __upcall_args {
- mount_upcall_args mount;
- open_upcall_args open;
- @@ -206,6 +214,7 @@ typedef union __upcall_args {
- volume_upcall_args volume;
- getacl_upcall_args getacl;
- setacl_upcall_args setacl;
- + queryallocatedranges_upcall_args queryallocatedranges;
- } upcall_args;
- typedef enum _nfs41_opcodes nfs41_opcodes;
- diff --git a/include/from_kernel.h b/include/from_kernel.h
- index 85cacce..8b9ddc0 100644
- --- a/include/from_kernel.h
- +++ b/include/from_kernel.h
- @@ -439,4 +439,17 @@ typedef struct _FILE_FS_SECTOR_SIZE_INFORMATION {
- typedef struct _FILE_INTERNAL_INFORMATION {
- LARGE_INTEGER IndexNumber;
- } FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION;
- +
- +/*
- + * |FILE_ALLOCATED_RANGE_BUFFER| - test for
- + * /usr/i686-w64-mingw32/sys-root/mingw/include/winioctl.h header
- + * to avoid type redefinition warnings
- + */
- +#ifndef _WINIOCTL_
- +typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
- + LARGE_INTEGER FileOffset;
- + LARGE_INTEGER Length;
- +} FILE_ALLOCATED_RANGE_BUFFER, *PFILE_ALLOCATED_RANGE_BUFFER;
- +#endif /* _WINIOCTL_ */
- +
- #endif
- diff --git a/include/nfs41_driver.h b/include/nfs41_driver.h
- index dde47af..403bf04 100644
- --- a/include/nfs41_driver.h
- +++ b/include/nfs41_driver.h
- @@ -82,6 +82,7 @@ typedef enum _nfs41_opcodes {
- NFS41_SYSOP_VOLUME_QUERY,
- NFS41_SYSOP_ACL_QUERY,
- NFS41_SYSOP_ACL_SET,
- + NFS41_SYSOP_FSCTL_QUERYALLOCATEDRANGES,
- NFS41_SYSOP_SHUTDOWN,
- NFS41_SYSOP_INVALID_OPCODE1
- } nfs41_opcodes;
- diff --git a/sys/nfs41sys_debug.c b/sys/nfs41sys_debug.c
- index 33b801c..dccd933 100644
- --- a/sys/nfs41sys_debug.c
- +++ b/sys/nfs41sys_debug.c
- @@ -677,6 +677,7 @@ const char *opcode2string(int opcode)
- case NFS41_SYSOP_VOLUME_QUERY: return "NFS41_SYSOP_VOLUME_QUERY";
- case NFS41_SYSOP_ACL_QUERY: return "NFS41_SYSOP_ACL_QUERY";
- case NFS41_SYSOP_ACL_SET: return "NFS41_SYSOP_ACL_SET";
- + case NFS41_SYSOP_FSCTL_QUERYALLOCATEDRANGES: return "NFS41_SYSOP_FSCTL_QUERYALLOCATEDRANGES";
- default: return "UNKNOWN";
- }
- }
- diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
- index 762e832..7fccf69 100644
- --- a/sys/nfs41sys_driver.h
- +++ b/sys/nfs41sys_driver.h
- @@ -1,6 +1,6 @@
- /* NFSv4.1 client for Windows
- * Copyright (C) 2012 The Regents of the University of Michigan
- - * Copyright (C) 2023-2024 Roland Mainz <roland.mainz@nrubsig.org>
- + * Copyright (C) 2023-2025 Roland Mainz <roland.mainz@nrubsig.org>
- *
- * Olga Kornievskaia <aglo@umich.edu>
- * Casey Bodley <cbodley@umich.edu>
- @@ -269,6 +269,13 @@ typedef struct _updowncall_entry {
- struct {
- SECURITY_INFORMATION query;
- } Acl;
- + struct {
- + FILE_ALLOCATED_RANGE_BUFFER inrange;
- + PMDL BufferMdl;
- + ULONG BufferSize;
- + PVOID Buffer;
- + LONGLONG returned_size;
- + } QueryAllocatedRanges;
- } u;
- } nfs41_updowncall_entry;
- @@ -635,6 +642,14 @@ NTSTATUS nfs41_QueryEaInformation(
- /* nfs41sys_fsctl.c */
- NTSTATUS nfs41_FsCtl(
- IN OUT PRX_CONTEXT RxContext);
- +NTSTATUS marshal_nfs41_queryallocatedranges(
- + nfs41_updowncall_entry *entry,
- + unsigned char *buf,
- + ULONG buf_len,
- + ULONG *len);
- +NTSTATUS unmarshal_nfs41_queryallocatedranges(
- + nfs41_updowncall_entry *cur,
- + unsigned char **buf);
- /* nfs41sys_ioctl.c */
- NTSTATUS nfs41_IoCtl(
- diff --git a/sys/nfs41sys_fsctl.c b/sys/nfs41sys_fsctl.c
- index 2937d8c..ee4c186 100644
- --- a/sys/nfs41sys_fsctl.c
- +++ b/sys/nfs41sys_fsctl.c
- @@ -1,6 +1,6 @@
- /* NFSv4.1 client for Windows
- * Copyright (C) 2012 The Regents of the University of Michigan
- - * Copyright (C) 2023-2024 Roland Mainz <roland.mainz@nrubsig.org>
- + * Copyright (C) 2023-2025 Roland Mainz <roland.mainz@nrubsig.org>
- *
- * Olga Kornievskaia <aglo@umich.edu>
- * Casey Bodley <cbodley@umich.edu>
- @@ -105,14 +105,20 @@ NTSTATUS nfs41_QueryAllocatedRanges(
- IN OUT PRX_CONTEXT RxContext)
- {
- NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
- + nfs41_updowncall_entry *entry = NULL;
- + __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
- + __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
- + NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
- + __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
- + NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
- __notnull XXCTL_LOWIO_COMPONENT *FsCtl =
- &RxContext->LowIoContext.ParamsFor.FsCtl;
- __notnull PFILE_ALLOCATED_RANGE_BUFFER in_range_buffer =
- (PFILE_ALLOCATED_RANGE_BUFFER)FsCtl->pInputBuffer;
- __notnull PFILE_ALLOCATED_RANGE_BUFFER out_range_buffer =
- (PFILE_ALLOCATED_RANGE_BUFFER)FsCtl->pOutputBuffer;
- - __notnull PNFS41_FCB nfs41_fcb =
- - NFS41GetFcbExtension(RxContext->pFcb);
- + ULONG out_range_buffer_len = FsCtl->OutputBufferLength;
- + __notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
- DbgEn();
- @@ -130,49 +136,185 @@ NTSTATUS nfs41_QueryAllocatedRanges(
- goto out;
- }
- -/*
- - * FIXME: For now we implement |FSCTL_QUERY_ALLOCATED_RANGES| using
- - * a dummy implementation which just returns { 0, filesize }
- - * so we can do testing with Cygwin >= 3.6.x
- - * |lseek(..., SEEK_HOLE/SEEK_DATA, ...)| and
- - * Windows $ fsutil sparse queryrange mysparsefile.txt #.
- - *
- - * We really need an upcall which issues NFSv4.2 SEEK to enumerate the
- - * data/hole sections and fill an array of
- - * |FILE_ALLOCATED_RANGE_BUFFER|s with the positions of tha SEEK_DATA
- - * results.
- - */
- -#define NFS41SYS_FSCTL_QUERY_ALLOCATED_RANGES_PLACEHOLDER_DUMMY_IMPL 1
- -
- -#ifdef NFS41SYS_FSCTL_QUERY_ALLOCATED_RANGES_PLACEHOLDER_DUMMY_IMPL
- - DbgP("nfs41_QueryAllocatedRanges: "
- + DbgP("nfs41_QueryAllocatedRanges/REAL: "
- "in_range_buffer=(FileOffset=%lld,Length=%lld)\n",
- (long long)in_range_buffer->FileOffset.QuadPart,
- (long long)in_range_buffer->Length.QuadPart);
- - if (FsCtl->OutputBufferLength <
- - (1*sizeof(FILE_ALLOCATED_RANGE_BUFFER))) {
- - DbgP("nfs41_QueryAllocatedRanges: "
- - "FsCtl->OutputBufferLength too small\n");
- - status = STATUS_BUFFER_TOO_SMALL;
- + status = nfs41_UpcallCreate(NFS41_SYSOP_FSCTL_QUERYALLOCATEDRANGES,
- + &nfs41_fobx->sec_ctx,
- + pVNetRootContext->session,
- + nfs41_fobx->nfs41_open_state,
- + pNetRootContext->nfs41d_version,
- + SrvOpen->pAlreadyPrefixedName,
- + &entry);
- +
- + if (status)
- goto out;
- +
- + entry->u.QueryAllocatedRanges.inrange = *in_range_buffer;
- + entry->u.QueryAllocatedRanges.BufferSize = out_range_buffer_len;
- +
- + /* lock the buffer for write access in user space */
- + entry->u.QueryAllocatedRanges.BufferMdl = IoAllocateMdl(
- + out_range_buffer,
- + out_range_buffer_len,
- + FALSE, FALSE, NULL);
- + if (entry->u.QueryAllocatedRanges.BufferMdl == NULL) {
- + status = STATUS_INTERNAL_ERROR;
- + DbgP("nfs41_QueryAllocatedRanges: IoAllocateMdl() failed\n");
- + goto out_free;
- }
- - out_range_buffer->FileOffset.QuadPart = 0;
- - out_range_buffer->Length.QuadPart =
- - nfs41_fcb->StandardInfo.EndOfFile.QuadPart;
- +#pragma warning( push )
- +/*
- + * C28145: "The opaque MDL structure should not be modified by a
- + * driver.", |MDL_MAPPING_CAN_FAIL| is the exception
- + */
- +#pragma warning (disable : 28145)
- + entry->u.QueryAllocatedRanges.BufferMdl->MdlFlags |=
- + MDL_MAPPING_CAN_FAIL;
- +#pragma warning( pop )
- + MmProbeAndLockPages(entry->u.QueryAllocatedRanges.BufferMdl,
- + KernelMode,
- + IoModifyAccess);
- - RxContext->IoStatusBlock.Information =
- - (ULONG_PTR)1*sizeof(FILE_ALLOCATED_RANGE_BUFFER);
- + status = nfs41_UpcallWaitForReply(entry, pVNetRootContext->timeout);
- + if (status) {
- + /* Timeout - |nfs41_downcall()| will free |entry|+contents */
- + goto out;
- + }
- +
- + if (entry->psec_ctx == &entry->sec_ctx) {
- + SeDeleteClientSecurity(entry->psec_ctx);
- + }
- + entry->psec_ctx = NULL;
- +
- + if (!entry->status) {
- + DbgP("nfs41_QueryAllocatedRanges: SUCCESS\n");
- + RxContext->CurrentIrp->IoStatus.Status = STATUS_SUCCESS;
- + RxContext->IoStatusBlock.Information =
- + (ULONG_PTR)entry->u.QueryAllocatedRanges.returned_size;
- + }
- + else {
- + DbgP("nfs41_QueryAllocatedRanges: "
- + "FAILURE, entry->status=0x%lx\n", entry->status);
- + status = map_setfile_error(entry->status);
- + RxContext->CurrentIrp->IoStatus.Status = status;
- + RxContext->IoStatusBlock.Information = 0;
- + }
- +
- +out_free:
- + if (entry) {
- + if (entry->u.QueryAllocatedRanges.BufferMdl) {
- + MmUnlockPages(entry->u.QueryAllocatedRanges.BufferMdl);
- + IoFreeMdl(entry->u.QueryAllocatedRanges.BufferMdl);
- + entry->u.QueryAllocatedRanges.BufferMdl = NULL;
- + }
- - status = STATUS_SUCCESS;
- -#endif /* NFS41SYS_FSCTL_QUERY_ALLOCATED_RANGES_PLACEHOLDER_DUMMY_IMPL */
- + nfs41_UpcallDestroy(entry);
- + }
- out:
- DbgEx();
- return status;
- }
- +NTSTATUS marshal_nfs41_queryallocatedranges(
- + nfs41_updowncall_entry *entry,
- + unsigned char *buf,
- + ULONG buf_len,
- + ULONG *len)
- +{
- + NTSTATUS status = STATUS_SUCCESS;
- + ULONG header_len = 0;
- + unsigned char *tmp = buf;
- +
- + status = marshal_nfs41_header(entry, tmp, buf_len, len);
- + if (status) goto out;
- + else tmp += *len;
- +
- + header_len = *len + sizeof(FILE_ALLOCATED_RANGE_BUFFER) +
- + sizeof(LONGLONG) +
- + sizeof(HANDLE);
- + if (header_len > buf_len) {
- + status = STATUS_INSUFFICIENT_RESOURCES;
- + goto out;
- + }
- +
- + RtlCopyMemory(tmp, &entry->u.QueryAllocatedRanges.inrange,
- + sizeof(entry->u.QueryAllocatedRanges.inrange));
- + tmp += sizeof(entry->u.QueryAllocatedRanges.inrange);
- + RtlCopyMemory(tmp, &entry->u.QueryAllocatedRanges.BufferSize,
- + sizeof(entry->u.QueryAllocatedRanges.BufferSize));
- + tmp += sizeof(entry->u.QueryAllocatedRanges.BufferSize);
- +
- + __try {
- + if (entry->u.QueryAllocatedRanges.BufferMdl) {
- + entry->u.QueryAllocatedRanges.Buffer =
- + MmMapLockedPagesSpecifyCache(
- + entry->u.QueryAllocatedRanges.BufferMdl,
- + UserMode, MmCached, NULL, FALSE,
- + NormalPagePriority|MdlMappingNoExecute);
- + if (entry->u.QueryAllocatedRanges.Buffer == NULL) {
- + print_error("marshal_nfs41_queryallocatedranges: "
- + "MmMapLockedPagesSpecifyCache() failed to "
- + "map pages\n");
- + status = STATUS_INSUFFICIENT_RESOURCES;
- + goto out;
- + }
- + }
- + } __except(EXCEPTION_EXECUTE_HANDLER) {
- + print_error("marshal_nfs41_queryallocatedranges: Call to "
- + "MmMapLockedPagesSpecifyCache() failed "
- + "due to exception 0x%lx\n", (long)GetExceptionCode());
- + status = STATUS_ACCESS_VIOLATION;
- + goto out;
- + }
- + RtlCopyMemory(tmp, &entry->u.QueryAllocatedRanges.Buffer,
- + sizeof(HANDLE));
- + *len = header_len;
- +
- + DbgP("marshal_nfs41_queryallocatedranges: name='%wZ' "
- + "buffersize=0x%ld, buffer=0x%p\n",
- + entry->filename,
- + (long)entry->u.QueryAllocatedRanges.BufferSize,
- + (void *)entry->u.QueryAllocatedRanges.Buffer);
- +out:
- + return status;
- +}
- +
- +NTSTATUS unmarshal_nfs41_queryallocatedranges(
- + nfs41_updowncall_entry *cur,
- + unsigned char **buf)
- +{
- + NTSTATUS status = STATUS_SUCCESS;
- +
- + __try {
- + if (cur->u.QueryAllocatedRanges.Buffer)
- + MmUnmapLockedPages(
- + cur->u.QueryAllocatedRanges.Buffer,
- + cur->u.QueryAllocatedRanges.BufferMdl);
- + } __except(EXCEPTION_EXECUTE_HANDLER) {
- + print_error("unmarshal_nfs41_queryallocatedranges: "
- + "MmUnmapLockedPages thrown exception=0x%lx\n",
- + (long)GetExceptionCode());
- + status = cur->status = STATUS_ACCESS_VIOLATION;
- + goto out;
- + }
- +
- + RtlCopyMemory(&cur->u.QueryAllocatedRanges.returned_size,
- + *buf, sizeof(ULONG));
- + *buf += sizeof(ULONG);
- +
- + DbgP("unmarshal_nfs41_queryallocatedranges: "
- + "queryallocatedranges.returned_size=%llu\n",
- + cur->u.QueryAllocatedRanges.returned_size);
- +
- +out:
- + return status;
- +}
- +
- NTSTATUS nfs41_FsCtl(
- IN OUT PRX_CONTEXT RxContext)
- {
- diff --git a/sys/nfs41sys_updowncall.c b/sys/nfs41sys_updowncall.c
- index 0f2afa6..5d1d259 100644
- --- a/sys/nfs41sys_updowncall.c
- +++ b/sys/nfs41sys_updowncall.c
- @@ -302,6 +302,10 @@ NTSTATUS handle_upcall(
- case NFS41_SYSOP_ACL_SET:
- status = marshal_nfs41_setacl(entry, pbOut, cbOut, len);
- break;
- + case NFS41_SYSOP_FSCTL_QUERYALLOCATEDRANGES:
- + status = marshal_nfs41_queryallocatedranges(entry,
- + pbOut, cbOut, len);
- + break;
- default:
- status = STATUS_INVALID_PARAMETER;
- print_error("Unknown nfs41 ops %d\n", entry->opcode);
- @@ -598,6 +602,15 @@ NTSTATUS nfs41_downcall(
- IoFreeMdl(cur->u.Open.EaMdl);
- }
- break;
- + case NFS41_SYSOP_FSCTL_QUERYALLOCATEDRANGES:
- + if (cur->u.QueryAllocatedRanges.BufferMdl) {
- + MmUnmapLockedPages(
- + cur->u.QueryAllocatedRanges.Buffer,
- + cur->u.QueryAllocatedRanges.BufferMdl);
- + IoFreeMdl(cur->u.QueryAllocatedRanges.BufferMdl);
- + cur->u.QueryAllocatedRanges.BufferMdl = NULL;
- + }
- + break;
- }
- ExReleaseFastMutex(&cur->lock);
- nfs41_RemoveEntry(downcallLock, cur);
- @@ -651,6 +664,9 @@ NTSTATUS nfs41_downcall(
- case NFS41_SYSOP_ACL_SET:
- unmarshal_nfs41_setattr(cur, &cur->ChangeTime, &buf);
- break;
- + case NFS41_SYSOP_FSCTL_QUERYALLOCATEDRANGES:
- + unmarshal_nfs41_queryallocatedranges(cur, &buf);
- + break;
- }
- }
- ExReleaseFastMutex(&cur->lock);
- --
- 2.45.1
msnfs41client: Patch to implement upcall/downcall for |FSCTL_QUERY_ALLOCATED_RANGES|, 2025-02-25
Posted by Anonymous on Wed 12th Feb 2025 17:13
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.