pastebin - collaborative debugging tool
rovema.kpaste.net RSS


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

  1. From fbd361997908b180d03a266b8135ad35c17a208a Mon Sep 17 00:00:00 2001
  2. From: Roland Mainz <roland.mainz@nrubsig.org>
  3. Date: Wed, 12 Feb 2025 17:58:13 +0100
  4. Subject: [PATCH] build.vc19,daemon,include,sys: Add upcall/downcall for
  5.  |FSCTL_QUERY_ALLOCATED_RANGES|
  6.  
  7. Add upcall/downcall for |FSCTL_QUERY_ALLOCATED_RANGES|.
  8.  
  9. Note: The dummy implementation in |handle_queryallocatedranges()|
  10. currently only returns one |FILE_ALLOCATED_RANGE_BUFFER| with
  11. { 0, filesize } (e.g. this means the file only contains data and no
  12. holes), and needs to be replaced with a function which uses
  13. NFSv4.2 SEEK to implement |FSCTL_QUERY_ALLOCATED_RANGES|
  14. correctly.
  15.  
  16. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  17. ---
  18. build.vc19/nfsd/nfsd.vcxproj         |   1 +
  19.  build.vc19/nfsd/nfsd.vcxproj.filters |   3 +
  20.  daemon/daemon_debug.c                |   1 +
  21.  daemon/fsctl.c                       | 118 ++++++++++++++++
  22.  daemon/upcall.c                      |   2 +
  23.  daemon/upcall.h                      |   9 ++
  24.  include/from_kernel.h                |  13 ++
  25.  include/nfs41_driver.h               |   1 +
  26.  sys/nfs41sys_debug.c                 |   1 +
  27.  sys/nfs41sys_driver.h                |  17 ++-
  28.  sys/nfs41sys_fsctl.c                 | 204 +++++++++++++++++++++++----
  29.  sys/nfs41sys_updowncall.c            |  16 +++
  30.  12 files changed, 354 insertions(+), 32 deletions(-)
  31.  create mode 100644 daemon/fsctl.c
  32.  
  33. diff --git a/build.vc19/nfsd/nfsd.vcxproj b/build.vc19/nfsd/nfsd.vcxproj
  34. index 3005f90..85ab083 100644
  35. --- a/build.vc19/nfsd/nfsd.vcxproj
  36. +++ b/build.vc19/nfsd/nfsd.vcxproj
  37. @@ -290,6 +290,7 @@
  38.      <ClCompile Include="..\..\daemon\delegation.c" />
  39.      <ClCompile Include="..\..\daemon\ea.c" />
  40.      <ClCompile Include="..\..\daemon\fileinfoutil.c" />
  41. +    <ClCompile Include="..\..\daemon\fsctl.c" />
  42.      <ClCompile Include="..\..\daemon\getattr.c" />
  43.      <ClCompile Include="..\..\daemon\idmap.c" />
  44.      <ClCompile Include="..\..\daemon\idmap_cygwin.c" />
  45. diff --git a/build.vc19/nfsd/nfsd.vcxproj.filters b/build.vc19/nfsd/nfsd.vcxproj.filters
  46. index 5190a8e..61891d6 100644
  47. --- a/build.vc19/nfsd/nfsd.vcxproj.filters
  48. +++ b/build.vc19/nfsd/nfsd.vcxproj.filters
  49. @@ -39,6 +39,9 @@
  50.      <ClCompile Include="..\..\daemon\fileinfoutil.c">
  51.        <Filter>Source Files</Filter>
  52.      </ClCompile>
  53. +    <ClCompile Include="..\..\daemon\fsctl.c">
  54. +      <Filter>Source Files</Filter>
  55. +    </ClCompile>
  56.      <ClCompile Include="..\..\daemon\getattr.c">
  57.        <Filter>Source Files</Filter>
  58.      </ClCompile>
  59. diff --git a/daemon/daemon_debug.c b/daemon/daemon_debug.c
  60. index f8f7d2e..5ca7427 100644
  61. --- a/daemon/daemon_debug.c
  62. +++ b/daemon/daemon_debug.c
  63. @@ -466,6 +466,7 @@ const char* opcode2string(nfs41_opcodes opcode)
  64.          NFSOPCODE_TO_STRLITERAL(NFS41_SYSOP_VOLUME_QUERY)
  65.          NFSOPCODE_TO_STRLITERAL(NFS41_SYSOP_ACL_QUERY)
  66.          NFSOPCODE_TO_STRLITERAL(NFS41_SYSOP_ACL_SET)
  67. +        NFSOPCODE_TO_STRLITERAL(NFS41_SYSOP_FSCTL_QUERYALLOCATEDRANGES)
  68.          NFSOPCODE_TO_STRLITERAL(NFS41_SYSOP_INVALID_OPCODE1)
  69.          default: break;
  70.      }
  71. diff --git a/daemon/fsctl.c b/daemon/fsctl.c
  72. new file mode 100644
  73. index 0000000..2eb85ee
  74. --- /dev/null
  75. +++ b/daemon/fsctl.c
  76. @@ -0,0 +1,118 @@
  77. +/* NFSv4.1 client for Windows
  78. + * Copyright (C) 2024-2025 Roland Mainz <roland.mainz@nrubsig.org>
  79. + *
  80. + * Roland Mainz <roland.mainz@nrubsig.org>
  81. + *
  82. + * This library is free software; you can redistribute it and/or modify it
  83. + * under the terms of the GNU Lesser General Public License as published by
  84. + * the Free Software Foundation; either version 2.1 of the License, or (at
  85. + * your option) any later version.
  86. + *
  87. + * This library is distributed in the hope that it will be useful, but
  88. + * without any warranty; without even the implied warranty of merchantability
  89. + * or fitness for a particular purpose.  See the GNU Lesser General Public
  90. + * License for more details.
  91. + *
  92. + * You should have received a copy of the GNU Lesser General Public License
  93. + * along with this library; if not, write to the Free Software Foundation,
  94. + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  95. + */
  96. +
  97. +#include <Windows.h>
  98. +#include <stdio.h>
  99. +
  100. +#include "nfs41_ops.h"
  101. +#include "name_cache.h"
  102. +#include "upcall.h"
  103. +#include "daemon_debug.h"
  104. +#include "util.h"
  105. +
  106. +static int parse_queryallocatedranges(unsigned char *buffer,
  107. +    uint32_t length, nfs41_upcall *upcall)
  108. +{
  109. +    int status;
  110. +    queryallocatedranges_upcall_args *args = &upcall->args.queryallocatedranges;
  111. +
  112. +    status = safe_read(&buffer, &length, &args->inrange, sizeof(args->inrange));
  113. +    if (status) goto out;
  114. +    status = safe_read(&buffer, &length, &args->outbuffersize, sizeof(args->outbuffersize));
  115. +    if (status) goto out;
  116. +    status = safe_read(&buffer, &length, &args->outbuffer, sizeof(args->outbuffer));
  117. +    if (status) goto out;
  118. +
  119. +    DPRINTF(0, ("parse_queryallocatedranges: "
  120. +        "parsing '%s' inrange=(FileOffset=%lld Length=%lld) "
  121. +        "outbuffersize=%lu outbuffer=0x%p\n",
  122. +        opcode2string(upcall->opcode),
  123. +        args->inrange.FileOffset.QuadPart,
  124. +        args->inrange.Length.QuadPart,
  125. +        (unsigned long)args->outbuffersize,
  126. +        (void *)args->outbuffer));
  127. +out:
  128. +    return status;
  129. +}
  130. +
  131. +
  132. +static int handle_queryallocatedranges(void *daemon_context, nfs41_upcall *upcall)
  133. +{
  134. +    queryallocatedranges_upcall_args *args =
  135. +        &upcall->args.queryallocatedranges;
  136. +    nfs41_open_state *state = upcall->state_ref;
  137. +    PFILE_ALLOCATED_RANGE_BUFFER outbuffer =
  138. +        (PFILE_ALLOCATED_RANGE_BUFFER)args->outbuffer;
  139. +    int status = ERROR_INVALID_PARAMETER;
  140. +    nfs41_file_info info;
  141. +
  142. +    DPRINTF(0,
  143. +        ("--> handle_queryallocatedranges("
  144. +            "state->path.path='%s')\n",
  145. +            state->path.path));
  146. +
  147. +    DPRINTF(0,
  148. +        ("handle_queryallocatedranges:"
  149. +            "got space for %ld records\n",
  150. +            (int)((size_t)args->outbuffersize / sizeof(FILE_ALLOCATED_RANGE_BUFFER))));
  151. +
  152. +    args->returned_size = 0;
  153. +
  154. +    (void)memset(&info, 0, sizeof(info));
  155. +
  156. +    status = nfs41_cached_getattr(state->session,
  157. +        &state->file, &info);
  158. +    if (status)
  159. +        goto out;
  160. +
  161. +    if (args->outbuffersize < (1*sizeof(FILE_ALLOCATED_RANGE_BUFFER))) {
  162. +        /* FIXME: We should return the size of the required buffer */
  163. +        status = ERROR_INSUFFICIENT_BUFFER;
  164. +        goto out;
  165. +    }
  166. +
  167. +    /* return size of file */
  168. +    outbuffer[0].FileOffset.QuadPart = 0;
  169. +    outbuffer[0].Length.QuadPart = info.size;
  170. +    args->returned_size = 1*sizeof(FILE_ALLOCATED_RANGE_BUFFER);
  171. +    status = NO_ERROR;
  172. +
  173. +out:
  174. +    DPRINTF(0, ("<-- handle_queryallocatedranges(), status=0x%lx\n", status));
  175. +    return status;
  176. +}
  177. +
  178. +static int marshall_queryallocatedranges(unsigned char *buffer,
  179. +    uint32_t *length, nfs41_upcall *upcall)
  180. +{
  181. +    int status;
  182. +    queryallocatedranges_upcall_args *args = &upcall->args.queryallocatedranges;
  183. +
  184. +    status = safe_write(&buffer, length, &args->returned_size, sizeof(args->returned_size));
  185. +
  186. +    return status;
  187. +}
  188. +
  189. +const nfs41_upcall_op nfs41_op_queryallocatedranges = {
  190. +    .parse = parse_queryallocatedranges,
  191. +    .handle = handle_queryallocatedranges,
  192. +    .marshall = marshall_queryallocatedranges,
  193. +    .arg_size = sizeof(queryallocatedranges_upcall_args)
  194. +};
  195. diff --git a/daemon/upcall.c b/daemon/upcall.c
  196. index 11863cb..f6216fc 100644
  197. --- a/daemon/upcall.c
  198. +++ b/daemon/upcall.c
  199. @@ -49,6 +49,7 @@ extern const nfs41_upcall_op nfs41_op_symlink_set;
  200.  extern const nfs41_upcall_op nfs41_op_volume;
  201.  extern const nfs41_upcall_op nfs41_op_getacl;
  202.  extern const nfs41_upcall_op nfs41_op_setacl;
  203. +extern const nfs41_upcall_op nfs41_op_queryallocatedranges;
  204.  
  205.  /* |_nfs41_opcodes| and |g_upcall_op_table| must be in sync! */
  206.  static const nfs41_upcall_op *g_upcall_op_table[] = {
  207. @@ -72,6 +73,7 @@ static const nfs41_upcall_op *g_upcall_op_table[] = {
  208.      &nfs41_op_volume,
  209.      &nfs41_op_getacl,
  210.      &nfs41_op_setacl,
  211. +    &nfs41_op_queryallocatedranges,
  212.      NULL,
  213.      NULL
  214.  };
  215. diff --git a/daemon/upcall.h b/daemon/upcall.h
  216. index e2ba48f..2fe50ba 100644
  217. --- a/daemon/upcall.h
  218. +++ b/daemon/upcall.h
  219. @@ -190,6 +190,14 @@ typedef struct __setacl_upcall_args {
  220.      ULONGLONG ctime;
  221.  } setacl_upcall_args;
  222.  
  223. +typedef struct __queryallocatedranges_upcall_args {
  224. +    FILE_ALLOCATED_RANGE_BUFFER     inrange;
  225. +    HANDLE                          outbuffer;
  226. +    ULONG                           outbuffersize;
  227. +    ULONG                           returned_size;
  228. +} queryallocatedranges_upcall_args;
  229. +
  230. +
  231.  typedef union __upcall_args {
  232.      mount_upcall_args       mount;
  233.      open_upcall_args        open;
  234. @@ -206,6 +214,7 @@ typedef union __upcall_args {
  235.      volume_upcall_args      volume;
  236.      getacl_upcall_args      getacl;
  237.      setacl_upcall_args      setacl;
  238. +    queryallocatedranges_upcall_args queryallocatedranges;
  239.  } upcall_args;
  240.  
  241.  typedef enum _nfs41_opcodes nfs41_opcodes;
  242. diff --git a/include/from_kernel.h b/include/from_kernel.h
  243. index 85cacce..8b9ddc0 100644
  244. --- a/include/from_kernel.h
  245. +++ b/include/from_kernel.h
  246. @@ -439,4 +439,17 @@ typedef struct _FILE_FS_SECTOR_SIZE_INFORMATION {
  247.  typedef struct _FILE_INTERNAL_INFORMATION {
  248.      LARGE_INTEGER IndexNumber;
  249.  } FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION;
  250. +
  251. +/*
  252. + * |FILE_ALLOCATED_RANGE_BUFFER| - test for
  253. + * /usr/i686-w64-mingw32/sys-root/mingw/include/winioctl.h header
  254. + * to avoid type redefinition warnings
  255. + */
  256. +#ifndef _WINIOCTL_
  257. +typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
  258. +    LARGE_INTEGER FileOffset;
  259. +    LARGE_INTEGER Length;
  260. +} FILE_ALLOCATED_RANGE_BUFFER, *PFILE_ALLOCATED_RANGE_BUFFER;
  261. +#endif /* _WINIOCTL_ */
  262. +
  263.  #endif
  264. diff --git a/include/nfs41_driver.h b/include/nfs41_driver.h
  265. index dde47af..403bf04 100644
  266. --- a/include/nfs41_driver.h
  267. +++ b/include/nfs41_driver.h
  268. @@ -82,6 +82,7 @@ typedef enum _nfs41_opcodes {
  269.      NFS41_SYSOP_VOLUME_QUERY,
  270.      NFS41_SYSOP_ACL_QUERY,
  271.      NFS41_SYSOP_ACL_SET,
  272. +    NFS41_SYSOP_FSCTL_QUERYALLOCATEDRANGES,
  273.      NFS41_SYSOP_SHUTDOWN,
  274.      NFS41_SYSOP_INVALID_OPCODE1
  275.  } nfs41_opcodes;
  276. diff --git a/sys/nfs41sys_debug.c b/sys/nfs41sys_debug.c
  277. index 33b801c..dccd933 100644
  278. --- a/sys/nfs41sys_debug.c
  279. +++ b/sys/nfs41sys_debug.c
  280. @@ -677,6 +677,7 @@ const char *opcode2string(int opcode)
  281.      case NFS41_SYSOP_VOLUME_QUERY: return "NFS41_SYSOP_VOLUME_QUERY";
  282.      case NFS41_SYSOP_ACL_QUERY: return "NFS41_SYSOP_ACL_QUERY";
  283.      case NFS41_SYSOP_ACL_SET: return "NFS41_SYSOP_ACL_SET";
  284. +    case NFS41_SYSOP_FSCTL_QUERYALLOCATEDRANGES: return "NFS41_SYSOP_FSCTL_QUERYALLOCATEDRANGES";
  285.      default: return "UNKNOWN";
  286.      }
  287.  }
  288. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  289. index 762e832..7fccf69 100644
  290. --- a/sys/nfs41sys_driver.h
  291. +++ b/sys/nfs41sys_driver.h
  292. @@ -1,6 +1,6 @@
  293.  /* NFSv4.1 client for Windows
  294.   * Copyright (C) 2012 The Regents of the University of Michigan
  295. - * Copyright (C) 2023-2024 Roland Mainz <roland.mainz@nrubsig.org>
  296. + * Copyright (C) 2023-2025 Roland Mainz <roland.mainz@nrubsig.org>
  297.   *
  298.   * Olga Kornievskaia <aglo@umich.edu>
  299.   * Casey Bodley <cbodley@umich.edu>
  300. @@ -269,6 +269,13 @@ typedef struct _updowncall_entry {
  301.          struct {
  302.              SECURITY_INFORMATION query;
  303.          } Acl;
  304. +        struct {
  305. +            FILE_ALLOCATED_RANGE_BUFFER inrange;
  306. +            PMDL BufferMdl;
  307. +            ULONG BufferSize;
  308. +            PVOID Buffer;
  309. +            LONGLONG returned_size;
  310. +        } QueryAllocatedRanges;
  311.      } u;
  312.  
  313.  } nfs41_updowncall_entry;
  314. @@ -635,6 +642,14 @@ NTSTATUS nfs41_QueryEaInformation(
  315.  /* nfs41sys_fsctl.c */
  316.  NTSTATUS nfs41_FsCtl(
  317.      IN OUT PRX_CONTEXT RxContext);
  318. +NTSTATUS marshal_nfs41_queryallocatedranges(
  319. +    nfs41_updowncall_entry *entry,
  320. +    unsigned char *buf,
  321. +    ULONG buf_len,
  322. +    ULONG *len);
  323. +NTSTATUS unmarshal_nfs41_queryallocatedranges(
  324. +    nfs41_updowncall_entry *cur,
  325. +    unsigned char **buf);
  326.  
  327.  /* nfs41sys_ioctl.c */
  328.  NTSTATUS nfs41_IoCtl(
  329. diff --git a/sys/nfs41sys_fsctl.c b/sys/nfs41sys_fsctl.c
  330. index 2937d8c..ee4c186 100644
  331. --- a/sys/nfs41sys_fsctl.c
  332. +++ b/sys/nfs41sys_fsctl.c
  333. @@ -1,6 +1,6 @@
  334.  /* NFSv4.1 client for Windows
  335.   * Copyright (C) 2012 The Regents of the University of Michigan
  336. - * Copyright (C) 2023-2024 Roland Mainz <roland.mainz@nrubsig.org>
  337. + * Copyright (C) 2023-2025 Roland Mainz <roland.mainz@nrubsig.org>
  338.   *
  339.   * Olga Kornievskaia <aglo@umich.edu>
  340.   * Casey Bodley <cbodley@umich.edu>
  341. @@ -105,14 +105,20 @@ NTSTATUS nfs41_QueryAllocatedRanges(
  342.      IN OUT PRX_CONTEXT RxContext)
  343.  {
  344.      NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
  345. +    nfs41_updowncall_entry *entry = NULL;
  346. +    __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  347. +    __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  348. +        NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  349. +    __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  350. +        NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
  351.      __notnull XXCTL_LOWIO_COMPONENT *FsCtl =
  352.          &RxContext->LowIoContext.ParamsFor.FsCtl;
  353.      __notnull PFILE_ALLOCATED_RANGE_BUFFER in_range_buffer =
  354.          (PFILE_ALLOCATED_RANGE_BUFFER)FsCtl->pInputBuffer;
  355.      __notnull PFILE_ALLOCATED_RANGE_BUFFER out_range_buffer =
  356.          (PFILE_ALLOCATED_RANGE_BUFFER)FsCtl->pOutputBuffer;
  357. -    __notnull PNFS41_FCB nfs41_fcb =
  358. -        NFS41GetFcbExtension(RxContext->pFcb);
  359. +    ULONG out_range_buffer_len = FsCtl->OutputBufferLength;
  360. +    __notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
  361.  
  362.      DbgEn();
  363.  
  364. @@ -130,49 +136,185 @@ NTSTATUS nfs41_QueryAllocatedRanges(
  365.          goto out;
  366.      }
  367.  
  368. -/*
  369. - * FIXME: For now we implement |FSCTL_QUERY_ALLOCATED_RANGES| using
  370. - * a dummy implementation which just returns { 0, filesize }
  371. - * so we can do testing with Cygwin >= 3.6.x
  372. - * |lseek(..., SEEK_HOLE/SEEK_DATA, ...)| and
  373. - * Windows $ fsutil sparse queryrange mysparsefile.txt #.
  374. - *
  375. - * We really need an upcall which issues NFSv4.2 SEEK to enumerate the
  376. - * data/hole sections and fill an array of
  377. - * |FILE_ALLOCATED_RANGE_BUFFER|s with the positions of tha SEEK_DATA
  378. - * results.
  379. - */
  380. -#define NFS41SYS_FSCTL_QUERY_ALLOCATED_RANGES_PLACEHOLDER_DUMMY_IMPL 1
  381. -
  382. -#ifdef NFS41SYS_FSCTL_QUERY_ALLOCATED_RANGES_PLACEHOLDER_DUMMY_IMPL
  383. -    DbgP("nfs41_QueryAllocatedRanges: "
  384. +    DbgP("nfs41_QueryAllocatedRanges/REAL: "
  385.          "in_range_buffer=(FileOffset=%lld,Length=%lld)\n",
  386.          (long long)in_range_buffer->FileOffset.QuadPart,
  387.          (long long)in_range_buffer->Length.QuadPart);
  388.  
  389. -    if (FsCtl->OutputBufferLength <
  390. -        (1*sizeof(FILE_ALLOCATED_RANGE_BUFFER))) {
  391. -        DbgP("nfs41_QueryAllocatedRanges: "
  392. -            "FsCtl->OutputBufferLength too small\n");
  393. -        status = STATUS_BUFFER_TOO_SMALL;
  394. +    status = nfs41_UpcallCreate(NFS41_SYSOP_FSCTL_QUERYALLOCATEDRANGES,
  395. +        &nfs41_fobx->sec_ctx,
  396. +        pVNetRootContext->session,
  397. +        nfs41_fobx->nfs41_open_state,
  398. +        pNetRootContext->nfs41d_version,
  399. +        SrvOpen->pAlreadyPrefixedName,
  400. +        &entry);
  401. +
  402. +    if (status)
  403.          goto out;
  404. +
  405. +    entry->u.QueryAllocatedRanges.inrange = *in_range_buffer;
  406. +    entry->u.QueryAllocatedRanges.BufferSize = out_range_buffer_len;
  407. +
  408. +    /* lock the buffer for write access in user space */
  409. +    entry->u.QueryAllocatedRanges.BufferMdl = IoAllocateMdl(
  410. +        out_range_buffer,
  411. +        out_range_buffer_len,
  412. +        FALSE, FALSE, NULL);
  413. +    if (entry->u.QueryAllocatedRanges.BufferMdl == NULL) {
  414. +        status = STATUS_INTERNAL_ERROR;
  415. +        DbgP("nfs41_QueryAllocatedRanges: IoAllocateMdl() failed\n");
  416. +        goto out_free;
  417.      }
  418.  
  419. -    out_range_buffer->FileOffset.QuadPart = 0;
  420. -    out_range_buffer->Length.QuadPart =
  421. -        nfs41_fcb->StandardInfo.EndOfFile.QuadPart;
  422. +#pragma warning( push )
  423. +/*
  424. + * C28145: "The opaque MDL structure should not be modified by a
  425. + * driver.", |MDL_MAPPING_CAN_FAIL| is the exception
  426. + */
  427. +#pragma warning (disable : 28145)
  428. +    entry->u.QueryAllocatedRanges.BufferMdl->MdlFlags |=
  429. +        MDL_MAPPING_CAN_FAIL;
  430. +#pragma warning( pop )
  431. +    MmProbeAndLockPages(entry->u.QueryAllocatedRanges.BufferMdl,
  432. +        KernelMode,
  433. +        IoModifyAccess);
  434.  
  435. -    RxContext->IoStatusBlock.Information =
  436. -        (ULONG_PTR)1*sizeof(FILE_ALLOCATED_RANGE_BUFFER);
  437. +    status = nfs41_UpcallWaitForReply(entry, pVNetRootContext->timeout);
  438. +    if (status) {
  439. +        /* Timeout - |nfs41_downcall()| will free |entry|+contents */
  440. +        goto out;
  441. +    }
  442. +
  443. +    if (entry->psec_ctx == &entry->sec_ctx) {
  444. +        SeDeleteClientSecurity(entry->psec_ctx);
  445. +    }
  446. +    entry->psec_ctx = NULL;
  447. +
  448. +    if (!entry->status) {
  449. +        DbgP("nfs41_QueryAllocatedRanges: SUCCESS\n");
  450. +        RxContext->CurrentIrp->IoStatus.Status = STATUS_SUCCESS;
  451. +        RxContext->IoStatusBlock.Information =
  452. +            (ULONG_PTR)entry->u.QueryAllocatedRanges.returned_size;
  453. +    }
  454. +    else {
  455. +        DbgP("nfs41_QueryAllocatedRanges: "
  456. +            "FAILURE, entry->status=0x%lx\n", entry->status);
  457. +        status = map_setfile_error(entry->status);
  458. +        RxContext->CurrentIrp->IoStatus.Status = status;
  459. +        RxContext->IoStatusBlock.Information = 0;
  460. +    }
  461. +
  462. +out_free:
  463. +    if (entry) {
  464. +        if (entry->u.QueryAllocatedRanges.BufferMdl) {
  465. +            MmUnlockPages(entry->u.QueryAllocatedRanges.BufferMdl);
  466. +            IoFreeMdl(entry->u.QueryAllocatedRanges.BufferMdl);
  467. +            entry->u.QueryAllocatedRanges.BufferMdl = NULL;
  468. +        }
  469.  
  470. -    status = STATUS_SUCCESS;
  471. -#endif /* NFS41SYS_FSCTL_QUERY_ALLOCATED_RANGES_PLACEHOLDER_DUMMY_IMPL */
  472. +        nfs41_UpcallDestroy(entry);
  473. +    }
  474.  
  475.  out:
  476.      DbgEx();
  477.      return status;
  478.  }
  479.  
  480. +NTSTATUS marshal_nfs41_queryallocatedranges(
  481. +    nfs41_updowncall_entry *entry,
  482. +    unsigned char *buf,
  483. +    ULONG buf_len,
  484. +    ULONG *len)
  485. +{
  486. +    NTSTATUS status = STATUS_SUCCESS;
  487. +    ULONG header_len = 0;
  488. +    unsigned char *tmp = buf;
  489. +
  490. +    status = marshal_nfs41_header(entry, tmp, buf_len, len);
  491. +    if (status) goto out;
  492. +    else tmp += *len;
  493. +
  494. +    header_len = *len + sizeof(FILE_ALLOCATED_RANGE_BUFFER) +
  495. +        sizeof(LONGLONG) +
  496. +        sizeof(HANDLE);
  497. +    if (header_len > buf_len) {
  498. +        status = STATUS_INSUFFICIENT_RESOURCES;
  499. +        goto out;
  500. +    }
  501. +
  502. +    RtlCopyMemory(tmp, &entry->u.QueryAllocatedRanges.inrange,
  503. +        sizeof(entry->u.QueryAllocatedRanges.inrange));
  504. +    tmp += sizeof(entry->u.QueryAllocatedRanges.inrange);
  505. +    RtlCopyMemory(tmp, &entry->u.QueryAllocatedRanges.BufferSize,
  506. +        sizeof(entry->u.QueryAllocatedRanges.BufferSize));
  507. +    tmp += sizeof(entry->u.QueryAllocatedRanges.BufferSize);
  508. +
  509. +    __try {
  510. +        if (entry->u.QueryAllocatedRanges.BufferMdl) {
  511. +            entry->u.QueryAllocatedRanges.Buffer =
  512. +                MmMapLockedPagesSpecifyCache(
  513. +                    entry->u.QueryAllocatedRanges.BufferMdl,
  514. +                    UserMode, MmCached, NULL, FALSE,
  515. +                    NormalPagePriority|MdlMappingNoExecute);
  516. +            if (entry->u.QueryAllocatedRanges.Buffer == NULL) {
  517. +                print_error("marshal_nfs41_queryallocatedranges: "
  518. +                    "MmMapLockedPagesSpecifyCache() failed to "
  519. +                    "map pages\n");
  520. +                status = STATUS_INSUFFICIENT_RESOURCES;
  521. +                goto out;
  522. +            }
  523. +        }
  524. +    } __except(EXCEPTION_EXECUTE_HANDLER) {
  525. +        print_error("marshal_nfs41_queryallocatedranges: Call to "
  526. +            "MmMapLockedPagesSpecifyCache() failed "
  527. +            "due to exception 0x%lx\n", (long)GetExceptionCode());
  528. +        status = STATUS_ACCESS_VIOLATION;
  529. +        goto out;
  530. +    }
  531. +    RtlCopyMemory(tmp, &entry->u.QueryAllocatedRanges.Buffer,
  532. +        sizeof(HANDLE));
  533. +    *len = header_len;
  534. +
  535. +    DbgP("marshal_nfs41_queryallocatedranges: name='%wZ' "
  536. +        "buffersize=0x%ld, buffer=0x%p\n",
  537. +         entry->filename,
  538. +         (long)entry->u.QueryAllocatedRanges.BufferSize,
  539. +         (void *)entry->u.QueryAllocatedRanges.Buffer);
  540. +out:
  541. +    return status;
  542. +}
  543. +
  544. +NTSTATUS unmarshal_nfs41_queryallocatedranges(
  545. +    nfs41_updowncall_entry *cur,
  546. +    unsigned char **buf)
  547. +{
  548. +    NTSTATUS status = STATUS_SUCCESS;
  549. +
  550. +    __try {
  551. +        if (cur->u.QueryAllocatedRanges.Buffer)
  552. +            MmUnmapLockedPages(
  553. +                cur->u.QueryAllocatedRanges.Buffer,
  554. +                cur->u.QueryAllocatedRanges.BufferMdl);
  555. +    } __except(EXCEPTION_EXECUTE_HANDLER) {
  556. +        print_error("unmarshal_nfs41_queryallocatedranges: "
  557. +            "MmUnmapLockedPages thrown exception=0x%lx\n",
  558. +            (long)GetExceptionCode());
  559. +        status = cur->status = STATUS_ACCESS_VIOLATION;
  560. +        goto out;
  561. +    }
  562. +
  563. +    RtlCopyMemory(&cur->u.QueryAllocatedRanges.returned_size,
  564. +        *buf, sizeof(ULONG));
  565. +    *buf += sizeof(ULONG);
  566. +
  567. +    DbgP("unmarshal_nfs41_queryallocatedranges: "
  568. +        "queryallocatedranges.returned_size=%llu\n",
  569. +        cur->u.QueryAllocatedRanges.returned_size);
  570. +
  571. +out:
  572. +    return status;
  573. +}
  574. +
  575.  NTSTATUS nfs41_FsCtl(
  576.      IN OUT PRX_CONTEXT RxContext)
  577.  {
  578. diff --git a/sys/nfs41sys_updowncall.c b/sys/nfs41sys_updowncall.c
  579. index 0f2afa6..5d1d259 100644
  580. --- a/sys/nfs41sys_updowncall.c
  581. +++ b/sys/nfs41sys_updowncall.c
  582. @@ -302,6 +302,10 @@ NTSTATUS handle_upcall(
  583.      case NFS41_SYSOP_ACL_SET:
  584.          status = marshal_nfs41_setacl(entry, pbOut, cbOut, len);
  585.          break;
  586. +    case NFS41_SYSOP_FSCTL_QUERYALLOCATEDRANGES:
  587. +        status = marshal_nfs41_queryallocatedranges(entry,
  588. +            pbOut, cbOut, len);
  589. +        break;
  590.      default:
  591.          status = STATUS_INVALID_PARAMETER;
  592.          print_error("Unknown nfs41 ops %d\n", entry->opcode);
  593. @@ -598,6 +602,15 @@ NTSTATUS nfs41_downcall(
  594.                  IoFreeMdl(cur->u.Open.EaMdl);
  595.              }
  596.              break;
  597. +        case NFS41_SYSOP_FSCTL_QUERYALLOCATEDRANGES:
  598. +            if (cur->u.QueryAllocatedRanges.BufferMdl) {
  599. +                MmUnmapLockedPages(
  600. +                    cur->u.QueryAllocatedRanges.Buffer,
  601. +                    cur->u.QueryAllocatedRanges.BufferMdl);
  602. +                IoFreeMdl(cur->u.QueryAllocatedRanges.BufferMdl);
  603. +                cur->u.QueryAllocatedRanges.BufferMdl = NULL;
  604. +            }
  605. +            break;
  606.          }
  607.          ExReleaseFastMutex(&cur->lock);
  608.          nfs41_RemoveEntry(downcallLock, cur);
  609. @@ -651,6 +664,9 @@ NTSTATUS nfs41_downcall(
  610.          case NFS41_SYSOP_ACL_SET:
  611.              unmarshal_nfs41_setattr(cur, &cur->ChangeTime, &buf);
  612.              break;
  613. +        case NFS41_SYSOP_FSCTL_QUERYALLOCATEDRANGES:
  614. +            unmarshal_nfs41_queryallocatedranges(cur, &buf);
  615. +            break;
  616.          }
  617.      }
  618.      ExReleaseFastMutex(&cur->lock);
  619. --
  620. 2.45.1

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.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at