pastebin - collaborative debugging tool
rovema.kpaste.net RSS


msnfs41client: Patches for clone tests+docs, 2025-05-06
Posted by Anonymous on Tue 6th May 2025 17:32
raw | new post

  1. From e946c4be6e09dd7697e2c9ca0acb0c9f1cb3160b Mon Sep 17 00:00:00 2001
  2. From: Roland Mainz <roland.mainz@nrubsig.org>
  3. Date: Tue, 6 May 2025 17:41:27 +0200
  4. Subject: [PATCH 1/2] tests: winclonefile: Add --clonechunksize option to test
  5.  NFS CLONE offsets
  6.  
  7. winclonefile: Add --clonechunksize option to test NFSv4.2 CLONE
  8. offsets.
  9.  
  10. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  11. ---
  12. tests/sparsefiles/multisparsefiletest.ksh |  39 ++++-
  13.  tests/winclonefile/winclonefile.c         | 199 +++++++++++++++-------
  14.  2 files changed, 168 insertions(+), 70 deletions(-)
  15.  
  16. diff --git a/tests/sparsefiles/multisparsefiletest.ksh b/tests/sparsefiles/multisparsefiletest.ksh
  17. index b2e7bd5..3994c1f 100644
  18. --- a/tests/sparsefiles/multisparsefiletest.ksh
  19. +++ b/tests/sparsefiles/multisparsefiletest.ksh
  20. @@ -186,7 +186,8 @@ function multisparsefiletest1
  21.          rm -f \
  22.              'sparsefile2.bin' \
  23.              'sparsefile2_cpsparse.bin' \
  24. -            'sparsefile2_cloned.bin'
  25. +            'sparsefile2_cloned_full.bin' \
  26. +            'sparsefile2_cloned_1mbchunks.bin'
  27.          c.testlabel=''
  28.  
  29.          if (( c.i == 0 )) ; then
  30. @@ -220,7 +221,14 @@ function multisparsefiletest1
  31.  
  32.          typeset tstmod
  33.  
  34. -        for tstmod in 'plainfile' 'cp_sparseauto' 'cloned' ; do
  35. +        typeset -a tstmodlist=(
  36. +            'plainfile'
  37. +            'cp_sparseauto'
  38. +            'cloned_full'
  39. +            'cloned_1mbchunks'
  40. +        )
  41. +
  42. +        for tstmod in "${tstmodlist[@]}" ; do
  43.              printf '# Test %d '%s' generated\n' c.i "${c.testlabel}/$tstmod"
  44.  
  45.              case "${tstmod}" in
  46. @@ -231,10 +239,23 @@ function multisparsefiletest1
  47.                      /usr/bin/cp --sparse='auto' 'sparsefile2.bin' 'sparsefile2_cpsparse.bin'
  48.                      c.stdout="$(lssparse -H 'sparsefile2_cpsparse.bin')"
  49.                      ;;
  50. -                'cloned')
  51. +                'cloned_full')
  52. +                    if $test_cloning ; then
  53. +                        winclonefile.exe 'sparsefile2.bin' 'sparsefile2_cloned_full.bin' 1>'/dev/null'
  54. +                        c.stdout="$(lssparse -H 'sparsefile2_cloned_full.bin')"
  55. +                    else
  56. +                        printf "# Test '%s' SKIPPED\n" "${c.testlabel}/${tstmod}"
  57. +                        (( tests_skipped++ ))
  58. +                        continue
  59. +                    fi
  60. +                    ;;
  61. +                'cloned_1mbchunks')
  62.                      if $test_cloning ; then
  63. -                        winclonefile.exe 'sparsefile2.bin' 'sparsefile2_cloned.bin' 1>'/dev/null'
  64. -                        c.stdout="$(lssparse -H 'sparsefile2_cloned.bin')"
  65. +                        winclonefile.exe \
  66. +                            --clonechunksize $((1024*1024)) \
  67. +                            'sparsefile2.bin' \
  68. +                            'sparsefile2_cloned_1mbchunks.bin' 1>'/dev/null'
  69. +                        c.stdout="$(lssparse -H 'sparsefile2_cloned_1mbchunks.bin')"
  70.                      else
  71.                          printf "# Test '%s' SKIPPED\n" "${c.testlabel}/${tstmod}"
  72.                          (( tests_skipped++ ))
  73. @@ -242,7 +263,7 @@ function multisparsefiletest1
  74.                      fi
  75.                      ;;
  76.                  *)
  77. -                    printf -u2 "Unknown test mod"
  78. +                    print -u2 -f 'Unknown test mod\n'
  79.                      ;;
  80.              esac
  81.  
  82. @@ -269,6 +290,11 @@ function multisparsefiletest1
  83.      return 0
  84.  }
  85.  
  86. +
  87. +#
  88. +# main
  89. +#
  90. +builtin rm
  91.  builtin wc
  92.  
  93.  #
  94. @@ -276,6 +302,7 @@ builtin wc
  95.  # - Test whether filesystem supports block cloning and
  96.  # winclonefile.exe is available
  97.  # - variable block size
  98. +# - verify file sizes (original vs copy/clone)
  99.  # - tests for sparse files >= 2GB, 4GB, 16GB
  100.  #
  101.  typeset test_cloning=false
  102. diff --git a/tests/winclonefile/winclonefile.c b/tests/winclonefile/winclonefile.c
  103. index 7d2d490..39b019b 100644
  104. --- a/tests/winclonefile/winclonefile.c
  105. +++ b/tests/winclonefile/winclonefile.c
  106. @@ -39,10 +39,9 @@
  107.  
  108.  #if 1
  109.  /*
  110. - * MinGW include do not define |DUPLICATE_EXTENTS_DATA| yet,
  111. - * see https://github.com/mingw-w64/mingw-w64/issues/90
  112. - * ("[mingw-w64/mingw-w64] No |DUPLICATE_EXTENTS_DATA|/
  113. - * |DUPLICATE_EXTENTS_DATA_EX| in MinGW includes")
  114. + * MinGW include do not define |DUPLICATE_EXTENTS_DATA| yet, see
  115. + * https://github.com/mingw-w64/mingw-w64/issues/90 ("[mingw-w64/mingw-w64]
  116. + * No |DUPLICATE_EXTENTS_DATA|/ |DUPLICATE_EXTENTS_DATA_EX| in MinGW includes")
  117.   */
  118.  typedef struct _DUPLICATE_EXTENTS_DATA {
  119.      HANDLE FileHandle;
  120. @@ -77,6 +76,66 @@ PrintWin32Error(const char *functionName, DWORD lasterrCode)
  121.      LocalFree(lpMsgBuf);
  122.  }
  123.  
  124. +static
  125. +LONGLONG getFsClusterSize(HANDLE h)
  126. +{
  127. +    BOOL bResult;
  128. +    FILE_STORAGE_INFO fsi = { 0 };
  129. +    bResult = GetFileInformationByHandleEx(h,
  130. +        FileStorageInfo, &fsi, sizeof(fsi));
  131. +    if (!bResult)
  132. +        return -1LL;
  133. +
  134. +    return fsi.PhysicalBytesPerSectorForAtomicity;
  135. +}
  136. +
  137. +static
  138. +BOOL fsctlduplicateextentstofile(HANDLE hSrc, HANDLE hDst,
  139. +    LONGLONG srcOffset, LONGLONG dstOffset, ULONG byteCount)
  140. +{
  141. +    BOOL bResult;
  142. +    DUPLICATE_EXTENTS_DATA ded = {
  143. +        .FileHandle = hSrc,
  144. +        .SourceFileOffset.QuadPart = srcOffset,
  145. +        .TargetFileOffset.QuadPart = dstOffset,
  146. +        .ByteCount.QuadPart = byteCount
  147. +    };
  148. +    DWORD bytesReturnedDummy = 0; /* dummy var */
  149. +
  150. +    bResult = DeviceIoControl(
  151. +        hDst,
  152. +        FSCTL_DUPLICATE_EXTENTS_TO_FILE,
  153. +        &ded,
  154. +        sizeof(ded),
  155. +        NULL,
  156. +        0,
  157. +        &bytesReturnedDummy,
  158. +        NULL);
  159. +
  160. +    return bResult;
  161. +}
  162. +
  163. +static
  164. +LONGLONG getFileSize(HANDLE h)
  165. +{
  166. +    BOOL bResult;
  167. +    LARGE_INTEGER fileSize = { .QuadPart = 0LL };
  168. +    bResult = GetFileSizeEx(h, &fileSize);
  169. +    if (!bResult)
  170. +        return -1LL;
  171. +
  172. +    return fileSize.QuadPart;
  173. +}
  174. +
  175. +
  176. +static
  177. +void print_usage(const char *av0)
  178. +{
  179. +    (void)fprintf(stderr,
  180. +        "Usage: %s [--clonechunksize <numbytes>] <infile> <outfile>\n",
  181. +        av0);
  182. +}
  183. +
  184.  int
  185.  main(int ac, char *av[])
  186.  {
  187. @@ -85,27 +144,42 @@ main(int ac, char *av[])
  188.      HANDLE hSrc = INVALID_HANDLE_VALUE;
  189.      HANDLE hDst = INVALID_HANDLE_VALUE;
  190.      BOOL bResult = FALSE;
  191. -    LARGE_INTEGER fileSize = { .QuadPart = 0LL };
  192. -    DUPLICATE_EXTENTS_DATA ded = {
  193. -        .FileHandle = INVALID_HANDLE_VALUE,
  194. -        .SourceFileOffset.QuadPart = 0LL,
  195. -        .TargetFileOffset.QuadPart = 0LL,
  196. -        .ByteCount.QuadPart = 0LL
  197. -    };
  198. -    DWORD bytesReturnedDummy = 0; /* dummy var */
  199. +    LONGLONG fileSize;
  200. +    LONGLONG maxCloneChunkSize =
  201. +        1024LL*1024LL*1024LL*1024LL*1024LL; /* 1PB */
  202.  
  203. -    if (ac != 3) {
  204. -        (void)fprintf(stderr, "Usage: %s <infile> <outfile>\n", av[0]);
  205. -        return (EXIT_USAGE);
  206. +    if (ac == 3) {
  207. +        srcFileName = av[1];
  208. +        dstFileName = av[2];
  209.      }
  210. +    else if (ac == 5) {
  211. +        if (strcmp(av[1], "--clonechunksize") != 0) {
  212. +            print_usage(av[0]);
  213. +            return (EXIT_USAGE);
  214. +        }
  215.  
  216. -    srcFileName = av[1];
  217. -    dstFileName = av[2];
  218. +        maxCloneChunkSize = atoll(av[2]);
  219. +        srcFileName = av[3];
  220. +        dstFileName = av[4];
  221. +    }
  222. +    else {
  223. +        print_usage(av[0]);
  224. +        return (EXIT_USAGE);
  225. +    }
  226.  
  227. -    (void)printf("# Attempting to clone existing file '%s' to '%s' "
  228. -        "using FSCTL_DUPLICATE_EXTENTS_TO_FILE...\n",
  229. -        srcFileName,
  230. -        dstFileName);
  231. +    if (ac == 3) {
  232. +        (void)printf("# Attempting to clone existing file '%s' to '%s' using "
  233. +            "FSCTL_DUPLICATE_EXTENTS_TO_FILE...\n",
  234. +            srcFileName,
  235. +            dstFileName);
  236. +    }
  237. +    else if (ac == 5) {
  238. +        (void)printf("# Attempting to clone existing file '%s' to '%s' in "
  239. +            "%lld byte chunks using FSCTL_DUPLICATE_EXTENTS_TO_FILE...\n",
  240. +            srcFileName,
  241. +            dstFileName,
  242. +            maxCloneChunkSize);
  243. +    }
  244.  
  245.      hSrc = CreateFileA(
  246.          srcFileName,
  247. @@ -124,36 +198,31 @@ main(int ac, char *av[])
  248.      (void)printf("# Successfully opened existing source file '%s'.\n",
  249.          srcFileName);
  250.  
  251. -    bResult = GetFileSizeEx(hSrc, &fileSize);
  252. -    if (!bResult) {
  253. +    fileSize = getFileSize(hSrc);
  254. +    if (fileSize < 0LL) {
  255.          PrintWin32Error("GetFileSizeEx",
  256.              GetLastError());
  257.          goto cleanup;
  258.      }
  259.  
  260. -    if (fileSize.QuadPart == 0LL) {
  261. -        (void)fprintf(stderr,
  262. -            "# [NOTE] Source file '%s' is empty, "
  263. -            "cloning will result in an empty file.\n",
  264. +    if (fileSize == 0LL) {
  265. +        (void)printf("# [NOTE] Source file '%s' is empty, cloning "
  266. +            "will result in an empty file.\n",
  267.              srcFileName);
  268.      }
  269.  
  270.      (void)printf("Source file size: %lld bytes.\n",
  271. -        fileSize.QuadPart);
  272. +        fileSize);
  273.  
  274.      /* Get cluster size */
  275. -    FILE_STORAGE_INFO fsi = { 0 };
  276. -    bResult = GetFileInformationByHandleEx(hSrc,
  277. -        FileStorageInfo, &fsi, sizeof(fsi));
  278. -    if (!bResult) {
  279. +    long long srcClusterSize =
  280. +        getFsClusterSize(hSrc);
  281. +    if (srcClusterSize < 0) {
  282.          PrintWin32Error("FileStorageInfo",
  283.              GetLastError());
  284.          goto cleanup;
  285.      }
  286. -
  287. -    unsigned long long srcClusterSize =
  288. -        fsi.PhysicalBytesPerSectorForAtomicity;
  289. -    (void)printf("src file cluster size=%llu\n", srcClusterSize);
  290. +    (void)printf("src file cluster size=%lld\n", srcClusterSize);
  291.  
  292.      hDst = CreateFileA(
  293.          dstFileName,
  294. @@ -170,14 +239,18 @@ main(int ac, char *av[])
  295.          goto cleanup;
  296.      }
  297.  
  298. -    if (fileSize.QuadPart > 0LL) {
  299. -        if (!SetFilePointerEx(hDst, fileSize, NULL, FILE_BEGIN)) {
  300. +    if (fileSize > 0LL) {
  301. +        LARGE_INTEGER fs = { .QuadPart = fileSize };
  302. +        if (!SetFilePointerEx(hDst, fs, NULL, FILE_BEGIN)) {
  303.               PrintWin32Error("SetFilePointerEx (pre-allocate)",
  304.                  GetLastError());
  305.               goto cleanup;
  306.          }
  307.  
  308. -        /* Sets the file size to the current position of the file pointer */
  309. +        /*
  310. +         * Sets the file size to the current position of the file
  311. +         * pointer
  312. +         */
  313.          bResult = SetEndOfFile(hDst);
  314.          if (!bResult) {
  315.              PrintWin32Error("SetEndOfFile (pre-allocate)",
  316. @@ -187,45 +260,43 @@ main(int ac, char *av[])
  317.  
  318.          /* Reset file pointer to pos 0 */
  319.          LARGE_INTEGER currentPos = { .QuadPart = 0LL };
  320. -        SetFilePointerEx(hDst, currentPos, NULL, FILE_BEGIN);
  321. +        (void)SetFilePointerEx(hDst, currentPos, NULL, FILE_BEGIN);
  322.      }
  323.  
  324. -    ded.FileHandle = hSrc;
  325. -    ded.SourceFileOffset.QuadPart = 0LL;
  326. -    ded.TargetFileOffset.QuadPart = 0LL;
  327. -    ded.ByteCount = fileSize;
  328. -
  329.      /*
  330. -     * |FSCTL_DUPLICATE_EXTENTS_TO_FILE| spec requires that the src size
  331. -     * is rounded to the filesytem's cluster size
  332. +     * |FSCTL_DUPLICATE_EXTENTS_TO_FILE| spec requires that the
  333. +     * src size is rounded to the filesytem's cluster size
  334.       *
  335.       * FIXME: What about the size of the destination file ?
  336.       */
  337. -    ded.ByteCount.QuadPart =
  338. -        (ded.ByteCount.QuadPart+srcClusterSize) & ~(srcClusterSize-1);
  339. +    LONGLONG byteCount =
  340. +        (fileSize+srcClusterSize) & ~(srcClusterSize-1);
  341.  
  342. -    (void)printf("# DeviceIoControl(FSCTL_DUPLICATE_EXTENTS_TO_FILE)\n");
  343. +    LONGLONG cloneOffset = 0LL;
  344.  
  345. -    bResult = DeviceIoControl(
  346. -        hDst,
  347. -        FSCTL_DUPLICATE_EXTENTS_TO_FILE,
  348. -        &ded,
  349. -        sizeof(ded),
  350. -        NULL,
  351. -        0,
  352. -        &bytesReturnedDummy,
  353. -        NULL);
  354. +    while(byteCount > 0) {
  355. +        (void)printf("# FSCTL_DUPLICATE_EXTENTS_TO_FILE: cloneOffset=%lld)\n",
  356. +            cloneOffset);
  357.  
  358. -    if (!bResult) {
  359. -        PrintWin32Error("DeviceIoControl(FSCTL_DUPLICATE_EXTENTS_TO_FILE)",
  360. -            GetLastError());
  361. -        goto cleanup;
  362. +        bResult = fsctlduplicateextentstofile(hSrc,
  363. +            hDst,
  364. +            cloneOffset,
  365. +            cloneOffset,
  366. +            __min(byteCount, maxCloneChunkSize));
  367. +
  368. +        if (!bResult) {
  369. +            PrintWin32Error("DeviceIoControl(FSCTL_DUPLICATE_EXTENTS_TO_FILE)",
  370. +                GetLastError());
  371. +            goto cleanup;
  372. +        }
  373. +
  374. +        byteCount -= maxCloneChunkSize;
  375. +        cloneOffset += maxCloneChunkSize;
  376.      }
  377.  
  378.      (void)printf("# Successfully cloned '%s' to '%s'!\n",
  379.          srcFileName, dstFileName);
  380.  
  381. -
  382.  cleanup:
  383.      if ((!bResult) && (hDst != INVALID_HANDLE_VALUE)) {
  384.          (void)printf("# Failure, deleting destination file...\n");
  385. --
  386. 2.45.1
  387.  
  388. From 8acaa301aafb52cd0d53631af0b875d1fc42cd56 Mon Sep 17 00:00:00 2001
  389. From: Roland Mainz <roland.mainz@nrubsig.org>
  390. Date: Tue, 6 May 2025 18:11:58 +0200
  391. Subject: [PATCH 2/2] cygwin: README.bintarball.txt: Recommend Cygwin version
  392.  3.6.1
  393.  
  394. README.bintarball.txt: Recommend Cygwin version 3.6.1
  395.  
  396. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  397. ---
  398. cygwin/README.bintarball.txt | 2 +-
  399.  1 file changed, 1 insertion(+), 1 deletion(-)
  400.  
  401. diff --git a/cygwin/README.bintarball.txt b/cygwin/README.bintarball.txt
  402. index 7b5fb9b..160df6f 100644
  403. --- a/cygwin/README.bintarball.txt
  404. +++ b/cygwin/README.bintarball.txt
  405. @@ -154,7 +154,7 @@ NFSv4.2/NFSv4.1 filesystem driver for Windows 10/11&Windows Server 2019+2022
  406.  - Windows 10 (32bit or 64bit), Windows 11 or Windows Server 2019+2022
  407.  - Cygwin:
  408.      - Cygwin versions:
  409. -        - 64bit: >= 3.5.7 (or 3.6.x-devel)
  410. +        - 64bit: >= 3.5.7, recommended >= 3.6.1
  411.          - 32bit: >= 3.3.6
  412.      - Packages (required):
  413.          cygwin
  414. --
  415. 2.45.1

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

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




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