- diff --git a/daemon/readdir.c b/daemon/readdir.c
 - index a2d7772..a9a9ead 100644
 - --- a/daemon/readdir.c
 - +++ b/daemon/readdir.c
 - @@ -876,6 +876,8 @@ static int marshall_readdir(unsigned char *buffer, uint32_t *length, nfs41_upcal
 - int status;
 - readdir_upcall_args *args = &upcall->args.readdir;
 - + flush_cpu_data_cache(args->kbuf, args->query_reply_len);
 - +
 - status = safe_write(&buffer, length, &args->query_reply_len, sizeof(args->query_reply_len));
 - return status;
 - }
 - diff --git a/daemon/readwrite.c b/daemon/readwrite.c
 - index 14e4bcb..35d61e5 100644
 - --- a/daemon/readwrite.c
 - +++ b/daemon/readwrite.c
 - @@ -26,6 +26,7 @@
 - #include "nfs41_ops.h"
 - #include "name_cache.h"
 - #include "upcall.h"
 - +#include "nfs41_driver.h" /* only for |NFS41_READ| */
 - #include "daemon_debug.h"
 - #include "util.h"
 - @@ -318,6 +319,11 @@ static int marshall_rw(unsigned char *buffer, uint32_t *length, nfs41_upcall *up
 - {
 - readwrite_upcall_args *args = &upcall->args.rw;
 - int status;
 - +
 - + if (upcall->opcode == NFS41_READ) {
 - + flush_cpu_data_cache(args->buffer, args->out_len);
 - + }
 - +
 - status = safe_write(&buffer, length, &args->out_len, sizeof(args->out_len));
 - if (status) goto out;
 - status = safe_write(&buffer, length, &args->ctime, sizeof(args->ctime));
 - diff --git a/daemon/util.c b/daemon/util.c
 - index ef41a30..a476115 100644
 - --- a/daemon/util.c
 - +++ b/daemon/util.c
 - @@ -391,6 +391,32 @@ out:
 - return status;
 - }
 - +void flush_cpu_data_cache(void *p, size_t len)
 - +{
 - +#if 1
 - +#if defined(_M_IX86) || defined(_M_X64)
 - +
 - +/*
 - + * FIXME: We should use |GetLogicalProcessorInformation()| to get the
 - + * correct cache line size instead of guessing it here
 - + */
 - +#if defined(_M_X64)
 - +#define MIN_DATACACHE_LINE_SIZE (64)
 - +#else
 - +#define MIN_DATACACHE_LINE_SIZE (32)
 - +#endif
 - + char *buf = p;
 - + size_t i;
 - +
 - + for (i = 0 ; i < len ; i+=MIN_DATACACHE_LINE_SIZE) {
 - + _mm_clflush(buf);
 - + buf+=MIN_DATACACHE_LINE_SIZE;
 - + }
 - +#else
 - + /* FIXME! */
 - +#endif /* defined(_M_IX86) || defined(_M_X64) */
 - +#endif
 - +}
 - /*
 - * Like Win32 |popen()| but doesn't randomly fail or genrates EINVAL
 - diff --git a/daemon/util.h b/daemon/util.h
 - index 7a4e12a..e056936 100644
 - --- a/daemon/util.h
 - +++ b/daemon/util.h
 - @@ -351,6 +351,8 @@ __inline int valid_handle(HANDLE handle) {
 - return handle != INVALID_HANDLE_VALUE && handle != 0;
 - }
 - +void flush_cpu_data_cache(void *p, size_t len);
 - +
 - typedef struct _subcmd_popen_context {
 - HANDLE hReadPipe;
 - HANDLE hWritePipe;
 - diff --git a/sys/nfs41sys_readwrite.c b/sys/nfs41sys_readwrite.c
 - index c039d23..f44559c 100644
 - --- a/sys/nfs41sys_readwrite.c
 - +++ b/sys/nfs41sys_readwrite.c
 - @@ -136,6 +136,25 @@ NTSTATUS marshal_nfs41_rw(
 - status = STATUS_ACCESS_VIOLATION;
 - goto out;
 - }
 - +
 - + if (entry->opcode == NFS41_WRITE) {
 - + /* |NFS41_WRITE| - Flush CPU cache for the
 - + * |MmMapLockedPagesSpecifyCache()| supplied buffer so the
 - + * usermode nfsd daemon always sees the correct data.
 - + * The |CacheType| parameter of
 - + * |MmMapLockedPagesSpecifyCache()| above does NOT
 - + * help, as the documentation states:
 - + * "... The routine uses the CacheType parameter only if the
 - + * pages that are described by the MDL do not already have a
 - + * cache type associated with them. However, in nearly all
 - + * cases, the pages already have an associated cache type,
 - + * and this cache type is used by the new mapping..."
 - + *
 - + * So we explicitly flush this here.
 - + */
 - + KeInvalidateRangeAllCaches(entry->buf, entry->buf_len);
 - + }
 - +
 - RtlCopyMemory(tmp, &entry->buf, sizeof(HANDLE));
 - *len = header_len;
 - diff --git a/tests/wintartests/wintartest_seq001.bash b/tests/wintartests/wintartest_seq001.bash
 - index 489d169..1f22858 100644
 - --- a/tests/wintartests/wintartest_seq001.bash
 - +++ b/tests/wintartests/wintartest_seq001.bash
 - @@ -11,19 +11,45 @@
 - # Written by Roland Mainz <roland.mainz@nrubsig.org>
 - #
 - -export PATH='/bin:/usr/bin'
 - +function test_wintar_seq
 - +{
 - + set -o xtrace
 - + set -o errexit
 - + set -o nounset
 - + # config
 - + typeset use_bzip2=$1
 - + typeset use_localdiskfortar=$2
 - +
 - + # local vars
 - + typeset tarfile_dir
 - + typeset tarfilename
 - typeset -i i
 - typeset out
 - + typeset -a testfiles
 - + typeset currf
 - -set -o xtrace
 - -set -o errexit
 - + # seq 1040 == 4093 bytes
 - + # seq 1042 == 4103 bytes
 - + for i in 1 100 1040 5000 10000 12000 ; do
 - + rm -f -- "${i}seq.txt"
 - + seq "$i" >"${i}seq.txt"
 - + testfiles+=( "${i}seq.txt" )
 - + done
 - -# Set umask=0000 to avoid permission trouble with SMB filesystems
 - -umask 0000
 - + if "${use_localdiskfortar}" ; then
 - + tarfile_dir='/tmp'
 - + else
 - + tarfile_dir="$PWD"
 - + fi
 - -rm -f '10000seq.txt'
 - -seq 100000 >'10000seq.txt' ; tar -cvf - '10000seq.txt' >'10000seq.tar' #| pbzip2 -1 >'10000seq.tar.bz2'
 - + if ${use_bzip2} ; then
 - + tarfilename="${tarfile_dir}/test_seq.tar.bz2"
 - + tar -cvf - "${testfiles[@]}" | pbzip2 -1 >"${tarfilename}"
 - + else
 - + tarfilename="${tarfile_dir}/test_seq.tar"
 - + tar -cvf - "${testfiles[@]}" >"${tarfilename}"
 - + fi
 - rm -Rf 'tmp'
 - mkdir 'tmp'
 - @@ -32,20 +58,33 @@ cd 'tmp'
 - set +o xtrace
 - for (( i=0 ; i < 2000 ; i++ )) ; do
 - - printf '# Cycle %d:\n' "$i"
 - - /cygdrive/c/Windows/system32/tar -xvf "$(cygpath -w '../10000seq.tar')"
 - - out="$(od -x -v '10000seq.txt' | grep -F ' 0000' | head -n 5)"
 - + printf '#### Test cycle %d (usingbzip=%s,tarfileonlocaldisk=%s):\n' "$i" "$use_bzip2" "$use_localdiskfortar"
 - + /cygdrive/c/Windows/system32/tar -xvf "$(cygpath -w "${tarfilename}")"
 - +
 - + for currf in "${testfiles[@]}" ; do
 - + out="$(od -t x1 -v "$currf" | grep -F ' 00' | head -n 5)"
 - if [[ "$out" != '' ]] ; then
 - - printf '# ERROR: Sequence of zero bytes in plain /usr/bin/seq output found:\n'
 - + printf '# ERROR: Zero byte in plain /usr/bin/seq output %q found:\n' "$currf"
 - printf -- '---- snip ----\n%s\n---- snip ----\n' "$out"
 - - exit 1
 - + return 1
 - fi
 - + done
 - - rm -f '10000seq.txt'
 - + rm -f -- "${testfiles[@]}"
 - done
 - printf '# SUCCESS\n'
 - -exit 0
 - + return 0
 - +}
 - +
 - +export PATH='/bin:/usr/bin'
 - +
 - +
 - +# Set umask=0000 to avoid permission trouble on SMB filesystems
 - +umask 0000
 - +
 - +test_wintar_seq true true
 - +
 - # EOF.
 
(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
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.
 nrubsig.kpaste.net RSS