pastebin - collaborative debugging tool
nrubsig.kpaste.net RSS


Debug code to hung hunt down the native Windows tar issue
Posted by Anonymous on Fri 15th Nov 2024 17:08
raw | new post

  1. # Debug code to hung hunt down the native Windows tar issue
  2. # So far it seems the zeros do not happen during read, only the NFS41_WRITE codepath sees (and writes to the NFS server) them
  3. # Next-best guess is that this happens in the kernel, or that the kernel doesn't flush the cache, or ...
  4. #
  5. # 1480/impersonated_user='roland_mainz'/'Kein' read_from_mds(upcall->state_ref->path.path='\bigdisk\builds\win_tar_test\wintar_tmp\bin\shcomp.exe',args->offset=458752): first 512 bytes are '\0', maxreadsize=131072, status=0
  6. # 2644/impersonated_user='roland_mainz'/'Kein' write_to_mds(upcall->state_ref->path.path='\bigdisk\builds\win_tar_test\tmp\10000seq.txt',args->offset=32768): layer1: first 512 bytes are '\0', maxwritesize=65536
  7. # 2644/impersonated_user='roland_mainz'/'Kein' write_to_mds(upcall->state_ref->path.path='\bigdisk\builds\win_tar_test\tmp\10000seq.txt',args->offset=32768): layer2: first 512 bytes are '\0', maxwritesize=65536
  8. # 2630/impersonated_user='roland_mainz'/'Kein' read_from_mds(upcall->state_ref->path.path='\bigdisk\builds\win_tar_test\tmp\10000seq.txt',args->offset=48894): first 512 bytes are '\0', maxreadsize=131072, status=0
  9. diff --git a/daemon/readwrite.c b/daemon/readwrite.c
  10. index 14e4bcb..c238228 100644
  11. --- a/daemon/readwrite.c
  12. +++ b/daemon/readwrite.c
  13. @@ -22,6 +22,7 @@
  14.  
  15.  #include <Windows.h>
  16.  #include <stdio.h>
  17. +#include <stdbool.h>
  18.  
  19.  #include "nfs41_ops.h"
  20.  #include "name_cache.h"
  21. @@ -103,6 +104,30 @@ static int read_from_mds(
  22.          }
  23.      }
  24.  out:
  25. +
  26. +#if 1
  27. +#define NUM_TEST_BYTES_FOR_ZERO 512
  28. +    if (len > NUM_TEST_BYTES_FOR_ZERO) {
  29. +        uint32_t zz;
  30. +        const unsigned char *zzc;
  31. +        for (zz = 0, zzc = args->buffer ; zz < NUM_TEST_BYTES_FOR_ZERO ; zz++, zzc++) {
  32. +            if (*zzc != 0)
  33. +                break;
  34. +        }
  35. +
  36. +        if (zz == NUM_TEST_BYTES_FOR_ZERO) {
  37. +            DPRINTF(0,
  38. +                ("read_from_mds(upcall->state_ref->path.path='%s',args->offset=%lld): "
  39. +                "first %d bytes are '\\0', maxreadsize=%d, status=%d\n",
  40. +                upcall->state_ref->path.path,
  41. +                (long long)args->offset,
  42. +                (int)NUM_TEST_BYTES_FOR_ZERO,
  43. +                (int)maxreadsize,
  44. +                (int)status));
  45. +        }
  46. +    }
  47. +#endif
  48. +
  49.      args->out_len = len;
  50.      return status;
  51.  }
  52. @@ -166,6 +191,10 @@ static int handle_read(void *daemon_context, nfs41_upcall *upcall)
  53.  
  54.      args->out_len += pnfs_bytes_read;
  55.  out:
  56. +
  57. +#if 1
  58. +    FlushProcessWriteBuffers();
  59. +#endif
  60.      return status;
  61.  }
  62.  
  63. @@ -181,7 +210,11 @@ static int write_to_mds(
  64.      nfs41_write_verf verf;
  65.      enum stable_how4 stable, committed;
  66.      unsigned char *p;
  67. +#if 1
  68. +    const uint32_t maxwritesize = 131072/2;
  69. +#else
  70.      const uint32_t maxwritesize = max_write_size(session, &file->fh);
  71. +#endif
  72.      uint32_t to_send, reloffset, len;
  73.      int status = 0;
  74.      /* on write verifier mismatch, retry N times before failing */
  75. @@ -189,18 +222,87 @@ static int write_to_mds(
  76.      nfs41_file_info info;
  77.  
  78.      (void)memset(&info, 0, sizeof(info));
  79. +    bool virtlockpages = false;
  80. +
  81. +#if 1
  82. +    if (args->len > NUM_TEST_BYTES_FOR_ZERO) {
  83. +        uint32_t zz;
  84. +        const unsigned char *zzc;
  85. +        for (zz = 0, zzc = args->buffer ; zz < NUM_TEST_BYTES_FOR_ZERO ; zz++, zzc++) {
  86. +            if (*zzc != 0)
  87. +                break;
  88. +        }
  89. +
  90. +        if (zz == NUM_TEST_BYTES_FOR_ZERO) {
  91. +            DPRINTF(0,
  92. +                ("write_to_mds(upcall->state_ref->path.path='%s',args->offset=%lld): "
  93. +                "layer1: first %d bytes are '\\0', maxwritesize=%d\n",
  94. +                upcall->state_ref->path.path,
  95. +                (long long)args->offset,
  96. +                (int)NUM_TEST_BYTES_FOR_ZERO,
  97. +                (int)maxwritesize));
  98. +        }
  99. +    }
  100. +#endif
  101. +
  102. +#if 0
  103. +    if (!VirtualLock(args->buffer, args->len)) {
  104. +        DPRINTF(0,
  105. +            ("write_to_mds(upcall->state_ref->path.path='%s'): "
  106. +            "VirtualLock() failed, GetLastError()=%d\n",
  107. +            upcall->state_ref->path.path, (int)GetLastError()));
  108. +            status = NFS4ERR_IO;
  109. +        goto out;
  110. +    }
  111. +    virtlockpages = true;
  112. +#endif
  113. +
  114. +#if 1
  115. +#if defined(_M_IX86) || defined(_M_X64)
  116. +    {
  117. +        uint32_t zz;
  118. +        const unsigned char *zzc;
  119. +        for (zz = 0, zzc = args->buffer ; zz < args->len ; zz+=64, zzc+=64) {
  120. +            _mm_clflush(zzc);
  121. +        }
  122. +        FlushProcessWriteBuffers();
  123. +    }
  124. +#endif /* defined(_M_IX86) || defined(_M_X64) */
  125. +#endif
  126. +
  127. +#if 1
  128. +    if (args->len > NUM_TEST_BYTES_FOR_ZERO) {
  129. +        uint32_t zz;
  130. +        const unsigned char *zzc;
  131. +        for (zz = 0, zzc = args->buffer ; zz < NUM_TEST_BYTES_FOR_ZERO ; zz++, zzc++) {
  132. +            if (*zzc != 0)
  133. +                break;
  134. +        }
  135. +
  136. +        if (zz == NUM_TEST_BYTES_FOR_ZERO) {
  137. +            DPRINTF(0,
  138. +                ("write_to_mds(upcall->state_ref->path.path='%s',args->offset=%lld): "
  139. +                "layer2: first %d bytes are '\\0', maxwritesize=%d\n",
  140. +                upcall->state_ref->path.path,
  141. +                (long long)args->offset,
  142. +                (int)NUM_TEST_BYTES_FOR_ZERO,
  143. +                (int)maxwritesize));
  144. +        }
  145. +    }
  146. +#endif
  147. +
  148.  
  149.  retry_write:
  150.      p = args->buffer;
  151.      to_send = args->len;
  152.      reloffset = 0;
  153.      len = 0;
  154. -    stable = to_send <= maxwritesize ? FILE_SYNC4 : UNSTABLE4;
  155. +    stable = to_send < maxwritesize ? FILE_SYNC4 : UNSTABLE4;
  156.      committed = FILE_SYNC4;
  157.  
  158. -    if (to_send > maxwritesize) {
  159. -        DPRINTF(1, ("handle_nfs41_write: writing %d in chunks of %d\n",
  160. -            to_send, maxwritesize));
  161. +    if (to_send >= maxwritesize) {
  162. +        DPRINTF(0, ("write_to_mds(upcall->state_ref->path.path='%s'): writing %d in chunks of %d\n",
  163. +            upcall->state_ref->path.path, to_send, maxwritesize));
  164.      }
  165.  
  166.      while(to_send > 0) {
  167. @@ -208,8 +310,12 @@ retry_write:
  168.  
  169.          status = nfs41_write(session, file, stateid, p, chunk,
  170.              args->offset + reloffset, stable, &bytes_written, &verf, &info);
  171. -        if (status && !len)
  172. -            goto out;
  173. +        if (status && !len) {
  174. +            DPRINTF(0,
  175. +                ("write_to_mds: fail status=%d, len=%ld\n",
  176. +                (int)status, (long)len));
  177. +            goto out;
  178. +        }
  179.          p += bytes_written;
  180.          to_send -= bytes_written;
  181.          len += bytes_written;
  182. @@ -247,6 +353,9 @@ retry_write:
  183.      args->ctime = info.change;
  184.  
  185.  out:
  186. +    if (virtlockpages) {
  187. +        (void)VirtualUnlock(args->buffer, args->len);
  188. +    }
  189.      args->out_len = len;
  190.      return nfs_to_windows_error(status, ERROR_NET_WRITE_FAULT);
  191.  
  192. diff --git a/tests/wintartests/wintartest_seq001.bash b/tests/wintartests/wintartest_seq001.bash
  193. index 489d169..ee9652b 100644
  194. --- a/tests/wintartests/wintartest_seq001.bash
  195. +++ b/tests/wintartests/wintartest_seq001.bash
  196. @@ -11,41 +11,99 @@
  197.  # Written by Roland Mainz <roland.mainz@nrubsig.org>
  198.  #
  199.  
  200. -export PATH='/bin:/usr/bin'
  201. +function test_wintar_seq
  202. +{
  203. +       set -o xtrace
  204. +       set -o errexit
  205. +       set -o nounset
  206.  
  207. -typeset -i i
  208. -typeset out
  209. +       # config
  210. +       typeset use_bzip2=$1
  211. +       typeset use_localdiskfortar=$2
  212.  
  213. -set -o xtrace
  214. -set -o errexit
  215. +       # local vars
  216. +       typeset tarfile_dir
  217. +       typeset tarfilename
  218. +       typeset -i i
  219. +       typeset out
  220. +       typeset -a testfiles
  221. +       typeset currf
  222.  
  223. -# Set umask=0000 to avoid permission trouble with SMB filesystems
  224. -umask 0000
  225. +       # seq 1040 == 4093 bytes
  226. +       # seq 1042 == 4103 bytes
  227. +       for i in 1 100 1040 5000 10000 12000 ; do
  228. +               rm -f -- "${i}seq.txt"
  229. +               seq "$i" >"${i}seq.txt"
  230. +               testfiles+=( "${i}seq.txt" )
  231. +       done
  232.  
  233. -rm -f '10000seq.txt'
  234. -seq 100000 >'10000seq.txt' ; tar -cvf - '10000seq.txt' >'10000seq.tar' #| pbzip2 -1 >'10000seq.tar.bz2'
  235. +       if "${use_localdiskfortar}" ; then
  236. +               tarfile_dir='/tmp'
  237. +       else
  238. +               tarfile_dir="$PWD"
  239. +       fi
  240.  
  241. -rm -Rf 'tmp'
  242. -mkdir 'tmp'
  243. -cd 'tmp'
  244. +       if ${use_bzip2} ; then
  245. +               tarfilename="${tarfile_dir}/test_seq.tar.bz2"
  246. +               tar -cvf - "${testfiles[@]}" | pbzip2 -1 >"${tarfilename}"
  247. +       else
  248. +               tarfilename="${tarfile_dir}/test_seq.tar"
  249. +               tar -cvf - "${testfiles[@]}" >"${tarfilename}"
  250. +       fi
  251.  
  252. -set +o xtrace
  253. +       rm -Rf 'tmp'
  254. +       mkdir 'tmp'
  255. +       cd 'tmp'
  256.  
  257. -for (( i=0 ; i < 2000 ; i++ )) ; do
  258. -       printf '# Cycle %d:\n' "$i"
  259. -       /cygdrive/c/Windows/system32/tar -xvf "$(cygpath -w '../10000seq.tar')"
  260. -       out="$(od -x -v '10000seq.txt' | grep -F ' 0000' | head -n 5)"
  261. +       set +o xtrace
  262.  
  263. -       if [[ "$out" != '' ]] ; then
  264. -               printf '# ERROR: Sequence of zero bytes in plain /usr/bin/seq output found:\n'
  265. -               printf -- '---- snip ----\n%s\n---- snip ----\n' "$out"
  266. -               exit 1
  267. -       fi
  268. +       for (( i=0 ; i < 2000 ; i++ )) ; do
  269. +               printf '#### Test cycle %d (usingbzip=%s,tarfileonlocaldisk=%s):\n' "$i" "$use_bzip2" "$use_localdiskfortar"
  270. +               /cygdrive/c/Windows/system32/tar -xvf "$(cygpath -w "${tarfilename}")"
  271. +
  272. +               for currf in "${testfiles[@]}" ; do
  273. +                       if [[ ! -r "$currf" ]] ; then
  274. +                               printf '## ERROR: File %q not found.\n' "$currf"
  275. +                               return 1
  276. +                       fi
  277. +                       if [[ ! -s "$currf" ]] ; then
  278. +                               printf '## ERROR: File %q is empty (ls -l == "%s").\n' "$currf" "$(ls -l "$currf")"
  279. +                               return 1
  280. +                       fi
  281. +
  282. +                       out="$(od -A x -t x1 -v "$currf" | grep -F ' 00' | head -n 5)"
  283. +
  284. +                       if [[ "$out" != '' ]] ; then
  285. +                               printf '## ERROR: Zero byte in plain /usr/bin/seq output %q found:\n' "$currf"
  286. +                               printf -- '---- snip ----\n%s\n---- snip ----\n' "$out"
  287. +                               return 1
  288. +                       fi
  289. +               done
  290. +
  291. +               rm -f -- "${testfiles[@]}"
  292. +       done
  293.  
  294. -       rm -f '10000seq.txt'
  295. -done
  296. +       printf '##### SUCCESS\n'
  297.  
  298. -printf '# SUCCESS\n'
  299. +       return 0
  300. +}
  301. +
  302. +
  303. +#
  304. +# main
  305. +#
  306. +
  307. +export PATH='/bin:/usr/bin'
  308. +
  309. +if [[ ! -x '/cygdrive/c/Windows/system32/tar' ]] ; then
  310. +       printf $"%s: %s not found.\n" \
  311. +               "$0" '/cygdrive/c/Windows/system32/tar' 1>&2
  312. +       exit 1
  313. +fi
  314. +
  315. +# Set umask=0000 to avoid permission trouble on SMB filesystems
  316. +umask 0000
  317.  
  318. -exit 0
  319. +test_wintar_seq true true
  320. +exit $?
  321.  # EOF.

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