pastebin - collaborative debugging tool
nrubsig.kpaste.net RSS


make replaced srvopen as stale fix
Posted by Anonymous on Wed 18th Feb 2026 19:34
raw | new post

  1. diff --git a/daemon/setattr.c b/daemon/setattr.c
  2. index 3c01a47..164c789 100644
  3. --- a/daemon/setattr.c
  4. +++ b/daemon/setattr.c
  5. @@ -349,6 +349,9 @@ static int handle_nfs41_rename(void *daemon_context, setattr_upcall_args *args)
  6.  #endif /* NFS41_REJECT_CYGWIN_SILLYRENAME_FOR_DIRS */
  7.      int status;
  8.  
  9. +#ifdef NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE
  10. +    args->rename_stale_dst_path_replaced = FALSE;
  11. +#endif /* NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE */
  12.      src_name = &state->file.name;
  13.  
  14.      if (rename->FileNameLength == 0) {
  15. @@ -720,10 +723,24 @@ static int handle_nfs41_rename(void *daemon_context, setattr_upcall_args *args)
  16.          DPRINTF(1, ("nfs41_rename() failed with error '%s'.\n",
  17.              nfs_error_string(status)));
  18.          status = nfs_to_windows_error(status, ERROR_ACCESS_DENIED);
  19. -    } else {
  20. -        /* rename state->path on success */
  21. -        open_state_rename(state, &dst_path);
  22. +        goto out;
  23. +    }
  24. +
  25. +#ifdef NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE
  26. +    if (rename->ReplaceIfExists) {
  27. +        /*
  28. +         * Send the (processed) destination path back to the kernel so it can
  29. +         * be marked there as "stale". Otherwise we can do a SRVOPEN collapsing
  30. +         * for a SRVOPEN which has been replaced
  31. +         */
  32. +        abs_path_copy(&args->rename_stale_dst_path, &dst_path);
  33. +        args->rename_stale_dst_path_replaced = TRUE;
  34.      }
  35. +#endif /* NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE */
  36. +
  37. +    /* rename state->path on success */
  38. +    open_state_rename(state, &dst_path);
  39. +
  40.  out:
  41.      return status;
  42.  }
  43. @@ -1080,8 +1097,30 @@ static int marshall_setattr(
  44.      uint32_t *restrict length,
  45.      nfs41_upcall *restrict upcall)
  46.  {
  47. +    int status;
  48.      const setattr_upcall_args *args = &upcall->args.setattr;
  49. -    return safe_write(&buffer, length, &args->ctime, sizeof(args->ctime));
  50. +    status = safe_write(&buffer, length, &args->ctime, sizeof(args->ctime));
  51. +    if (status) goto out;
  52. +
  53. +#ifdef NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE
  54. +    if (args->set_class == FileRenameInformation) {
  55. +        status = safe_write(&buffer, length,
  56. +            &args->rename_stale_dst_path_replaced,
  57. +            sizeof(args->rename_stale_dst_path_replaced));
  58. +        if (status) goto out;
  59. +        if (args->rename_stale_dst_path_replaced) {
  60. +            USHORT dst_path_len = args->rename_stale_dst_path.len;
  61. +            status = safe_write(&buffer, length, &dst_path_len, sizeof(dst_path_len));
  62. +            if (status) goto out;
  63. +            status = safe_write(&buffer, length,
  64. +                &args->rename_stale_dst_path.path[0], dst_path_len);
  65. +            if (status) goto out;
  66. +        }
  67. +    }
  68. +#endif /* NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE */
  69. +
  70. +out:
  71. +    return status;
  72.  }
  73.  
  74.  
  75. diff --git a/daemon/upcall.h b/daemon/upcall.h
  76. index 01a84ed..a9f3dfe 100644
  77. --- a/daemon/upcall.h
  78. +++ b/daemon/upcall.h
  79. @@ -140,6 +140,11 @@ typedef struct __setattr_upcall_args {
  80.      uint32_t buf_len;
  81.      int set_class;
  82.      ULONGLONG ctime;
  83. +    /* Downcall info */
  84. +#ifdef NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE
  85. +    BOOLEAN rename_stale_dst_path_replaced;
  86. +    nfs41_abs_path rename_stale_dst_path;
  87. +#endif /* NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE */
  88.  } setattr_upcall_args;
  89.  
  90.  typedef struct __getexattr_upcall_args {
  91. diff --git a/nfs41_build_features.h b/nfs41_build_features.h
  92. index 63a0a2d..53f65ee 100644
  93. --- a/nfs41_build_features.h
  94. +++ b/nfs41_build_features.h
  95. @@ -384,4 +384,18 @@
  96.   */
  97.  #define NFS41_DRIVER_COLLAPSEOPEN 1
  98.  
  99. +/*
  100. + * |NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE| - mark
  101. + * the destination path of a |FileRenameInformation| as "stale" if we
  102. + * replace that file/dir.
  103. + * Otherwise we can use the old SRVOPEN (of the file/dir which was already
  104. + * relaced) for SRVOPEN collapsing, which breaks native Windows git (e.g.
  105. + * try git version "2.51.1.windows.1" like this
  106. + * $ '/cygdrive/c/Program Files/Git/cmd/git' clone \
  107. + *      https://github.com/kofemann/ms-nfs41-client.git # will fail with
  108. + * "warning: remote HEAD refers to nonexistent ref, unable to checkout"
  109. + * because we use the old NFS handle for ".git/HEAD".
  110. + */
  111. +#define NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE 1
  112. +
  113.  #endif /* !_NFS41_DRIVER_BUILDFEATURES_ */
  114. diff --git a/sys/nfs41sys_driver.c b/sys/nfs41sys_driver.c
  115. index 091e61a..e62d007 100644
  116. --- a/sys/nfs41sys_driver.c
  117. +++ b/sys/nfs41sys_driver.c
  118. @@ -998,7 +998,6 @@ NTSTATUS nfs41_ComputeNewBufferingState(
  119.  #ifdef DEBUG_TIME_BASED_COHERENCY
  120.      ULONG oldFlags = pSrvOpen->BufferingFlags;
  121.  #endif
  122. -
  123.      switch(flag) {
  124.      case DISABLE_CACHING:
  125.          if (pSrvOpen->BufferingFlags &
  126. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  127. index 441d8f7..8c303ab 100644
  128. --- a/sys/nfs41sys_driver.h
  129. +++ b/sys/nfs41sys_driver.h
  130. @@ -276,6 +276,13 @@ typedef struct _updowncall_entry {
  131.              FILE_INFORMATION_CLASS InfoClass;
  132.              PVOID buf;
  133.              ULONG buf_len;
  134. +#ifdef NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE
  135. +            struct {
  136. +                BOOLEAN path_replaced;
  137. +                USHORT path_len;
  138. +                const unsigned char *path_buf;
  139. +            } rename_stale_dst;
  140. +#endif /* NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE */
  141.          } SetFile;
  142.          struct {
  143.              DWORD mode;
  144. @@ -507,6 +514,10 @@ typedef struct _NFS41_FCB {
  145.  
  146.  typedef struct _NFS41_SRV_OPEN {
  147.      BOOLEAN         initialised;
  148. +#ifdef NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE
  149. +    BOOLEAN                 stale;
  150. +#endif /* NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE */
  151. +
  152.      /*
  153.       * |sec_ctx| must be per |SRV_OPEN| to handle newgrp()/|setgid()|
  154.       * support. But this only works if we prevent |SRV_OPEN| collapsing
  155. @@ -945,6 +956,10 @@ void unmarshal_nfs41_attrget(
  156.      ULONG *attr_len,
  157.      const unsigned char *restrict *restrict buf,
  158.      BOOL copy_partial);
  159. +void unmarshal_nfs41_getchangetime(
  160. +    nfs41_updowncall_entry *cur,
  161. +    PULONGLONG dest_buf,
  162. +    const unsigned char *restrict *restrict buf);
  163.  NTSTATUS nfs41_UpcallCreate(
  164.      IN nfs41_opcodes opcode,
  165.      IN PSECURITY_CLIENT_CONTEXT clnt_sec_ctx,
  166. @@ -977,7 +992,6 @@ NTSTATUS marshal_nfs41_fileset(
  167.      ULONG *len);
  168.  void unmarshal_nfs41_setattr(
  169.      nfs41_updowncall_entry *cur,
  170. -    PULONGLONG dest_buf,
  171.      const unsigned char *restrict *restrict buf);
  172.  void unmarshal_nfs41_getattr(
  173.      nfs41_updowncall_entry *cur,
  174. diff --git a/sys/nfs41sys_fileinfo.c b/sys/nfs41sys_fileinfo.c
  175. index b7ef8ec..3f75f5f 100644
  176. --- a/sys/nfs41sys_fileinfo.c
  177. +++ b/sys/nfs41sys_fileinfo.c
  178. @@ -160,8 +160,14 @@ NTSTATUS marshal_nfs41_fileset(
  179.          }
  180.  #endif /* NFS41_DRIVER_STOMP_CYGWIN_SILLYRENAME_INVALID_UTF16_SEQUENCE_SUPPORT */
  181.  
  182. +        /*
  183. +         * We use %lu here for |ReplaceIfExists| because of
  184. +         * |FileRenameInformationEx| uses a ULONG flags field
  185. +         */
  186.          DbgP("marshal_nfs41_fileset: "
  187. -            "FILE_RENAME_INFORMATION.(FileNameLength=%d FileName='%.*ls')\n",
  188. +            "FILE_RENAME_INFORMATION."
  189. +            "(ReplaceIfExists=%lu FileNameLength=%d FileName='%.*ls')\n",
  190. +            (unsigned long)fri->ReplaceIfExists,
  191.              (int)fri->FileNameLength,
  192.              (int)(fri->FileNameLength/sizeof(wchar_t)), fri->FileName);
  193.      }
  194. @@ -207,14 +213,27 @@ out:
  195.  
  196.  void unmarshal_nfs41_setattr(
  197.      nfs41_updowncall_entry *cur,
  198. -    PULONGLONG dest_buf,
  199.      const unsigned char *restrict *restrict buf)
  200.  {
  201. -    RtlCopyMemory(dest_buf, *buf, sizeof(*dest_buf));
  202. -    *buf += sizeof(*dest_buf);
  203. -#ifdef DEBUG_MARSHAL_DETAIL
  204. -    DbgP("unmarshal_nfs41_setattr: returned ChangeTime %llu\n", *dest_buf);
  205. -#endif
  206. +    RtlCopyMemory(&cur->ChangeTime, *buf, sizeof(cur->ChangeTime));
  207. +    *buf += sizeof(cur->ChangeTime);
  208. +
  209. +#ifdef NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE
  210. +    if (cur->u.SetFile.InfoClass == FileRenameInformation) {
  211. +        RtlCopyMemory(&cur->u.SetFile.rename_stale_dst.path_replaced,
  212. +            *buf, sizeof(cur->u.SetFile.rename_stale_dst.path_replaced));
  213. +        *buf += sizeof(cur->u.SetFile.rename_stale_dst.path_replaced);
  214. +
  215. +        if (cur->u.SetFile.rename_stale_dst.path_replaced) {
  216. +            RtlCopyMemory(&cur->u.SetFile.rename_stale_dst.path_len,
  217. +                *buf, sizeof(cur->u.SetFile.rename_stale_dst.path_len));
  218. +            *buf += sizeof(cur->u.SetFile.rename_stale_dst.path_len);
  219. +
  220. +            cur->u.SetFile.rename_stale_dst.path_buf = *buf;
  221. +            *buf += cur->u.SetFile.rename_stale_dst.path_len;
  222. +        }
  223. +    }
  224. +#endif /* NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE */
  225.  }
  226.  
  227.  void unmarshal_nfs41_getattr(
  228. @@ -737,6 +756,58 @@ out:
  229.      return status;
  230.  }
  231.  
  232. +#ifdef NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE
  233. +VOID nfs41_mark_file_as_non_collapsible(
  234. +    PNET_ROOT netroot,
  235. +    PUNICODE_STRING nonc_filename)
  236. +{
  237. +    PFCB fcb;
  238. +    PNFS41_SRV_OPEN nfs41_srvopen;
  239. +
  240. +    DbgP("nfs41_mark_file_as_non_collapsible: "
  241. +        "argument filename='%wZ'\n",
  242. +        nonc_filename);
  243. +
  244. +    RxAcquireFcbTableLockExclusive(&netroot->FcbTable, TRUE);
  245. +
  246. +    fcb = RxFcbTableLookupFcb(&netroot->FcbTable, nonc_filename);
  247. +
  248. +    RxReleaseFcbTableLock(&netroot->FcbTable);
  249. +
  250. +    if (fcb) {
  251. +        PLIST_ENTRY pSrvOpenListEntry;
  252. +        PSRV_OPEN srv_open;
  253. +
  254. +        pSrvOpenListEntry = fcb->SrvOpenList.Flink;
  255. +
  256. +        for (;;) {
  257. +            if (pSrvOpenListEntry == &fcb->SrvOpenList) {
  258. +                break;
  259. +            }
  260. +
  261. +            srv_open = (PSRV_OPEN)
  262. +                CONTAINING_RECORD(pSrvOpenListEntry, SRV_OPEN, SrvOpenQLinks);
  263. +            nfs41_srvopen = NFS41GetSrvOpenExtension(srv_open);
  264. +
  265. +            DbgP("nfs41_mark_file_as_non_collapsible: "
  266. +                "marking filename='%wZ'/fcb=0x%p/srv_open=0x%p as stale\n",
  267. +                nonc_filename, (void *)fcb, (void *)srv_open);
  268. +
  269. +            nfs41_srvopen->stale = TRUE;
  270. +
  271. +            pSrvOpenListEntry = pSrvOpenListEntry->Flink;
  272. +        }
  273. +
  274. +        RxpDereferenceNetFcb(fcb);
  275. +    }
  276. +    else {
  277. +        DbgP("nfs41_mark_file_as_non_collapsible: "
  278. +            "nothing found for filename='%wZ'\n",
  279. +            nonc_filename);
  280. +    }
  281. +}
  282. +#endif /* NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE */
  283. +
  284.  static
  285.  NTSTATUS nfs41_SetFileInformationImpl(
  286.      IN OUT PRX_CONTEXT RxContext,
  287. @@ -902,6 +973,49 @@ NTSTATUS nfs41_SetFileInformationImpl(
  288.                  (FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)))
  289.              nfs41_update_fcb_list(RxContext->pFcb, entry->ChangeTime);
  290.          nfs41_fcb->changeattr = entry->ChangeTime;
  291. +
  292. +#ifdef NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE
  293. +        if (RxContext->Info.FileInformationClass == FileRenameInformation) {
  294. +            DbgP("nfs41_SetFileInformationImpl: "
  295. +                "finishig FileRenameInformation for filename='%wZ', "
  296. +                "rename_stale_dst.path_replaced=%d\n",
  297. +                entry->filename,
  298. +                (int)entry->u.SetFile.rename_stale_dst.path_replaced);
  299. +
  300. +            if (entry->u.SetFile.rename_stale_dst.path_replaced) {
  301. +                DbgP("nfs41_SetFileInformationImpl: "
  302. +                    "rename_stale_dst.path_len=%d inbuf='%.*s'\n",
  303. +                    (int)entry->u.SetFile.rename_stale_dst.path_len,
  304. +                    (int)entry->u.SetFile.rename_stale_dst.path_len,
  305. +                    entry->u.SetFile.rename_stale_dst.path_buf);
  306. +                UTF8_STRING stale_utf8filename = {
  307. +                    .Length = (USHORT)
  308. +                        entry->u.SetFile.rename_stale_dst.path_len,
  309. +                    .MaximumLength = (USHORT)
  310. +                        entry->u.SetFile.rename_stale_dst.path_len,
  311. +                    .Buffer = (PCHAR)
  312. +                        entry->u.SetFile.rename_stale_dst.path_buf
  313. +                };
  314. +
  315. +                UNICODE_STRING stale_filename;
  316. +
  317. +                status = RtlUTF8StringToUnicodeString(&stale_filename,
  318. +                    &stale_utf8filename, TRUE);
  319. +                if (NT_SUCCESS(status)) {
  320. +                    DbgP("nfs41_SetFileInformationImpl/stale: "
  321. +                        "stale_filename='%wZ'\n",
  322. +                        &stale_filename);
  323. +
  324. +                    nfs41_mark_file_as_non_collapsible(
  325. +                        (PNET_ROOT)SrvOpen->pVNetRoot->pNetRoot,
  326. +                        &stale_filename);
  327. +
  328. +                    RtlFreeUnicodeString(&stale_filename);
  329. +                    status = STATUS_SUCCESS;
  330. +                }
  331. +            }
  332. +        }
  333. +#endif /* NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE */
  334.      }
  335.  out:
  336.      if (entry) {
  337. diff --git a/sys/nfs41sys_openclose.c b/sys/nfs41sys_openclose.c
  338. index eaf04f0..af546c8 100644
  339. --- a/sys/nfs41sys_openclose.c
  340. +++ b/sys/nfs41sys_openclose.c
  341. @@ -1385,6 +1385,16 @@ NTSTATUS nfs41_ShouldTryToCollapseThisOpen(
  342.          goto out;
  343.      }
  344.  
  345. +#ifdef NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE
  346. +    if (nfs41_srvopen->stale) {
  347. +        DbgP("nfs41_ShouldTryToCollapseThisOpen: "
  348. +            "filename='%wZ' nfs41_srvopen->stale set, cannot collapse\n",
  349. +            SrvOpen->pAlreadyPrefixedName);
  350. +        status = STATUS_MORE_PROCESSING_REQUIRED;
  351. +        goto out;
  352. +    }
  353. +#endif /* NFS41_DRIVER_MARK_OVERWRITTEN_RENAME_DST_PATH_SRVOPEN_AS_STALE */
  354. +
  355.  #ifdef WINBUG_NO_COLLAPSE_IF_PRIMARYGROUPS_DIFFER
  356.      /*
  357.       * Reject srvopens if the primary group used to create
  358. diff --git a/sys/nfs41sys_updowncall.c b/sys/nfs41sys_updowncall.c
  359. index 15f948c..dedfa4e 100644
  360. --- a/sys/nfs41sys_updowncall.c
  361. +++ b/sys/nfs41sys_updowncall.c
  362. @@ -193,6 +193,19 @@ void unmarshal_nfs41_attrget(
  363.      *buf += buf_len;
  364.  }
  365.  
  366. +void unmarshal_nfs41_getchangetime(
  367. +    nfs41_updowncall_entry *cur,
  368. +    PULONGLONG dest_buf,
  369. +    const unsigned char *restrict *restrict buf)
  370. +{
  371. +    RtlCopyMemory(dest_buf, *buf, sizeof(*dest_buf));
  372. +    *buf += sizeof(*dest_buf);
  373. +#ifdef DEBUG_MARSHAL_DETAIL
  374. +    DbgP("unmarshal_nfs41_getchangetime: "
  375. +        "returned ChangeTime %llu\n", *dest_buf);
  376. +#endif
  377. +}
  378. +
  379.  NTSTATUS handle_upcall(
  380.      IN PRX_CONTEXT RxContext,
  381.      IN nfs41_updowncall_entry *entry,
  382. @@ -773,13 +786,13 @@ NTSTATUS nfs41_downcall(
  383.              break;
  384.          case NFS41_SYSOP_FILE_SET:
  385.          case NFS41_SYSOP_FILE_SET_AT_CLEANUP:
  386. -            unmarshal_nfs41_setattr(cur, &cur->ChangeTime, &inbuf);
  387. +            unmarshal_nfs41_setattr(cur, &inbuf);
  388.              break;
  389.          case NFS41_SYSOP_EA_SET:
  390. -            unmarshal_nfs41_setattr(cur, &cur->ChangeTime, &inbuf);
  391. +            unmarshal_nfs41_getchangetime(cur, &cur->ChangeTime, &inbuf);
  392.              break;
  393.          case NFS41_SYSOP_ACL_SET:
  394. -            unmarshal_nfs41_setattr(cur, &cur->ChangeTime, &inbuf);
  395. +            unmarshal_nfs41_getchangetime(cur, &cur->ChangeTime, &inbuf);
  396.              break;
  397.          case NFS41_SYSOP_FSCTL_QUERYALLOCATEDRANGES:
  398.              unmarshal_nfs41_queryallocatedranges(cur, &inbuf);

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