diff mbox series

Add test for file truncation over NFS

Message ID 20240213140233.14445-1-mdoucha@suse.cz
State Accepted
Headers show
Series Add test for file truncation over NFS | expand

Commit Message

Martin Doucha Feb. 13, 2024, 2:02 p.m. UTC
Some older kernels have a bug in NFS where the client caches that
a file does not exist after unsuccessful access to it and then
does not pass O_TRUNC flag to the server even though the file may
have been created by another client in the mean time. This may result
in new data being merged with old file contents instead of replacing
them.

Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---
 runtest/net.nfs                           | 11 ++++++++
 testcases/network/nfs/nfs_stress/nfs09.sh | 34 +++++++++++++++++++++++
 2 files changed, 45 insertions(+)
 create mode 100755 testcases/network/nfs/nfs_stress/nfs09.sh

Comments

Petr Vorel Feb. 13, 2024, 4:48 p.m. UTC | #1
Hi Martin,

Merged, thank you!

> Some older kernels have a bug in NFS where the client caches that
> a file does not exist after unsuccessful access to it and then
> does not pass O_TRUNC flag to the server even though the file may
> have been created by another client in the mean time. This may result
> in new data being merged with old file contents instead of replacing
> them.
...

> +++ b/runtest/net.nfs
> @@ -83,6 +83,17 @@ nfs08_v40_ip6t nfs08.sh -6 -v 4 -t tcp
>  nfs08_v41_ip6t nfs08.sh -6 -v 4.1 -t tcp
>  nfs08_v42_ip6t nfs08.sh -6 -v 4.2 -t tcp

> +nfs09_v30_ip4u nfs09.sh -v 3 -t udp
> +nfs09_v30_ip4t nfs09.sh -v 3 -t tcp

For a record, this is the test which fails. And NFSv3 is affected on all
kernels, including latest stable 6.7.4 and 6.8.0-rc1 (both openSUSE packages).

> +nfs09_v40_ip4t nfs09.sh -v 4 -t tcp
> +nfs09_v41_ip4t nfs09.sh -v 4.1 -t tcp
> +nfs09_v42_ip4t nfs09.sh -v 4.2 -t tcp
> +nfs09_v30_ip6u nfs09.sh -6 -v 3 -t udp
> +nfs09_v30_ip6t nfs09.sh -6 -v 3 -t tcp
> +nfs09_v40_ip6t nfs09.sh -6 -v 4 -t tcp
> +nfs09_v41_ip6t nfs09.sh -6 -v 4.1 -t tcp
> +nfs09_v42_ip6t nfs09.sh -6 -v 4.2 -t tcp
...
> +++ b/testcases/network/nfs/nfs_stress/nfs09.sh
...
> +do_test()
> +{
> +	local local_file="testfile"
> +	local remote_file="$(nfs_get_remote_path)/$local_file"
> +	local testmsg='File truncated'
> +	local data
> +
> +	EXPECT_FAIL "ls -l '$local_file'"
> +	tst_rhost_run -c "echo -n 'File rewritten not' >'$remote_file'"
> +	echo -n "$testmsg" >"$local_file"
echo is considered unportable (printf is preferred), but "echo -n" should be
hopefully safe nowadays.

Kind regards,
Petr
diff mbox series

Patch

diff --git a/runtest/net.nfs b/runtest/net.nfs
index 9c1c5c63e..af2a64174 100644
--- a/runtest/net.nfs
+++ b/runtest/net.nfs
@@ -83,6 +83,17 @@  nfs08_v40_ip6t nfs08.sh -6 -v 4 -t tcp
 nfs08_v41_ip6t nfs08.sh -6 -v 4.1 -t tcp
 nfs08_v42_ip6t nfs08.sh -6 -v 4.2 -t tcp
 
+nfs09_v30_ip4u nfs09.sh -v 3 -t udp
+nfs09_v30_ip4t nfs09.sh -v 3 -t tcp
+nfs09_v40_ip4t nfs09.sh -v 4 -t tcp
+nfs09_v41_ip4t nfs09.sh -v 4.1 -t tcp
+nfs09_v42_ip4t nfs09.sh -v 4.2 -t tcp
+nfs09_v30_ip6u nfs09.sh -6 -v 3 -t udp
+nfs09_v30_ip6t nfs09.sh -6 -v 3 -t tcp
+nfs09_v40_ip6t nfs09.sh -6 -v 4 -t tcp
+nfs09_v41_ip6t nfs09.sh -6 -v 4.1 -t tcp
+nfs09_v42_ip6t nfs09.sh -6 -v 4.2 -t tcp
+
 nfslock01_v30_ip4u nfslock01.sh -v 3 -t udp
 nfslock01_v30_ip4t nfslock01.sh -v 3 -t tcp
 nfslock01_v40_ip4t nfslock01.sh -v 4 -t tcp
diff --git a/testcases/network/nfs/nfs_stress/nfs09.sh b/testcases/network/nfs/nfs_stress/nfs09.sh
new file mode 100755
index 000000000..88c1a1ec5
--- /dev/null
+++ b/testcases/network/nfs/nfs_stress/nfs09.sh
@@ -0,0 +1,34 @@ 
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2024 SUSE LLC <mdoucha@suse.cz>
+#
+# DESCRIPTION: Check that stale NFS client cache does not prevent file
+# truncation.
+#
+# 1. Through NFS, access metadata of a file that does not exist
+# 2. Create the file on the remote end (bypassing NFS)
+# 3. Through NFS, try to overwrite the file with shorter data
+
+TST_TESTFUNC="do_test"
+
+do_test()
+{
+	local local_file="testfile"
+	local remote_file="$(nfs_get_remote_path)/$local_file"
+	local testmsg='File truncated'
+	local data
+
+	EXPECT_FAIL "ls -l '$local_file'"
+	tst_rhost_run -c "echo -n 'File rewritten not' >'$remote_file'"
+	echo -n "$testmsg" >"$local_file"
+	data=$(tst_rhost_run -c "cat '$remote_file'")
+
+	if [ "$data" != "$testmsg" ]; then
+		tst_res TFAIL "Wrong file contents, expected '$testmsg', got '$data'"
+	else
+		tst_res TPASS "File was truncated correctly"
+	fi
+}
+
+. nfs_lib.sh
+tst_run