- diff --git a/daemon/readwrite.c b/daemon/readwrite.c
- index 14e4bcb..8c0e77e 100644
- --- a/daemon/readwrite.c
- +++ b/daemon/readwrite.c
- @@ -22,6 +22,7 @@
- #include <Windows.h>
- #include <stdio.h>
- +#include <stdbool.h>
- #include "nfs41_ops.h"
- #include "name_cache.h"
- @@ -103,6 +104,30 @@ static int read_from_mds(
- }
- }
- out:
- +
- +#if 1
- +#define NUM_TEST_BYTES_FOR_ZERO 512
- + if (len > NUM_TEST_BYTES_FOR_ZERO) {
- + uint32_t zz;
- + const unsigned char *zzc;
- + for (zz = 0, zzc = args->buffer ; zz < NUM_TEST_BYTES_FOR_ZERO ; zz++, zzc++) {
- + if (*zzc != 0)
- + break;
- + }
- +
- + if (zz == NUM_TEST_BYTES_FOR_ZERO) {
- + DPRINTF(0,
- + ("read_from_mds(upcall->state_ref->path.path='%s',args->offset=%lld): "
- + "first %d bytes are '\\0', maxreadsize=%d, status=%d\n",
- + upcall->state_ref->path.path,
- + (long long)args->offset,
- + (int)NUM_TEST_BYTES_FOR_ZERO,
- + (int)maxreadsize,
- + (int)status));
- + }
- + }
- +#endif
- +
- args->out_len = len;
- return status;
- }
- @@ -166,6 +191,10 @@ static int handle_read(void *daemon_context, nfs41_upcall *upcall)
- args->out_len += pnfs_bytes_read;
- out:
- +
- +#if 1
- + FlushProcessWriteBuffers();
- +#endif
- return status;
- }
- @@ -181,7 +210,11 @@ static int write_to_mds(
- nfs41_write_verf verf;
- enum stable_how4 stable, committed;
- unsigned char *p;
- +#if 1
- + const uint32_t maxwritesize = 131072/2;
- +#else
- const uint32_t maxwritesize = max_write_size(session, &file->fh);
- +#endif
- uint32_t to_send, reloffset, len;
- int status = 0;
- /* on write verifier mismatch, retry N times before failing */
- @@ -189,18 +222,110 @@ static int write_to_mds(
- nfs41_file_info info;
- (void)memset(&info, 0, sizeof(info));
- + bool virtlockpages = false;
- +
- +#if 1
- + WIN32_MEMORY_RANGE_ENTRY mre = {
- + .VirtualAddress=args->buffer,
- + .NumberOfBytes=args->len
- + };
- +
- + if (!PrefetchVirtualMemory(GetCurrentProcess(), 1, &mre, 0)) {
- + DPRINTF(0,
- + ("write_to_mds: "
- + "PrefetchVirtualMemory() failed, GetLastError()=%d\n",
- + (int)GetLastError()));
- + }
- +#endif
- +
- +#if 1
- + void *args_buffer = malloc(args->len);
- + if (!args_buffer)
- + goto out;
- + (void)memmove(args_buffer, args->buffer, args->len);
- +#else
- + void *args_buffer = args->buffer;
- +#endif
- +
- +#if 1
- + if (args->len > NUM_TEST_BYTES_FOR_ZERO) {
- + uint32_t zz;
- + const unsigned char *zzc;
- + for (zz = 0, zzc = args_buffer ; zz < NUM_TEST_BYTES_FOR_ZERO ; zz++, zzc++) {
- + if (*zzc != 0)
- + break;
- + }
- +
- + if (zz == NUM_TEST_BYTES_FOR_ZERO) {
- + DPRINTF(0,
- + ("write_to_mds(upcall->state_ref->path.path='%s',args->offset=%lld): "
- + "layer1: first %d bytes are '\\0', maxwritesize=%d\n",
- + upcall->state_ref->path.path,
- + (long long)args->offset,
- + (int)NUM_TEST_BYTES_FOR_ZERO,
- + (int)maxwritesize));
- + }
- + }
- +#endif
- +
- +#if 0
- + if (!VirtualLock(args_buffer, args->len)) {
- + DPRINTF(0,
- + ("write_to_mds(upcall->state_ref->path.path='%s'): "
- + "VirtualLock() failed, GetLastError()=%d\n",
- + upcall->state_ref->path.path, (int)GetLastError()));
- + status = NFS4ERR_IO;
- + goto out;
- + }
- + virtlockpages = true;
- +#endif
- +
- +#if 1
- +#if defined(_M_IX86) || defined(_M_X64)
- + {
- + uint32_t zz;
- + const unsigned char *zzc;
- + for (zz = 0, zzc = args_buffer ; zz < args->len ; zz+=64, zzc+=64) {
- + _mm_clflush(zzc);
- + }
- + FlushProcessWriteBuffers();
- + }
- +#endif /* defined(_M_IX86) || defined(_M_X64) */
- +#endif
- +
- +#if 1
- + if (args->len > NUM_TEST_BYTES_FOR_ZERO) {
- + uint32_t zz;
- + const unsigned char *zzc;
- + for (zz = 0, zzc = args_buffer ; zz < NUM_TEST_BYTES_FOR_ZERO ; zz++, zzc++) {
- + if (*zzc != 0)
- + break;
- + }
- +
- + if (zz == NUM_TEST_BYTES_FOR_ZERO) {
- + DPRINTF(0,
- + ("write_to_mds(upcall->state_ref->path.path='%s',args->offset=%lld): "
- + "layer2: first %d bytes are '\\0', maxwritesize=%d\n",
- + upcall->state_ref->path.path,
- + (long long)args->offset,
- + (int)NUM_TEST_BYTES_FOR_ZERO,
- + (int)maxwritesize));
- + }
- + }
- +#endif
- +
- retry_write:
- - p = args->buffer;
- + p = args_buffer;
- to_send = args->len;
- reloffset = 0;
- len = 0;
- - stable = to_send <= maxwritesize ? FILE_SYNC4 : UNSTABLE4;
- + stable = to_send < maxwritesize ? FILE_SYNC4 : UNSTABLE4;
- committed = FILE_SYNC4;
- - if (to_send > maxwritesize) {
- - DPRINTF(1, ("handle_nfs41_write: writing %d in chunks of %d\n",
- - to_send, maxwritesize));
- + if (to_send >= maxwritesize) {
- + DPRINTF(0, ("write_to_mds(upcall->state_ref->path.path='%s'): writing %d in chunks of %d\n",
- + upcall->state_ref->path.path, to_send, maxwritesize));
- }
- while(to_send > 0) {
- @@ -208,8 +333,12 @@ retry_write:
- status = nfs41_write(session, file, stateid, p, chunk,
- args->offset + reloffset, stable, &bytes_written, &verf, &info);
- - if (status && !len)
- + if (status && !len) {
- + DPRINTF(0,
- + ("write_to_mds: fail status=%d, len=%ld\n",
- + (int)status, (long)len));
- goto out;
- + }
- p += bytes_written;
- to_send -= bytes_written;
- len += bytes_written;
- @@ -247,6 +376,12 @@ retry_write:
- args->ctime = info.change;
- out:
- +#if 1
- + free(args_buffer);
- +#endif
- + if (virtlockpages) {
- + (void)VirtualUnlock(args_buffer, args->len);
- + }
- args->out_len = len;
- return nfs_to_windows_error(status, ERROR_NET_WRITE_FAULT);
- diff --git a/sys/nfs41sys_readwrite.c b/sys/nfs41sys_readwrite.c
- index c039d23..edf4b76 100644
- --- a/sys/nfs41sys_readwrite.c
- +++ b/sys/nfs41sys_readwrite.c
- @@ -109,6 +109,21 @@ NTSTATUS marshal_nfs41_rw(
- RtlCopyMemory(tmp, &entry->u.ReadWrite.offset,
- sizeof(entry->u.ReadWrite.offset));
- tmp += sizeof(entry->u.ReadWrite.offset);
- +
- + if (entry->opcode == NFS41_WRITE) {
- + DbgP("marshal_nfs41_rw: write: len=%lu offset=%llu "
- + "MdlAddress=0x%p MdlFlags=0x%lx\n",
- + entry->buf_len, entry->u.ReadWrite.offset,
- + entry->u.ReadWrite.MdlAddress, (long)entry->u.ReadWrite.MdlAddress->MdlFlags);
- +
- +
- +#if 1
- +#if !defined(_ARM64_)
- + (void)(KeInvalidateAllCaches)();
- +#endif
- +#endif
- + }
- +
- __try {
- #pragma warning( push )
- /*
- @@ -120,7 +135,7 @@ NTSTATUS marshal_nfs41_rw(
- #pragma warning( pop )
- entry->buf =
- MmMapLockedPagesSpecifyCache(entry->u.ReadWrite.MdlAddress,
- - UserMode, MmCached, NULL, TRUE, NormalPagePriority);
- + UserMode, MmCached, NULL, TRUE, HighPagePriority);
- if (entry->buf == NULL) {
- print_error("marshal_nfs41_rw: "
- "MmMapLockedPagesSpecifyCache() failed to map pages\n");
- @@ -139,6 +154,30 @@ NTSTATUS marshal_nfs41_rw(
- RtlCopyMemory(tmp, &entry->buf, sizeof(HANDLE));
- *len = header_len;
- + if (entry->opcode == NFS41_WRITE) {
- + DbgP("marshal_nfs41_rw: write: len=%lu offset=%llu "
- + "MdlAddress=0x%p MdlFlags=0x%lx\n",
- + entry->buf_len, entry->u.ReadWrite.offset,
- + entry->u.ReadWrite.MdlAddress, (long)entry->u.ReadWrite.MdlAddress->MdlFlags);
- + }
- +
- +#if 1
- +#define NUM_TEST_BYTES_FOR_ZERO 512
- + if ((entry->opcode == NFS41_WRITE) && (entry->buf_len > NUM_TEST_BYTES_FOR_ZERO)) {
- + long zz;
- + const unsigned char *zzc;
- + for (zz = 0, zzc = entry->buf ; zz < NUM_TEST_BYTES_FOR_ZERO ; zz++, zzc++) {
- + if (*zzc != 0)
- + break;
- + }
- +
- + if (zz == NUM_TEST_BYTES_FOR_ZERO) {
- + DbgP("marshal_nfs41_rw: MYASSERT: "
- + "first %d bytes are '\\0'\n",
- + (int)NUM_TEST_BYTES_FOR_ZERO);
- + }
- + }
- +#endif
- #ifdef DEBUG_MARSHAL_DETAIL_RW
- DbgP("marshal_nfs41_rw: len=%lu offset=%llu "
- "MdlAddress=0x%p Userspace=0x%p\n",
- diff --git a/tests/wintartests/wintartest_seq001.bash b/tests/wintartests/wintartest_seq001.bash
- index 489d169..ee9652b 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,52 @@ 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
- + if [[ ! -r "$currf" ]] ; then
- + printf '## ERROR: File %q not found.\n' "$currf"
- + return 1
- + fi
- + if [[ ! -s "$currf" ]] ; then
- + printf '## ERROR: File %q is empty (ls -l == "%s").\n' "$currf" "$(ls -l "$currf")"
- + return 1
- + fi
- +
- + out="$(od -A x -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'
- + printf '##### SUCCESS\n'
- +
- + return 0
- +}
- +
- +
- +#
- +# main
- +#
- +
- +export PATH='/bin:/usr/bin'
- +
- +if [[ ! -x '/cygdrive/c/Windows/system32/tar' ]] ; then
- + printf $"%s: %s not found.\n" \
- + "$0" '/cygdrive/c/Windows/system32/tar' 1>&2
- + exit 1
- +fi
- +
- +# Set umask=0000 to avoid permission trouble on SMB filesystems
- +umask 0000
- -exit 0
- +test_wintar_seq true true
- +exit $?
- # EOF.
More debug code to hunt down the Win tar '0' write corruption bug
Posted by Anonymous on Sat 16th Nov 2024 13:01
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.