pastebin - collaborative debugging tool
rovema.kpaste.net RSS


msnfs41client: 28 patches for Extended Create Parameter support, ACL fixes, SRV_OPEN collapsing support+misc, 2025-12-01
Posted by Anonymous on Mon 1st Dec 2025 12:16
raw | new post

  1. From d1a302baf4bdb79db3ebd3d0e49cfeff06931c64 Mon Sep 17 00:00:00 2001
  2. From: Roland Mainz <roland.mainz@nrubsig.org>
  3. Date: Tue, 18 Nov 2025 12:28:39 +0100
  4. Subject: [PATCH 01/28] daemon: |FATTR4_WORD2_MODE_SET_MASKED| uses both
  5.  |mode_mask| AND |mode|
  6.  
  7. |FATTR4_WORD2_MODE_SET_MASKED| uses both |mode_mask| AND |mode|
  8. of |nfs41_file_info|.
  9.  
  10. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  11. ---
  12. daemon/fileinfoutil.c | 1 +
  13.  daemon/nfs41_types.h  | 1 +
  14.  2 files changed, 2 insertions(+)
  15.  
  16. diff --git a/daemon/fileinfoutil.c b/daemon/fileinfoutil.c
  17. index 3466cfd..fe24b0a 100644
  18. --- a/daemon/fileinfoutil.c
  19. +++ b/daemon/fileinfoutil.c
  20. @@ -628,6 +628,7 @@ void nfs41_file_info_cpy(
  21.      }
  22.      if (attrmask->count > 2) {
  23.          if (attrmask->arr[2] & FATTR4_WORD2_MODE_SET_MASKED) {
  24. +            dest->mode = src->mode;
  25.              dest->mode_mask = src->mode_mask;
  26.          }
  27.          if (attrmask->arr[2] & FATTR4_WORD2_MDSTHRESHOLD) {
  28. diff --git a/daemon/nfs41_types.h b/daemon/nfs41_types.h
  29. index bded8db..6b1cf12 100644
  30. --- a/daemon/nfs41_types.h
  31. +++ b/daemon/nfs41_types.h
  32. @@ -216,6 +216,7 @@ typedef struct __nfs41_file_info {
  33.      uint32_t                numlinks;
  34.      uint32_t                rdattr_error;
  35.      uint32_t                mode;
  36. +    /* |FATTR4_WORD2_MODE_SET_MASKED| uses |mode| AND |mode_mask| */
  37.      uint32_t                mode_mask;
  38.      char                    *owner;
  39.      char                    *owner_group;
  40. --
  41. 2.51.0
  42.  
  43. From 8fcc72c1155e95bd1d0d453dc94f5cc132be7e4e Mon Sep 17 00:00:00 2001
  44. From: Roland Mainz <roland.mainz@nrubsig.org>
  45. Date: Tue, 18 Nov 2025 18:36:40 +0100
  46. Subject: [PATCH 02/28] daemon: Only toggle |FILE_ATTRIBUTE_READONLY| if
  47.  |FILE_ATTRIBUTE_NORMAL| is set
  48.  
  49. Only toggle |FILE_ATTRIBUTE_READONLY| if |FILE_ATTRIBUTE_NORMAL| is set,
  50. otherwise we can accidently stomp over valid mode bits.
  51.  
  52. This is actually what Windows Explorer does: It will set
  53. |FILE_ATTRIBUTE_NORMAL| when it wants to change flags like
  54. |FILE_ATTRIBUTE_READONLY|, |FILE_ATTRIBUTE_HIDDEN|,
  55. |FILE_ATTRIBUTE_SYSTEM|, or |FILE_ATTRIBUTE_ARCHIVE|, and
  56. keeps |FILE_BASIC_INFORMATION->FileAttributes == 0x0| if it
  57. does not wish to change any attributes.
  58.  
  59. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  60. ---
  61. daemon/setattr.c | 32 ++++++++++++++++++++++----------
  62.  1 file changed, 22 insertions(+), 10 deletions(-)
  63.  
  64. diff --git a/daemon/setattr.c b/daemon/setattr.c
  65. index 971b973..8c281e9 100644
  66. --- a/daemon/setattr.c
  67. +++ b/daemon/setattr.c
  68. @@ -101,6 +101,18 @@ static int handle_nfs41_setattr_basicinfo(void *daemon_context,
  69.          goto out;
  70.      }
  71.  
  72. +    /*
  73. +     * Set file attributes
  74. +     *
  75. +     * Notes:
  76. +     * - MS-FSCC 2.6 File Attributes: "... There is no file attribute with the
  77. +     * value 0x00000000 because a value of 0x00000000 in the FileAttributes
  78. +     * field means that the file attributes for this file MUST NOT be changed
  79. +     * when setting basic information for the file. ..."
  80. +     * - Windows Explorer will set |FILE_ATTRIBUTE_NORMAL| when it wants
  81. +     * to change flags like |FILE_ATTRIBUTE_READONLY|, |FILE_ATTRIBUTE_HIDDEN|,
  82. +     * |FILE_ATTRIBUTE_SYSTEM|, |FILE_ATTRIBUTE_ARCHIVE|
  83. +     */
  84.      if (basic_info->FileAttributes) {
  85.          info.hidden = basic_info->FileAttributes & FILE_ATTRIBUTE_HIDDEN ? 1 : 0;
  86.          info.system = basic_info->FileAttributes & FILE_ATTRIBUTE_SYSTEM ? 1 : 0;
  87. @@ -127,20 +139,20 @@ static int handle_nfs41_setattr_basicinfo(void *daemon_context,
  88.              ("handle_nfs41_setattr_basicinfo(args->path='%s)': "
  89.              "Unsupported flag FILE_ATTRIBUTE_COMPRESSED ignored.\n",
  90.              args->path));
  91. -    }
  92.  
  93. -    /* mode */
  94. -    if (basic_info->FileAttributes & FILE_ATTRIBUTE_READONLY) {
  95. -        info.mode = 0444;
  96. -        info.attrmask.arr[1] |= FATTR4_WORD1_MODE;
  97. -        info.attrmask.count = __max(info.attrmask.count, 2);
  98. -    }
  99. -    else {
  100. -        if (old_info.mode == 0444) {
  101. -            info.mode = 0644;
  102. +        /* mode */
  103. +        if (basic_info->FileAttributes & FILE_ATTRIBUTE_READONLY) {
  104. +            info.mode = 0444;
  105.              info.attrmask.arr[1] |= FATTR4_WORD1_MODE;
  106.              info.attrmask.count = __max(info.attrmask.count, 2);
  107.          }
  108. +        else {
  109. +            if (old_info.mode == 0444) {
  110. +                info.mode = 0644;
  111. +                info.attrmask.arr[1] |= FATTR4_WORD1_MODE;
  112. +                info.attrmask.count = __max(info.attrmask.count, 2);
  113. +            }
  114. +        }
  115.      }
  116.  
  117.      if (superblock->cansettime) {
  118. --
  119. 2.51.0
  120.  
  121. From bebe7a51289c241e336edc151bf960b04d5416fa Mon Sep 17 00:00:00 2001
  122. From: Roland Mainz <roland.mainz@nrubsig.org>
  123. Date: Tue, 18 Nov 2025 19:39:14 +0100
  124. Subject: [PATCH 03/28] daemon: Setting/getting |FILE_ATTRIBUTE_READONLY|
  125.  should not touch "x"/setid mode bits
  126.  
  127. Setting/getting |FILE_ATTRIBUTE_READONLY| should not touch any
  128. of the "x"/set@(uid|gid) mode bits.
  129.  
  130. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  131. ---
  132. daemon/fileinfoutil.c |  2 +-
  133.  daemon/setattr.c      | 48 +++++++++++++++++++++++++++++++++++--------
  134.  2 files changed, 40 insertions(+), 10 deletions(-)
  135.  
  136. diff --git a/daemon/fileinfoutil.c b/daemon/fileinfoutil.c
  137. index fe24b0a..0dca8ad 100644
  138. --- a/daemon/fileinfoutil.c
  139. +++ b/daemon/fileinfoutil.c
  140. @@ -74,7 +74,7 @@ ULONG nfs_file_info_to_attributes(
  141.  
  142.      EASSERT(bitmap_isset(&info->attrmask, 1, FATTR4_WORD1_MODE));
  143.      if (bitmap_isset(&info->attrmask, 1, FATTR4_WORD1_MODE)) {
  144. -        if (info->mode == 0444) /* XXX: 0444 for READONLY */
  145. +        if ((info->mode & 0666) == 0444) /* XXX: 0444 for READONLY */
  146.              attrs |= FILE_ATTRIBUTE_READONLY;
  147.      }
  148.  
  149. diff --git a/daemon/setattr.c b/daemon/setattr.c
  150. index 8c281e9..20a81e3 100644
  151. --- a/daemon/setattr.c
  152. +++ b/daemon/setattr.c
  153. @@ -140,19 +140,46 @@ static int handle_nfs41_setattr_basicinfo(void *daemon_context,
  154.              "Unsupported flag FILE_ATTRIBUTE_COMPRESSED ignored.\n",
  155.              args->path));
  156.  
  157. -        /* mode */
  158. +        /* |FILE_ATTRIBUTE_READONLY| to POSIX mode */
  159. +        bool modesetmasksupported = bitmap_isset(&superblock->supported_attrs,
  160. +            2, FATTR4_WORD2_MODE_SET_MASKED);
  161. +
  162.          if (basic_info->FileAttributes & FILE_ATTRIBUTE_READONLY) {
  163. -            info.mode = 0444;
  164. -            info.attrmask.arr[1] |= FATTR4_WORD1_MODE;
  165. -            info.attrmask.count = __max(info.attrmask.count, 2);
  166. -        }
  167. -        else {
  168. -            if (old_info.mode == 0444) {
  169. -                info.mode = 0644;
  170. +            if (modesetmasksupported) {
  171. +                /* Make sure we preserve the "x" and setuid/setgid bits */
  172. +                info.mode = 0444;
  173. +                info.mode_mask = 0666;
  174. +
  175. +                info.attrmask.arr[2] |= FATTR4_WORD2_MODE_SET_MASKED;
  176. +                info.attrmask.count = __max(info.attrmask.count, 3);
  177. +            }
  178. +            else {
  179. +                /* Make sure we preserve the "x" and setuid/setgid bits */
  180. +                info.mode = (old_info.mode & ~0666) | 0444;
  181. +
  182.                  info.attrmask.arr[1] |= FATTR4_WORD1_MODE;
  183.                  info.attrmask.count = __max(info.attrmask.count, 2);
  184.              }
  185.          }
  186. +        else {
  187. +            if ((old_info.mode & 0666) == 0444) {
  188. +                if (modesetmasksupported) {
  189. +                    /* Make sure we preserve the "x" and setuid/setgid bits */
  190. +                    info.mode = 0644;
  191. +                    info.mode_mask = 0666;
  192. +
  193. +                    info.attrmask.arr[2] |= FATTR4_WORD2_MODE_SET_MASKED;
  194. +                    info.attrmask.count = __max(info.attrmask.count, 3);
  195. +                }
  196. +                else {
  197. +                    /* Make sure we preserve the "x" and setuid/setgid bits */
  198. +                    info.mode = (old_info.mode & ~0666) | 0644;
  199. +
  200. +                    info.attrmask.arr[1] |= FATTR4_WORD1_MODE;
  201. +                    info.attrmask.count = __max(info.attrmask.count, 2);
  202. +                }
  203. +            }
  204. +        }
  205.      }
  206.  
  207.      if (superblock->cansettime) {
  208. @@ -207,11 +234,14 @@ static int handle_nfs41_setattr_basicinfo(void *daemon_context,
  209.       */
  210.      if ((opcode != NFS41_SYSOP_FILE_SET_AT_CLEANUP) &&
  211.          (bitmap_isset(&info.attrmask, 1, FATTR4_WORD1_MODE) ||
  212. +        bitmap_isset(&info.attrmask, 2, FATTR4_WORD2_MODE_SET_MASKED) ||
  213.          bitmap_isset(&info.attrmask, 1, FATTR4_WORD1_TIME_CREATE))) {
  214.          DPRINTF(0, ("handle_nfs41_setattr_basicinfo(args->path='%s'): "
  215. -            "returning read delegation because of mode=%d, time_create=%d\n",
  216. +            "returning read delegation because of "
  217. +            "mode=%d/mode_set_masked=%d, time_create=%d\n",
  218.              args->path,
  219.              (int)bitmap_isset(&info.attrmask, 1, FATTR4_WORD1_MODE),
  220. +            (int)bitmap_isset(&info.attrmask, 2, FATTR4_WORD2_MODE_SET_MASKED),
  221.              (int)bitmap_isset(&info.attrmask, 1, FATTR4_WORD1_TIME_CREATE)));
  222.          nfs41_delegation_return(state->session, &state->file,
  223.              OPEN_DELEGATE_READ, FALSE);
  224. --
  225. 2.51.0
  226.  
  227. From efbcc2bf83a784ed6969bddfd8e2ce2f6457b5b4 Mon Sep 17 00:00:00 2001
  228. From: Roland Mainz <roland.mainz@nrubsig.org>
  229. Date: Wed, 19 Nov 2025 13:18:58 +0100
  230. Subject: [PATCH 04/28] daemon: |read_from_mds()| should retry with op READ if
  231.  op READ_PLUS is not supported
  232. MIME-Version: 1.0
  233. Content-Type: text/plain; charset=UTF-8
  234. Content-Transfer-Encoding: 8bit
  235.  
  236. |read_from_mds()| should retry with NFSv4.1 op READ if NFSv4.2 op READ_PLUS is
  237. not supported.
  238.  
  239. Reported as read error with Windows git with a FreeBSD 14.3 nfsd.
  240.  
  241. Reported-by: Aurélien Couderc <aurelien.couderc2002@gmail.com>
  242. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  243. ---
  244. daemon/readwrite.c | 4 ++++
  245.  1 file changed, 4 insertions(+)
  246.  
  247. diff --git a/daemon/readwrite.c b/daemon/readwrite.c
  248. index d4d1b33..21f1fd8 100644
  249. --- a/daemon/readwrite.c
  250. +++ b/daemon/readwrite.c
  251. @@ -212,6 +212,7 @@ static int read_from_mds(
  252.      while(to_rcv > 0) {
  253.          uint32_t bytes_read = 0, chunk = min(to_rcv, maxreadsize);
  254.  
  255. +retry_read:
  256.          if (session->client->root->supports_nfs42_read_plus) {
  257.              status = nfs42_read_plus(session, file, stateid,
  258.                  args->offset + reloffset, chunk,
  259. @@ -227,6 +228,9 @@ static int read_from_mds(
  260.                      "disabling OP_READ_PLUS\n",
  261.                      nfs_error_string(status)));
  262.                  session->client->root->supports_nfs42_read_plus = false;
  263. +
  264. +                /* Retry now with |nfs41_read()| ... */
  265. +                goto retry_read;
  266.              }
  267.          }
  268.          else {
  269. --
  270. 2.51.0
  271.  
  272. From fab638bc106087f57a9a5a77d7c4a123bce95a73 Mon Sep 17 00:00:00 2001
  273. From: Dan Shelton <dan.f.shelton@gmail.com>
  274. Date: Wed, 19 Nov 2025 15:27:33 +0100
  275. Subject: [PATCH 05/28] sys: Add more FSCTL_* to debug fsctl2string()
  276.  
  277. Add more FSCTL_* to debug fsctl2string().
  278.  
  279. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  280. ---
  281. sys/nfs41sys_debug.c | 21 +++++++++++++++++++++
  282.  1 file changed, 21 insertions(+)
  283.  
  284. diff --git a/sys/nfs41sys_debug.c b/sys/nfs41sys_debug.c
  285. index c1c996f..df866b3 100644
  286. --- a/sys/nfs41sys_debug.c
  287. +++ b/sys/nfs41sys_debug.c
  288. @@ -831,6 +831,15 @@ dprintk(
  289.  
  290.  const char *fsctl2string(ULONG fscontrolcode)
  291.  {
  292. +#ifndef FSCTL_LMR_GET_HINT_SIZE
  293. +#define FSCTL_LMR_GET_HINT_SIZE \
  294. +    CTL_CODE(FILE_DEVICE_NETWORK_FILE_SYSTEM, 113, METHOD_BUFFERED, FILE_ANY_ACCESS)
  295. +#endif /* !FSCTL_LMR_GET_HINT_SIZE */
  296. +#ifndef FSCTL_LMR_GET_VERSIONS
  297. +#define FSCTL_LMR_GET_VERSIONS  \
  298. +    CTL_CODE(FILE_DEVICE_NETWORK_FILE_SYSTEM, 106, METHOD_BUFFERED, FILE_ANY_ACCESS)
  299. +#endif /* !FSCTL_LMR_GET_VERSIONS */
  300. +
  301.  #define CASE_SYM2STR_RET(x) case (x): return #x ; break;
  302.      switch(fscontrolcode) {
  303.  #ifdef FSCTL_ADD_OVERLAY
  304. @@ -1052,6 +1061,18 @@ const char *fsctl2string(ULONG fscontrolcode)
  305.  #ifdef FSCTL_IS_VOLUME_OWNED_BYCSVFS
  306.          CASE_SYM2STR_RET(FSCTL_IS_VOLUME_OWNED_BYCSVFS)
  307.  #endif /* FSCTL_IS_VOLUME_OWNED_BYCSVFS */
  308. +#ifdef FSCTL_LMR_GET_HINT_SIZE
  309. +        CASE_SYM2STR_RET(FSCTL_LMR_GET_HINT_SIZE)
  310. +#endif /* FSCTL_LMR_GET_HINT_SIZE */
  311. +#ifdef FSCTL_LMR_GET_LINK_TRACKING_INFORMATION
  312. +        CASE_SYM2STR_RET(FSCTL_LMR_GET_LINK_TRACKING_INFORMATION)
  313. +#endif /* FSCTL_LMR_GET_LINK_TRACKING_INFORMATION */
  314. +#ifdef FSCTL_LMR_GET_VERSIONS
  315. +        CASE_SYM2STR_RET(FSCTL_LMR_GET_VERSIONS)
  316. +#endif /* FSCTL_LMR_GET_VERSIONS */
  317. +#ifdef FSCTL_LMR_SET_LINK_TRACKING_INFORMATION
  318. +        CASE_SYM2STR_RET(FSCTL_LMR_SET_LINK_TRACKING_INFORMATION)
  319. +#endif /* FSCTL_LMR_SET_LINK_TRACKING_INFORMATION */
  320.  #ifdef FSCTL_LOCK_VOLUME
  321.          CASE_SYM2STR_RET(FSCTL_LOCK_VOLUME)
  322.  #endif /* FSCTL_LOCK_VOLUME */
  323. --
  324. 2.51.0
  325.  
  326. From d632609432affe3615d087e03e4727bf04f13d6a Mon Sep 17 00:00:00 2001
  327. From: Roland Mainz <roland.mainz@nrubsig.org>
  328. Date: Thu, 20 Nov 2025 19:00:09 +0100
  329. Subject: [PATCH 06/28] sys: Print ECP (Extended Create Parameters) GUIDs at
  330.  file creation time
  331.  
  332. Print ECP (Extended Create Parameters) GUIDs at file creation time.
  333.  
  334. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  335. ---
  336. sys/nfs41sys_debug.c     | 128 +++++++++++++++++++++++++++++++++++++++
  337.  sys/nfs41sys_debug.h     |   4 +-
  338.  sys/nfs41sys_driver.c    |  39 ++++++++++++
  339.  sys/nfs41sys_openclose.c |   2 +
  340.  4 files changed, 172 insertions(+), 1 deletion(-)
  341.  
  342. diff --git a/sys/nfs41sys_debug.c b/sys/nfs41sys_debug.c
  343. index df866b3..f17fa13 100644
  344. --- a/sys/nfs41sys_debug.c
  345. +++ b/sys/nfs41sys_debug.c
  346. @@ -55,6 +55,8 @@
  347.  #include <stdarg.h>
  348.  #include <ntstrsafe.h>
  349.  #include <winerror.h>
  350. +#include <stdbool.h>
  351. +#include <ntifs.h>
  352.  
  353.  #include "win_reparse.h"
  354.  
  355. @@ -1579,3 +1581,129 @@ void print_debug_header(
  356.      if (RxContext->CurrentIrp)
  357.          print_irp_flags(0, RxContext->CurrentIrp);
  358.  }
  359. +
  360. +/*
  361. + * Print Extended Create Parameters (ECP)
  362. + */
  363. +
  364. +/*
  365. + * GUIDs for Extended Create Parameters (ECP)
  366. + *
  367. + * FIXME: These are declared in nfs41sys_driver.c and should be in a header,
  368. + * but nfs41sys_debug.c should not depend in nfs41sys_driver.h
  369. + */
  370. +/*
  371. + * |GUID_ECP_OPEN_AS_BLOCK_DEVICE| - "open as a block device"
  372. + * From https://www.snia.org/sites/default/files/files2/files2/SDC2013/presentations/Workloads/Barreto_Kurjanowicz-Shared_VHDX-v3.pdf
  373. + */
  374. +EXTERN_C const GUID FAR GUID_ECP_OPEN_AS_BLOCK_DEVICE;
  375. +EXTERN_C const GUID FAR GUID_ECP_QUERY_ON_CREATE;
  376. +EXTERN_C const GUID FAR GUID_ECP_CLOUDFILES_ATTRIBUTION;
  377. +EXTERN_C const GUID FAR GUID_ECP_CREATE_USER_PROCESS;
  378. +EXTERN_C const GUID FAR GUID_ECP_ATOMIC_CREATE;
  379. +EXTERN_C const GUID FAR GUID_ECP_OPEN_PARAMETERS;
  380. +
  381. +
  382. +typedef struct _ECP_NAME_MAP {
  383. +    const GUID *Guid;
  384. +    const char *Name;
  385. +} ECP_NAME_MAP;
  386. +
  387. +#define ECP_ENTRY(guid) { (const GUID*)&guid, #guid }
  388. +
  389. +static
  390. +const ECP_NAME_MAP KnownEcps[] = {
  391. +//    ECP_ENTRY(GUID_ECP_FLT_CREATEFILE_TARGET),
  392. +    ECP_ENTRY(GUID_ECP_CREATE_USER_PROCESS),
  393. +    ECP_ENTRY(GUID_ECP_OPLOCK_KEY),
  394. +    ECP_ENTRY(GUID_ECP_DUAL_OPLOCK_KEY),
  395. +    ECP_ENTRY(GUID_ECP_NETWORK_OPEN_CONTEXT),
  396. +    ECP_ENTRY(GUID_ECP_NETWORK_APP_INSTANCE),
  397. +    ECP_ENTRY(GUID_ECP_NETWORK_APP_INSTANCE_VERSION),
  398. +    /* GUID_ECP_PREFETCH_OPEN - Prefetch Open (Superfetch) */
  399. +    ECP_ENTRY(GUID_ECP_PREFETCH_OPEN),
  400. +    ECP_ENTRY(GUID_ECP_NFS_OPEN),
  401. +    /* GUID_ECP_SRV_OPEN - SMB SRV Open */
  402. +    ECP_ENTRY(GUID_ECP_SRV_OPEN),
  403. +    ECP_ENTRY(GUID_ECP_RKF_BYPASS),
  404. +    ECP_ENTRY(GUID_ECP_IO_DEVICE_HINT),
  405. +    ECP_ENTRY(GUID_ECP_CSV_DOWN_LEVEL_OPEN),
  406. +    ECP_ENTRY(GUID_ECP_CSV_QUERY_FILE_REVISION),
  407. +    ECP_ENTRY(GUID_ECP_CSV_QUERY_FILE_REVISION_FILE_ID_128),
  408. +    ECP_ENTRY(GUID_ECP_CSV_SET_HANDLE_PROPERTIES),
  409. +    ECP_ENTRY(GUID_ECP_CREATE_REDIRECTION),
  410. +    ECP_ENTRY(GUID_ECP_ATOMIC_CREATE),
  411. +    ECP_ENTRY(GUID_ECP_OPEN_PARAMETERS),
  412. +    ECP_ENTRY(GUID_ECP_QUERY_ON_CREATE),
  413. +    ECP_ENTRY(GUID_ECP_CLOUDFILES_ATTRIBUTION),
  414. +    /*
  415. +     * Custom ECP not in <ntifs.h>/Windows headers
  416. +     */
  417. +    ECP_ENTRY(GUID_ECP_OPEN_AS_BLOCK_DEVICE),
  418. +    { NULL, NULL }
  419. +};
  420. +
  421. +static
  422. +const char *GetEcpNameFromGuid(const GUID *restrict guid)
  423. +{
  424. +    for (int i = 0; KnownEcps[i].Guid != NULL; i++) {
  425. +        if (IsEqualGUID(guid, KnownEcps[i].Guid)) {
  426. +            return KnownEcps[i].Name;
  427. +        }
  428. +    }
  429. +    return "<Unknown-ECP>";
  430. +}
  431. +
  432. +void debug_printirpecps(PIRP irp)
  433. +{
  434. +    NTSTATUS status;
  435. +    PECP_LIST ecpList = NULL;
  436. +    PVOID currentContext = NULL;
  437. +    PVOID nextContext = NULL;
  438. +    GUID ecpGuid;
  439. +    ULONG ecpSize = 0;
  440. +    UNICODE_STRING guidString;
  441. +
  442. +    status = FsRtlGetEcpListFromIrp(irp, &ecpList);
  443. +
  444. +    if ((status == STATUS_NOT_FOUND) || (ecpList == NULL)) {
  445. +        DbgP("debug_printirpecps: No ECP list found attached to the IRP.\n");
  446. +        return;
  447. +    } else if (!NT_SUCCESS(status)) {
  448. +        DbgP("debug_printirpecps: Failed to retrieve ECP list, status=0x%lx\n",
  449. +            (long)status);
  450. +        return;
  451. +    }
  452. +
  453. +    while(true) {
  454. +        status = FsRtlGetNextExtraCreateParameter(
  455. +            ecpList,
  456. +            currentContext,
  457. +            &ecpGuid,
  458. +            &nextContext,
  459. +            &ecpSize
  460. +        );
  461. +
  462. +        if (status == STATUS_NOT_FOUND) {
  463. +            break;
  464. +        }
  465. +
  466. +        if (!NT_SUCCESS(status)) {
  467. +            DbgP("debug_printirpecps: "
  468. +                "FsRtlGetNextExtraCreateParameter() returned status=0x%lx\n",
  469. +                (long)status);
  470. +            break;
  471. +        }
  472. +
  473. +        if (NT_SUCCESS(RtlStringFromGUID(&ecpGuid, &guidString))) {
  474. +            const char *friendlyName = GetEcpNameFromGuid(&ecpGuid);
  475. +
  476. +            DbgP("debug_printirpecps: ECP: Name='%s', GUID='%wZ', size=%lu\n",
  477. +                friendlyName, &guidString, ecpSize);
  478. +
  479. +            RtlFreeUnicodeString(&guidString);
  480. +        }
  481. +
  482. +        currentContext = nextContext;
  483. +    }
  484. +}
  485. diff --git a/sys/nfs41sys_debug.h b/sys/nfs41sys_debug.h
  486. index 47f8d61..aac1c31 100644
  487. --- a/sys/nfs41sys_debug.h
  488. +++ b/sys/nfs41sys_debug.h
  489. @@ -1,5 +1,6 @@
  490.  /* NFSv4.1 client for Windows
  491. - * Copyright (C) 2012 The Regents of the University of Michigan
  492. + * Copyright (C) 2012 The Regents of the University of Michigan
  493. + * Copyright (C) 2023-2025 Roland Mainz <roland.mainz@nrubsig.org>
  494.   *
  495.   * Olga Kornievskaia <aglo@umich.edu>
  496.   * Casey Bodley <cbodley@umich.edu>
  497. @@ -60,6 +61,7 @@ const char *reparsetag2string(ULONG tag);
  498.  void print_lookasidelist_stat(const char *label, PNPAGED_LOOKASIDE_LIST ll);
  499.  #endif /* USE_LOOKASIDELISTS_FOR_UPDOWNCALLENTRY_MEM */
  500.  void print_debug_header(PRX_CONTEXT RxContext);
  501. +void debug_printirpecps(PIRP irp);
  502.  
  503.  #define PTR2PTRDIFF_T(p) (((char *)(p))-((char *)0))
  504.  #define PsGetCurrentProcessShortDebugId() ((int)PTR2PTRDIFF_T(PsGetCurrentProcessId()))
  505. diff --git a/sys/nfs41sys_driver.c b/sys/nfs41sys_driver.c
  506. index 39689ab..1ae41e0 100644
  507. --- a/sys/nfs41sys_driver.c
  508. +++ b/sys/nfs41sys_driver.c
  509. @@ -52,6 +52,11 @@
  510.  #endif
  511.  #endif /* _MSC_VER >= 1900 */
  512.  
  513. +/*
  514. + * <initguid.h> must be included FIRST to get GUID variable declarations below
  515. + */
  516. +#include <initguid.h>
  517. +
  518.  #define MINIRDR__NAME MRxNFS41
  519.  #include <rx.h>
  520.  #include <windef.h>
  521. @@ -88,6 +93,40 @@ DECLARE_CONST_ANSI_STRING(NfsV3Attributes, EA_NFSV3ATTRIBUTES);
  522.  DECLARE_CONST_ANSI_STRING(NfsSymlinkTargetName, EA_NFSSYMLINKTARGETNAME);
  523.  DECLARE_CONST_ANSI_STRING(NfsActOnLink, EA_NFSACTONLINK);
  524.  
  525. +/*
  526. + * |GUID_ECP_OPEN_AS_BLOCK_DEVICE| - "open as a block device"
  527. + * From https://www.snia.org/sites/default/files/files2/files2/SDC2013/presentations/Workloads/Barreto_Kurjanowicz-Shared_VHDX-v3.pdf
  528. + */
  529. +DEFINE_GUID(GUID_ECP_OPEN_AS_BLOCK_DEVICE,
  530. +    0x9ecfcb9c, 0xc104, 0x43e6,
  531. +    0x98, 0x0e, 0x15, 0x8d, 0xa1, 0xf6, 0xec, 0x83);
  532. +
  533. +#if !(NTDDI_VERSION >= NTDDI_WIN10_RS5)
  534. +DEFINE_GUID(GUID_ECP_QUERY_ON_CREATE,
  535. +    0x1aca62e9, 0xabb4, 0x4ff2,
  536. +    0xbb, 0x5c, 0x1c, 0x79, 0x2, 0x5e, 0x41, 0x7f);
  537. +#endif /* !(NTDDI_VERSION >= NTDDI_WIN10_RS5) */
  538. +#if !(NTDDI_VERSION >= NTDDI_WIN10_VB)
  539. +DEFINE_GUID(GUID_ECP_CLOUDFILES_ATTRIBUTION,
  540. +    0x2932ff52, 0x8378, 0x4fc1,
  541. +    0x8e, 0xdb, 0x6b, 0xdc, 0x8f, 0x60, 0x27, 0x09);
  542. +#endif /* !(NTDDI_VERSION >= NTDDI_WIN10_VB) */
  543. +#if !(NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
  544. +DEFINE_GUID(GUID_ECP_CREATE_USER_PROCESS,
  545. +    0xe0e429ff, 0x6ddc, 0x4e65,
  546. +    0xaa, 0xb6, 0x45, 0xd0, 0x5a, 0x3, 0x8a, 0x8);
  547. +#endif /* !(NTDDI_VERSION >= NTDDI_WINTHRESHOLD) */
  548. +#if !(NTDDI_VERSION >= NTDDI_WIN10_TH2)
  549. +DEFINE_GUID(GUID_ECP_ATOMIC_CREATE,
  550. +    0x4720bd83, 0x52ac, 0x4104,
  551. +    0xa1, 0x30, 0xd1, 0xec, 0x6a, 0x8c, 0xc8, 0xe5);
  552. +#endif /* !(NTDDI_VERSION >= NTDDI_WIN10_TH2) */
  553. +#if !(NTDDI_VERSION >= NTDDI_WIN10_RS3)
  554. +DEFINE_GUID(GUID_ECP_OPEN_PARAMETERS,
  555. +    0xcd0a93c3, 0x3bb7, 0x463d,
  556. +    0xac, 0xcb, 0x96, 0x9d, 0x34, 0x35, 0xa5, 0xa5);
  557. +#endif /* !(NTDDI_VERSION >= NTDDI_WIN10_RS3) */
  558. +
  559.  #ifdef USE_LOOKASIDELISTS_FOR_UPDOWNCALLENTRY_MEM
  560.  NPAGED_LOOKASIDE_LIST updowncall_entry_upcall_lookasidelist;
  561.  #ifndef USE_STACK_FOR_DOWNCALL_UPDOWNCALLENTRY_MEM
  562. diff --git a/sys/nfs41sys_openclose.c b/sys/nfs41sys_openclose.c
  563. index 3247539..25ae634 100644
  564. --- a/sys/nfs41sys_openclose.c
  565. +++ b/sys/nfs41sys_openclose.c
  566. @@ -655,6 +655,8 @@ NTSTATUS nfs41_Create(
  567.      status = check_nfs41_create_args(RxContext);
  568.      if (status) goto out;
  569.  
  570. +    debug_printirpecps(RxContext->CurrentIrp);
  571. +
  572.  #ifdef NFS41_DRIVER_ALLOW_CREATEFILE_ACLS
  573.      ULONG SdLength = RxContext->Create.SdLength;
  574.      PSECURITY_DESCRIPTOR SdBuffer;
  575. --
  576. 2.51.0
  577.  
  578. From 1b12578a04fe5a4c58fba1969b7dcf685db7e842 Mon Sep 17 00:00:00 2001
  579. From: Roland Mainz <roland.mainz@nrubsig.org>
  580. Date: Thu, 20 Nov 2025 19:08:47 +0100
  581. Subject: [PATCH 07/28] sys: Fix comment about SMB also using
  582.  |IO_NETWORK_INCREMENT|
  583.  
  584. Fix comment about SMB also using |IO_NETWORK_INCREMENT|.
  585.  
  586. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  587. ---
  588. sys/nfs41sys_driver.h | 2 +-
  589.  1 file changed, 1 insertion(+), 1 deletion(-)
  590.  
  591. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  592. index 1c327ab..47e58eb 100644
  593. --- a/sys/nfs41sys_driver.h
  594. +++ b/sys/nfs41sys_driver.h
  595. @@ -92,7 +92,7 @@ typedef struct __nfs41_timings {
  596.  } nfs41_timings;
  597.  #endif /* ENABLE_TIMINGS */
  598.  
  599. -/* Windows SMB driver also uses |IO_NFS41FS_INCREMENT| */
  600. +/* Windows SMB driver also uses |IO_NETWORK_INCREMENT| */
  601.  #define IO_NFS41FS_INCREMENT IO_NETWORK_INCREMENT
  602.  
  603.  #define DISABLE_CACHING 0
  604. --
  605. 2.51.0
  606.  
  607. From 4625971d4748376e1b75178f1643627d397f4143 Mon Sep 17 00:00:00 2001
  608. From: Roland Mainz <roland.mainz@nrubsig.org>
  609. Date: Thu, 20 Nov 2025 20:31:38 +0100
  610. Subject: [PATCH 08/28] sys: Print
  611.  |QUERY_ON_CREATE_ECP_CONTEXT.RequestedClasses| to debug log
  612.  
  613. Print |QUERY_ON_CREATE_ECP_CONTEXT.RequestedClasses| to debug log
  614. if we got a |GUID_ECP_QUERY_ON_CREATE| at file/dir creation time.
  615.  
  616. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  617. ---
  618. sys/nfs41sys_openclose.c |  6 ++++++
  619.  sys/nfs41sys_util.c      | 29 ++++++++++++++++++++++++++++-
  620.  sys/nfs41sys_util.h      |  5 ++++-
  621.  3 files changed, 38 insertions(+), 2 deletions(-)
  622.  
  623. diff --git a/sys/nfs41sys_openclose.c b/sys/nfs41sys_openclose.c
  624. index 25ae634..53bb879 100644
  625. --- a/sys/nfs41sys_openclose.c
  626. +++ b/sys/nfs41sys_openclose.c
  627. @@ -657,6 +657,12 @@ NTSTATUS nfs41_Create(
  628.  
  629.      debug_printirpecps(RxContext->CurrentIrp);
  630.  
  631. +    PQUERY_ON_CREATE_ECP_CONTEXT qocec =
  632. +        get_queryoncreateecpcontext(RxContext->CurrentIrp);
  633. +    if (qocec) {
  634. +        DbgP("nfs41_Create: RequestedClasses=0x%lx\n", qocec->RequestedClasses);
  635. +    }
  636. +
  637.  #ifdef NFS41_DRIVER_ALLOW_CREATEFILE_ACLS
  638.      ULONG SdLength = RxContext->Create.SdLength;
  639.      PSECURITY_DESCRIPTOR SdBuffer;
  640. diff --git a/sys/nfs41sys_util.c b/sys/nfs41sys_util.c
  641. index 6cceee8..27691fd 100644
  642. --- a/sys/nfs41sys_util.c
  643. +++ b/sys/nfs41sys_util.c
  644. @@ -1,6 +1,6 @@
  645.  /* NFSv4.1 client for Windows
  646.   * Copyright (C) 2012 The Regents of the University of Michigan
  647. - * Copyright (C) 2023-2024 Roland Mainz <roland.mainz@nrubsig.org>
  648. + * Copyright (C) 2023-2025 Roland Mainz <roland.mainz@nrubsig.org>
  649.   *
  650.   * Olga Kornievskaia <aglo@umich.edu>
  651.   * Casey Bodley <cbodley@umich.edu>
  652. @@ -194,3 +194,30 @@ NTSTATUS nfs41_UnmapLockedKernelPagesInNfsDaemonAddressSpace(
  653.  
  654.      return status;
  655.  }
  656. +
  657. +PQUERY_ON_CREATE_ECP_CONTEXT get_queryoncreateecpcontext(
  658. +    __in PIRP Irp)
  659. +{
  660. +    NTSTATUS status;
  661. +    PECP_LIST ecpList = NULL;
  662. +    PVOID ecpContext = NULL;
  663. +
  664. +    status = FsRtlGetEcpListFromIrp(Irp, &ecpList);
  665. +
  666. +    if ((!NT_SUCCESS(status)) || (ecpList == NULL)) {
  667. +        return NULL;
  668. +    }
  669. +
  670. +    status = FsRtlFindExtraCreateParameter(
  671. +        ecpList,
  672. +        &GUID_ECP_QUERY_ON_CREATE,
  673. +        &ecpContext,
  674. +        NULL
  675. +    );
  676. +
  677. +    if (!NT_SUCCESS(status)) {
  678. +        return NULL;
  679. +    }
  680. +
  681. +    return (PQUERY_ON_CREATE_ECP_CONTEXT)ecpContext;
  682. +}
  683. diff --git a/sys/nfs41sys_util.h b/sys/nfs41sys_util.h
  684. index 6157195..793f440 100644
  685. --- a/sys/nfs41sys_util.h
  686. +++ b/sys/nfs41sys_util.h
  687. @@ -1,6 +1,6 @@
  688.  /* NFSv4.1 client for Windows
  689.   * Copyright (C) 2012 The Regents of the University of Michigan
  690. - * Copyright (C) 2023-2024 Roland Mainz <roland.mainz@nrubsig.org>
  691. + * Copyright (C) 2023-2025 Roland Mainz <roland.mainz@nrubsig.org>
  692.   *
  693.   * Olga Kornievskaia <aglo@umich.edu>
  694.   * Casey Bodley <cbodley@umich.edu>
  695. @@ -65,4 +65,7 @@ NTSTATUS nfs41_MapLockedPagesInNfsDaemonAddressSpace(
  696.  NTSTATUS nfs41_UnmapLockedKernelPagesInNfsDaemonAddressSpace(
  697.      __in PVOID BaseAddress,
  698.      __in PMDL  MemoryDescriptorList);
  699. +PQUERY_ON_CREATE_ECP_CONTEXT get_queryoncreateecpcontext(
  700. +    __in PIRP Irp);
  701. +
  702.  #endif /* !_NFS41SYS_UTIL_H_ */
  703. --
  704. 2.51.0
  705.  
  706. From d8def0564972e647f12804a1910aba3cb3dce084 Mon Sep 17 00:00:00 2001
  707. From: Roland Mainz <roland.mainz@nrubsig.org>
  708. Date: Thu, 20 Nov 2025 21:29:58 +0100
  709. Subject: [PATCH 09/28] sys: Invalidate kernel ACL cache if it does not contain
  710.  the info we requested
  711. MIME-Version: 1.0
  712. Content-Type: text/plain; charset=UTF-8
  713. Content-Transfer-Encoding: 8bit
  714.  
  715. Invalidate kernel ACL cache if it does not contain the info we requested
  716. (e.g. we have cached info for owner+primary group, but DACL info
  717. are requested).
  718.  
  719. Reported-by: Aurélien Couderc <aurelien.couderc2002@gmail.com>
  720. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  721. ---
  722. sys/nfs41sys_acl.c    | 45 ++++++++++++++++++++++++++++---------------
  723.  sys/nfs41sys_driver.h |  1 +
  724.  2 files changed, 30 insertions(+), 16 deletions(-)
  725.  
  726. diff --git a/sys/nfs41sys_acl.c b/sys/nfs41sys_acl.c
  727. index d8e4aa8..aef18d0 100644
  728. --- a/sys/nfs41sys_acl.c
  729. +++ b/sys/nfs41sys_acl.c
  730. @@ -275,27 +275,37 @@ NTSTATUS nfs41_QuerySecurityInformation(
  731.                  goto out;
  732.              }
  733.  
  734. -            PSECURITY_DESCRIPTOR sec_desc = (PSECURITY_DESCRIPTOR)
  735. -                RxContext->CurrentIrp->UserBuffer;
  736. -            RtlCopyMemory(sec_desc, nfs41_fobx->acl, nfs41_fobx->acl_len);
  737. -            RxContext->IoStatusBlock.Information =
  738. -                RxContext->InformationToReturn = nfs41_fobx->acl_len;
  739. -            RxContext->IoStatusBlock.Status = status = STATUS_SUCCESS;
  740. +            /* Check whether the cached info have all the info we need */
  741. +            if ((nfs41_fobx->acl_secinfo & info_class) == info_class) {
  742. +                PSECURITY_DESCRIPTOR sec_desc = (PSECURITY_DESCRIPTOR)
  743. +                    RxContext->CurrentIrp->UserBuffer;
  744. +                RtlCopyMemory(sec_desc, nfs41_fobx->acl, nfs41_fobx->acl_len);
  745. +                RxContext->IoStatusBlock.Information =
  746. +                    RxContext->InformationToReturn = nfs41_fobx->acl_len;
  747. +                RxContext->IoStatusBlock.Status = status = STATUS_SUCCESS;
  748.  #ifdef ENABLE_TIMINGS
  749. -            InterlockedIncrement(&getacl.sops);
  750. -            InterlockedAdd64(&getacl.size, nfs41_fobx->acl_len);
  751. +                InterlockedIncrement(&getacl.sops);
  752. +                InterlockedAdd64(&getacl.size, nfs41_fobx->acl_len);
  753.  #endif
  754.  
  755. -            DbgP("nfs41_QuerySecurityInformation: using cached ACL info\n");
  756. -            goto out;
  757. -        } else {
  758. -            if (nfs41_fobx->acl) {
  759. -                RxFreePool(nfs41_fobx->acl);
  760. -                nfs41_fobx->acl = NULL;
  761. -                nfs41_fobx->acl_len = 0;
  762. +                DbgP("nfs41_QuerySecurityInformation: using cached ACL info\n");
  763. +                goto out;
  764.              }
  765. -            DbgP("nfs41_QuerySecurityInformation: cached ACL info invalidated\n");
  766. +            else {
  767. +                DbgP("nfs41_QuerySecurityInformation: "
  768. +                    "cache misses requested info, acl_secinfo=0x%lx, info_class=0x%lx\n",
  769. +                    (unsigned long)nfs41_fobx->acl_secinfo,
  770. +                    (unsigned long)info_class);
  771. +            }
  772. +        }
  773. +
  774. +        if (nfs41_fobx->acl) {
  775. +            RxFreePool(nfs41_fobx->acl);
  776. +            nfs41_fobx->acl = NULL;
  777. +            nfs41_fobx->acl_len = 0;
  778. +            nfs41_fobx->acl_secinfo = 0;
  779.          }
  780. +        DbgP("nfs41_QuerySecurityInformation: cached ACL info invalidated\n");
  781.      }
  782.  
  783.      status = nfs41_UpcallCreate(NFS41_SYSOP_ACL_QUERY, &nfs41_fobx->sec_ctx,
  784. @@ -338,10 +348,12 @@ NTSTATUS nfs41_QuerySecurityInformation(
  785.              RxFreePool(nfs41_fobx->acl);
  786.              nfs41_fobx->acl = NULL;
  787.              nfs41_fobx->acl_len = 0;
  788. +            nfs41_fobx->acl_secinfo = 0;
  789.          }
  790.  
  791.          nfs41_fobx->acl = entry->u.Acl.buf;
  792.          nfs41_fobx->acl_len = entry->u.Acl.buf_len;
  793. +        nfs41_fobx->acl_secinfo = entry->u.Acl.query;
  794.          entry->u.Acl.buf = NULL;
  795.          KeQuerySystemTime(&nfs41_fobx->time);
  796.  
  797. @@ -479,6 +491,7 @@ NTSTATUS nfs41_SetSecurityInformation(
  798.          RxFreePool(nfs41_fobx->acl);
  799.          nfs41_fobx->acl = NULL;
  800.          nfs41_fobx->acl_len = 0;
  801. +        nfs41_fobx->acl_secinfo = 0;
  802.      }
  803.  
  804.      status = nfs41_UpcallWaitForReply(entry, pVNetRootContext->timeout);
  805. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  806. index 47e58eb..ad1b2f4 100644
  807. --- a/sys/nfs41sys_driver.h
  808. +++ b/sys/nfs41sys_driver.h
  809. @@ -496,6 +496,7 @@ typedef struct _NFS41_FOBX {
  810.      SECURITY_CLIENT_CONTEXT sec_ctx;
  811.      PVOID acl;
  812.      DWORD acl_len;
  813. +    SECURITY_INFORMATION acl_secinfo;
  814.      LARGE_INTEGER time;
  815.      DWORD deleg_type;
  816.      BOOLEAN write_thru;
  817. --
  818. 2.51.0
  819.  
  820. From 49a907fb0b098af469032c6fb55f654ae25e7e7e Mon Sep 17 00:00:00 2001
  821. From: Roland Mainz <roland.mainz@nrubsig.org>
  822. Date: Thu, 20 Nov 2025 21:45:03 +0100
  823. Subject: [PATCH 10/28] daemon,sys: Rename all instances in ACL code which
  824.  refer to |SECURITY_INFORMATION| to |*secinfo|
  825.  
  826. Rename all instances in ACL code which refer to |SECURITY_INFORMATION|
  827. to |*secinfo|.
  828.  
  829. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  830. ---
  831. daemon/acl.c          | 41 +++++++++++++++++++++------------------
  832.  daemon/upcall.h       |  4 ++--
  833.  sys/nfs41sys_acl.c    | 45 +++++++++++++++++++++++--------------------
  834.  sys/nfs41sys_driver.h |  2 +-
  835.  4 files changed, 49 insertions(+), 43 deletions(-)
  836.  
  837. diff --git a/daemon/acl.c b/daemon/acl.c
  838. index bd02f56..2d7546b 100644
  839. --- a/daemon/acl.c
  840. +++ b/daemon/acl.c
  841. @@ -45,12 +45,14 @@ static int parse_getacl(
  842.      int status;
  843.      getacl_upcall_args *args = &upcall->args.getacl;
  844.  
  845. -    status = safe_read(&buffer, &length, &args->query, sizeof(args->query));
  846. +    status = safe_read(&buffer, &length, &args->query_secinfo,
  847. +        sizeof(args->query_secinfo));
  848.      if (status) goto out;
  849.  
  850.      EASSERT(length == 0);
  851.  
  852. -    DPRINTF(1, ("parsing NFS41_SYSOP_ACL_QUERY: info_class=%d\n", args->query));
  853. +    DPRINTF(1, ("parsing NFS41_SYSOP_ACL_QUERY: secinfo=0xlx\n",
  854. +        (long)args->query_secinfo));
  855.  out:
  856.      return status;
  857.  }
  858. @@ -79,7 +81,7 @@ static int handle_getacl(void *daemon_context, nfs41_upcall *upcall)
  859.      DPRINTF(ACLLVL1, ("--> handle_getacl(state->path.path='%s')\n",
  860.          state->path.path));
  861.  
  862. -    if (args->query & DACL_SECURITY_INFORMATION) {
  863. +    if (args->query_secinfo & DACL_SECURITY_INFORMATION) {
  864.          owner_group_acl_bitmap.arr[0] |= FATTR4_WORD0_ACL;
  865.      }
  866.  
  867. @@ -102,13 +104,13 @@ static int handle_getacl(void *daemon_context, nfs41_upcall *upcall)
  868.      }
  869.  
  870.      EASSERT(info.attrmask.count > 1);
  871. -    if (args->query & DACL_SECURITY_INFORMATION) {
  872. +    if (args->query_secinfo & DACL_SECURITY_INFORMATION) {
  873.          EASSERT(bitmap_isset(&info.attrmask, 0, FATTR4_WORD0_ACL) == true);
  874.      }
  875. -    if (args->query & OWNER_SECURITY_INFORMATION) {
  876. +    if (args->query_secinfo & OWNER_SECURITY_INFORMATION) {
  877.          EASSERT(bitmap_isset(&info.attrmask, 1, FATTR4_WORD1_OWNER) == true);
  878.      }
  879. -    if (args->query & GROUP_SECURITY_INFORMATION) {
  880. +    if (args->query_secinfo & GROUP_SECURITY_INFORMATION) {
  881.          EASSERT(bitmap_isset(&info.attrmask, 1, FATTR4_WORD1_OWNER_GROUP) == true);
  882.      }
  883.  
  884. @@ -125,7 +127,7 @@ static int handle_getacl(void *daemon_context, nfs41_upcall *upcall)
  885.        * stores pointers to the sids. thus each owner and group needs its own
  886.        * memory. free them after creating self-relative security descriptor.
  887.        */
  888. -    if (args->query & OWNER_SECURITY_INFORMATION) {
  889. +    if (args->query_secinfo & OWNER_SECURITY_INFORMATION) {
  890.          // parse user@domain. currently ignoring domain part XX
  891.          convert_nfs4name_2_user_domain(info.owner, &domain);
  892.          DPRINTF(ACLLVL2, ("handle_getacl: OWNER_SECURITY_INFORMATION: for user='%s' "
  893. @@ -144,7 +146,7 @@ static int handle_getacl(void *daemon_context, nfs41_upcall *upcall)
  894.          }
  895.      }
  896.  
  897. -    if (args->query & GROUP_SECURITY_INFORMATION) {
  898. +    if (args->query_secinfo & GROUP_SECURITY_INFORMATION) {
  899.          convert_nfs4name_2_user_domain(info.owner_group, &domain);
  900.          DPRINTF(ACLLVL2, ("handle_getacl: GROUP_SECURITY_INFORMATION: for '%s' "
  901.                  "domain='%s'\n", info.owner_group, domain?domain:"<null>"));
  902. @@ -162,7 +164,7 @@ static int handle_getacl(void *daemon_context, nfs41_upcall *upcall)
  903.          }
  904.      }
  905.  
  906. -    if (args->query & DACL_SECURITY_INFORMATION) {
  907. +    if (args->query_secinfo & DACL_SECURITY_INFORMATION) {
  908.          DPRINTF(ACLLVL2, ("handle_getacl: DACL_SECURITY_INFORMATION\n"));
  909.          status = convert_nfs4acl_2_dacl(nfs41dg,
  910.              info.acl, state->type, &dacl, &sids,
  911. @@ -204,13 +206,13 @@ static int handle_getacl(void *daemon_context, nfs41_upcall *upcall)
  912.      } else status = ERROR_SUCCESS;
  913.  
  914.  out:
  915. -    if (args->query & OWNER_SECURITY_INFORMATION) {
  916. +    if (args->query_secinfo & OWNER_SECURITY_INFORMATION) {
  917.          if (osid) free(osid);
  918.      }
  919. -    if (args->query & GROUP_SECURITY_INFORMATION) {
  920. +    if (args->query_secinfo & GROUP_SECURITY_INFORMATION) {
  921.          if (gsid) free(gsid);
  922.      }
  923. -    if (args->query & DACL_SECURITY_INFORMATION) {
  924. +    if (args->query_secinfo & DACL_SECURITY_INFORMATION) {
  925.          if (sids) free_sids(sids, info.acl->count);
  926.          free(dacl);
  927.          nfsacl41_free(info.acl);
  928. @@ -257,7 +259,8 @@ static int parse_setacl(
  929.      const void *sec_desc_ptr;
  930.      ULONG sec_desc_len;
  931.  
  932. -    status = safe_read(&buffer, &length, &args->query, sizeof(args->query));
  933. +    status = safe_read(&buffer, &length, &args->query_secinfo,
  934. +        sizeof(args->query_secinfo));
  935.      if (status) goto out;
  936.      status = safe_read(&buffer, &length, &sec_desc_len, sizeof(ULONG));
  937.      if (status) goto out;
  938. @@ -268,8 +271,8 @@ static int parse_setacl(
  939.  
  940.      EASSERT(length == 0);
  941.  
  942. -    DPRINTF(1, ("parsing NFS41_SYSOP_ACL_SET: info_class=%d sec_desc_len=%d\n",
  943. -            args->query, sec_desc_len));
  944. +    DPRINTF(1, ("parsing NFS41_SYSOP_ACL_SET: secinfo=0x%lx sec_desc_len=%d\n",
  945. +        (long)args->query_secinfo, sec_desc_len));
  946.  out:
  947.      return status;
  948.  }
  949. @@ -297,7 +300,7 @@ static int handle_setacl(void *daemon_context, nfs41_upcall *upcall)
  950.          goto out;
  951.      }
  952.  
  953. -    if (args->query & OWNER_SECURITY_INFORMATION) {
  954. +    if (args->query_secinfo & OWNER_SECURITY_INFORMATION) {
  955.          DPRINTF(ACLLVL2, ("handle_setacl: OWNER_SECURITY_INFORMATION\n"));
  956.          status = GetSecurityDescriptorOwner(args->sec_desc, &sid, &sid_default);
  957.          if (!status) {
  958. @@ -319,7 +322,7 @@ static int handle_setacl(void *daemon_context, nfs41_upcall *upcall)
  959.              ("info.owner='%s'\n", info.owner));
  960.      }
  961.  
  962. -    if (args->query & GROUP_SECURITY_INFORMATION) {
  963. +    if (args->query_secinfo & GROUP_SECURITY_INFORMATION) {
  964.          DPRINTF(ACLLVL2, ("handle_setacl: GROUP_SECURITY_INFORMATION\n"));
  965.          status = GetSecurityDescriptorGroup(args->sec_desc, &sid, &sid_default);
  966.          if (!status) {
  967. @@ -341,7 +344,7 @@ static int handle_setacl(void *daemon_context, nfs41_upcall *upcall)
  968.              ("info.owner_group='%s'\n", info.owner_group));
  969.      }
  970.  
  971. -    if (args->query & DACL_SECURITY_INFORMATION) {
  972. +    if (args->query_secinfo & DACL_SECURITY_INFORMATION) {
  973.          BOOL dacl_present, dacl_default;
  974.          PACL acl;
  975.          DPRINTF(ACLLVL2, ("handle_setacl: DACL_SECURITY_INFORMATION\n"));
  976. @@ -400,7 +403,7 @@ static int handle_setacl(void *daemon_context, nfs41_upcall *upcall)
  977.          }
  978.      }
  979.  
  980. -    if (args->query & DACL_SECURITY_INFORMATION)
  981. +    if (args->query_secinfo & DACL_SECURITY_INFORMATION)
  982.          free(nfs4_acl.aces);
  983.  out:
  984.      DPRINTF(ACLLVL1, ("<-- handle_setacl() returning %d\n", status));
  985. diff --git a/daemon/upcall.h b/daemon/upcall.h
  986. index 5e78f54..1563c25 100644
  987. --- a/daemon/upcall.h
  988. +++ b/daemon/upcall.h
  989. @@ -198,13 +198,13 @@ typedef struct __volume_upcall_args {
  990.  } volume_upcall_args;
  991.  
  992.  typedef struct __getacl_upcall_args {
  993. -    SECURITY_INFORMATION query;
  994. +    SECURITY_INFORMATION query_secinfo;
  995.      PSECURITY_DESCRIPTOR sec_desc;
  996.      DWORD sec_desc_len;
  997.  } getacl_upcall_args;
  998.  
  999.  typedef struct __setacl_upcall_args {
  1000. -    SECURITY_INFORMATION query;
  1001. +    SECURITY_INFORMATION query_secinfo;
  1002.      PSECURITY_DESCRIPTOR sec_desc;
  1003.      ULONGLONG ctime;
  1004.  } setacl_upcall_args;
  1005. diff --git a/sys/nfs41sys_acl.c b/sys/nfs41sys_acl.c
  1006. index aef18d0..da293ec 100644
  1007. --- a/sys/nfs41sys_acl.c
  1008. +++ b/sys/nfs41sys_acl.c
  1009. @@ -90,7 +90,8 @@ NTSTATUS marshal_nfs41_getacl(
  1010.          goto out;
  1011.      }
  1012.  
  1013. -    RtlCopyMemory(tmp, &entry->u.Acl.query, sizeof(SECURITY_INFORMATION));
  1014. +    RtlCopyMemory(tmp,
  1015. +        &entry->u.Acl.query_secinfo, sizeof(SECURITY_INFORMATION));
  1016.      tmp += sizeof(SECURITY_INFORMATION);
  1017.  
  1018.      *len = (ULONG)(tmp - buf);
  1019. @@ -102,7 +103,8 @@ NTSTATUS marshal_nfs41_getacl(
  1020.      }
  1021.  
  1022.  #ifdef DEBUG_MARSHAL_DETAIL
  1023. -    DbgP("marshal_nfs41_getacl: class=0x%x\n", (int)entry->u.Acl.query);
  1024. +    DbgP("marshal_nfs41_getacl: class=0x%x\n",
  1025. +        (int)entry->u.Acl.query_secinfo);
  1026.  #endif
  1027.  out:
  1028.      return status;
  1029. @@ -130,7 +132,8 @@ NTSTATUS marshal_nfs41_setacl(
  1030.          goto out;
  1031.      }
  1032.  
  1033. -    RtlCopyMemory(tmp, &entry->u.Acl.query, sizeof(SECURITY_INFORMATION));
  1034. +    RtlCopyMemory(tmp,
  1035. +        &entry->u.Acl.query_secinfo, sizeof(SECURITY_INFORMATION));
  1036.      tmp += sizeof(SECURITY_INFORMATION);
  1037.      RtlCopyMemory(tmp, &entry->u.Acl.buf_len, sizeof(ULONG));
  1038.      tmp += sizeof(ULONG);
  1039. @@ -147,7 +150,7 @@ NTSTATUS marshal_nfs41_setacl(
  1040.  
  1041.  #ifdef DEBUG_MARSHAL_DETAIL
  1042.      DbgP("marshal_nfs41_setacl: class=0x%x sec_desc_len=%lu\n",
  1043. -         (int)entry->u.Acl.query, (long)entry->u.Acl.buf_len);
  1044. +         (int)entry->u.Acl.query_secinfo, (long)entry->u.Acl.buf_len);
  1045.  #endif
  1046.  out:
  1047.      return status;
  1048. @@ -204,12 +207,12 @@ NTSTATUS check_nfs41_getacl_args(
  1049.      PRX_CONTEXT RxContext)
  1050.  {
  1051.      NTSTATUS status = STATUS_SUCCESS;
  1052. -    SECURITY_INFORMATION info_class =
  1053. +    SECURITY_INFORMATION secinfo =
  1054.          RxContext->CurrentIrpSp->Parameters.QuerySecurity.SecurityInformation;
  1055.  
  1056.      /* we don't support sacls (yet) */
  1057. -    if (info_class == SACL_SECURITY_INFORMATION ||
  1058. -            info_class == LABEL_SECURITY_INFORMATION) {
  1059. +    if (secinfo == SACL_SECURITY_INFORMATION ||
  1060. +            secinfo == LABEL_SECURITY_INFORMATION) {
  1061.          DbgP("check_nfs41_getacl_args: SACLs not supported (yet)\n");
  1062.          status = STATUS_NOT_SUPPORTED;
  1063.          goto out;
  1064. @@ -235,7 +238,7 @@ NTSTATUS nfs41_QuerySecurityInformation(
  1065.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  1066.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  1067.          NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
  1068. -    SECURITY_INFORMATION info_class =
  1069. +    SECURITY_INFORMATION secinfo =
  1070.          RxContext->CurrentIrpSp->Parameters.QuerySecurity.SecurityInformation;
  1071.      ULONG querysecuritylength =
  1072.          RxContext->CurrentIrpSp->Parameters.QuerySecurity.Length;
  1073. @@ -247,7 +250,7 @@ NTSTATUS nfs41_QuerySecurityInformation(
  1074.  #ifdef DEBUG_ACL_QUERY
  1075.      DbgEn();
  1076.      print_debug_header(RxContext);
  1077. -    print_acl_args(info_class);
  1078. +    print_acl_args(secinfo);
  1079.  #endif
  1080.      FsRtlEnterFileSystem();
  1081.  
  1082. @@ -276,7 +279,7 @@ NTSTATUS nfs41_QuerySecurityInformation(
  1083.              }
  1084.  
  1085.              /* Check whether the cached info have all the info we need */
  1086. -            if ((nfs41_fobx->acl_secinfo & info_class) == info_class) {
  1087. +            if ((nfs41_fobx->acl_secinfo & secinfo) == secinfo) {
  1088.                  PSECURITY_DESCRIPTOR sec_desc = (PSECURITY_DESCRIPTOR)
  1089.                      RxContext->CurrentIrp->UserBuffer;
  1090.                  RtlCopyMemory(sec_desc, nfs41_fobx->acl, nfs41_fobx->acl_len);
  1091. @@ -293,9 +296,9 @@ NTSTATUS nfs41_QuerySecurityInformation(
  1092.              }
  1093.              else {
  1094.                  DbgP("nfs41_QuerySecurityInformation: "
  1095. -                    "cache misses requested info, acl_secinfo=0x%lx, info_class=0x%lx\n",
  1096. +                    "cache misses requested info, acl_secinfo=0x%lx, secinfo=0x%lx\n",
  1097.                      (unsigned long)nfs41_fobx->acl_secinfo,
  1098. -                    (unsigned long)info_class);
  1099. +                    (unsigned long)secinfo);
  1100.              }
  1101.          }
  1102.  
  1103. @@ -313,7 +316,7 @@ NTSTATUS nfs41_QuerySecurityInformation(
  1104.          pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  1105.      if (status) goto out;
  1106.  
  1107. -    entry->u.Acl.query = info_class;
  1108. +    entry->u.Acl.query_secinfo = secinfo;
  1109.      /* we can't provide RxContext->CurrentIrp->UserBuffer to the upcall thread
  1110.       * because it becomes an invalid pointer with that execution context
  1111.       */
  1112. @@ -353,7 +356,7 @@ NTSTATUS nfs41_QuerySecurityInformation(
  1113.  
  1114.          nfs41_fobx->acl = entry->u.Acl.buf;
  1115.          nfs41_fobx->acl_len = entry->u.Acl.buf_len;
  1116. -        nfs41_fobx->acl_secinfo = entry->u.Acl.query;
  1117. +        nfs41_fobx->acl_secinfo = entry->u.Acl.query_secinfo;
  1118.          entry->u.Acl.buf = NULL;
  1119.          KeQuerySystemTime(&nfs41_fobx->time);
  1120.  
  1121. @@ -406,7 +409,7 @@ NTSTATUS check_nfs41_setacl_args(
  1122.      NTSTATUS status = STATUS_SUCCESS;
  1123.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  1124.          NFS41GetVNetRootExtension(RxContext->pRelevantSrvOpen->pVNetRoot);
  1125. -    SECURITY_INFORMATION info_class =
  1126. +    SECURITY_INFORMATION secinfo =
  1127.          RxContext->CurrentIrpSp->Parameters.SetSecurity.SecurityInformation;
  1128.  
  1129.      if (pVNetRootContext->read_only) {
  1130. @@ -415,8 +418,8 @@ NTSTATUS check_nfs41_setacl_args(
  1131.          goto out;
  1132.      }
  1133.      /* we don't support sacls (yet) */
  1134. -    if (info_class == SACL_SECURITY_INFORMATION  ||
  1135. -            info_class == LABEL_SECURITY_INFORMATION) {
  1136. +    if (secinfo == SACL_SECURITY_INFORMATION  ||
  1137. +            secinfo == LABEL_SECURITY_INFORMATION) {
  1138.          DbgP("check_nfs41_setacl_args: SACLs not supported (yet)\n");
  1139.          status = STATUS_NOT_SUPPORTED;
  1140.          goto out;
  1141. @@ -439,7 +442,7 @@ NTSTATUS nfs41_SetSecurityInformation(
  1142.      __notnull PSECURITY_DESCRIPTOR sec_desc =
  1143.          RxContext->CurrentIrpSp->Parameters.SetSecurity.SecurityDescriptor;
  1144.      __notnull PNFS41_FCB nfs41_fcb = NFS41GetFcbExtension(RxContext->pFcb);
  1145. -    SECURITY_INFORMATION info_class =
  1146. +    SECURITY_INFORMATION secinfo =
  1147.          RxContext->CurrentIrpSp->Parameters.SetSecurity.SecurityInformation;
  1148.  #ifdef ENABLE_TIMINGS
  1149.      LARGE_INTEGER t1, t2;
  1150. @@ -449,7 +452,7 @@ NTSTATUS nfs41_SetSecurityInformation(
  1151.  #ifdef DEBUG_ACL_SET
  1152.      DbgEn();
  1153.      print_debug_header(RxContext);
  1154. -    print_acl_args(info_class);
  1155. +    print_acl_args(secinfo);
  1156.  #endif
  1157.      FsRtlEnterFileSystem();
  1158.  
  1159. @@ -457,7 +460,7 @@ NTSTATUS nfs41_SetSecurityInformation(
  1160.      if (status) goto out;
  1161.  
  1162.      /* check that ACL is present */
  1163. -    if (info_class & DACL_SECURITY_INFORMATION) {
  1164. +    if (secinfo & DACL_SECURITY_INFORMATION) {
  1165.          PACL acl;
  1166.          BOOLEAN present, dacl_default;
  1167.          status = RtlGetDaclSecurityDescriptor(sec_desc, &present, &acl,
  1168. @@ -478,7 +481,7 @@ NTSTATUS nfs41_SetSecurityInformation(
  1169.          pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  1170.      if (status) goto out;
  1171.  
  1172. -    entry->u.Acl.query = info_class;
  1173. +    entry->u.Acl.query_secinfo = secinfo;
  1174.      entry->u.Acl.buf = sec_desc;
  1175.      entry->u.Acl.buf_len = RtlLengthSecurityDescriptor(sec_desc);
  1176.  #ifdef ENABLE_TIMINGS
  1177. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  1178. index ad1b2f4..bc7537c 100644
  1179. --- a/sys/nfs41sys_driver.h
  1180. +++ b/sys/nfs41sys_driver.h
  1181. @@ -298,7 +298,7 @@ typedef struct _updowncall_entry {
  1182.              ULONG buf_len;
  1183.          } Volume;
  1184.          struct {
  1185. -            SECURITY_INFORMATION query;
  1186. +            SECURITY_INFORMATION query_secinfo;
  1187.              PVOID buf;
  1188.              ULONG buf_len;
  1189.          } Acl;
  1190. --
  1191. 2.51.0
  1192.  
  1193. From c559e5a22ca8aa4fe395e0e71b9f865ba0833be8 Mon Sep 17 00:00:00 2001
  1194. From: Roland Mainz <roland.mainz@nrubsig.org>
  1195. Date: Thu, 20 Nov 2025 21:57:16 +0100
  1196. Subject: [PATCH 11/28] sys: Fix tests for unsupported
  1197.  |SACL_SECURITY_INFORMATION|+|LABEL_SECURITY_INFORMATION|
  1198.  
  1199. Fix tests for unsupported |SACL_SECURITY_INFORMATION|+
  1200. |LABEL_SECURITY_INFORMATION|.
  1201.  
  1202. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  1203. ---
  1204. sys/nfs41sys_acl.c | 8 ++++----
  1205.  1 file changed, 4 insertions(+), 4 deletions(-)
  1206.  
  1207. diff --git a/sys/nfs41sys_acl.c b/sys/nfs41sys_acl.c
  1208. index da293ec..80060cb 100644
  1209. --- a/sys/nfs41sys_acl.c
  1210. +++ b/sys/nfs41sys_acl.c
  1211. @@ -211,8 +211,8 @@ NTSTATUS check_nfs41_getacl_args(
  1212.          RxContext->CurrentIrpSp->Parameters.QuerySecurity.SecurityInformation;
  1213.  
  1214.      /* we don't support sacls (yet) */
  1215. -    if (secinfo == SACL_SECURITY_INFORMATION ||
  1216. -            secinfo == LABEL_SECURITY_INFORMATION) {
  1217. +    if ((secinfo & SACL_SECURITY_INFORMATION) ||
  1218. +        (secinfo & LABEL_SECURITY_INFORMATION)) {
  1219.          DbgP("check_nfs41_getacl_args: SACLs not supported (yet)\n");
  1220.          status = STATUS_NOT_SUPPORTED;
  1221.          goto out;
  1222. @@ -418,8 +418,8 @@ NTSTATUS check_nfs41_setacl_args(
  1223.          goto out;
  1224.      }
  1225.      /* we don't support sacls (yet) */
  1226. -    if (secinfo == SACL_SECURITY_INFORMATION  ||
  1227. -            secinfo == LABEL_SECURITY_INFORMATION) {
  1228. +    if ((secinfo & SACL_SECURITY_INFORMATION) ||
  1229. +        (secinfo & LABEL_SECURITY_INFORMATION)) {
  1230.          DbgP("check_nfs41_setacl_args: SACLs not supported (yet)\n");
  1231.          status = STATUS_NOT_SUPPORTED;
  1232.          goto out;
  1233. --
  1234. 2.51.0
  1235.  
  1236. From 7ea5f19ac2bef56db9ec7e54947f75086913d8d7 Mon Sep 17 00:00:00 2001
  1237. From: Roland Mainz <roland.mainz@nrubsig.org>
  1238. Date: Fri, 21 Nov 2025 12:30:43 +0100
  1239. Subject: [PATCH 12/28] sys: Move acl cache variables int it's own sub-struct
  1240.  
  1241. Move acl cache variables int it's own sub-struct.
  1242.  
  1243. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  1244. ---
  1245. sys/nfs41sys_acl.c    | 71 +++++++++++++++++++++++--------------------
  1246.  sys/nfs41sys_driver.c |  6 ++--
  1247.  sys/nfs41sys_driver.h | 10 +++---
  1248.  3 files changed, 47 insertions(+), 40 deletions(-)
  1249.  
  1250. diff --git a/sys/nfs41sys_acl.c b/sys/nfs41sys_acl.c
  1251. index 80060cb..a927f09 100644
  1252. --- a/sys/nfs41sys_acl.c
  1253. +++ b/sys/nfs41sys_acl.c
  1254. @@ -257,38 +257,41 @@ NTSTATUS nfs41_QuerySecurityInformation(
  1255.      status = check_nfs41_getacl_args(RxContext);
  1256.      if (status) goto out;
  1257.  
  1258. -    if (nfs41_fobx->acl && nfs41_fobx->acl_len) {
  1259. +    if (nfs41_fobx->aclcache.data && nfs41_fobx->aclcache.data_len) {
  1260.          LARGE_INTEGER current_time;
  1261.          KeQuerySystemTime(&current_time);
  1262.  #ifdef DEBUG_ACL_QUERY
  1263.          DbgP("CurrentTime 0x%llx Saved Acl time 0x%llx\n",
  1264.              (long long)current_time.QuadPart,
  1265. -            (long long)nfs41_fobx->time.QuadPart);
  1266. +            (long long)nfs41_fobx->aclcache.time.QuadPart);
  1267.  #endif
  1268. -        if ((current_time.QuadPart - nfs41_fobx->time.QuadPart) <= (10*1000)) {
  1269. -            if (querysecuritylength < nfs41_fobx->acl_len) {
  1270. +        if ((current_time.QuadPart - nfs41_fobx->aclcache.time.QuadPart)
  1271. +            <= (10*1000)) {
  1272. +            if (querysecuritylength < nfs41_fobx->aclcache.data_len) {
  1273.                  status = STATUS_BUFFER_OVERFLOW;
  1274. -                RxContext->InformationToReturn = nfs41_fobx->acl_len;
  1275. +                RxContext->InformationToReturn = nfs41_fobx->aclcache.data_len;
  1276.  
  1277.                  DbgP("nfs41_QuerySecurityInformation: "
  1278.                      "STATUS_BUFFER_OVERFLOW for cached entry, "
  1279.                      "got %lu, need %lu\n",
  1280.                      (unsigned long)querysecuritylength,
  1281. -                    (unsigned long)nfs41_fobx->acl_len);
  1282. +                    (unsigned long)nfs41_fobx->aclcache.data_len);
  1283.                  goto out;
  1284.              }
  1285.  
  1286.              /* Check whether the cached info have all the info we need */
  1287. -            if ((nfs41_fobx->acl_secinfo & secinfo) == secinfo) {
  1288. +            if ((nfs41_fobx->aclcache.secinfo & secinfo) == secinfo) {
  1289.                  PSECURITY_DESCRIPTOR sec_desc = (PSECURITY_DESCRIPTOR)
  1290.                      RxContext->CurrentIrp->UserBuffer;
  1291. -                RtlCopyMemory(sec_desc, nfs41_fobx->acl, nfs41_fobx->acl_len);
  1292. +                RtlCopyMemory(sec_desc, nfs41_fobx->aclcache.data,
  1293. +                    nfs41_fobx->aclcache.data_len);
  1294.                  RxContext->IoStatusBlock.Information =
  1295. -                    RxContext->InformationToReturn = nfs41_fobx->acl_len;
  1296. +                    RxContext->InformationToReturn =
  1297. +                        nfs41_fobx->aclcache.data_len;
  1298.                  RxContext->IoStatusBlock.Status = status = STATUS_SUCCESS;
  1299.  #ifdef ENABLE_TIMINGS
  1300.                  InterlockedIncrement(&getacl.sops);
  1301. -                InterlockedAdd64(&getacl.size, nfs41_fobx->acl_len);
  1302. +                InterlockedAdd64(&getacl.size, nfs41_fobx->aclcache.data_len);
  1303.  #endif
  1304.  
  1305.                  DbgP("nfs41_QuerySecurityInformation: using cached ACL info\n");
  1306. @@ -296,17 +299,18 @@ NTSTATUS nfs41_QuerySecurityInformation(
  1307.              }
  1308.              else {
  1309.                  DbgP("nfs41_QuerySecurityInformation: "
  1310. -                    "cache misses requested info, acl_secinfo=0x%lx, secinfo=0x%lx\n",
  1311. -                    (unsigned long)nfs41_fobx->acl_secinfo,
  1312. +                    "cache misses requested info, "
  1313. +                    "acl_secinfo=0x%lx, secinfo=0x%lx\n",
  1314. +                    (unsigned long)nfs41_fobx->aclcache.secinfo,
  1315.                      (unsigned long)secinfo);
  1316.              }
  1317.          }
  1318.  
  1319. -        if (nfs41_fobx->acl) {
  1320. -            RxFreePool(nfs41_fobx->acl);
  1321. -            nfs41_fobx->acl = NULL;
  1322. -            nfs41_fobx->acl_len = 0;
  1323. -            nfs41_fobx->acl_secinfo = 0;
  1324. +        if (nfs41_fobx->aclcache.data) {
  1325. +            RxFreePool(nfs41_fobx->aclcache.data);
  1326. +            nfs41_fobx->aclcache.data = NULL;
  1327. +            nfs41_fobx->aclcache.data_len = 0;
  1328. +            nfs41_fobx->aclcache.secinfo = 0;
  1329.          }
  1330.          DbgP("nfs41_QuerySecurityInformation: cached ACL info invalidated\n");
  1331.      }
  1332. @@ -347,24 +351,25 @@ NTSTATUS nfs41_QuerySecurityInformation(
  1333.           * Free previous ACL data. This can happen if two concurrent
  1334.           * requests are executed for the same file
  1335.           */
  1336. -        if (nfs41_fobx->acl) {
  1337. -            RxFreePool(nfs41_fobx->acl);
  1338. -            nfs41_fobx->acl = NULL;
  1339. -            nfs41_fobx->acl_len = 0;
  1340. -            nfs41_fobx->acl_secinfo = 0;
  1341. +        if (nfs41_fobx->aclcache.data) {
  1342. +            RxFreePool(nfs41_fobx->aclcache.data);
  1343. +            nfs41_fobx->aclcache.data = NULL;
  1344. +            nfs41_fobx->aclcache.data_len = 0;
  1345. +            nfs41_fobx->aclcache.secinfo = 0;
  1346.          }
  1347.  
  1348. -        nfs41_fobx->acl = entry->u.Acl.buf;
  1349. -        nfs41_fobx->acl_len = entry->u.Acl.buf_len;
  1350. -        nfs41_fobx->acl_secinfo = entry->u.Acl.query_secinfo;
  1351. +        nfs41_fobx->aclcache.data = entry->u.Acl.buf;
  1352. +        nfs41_fobx->aclcache.data_len = entry->u.Acl.buf_len;
  1353. +        nfs41_fobx->aclcache.secinfo = entry->u.Acl.query_secinfo;
  1354.          entry->u.Acl.buf = NULL;
  1355. -        KeQuerySystemTime(&nfs41_fobx->time);
  1356. +        KeQuerySystemTime(&nfs41_fobx->aclcache.time);
  1357.  
  1358.          PSECURITY_DESCRIPTOR sec_desc = (PSECURITY_DESCRIPTOR)
  1359.              RxContext->CurrentIrp->UserBuffer;
  1360. -        RtlCopyMemory(sec_desc, nfs41_fobx->acl, nfs41_fobx->acl_len);
  1361. +        RtlCopyMemory(sec_desc, nfs41_fobx->aclcache.data,
  1362. +            nfs41_fobx->aclcache.data_len);
  1363.          RxContext->IoStatusBlock.Information =
  1364. -            RxContext->InformationToReturn = nfs41_fobx->acl_len;
  1365. +            RxContext->InformationToReturn = nfs41_fobx->aclcache.data_len;
  1366.          RxContext->IoStatusBlock.Status = status = STATUS_SUCCESS;
  1367.  
  1368.  #ifdef ENABLE_TIMINGS
  1369. @@ -490,11 +495,11 @@ NTSTATUS nfs41_SetSecurityInformation(
  1370.  #endif
  1371.  
  1372.      /* Invalidate cached ACL info */
  1373. -    if (nfs41_fobx->acl) {
  1374. -        RxFreePool(nfs41_fobx->acl);
  1375. -        nfs41_fobx->acl = NULL;
  1376. -        nfs41_fobx->acl_len = 0;
  1377. -        nfs41_fobx->acl_secinfo = 0;
  1378. +    if (nfs41_fobx->aclcache.data) {
  1379. +        RxFreePool(nfs41_fobx->aclcache.data);
  1380. +        nfs41_fobx->aclcache.data = NULL;
  1381. +        nfs41_fobx->aclcache.data_len = 0;
  1382. +        nfs41_fobx->aclcache.secinfo = 0;
  1383.      }
  1384.  
  1385.      status = nfs41_UpcallWaitForReply(entry, pVNetRootContext->timeout);
  1386. diff --git a/sys/nfs41sys_driver.c b/sys/nfs41sys_driver.c
  1387. index 1ae41e0..df76d8a 100644
  1388. --- a/sys/nfs41sys_driver.c
  1389. +++ b/sys/nfs41sys_driver.c
  1390. @@ -918,9 +918,9 @@ NTSTATUS nfs41_DeallocateForFobx(
  1391.      nfs41_invalidate_fobx_entry(pFobx);
  1392.      nfs41_remove_offloadcontext_for_fobx(pFobx);
  1393.  
  1394. -    if (nfs41_fobx->acl) {
  1395. -        RxFreePool(nfs41_fobx->acl);
  1396. -        nfs41_fobx->acl = NULL;
  1397. +    if (nfs41_fobx->aclcache.data) {
  1398. +        RxFreePool(nfs41_fobx->aclcache.data);
  1399. +        nfs41_fobx->aclcache.data = NULL;
  1400.      }
  1401.  
  1402.      if (nfs41_fobx->sec_ctx.ClientToken) {
  1403. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  1404. index bc7537c..e559109 100644
  1405. --- a/sys/nfs41sys_driver.h
  1406. +++ b/sys/nfs41sys_driver.h
  1407. @@ -494,10 +494,12 @@ typedef struct _NFS41_FOBX {
  1408.  
  1409.      HANDLE nfs41_open_state;
  1410.      SECURITY_CLIENT_CONTEXT sec_ctx;
  1411. -    PVOID acl;
  1412. -    DWORD acl_len;
  1413. -    SECURITY_INFORMATION acl_secinfo;
  1414. -    LARGE_INTEGER time;
  1415. +    struct {
  1416. +        PVOID data;
  1417. +        DWORD data_len;
  1418. +        SECURITY_INFORMATION secinfo;
  1419. +        LARGE_INTEGER time;
  1420. +    } aclcache;
  1421.      DWORD deleg_type;
  1422.      BOOLEAN write_thru;
  1423.      BOOLEAN nocache;
  1424. --
  1425. 2.51.0
  1426.  
  1427. From 396803642a9bc4263ee4706fc57093d33fdfb32a Mon Sep 17 00:00:00 2001
  1428. From: Roland Mainz <roland.mainz@nrubsig.org>
  1429. Date: Fri, 21 Nov 2025 15:08:02 +0100
  1430. Subject: [PATCH 13/28] sys: Move ACL cache to FCB so multiple FILE_OBJECTs can
  1431.  share it
  1432.  
  1433. Move ACL cache to FCB so multiple FILE_OBJECTs can share it.
  1434.  
  1435. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  1436. ---
  1437. sys/nfs41sys_acl.c    | 78 ++++++++++++++++++++++++-------------------
  1438.  sys/nfs41sys_driver.c | 13 +++++---
  1439.  sys/nfs41sys_driver.h | 12 +++----
  1440.  3 files changed, 58 insertions(+), 45 deletions(-)
  1441.  
  1442. diff --git a/sys/nfs41sys_acl.c b/sys/nfs41sys_acl.c
  1443. index a927f09..a9f4200 100644
  1444. --- a/sys/nfs41sys_acl.c
  1445. +++ b/sys/nfs41sys_acl.c
  1446. @@ -234,6 +234,7 @@ NTSTATUS nfs41_QuerySecurityInformation(
  1447.      nfs41_updowncall_entry *entry = NULL;
  1448.      __notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
  1449.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  1450. +    __notnull PNFS41_FCB nfs41_fcb = NFS41GetFcbExtension(RxContext->pFcb);
  1451.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  1452.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  1453.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  1454. @@ -257,41 +258,41 @@ NTSTATUS nfs41_QuerySecurityInformation(
  1455.      status = check_nfs41_getacl_args(RxContext);
  1456.      if (status) goto out;
  1457.  
  1458. -    if (nfs41_fobx->aclcache.data && nfs41_fobx->aclcache.data_len) {
  1459. +    if (nfs41_fcb->aclcache.data && nfs41_fcb->aclcache.data_len) {
  1460.          LARGE_INTEGER current_time;
  1461.          KeQuerySystemTime(&current_time);
  1462.  #ifdef DEBUG_ACL_QUERY
  1463.          DbgP("CurrentTime 0x%llx Saved Acl time 0x%llx\n",
  1464.              (long long)current_time.QuadPart,
  1465. -            (long long)nfs41_fobx->aclcache.time.QuadPart);
  1466. +            (long long)nfs41_fcb->aclcache.time.QuadPart);
  1467.  #endif
  1468. -        if ((current_time.QuadPart - nfs41_fobx->aclcache.time.QuadPart)
  1469. +        if ((current_time.QuadPart - nfs41_fcb->aclcache.time.QuadPart)
  1470.              <= (10*1000)) {
  1471. -            if (querysecuritylength < nfs41_fobx->aclcache.data_len) {
  1472. +            if (querysecuritylength < nfs41_fcb->aclcache.data_len) {
  1473.                  status = STATUS_BUFFER_OVERFLOW;
  1474. -                RxContext->InformationToReturn = nfs41_fobx->aclcache.data_len;
  1475. +                RxContext->InformationToReturn = nfs41_fcb->aclcache.data_len;
  1476.  
  1477.                  DbgP("nfs41_QuerySecurityInformation: "
  1478.                      "STATUS_BUFFER_OVERFLOW for cached entry, "
  1479.                      "got %lu, need %lu\n",
  1480.                      (unsigned long)querysecuritylength,
  1481. -                    (unsigned long)nfs41_fobx->aclcache.data_len);
  1482. +                    (unsigned long)nfs41_fcb->aclcache.data_len);
  1483.                  goto out;
  1484.              }
  1485.  
  1486.              /* Check whether the cached info have all the info we need */
  1487. -            if ((nfs41_fobx->aclcache.secinfo & secinfo) == secinfo) {
  1488. +            if ((nfs41_fcb->aclcache.secinfo & secinfo) == secinfo) {
  1489.                  PSECURITY_DESCRIPTOR sec_desc = (PSECURITY_DESCRIPTOR)
  1490.                      RxContext->CurrentIrp->UserBuffer;
  1491. -                RtlCopyMemory(sec_desc, nfs41_fobx->aclcache.data,
  1492. -                    nfs41_fobx->aclcache.data_len);
  1493. +                RtlCopyMemory(sec_desc, nfs41_fcb->aclcache.data,
  1494. +                    nfs41_fcb->aclcache.data_len);
  1495.                  RxContext->IoStatusBlock.Information =
  1496.                      RxContext->InformationToReturn =
  1497. -                        nfs41_fobx->aclcache.data_len;
  1498. +                        nfs41_fcb->aclcache.data_len;
  1499.                  RxContext->IoStatusBlock.Status = status = STATUS_SUCCESS;
  1500.  #ifdef ENABLE_TIMINGS
  1501.                  InterlockedIncrement(&getacl.sops);
  1502. -                InterlockedAdd64(&getacl.size, nfs41_fobx->aclcache.data_len);
  1503. +                InterlockedAdd64(&getacl.size, nfs41_fcb->aclcache.data_len);
  1504.  #endif
  1505.  
  1506.                  DbgP("nfs41_QuerySecurityInformation: using cached ACL info\n");
  1507. @@ -301,16 +302,22 @@ NTSTATUS nfs41_QuerySecurityInformation(
  1508.                  DbgP("nfs41_QuerySecurityInformation: "
  1509.                      "cache misses requested info, "
  1510.                      "acl_secinfo=0x%lx, secinfo=0x%lx\n",
  1511. -                    (unsigned long)nfs41_fobx->aclcache.secinfo,
  1512. +                    (unsigned long)nfs41_fcb->aclcache.secinfo,
  1513.                      (unsigned long)secinfo);
  1514.              }
  1515.          }
  1516. +        else {
  1517. +            DbgP("nfs41_QuerySecurityInformation: acl cache expired, "
  1518. +                "current_time=%llu, nfs41_fcb->aclcache.time=%llu\n",
  1519. +                current_time.QuadPart, nfs41_fcb->aclcache.time.QuadPart);
  1520. +        }
  1521.  
  1522. -        if (nfs41_fobx->aclcache.data) {
  1523. -            RxFreePool(nfs41_fobx->aclcache.data);
  1524. -            nfs41_fobx->aclcache.data = NULL;
  1525. -            nfs41_fobx->aclcache.data_len = 0;
  1526. -            nfs41_fobx->aclcache.secinfo = 0;
  1527. +        if (nfs41_fcb->aclcache.data) {
  1528. +            RxFreePool(nfs41_fcb->aclcache.data);
  1529. +            nfs41_fcb->aclcache.data = NULL;
  1530. +            nfs41_fcb->aclcache.data_len = 0;
  1531. +            nfs41_fcb->aclcache.secinfo = 0;
  1532. +            nfs41_fcb->aclcache.time.QuadPart = 0LL;
  1533.          }
  1534.          DbgP("nfs41_QuerySecurityInformation: cached ACL info invalidated\n");
  1535.      }
  1536. @@ -351,25 +358,26 @@ NTSTATUS nfs41_QuerySecurityInformation(
  1537.           * Free previous ACL data. This can happen if two concurrent
  1538.           * requests are executed for the same file
  1539.           */
  1540. -        if (nfs41_fobx->aclcache.data) {
  1541. -            RxFreePool(nfs41_fobx->aclcache.data);
  1542. -            nfs41_fobx->aclcache.data = NULL;
  1543. -            nfs41_fobx->aclcache.data_len = 0;
  1544. -            nfs41_fobx->aclcache.secinfo = 0;
  1545. +        if (nfs41_fcb->aclcache.data) {
  1546. +            RxFreePool(nfs41_fcb->aclcache.data);
  1547. +            nfs41_fcb->aclcache.data = NULL;
  1548. +            nfs41_fcb->aclcache.data_len = 0;
  1549. +            nfs41_fcb->aclcache.secinfo = 0;
  1550. +            nfs41_fcb->aclcache.time.QuadPart = 0LL;
  1551.          }
  1552.  
  1553. -        nfs41_fobx->aclcache.data = entry->u.Acl.buf;
  1554. -        nfs41_fobx->aclcache.data_len = entry->u.Acl.buf_len;
  1555. -        nfs41_fobx->aclcache.secinfo = entry->u.Acl.query_secinfo;
  1556. +        nfs41_fcb->aclcache.data = entry->u.Acl.buf;
  1557. +        nfs41_fcb->aclcache.data_len = entry->u.Acl.buf_len;
  1558. +        nfs41_fcb->aclcache.secinfo = entry->u.Acl.query_secinfo;
  1559.          entry->u.Acl.buf = NULL;
  1560. -        KeQuerySystemTime(&nfs41_fobx->aclcache.time);
  1561. +        KeQuerySystemTime(&nfs41_fcb->aclcache.time);
  1562.  
  1563.          PSECURITY_DESCRIPTOR sec_desc = (PSECURITY_DESCRIPTOR)
  1564.              RxContext->CurrentIrp->UserBuffer;
  1565. -        RtlCopyMemory(sec_desc, nfs41_fobx->aclcache.data,
  1566. -            nfs41_fobx->aclcache.data_len);
  1567. +        RtlCopyMemory(sec_desc, nfs41_fcb->aclcache.data,
  1568. +            nfs41_fcb->aclcache.data_len);
  1569.          RxContext->IoStatusBlock.Information =
  1570. -            RxContext->InformationToReturn = nfs41_fobx->aclcache.data_len;
  1571. +            RxContext->InformationToReturn = nfs41_fcb->aclcache.data_len;
  1572.          RxContext->IoStatusBlock.Status = status = STATUS_SUCCESS;
  1573.  
  1574.  #ifdef ENABLE_TIMINGS
  1575. @@ -414,6 +422,7 @@ NTSTATUS check_nfs41_setacl_args(
  1576.      NTSTATUS status = STATUS_SUCCESS;
  1577.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  1578.          NFS41GetVNetRootExtension(RxContext->pRelevantSrvOpen->pVNetRoot);
  1579. +
  1580.      SECURITY_INFORMATION secinfo =
  1581.          RxContext->CurrentIrpSp->Parameters.SetSecurity.SecurityInformation;
  1582.  
  1583. @@ -495,11 +504,12 @@ NTSTATUS nfs41_SetSecurityInformation(
  1584.  #endif
  1585.  
  1586.      /* Invalidate cached ACL info */
  1587. -    if (nfs41_fobx->aclcache.data) {
  1588. -        RxFreePool(nfs41_fobx->aclcache.data);
  1589. -        nfs41_fobx->aclcache.data = NULL;
  1590. -        nfs41_fobx->aclcache.data_len = 0;
  1591. -        nfs41_fobx->aclcache.secinfo = 0;
  1592. +    if (nfs41_fcb->aclcache.data) {
  1593. +        RxFreePool(nfs41_fcb->aclcache.data);
  1594. +        nfs41_fcb->aclcache.data = NULL;
  1595. +        nfs41_fcb->aclcache.data_len = 0;
  1596. +        nfs41_fcb->aclcache.secinfo = 0;
  1597. +        nfs41_fcb->aclcache.time.QuadPart = 0LL;
  1598.      }
  1599.  
  1600.      status = nfs41_UpcallWaitForReply(entry, pVNetRootContext->timeout);
  1601. diff --git a/sys/nfs41sys_driver.c b/sys/nfs41sys_driver.c
  1602. index df76d8a..4ea927a 100644
  1603. --- a/sys/nfs41sys_driver.c
  1604. +++ b/sys/nfs41sys_driver.c
  1605. @@ -906,7 +906,15 @@ NTSTATUS nfs41_Flush(
  1606.  NTSTATUS nfs41_DeallocateForFcb(
  1607.      IN OUT PMRX_FCB pFcb)
  1608.  {
  1609. +    __notnull PNFS41_FCB nfs41_fcb = NFS41GetFcbExtension(pFcb);
  1610. +
  1611.      nfs41_remove_fcb_entry(pFcb);
  1612. +
  1613. +    if (nfs41_fcb->aclcache.data) {
  1614. +        RxFreePool(nfs41_fcb->aclcache.data);
  1615. +        nfs41_fcb->aclcache.data = NULL;
  1616. +    }
  1617. +
  1618.      return STATUS_SUCCESS;
  1619.  }
  1620.  
  1621. @@ -918,11 +926,6 @@ NTSTATUS nfs41_DeallocateForFobx(
  1622.      nfs41_invalidate_fobx_entry(pFobx);
  1623.      nfs41_remove_offloadcontext_for_fobx(pFobx);
  1624.  
  1625. -    if (nfs41_fobx->aclcache.data) {
  1626. -        RxFreePool(nfs41_fobx->aclcache.data);
  1627. -        nfs41_fobx->aclcache.data = NULL;
  1628. -    }
  1629. -
  1630.      if (nfs41_fobx->sec_ctx.ClientToken) {
  1631.          SeDeleteClientSecurity(&nfs41_fobx->sec_ctx);
  1632.          nfs41_fobx->sec_ctx.ClientToken = NULL;
  1633. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  1634. index e559109..4ef084a 100644
  1635. --- a/sys/nfs41sys_driver.h
  1636. +++ b/sys/nfs41sys_driver.h
  1637. @@ -483,6 +483,12 @@ typedef struct _NFS41_FCB {
  1638.      DWORD                   owner_local_uid;       /* owner mapped into local uid */
  1639.      DWORD                   owner_group_local_gid; /* owner group mapped into local gid */
  1640.  #endif /* NFS41_DRIVER_FEATURE_LOCAL_UIDGID_IN_NFSV3ATTRIBUTES */
  1641. +    struct {
  1642. +        PVOID data;
  1643. +        DWORD data_len;
  1644. +        SECURITY_INFORMATION secinfo;
  1645. +        LARGE_INTEGER time;
  1646. +    } aclcache;
  1647.      ULONGLONG               changeattr;
  1648.  } NFS41_FCB, *PNFS41_FCB;
  1649.  #define NFS41GetFcbExtension(pFcb)      \
  1650. @@ -494,12 +500,6 @@ typedef struct _NFS41_FOBX {
  1651.  
  1652.      HANDLE nfs41_open_state;
  1653.      SECURITY_CLIENT_CONTEXT sec_ctx;
  1654. -    struct {
  1655. -        PVOID data;
  1656. -        DWORD data_len;
  1657. -        SECURITY_INFORMATION secinfo;
  1658. -        LARGE_INTEGER time;
  1659. -    } aclcache;
  1660.      DWORD deleg_type;
  1661.      BOOLEAN write_thru;
  1662.      BOOLEAN nocache;
  1663. --
  1664. 2.51.0
  1665.  
  1666. From 3aca058e0b313786e6bd14313ccba2da2fa1ecd7 Mon Sep 17 00:00:00 2001
  1667. From: Roland Mainz <roland.mainz@nrubsig.org>
  1668. Date: Fri, 21 Nov 2025 15:08:52 +0100
  1669. Subject: [PATCH 14/28] sys: Set ACL cache timeout to 10 seconds
  1670.  
  1671. Set ACL cache timeout to 10 seconds.
  1672.  
  1673. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  1674. ---
  1675. sys/nfs41sys_acl.c | 2 +-
  1676.  1 file changed, 1 insertion(+), 1 deletion(-)
  1677.  
  1678. diff --git a/sys/nfs41sys_acl.c b/sys/nfs41sys_acl.c
  1679. index a9f4200..9ad1036 100644
  1680. --- a/sys/nfs41sys_acl.c
  1681. +++ b/sys/nfs41sys_acl.c
  1682. @@ -267,7 +267,7 @@ NTSTATUS nfs41_QuerySecurityInformation(
  1683.              (long long)nfs41_fcb->aclcache.time.QuadPart);
  1684.  #endif
  1685.          if ((current_time.QuadPart - nfs41_fcb->aclcache.time.QuadPart)
  1686. -            <= (10*1000)) {
  1687. +            <= (10*10000000)) {
  1688.              if (querysecuritylength < nfs41_fcb->aclcache.data_len) {
  1689.                  status = STATUS_BUFFER_OVERFLOW;
  1690.                  RxContext->InformationToReturn = nfs41_fcb->aclcache.data_len;
  1691. --
  1692. 2.51.0
  1693.  
  1694. From bac22964088557658d5436442245e5fa2bbc4dc2 Mon Sep 17 00:00:00 2001
  1695. From: Roland Mainz <roland.mainz@nrubsig.org>
  1696. Date: Fri, 21 Nov 2025 15:58:59 +0100
  1697. Subject: [PATCH 15/28] sys: Remove checks for
  1698.  |SACL_SECURITY_INFORMATION|+|LABEL_SECURITY_INFORMATION|
  1699.  
  1700. Remove checks for |SACL_SECURITY_INFORMATION|+|LABEL_SECURITY_INFORMATION|,
  1701. they are not really needed.
  1702.  
  1703. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  1704. ---
  1705. sys/nfs41sys_acl.c | 20 --------------------
  1706.  1 file changed, 20 deletions(-)
  1707.  
  1708. diff --git a/sys/nfs41sys_acl.c b/sys/nfs41sys_acl.c
  1709. index 9ad1036..d9a67e7 100644
  1710. --- a/sys/nfs41sys_acl.c
  1711. +++ b/sys/nfs41sys_acl.c
  1712. @@ -207,23 +207,13 @@ NTSTATUS check_nfs41_getacl_args(
  1713.      PRX_CONTEXT RxContext)
  1714.  {
  1715.      NTSTATUS status = STATUS_SUCCESS;
  1716. -    SECURITY_INFORMATION secinfo =
  1717. -        RxContext->CurrentIrpSp->Parameters.QuerySecurity.SecurityInformation;
  1718.  
  1719. -    /* we don't support sacls (yet) */
  1720. -    if ((secinfo & SACL_SECURITY_INFORMATION) ||
  1721. -        (secinfo & LABEL_SECURITY_INFORMATION)) {
  1722. -        DbgP("check_nfs41_getacl_args: SACLs not supported (yet)\n");
  1723. -        status = STATUS_NOT_SUPPORTED;
  1724. -        goto out;
  1725. -    }
  1726.      if (RxContext->CurrentIrp->UserBuffer == NULL &&
  1727.              RxContext->CurrentIrpSp->Parameters.QuerySecurity.Length) {
  1728.          DbgP("check_nfs41_getacl_args: "
  1729.              "RxContext->CurrentIrp->UserBuffer == NULL\n");
  1730.          status = STATUS_INVALID_USER_BUFFER;
  1731.      }
  1732. -out:
  1733.      return status;
  1734.  }
  1735.  
  1736. @@ -423,21 +413,11 @@ NTSTATUS check_nfs41_setacl_args(
  1737.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  1738.          NFS41GetVNetRootExtension(RxContext->pRelevantSrvOpen->pVNetRoot);
  1739.  
  1740. -    SECURITY_INFORMATION secinfo =
  1741. -        RxContext->CurrentIrpSp->Parameters.SetSecurity.SecurityInformation;
  1742. -
  1743.      if (pVNetRootContext->read_only) {
  1744.          print_error("check_nfs41_setacl_args: Read-only mount\n");
  1745.          status = STATUS_MEDIA_WRITE_PROTECTED;
  1746.          goto out;
  1747.      }
  1748. -    /* we don't support sacls (yet) */
  1749. -    if ((secinfo & SACL_SECURITY_INFORMATION) ||
  1750. -        (secinfo & LABEL_SECURITY_INFORMATION)) {
  1751. -        DbgP("check_nfs41_setacl_args: SACLs not supported (yet)\n");
  1752. -        status = STATUS_NOT_SUPPORTED;
  1753. -        goto out;
  1754. -    }
  1755.  out:
  1756.      return status;
  1757.  }
  1758. --
  1759. 2.51.0
  1760.  
  1761. From 8927f158e6cee9f8f07085170b856c7b7ad58b22 Mon Sep 17 00:00:00 2001
  1762. From: Roland Mainz <roland.mainz@nrubsig.org>
  1763. Date: Sat, 22 Nov 2025 12:50:48 +0100
  1764. Subject: [PATCH 16/28] sys: Add |FAST_MUTEX| for ACL cache
  1765.  
  1766. Add |FAST_MUTEX| for ACL cache.
  1767.  
  1768. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  1769. ---
  1770. sys/nfs41sys_acl.c       | 20 +++++++++++++++++++-
  1771.  sys/nfs41sys_driver.h    |  2 ++
  1772.  sys/nfs41sys_openclose.c |  5 +++++
  1773.  3 files changed, 26 insertions(+), 1 deletion(-)
  1774.  
  1775. diff --git a/sys/nfs41sys_acl.c b/sys/nfs41sys_acl.c
  1776. index d9a67e7..2c94021 100644
  1777. --- a/sys/nfs41sys_acl.c
  1778. +++ b/sys/nfs41sys_acl.c
  1779. @@ -58,6 +58,7 @@
  1780.  #include <winerror.h>
  1781.  
  1782.  #include <Ntstrsafe.h>
  1783. +#include <stdbool.h>
  1784.  
  1785.  #include "nfs41sys_buildconfig.h"
  1786.  
  1787. @@ -233,6 +234,8 @@ NTSTATUS nfs41_QuerySecurityInformation(
  1788.          RxContext->CurrentIrpSp->Parameters.QuerySecurity.SecurityInformation;
  1789.      ULONG querysecuritylength =
  1790.          RxContext->CurrentIrpSp->Parameters.QuerySecurity.Length;
  1791. +    bool aclcache_locked = false;
  1792. +
  1793.  #ifdef ENABLE_TIMINGS
  1794.      LARGE_INTEGER t1, t2;
  1795.      t1 = KeQueryPerformanceCounter(NULL);
  1796. @@ -248,6 +251,9 @@ NTSTATUS nfs41_QuerySecurityInformation(
  1797.      status = check_nfs41_getacl_args(RxContext);
  1798.      if (status) goto out;
  1799.  
  1800. +    ExAcquireFastMutexUnsafe(&nfs41_fcb->aclcache.lock);
  1801. +    aclcache_locked = true;
  1802. +
  1803.      if (nfs41_fcb->aclcache.data && nfs41_fcb->aclcache.data_len) {
  1804.          LARGE_INTEGER current_time;
  1805.          KeQuerySystemTime(&current_time);
  1806. @@ -382,7 +388,12 @@ NTSTATUS nfs41_QuerySecurityInformation(
  1807.              entry->u.Acl.buf = NULL;
  1808.          }
  1809.      }
  1810. +
  1811.  out:
  1812. +    if (aclcache_locked) {
  1813. +        ExReleaseFastMutexUnsafe(&nfs41_fcb->aclcache.lock);
  1814. +    }
  1815. +
  1816.      if (entry) {
  1817.          nfs41_UpcallDestroy(entry);
  1818.      }
  1819. @@ -438,6 +449,7 @@ NTSTATUS nfs41_SetSecurityInformation(
  1820.      __notnull PNFS41_FCB nfs41_fcb = NFS41GetFcbExtension(RxContext->pFcb);
  1821.      SECURITY_INFORMATION secinfo =
  1822.          RxContext->CurrentIrpSp->Parameters.SetSecurity.SecurityInformation;
  1823. +
  1824.  #ifdef ENABLE_TIMINGS
  1825.      LARGE_INTEGER t1, t2;
  1826.      t1 = KeQueryPerformanceCounter(NULL);
  1827. @@ -483,7 +495,12 @@ NTSTATUS nfs41_SetSecurityInformation(
  1828.      InterlockedAdd64(&setacl.size, entry->u.Acl.buf_len);
  1829.  #endif
  1830.  
  1831. -    /* Invalidate cached ACL info */
  1832. +    /*
  1833. +     * Invalidate cached ACL info
  1834. +     * (we do not try to fill the cache afte a |NFS41_SYSOP_ACL_SET|
  1835. +     * because it is typically not read after that)
  1836. +     */
  1837. +    ExAcquireFastMutexUnsafe(&nfs41_fcb->aclcache.lock);
  1838.      if (nfs41_fcb->aclcache.data) {
  1839.          RxFreePool(nfs41_fcb->aclcache.data);
  1840.          nfs41_fcb->aclcache.data = NULL;
  1841. @@ -491,6 +508,7 @@ NTSTATUS nfs41_SetSecurityInformation(
  1842.          nfs41_fcb->aclcache.secinfo = 0;
  1843.          nfs41_fcb->aclcache.time.QuadPart = 0LL;
  1844.      }
  1845. +    ExReleaseFastMutexUnsafe(&nfs41_fcb->aclcache.lock);
  1846.  
  1847.      status = nfs41_UpcallWaitForReply(entry, pVNetRootContext->timeout);
  1848.      if (status) {
  1849. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  1850. index 4ef084a..0296a91 100644
  1851. --- a/sys/nfs41sys_driver.h
  1852. +++ b/sys/nfs41sys_driver.h
  1853. @@ -472,6 +472,7 @@ typedef struct _NFS41_V_NET_ROOT_EXTENSION {
  1854.  typedef struct _NFS41_FCB {
  1855.      NODE_TYPE_CODE          NodeTypeCode;
  1856.      NODE_BYTE_SIZE          NodeByteSize;
  1857. +    BOOLEAN                 initialised;
  1858.      FILE_BASIC_INFORMATION  BasicInfo;
  1859.      FILE_STANDARD_INFORMATION StandardInfo;
  1860.      ULONGLONG               fileid;
  1861. @@ -484,6 +485,7 @@ typedef struct _NFS41_FCB {
  1862.      DWORD                   owner_group_local_gid; /* owner group mapped into local gid */
  1863.  #endif /* NFS41_DRIVER_FEATURE_LOCAL_UIDGID_IN_NFSV3ATTRIBUTES */
  1864.      struct {
  1865. +        FAST_MUTEX lock;
  1866.          PVOID data;
  1867.          DWORD data_len;
  1868.          SECURITY_INFORMATION secinfo;
  1869. diff --git a/sys/nfs41sys_openclose.c b/sys/nfs41sys_openclose.c
  1870. index 53bb879..7a09cd8 100644
  1871. --- a/sys/nfs41sys_openclose.c
  1872. +++ b/sys/nfs41sys_openclose.c
  1873. @@ -655,6 +655,11 @@ NTSTATUS nfs41_Create(
  1874.      status = check_nfs41_create_args(RxContext);
  1875.      if (status) goto out;
  1876.  
  1877. +    if (nfs41_fcb->initialised == FALSE) {
  1878. +        nfs41_fcb->initialised = TRUE;
  1879. +        ExInitializeFastMutex(&nfs41_fcb->aclcache.lock);
  1880. +    }
  1881. +
  1882.      debug_printirpecps(RxContext->CurrentIrp);
  1883.  
  1884.      PQUERY_ON_CREATE_ECP_CONTEXT qocec =
  1885. --
  1886. 2.51.0
  1887.  
  1888. From 5257bf034e6dfaa883d1523a39f80d19bc8c5ddc Mon Sep 17 00:00:00 2001
  1889. From: Roland Mainz <roland.mainz@nrubsig.org>
  1890. Date: Sat, 22 Nov 2025 22:37:24 +0100
  1891. Subject: [PATCH 17/28] tests: Update NTP&co instructions for NFS test server
  1892.  setups
  1893.  
  1894. Update NTP&co instructions for NFS test server setups.
  1895.  
  1896. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  1897. ---
  1898. tests/nfs_server_setup.txt | 29 ++++++++++++++++++++++++-----
  1899.  1 file changed, 24 insertions(+), 5 deletions(-)
  1900.  
  1901. diff --git a/tests/nfs_server_setup.txt b/tests/nfs_server_setup.txt
  1902. index d945ec7..cafdaeb 100644
  1903. --- a/tests/nfs_server_setup.txt
  1904. +++ b/tests/nfs_server_setup.txt
  1905. @@ -85,6 +85,13 @@ service nfs-server restart
  1906.  # Adminstrator PowerShell
  1907.  Install-WindowsFeature -name Telnet-Client
  1908.  
  1909. +# make sure the time sync service is running and uses a valid ntp server:
  1910. +sc config w32time start=auto
  1911. +sc start w32time
  1912. +w32tm /config /update /manualpeerlist:10.49.0.6
  1913. +# wait 30sec and then verify the status:
  1914. +w32tm /query /status
  1915. +
  1916.  Import-Module ServerManager
  1917.  Add-WindowsFeature FS-NFS-Service
  1918.  Import-Module NFS
  1919. @@ -114,8 +121,8 @@ C:\cygwin64\sbin\nfs_mount -o rw N nfs://192.168.209.129//
  1920.  #
  1921.  
  1922.  ##### 1. Server setup
  1923. -# enable ntp server "10.49.0.5"
  1924. -printf "server 10.49.0.5\n" >/etc/inet/ntp.conf
  1925. +# enable ntp server "10.49.0.6"
  1926. +printf "server 10.49.0.6\n" >'/etc/inet/ntp.conf'
  1927.  svcadm enable ntp
  1928.  
  1929.  # configure&start NFS server
  1930. @@ -156,8 +163,8 @@ See https://docs.oracle.com/en/operating-systems/solaris/oracle-solaris/11.4/man
  1931.  #
  1932.  
  1933.  ##### 1. Server setup
  1934. -# enable ntp server "10.49.0.5"
  1935. -printf "server 10.49.0.5\n" >/etc/inet/ntp.conf
  1936. +# enable ntp server "10.49.0.6"
  1937. +printf "server 10.49.0.6\n" >'/etc/inet/ntp.conf'
  1938.  svcadm enable ntp
  1939.  svcadm restart ntp
  1940.  
  1941. @@ -205,6 +212,17 @@ See https://docs.oracle.com/en/operating-systems/solaris/oracle-solaris/11.4/man
  1942.  
  1943.  # Install FreeBSD (14.3) with NTP enabled
  1944.  
  1945. +# enable time server
  1946. +-- snip --
  1947. +printf 'server 10.49.0.6 prefer minpoll 5 maxpoll 8\nlogfile /var/log/ntp.log\nleapfile "/var/db/ntpd.leap-seconds.list"\n' >'/etc/ntp.conf'
  1948. +sysrc ntpd_enable="YES"
  1949. +sysrc ntpd_flags=""
  1950. +sysrc ntpd_sync_on_start="YES"
  1951. +-- snip --
  1952. +
  1953. +# Verify NTP config with
  1954. +ntpq -np
  1955. +
  1956.  # configure NFSv4.2 server with idmapping enabled
  1957.  sysrc rpcbind_enable="YES"
  1958.  sysrc mountd_enable="YES"
  1959. @@ -217,6 +235,7 @@ printf 'vfs.nfs.enable_uidtostring=0\n' >>'/etc/sysctl.conf'
  1960.  printf 'vfs.nfsd.enable_stringtouid=0\n' >>'/etc/sysctl.conf'
  1961.  printf 'vfs.nfsd.issue_delegations=1\n' >>'/etc/sysctl.conf'
  1962.  
  1963. +# configure an export
  1964.  mkdir /nfsdata
  1965.  chmod a+rwxt /nfsdata
  1966.  
  1967. @@ -226,7 +245,7 @@ printf 'V4: /\n' >'/etc/exports'
  1968.  printf '/nfsdata -network=10.49.202.0 -mask=255.255.255.0  -sec=sys\n' >>'/etc/exports'
  1969.  service nfsd start
  1970.  
  1971. -##### 2. ms-nfs41-client setup:
  1972. +##### 2. FreeBSD-specific ms-nfs41-client setup:
  1973.  - Normal setup
  1974.  - Add groups entry for group "wheel" if neccesary:
  1975.  $ printf 'wheel:S-1-0-0:0:\n' >>'/etc/group'
  1976. --
  1977. 2.51.0
  1978.  
  1979. From dedd2ca7bdb09e3f35313f7e1d59157a0a93850f Mon Sep 17 00:00:00 2001
  1980. From: Roland Mainz <roland.mainz@nrubsig.org>
  1981. Date: Sat, 22 Nov 2025 22:57:10 +0100
  1982. Subject: [PATCH 18/28] cygwin: Install nfs_server_setup.txt as
  1983.  /usr/share/msnfs41client/tests/nfs_server_setup.txt
  1984.  
  1985. Install nfs_server_setup.txt as /usr/share/msnfs41client/tests/nfs_server_setup.txt
  1986. for admins as reference.
  1987.  
  1988. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  1989. ---
  1990. cygwin/Makefile.install | 1 +
  1991.  1 file changed, 1 insertion(+)
  1992.  
  1993. diff --git a/cygwin/Makefile.install b/cygwin/Makefile.install
  1994. index 129366f..087fb34 100644
  1995. --- a/cygwin/Makefile.install
  1996. +++ b/cygwin/Makefile.install
  1997. @@ -144,6 +144,7 @@ installdest:
  1998.         /usr/bin/ksh93 $(CYGWIN_MAKEFILE_DIR)/utils/nfsurlconv/nfsurlconv.ksh --nroff 2>"$(DESTDIR)/usr/share/man/man1/nfsurlconv.1" || true
  1999.         @ printf "# Package tests\n"
  2000.         cp "$(PROJECT_BASEDIR_DIR)/tests/manual_testing.txt" $(DESTDIR)/usr/share/msnfs41client/tests/manual_testing.txt
  2001. +       cp "$(PROJECT_BASEDIR_DIR)/tests/nfs_server_setup.txt" $(DESTDIR)/usr/share/msnfs41client/tests/nfs_server_setup.txt
  2002.         cp "$(PROJECT_BASEDIR_DIR)/tests/winfsinfo1/winfsinfo.x86_64.exe" $(DESTDIR)/bin/winfsinfo.x86_64.exe
  2003.         cp "$(PROJECT_BASEDIR_DIR)/tests/winfsinfo1/winfsinfo.i686.exe" $(DESTDIR)/bin/winfsinfo.i686.exe
  2004.         cp "$(PROJECT_BASEDIR_DIR)/tests/winclonefile/winclonefile.x86_64.exe" $(DESTDIR)/bin/winclonefile.x86_64.exe
  2005. --
  2006. 2.51.0
  2007.  
  2008. From 1fe3257946fb74eb615ce7f34b3f223cb86e01be Mon Sep 17 00:00:00 2001
  2009. From: Roland Mainz <roland.mainz@nrubsig.org>
  2010. Date: Sat, 29 Nov 2025 15:31:18 +0100
  2011. Subject: [PATCH 19/28] sys: Move NFSv4.1 open state into |SRV_OPEN| extension
  2012.  
  2013. Move NFSv4.1 openstate handle into |SRV_OPEN| extension.
  2014. The Win32 RDR spec expects that a filesystem handle is stored in a
  2015. |SRV_OPEN| extension (and not in a FOBX extension) so multiple
  2016. FILE_OBJECT/FOBX can use one |SRV_OPEN| (the RDR calls this
  2017. "collapsing").
  2018.  
  2019. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  2020. ---
  2021. sys/nfs41sys_acl.c       |  8 +++--
  2022.  sys/nfs41sys_dir.c       |  3 +-
  2023.  sys/nfs41sys_driver.c    | 12 +++++--
  2024.  sys/nfs41sys_driver.h    | 17 ++++++++--
  2025.  sys/nfs41sys_ea.c        | 11 ++++---
  2026.  sys/nfs41sys_fileinfo.c  |  8 +++--
  2027.  sys/nfs41sys_fsctl.c     | 28 +++++++++-------
  2028.  sys/nfs41sys_lock.c      |  6 ++--
  2029.  sys/nfs41sys_openclose.c | 69 ++++++++++++++++++++++++++--------------
  2030.  sys/nfs41sys_readwrite.c |  8 +++--
  2031.  sys/nfs41sys_symlink.c   |  6 ++--
  2032.  sys/nfs41sys_volinfo.c   |  3 +-
  2033.  12 files changed, 119 insertions(+), 60 deletions(-)
  2034.  
  2035. diff --git a/sys/nfs41sys_acl.c b/sys/nfs41sys_acl.c
  2036. index 2c94021..16caa63 100644
  2037. --- a/sys/nfs41sys_acl.c
  2038. +++ b/sys/nfs41sys_acl.c
  2039. @@ -225,6 +225,7 @@ NTSTATUS nfs41_QuerySecurityInformation(
  2040.      nfs41_updowncall_entry *entry = NULL;
  2041.      __notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
  2042.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2043. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2044.      __notnull PNFS41_FCB nfs41_fcb = NFS41GetFcbExtension(RxContext->pFcb);
  2045.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  2046.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2047. @@ -319,7 +320,7 @@ NTSTATUS nfs41_QuerySecurityInformation(
  2048.      }
  2049.  
  2050.      status = nfs41_UpcallCreate(NFS41_SYSOP_ACL_QUERY, &nfs41_fobx->sec_ctx,
  2051. -        pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
  2052. +        pVNetRootContext->session, nfs41_srvopen->nfs41_open_state,
  2053.          pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  2054.      if (status) goto out;
  2055.  
  2056. @@ -440,6 +441,7 @@ NTSTATUS nfs41_SetSecurityInformation(
  2057.      nfs41_updowncall_entry *entry = NULL;
  2058.      __notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
  2059.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2060. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2061.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  2062.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2063.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2064. @@ -483,7 +485,7 @@ NTSTATUS nfs41_SetSecurityInformation(
  2065.      }
  2066.  
  2067.      status = nfs41_UpcallCreate(NFS41_SYSOP_ACL_SET, &nfs41_fobx->sec_ctx,
  2068. -        pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
  2069. +        pVNetRootContext->session, nfs41_srvopen->nfs41_open_state,
  2070.          pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  2071.      if (status) goto out;
  2072.  
  2073. @@ -519,7 +521,7 @@ NTSTATUS nfs41_SetSecurityInformation(
  2074.  
  2075.      status = map_query_acl_error(entry->status);
  2076.      if (!status) {
  2077. -        if (!nfs41_fobx->deleg_type && entry->ChangeTime &&
  2078. +        if ((nfs41_srvopen->deleg_type == 0) && entry->ChangeTime &&
  2079.                  (SrvOpen->DesiredAccess &
  2080.                  (FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)))
  2081.              nfs41_update_fcb_list(RxContext->pFcb, entry->ChangeTime);
  2082. diff --git a/sys/nfs41sys_dir.c b/sys/nfs41sys_dir.c
  2083. index e80aa1e..60e5b50 100644
  2084. --- a/sys/nfs41sys_dir.c
  2085. +++ b/sys/nfs41sys_dir.c
  2086. @@ -231,6 +231,7 @@ NTSTATUS nfs41_QueryDirectory(
  2087.      FILE_INFORMATION_CLASS InfoClass = RxContext->Info.FileInformationClass;
  2088.      PUNICODE_STRING Filter = &RxContext->pFobx->UnicodeQueryTemplate;
  2089.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2090. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2091.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  2092.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2093.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2094. @@ -269,7 +270,7 @@ NTSTATUS nfs41_QueryDirectory(
  2095.          goto out;
  2096.      }
  2097.      status = nfs41_UpcallCreate(NFS41_SYSOP_DIR_QUERY, &nfs41_fobx->sec_ctx,
  2098. -        pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
  2099. +        pVNetRootContext->session, nfs41_srvopen->nfs41_open_state,
  2100.          pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  2101.      if (status) goto out;
  2102.  
  2103. diff --git a/sys/nfs41sys_driver.c b/sys/nfs41sys_driver.c
  2104. index 4ea927a..0b7a1f6 100644
  2105. --- a/sys/nfs41sys_driver.c
  2106. +++ b/sys/nfs41sys_driver.c
  2107. @@ -1030,6 +1030,7 @@ void enable_caching(
  2108.      ULONGLONG ChangeTime,
  2109.      HANDLE session)
  2110.  {
  2111. +    PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2112.      ULONG flag = 0;
  2113.      PLIST_ENTRY pEntry;
  2114.      nfs41_fcb_list_entry *cur;
  2115. @@ -1078,7 +1079,7 @@ void enable_caching(
  2116.          }
  2117.          pEntry = pEntry->Flink;
  2118.      }
  2119. -    if (!found && nfs41_fobx->deleg_type) {
  2120. +    if (!found && (nfs41_srvopen->deleg_type != 0)) {
  2121.          nfs41_fcb_list_entry *oentry;
  2122.  #ifdef DEBUG_TIME_BASED_COHERENCY
  2123.          DbgP("enable_caching: delegation recalled: srv_open=0x%p\n", SrvOpen);
  2124. @@ -1092,7 +1093,7 @@ void enable_caching(
  2125.          oentry->ChangeTime = ChangeTime;
  2126.          oentry->skip = FALSE;
  2127.          InsertTailList(&openlist.head, &oentry->next);
  2128. -        nfs41_fobx->deleg_type = 0;
  2129. +        nfs41_srvopen->deleg_type = 0;
  2130.      }
  2131.  out_release_fcblistlock:
  2132.      ExReleaseFastMutexUnsafe(&openlist.lock);
  2133. @@ -1227,12 +1228,14 @@ NTSTATUS nfs41_init_ops(void)
  2134.      nfs41_ops.MRxFlags = (RDBSS_MANAGE_NET_ROOT_EXTENSION |
  2135.                              RDBSS_MANAGE_V_NET_ROOT_EXTENSION |
  2136.                              RDBSS_MANAGE_FCB_EXTENSION |
  2137. +                            RDBSS_MANAGE_SRV_OPEN_EXTENSION |
  2138.                              RDBSS_MANAGE_FOBX_EXTENSION);
  2139.  
  2140.      nfs41_ops.MRxSrvCallSize  = 0; // srvcall extension is not handled in rdbss
  2141.      nfs41_ops.MRxNetRootSize  = sizeof(NFS41_NETROOT_EXTENSION);
  2142.      nfs41_ops.MRxVNetRootSize = sizeof(NFS41_V_NET_ROOT_EXTENSION);
  2143.      nfs41_ops.MRxFcbSize      = sizeof(NFS41_FCB);
  2144. +    nfs41_ops.MRxSrvOpenSize  = sizeof(NFS41_SRV_OPEN);
  2145.      nfs41_ops.MRxFobxSize     = sizeof(NFS41_FOBX);
  2146.  
  2147.      // Mini redirector cancel routine
  2148. @@ -1417,11 +1420,14 @@ VOID fcbopen_main(PVOID ctx)
  2149.  
  2150.              pNetRootContext =
  2151.                  NFS41GetNetRootExtension(cur->fcb->pNetRoot);
  2152. +            PNFS41_SRV_OPEN nfs41_srvopen =
  2153. +                NFS41GetSrvOpenExtension(cur->srvopen);
  2154. +
  2155.              /* place an upcall for this srv_open */
  2156.              status = nfs41_UpcallCreate(
  2157.                  NFS41_SYSOP_FILE_QUERY_TIME_BASED_COHERENCY,
  2158.                  &cur->nfs41_fobx->sec_ctx, cur->session,
  2159. -                cur->nfs41_fobx->nfs41_open_state,
  2160. +                nfs41_srvopen->nfs41_open_state,
  2161.                  pNetRootContext->nfs41d_version, NULL, &entry);
  2162.              if (status) goto out;
  2163.  
  2164. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  2165. index 0296a91..9c979f7 100644
  2166. --- a/sys/nfs41sys_driver.h
  2167. +++ b/sys/nfs41sys_driver.h
  2168. @@ -95,6 +95,9 @@ typedef struct __nfs41_timings {
  2169.  /* Windows SMB driver also uses |IO_NETWORK_INCREMENT| */
  2170.  #define IO_NFS41FS_INCREMENT IO_NETWORK_INCREMENT
  2171.  
  2172. +/* Number of bytes needed to store an SID */
  2173. +#define SID_BUF_SIZE (SECURITY_MAX_SID_SIZE)
  2174. +
  2175.  #define DISABLE_CACHING 0
  2176.  #define ENABLE_READ_CACHING 1
  2177.  #define ENABLE_WRITE_CACHING 2
  2178. @@ -496,13 +499,22 @@ typedef struct _NFS41_FCB {
  2179.  #define NFS41GetFcbExtension(pFcb)      \
  2180.          (((pFcb) == NULL) ? NULL : (PNFS41_FCB)((pFcb)->Context))
  2181.  
  2182. +typedef struct _NFS41_SRV_OPEN {
  2183. +    HANDLE          nfs41_open_state;
  2184. +    DWORD           deleg_type;
  2185. +} NFS41_SRV_OPEN, *PNFS41_SRV_OPEN;
  2186. +#define NFS41GetSrvOpenExtension(pSrvOpen)  \
  2187. +        (((pSrvOpen) == NULL) ? NULL : (PNFS41_SRV_OPEN)((pSrvOpen)->Context))
  2188. +
  2189.  typedef struct _NFS41_FOBX {
  2190.      NODE_TYPE_CODE          NodeTypeCode;
  2191.      NODE_BYTE_SIZE          NodeByteSize;
  2192.  
  2193. -    HANDLE nfs41_open_state;
  2194. +    /*
  2195. +     * |sec_ctx| must be per |FILE_OBJECT| to handle newgrp()1/|setgid()|
  2196. +     * support
  2197. +     */
  2198.      SECURITY_CLIENT_CONTEXT sec_ctx;
  2199. -    DWORD deleg_type;
  2200.      BOOLEAN write_thru;
  2201.      BOOLEAN nocache;
  2202.      BOOLEAN timebasedcoherency;
  2203. @@ -533,6 +545,7 @@ typedef struct _NFS41_DEVICE_EXTENSION {
  2204.  typedef struct _nfs41_fcb_list_entry {
  2205.      LIST_ENTRY next;
  2206.      PMRX_FCB fcb;
  2207. +    PMRX_SRV_OPEN srvopen;
  2208.      HANDLE session;
  2209.      PNFS41_FOBX nfs41_fobx;
  2210.      ULONGLONG ChangeTime;
  2211. diff --git a/sys/nfs41sys_ea.c b/sys/nfs41sys_ea.c
  2212. index 1d415da..0f2a9dd 100644
  2213. --- a/sys/nfs41sys_ea.c
  2214. +++ b/sys/nfs41sys_ea.c
  2215. @@ -349,6 +349,7 @@ NTSTATUS nfs41_SetEaInformation(
  2216.      nfs3_attrs *attrs = NULL;
  2217.      ULONG buflen = RxContext->CurrentIrpSp->Parameters.SetEa.Length, error_offset;
  2218.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2219. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2220.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  2221.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2222.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2223. @@ -371,7 +372,7 @@ NTSTATUS nfs41_SetEaInformation(
  2224.      if (status) goto out;
  2225.  
  2226.      status = nfs41_UpcallCreate(NFS41_SYSOP_EA_SET, &nfs41_fobx->sec_ctx,
  2227. -        pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
  2228. +        pVNetRootContext->session, nfs41_srvopen->nfs41_open_state,
  2229.          pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  2230.      if (status) goto out;
  2231.  
  2232. @@ -411,7 +412,7 @@ NTSTATUS nfs41_SetEaInformation(
  2233.  #endif
  2234.      status = map_setea_error(entry->status);
  2235.      if (!status) {
  2236. -        if (!nfs41_fobx->deleg_type && entry->ChangeTime &&
  2237. +        if ((nfs41_srvopen->deleg_type == 0) && entry->ChangeTime &&
  2238.                  (SrvOpen->DesiredAccess &
  2239.                  (FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)))
  2240.              nfs41_update_fcb_list(RxContext->pFcb, entry->ChangeTime);
  2241. @@ -479,6 +480,7 @@ NTSTATUS QueryCygwinSymlink(
  2242.      OUT PFILE_FULL_EA_INFORMATION info)
  2243.  {
  2244.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2245. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2246.      __notnull PNFS41_V_NET_ROOT_EXTENSION VNetRootContext =
  2247.              NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2248.      __notnull PNFS41_NETROOT_EXTENSION NetRootContext =
  2249. @@ -501,7 +503,7 @@ NTSTATUS QueryCygwinSymlink(
  2250.          HeaderLen, 0xFFFF);
  2251.  
  2252.      status = nfs41_UpcallCreate(NFS41_SYSOP_SYMLINK_GET, &Fobx->sec_ctx,
  2253. -        VNetRootContext->session, Fobx->nfs41_open_state,
  2254. +        VNetRootContext->session, nfs41_srvopen->nfs41_open_state,
  2255.          NetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  2256.      if (status) goto out;
  2257.  
  2258. @@ -630,6 +632,7 @@ NTSTATUS nfs41_QueryEaInformation(
  2259.              RxContext->CurrentIrpSp->Parameters.QueryEa.EaList;
  2260.      ULONG buflen = RxContext->CurrentIrpSp->Parameters.QueryEa.Length;
  2261.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2262. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2263.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  2264.              NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2265.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2266. @@ -657,7 +660,7 @@ NTSTATUS nfs41_QueryEaInformation(
  2267.          goto out;
  2268.  
  2269.      status = nfs41_UpcallCreate(NFS41_SYSOP_EA_GET, &nfs41_fobx->sec_ctx,
  2270. -        pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
  2271. +        pVNetRootContext->session, nfs41_srvopen->nfs41_open_state,
  2272.          pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  2273.      if (status) goto out;
  2274.  
  2275. diff --git a/sys/nfs41sys_fileinfo.c b/sys/nfs41sys_fileinfo.c
  2276. index 991646b..1bf736f 100644
  2277. --- a/sys/nfs41sys_fileinfo.c
  2278. +++ b/sys/nfs41sys_fileinfo.c
  2279. @@ -205,6 +205,7 @@ NTSTATUS nfs41_QueryFileInformation(
  2280.      FILE_INFORMATION_CLASS InfoClass = RxContext->Info.FileInformationClass;
  2281.      nfs41_updowncall_entry *entry = NULL;
  2282.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2283. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2284.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  2285.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2286.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2287. @@ -407,7 +408,7 @@ NTSTATUS nfs41_QueryFileInformation(
  2288.      }
  2289.  
  2290.      status = nfs41_UpcallCreate(NFS41_SYSOP_FILE_QUERY, &nfs41_fobx->sec_ctx,
  2291. -        pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
  2292. +        pVNetRootContext->session, nfs41_srvopen->nfs41_open_state,
  2293.          pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  2294.      if (status) {
  2295.          print_error("nfs41_QueryFileInformation: "
  2296. @@ -676,6 +677,7 @@ NTSTATUS nfs41_SetFileInformationImpl(
  2297.      FILE_RENAME_INFORMATION rinfo;
  2298.  #endif /* FORCE_POSIX_SEMANTICS_DELETE */
  2299.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2300. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2301.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  2302.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2303.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2304. @@ -788,7 +790,7 @@ NTSTATUS nfs41_SetFileInformationImpl(
  2305.      }
  2306.  
  2307.      status = nfs41_UpcallCreate(opcode, &nfs41_fobx->sec_ctx,
  2308. -        pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
  2309. +        pVNetRootContext->session, nfs41_srvopen->nfs41_open_state,
  2310.          pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  2311.      if (status) goto out;
  2312.  
  2313. @@ -822,7 +824,7 @@ NTSTATUS nfs41_SetFileInformationImpl(
  2314.  
  2315.      status = map_setfile_error(entry->status);
  2316.      if (!status) {
  2317. -        if (!nfs41_fobx->deleg_type && entry->ChangeTime &&
  2318. +        if ((nfs41_srvopen->deleg_type != 0) && entry->ChangeTime &&
  2319.                  (SrvOpen->DesiredAccess &
  2320.                  (FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)))
  2321.              nfs41_update_fcb_list(RxContext->pFcb, entry->ChangeTime);
  2322. diff --git a/sys/nfs41sys_fsctl.c b/sys/nfs41sys_fsctl.c
  2323. index 864ad78..f31b976 100644
  2324. --- a/sys/nfs41sys_fsctl.c
  2325. +++ b/sys/nfs41sys_fsctl.c
  2326. @@ -128,6 +128,7 @@ NTSTATUS nfs41_QueryAllocatedRanges(
  2327.      NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
  2328.      nfs41_updowncall_entry *entry = NULL;
  2329.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2330. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2331.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  2332.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2333.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2334. @@ -161,7 +162,7 @@ NTSTATUS nfs41_QueryAllocatedRanges(
  2335.      status = nfs41_UpcallCreate(NFS41_SYSOP_FSCTL_QUERYALLOCATEDRANGES,
  2336.          &nfs41_fobx->sec_ctx,
  2337.          pVNetRootContext->session,
  2338. -        nfs41_fobx->nfs41_open_state,
  2339. +        nfs41_srvopen->nfs41_open_state,
  2340.          pNetRootContext->nfs41d_version,
  2341.          SrvOpen->pAlreadyPrefixedName,
  2342.          &entry);
  2343. @@ -448,6 +449,7 @@ NTSTATUS nfs41_SetZeroData(
  2344.      NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
  2345.      nfs41_updowncall_entry *entry = NULL;
  2346.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2347. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2348.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  2349.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2350.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2351. @@ -501,7 +503,7 @@ NTSTATUS nfs41_SetZeroData(
  2352.      status = nfs41_UpcallCreate(NFS41_SYSOP_FSCTL_SET_ZERO_DATA,
  2353.          &nfs41_fobx->sec_ctx,
  2354.          pVNetRootContext->session,
  2355. -        nfs41_fobx->nfs41_open_state,
  2356. +        nfs41_srvopen->nfs41_open_state,
  2357.          pNetRootContext->nfs41d_version,
  2358.          SrvOpen->pAlreadyPrefixedName,
  2359.          &entry);
  2360. @@ -629,6 +631,7 @@ NTSTATUS nfs41_DuplicateData(
  2361.      NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
  2362.      nfs41_updowncall_entry *entry = NULL;
  2363.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2364. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2365.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  2366.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2367.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2368. @@ -751,6 +754,7 @@ NTSTATUS nfs41_DuplicateData(
  2369.      PFCB srcfcb = srcfo->FsContext;
  2370.      PFOBX srcfox = srcfo->FsContext2;
  2371.      PNFS41_FCB nfs41_src_fcb = NFS41GetFcbExtension(srcfcb);
  2372. +    PNFS41_SRV_OPEN src_nfs41_srvopen = NFS41GetSrvOpenExtension(srcfox->SrvOpen);
  2373.      PNFS41_FOBX nfs41_src_fobx = NFS41GetFobxExtension(srcfox);
  2374.  
  2375.      if (!nfs41_src_fcb) {
  2376. @@ -807,7 +811,7 @@ NTSTATUS nfs41_DuplicateData(
  2377.      status = nfs41_UpcallCreate(NFS41_SYSOP_FSCTL_DUPLICATE_DATA,
  2378.          &nfs41_fobx->sec_ctx,
  2379.          pVNetRootContext->session,
  2380. -        nfs41_fobx->nfs41_open_state,
  2381. +        nfs41_srvopen->nfs41_open_state,
  2382.          pNetRootContext->nfs41d_version,
  2383.          SrvOpen->pAlreadyPrefixedName,
  2384.          &entry);
  2385. @@ -815,7 +819,7 @@ NTSTATUS nfs41_DuplicateData(
  2386.      if (status)
  2387.          goto out;
  2388.  
  2389. -    entry->u.DuplicateData.src_state = nfs41_src_fobx->nfs41_open_state;
  2390. +    entry->u.DuplicateData.src_state = src_nfs41_srvopen->nfs41_open_state;
  2391.      entry->u.DuplicateData.srcfileoffset = dd.srcfileoffset;
  2392.      entry->u.DuplicateData.destfileoffset = dd.destfileoffset;
  2393.      entry->u.DuplicateData.bytecount = dd.bytecount;
  2394. @@ -949,7 +953,7 @@ typedef struct _offloadcontext_entry
  2395.       */
  2396.      ERESOURCE               resource;
  2397.      STORAGE_OFFLOAD_TOKEN   token;
  2398. -    PNFS41_FOBX             src_fobx;
  2399. +    PMRX_FOBX               src_fobx;
  2400.      ULONGLONG               src_fileoffset;
  2401.      ULONGLONG               src_length;
  2402.  } offloadcontext_entry;
  2403. @@ -960,7 +964,6 @@ void nfs41_remove_offloadcontext_for_fobx(
  2404.  {
  2405.      PLIST_ENTRY pEntry;
  2406.      offloadcontext_entry *cur, *found = NULL;
  2407. -    __notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(pFobx);
  2408.  
  2409.      ExAcquireFastMutexUnsafe(&offloadcontextlist.lock);
  2410.  
  2411. @@ -968,7 +971,7 @@ void nfs41_remove_offloadcontext_for_fobx(
  2412.      while (!IsListEmpty(&offloadcontextlist.head)) {
  2413.          cur = (offloadcontext_entry *)CONTAINING_RECORD(pEntry,
  2414.              offloadcontext_entry, next);
  2415. -        if (cur->src_fobx == nfs41_fobx) {
  2416. +        if (cur->src_fobx == pFobx) {
  2417.              found = cur;
  2418.              break;
  2419.          }
  2420. @@ -1054,7 +1057,6 @@ NTSTATUS nfs41_OffloadRead(
  2421.      __notnull const XXCTL_LOWIO_COMPONENT *FsCtl =
  2422.          &RxContext->LowIoContext.ParamsFor.FsCtl;
  2423.      __notnull PNFS41_FCB nfs41_fcb = NFS41GetFcbExtension(RxContext->pFcb);
  2424. -    __notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
  2425.  
  2426.      DbgEn();
  2427.  
  2428. @@ -1124,7 +1126,7 @@ NTSTATUS nfs41_OffloadRead(
  2429.      *((USHORT *)(&oce->token.TokenIdLength[0])) =
  2430.          STORAGE_OFFLOAD_TOKEN_ID_LENGTH;
  2431.      *((void **)(&oce->token.Token[0])) = oce;
  2432. -    oce->src_fobx = nfs41_fobx;
  2433. +    oce->src_fobx = RxContext->pFobx;
  2434.      oce->src_fileoffset = ori->FileOffset;
  2435.      oce->src_length = ori->CopyLength;
  2436.  
  2437. @@ -1180,6 +1182,7 @@ NTSTATUS nfs41_OffloadWrite(
  2438.      NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
  2439.      nfs41_updowncall_entry *entry = NULL;
  2440.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2441. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2442.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  2443.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2444.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2445. @@ -1291,12 +1294,13 @@ NTSTATUS nfs41_OffloadWrite(
  2446.          goto out;
  2447.      }
  2448.  
  2449. -    PNFS41_FOBX nfs41_src_fobx = src_oce->src_fobx;
  2450. +    PNFS41_FOBX nfs41_src_fobx = NFS41GetFobxExtension(src_oce->src_fobx);
  2451.      if (!nfs41_src_fobx) {
  2452.          DbgP("nfs41_OffloadWrite: No nfs41_src_fobx\n");
  2453.          status = STATUS_INVALID_PARAMETER;
  2454.          goto out;
  2455.      }
  2456. +    PNFS41_SRV_OPEN src_nfs41_srvopen = NFS41GetSrvOpenExtension(((PFOBX)src_oce->src_fobx)->SrvOpen);
  2457.  
  2458.      /*
  2459.       * Disable caching because NFSv4.2 COPY is basically a
  2460. @@ -1314,7 +1318,7 @@ NTSTATUS nfs41_OffloadWrite(
  2461.      status = nfs41_UpcallCreate(NFS41_SYSOP_FSCTL_OFFLOAD_DATACOPY,
  2462.          &nfs41_fobx->sec_ctx,
  2463.          pVNetRootContext->session,
  2464. -        nfs41_fobx->nfs41_open_state,
  2465. +        nfs41_srvopen->nfs41_open_state,
  2466.          pNetRootContext->nfs41d_version,
  2467.          SrvOpen->pAlreadyPrefixedName,
  2468.          &entry);
  2469. @@ -1322,7 +1326,7 @@ NTSTATUS nfs41_OffloadWrite(
  2470.      if (status)
  2471.          goto out;
  2472.  
  2473. -    entry->u.DuplicateData.src_state = nfs41_src_fobx->nfs41_open_state;
  2474. +    entry->u.DuplicateData.src_state = src_nfs41_srvopen->nfs41_open_state;
  2475.      entry->u.DuplicateData.srcfileoffset = dd.srcfileoffset;
  2476.      entry->u.DuplicateData.destfileoffset = dd.destfileoffset;
  2477.      entry->u.DuplicateData.bytecount = dd.bytecount;
  2478. diff --git a/sys/nfs41sys_lock.c b/sys/nfs41sys_lock.c
  2479. index 7b52ad6..71a7dec 100644
  2480. --- a/sys/nfs41sys_lock.c
  2481. +++ b/sys/nfs41sys_lock.c
  2482. @@ -268,6 +268,7 @@ NTSTATUS nfs41_Lock(
  2483.      PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  2484.      __notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
  2485.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2486. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2487.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  2488.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2489.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2490. @@ -301,7 +302,7 @@ NTSTATUS nfs41_Lock(
  2491.  #endif /* NFS41_DRIVER_HACK_LOCKING_STORAGE32_RANGELOCK_PROBING */
  2492.  
  2493.      status = nfs41_UpcallCreate(NFS41_SYSOP_LOCK, &nfs41_fobx->sec_ctx,
  2494. -        pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
  2495. +        pVNetRootContext->session, nfs41_srvopen->nfs41_open_state,
  2496.          pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  2497.      if (status) goto out;
  2498.  
  2499. @@ -379,6 +380,7 @@ NTSTATUS nfs41_Unlock(
  2500.      PLOWIO_CONTEXT LowIoContext  = &RxContext->LowIoContext;
  2501.      __notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
  2502.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2503. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2504.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  2505.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2506.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2507. @@ -415,7 +417,7 @@ NTSTATUS nfs41_Unlock(
  2508.  #endif /* NFS41_DRIVER_HACK_LOCKING_STORAGE32_RANGELOCK_PROBING */
  2509.  
  2510.      status = nfs41_UpcallCreate(NFS41_SYSOP_UNLOCK, &nfs41_fobx->sec_ctx,
  2511. -        pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
  2512. +        pVNetRootContext->session, nfs41_srvopen->nfs41_open_state,
  2513.          pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  2514.      if (status) goto out;
  2515.  
  2516. diff --git a/sys/nfs41sys_openclose.c b/sys/nfs41sys_openclose.c
  2517. index 7a09cd8..41cc89a 100644
  2518. --- a/sys/nfs41sys_openclose.c
  2519. +++ b/sys/nfs41sys_openclose.c
  2520. @@ -619,6 +619,27 @@ out:
  2521.      return status;
  2522.  }
  2523.  
  2524. +NTSTATUS nfs41_createnetfobx(
  2525. +    PRX_CONTEXT  RxContext,
  2526. +    PMRX_SRV_OPEN SrvOpen)
  2527. +{
  2528. +    NTSTATUS status;
  2529. +    PNFS41_FOBX nfs41_fobx;
  2530. +
  2531. +    RxContext->pFobx = RxCreateNetFobx(RxContext, SrvOpen);
  2532. +    if (RxContext->pFobx == NULL) {
  2533. +        status = STATUS_INSUFFICIENT_RESOURCES;
  2534. +        goto out;
  2535. +    }
  2536. +
  2537. +    nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
  2538. +    status = nfs41_get_sec_ctx(SecurityImpersonation, &nfs41_fobx->sec_ctx);
  2539. +
  2540. +out:
  2541. +    return status;
  2542. +}
  2543. +
  2544. +
  2545.  NTSTATUS nfs41_Create(
  2546.      IN OUT PRX_CONTEXT RxContext)
  2547.  {
  2548. @@ -628,6 +649,7 @@ NTSTATUS nfs41_Create(
  2549.      PFILE_FULL_EA_INFORMATION ea = (PFILE_FULL_EA_INFORMATION)
  2550.          RxContext->CurrentIrp->AssociatedIrp.SystemBuffer;
  2551.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2552. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2553.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  2554.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2555.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2556. @@ -943,21 +965,16 @@ retry_on_link:
  2557.          fcb_locked_exclusive = true;
  2558.      }
  2559.  
  2560. -    RxContext->pFobx = RxCreateNetFobx(RxContext, SrvOpen);
  2561. -    if (RxContext->pFobx == NULL) {
  2562. -        status = STATUS_INSUFFICIENT_RESOURCES;
  2563. +    nfs41_srvopen->nfs41_open_state = entry->open_state;
  2564. +
  2565. +    status = nfs41_createnetfobx(RxContext, SrvOpen);
  2566. +    if (status)
  2567.          goto out;
  2568. -    }
  2569. +
  2570.  #ifdef DEBUG_OPEN
  2571.      DbgP("nfs41_Create: created FOBX 0x%p\n", RxContext->pFobx);
  2572.  #endif
  2573.      nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
  2574. -    nfs41_fobx->nfs41_open_state = entry->open_state;
  2575. -    if (nfs41_fobx->sec_ctx.ClientToken == NULL) {
  2576. -        status = nfs41_get_sec_ctx(SecurityImpersonation, &nfs41_fobx->sec_ctx);
  2577. -        if (status)
  2578. -            goto out;
  2579. -    }
  2580.  
  2581.      // we get attributes only for data access and file (not directories)
  2582.      if (Fcb->OpenCount == 0 ||
  2583. @@ -1104,7 +1121,7 @@ retry_on_link:
  2584.  
  2585.      if (!nfs41_fcb->StandardInfo.Directory &&
  2586.              isDataAccess(params->DesiredAccess)) {
  2587. -        nfs41_fobx->deleg_type = entry->u.Open.deleg_type;
  2588. +        nfs41_srvopen->deleg_type = entry->u.Open.deleg_type;
  2589.  #ifdef DEBUG_OPEN
  2590.          DbgP("nfs41_Create: received delegation %d\n", entry->u.Open.deleg_type);
  2591.  #endif
  2592. @@ -1168,6 +1185,7 @@ retry_on_link:
  2593.                  goto out;
  2594.              }
  2595.              oentry->fcb = RxContext->pFcb;
  2596. +            oentry->srvopen = SrvOpen;
  2597.              oentry->nfs41_fobx = nfs41_fobx;
  2598.              oentry->session = pVNetRootContext->session;
  2599.              oentry->ChangeTime = entry->ChangeTime;
  2600. @@ -1225,23 +1243,25 @@ out:
  2601.      return status;
  2602.  }
  2603.  
  2604. -NTSTATUS nfs41_CollapseOpen(
  2605. +NTSTATUS nfs41_ShouldTryToCollapseThisOpen(
  2606.      IN OUT PRX_CONTEXT RxContext)
  2607.  {
  2608. -    NTSTATUS status = STATUS_MORE_PROCESSING_REQUIRED;
  2609. -    DbgEn();
  2610. -    FsRtlEnterFileSystem();
  2611. -    FsRtlExitFileSystem();
  2612. -    DbgEx();
  2613. -    return status;
  2614. +    if (RxContext->pRelevantSrvOpen == NULL)
  2615. +        return STATUS_SUCCESS;
  2616. +    return STATUS_MORE_PROCESSING_REQUIRED;
  2617.  }
  2618.  
  2619. -NTSTATUS nfs41_ShouldTryToCollapseThisOpen(
  2620. +/*
  2621. + * |nfs41_CollapseOpen()| - like |nfs41_Create()|, but use an existing
  2622. + * |MRX_SRV_OPEN|.
  2623. + * This means one |MRX_SRV_OPEN| can have multiple |NFS41_FOBX|/|FILE_OBJECTS|
  2624. + * if the access parameters match.
  2625. + */
  2626. +NTSTATUS nfs41_CollapseOpen(
  2627.      IN OUT PRX_CONTEXT RxContext)
  2628.  {
  2629. -    if (RxContext->pRelevantSrvOpen == NULL)
  2630. -        return STATUS_SUCCESS;
  2631. -    else return STATUS_MORE_PROCESSING_REQUIRED;
  2632. +    NTSTATUS status = STATUS_MORE_PROCESSING_REQUIRED;
  2633. +    return status;
  2634.  }
  2635.  
  2636.  NTSTATUS map_close_errors(
  2637. @@ -1271,6 +1291,7 @@ NTSTATUS nfs41_CloseSrvOpen(
  2638.      NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
  2639.      nfs41_updowncall_entry *entry = NULL;
  2640.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2641. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2642.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  2643.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2644.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2645. @@ -1288,13 +1309,13 @@ NTSTATUS nfs41_CloseSrvOpen(
  2646.  #endif
  2647.      FsRtlEnterFileSystem();
  2648.  
  2649. -    if (!nfs41_fobx->deleg_type && !nfs41_fcb->StandardInfo.Directory &&
  2650. +    if ((nfs41_srvopen->deleg_type == 0) && !nfs41_fcb->StandardInfo.Directory &&
  2651.              !RxContext->pFcb->OpenCount) {
  2652.          nfs41_remove_fcb_entry(RxContext->pFcb);
  2653.      }
  2654.  
  2655.      status = nfs41_UpcallCreate(NFS41_SYSOP_CLOSE, &nfs41_fobx->sec_ctx,
  2656. -        pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
  2657. +        pVNetRootContext->session, nfs41_srvopen->nfs41_open_state,
  2658.          pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  2659.      if (status) goto out;
  2660.  
  2661. diff --git a/sys/nfs41sys_readwrite.c b/sys/nfs41sys_readwrite.c
  2662. index f82549c..8f313d9 100644
  2663. --- a/sys/nfs41sys_readwrite.c
  2664. +++ b/sys/nfs41sys_readwrite.c
  2665. @@ -236,6 +236,7 @@ NTSTATUS nfs41_Read(
  2666.      BOOLEAN async = FALSE;
  2667.      PLOWIO_CONTEXT LowIoContext  = &RxContext->LowIoContext;
  2668.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2669. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2670.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  2671.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2672.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2673. @@ -258,7 +259,7 @@ NTSTATUS nfs41_Read(
  2674.      if (status) goto out;
  2675.  
  2676.      status = nfs41_UpcallCreate(NFS41_SYSOP_READ, &nfs41_fobx->sec_ctx,
  2677. -        pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
  2678. +        pVNetRootContext->session, nfs41_srvopen->nfs41_open_state,
  2679.          pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  2680.      if (status) goto out;
  2681.  
  2682. @@ -364,6 +365,7 @@ NTSTATUS nfs41_Write(
  2683.      BOOLEAN async = FALSE;
  2684.      PLOWIO_CONTEXT LowIoContext  = &RxContext->LowIoContext;
  2685.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2686. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2687.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  2688.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2689.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2690. @@ -386,7 +388,7 @@ NTSTATUS nfs41_Write(
  2691.      if (status) goto out;
  2692.  
  2693.      status = nfs41_UpcallCreate(NFS41_SYSOP_WRITE, &nfs41_fobx->sec_ctx,
  2694. -        pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
  2695. +        pVNetRootContext->session, nfs41_srvopen->nfs41_open_state,
  2696.          pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  2697.      if (status) goto out;
  2698.  
  2699. @@ -441,7 +443,7 @@ NTSTATUS nfs41_Write(
  2700.                   FCB_STATE_WRITECACHING_ENABLED))) {
  2701.              enable_caching(SrvOpen, nfs41_fobx, nfs41_fcb->changeattr,
  2702.                  pVNetRootContext->session);
  2703. -        } else if (!nfs41_fobx->deleg_type)
  2704. +        } else if (nfs41_srvopen->deleg_type == 0)
  2705.              nfs41_update_fcb_list(RxContext->pFcb, entry->ChangeTime);
  2706.  
  2707.      } else {
  2708. diff --git a/sys/nfs41sys_symlink.c b/sys/nfs41sys_symlink.c
  2709. index 2c81f9a..c157164 100644
  2710. --- a/sys/nfs41sys_symlink.c
  2711. +++ b/sys/nfs41sys_symlink.c
  2712. @@ -259,6 +259,7 @@ NTSTATUS nfs41_SetSymlinkReparsePoint(
  2713.          (const PREPARSE_DATA_BUFFER)FsCtl->pInputBuffer;
  2714.      __notnull PNFS41_FOBX Fobx = NFS41GetFobxExtension(RxContext->pFobx);
  2715.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2716. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2717.      __notnull PNFS41_V_NET_ROOT_EXTENSION VNetRootContext =
  2718.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2719.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2720. @@ -416,7 +417,7 @@ NTSTATUS nfs41_SetSymlinkReparsePoint(
  2721.      }
  2722.  
  2723.      status = nfs41_UpcallCreate(NFS41_SYSOP_SYMLINK_SET, &Fobx->sec_ctx,
  2724. -        VNetRootContext->session, Fobx->nfs41_open_state,
  2725. +        VNetRootContext->session, nfs41_srvopen->nfs41_open_state,
  2726.          pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  2727.      if (status) goto out;
  2728.  
  2729. @@ -569,6 +570,7 @@ NTSTATUS nfs41_GetSymlinkReparsePoint(
  2730.      XXCTL_LOWIO_COMPONENT *FsCtl = &RxContext->LowIoContext.ParamsFor.FsCtl;
  2731.      __notnull PNFS41_FOBX Fobx = NFS41GetFobxExtension(RxContext->pFobx);
  2732.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2733. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2734.      __notnull PNFS41_V_NET_ROOT_EXTENSION VNetRootContext =
  2735.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2736.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2737. @@ -602,7 +604,7 @@ NTSTATUS nfs41_GetSymlinkReparsePoint(
  2738.      TargetName.MaximumLength = (USHORT)targetname_buffer_len;
  2739.  
  2740.      status = nfs41_UpcallCreate(NFS41_SYSOP_SYMLINK_GET, &Fobx->sec_ctx,
  2741. -        VNetRootContext->session, Fobx->nfs41_open_state,
  2742. +        VNetRootContext->session, nfs41_srvopen->nfs41_open_state,
  2743.          pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  2744.      if (status) goto out;
  2745.  
  2746. diff --git a/sys/nfs41sys_volinfo.c b/sys/nfs41sys_volinfo.c
  2747. index 017dcb6..10b9c61 100644
  2748. --- a/sys/nfs41sys_volinfo.c
  2749. +++ b/sys/nfs41sys_volinfo.c
  2750. @@ -153,6 +153,7 @@ NTSTATUS nfs41_QueryVolumeInformation(
  2751.      ULONG RemainingLength = RxContext->Info.LengthRemaining, SizeUsed;
  2752.      FS_INFORMATION_CLASS InfoClass = RxContext->Info.FsInformationClass;
  2753.      __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2754. +    __notnull PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2755.      __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
  2756.          NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  2757.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  2758. @@ -206,7 +207,7 @@ NTSTATUS nfs41_QueryVolumeInformation(
  2759.          goto out;
  2760.      }
  2761.      status = nfs41_UpcallCreate(NFS41_SYSOP_VOLUME_QUERY, &nfs41_fobx->sec_ctx,
  2762. -        pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
  2763. +        pVNetRootContext->session, nfs41_srvopen->nfs41_open_state,
  2764.          pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  2765.      if (status) goto out;
  2766.  
  2767. --
  2768. 2.51.0
  2769.  
  2770. From 51ffe18a79710ea0b53e2f152a687078ed322607 Mon Sep 17 00:00:00 2001
  2771. From: Roland Mainz <roland.mainz@nrubsig.org>
  2772. Date: Sat, 29 Nov 2025 16:11:35 +0100
  2773. Subject: [PATCH 20/28] sys: Implement SRV_OPEN collapsing
  2774.  
  2775. Implement SRV_OPEN collapsing.
  2776.  
  2777. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  2778. ---
  2779. sys/nfs41sys_buildconfig.h |  46 ++++++++++++
  2780.  sys/nfs41sys_driver.c      |  11 +++
  2781.  sys/nfs41sys_driver.h      |  15 ++++
  2782.  sys/nfs41sys_openclose.c   | 149 +++++++++++++++++++++++++++++++++++++
  2783.  sys/nfs41sys_updowncall.c  |  32 ++++++++
  2784.  sys/nfs41sys_util.c        |  59 +++++++++++++++
  2785.  sys/nfs41sys_util.h        |   3 +
  2786.  7 files changed, 315 insertions(+)
  2787.  
  2788. diff --git a/sys/nfs41sys_buildconfig.h b/sys/nfs41sys_buildconfig.h
  2789. index 760f39d..dea5e1d 100644
  2790. --- a/sys/nfs41sys_buildconfig.h
  2791. +++ b/sys/nfs41sys_buildconfig.h
  2792. @@ -50,6 +50,52 @@
  2793.  // #define LOOKASIDELISTS_STATS 1
  2794.  #endif /* (NTDDI_VERSION >= NTDDI_WIN10_VB) */
  2795.  
  2796. +/*
  2797. + * |ENABLE_COLLAPSEOPEN| - SRV_OPEN collapse support
  2798. + *
  2799. + * This will re-use an existing SRV_OPEN
  2800. + * when opening a file with matching parameters/flags, avoiding an
  2801. + * upcall to the NFS server.
  2802. + *
  2803. + * This is currently experimental (and shoud be a mount option),
  2804. + * requires more testing.
  2805. + *
  2806. + * Note this only has limited benefits (because it only short-cuts
  2807. + * duplicate file opening requests to the NFS server) except in a
  2808. + * benchmark which measures pure file |open()| performance:
  2809. + * ---- snip ----
  2810. + * $ cat "open_x_c_100000times.c"
  2811. + * #include <windows.h>
  2812. + * int main() {
  2813. + *     CreateFileA("x.c", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
  2814. + *     for(int i=0;i<100000;i++) {
  2815. + *         HANDLE h;
  2816. + *         h = CreateFileA("x.c", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
  2817. + *         CloseHandle(h);
  2818. + *     }
  2819. + *     return 0;
  2820. + * }
  2821. + *
  2822. + * # with collapsing enabled:
  2823. + * $ time ./open_x_c_100000times.c
  2824. + *
  2825. + * real    3m20.027s
  2826. + * user    0m0.562s
  2827. + * sys     0m34.296s
  2828. + * # collapsing disabled:
  2829. + * $ time ./open_x_c_100000times.c
  2830. + *
  2831. + * real    6m59.528s
  2832. + * user    0m1.155s
  2833. + * sys     0m48.936s
  2834. + * ---- snip ----
  2835. + */
  2836. +#define ENABLE_COLLAPSEOPEN 1
  2837. +#ifdef ENABLE_COLLAPSEOPEN
  2838. +#define WINBUG_NO_COLLAPSE_IF_PRIMARYGROUPS_DIFFER 1
  2839. +#define WINBUG_WORKAROUND_CLOSESRVOPEN_CALLED_AFTER_FOXB_CLEANUP 1
  2840. +#endif /* ENABLE_COLLAPSEOPEN */
  2841. +
  2842.  /* debugging printout defines */
  2843.  #if defined(_DEBUG)
  2844.  /* Debug build defines follow... */
  2845. diff --git a/sys/nfs41sys_driver.c b/sys/nfs41sys_driver.c
  2846. index 0b7a1f6..a8a2810 100644
  2847. --- a/sys/nfs41sys_driver.c
  2848. +++ b/sys/nfs41sys_driver.c
  2849. @@ -787,6 +787,17 @@ NTSTATUS nfs41_CreateSrvCall(
  2850.      ASSERT( pSrvCall );
  2851.      ASSERT( NodeType(pSrvCall) == RDBSS_NTC_SRVCALL );
  2852.  
  2853. +#ifdef ENABLE_COLLAPSEOPEN
  2854. +    /*
  2855. +     * FIXME: This should be a tuneable
  2856. +     *
  2857. +     * Notes:
  2858. +     * - Windows 10 limit is 1023 per
  2859. +     * $ powershell -Command 'Get-SmbClientConfiguration | Select DormantFileLimit'
  2860. +     */
  2861. +    pSrvCall->MaximumNumberOfCloseDelayedFiles = 8192;
  2862. +#endif /* ENABLE_COLLAPSEOPEN */
  2863. +
  2864.      if (IoGetCurrentProcess() == RxGetRDBSSProcess()) {
  2865.          DbgP("executing with RDBSS context\n");
  2866.          status = _nfs41_CreateSrvCall(pCallbackContext);
  2867. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  2868. index 9c979f7..32b3629 100644
  2869. --- a/sys/nfs41sys_driver.h
  2870. +++ b/sys/nfs41sys_driver.h
  2871. @@ -500,8 +500,23 @@ typedef struct _NFS41_FCB {
  2872.          (((pFcb) == NULL) ? NULL : (PNFS41_FCB)((pFcb)->Context))
  2873.  
  2874.  typedef struct _NFS41_SRV_OPEN {
  2875. +    BOOLEAN         initialised;
  2876.      HANDLE          nfs41_open_state;
  2877.      DWORD           deleg_type;
  2878. +#ifdef WINBUG_NO_COLLAPSE_IF_PRIMARYGROUPS_DIFFER
  2879. +    /*
  2880. +     * |open_pg_sidbuff| - Note that buffers with SID values must be 16byte
  2881. +     * aligned on Windows 10/32bit
  2882. +     */
  2883. +#ifdef _MSC_BUILD
  2884. +    __declspec(align(16)) char open_pg_sidbuff[SID_BUF_SIZE];
  2885. +#else
  2886. +    char open_pg_sidbuff[SID_BUF_SIZE] __attribute__((aligned(16)));
  2887. +#endif /* _MSC_BUILD */
  2888. +
  2889. +    /* |open_pg_sid| - PrimaryGroup SID used for opening this NFS handle */
  2890. +    PSID            open_pg_sid;
  2891. +#endif /* WINBUG_NO_COLLAPSE_IF_PRIMARYGROUPS_DIFFER */
  2892.  } NFS41_SRV_OPEN, *PNFS41_SRV_OPEN;
  2893.  #define NFS41GetSrvOpenExtension(pSrvOpen)  \
  2894.          (((pSrvOpen) == NULL) ? NULL : (PNFS41_SRV_OPEN)((pSrvOpen)->Context))
  2895. diff --git a/sys/nfs41sys_openclose.c b/sys/nfs41sys_openclose.c
  2896. index 41cc89a..c88d27f 100644
  2897. --- a/sys/nfs41sys_openclose.c
  2898. +++ b/sys/nfs41sys_openclose.c
  2899. @@ -682,6 +682,28 @@ NTSTATUS nfs41_Create(
  2900.          ExInitializeFastMutex(&nfs41_fcb->aclcache.lock);
  2901.      }
  2902.  
  2903. +    if (nfs41_srvopen->initialised == FALSE) {
  2904. +        nfs41_srvopen->initialised = TRUE;
  2905. +#ifdef WINBUG_NO_COLLAPSE_IF_PRIMARYGROUPS_DIFFER
  2906. +        /* PrimaryGroup SID used for opening this NFS handle */
  2907. +        nfs41_srvopen->open_pg_sid = (PSID)nfs41_srvopen->open_pg_sidbuff;
  2908. +
  2909. +        /*
  2910. +         * Store PrimaryGroup SID used to create the |SRV_OPEN|
  2911. +         *
  2912. +         * This is used to test whether the PrimaryGroup of a
  2913. +         * collapsing request is the same as this SID, and reject
  2914. +         * the collapsing request if the groups do not match,
  2915. +         * to avoid that a |SRV_OPEN| with the wrong group is reused.
  2916. +         */
  2917. +        if (!get_primarygroup_id(nfs41_srvopen->open_pg_sid)) {
  2918. +            DbgP("nfs41_Create: get_primarygroup_id() failed\n");
  2919. +            status = STATUS_INSUFFICIENT_RESOURCES;
  2920. +            goto out;
  2921. +        }
  2922. +#endif /* WINBUG_NO_COLLAPSE_IF_PRIMARYGROUPS_DIFFER */
  2923. +    }
  2924. +
  2925.      debug_printirpecps(RxContext->CurrentIrp);
  2926.  
  2927.      PQUERY_ON_CREATE_ECP_CONTEXT qocec =
  2928. @@ -1246,9 +1268,100 @@ out:
  2929.  NTSTATUS nfs41_ShouldTryToCollapseThisOpen(
  2930.      IN OUT PRX_CONTEXT RxContext)
  2931.  {
  2932. +#ifdef ENABLE_COLLAPSEOPEN
  2933. +    NTSTATUS status = STATUS_SUCCESS;
  2934. +    PNFS41_FCB nfs41_fcb = NFS41GetFcbExtension(RxContext->pFcb);
  2935. +    PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2936. +    PNFS41_SRV_OPEN nfs41_srvopen = NFS41GetSrvOpenExtension(SrvOpen);
  2937. +
  2938. +    if (SrvOpen == NULL) {
  2939. +        DbgP("nfs41_ShouldTryToCollapseThisOpen: "
  2940. +            "SrvOpen==NULL, status=STATUS_SUCCESS\n");
  2941. +        return STATUS_SUCCESS;
  2942. +    }
  2943. +
  2944. +    if (nfs41_fcb->StandardInfo.Directory) {
  2945. +        status = STATUS_MORE_PROCESSING_REQUIRED;
  2946. +        goto out;
  2947. +    }
  2948. +
  2949. +#ifdef WINBUG_NO_COLLAPSE_IF_PRIMARYGROUPS_DIFFER
  2950. +    /*
  2951. +     * Reject srvopens if the primary group used to create
  2952. +     * |RxContext->pRelevantSrvOpen| does not match the current primary group
  2953. +     *
  2954. +     * Example:
  2955. +     * $ bash -c $'command exec {n}<x.c ; newgrp cygwingrp2 bash -c \'id -a ; \
  2956. +     * for ((i=0 ; i < 5 ; i++)) ; do (command exec {nn}<x.c) done\''
  2957. +     *
  2958. +     * What happens here is that we start with primarygroup="None",
  2959. +     * start bash.exe, obtain a read file handle for file "x.c".
  2960. +     * Then we call newgrp to run a new bash.exe with a different primarygroup
  2961. +     * ("cygwingrp2", but same user), and request read file handles for "x.c"
  2962. +     * again.
  2963. +     * |MRxCollapseOpen()| is called to collapse the open request for "x.c"
  2964. +     * with primarygroup="cygwingrp2" into the SRV_OPEN which was created for
  2965. +     * primarygroup="Kein" - which leads to a privilege escalation if group
  2966. +     * "Kein" has access to the file but group "cygwingrp2" does not.
  2967. +     */
  2968. +
  2969. +    /*
  2970. +     * |pg_sidbuff| - Note that buffers with SID values must be 16byte
  2971. +     * aligned on Windows 10/32bit
  2972. +     */
  2973. +#ifdef _MSC_BUILD
  2974. +    __declspec(align(16)) char pg_sidbuff[SID_BUF_SIZE];
  2975. +#else
  2976. +    char pg_sidbuff[SID_BUF_SIZE] __attribute__((aligned(16)));
  2977. +#endif /* _MSC_BUILD */
  2978. +    PSID pg_sid = (PSID)pg_sidbuff;
  2979. +
  2980. +    (void)get_primarygroup_id(pg_sid);
  2981. +
  2982. +    if (RtlEqualSid(pg_sid, nfs41_srvopen->open_pg_sid)) {
  2983. +        status = STATUS_SUCCESS;
  2984. +    }
  2985. +    else {
  2986. +        wchar_t pg_sid_string_buf[200];
  2987. +        UNICODE_STRING pg_sid_string = {
  2988. +            .Buffer = pg_sid_string_buf,
  2989. +            .Length = 0,
  2990. +            .MaximumLength = sizeof(pg_sid_string_buf)
  2991. +        };
  2992. +
  2993. +        wchar_t srvopen_pg_sid_string_buf[200];
  2994. +        UNICODE_STRING srvopen_pg_sid_string = {
  2995. +            .Buffer = srvopen_pg_sid_string_buf,
  2996. +            .Length = 0,
  2997. +            .MaximumLength = sizeof(srvopen_pg_sid_string_buf)
  2998. +        };
  2999. +
  3000. +        (void)RtlConvertSidToUnicodeString(&pg_sid_string, pg_sid, FALSE);
  3001. +        (void)RtlConvertSidToUnicodeString(&srvopen_pg_sid_string,
  3002. +            nfs41_srvopen->open_pg_sid, FALSE);
  3003. +        DbgP("nfs41_ShouldTryToCollapseThisOpen: "
  3004. +            "Threads pg SID('%wZ') != nfs41_srvopen->open_pg_sid('%wZ')\n",
  3005. +            &pg_sid_string,
  3006. +            &srvopen_pg_sid_string);
  3007. +
  3008. +        status = STATUS_MORE_PROCESSING_REQUIRED;
  3009. +        goto out;
  3010. +    }
  3011. +#else
  3012. +    status = STATUS_SUCCESS;
  3013. +#endif /* WINBUG_NO_COLLAPSE_IF_PRIMARYGROUPS_DIFFER */
  3014. +
  3015. +out:
  3016. +    DbgP("nfs41_ShouldTryToCollapseThisOpen: filename='%wZ', status=0x%lx\n",
  3017. +        SrvOpen->pAlreadyPrefixedName,
  3018. +        (long)status);
  3019. +
  3020. +    return status;
  3021. +#else
  3022.      if (RxContext->pRelevantSrvOpen == NULL)
  3023.          return STATUS_SUCCESS;
  3024.      return STATUS_MORE_PROCESSING_REQUIRED;
  3025. +#endif /* ENABLE_COLLAPSEOPEN */
  3026.  }
  3027.  
  3028.  /*
  3029. @@ -1260,7 +1373,43 @@ NTSTATUS nfs41_ShouldTryToCollapseThisOpen(
  3030.  NTSTATUS nfs41_CollapseOpen(
  3031.      IN OUT PRX_CONTEXT RxContext)
  3032.  {
  3033. +#ifdef ENABLE_COLLAPSEOPEN
  3034. +    NTSTATUS status;
  3035. +    PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  3036. +
  3037. +    FsRtlEnterFileSystem();
  3038. +
  3039. +    /*
  3040. +     * FIXME/ToDo:
  3041. +     * - Check whether ECP (Extended Create Parameters) must be handled
  3042. +     * - Check whether Cygwin/SFU EA must be handled
  3043. +     */
  3044. +
  3045. +    debug_printirpecps(RxContext->CurrentIrp);
  3046. +
  3047. +    PQUERY_ON_CREATE_ECP_CONTEXT qocec =
  3048. +        get_queryoncreateecpcontext(RxContext->CurrentIrp);
  3049. +    if (qocec) {
  3050. +        DbgP("nfs41_CollapseOpen: RequestedClasses=0x%lx\n",
  3051. +            qocec->RequestedClasses);
  3052. +    }
  3053. +
  3054. +    status = nfs41_createnetfobx(RxContext, SrvOpen);
  3055. +    if (status)
  3056. +        goto out;
  3057. +
  3058. +    RxContext->pFobx->OffsetOfNextEaToReturn = 1; /* FIXME: Why ? */
  3059. +    status = STATUS_SUCCESS;
  3060. +
  3061. +out:
  3062. +    DbgP("nfs41_CollapseOpen: collapsingopen for '%wZ', status=0x%lx\n",
  3063. +        SrvOpen->pAlreadyPrefixedName,
  3064. +        (long)status);
  3065. +
  3066. +    FsRtlExitFileSystem();
  3067. +#else
  3068.      NTSTATUS status = STATUS_MORE_PROCESSING_REQUIRED;
  3069. +#endif /* ENABLE_COLLAPSEOPEN */
  3070.      return status;
  3071.  }
  3072.  
  3073. diff --git a/sys/nfs41sys_updowncall.c b/sys/nfs41sys_updowncall.c
  3074. index cd1c1c2..84417e7 100644
  3075. --- a/sys/nfs41sys_updowncall.c
  3076. +++ b/sys/nfs41sys_updowncall.c
  3077. @@ -383,6 +383,38 @@ NTSTATUS nfs41_UpcallCreate(
  3078.      KeInitializeEvent(&entry->cond, SynchronizationEvent, FALSE);
  3079.      ExInitializeFastMutex(&entry->lock);
  3080.  
  3081. +#ifdef WINBUG_WORKAROUND_CLOSESRVOPEN_CALLED_AFTER_FOXB_CLEANUP
  3082. +    /*
  3083. +     * HACK: Workaround the RDBSS bug where |RxPurgeRelatedFobxs()| first
  3084. +     * destroyes a FOBX via |RxFinalizeNetFobx()|,and then calls
  3085. +     * |nfs41_CloseSrvOpen()| to close the SRV_OPEN with the same FOBX,
  3086. +     * which results in |clnt_sec_ctx->ClientToken == NULL|.
  3087. +     *
  3088. +     * Without the workaround we crash like this, because
  3089. +     * |clnt_sec_ctx->ClientToken == NULL|:
  3090. +     * ---- snip ----
  3091. +     * nt!ObfReferenceObject
  3092. +     * nfs41_driver!nfs41_UpcallCreate
  3093. +     * nfs41_driver!nfs41_CloseSrvOpen
  3094. +     * nfs41_driver!RxCloseAssociatedSrvOpen
  3095. +     * nfs41_driver!RxFinalizeNetFobx
  3096. +     * nfs41_driver!RxDereference
  3097. +     * nfs41_driver!RxPurgeRelatedFobxs
  3098. +     * nfs41_driver!RxCommonSetInformation
  3099. +     * nfs41_driver!RxFsdCommonDispatch
  3100. +     * nfs41_driver!RxFsdDispatch
  3101. +     * nfs41_driver!nfs41_FsdDispatch
  3102. +     * ---- snip ----
  3103. +     */
  3104. +    if (opcode == NFS41_SYSOP_CLOSE) {
  3105. +        if (clnt_sec_ctx) {
  3106. +            if (clnt_sec_ctx->ClientToken == NULL) {
  3107. +                clnt_sec_ctx = NULL;
  3108. +            }
  3109. +        }
  3110. +    }
  3111. +#endif /* WINBUG_WORKAROUND_CLOSESRVOPEN_CALLED_AFTER_FOXB_CLEANUP */
  3112. +
  3113.      if (clnt_sec_ctx == NULL) {
  3114.          SeCaptureSubjectContext(&sec_ctx);
  3115.          sec_qos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
  3116. diff --git a/sys/nfs41sys_util.c b/sys/nfs41sys_util.c
  3117. index 27691fd..f116aa5 100644
  3118. --- a/sys/nfs41sys_util.c
  3119. +++ b/sys/nfs41sys_util.c
  3120. @@ -221,3 +221,62 @@ PQUERY_ON_CREATE_ECP_CONTEXT get_queryoncreateecpcontext(
  3121.  
  3122.      return (PQUERY_ON_CREATE_ECP_CONTEXT)ecpContext;
  3123.  }
  3124. +
  3125. +bool get_primarygroup_id(__out SID *restrict ret_sid)
  3126. +{
  3127. +    PACCESS_TOKEN token = NULL;
  3128. +    PVOID infoBuffer = NULL;
  3129. +    NTSTATUS status;
  3130. +    bool retval = false;
  3131. +
  3132. +    BOOLEAN copyOnOpen = FALSE;
  3133. +    BOOLEAN effectiveOnly = FALSE;
  3134. +    SECURITY_IMPERSONATION_LEVEL impLevel;
  3135. +    token = PsReferenceImpersonationToken(PsGetCurrentThread(),
  3136. +        &copyOnOpen, &effectiveOnly, &impLevel);
  3137. +    if (token == NULL) {
  3138. +        token = PsReferencePrimaryToken(PsGetCurrentProcess());
  3139. +        if (token == NULL) {
  3140. +            DbgP("get_primarygroup_id: Failed to get token\n");
  3141. +            return false;
  3142. +        }
  3143. +    }
  3144. +
  3145. +    status = SeQueryInformationToken(token,
  3146. +        TokenPrimaryGroup, &infoBuffer);
  3147. +    if (!NT_SUCCESS(status) || (infoBuffer == NULL)) {
  3148. +        DbgPrint("get_primarygroup_id: "
  3149. +            "SeQueryInformationToken(TokenPrimaryGroup) failed: 0x%lx\n",
  3150. +            (long)status);
  3151. +        goto out_cleanup_sequeryinfotok;
  3152. +    }
  3153. +
  3154. +    TOKEN_PRIMARY_GROUP *primaryGroup = (TOKEN_PRIMARY_GROUP *)infoBuffer;
  3155. +    if ((primaryGroup == NULL) || (primaryGroup->PrimaryGroup == NULL)) {
  3156. +        DbgP("get_primarygroup_id: "
  3157. +            "primaryGroup or PrimaryGroup SID is NULL\n");
  3158. +        goto out_cleanup_sequeryinfotok;
  3159. +    }
  3160. +
  3161. +    ULONG sidLength = RtlLengthSid(primaryGroup->PrimaryGroup);
  3162. +    if ((sidLength == 0UL) || (sidLength > SID_BUF_SIZE)) {
  3163. +        DbgP("get_primarygroup_id: "
  3164. +            "SID length (%lu) invalid or too large for buffer (%u)\n",
  3165. +            sidLength, (unsigned)SID_BUF_SIZE);
  3166. +        goto out_cleanup_sequeryinfotok;
  3167. +    }
  3168. +
  3169. +    (void)memcpy(ret_sid, primaryGroup->PrimaryGroup, sidLength);
  3170. +    retval = true;
  3171. +
  3172. +out_cleanup_sequeryinfotok:
  3173. +    if (infoBuffer) {
  3174. +        ExFreePool(infoBuffer);
  3175. +    }
  3176. +
  3177. +    if (token) {
  3178. +        ObDereferenceObject(token);
  3179. +    }
  3180. +
  3181. +    return retval;
  3182. +}
  3183. diff --git a/sys/nfs41sys_util.h b/sys/nfs41sys_util.h
  3184. index 793f440..f3a1aec 100644
  3185. --- a/sys/nfs41sys_util.h
  3186. +++ b/sys/nfs41sys_util.h
  3187. @@ -24,6 +24,8 @@
  3188.  #ifndef _NFS41SYS_UTIL_H_
  3189.  #define _NFS41SYS_UTIL_H_ 1
  3190.  
  3191. +#include <stdbool.h>
  3192. +
  3193.  static INLINE BOOL AnsiStrEq(
  3194.      IN const ANSI_STRING *lhs,
  3195.      IN const CHAR *rhs,
  3196. @@ -67,5 +69,6 @@ NTSTATUS nfs41_UnmapLockedKernelPagesInNfsDaemonAddressSpace(
  3197.      __in PMDL  MemoryDescriptorList);
  3198.  PQUERY_ON_CREATE_ECP_CONTEXT get_queryoncreateecpcontext(
  3199.      __in PIRP Irp);
  3200. +bool get_primarygroup_id(__out SID *restrict ret_sid);
  3201.  
  3202.  #endif /* !_NFS41SYS_UTIL_H_ */
  3203. --
  3204. 2.51.0
  3205.  
  3206. From e3b62e6418a2605ed6ac7ecf82e26863b2466322 Mon Sep 17 00:00:00 2001
  3207. From: Dan Shelton <dan.f.shelton@gmail.com>
  3208. Date: Sat, 29 Nov 2025 16:26:28 +0100
  3209. Subject: [PATCH 21/28] sys: nfs41_UpcallCreate()+opcode2string() should use
  3210.  nfs41_opcodes enum
  3211.  
  3212. nfs41_UpcallCreate()+opcode2string() should use nfs41_opcodes enum.
  3213.  
  3214. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  3215. ---
  3216. sys/nfs41sys_debug.c      | 2 +-
  3217.  sys/nfs41sys_debug.h      | 4 +++-
  3218.  sys/nfs41sys_driver.h     | 4 +++-
  3219.  sys/nfs41sys_updowncall.c | 2 +-
  3220.  4 files changed, 8 insertions(+), 4 deletions(-)
  3221.  
  3222. diff --git a/sys/nfs41sys_debug.c b/sys/nfs41sys_debug.c
  3223. index f17fa13..a8513e9 100644
  3224. --- a/sys/nfs41sys_debug.c
  3225. +++ b/sys/nfs41sys_debug.c
  3226. @@ -671,7 +671,7 @@ void print_caching_level(int on, ULONG flag, PUNICODE_STRING name)
  3227.      }
  3228.  }
  3229.  
  3230. -const char *opcode2string(int opcode)
  3231. +const char *opcode2string(nfs41_opcodes opcode)
  3232.  {
  3233.      switch(opcode) {
  3234.      case NFS41_SYSOP_SHUTDOWN: return "NFS41_SYSOP_SHUTDOWN";
  3235. diff --git a/sys/nfs41sys_debug.h b/sys/nfs41sys_debug.h
  3236. index aac1c31..d9dd4d0 100644
  3237. --- a/sys/nfs41sys_debug.h
  3238. +++ b/sys/nfs41sys_debug.h
  3239. @@ -24,6 +24,8 @@
  3240.  #ifndef NFS41SYS_DEBUG_H
  3241.  #define NFS41SYS_DEBUG_H 1
  3242.  
  3243. +typedef enum _nfs41_opcodes nfs41_opcodes;
  3244. +
  3245.  #define _DRIVER_NAME_ "NFS4.1 Driver"
  3246.  
  3247.  ULONG __cdecl DbgP(IN PCCH fmt, ...);
  3248. @@ -50,7 +52,7 @@ void print_std_info(int on, PFILE_STANDARD_INFORMATION info);
  3249.  void print_ea_info(PFILE_FULL_EA_INFORMATION info);
  3250.  void print_get_ea(int on, PFILE_GET_EA_INFORMATION info);
  3251.  void print_caching_level(int on, ULONG flag, PUNICODE_STRING s);
  3252. -const char *opcode2string(int opcode);
  3253. +const char *opcode2string(nfs41_opcodes opcode);
  3254.  void print_open_error(int on, int status);
  3255.  void print_wait_status(int on, const char *str, NTSTATUS status,
  3256.                         const char *opcode, PVOID entry, LONGLONG xid);
  3257. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  3258. index 32b3629..40eb7ea 100644
  3259. --- a/sys/nfs41sys_driver.h
  3260. +++ b/sys/nfs41sys_driver.h
  3261. @@ -34,6 +34,8 @@
  3262.  
  3263.  #include "nfs_ea.h"
  3264.  
  3265. +typedef enum _nfs41_opcodes nfs41_opcodes;
  3266. +
  3267.  #if (NTDDI_VERSION >= NTDDI_WIN10_VB)
  3268.  #define EXALLOCATEPOOLWITHTAG_DEPRECATED 1
  3269.  #endif /* (NTDDI_VERSION >= NTDDI_WIN10_VB) */
  3270. @@ -928,7 +930,7 @@ void unmarshal_nfs41_attrget(
  3271.      const unsigned char *restrict *restrict buf,
  3272.      BOOL copy_partial);
  3273.  NTSTATUS nfs41_UpcallCreate(
  3274. -    IN DWORD opcode,
  3275. +    IN nfs41_opcodes opcode,
  3276.      IN PSECURITY_CLIENT_CONTEXT clnt_sec_ctx,
  3277.      IN HANDLE session,
  3278.      IN HANDLE open_state,
  3279. diff --git a/sys/nfs41sys_updowncall.c b/sys/nfs41sys_updowncall.c
  3280. index 84417e7..4a44f2b 100644
  3281. --- a/sys/nfs41sys_updowncall.c
  3282. +++ b/sys/nfs41sys_updowncall.c
  3283. @@ -349,7 +349,7 @@ out:
  3284.  }
  3285.  
  3286.  NTSTATUS nfs41_UpcallCreate(
  3287. -    IN DWORD opcode,
  3288. +    IN nfs41_opcodes opcode,
  3289.      IN PSECURITY_CLIENT_CONTEXT clnt_sec_ctx,
  3290.      IN HANDLE session,
  3291.      IN HANDLE open_state,
  3292. --
  3293. 2.51.0
  3294.  
  3295. From 858d1a030423743d9c1c396e7e7650bc83e63f00 Mon Sep 17 00:00:00 2001
  3296. From: Cedric Blancher <cedric.blancher@gmail.com>
  3297. Date: Sat, 29 Nov 2025 16:44:00 +0100
  3298. Subject: [PATCH 22/28] daemon: get_superblock_attrs() should print fsid when
  3299.  warning that "forcecaseinsensitive=1" mount override is active
  3300.  
  3301. get_superblock_attrs() should print fsid when warning that
  3302. "forcecaseinsensitive=1" mount override is active.
  3303.  
  3304. Signed-off-by: Roland Mainz <roland.mainz@nrubsig.org>
  3305. ---
  3306. daemon/nfs41_superblock.c | 8 ++++++--
  3307.  1 file changed, 6 insertions(+), 2 deletions(-)
  3308.  
  3309. diff --git a/daemon/nfs41_superblock.c b/daemon/nfs41_superblock.c
  3310. index 3e64444..5ffb171 100644
  3311. --- a/daemon/nfs41_superblock.c
  3312. +++ b/daemon/nfs41_superblock.c
  3313. @@ -134,7 +134,9 @@ static int get_superblock_attrs(
  3314.      else {
  3315.          superblock->case_preserving = BOOL2BIT(root->force_case_preserving);
  3316.          DPRINTF(0,
  3317. -            ("get_superblock_attrs: OVERRIDING case_preserving to %d\n",
  3318. +            ("get_superblock_attrs(fsid=(%llu,%llu)): "
  3319. +            "OVERRIDING case_preserving to %d\n",
  3320. +            superblock->fsid.major, superblock->fsid.minor,
  3321.              (int)superblock->case_preserving));
  3322.      }
  3323.      if (root->force_case_insensitive == TRISTATE_BOOL_NOT_SET) {
  3324. @@ -143,7 +145,9 @@ static int get_superblock_attrs(
  3325.      else {
  3326.          superblock->case_insensitive = BOOL2BIT(root->force_case_insensitive);
  3327.          DPRINTF(0,
  3328. -            ("get_superblock_attrs: OVERRIDING case_insensitive to %d\n",
  3329. +            ("get_superblock_attrs(fsid=(%llu,%llu)): "
  3330. +            "OVERRIDING case_insensitive to %d\n",
  3331. +            superblock->fsid.major, superblock->fsid.minor,
  3332.              (int)superblock->case_insensitive));
  3333.      }
  3334.  #else
  3335. --
  3336. 2.51.0
  3337.  
  3338. From 543202a540ed0c412984f8700eb81e8849a85558 Mon Sep 17 00:00:00 2001
  3339. From: Roland Mainz <roland.mainz@nrubsig.org>
  3340. Date: Sat, 29 Nov 2025 17:40:53 +0100
  3341. Subject: [PATCH 23/28] daemon,include,sys: Kernel should use enum for
  3342.  |deleg_type|
  3343.  
  3344. Kernel should use an enum for |deleg_type|.
  3345.  
  3346. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  3347. ---
  3348. daemon/nfs41_ops.h       |  1 +
  3349.  include/nfs41_driver.h   |  8 ++++++++
  3350.  sys/nfs41sys_acl.c       |  5 +++--
  3351.  sys/nfs41sys_driver.c    |  4 ++--
  3352.  sys/nfs41sys_driver.h    |  2 +-
  3353.  sys/nfs41sys_ea.c        |  2 +-
  3354.  sys/nfs41sys_fileinfo.c  |  2 +-
  3355.  sys/nfs41sys_openclose.c | 14 ++++++++------
  3356.  sys/nfs41sys_readwrite.c |  4 ++--
  3357.  9 files changed, 27 insertions(+), 15 deletions(-)
  3358.  
  3359. diff --git a/daemon/nfs41_ops.h b/daemon/nfs41_ops.h
  3360. index f1bf145..c7d45a8 100644
  3361. --- a/daemon/nfs41_ops.h
  3362. +++ b/daemon/nfs41_ops.h
  3363. @@ -621,6 +621,7 @@ enum {
  3364.      OPEN4_SHARE_ACCESS_WANT_PUSH_DELEG_WHEN_UNCONTENDED = 0x20000
  3365.  };
  3366.  
  3367. +/* Same as "include/nfs41_driver.h" |nfs41_open_delegation_type| */
  3368.  enum open_delegation_type4 {
  3369.      OPEN_DELEGATE_NONE      = 0,
  3370.      OPEN_DELEGATE_READ      = 1,
  3371. diff --git a/include/nfs41_driver.h b/include/nfs41_driver.h
  3372. index ce4fb54..dbb17ba 100644
  3373. --- a/include/nfs41_driver.h
  3374. +++ b/include/nfs41_driver.h
  3375. @@ -97,6 +97,14 @@ typedef enum _nfs41_opcodes {
  3376.      NFS41_SYSOP_INVALID_OPCODE1
  3377.  } nfs41_opcodes;
  3378.  
  3379. +/* Same as "daemon/nfs41_ops.h" |open_delegation_type4| */
  3380. +typedef enum _nfs41_open_delegation_type {
  3381. +    NFS41_OPEN_DELEGATE_NONE      = 0,
  3382. +    NFS41_OPEN_DELEGATE_READ      = 1,
  3383. +    NFS41_OPEN_DELEGATE_WRITE     = 2,
  3384. +    NFS41_OPEN_DELEGATE_NONE_EXT  = 3
  3385. +} nfs41_open_delegation_type;
  3386. +
  3387.  /*
  3388.   * Same as |FILE_FS_ATTRIBUTE_INFORMATION| but with inline buffer
  3389.   * for 32 characters
  3390. diff --git a/sys/nfs41sys_acl.c b/sys/nfs41sys_acl.c
  3391. index 16caa63..1ef55ca 100644
  3392. --- a/sys/nfs41sys_acl.c
  3393. +++ b/sys/nfs41sys_acl.c
  3394. @@ -521,8 +521,9 @@ NTSTATUS nfs41_SetSecurityInformation(
  3395.  
  3396.      status = map_query_acl_error(entry->status);
  3397.      if (!status) {
  3398. -        if ((nfs41_srvopen->deleg_type == 0) && entry->ChangeTime &&
  3399. -                (SrvOpen->DesiredAccess &
  3400. +        if ((nfs41_srvopen->deleg_type == NFS41_OPEN_DELEGATE_NONE) &&
  3401. +            entry->ChangeTime &&
  3402. +            (SrvOpen->DesiredAccess &
  3403.                  (FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)))
  3404.              nfs41_update_fcb_list(RxContext->pFcb, entry->ChangeTime);
  3405.          nfs41_fcb->changeattr = entry->ChangeTime;
  3406. diff --git a/sys/nfs41sys_driver.c b/sys/nfs41sys_driver.c
  3407. index a8a2810..b906e64 100644
  3408. --- a/sys/nfs41sys_driver.c
  3409. +++ b/sys/nfs41sys_driver.c
  3410. @@ -1090,7 +1090,7 @@ void enable_caching(
  3411.          }
  3412.          pEntry = pEntry->Flink;
  3413.      }
  3414. -    if (!found && (nfs41_srvopen->deleg_type != 0)) {
  3415. +    if (!found && (nfs41_srvopen->deleg_type != NFS41_OPEN_DELEGATE_NONE)) {
  3416.          nfs41_fcb_list_entry *oentry;
  3417.  #ifdef DEBUG_TIME_BASED_COHERENCY
  3418.          DbgP("enable_caching: delegation recalled: srv_open=0x%p\n", SrvOpen);
  3419. @@ -1104,7 +1104,7 @@ void enable_caching(
  3420.          oentry->ChangeTime = ChangeTime;
  3421.          oentry->skip = FALSE;
  3422.          InsertTailList(&openlist.head, &oentry->next);
  3423. -        nfs41_srvopen->deleg_type = 0;
  3424. +        nfs41_srvopen->deleg_type = NFS41_OPEN_DELEGATE_NONE;
  3425.      }
  3426.  out_release_fcblistlock:
  3427.      ExReleaseFastMutexUnsafe(&openlist.lock);
  3428. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  3429. index 40eb7ea..a3a74c7 100644
  3430. --- a/sys/nfs41sys_driver.h
  3431. +++ b/sys/nfs41sys_driver.h
  3432. @@ -504,7 +504,7 @@ typedef struct _NFS41_FCB {
  3433.  typedef struct _NFS41_SRV_OPEN {
  3434.      BOOLEAN         initialised;
  3435.      HANDLE          nfs41_open_state;
  3436. -    DWORD           deleg_type;
  3437. +    nfs41_open_delegation_type deleg_type;
  3438.  #ifdef WINBUG_NO_COLLAPSE_IF_PRIMARYGROUPS_DIFFER
  3439.      /*
  3440.       * |open_pg_sidbuff| - Note that buffers with SID values must be 16byte
  3441. diff --git a/sys/nfs41sys_ea.c b/sys/nfs41sys_ea.c
  3442. index 0f2a9dd..6e690f6 100644
  3443. --- a/sys/nfs41sys_ea.c
  3444. +++ b/sys/nfs41sys_ea.c
  3445. @@ -412,7 +412,7 @@ NTSTATUS nfs41_SetEaInformation(
  3446.  #endif
  3447.      status = map_setea_error(entry->status);
  3448.      if (!status) {
  3449. -        if ((nfs41_srvopen->deleg_type == 0) && entry->ChangeTime &&
  3450. +        if ((nfs41_srvopen->deleg_type == NFS41_OPEN_DELEGATE_NONE) && entry->ChangeTime &&
  3451.                  (SrvOpen->DesiredAccess &
  3452.                  (FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)))
  3453.              nfs41_update_fcb_list(RxContext->pFcb, entry->ChangeTime);
  3454. diff --git a/sys/nfs41sys_fileinfo.c b/sys/nfs41sys_fileinfo.c
  3455. index 1bf736f..be92f0a 100644
  3456. --- a/sys/nfs41sys_fileinfo.c
  3457. +++ b/sys/nfs41sys_fileinfo.c
  3458. @@ -824,7 +824,7 @@ NTSTATUS nfs41_SetFileInformationImpl(
  3459.  
  3460.      status = map_setfile_error(entry->status);
  3461.      if (!status) {
  3462. -        if ((nfs41_srvopen->deleg_type != 0) && entry->ChangeTime &&
  3463. +        if ((nfs41_srvopen->deleg_type != NFS41_OPEN_DELEGATE_NONE) && entry->ChangeTime &&
  3464.                  (SrvOpen->DesiredAccess &
  3465.                  (FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)))
  3466.              nfs41_update_fcb_list(RxContext->pFcb, entry->ChangeTime);
  3467. diff --git a/sys/nfs41sys_openclose.c b/sys/nfs41sys_openclose.c
  3468. index c88d27f..1d2378c 100644
  3469. --- a/sys/nfs41sys_openclose.c
  3470. +++ b/sys/nfs41sys_openclose.c
  3471. @@ -1167,7 +1167,7 @@ retry_on_link:
  3472.  
  3473.          if (!(params->CreateOptions & FILE_WRITE_THROUGH) &&
  3474.                  !pVNetRootContext->write_thru &&
  3475. -                (entry->u.Open.deleg_type == 2 ||
  3476. +                (entry->u.Open.deleg_type == NFS41_OPEN_DELEGATE_WRITE ||
  3477.                  (params->DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)))) {
  3478.  #ifdef DEBUG_OPEN
  3479.              DbgP("nfs41_Create: enabling write buffering\n");
  3480. @@ -1178,8 +1178,9 @@ retry_on_link:
  3481.          } else if (params->CreateOptions & FILE_WRITE_THROUGH ||
  3482.                      pVNetRootContext->write_thru)
  3483.              nfs41_fobx->write_thru = TRUE;
  3484. -        if (entry->u.Open.deleg_type >= 1 ||
  3485. -                params->DesiredAccess & FILE_READ_DATA) {
  3486. +        if ((entry->u.Open.deleg_type == NFS41_OPEN_DELEGATE_READ) ||
  3487. +            (entry->u.Open.deleg_type == NFS41_OPEN_DELEGATE_WRITE) ||
  3488. +            (params->DesiredAccess & FILE_READ_DATA)) {
  3489.  #ifdef DEBUG_OPEN
  3490.              DbgP("nfs41_Create: enabling read buffering\n");
  3491.  #endif
  3492. @@ -1195,7 +1196,7 @@ retry_on_link:
  3493.  #endif
  3494.              SrvOpen->BufferingFlags = FCB_STATE_DISABLE_LOCAL_BUFFERING;
  3495.              nfs41_fobx->nocache = TRUE;
  3496. -        } else if (!entry->u.Open.deleg_type && !Fcb->OpenCount) {
  3497. +        } else if ((entry->u.Open.deleg_type == NFS41_OPEN_DELEGATE_NONE) && !Fcb->OpenCount) {
  3498.              nfs41_fcb_list_entry *oentry;
  3499.  #ifdef DEBUG_OPEN
  3500.              DbgP("nfs41_Create: received no delegations: srv_open=0x%p "
  3501. @@ -1458,8 +1459,9 @@ NTSTATUS nfs41_CloseSrvOpen(
  3502.  #endif
  3503.      FsRtlEnterFileSystem();
  3504.  
  3505. -    if ((nfs41_srvopen->deleg_type == 0) && !nfs41_fcb->StandardInfo.Directory &&
  3506. -            !RxContext->pFcb->OpenCount) {
  3507. +    if ((nfs41_srvopen->deleg_type == NFS41_OPEN_DELEGATE_NONE) &&
  3508. +        !nfs41_fcb->StandardInfo.Directory &&
  3509. +        RxContext->pFcb->OpenCount == 0) {
  3510.          nfs41_remove_fcb_entry(RxContext->pFcb);
  3511.      }
  3512.  
  3513. diff --git a/sys/nfs41sys_readwrite.c b/sys/nfs41sys_readwrite.c
  3514. index 8f313d9..c9f95db 100644
  3515. --- a/sys/nfs41sys_readwrite.c
  3516. +++ b/sys/nfs41sys_readwrite.c
  3517. @@ -443,9 +443,9 @@ NTSTATUS nfs41_Write(
  3518.                   FCB_STATE_WRITECACHING_ENABLED))) {
  3519.              enable_caching(SrvOpen, nfs41_fobx, nfs41_fcb->changeattr,
  3520.                  pVNetRootContext->session);
  3521. -        } else if (nfs41_srvopen->deleg_type == 0)
  3522. +        } else if (nfs41_srvopen->deleg_type == NFS41_OPEN_DELEGATE_NONE) {
  3523.              nfs41_update_fcb_list(RxContext->pFcb, entry->ChangeTime);
  3524. -
  3525. +        }
  3526.      } else {
  3527.          status = map_readwrite_errors(entry->status);
  3528.          RxContext->CurrentIrp->IoStatus.Status = status;
  3529. --
  3530. 2.51.0
  3531.  
  3532. From a85eb27895fa48c85de32131e6f1aabd2c09dc8f Mon Sep 17 00:00:00 2001
  3533. From: Roland Mainz <roland.mainz@nrubsig.org>
  3534. Date: Sat, 29 Nov 2025 18:12:27 +0100
  3535. Subject: [PATCH 24/28] include,sys: Kernel should handle
  3536.  |NFS41_OPEN_DELEGATE_NONE_EXT| the same as |NFS41_OPEN_DELEGATE_NONE|
  3537.  
  3538. Kernel should handle |NFS41_OPEN_DELEGATE_NONE_EXT| the same as
  3539. |NFS41_OPEN_DELEGATE_NONE|.
  3540.  
  3541. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  3542. ---
  3543. include/nfs41_driver.h   | 4 ++++
  3544.  sys/nfs41sys_acl.c       | 2 +-
  3545.  sys/nfs41sys_driver.c    | 2 +-
  3546.  sys/nfs41sys_ea.c        | 5 +++--
  3547.  sys/nfs41sys_fileinfo.c  | 5 +++--
  3548.  sys/nfs41sys_openclose.c | 5 +++--
  3549.  sys/nfs41sys_readwrite.c | 2 +-
  3550.  7 files changed, 16 insertions(+), 9 deletions(-)
  3551.  
  3552. diff --git a/include/nfs41_driver.h b/include/nfs41_driver.h
  3553. index dbb17ba..8aad552 100644
  3554. --- a/include/nfs41_driver.h
  3555. +++ b/include/nfs41_driver.h
  3556. @@ -105,6 +105,10 @@ typedef enum _nfs41_open_delegation_type {
  3557.      NFS41_OPEN_DELEGATE_NONE_EXT  = 3
  3558.  } nfs41_open_delegation_type;
  3559.  
  3560. +#define IS_NFS41_OPEN_DELEGATE_NONE(dt) \
  3561. +    (((dt) == NFS41_OPEN_DELEGATE_NONE) || \
  3562. +     ((dt) == NFS41_OPEN_DELEGATE_NONE_EXT))
  3563. +
  3564.  /*
  3565.   * Same as |FILE_FS_ATTRIBUTE_INFORMATION| but with inline buffer
  3566.   * for 32 characters
  3567. diff --git a/sys/nfs41sys_acl.c b/sys/nfs41sys_acl.c
  3568. index 1ef55ca..0ab1f80 100644
  3569. --- a/sys/nfs41sys_acl.c
  3570. +++ b/sys/nfs41sys_acl.c
  3571. @@ -521,7 +521,7 @@ NTSTATUS nfs41_SetSecurityInformation(
  3572.  
  3573.      status = map_query_acl_error(entry->status);
  3574.      if (!status) {
  3575. -        if ((nfs41_srvopen->deleg_type == NFS41_OPEN_DELEGATE_NONE) &&
  3576. +        if ((IS_NFS41_OPEN_DELEGATE_NONE(nfs41_srvopen->deleg_type)) &&
  3577.              entry->ChangeTime &&
  3578.              (SrvOpen->DesiredAccess &
  3579.                  (FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)))
  3580. diff --git a/sys/nfs41sys_driver.c b/sys/nfs41sys_driver.c
  3581. index b906e64..564087d 100644
  3582. --- a/sys/nfs41sys_driver.c
  3583. +++ b/sys/nfs41sys_driver.c
  3584. @@ -1090,7 +1090,7 @@ void enable_caching(
  3585.          }
  3586.          pEntry = pEntry->Flink;
  3587.      }
  3588. -    if (!found && (nfs41_srvopen->deleg_type != NFS41_OPEN_DELEGATE_NONE)) {
  3589. +    if (!found && (!IS_NFS41_OPEN_DELEGATE_NONE(nfs41_srvopen->deleg_type))) {
  3590.          nfs41_fcb_list_entry *oentry;
  3591.  #ifdef DEBUG_TIME_BASED_COHERENCY
  3592.          DbgP("enable_caching: delegation recalled: srv_open=0x%p\n", SrvOpen);
  3593. diff --git a/sys/nfs41sys_ea.c b/sys/nfs41sys_ea.c
  3594. index 6e690f6..8ba33f4 100644
  3595. --- a/sys/nfs41sys_ea.c
  3596. +++ b/sys/nfs41sys_ea.c
  3597. @@ -412,8 +412,9 @@ NTSTATUS nfs41_SetEaInformation(
  3598.  #endif
  3599.      status = map_setea_error(entry->status);
  3600.      if (!status) {
  3601. -        if ((nfs41_srvopen->deleg_type == NFS41_OPEN_DELEGATE_NONE) && entry->ChangeTime &&
  3602. -                (SrvOpen->DesiredAccess &
  3603. +        if (IS_NFS41_OPEN_DELEGATE_NONE(nfs41_srvopen->deleg_type) &&
  3604. +            entry->ChangeTime &&
  3605. +            (SrvOpen->DesiredAccess &
  3606.                  (FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)))
  3607.              nfs41_update_fcb_list(RxContext->pFcb, entry->ChangeTime);
  3608.          nfs41_fcb->changeattr = entry->ChangeTime;
  3609. diff --git a/sys/nfs41sys_fileinfo.c b/sys/nfs41sys_fileinfo.c
  3610. index be92f0a..b1642bf 100644
  3611. --- a/sys/nfs41sys_fileinfo.c
  3612. +++ b/sys/nfs41sys_fileinfo.c
  3613. @@ -824,8 +824,9 @@ NTSTATUS nfs41_SetFileInformationImpl(
  3614.  
  3615.      status = map_setfile_error(entry->status);
  3616.      if (!status) {
  3617. -        if ((nfs41_srvopen->deleg_type != NFS41_OPEN_DELEGATE_NONE) && entry->ChangeTime &&
  3618. -                (SrvOpen->DesiredAccess &
  3619. +        if ((!IS_NFS41_OPEN_DELEGATE_NONE(nfs41_srvopen->deleg_type)) &&
  3620. +            entry->ChangeTime &&
  3621. +            (SrvOpen->DesiredAccess &
  3622.                  (FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)))
  3623.              nfs41_update_fcb_list(RxContext->pFcb, entry->ChangeTime);
  3624.          nfs41_fcb->changeattr = entry->ChangeTime;
  3625. diff --git a/sys/nfs41sys_openclose.c b/sys/nfs41sys_openclose.c
  3626. index 1d2378c..bde50a0 100644
  3627. --- a/sys/nfs41sys_openclose.c
  3628. +++ b/sys/nfs41sys_openclose.c
  3629. @@ -1196,7 +1196,8 @@ retry_on_link:
  3630.  #endif
  3631.              SrvOpen->BufferingFlags = FCB_STATE_DISABLE_LOCAL_BUFFERING;
  3632.              nfs41_fobx->nocache = TRUE;
  3633. -        } else if ((entry->u.Open.deleg_type == NFS41_OPEN_DELEGATE_NONE) && !Fcb->OpenCount) {
  3634. +        } else if (IS_NFS41_OPEN_DELEGATE_NONE(entry->u.Open.deleg_type) &&
  3635. +            (Fcb->OpenCount == 0)) {
  3636.              nfs41_fcb_list_entry *oentry;
  3637.  #ifdef DEBUG_OPEN
  3638.              DbgP("nfs41_Create: received no delegations: srv_open=0x%p "
  3639. @@ -1459,7 +1460,7 @@ NTSTATUS nfs41_CloseSrvOpen(
  3640.  #endif
  3641.      FsRtlEnterFileSystem();
  3642.  
  3643. -    if ((nfs41_srvopen->deleg_type == NFS41_OPEN_DELEGATE_NONE) &&
  3644. +    if (IS_NFS41_OPEN_DELEGATE_NONE(nfs41_srvopen->deleg_type) &&
  3645.          !nfs41_fcb->StandardInfo.Directory &&
  3646.          RxContext->pFcb->OpenCount == 0) {
  3647.          nfs41_remove_fcb_entry(RxContext->pFcb);
  3648. diff --git a/sys/nfs41sys_readwrite.c b/sys/nfs41sys_readwrite.c
  3649. index c9f95db..75145a5 100644
  3650. --- a/sys/nfs41sys_readwrite.c
  3651. +++ b/sys/nfs41sys_readwrite.c
  3652. @@ -443,7 +443,7 @@ NTSTATUS nfs41_Write(
  3653.                   FCB_STATE_WRITECACHING_ENABLED))) {
  3654.              enable_caching(SrvOpen, nfs41_fobx, nfs41_fcb->changeattr,
  3655.                  pVNetRootContext->session);
  3656. -        } else if (nfs41_srvopen->deleg_type == NFS41_OPEN_DELEGATE_NONE) {
  3657. +        } else if (IS_NFS41_OPEN_DELEGATE_NONE(nfs41_srvopen->deleg_type)) {
  3658.              nfs41_update_fcb_list(RxContext->pFcb, entry->ChangeTime);
  3659.          }
  3660.      } else {
  3661. --
  3662. 2.51.0
  3663.  
  3664. From 102158222e0b9fa45087dd21dbe1501d6e7799cf Mon Sep 17 00:00:00 2001
  3665. From: Roland Mainz <roland.mainz@nrubsig.org>
  3666. Date: Mon, 1 Dec 2025 10:56:27 +0100
  3667. Subject: [PATCH 25/28] sys: Move |nfs41_AreFilesAliased()| and
  3668.  |nfs41_DeallocateForFobx()| to nfs41sys_openclose.c
  3669.  
  3670. Move |nfs41_AreFilesAliased()| and |nfs41_DeallocateForFobx()| to
  3671. nfs41sys_openclose.c.
  3672.  
  3673. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  3674. ---
  3675. sys/nfs41sys_driver.c    | 86 ----------------------------------------
  3676.  sys/nfs41sys_driver.h    |  5 +++
  3677.  sys/nfs41sys_openclose.c | 86 ++++++++++++++++++++++++++++++++++++++++
  3678.  3 files changed, 91 insertions(+), 86 deletions(-)
  3679.  
  3680. diff --git a/sys/nfs41sys_driver.c b/sys/nfs41sys_driver.c
  3681. index 564087d..69616c4 100644
  3682. --- a/sys/nfs41sys_driver.c
  3683. +++ b/sys/nfs41sys_driver.c
  3684. @@ -871,40 +871,6 @@ VOID nfs41_remove_fcb_entry(
  3685.      ExReleaseFastMutexUnsafe(&openlist.lock);
  3686.  }
  3687.  
  3688. -static
  3689. -VOID nfs41_invalidate_fobx_entry(
  3690. -    IN OUT PMRX_FOBX pFobx)
  3691. -{
  3692. -    PLIST_ENTRY pEntry;
  3693. -    nfs41_fcb_list_entry *cur;
  3694. -    __notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(pFobx);
  3695. -
  3696. -    ExAcquireFastMutexUnsafe(&openlist.lock);
  3697. -
  3698. -    pEntry = openlist.head.Flink;
  3699. -    while (!IsListEmpty(&openlist.head)) {
  3700. -        cur = (nfs41_fcb_list_entry *)CONTAINING_RECORD(pEntry,
  3701. -                nfs41_fcb_list_entry, next);
  3702. -        if (cur->nfs41_fobx == nfs41_fobx) {
  3703. -#ifdef DEBUG_CLOSE
  3704. -            DbgP("nfs41_invalidate_fobx_entry: Found match for nfs41_fobx=0x%p\n",
  3705. -                nfs41_fobx);
  3706. -#endif
  3707. -            cur->nfs41_fobx = NULL;
  3708. -            break;
  3709. -        }
  3710. -        if (pEntry->Flink == &openlist.head) {
  3711. -#ifdef DEBUG_CLOSE
  3712. -            DbgP("nfs41_invalidate_fobx_entry: reached EOL looking "
  3713. -                "for nfs41_fobx=0x%p\n", nfs41_fobx);
  3714. -#endif
  3715. -            break;
  3716. -        }
  3717. -        pEntry = pEntry->Flink;
  3718. -    }
  3719. -    ExReleaseFastMutexUnsafe(&openlist.lock);
  3720. -}
  3721. -
  3722.  NTSTATUS nfs41_Flush(
  3723.      IN OUT PRX_CONTEXT RxContext)
  3724.  {
  3725. @@ -929,22 +895,6 @@ NTSTATUS nfs41_DeallocateForFcb(
  3726.      return STATUS_SUCCESS;
  3727.  }
  3728.  
  3729. -NTSTATUS nfs41_DeallocateForFobx(
  3730. -    IN OUT PMRX_FOBX pFobx)
  3731. -{
  3732. -    __notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(pFobx);
  3733. -
  3734. -    nfs41_invalidate_fobx_entry(pFobx);
  3735. -    nfs41_remove_offloadcontext_for_fobx(pFobx);
  3736. -
  3737. -    if (nfs41_fobx->sec_ctx.ClientToken) {
  3738. -        SeDeleteClientSecurity(&nfs41_fobx->sec_ctx);
  3739. -        nfs41_fobx->sec_ctx.ClientToken = NULL;
  3740. -    }
  3741. -
  3742. -    return STATUS_SUCCESS;
  3743. -}
  3744. -
  3745.  VOID nfs41_update_fcb_list(
  3746.      PMRX_FCB fcb,
  3747.      ULONGLONG ChangeTime)
  3748. @@ -1164,42 +1114,6 @@ NTSTATUS nfs41_Unimplemented(
  3749.      return STATUS_NOT_IMPLEMENTED;
  3750.  }
  3751.  
  3752. -NTSTATUS nfs41_AreFilesAliased(
  3753. -    PFCB a,
  3754. -    PFCB b)
  3755. -{
  3756. -    __notnull PNFS41_FCB nfs41_fcb_a = (PNFS41_FCB)a;
  3757. -    __notnull PNFS41_FCB nfs41_fcb_b = (PNFS41_FCB)b;
  3758. -
  3759. -    if ((nfs41_fcb_a->fileid == nfs41_fcb_b->fileid) &&
  3760. -        (nfs41_fcb_a->fsid_major == nfs41_fcb_b->fsid_major) &&
  3761. -        (nfs41_fcb_a->fsid_minor == nfs41_fcb_b->fsid_minor)) {
  3762. -
  3763. -        DbgP("nfs41_AreFilesAliased: "
  3764. -            "a=0x%p b=0x%p aliases, fileid=0x%llx "
  3765. -            "fsid_major=0x%llx fsid_minor=0x%llx\n",
  3766. -            (void *)a, (void *)b,
  3767. -            (long long)nfs41_fcb_a->fileid,
  3768. -            (long long)nfs41_fcb_a->fsid_major,
  3769. -            (long long)nfs41_fcb_a->fsid_minor);
  3770. -        return STATUS_MORE_PROCESSING_REQUIRED;
  3771. -    }
  3772. -    else {
  3773. -        DbgP("nfs41_AreFilesAliased: "
  3774. -            "a=0x%p b=0x%p NOT aliases, "
  3775. -            "a=(fileid=0x%llx fsid_major=0x%llx fsid_minor=0x%llx) "
  3776. -            "b=(fileid=0x%llx fsid_major=0x%llx fsid_minor=0x%llx)\n",
  3777. -            (void *)a, (void *)b,
  3778. -            (long long)nfs41_fcb_a->fileid,
  3779. -            (long long)nfs41_fcb_a->fsid_major,
  3780. -            (long long)nfs41_fcb_a->fsid_minor,
  3781. -            (long long)nfs41_fcb_b->fileid,
  3782. -            (long long)nfs41_fcb_b->fsid_major,
  3783. -            (long long)nfs41_fcb_b->fsid_minor);
  3784. -        return STATUS_SUCCESS;
  3785. -    }
  3786. -}
  3787. -
  3788.  static
  3789.  NTSTATUS nfs41_init_ops(void)
  3790.  {
  3791. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  3792. index a3a74c7..8459d3c 100644
  3793. --- a/sys/nfs41sys_driver.h
  3794. +++ b/sys/nfs41sys_driver.h
  3795. @@ -865,6 +865,11 @@ NTSTATUS marshal_nfs41_close(
  3796.  NTSTATUS unmarshal_nfs41_open(
  3797.      nfs41_updowncall_entry *cur,
  3798.      const unsigned char *restrict *restrict buf);
  3799. +NTSTATUS nfs41_AreFilesAliased(
  3800. +    PFCB a,
  3801. +    PFCB b);
  3802. +NTSTATUS nfs41_DeallocateForFobx(
  3803. +    IN OUT PMRX_FOBX pFobx);
  3804.  NTSTATUS nfs41_Create(
  3805.      IN OUT PRX_CONTEXT RxContext);
  3806.  NTSTATUS nfs41_CollapseOpen(
  3807. diff --git a/sys/nfs41sys_openclose.c b/sys/nfs41sys_openclose.c
  3808. index bde50a0..a14684c 100644
  3809. --- a/sys/nfs41sys_openclose.c
  3810. +++ b/sys/nfs41sys_openclose.c
  3811. @@ -347,6 +347,92 @@ out:
  3812.      return status;
  3813.  }
  3814.  
  3815. +NTSTATUS nfs41_AreFilesAliased(
  3816. +    PFCB a,
  3817. +    PFCB b)
  3818. +{
  3819. +    __notnull PNFS41_FCB nfs41_fcb_a = (PNFS41_FCB)a;
  3820. +    __notnull PNFS41_FCB nfs41_fcb_b = (PNFS41_FCB)b;
  3821. +
  3822. +    if ((nfs41_fcb_a->fileid == nfs41_fcb_b->fileid) &&
  3823. +        (nfs41_fcb_a->fsid_major == nfs41_fcb_b->fsid_major) &&
  3824. +        (nfs41_fcb_a->fsid_minor == nfs41_fcb_b->fsid_minor)) {
  3825. +
  3826. +        DbgP("nfs41_AreFilesAliased: "
  3827. +            "a=0x%p b=0x%p aliases, fileid=0x%llx "
  3828. +            "fsid_major=0x%llx fsid_minor=0x%llx\n",
  3829. +            (void *)a, (void *)b,
  3830. +            (long long)nfs41_fcb_a->fileid,
  3831. +            (long long)nfs41_fcb_a->fsid_major,
  3832. +            (long long)nfs41_fcb_a->fsid_minor);
  3833. +        return STATUS_MORE_PROCESSING_REQUIRED;
  3834. +    }
  3835. +    else {
  3836. +        DbgP("nfs41_AreFilesAliased: "
  3837. +            "a=0x%p b=0x%p NOT aliases, "
  3838. +            "a=(fileid=0x%llx fsid_major=0x%llx fsid_minor=0x%llx) "
  3839. +            "b=(fileid=0x%llx fsid_major=0x%llx fsid_minor=0x%llx)\n",
  3840. +            (void *)a, (void *)b,
  3841. +            (long long)nfs41_fcb_a->fileid,
  3842. +            (long long)nfs41_fcb_a->fsid_major,
  3843. +            (long long)nfs41_fcb_a->fsid_minor,
  3844. +            (long long)nfs41_fcb_b->fileid,
  3845. +            (long long)nfs41_fcb_b->fsid_major,
  3846. +            (long long)nfs41_fcb_b->fsid_minor);
  3847. +        return STATUS_SUCCESS;
  3848. +    }
  3849. +}
  3850. +
  3851. +static
  3852. +VOID nfs41_invalidate_fobx_entry(
  3853. +    IN OUT PMRX_FOBX pFobx)
  3854. +{
  3855. +    PLIST_ENTRY pEntry;
  3856. +    nfs41_fcb_list_entry *cur;
  3857. +    __notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(pFobx);
  3858. +
  3859. +    ExAcquireFastMutexUnsafe(&openlist.lock);
  3860. +
  3861. +    pEntry = openlist.head.Flink;
  3862. +    while (!IsListEmpty(&openlist.head)) {
  3863. +        cur = (nfs41_fcb_list_entry *)CONTAINING_RECORD(pEntry,
  3864. +                nfs41_fcb_list_entry, next);
  3865. +        if (cur->nfs41_fobx == nfs41_fobx) {
  3866. +#ifdef DEBUG_CLOSE
  3867. +            DbgP("nfs41_invalidate_fobx_entry: Found match for nfs41_fobx=0x%p\n",
  3868. +                nfs41_fobx);
  3869. +#endif
  3870. +            cur->nfs41_fobx = NULL;
  3871. +            break;
  3872. +        }
  3873. +        if (pEntry->Flink == &openlist.head) {
  3874. +#ifdef DEBUG_CLOSE
  3875. +            DbgP("nfs41_invalidate_fobx_entry: reached EOL looking "
  3876. +                "for nfs41_fobx=0x%p\n", nfs41_fobx);
  3877. +#endif
  3878. +            break;
  3879. +        }
  3880. +        pEntry = pEntry->Flink;
  3881. +    }
  3882. +    ExReleaseFastMutexUnsafe(&openlist.lock);
  3883. +}
  3884. +
  3885. +NTSTATUS nfs41_DeallocateForFobx(
  3886. +    IN OUT PMRX_FOBX pFobx)
  3887. +{
  3888. +    __notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(pFobx);
  3889. +
  3890. +    nfs41_invalidate_fobx_entry(pFobx);
  3891. +    nfs41_remove_offloadcontext_for_fobx(pFobx);
  3892. +
  3893. +    if (nfs41_fobx->sec_ctx.ClientToken) {
  3894. +        SeDeleteClientSecurity(&nfs41_fobx->sec_ctx);
  3895. +        nfs41_fobx->sec_ctx.ClientToken = NULL;
  3896. +    }
  3897. +
  3898. +    return STATUS_SUCCESS;
  3899. +}
  3900. +
  3901.  static BOOLEAN isDataAccess(
  3902.      ACCESS_MASK mask)
  3903.  {
  3904. --
  3905. 2.51.0
  3906.  
  3907. From c3432735bdb1ef54121e2256567d34c62d4b9cb0 Mon Sep 17 00:00:00 2001
  3908. From: Roland Mainz <roland.mainz@nrubsig.org>
  3909. Date: Mon, 1 Dec 2025 11:28:10 +0100
  3910. Subject: [PATCH 26/28] sys: Implement |MRxCleanupFobx()| dummy function
  3911.  
  3912. Implement |MRxCleanupFobx()| dummy function, document that...
  3913. 1. |MRxCleanupFobx()| is usually called before |MRxCloseSrvOpen()|
  3914. 2. |MRxDeallocateForFobx()| is usually called after |MRxCloseSrvOpen()|
  3915. ... and move |nfs41_DeallocateForFobx()| after |nfs41_CloseSrvOpen()|.
  3916.  
  3917. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  3918. ---
  3919. sys/nfs41sys_driver.c    |  4 ++++
  3920.  sys/nfs41sys_driver.h    |  3 +++
  3921.  sys/nfs41sys_openclose.c | 52 +++++++++++++++++++++++++++-------------
  3922.  3 files changed, 43 insertions(+), 16 deletions(-)
  3923.  
  3924. diff --git a/sys/nfs41sys_driver.c b/sys/nfs41sys_driver.c
  3925. index 69616c4..e043602 100644
  3926. --- a/sys/nfs41sys_driver.c
  3927. +++ b/sys/nfs41sys_driver.c
  3928. @@ -1210,6 +1210,8 @@ NTSTATUS nfs41_init_ops(void)
  3929.          (PMRX_EXTENDFILE_CALLDOWN)nfs41_ExtendForCache;
  3930.      nfs41_ops.MRxExtendForNonCache =
  3931.          (PMRX_EXTENDFILE_CALLDOWN)nfs41_ExtendForCache;
  3932. +    nfs41_ops.MRxCleanupFobx      =
  3933. +        (PMRX_CALLDOWN)nfs41_CleanupFobx;
  3934.      nfs41_ops.MRxCloseSrvOpen      =
  3935.          (PMRX_CALLDOWN)nfs41_CloseSrvOpen;
  3936.      nfs41_ops.MRxFlush             =
  3937. @@ -1218,6 +1220,8 @@ NTSTATUS nfs41_init_ops(void)
  3938.          (PMRX_DEALLOCATE_FOR_FCB)nfs41_DeallocateForFcb;
  3939.      nfs41_ops.MRxDeallocateForFobx =
  3940.          (PMRX_DEALLOCATE_FOR_FOBX)nfs41_DeallocateForFobx;
  3941. +
  3942. +
  3943.      nfs41_ops.MRxIsLockRealizable  =
  3944.          (PMRX_IS_LOCK_REALIZABLE)nfs41_IsLockRealizable;
  3945.  
  3946. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  3947. index 8459d3c..389e67f 100644
  3948. --- a/sys/nfs41sys_driver.h
  3949. +++ b/sys/nfs41sys_driver.h
  3950. @@ -870,6 +870,9 @@ NTSTATUS nfs41_AreFilesAliased(
  3951.      PFCB b);
  3952.  NTSTATUS nfs41_DeallocateForFobx(
  3953.      IN OUT PMRX_FOBX pFobx);
  3954. +NTSTATUS
  3955. +nfs41_CleanupFobx(
  3956. +    IN PRX_CONTEXT RxContext);
  3957.  NTSTATUS nfs41_Create(
  3958.      IN OUT PRX_CONTEXT RxContext);
  3959.  NTSTATUS nfs41_CollapseOpen(
  3960. diff --git a/sys/nfs41sys_openclose.c b/sys/nfs41sys_openclose.c
  3961. index a14684c..eb4465b 100644
  3962. --- a/sys/nfs41sys_openclose.c
  3963. +++ b/sys/nfs41sys_openclose.c
  3964. @@ -417,22 +417,6 @@ VOID nfs41_invalidate_fobx_entry(
  3965.      ExReleaseFastMutexUnsafe(&openlist.lock);
  3966.  }
  3967.  
  3968. -NTSTATUS nfs41_DeallocateForFobx(
  3969. -    IN OUT PMRX_FOBX pFobx)
  3970. -{
  3971. -    __notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(pFobx);
  3972. -
  3973. -    nfs41_invalidate_fobx_entry(pFobx);
  3974. -    nfs41_remove_offloadcontext_for_fobx(pFobx);
  3975. -
  3976. -    if (nfs41_fobx->sec_ctx.ClientToken) {
  3977. -        SeDeleteClientSecurity(&nfs41_fobx->sec_ctx);
  3978. -        nfs41_fobx->sec_ctx.ClientToken = NULL;
  3979. -    }
  3980. -
  3981. -    return STATUS_SUCCESS;
  3982. -}
  3983. -
  3984.  static BOOLEAN isDataAccess(
  3985.      ACCESS_MASK mask)
  3986.  {
  3987. @@ -1522,6 +1506,20 @@ NTSTATUS map_close_errors(
  3988.      }
  3989.  }
  3990.  
  3991. +/* |MRxCleanupFobx()| is usually called before |MRxCloseSrvOpen()| */
  3992. +NTSTATUS
  3993. +nfs41_CleanupFobx(
  3994. +    IN PRX_CONTEXT RxContext)
  3995. +{
  3996. +#ifdef DEBUG_CLOSE
  3997. +    DbgP("nfs41_CleanupFobx: FileName is '%wZ'\n",
  3998. +        &RxContext->CurrentIrpSp->FileObject->FileName);
  3999. +#endif /* DEBUG_CLOSE */
  4000. +
  4001. +    return STATUS_SUCCESS;
  4002. +}
  4003. +
  4004. +
  4005.  NTSTATUS nfs41_CloseSrvOpen(
  4006.      IN OUT PRX_CONTEXT RxContext)
  4007.  {
  4008. @@ -1599,3 +1597,25 @@ out:
  4009.  #endif
  4010.      return status;
  4011.  }
  4012. +
  4013. +/* |MRxDeallocateForFobx()| is usually called after |MRxCloseSrvOpen()| */
  4014. +NTSTATUS nfs41_DeallocateForFobx(
  4015. +    IN OUT PMRX_FOBX pFobx)
  4016. +{
  4017. +    __notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(pFobx);
  4018. +
  4019. +#ifdef DEBUG_CLOSE
  4020. +    DbgP("nfs41_DeallocateForFobx: FileName is '%wZ'\n",
  4021. +        pFobx->pSrvOpen->pAlreadyPrefixedName);
  4022. +#endif /* DEBUG_CLOSE */
  4023. +
  4024. +    nfs41_invalidate_fobx_entry(pFobx);
  4025. +    nfs41_remove_offloadcontext_for_fobx(pFobx);
  4026. +
  4027. +    if (nfs41_fobx->sec_ctx.ClientToken) {
  4028. +        SeDeleteClientSecurity(&nfs41_fobx->sec_ctx);
  4029. +        nfs41_fobx->sec_ctx.ClientToken = NULL;
  4030. +    }
  4031. +
  4032. +    return STATUS_SUCCESS;
  4033. +}
  4034. --
  4035. 2.51.0
  4036.  
  4037. From b598019c582d8b48b080d526b4415f861f60dce8 Mon Sep 17 00:00:00 2001
  4038. From: Roland Mainz <roland.mainz@nrubsig.org>
  4039. Date: Mon, 1 Dec 2025 12:06:36 +0100
  4040. Subject: [PATCH 27/28] sys: |nfs41_AreFilesAliased()| should use
  4041.  NFS41GetFcbExtension() to get the FCB extension
  4042.  
  4043. |nfs41_AreFilesAliased()| should use NFS41GetFcbExtension() to get the FCB extension.
  4044.  
  4045. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  4046. ---
  4047. sys/nfs41sys_openclose.c | 4 ++--
  4048.  1 file changed, 2 insertions(+), 2 deletions(-)
  4049.  
  4050. diff --git a/sys/nfs41sys_openclose.c b/sys/nfs41sys_openclose.c
  4051. index eb4465b..ce3aec2 100644
  4052. --- a/sys/nfs41sys_openclose.c
  4053. +++ b/sys/nfs41sys_openclose.c
  4054. @@ -351,8 +351,8 @@ NTSTATUS nfs41_AreFilesAliased(
  4055.      PFCB a,
  4056.      PFCB b)
  4057.  {
  4058. -    __notnull PNFS41_FCB nfs41_fcb_a = (PNFS41_FCB)a;
  4059. -    __notnull PNFS41_FCB nfs41_fcb_b = (PNFS41_FCB)b;
  4060. +    __notnull PNFS41_FCB nfs41_fcb_a = NFS41GetFcbExtension(a);
  4061. +    __notnull PNFS41_FCB nfs41_fcb_b = NFS41GetFcbExtension(b);
  4062.  
  4063.      if ((nfs41_fcb_a->fileid == nfs41_fcb_b->fileid) &&
  4064.          (nfs41_fcb_a->fsid_major == nfs41_fcb_b->fsid_major) &&
  4065. --
  4066. 2.51.0
  4067.  
  4068. From e9641566cc867aefdd0c7143b69909aff0b7b2f5 Mon Sep 17 00:00:00 2001
  4069. From: Roland Mainz <roland.mainz@nrubsig.org>
  4070. Date: Mon, 1 Dec 2025 13:00:25 +0100
  4071. Subject: [PATCH 28/28] sys: |offloadcontext_entry| should use a
  4072.  |PMRX_SRV_OPEN| instead of a |PMRX_FOBX|
  4073.  
  4074. |offloadcontext_entry| (used by |FSCTL_OFFLOAD_READ|+|FSCTL_OFFLOAD_WRITE|)
  4075. should use a |PMRX_SRV_OPEN| instead of a |PMRX_FOBX|.
  4076.  
  4077. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  4078. ---
  4079. sys/nfs41sys_driver.h    |  4 ++--
  4080.  sys/nfs41sys_fsctl.c     | 35 ++++++++++++-----------------------
  4081.  sys/nfs41sys_openclose.c |  5 ++++-
  4082.  3 files changed, 18 insertions(+), 26 deletions(-)
  4083.  
  4084. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  4085. index 389e67f..d6bd5ca 100644
  4086. --- a/sys/nfs41sys_driver.h
  4087. +++ b/sys/nfs41sys_driver.h
  4088. @@ -760,8 +760,8 @@ NTSTATUS marshal_nfs41_duplicatedata(
  4089.  NTSTATUS unmarshal_nfs41_duplicatedata(
  4090.      nfs41_updowncall_entry *cur,
  4091.      const unsigned char *restrict *restrict buf);
  4092. -void nfs41_remove_offloadcontext_for_fobx(
  4093. -    IN PMRX_FOBX pFobx);
  4094. +void nfs41_remove_offloadcontext_for_srvopen(
  4095. +    IN PMRX_SRV_OPEN pSrvopen);
  4096.  
  4097.  /* nfs41sys_ioctl.c */
  4098.  NTSTATUS nfs41_IoCtl(
  4099. diff --git a/sys/nfs41sys_fsctl.c b/sys/nfs41sys_fsctl.c
  4100. index f31b976..25c1290 100644
  4101. --- a/sys/nfs41sys_fsctl.c
  4102. +++ b/sys/nfs41sys_fsctl.c
  4103. @@ -755,7 +755,6 @@ NTSTATUS nfs41_DuplicateData(
  4104.      PFOBX srcfox = srcfo->FsContext2;
  4105.      PNFS41_FCB nfs41_src_fcb = NFS41GetFcbExtension(srcfcb);
  4106.      PNFS41_SRV_OPEN src_nfs41_srvopen = NFS41GetSrvOpenExtension(srcfox->SrvOpen);
  4107. -    PNFS41_FOBX nfs41_src_fobx = NFS41GetFobxExtension(srcfox);
  4108.  
  4109.      if (!nfs41_src_fcb) {
  4110.          DbgP("nfs41_DuplicateData: No nfs41_src_fcb\n");
  4111. @@ -763,12 +762,6 @@ NTSTATUS nfs41_DuplicateData(
  4112.          goto out;
  4113.      }
  4114.  
  4115. -    if (!nfs41_src_fobx) {
  4116. -        DbgP("nfs41_DuplicateData: No nfs41_src_fobx\n");
  4117. -        status = STATUS_INVALID_PARAMETER;
  4118. -        goto out;
  4119. -    }
  4120. -
  4121.      if (nfs41_src_fcb->StandardInfo.Directory) {
  4122.          DbgP("nfs41_DuplicateData: src is a dir\n");
  4123.          status = STATUS_FILE_IS_A_DIRECTORY;
  4124. @@ -953,14 +946,14 @@ typedef struct _offloadcontext_entry
  4125.       */
  4126.      ERESOURCE               resource;
  4127.      STORAGE_OFFLOAD_TOKEN   token;
  4128. -    PMRX_FOBX               src_fobx;
  4129. +    PMRX_SRV_OPEN           src_srvopen;
  4130.      ULONGLONG               src_fileoffset;
  4131.      ULONGLONG               src_length;
  4132.  } offloadcontext_entry;
  4133.  
  4134.  
  4135. -void nfs41_remove_offloadcontext_for_fobx(
  4136. -    IN PMRX_FOBX pFobx)
  4137. +void nfs41_remove_offloadcontext_for_srvopen(
  4138. +    IN PMRX_SRV_OPEN pSrvopen)
  4139.  {
  4140.      PLIST_ENTRY pEntry;
  4141.      offloadcontext_entry *cur, *found = NULL;
  4142. @@ -971,7 +964,7 @@ void nfs41_remove_offloadcontext_for_fobx(
  4143.      while (!IsListEmpty(&offloadcontextlist.head)) {
  4144.          cur = (offloadcontext_entry *)CONTAINING_RECORD(pEntry,
  4145.              offloadcontext_entry, next);
  4146. -        if (cur->src_fobx == pFobx) {
  4147. +        if (cur->src_srvopen == pSrvopen) {
  4148.              found = cur;
  4149.              break;
  4150.          }
  4151. @@ -982,9 +975,9 @@ void nfs41_remove_offloadcontext_for_fobx(
  4152.      }
  4153.  
  4154.      if (found) {
  4155. -        DbgP("nfs41_remove_offloadcontext(pFobx=0x%p): "
  4156. +        DbgP("nfs41_remove_offloadcontext_for_srvopen(pSrvopen=0x%p): "
  4157.              "removing found=0x%p\n",
  4158. -            pFobx,
  4159. +            pSrvopen,
  4160.              found);
  4161.  
  4162.          /* Wait for any shared access in |nfs41_OffloadWrite()| to finish */
  4163. @@ -998,8 +991,9 @@ void nfs41_remove_offloadcontext_for_fobx(
  4164.      }
  4165.      else {
  4166.  #ifdef DEBUG_FSCTL_OFFLOAD_READWRITE
  4167. -        DbgP("nfs41_remove_offloadcontext(pFobx=0x%p): Nothing found.\n",
  4168. -            pFobx);
  4169. +        DbgP("nfs41_remove_offloadcontext_for_srvopen(pSrvopen=0x%p): "
  4170. +            "Nothing found.\n",
  4171. +            pSrvopen);
  4172.  #endif /* DEBUG_FSCTL_OFFLOAD_READWRITE */
  4173.      }
  4174.  
  4175. @@ -1126,7 +1120,7 @@ NTSTATUS nfs41_OffloadRead(
  4176.      *((USHORT *)(&oce->token.TokenIdLength[0])) =
  4177.          STORAGE_OFFLOAD_TOKEN_ID_LENGTH;
  4178.      *((void **)(&oce->token.Token[0])) = oce;
  4179. -    oce->src_fobx = RxContext->pFobx;
  4180. +    oce->src_srvopen = RxContext->pRelevantSrvOpen;
  4181.      oce->src_fileoffset = ori->FileOffset;
  4182.      oce->src_length = ori->CopyLength;
  4183.  
  4184. @@ -1294,13 +1288,8 @@ NTSTATUS nfs41_OffloadWrite(
  4185.          goto out;
  4186.      }
  4187.  
  4188. -    PNFS41_FOBX nfs41_src_fobx = NFS41GetFobxExtension(src_oce->src_fobx);
  4189. -    if (!nfs41_src_fobx) {
  4190. -        DbgP("nfs41_OffloadWrite: No nfs41_src_fobx\n");
  4191. -        status = STATUS_INVALID_PARAMETER;
  4192. -        goto out;
  4193. -    }
  4194. -    PNFS41_SRV_OPEN src_nfs41_srvopen = NFS41GetSrvOpenExtension(((PFOBX)src_oce->src_fobx)->SrvOpen);
  4195. +    PNFS41_SRV_OPEN src_nfs41_srvopen =
  4196. +        NFS41GetSrvOpenExtension(src_oce->src_srvopen);
  4197.  
  4198.      /*
  4199.       * Disable caching because NFSv4.2 COPY is basically a
  4200. diff --git a/sys/nfs41sys_openclose.c b/sys/nfs41sys_openclose.c
  4201. index ce3aec2..5d4c16c 100644
  4202. --- a/sys/nfs41sys_openclose.c
  4203. +++ b/sys/nfs41sys_openclose.c
  4204. @@ -1578,6 +1578,10 @@ NTSTATUS nfs41_CloseSrvOpen(
  4205.  
  4206.      /* map windows ERRORs to NTSTATUS */
  4207.      status = map_close_errors(entry->status);
  4208. +
  4209. +    if (NT_SUCCESS(status)) {
  4210. +        nfs41_remove_offloadcontext_for_srvopen(SrvOpen);
  4211. +    }
  4212.  out:
  4213.      if (entry) {
  4214.          nfs41_UpcallDestroy(entry);
  4215. @@ -1610,7 +1614,6 @@ NTSTATUS nfs41_DeallocateForFobx(
  4216.  #endif /* DEBUG_CLOSE */
  4217.  
  4218.      nfs41_invalidate_fobx_entry(pFobx);
  4219. -    nfs41_remove_offloadcontext_for_fobx(pFobx);
  4220.  
  4221.      if (nfs41_fobx->sec_ctx.ClientToken) {
  4222.          SeDeleteClientSecurity(&nfs41_fobx->sec_ctx);
  4223. --
  4224. 2.51.0

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