pastebin - collaborative debugging tool
nrubsig.kpaste.net RSS


(Failed) explicit cache flush experriment to try to fix Win tar problems with 00 bytes in text files
Posted by Anonymous on Fri 15th Nov 2024 09:51
raw | new post

  1. diff --git a/daemon/readdir.c b/daemon/readdir.c
  2. index a2d7772..a9a9ead 100644
  3. --- a/daemon/readdir.c
  4. +++ b/daemon/readdir.c
  5. @@ -876,6 +876,8 @@ static int marshall_readdir(unsigned char *buffer, uint32_t *length, nfs41_upcal
  6.      int status;
  7.      readdir_upcall_args *args = &upcall->args.readdir;
  8.  
  9. +    flush_cpu_data_cache(args->kbuf, args->query_reply_len);
  10. +
  11.      status = safe_write(&buffer, length, &args->query_reply_len, sizeof(args->query_reply_len));
  12.      return status;
  13.  }
  14. diff --git a/daemon/readwrite.c b/daemon/readwrite.c
  15. index 14e4bcb..35d61e5 100644
  16. --- a/daemon/readwrite.c
  17. +++ b/daemon/readwrite.c
  18. @@ -26,6 +26,7 @@
  19.  #include "nfs41_ops.h"
  20.  #include "name_cache.h"
  21.  #include "upcall.h"
  22. +#include "nfs41_driver.h" /* only for |NFS41_READ| */
  23.  #include "daemon_debug.h"
  24.  #include "util.h"
  25.  
  26. @@ -318,6 +319,11 @@ static int marshall_rw(unsigned char *buffer, uint32_t *length, nfs41_upcall *up
  27.  {
  28.      readwrite_upcall_args *args = &upcall->args.rw;
  29.      int status;
  30. +
  31. +    if (upcall->opcode == NFS41_READ) {
  32. +        flush_cpu_data_cache(args->buffer, args->out_len);
  33. +    }
  34. +
  35.      status = safe_write(&buffer, length, &args->out_len, sizeof(args->out_len));
  36.      if (status) goto out;
  37.      status = safe_write(&buffer, length, &args->ctime, sizeof(args->ctime));
  38. diff --git a/daemon/util.c b/daemon/util.c
  39. index ef41a30..a476115 100644
  40. --- a/daemon/util.c
  41. +++ b/daemon/util.c
  42. @@ -391,6 +391,32 @@ out:
  43.      return status;
  44.  }
  45.  
  46. +void flush_cpu_data_cache(void *p, size_t len)
  47. +{
  48. +#if 1
  49. +#if defined(_M_IX86) || defined(_M_X64)
  50. +
  51. +/*
  52. + * FIXME: We should use |GetLogicalProcessorInformation()| to get the
  53. + * correct cache line size instead of guessing it here
  54. + */
  55. +#if defined(_M_X64)
  56. +#define MIN_DATACACHE_LINE_SIZE (64)
  57. +#else
  58. +#define MIN_DATACACHE_LINE_SIZE (32)
  59. +#endif
  60. +    char *buf = p;
  61. +    size_t i;
  62. +
  63. +    for (i = 0 ; i < len ; i+=MIN_DATACACHE_LINE_SIZE) {
  64. +        _mm_clflush(buf);
  65. +        buf+=MIN_DATACACHE_LINE_SIZE;
  66. +    }
  67. +#else
  68. +    /* FIXME! */
  69. +#endif /* defined(_M_IX86) || defined(_M_X64) */
  70. +#endif
  71. +}
  72.  
  73.  /*
  74.   * Like Win32 |popen()| but doesn't randomly fail or genrates EINVAL
  75. diff --git a/daemon/util.h b/daemon/util.h
  76. index 7a4e12a..e056936 100644
  77. --- a/daemon/util.h
  78. +++ b/daemon/util.h
  79. @@ -351,6 +351,8 @@ __inline int valid_handle(HANDLE handle) {
  80.      return handle != INVALID_HANDLE_VALUE && handle != 0;
  81.  }
  82.  
  83. +void flush_cpu_data_cache(void *p, size_t len);
  84. +
  85.  typedef struct _subcmd_popen_context {
  86.      HANDLE hReadPipe;
  87.      HANDLE hWritePipe;
  88. diff --git a/sys/nfs41sys_readwrite.c b/sys/nfs41sys_readwrite.c
  89. index c039d23..f44559c 100644
  90. --- a/sys/nfs41sys_readwrite.c
  91. +++ b/sys/nfs41sys_readwrite.c
  92. @@ -136,6 +136,25 @@ NTSTATUS marshal_nfs41_rw(
  93.          status = STATUS_ACCESS_VIOLATION;
  94.          goto out;
  95.      }
  96. +
  97. +    if (entry->opcode == NFS41_WRITE) {
  98. +        /* |NFS41_WRITE| - Flush CPU cache for the
  99. +         * |MmMapLockedPagesSpecifyCache()| supplied buffer so the
  100. +         * usermode nfsd daemon always sees the correct data.
  101. +         * The |CacheType| parameter of
  102. +         * |MmMapLockedPagesSpecifyCache()| above does NOT
  103. +         * help, as the documentation states:
  104. +         * "... The routine uses the CacheType parameter only if the
  105. +         * pages that are described by the MDL do not already have a
  106. +         * cache type associated with them. However, in nearly all
  107. +         * cases, the pages already have an associated cache type,
  108. +         * and this cache type is used by the new mapping..."
  109. +         *
  110. +         * So we explicitly flush this here.
  111. +         */
  112. +        KeInvalidateRangeAllCaches(entry->buf, entry->buf_len);
  113. +    }
  114. +
  115.      RtlCopyMemory(tmp, &entry->buf, sizeof(HANDLE));
  116.      *len = header_len;
  117.  
  118. diff --git a/tests/wintartests/wintartest_seq001.bash b/tests/wintartests/wintartest_seq001.bash
  119. index 489d169..1f22858 100644
  120. --- a/tests/wintartests/wintartest_seq001.bash
  121. +++ b/tests/wintartests/wintartest_seq001.bash
  122. @@ -11,19 +11,45 @@
  123.  # Written by Roland Mainz <roland.mainz@nrubsig.org>
  124.  #
  125.  
  126. -export PATH='/bin:/usr/bin'
  127. +function test_wintar_seq
  128. +{
  129. +       set -o xtrace
  130. +       set -o errexit
  131. +       set -o nounset
  132.  
  133. +       # config
  134. +       typeset use_bzip2=$1
  135. +       typeset use_localdiskfortar=$2
  136. +
  137. +       # local vars
  138. +       typeset tarfile_dir
  139. +       typeset tarfilename
  140.         typeset -i i
  141.         typeset out
  142. +       typeset -a testfiles
  143. +       typeset currf
  144.  
  145. -set -o xtrace
  146. -set -o errexit
  147. +       # seq 1040 == 4093 bytes
  148. +       # seq 1042 == 4103 bytes
  149. +       for i in 1 100 1040 5000 10000 12000 ; do
  150. +               rm -f -- "${i}seq.txt"
  151. +               seq "$i" >"${i}seq.txt"
  152. +               testfiles+=( "${i}seq.txt" )
  153. +       done
  154.  
  155. -# Set umask=0000 to avoid permission trouble with SMB filesystems
  156. -umask 0000
  157. +       if "${use_localdiskfortar}" ; then
  158. +               tarfile_dir='/tmp'
  159. +       else
  160. +               tarfile_dir="$PWD"
  161. +       fi
  162.  
  163. -rm -f '10000seq.txt'
  164. -seq 100000 >'10000seq.txt' ; tar -cvf - '10000seq.txt' >'10000seq.tar' #| pbzip2 -1 >'10000seq.tar.bz2'
  165. +       if ${use_bzip2} ; then
  166. +               tarfilename="${tarfile_dir}/test_seq.tar.bz2"
  167. +               tar -cvf - "${testfiles[@]}" | pbzip2 -1 >"${tarfilename}"
  168. +       else
  169. +               tarfilename="${tarfile_dir}/test_seq.tar"
  170. +               tar -cvf - "${testfiles[@]}" >"${tarfilename}"
  171. +       fi
  172.  
  173.         rm -Rf 'tmp'
  174.         mkdir 'tmp'
  175. @@ -32,20 +58,33 @@ cd 'tmp'
  176.         set +o xtrace
  177.  
  178.         for (( i=0 ; i < 2000 ; i++ )) ; do
  179. -       printf '# Cycle %d:\n' "$i"
  180. -       /cygdrive/c/Windows/system32/tar -xvf "$(cygpath -w '../10000seq.tar')"
  181. -       out="$(od -x -v '10000seq.txt' | grep -F ' 0000' | head -n 5)"
  182. +               printf '#### Test cycle %d (usingbzip=%s,tarfileonlocaldisk=%s):\n' "$i" "$use_bzip2" "$use_localdiskfortar"
  183. +               /cygdrive/c/Windows/system32/tar -xvf "$(cygpath -w "${tarfilename}")"
  184. +
  185. +               for currf in "${testfiles[@]}" ; do
  186. +                       out="$(od -t x1 -v "$currf" | grep -F ' 00' | head -n 5)"
  187.  
  188.                         if [[ "$out" != '' ]] ; then
  189. -               printf '# ERROR: Sequence of zero bytes in plain /usr/bin/seq output found:\n'
  190. +                               printf '# ERROR: Zero byte in plain /usr/bin/seq output %q found:\n' "$currf"
  191.                                 printf -- '---- snip ----\n%s\n---- snip ----\n' "$out"
  192. -               exit 1
  193. +                               return 1
  194.                         fi
  195. +               done
  196.  
  197. -       rm -f '10000seq.txt'
  198. +               rm -f -- "${testfiles[@]}"
  199.         done
  200.  
  201.         printf '# SUCCESS\n'
  202.  
  203. -exit 0
  204. +       return 0
  205. +}
  206. +
  207. +export PATH='/bin:/usr/bin'
  208. +
  209. +
  210. +# Set umask=0000 to avoid permission trouble on SMB filesystems
  211. +umask 0000
  212. +
  213. +test_wintar_seq true true
  214. +
  215.  # 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