public inbox for linux-unionfs@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/7] overlay hardlink tests
@ 2017-07-05 12:01 Amir Goldstein
  2017-07-05 12:02 ` [PATCH v3 1/7] overlay/018: re-factor and add to hardlink group Amir Goldstein
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Amir Goldstein @ 2017-07-05 12:01 UTC (permalink / raw)
  To: Eryu Guan; +Cc: Miklos Szeredi, linux-unionfs, fstests

Eryu,

overlay/018 and the three new tests added to overlay/hardlink
group, pass with the current overlayfs-next branch.

overlay/033-034 were added to test a new mechanism of persistent
overlay nlink accounting, that was added along with the fix to
breaking hardlinks on copy up.

overlay/034 passes on current upstream kernel, because the
behavior of breaking hardlinks on copy up cancels the nlink
accounting effects.

Changes from v2:
- Better commentary for overlay/034 and overlay/032
- Increase copy up file size of overlay/032 to 1g

Thanks,
Amir.

Amir Goldstein (7):
  overlay/018: re-factor and add to hardlink group
  overlay/018: print hardlink content to golden output
  overlay/018: test broken hardlinks after mount cycle
  overlay/018: test lower hardlinks re-unite on copy up
  overlay: test concurrent copy up of lower hardlinks
  overlay: test nlink accounting of overlay hardlinks
  overlay: test dropping nlink below zero

 tests/overlay/018     |  60 ++++++++++++++++----
 tests/overlay/018.out |  21 ++++++-
 tests/overlay/032     | 109 ++++++++++++++++++++++++++++++++++++
 tests/overlay/032.out |   4 ++
 tests/overlay/033     | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/overlay/033.out |  69 +++++++++++++++++++++++
 tests/overlay/034     | 107 ++++++++++++++++++++++++++++++++++++
 tests/overlay/034.out |   2 +
 tests/overlay/group   |   5 +-
 9 files changed, 512 insertions(+), 14 deletions(-)
 create mode 100755 tests/overlay/032
 create mode 100644 tests/overlay/032.out
 create mode 100755 tests/overlay/033
 create mode 100644 tests/overlay/033.out
 create mode 100755 tests/overlay/034
 create mode 100644 tests/overlay/034.out

-- 
2.7.4

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v3 1/7] overlay/018: re-factor and add to hardlink group
  2017-07-05 12:01 [PATCH v3 0/7] overlay hardlink tests Amir Goldstein
@ 2017-07-05 12:02 ` Amir Goldstein
  2017-07-05 12:02 ` [PATCH v3 2/7] overlay/018: print hardlink content to golden output Amir Goldstein
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Amir Goldstein @ 2017-07-05 12:02 UTC (permalink / raw)
  To: Eryu Guan; +Cc: Miklos Szeredi, linux-unionfs, fstests

Use helpers to records and check inode numbers so we can repeat
the same test after each hardlink copy up and mount cycle.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 tests/overlay/018   | 33 +++++++++++++++++++++++++--------
 tests/overlay/group |  2 +-
 2 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/tests/overlay/018 b/tests/overlay/018
index 7e47732..527b9d1 100755
--- a/tests/overlay/018
+++ b/tests/overlay/018
@@ -61,25 +61,42 @@ echo "patient zero" >> $lowerdir/foo
 ln $lowerdir/foo $lowerdir/bar
 
 
+# Record inode numbers in format <ino> <nlink>
+function record_ino_nlink()
+{
+	ls -li $FILES | awk '{ print $1, $3 }' > $1
+}
+
+# Check inode numbers match recorded inode numbers
+function check_ino_nlink()
+{
+	before=$1
+	after=$2
+
+	record_ino_nlink $after
+
+	# Test constant stat(2) st_ino/st_nlink -
+	#   Compare before..after - expect silence
+	# We use diff -u so out.bad will tell us which stage failed
+	diff -u $before $after
+}
+
 _scratch_mount
 
 
-rm -f $tmp.before $tmp.after
+rm -f $tmp.*
 
 foo=$SCRATCH_MNT/foo
 bar=$SCRATCH_MNT/bar
 
-# Record inode number and nlink before copy up
-ls -li $foo $bar | awk '{ print $1, $3 }' > $tmp.before
+FILES="$foo $bar"
+
+record_ino_nlink $tmp.before
 
 # Modify content of one of the hardlinks
 echo "mutated" >> $foo
 
-# Record inode number and nlink after copy up
-ls -li $foo $bar | awk '{ print $1, $3 }' > $tmp.after
-
-# Compare ino/nlink before..after - expect silence
-diff $tmp.before $tmp.after
+check_ino_nlink $tmp.before $tmp.after
 
 # Compare content of files - expect silence
 diff $foo $bar
diff --git a/tests/overlay/group b/tests/overlay/group
index 64d200c..28df5b6 100644
--- a/tests/overlay/group
+++ b/tests/overlay/group
@@ -20,7 +20,7 @@
 015 auto quick whiteout
 016 auto quick copyup
 017 auto quick copyup
-018 auto quick copyup
+018 auto quick copyup hardlink
 019 auto stress
 020 auto quick copyup perms
 021 auto quick copyup
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 2/7] overlay/018: print hardlink content to golden output
  2017-07-05 12:01 [PATCH v3 0/7] overlay hardlink tests Amir Goldstein
  2017-07-05 12:02 ` [PATCH v3 1/7] overlay/018: re-factor and add to hardlink group Amir Goldstein
@ 2017-07-05 12:02 ` Amir Goldstein
  2017-07-05 12:02 ` [PATCH v3 3/7] overlay/018: test broken hardlinks after mount cycle Amir Goldstein
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Amir Goldstein @ 2017-07-05 12:02 UTC (permalink / raw)
  To: Eryu Guan; +Cc: Miklos Szeredi, linux-unionfs, fstests

diff may skips comparing content of files with identical st_ino/st_dev.
Overlayfs stat(2) may return same st_dev/st_ino for hardlink copy ups,
but it does not mean that read(2) will return the same content.

Convert the test to output hardlink files content to golden output
instead of using diff.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 tests/overlay/018     | 12 ++++++------
 tests/overlay/018.out |  9 ++++++++-
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/tests/overlay/018 b/tests/overlay/018
index 527b9d1..7570a16 100755
--- a/tests/overlay/018
+++ b/tests/overlay/018
@@ -57,7 +57,7 @@ _scratch_mkfs >>$seqres.full 2>&1
 # Create 2 hardlinked files in lower
 lowerdir=$OVL_BASE_SCRATCH_MNT/$OVL_LOWER
 mkdir -p $lowerdir
-echo "patient zero" >> $lowerdir/foo
+echo "zero" >> $lowerdir/foo
 ln $lowerdir/foo $lowerdir/bar
 
 
@@ -91,16 +91,16 @@ bar=$SCRATCH_MNT/bar
 
 FILES="$foo $bar"
 
+echo "== Before copy up =="
+cat $FILES
 record_ino_nlink $tmp.before
 
 # Modify content of one of the hardlinks
-echo "mutated" >> $foo
+echo "one" >> $foo
 
+echo "== After write one =="
+cat $FILES
 check_ino_nlink $tmp.before $tmp.after
 
-# Compare content of files - expect silence
-diff $foo $bar
-
-echo "Silence is golden"
 status=0
 exit
diff --git a/tests/overlay/018.out b/tests/overlay/018.out
index 8849e30..784e8bc 100644
--- a/tests/overlay/018.out
+++ b/tests/overlay/018.out
@@ -1,2 +1,9 @@
 QA output created by 018
-Silence is golden
+== Before copy up ==
+zero
+zero
+== After write one ==
+zero
+one
+zero
+one
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 3/7] overlay/018: test broken hardlinks after mount cycle
  2017-07-05 12:01 [PATCH v3 0/7] overlay hardlink tests Amir Goldstein
  2017-07-05 12:02 ` [PATCH v3 1/7] overlay/018: re-factor and add to hardlink group Amir Goldstein
  2017-07-05 12:02 ` [PATCH v3 2/7] overlay/018: print hardlink content to golden output Amir Goldstein
@ 2017-07-05 12:02 ` Amir Goldstein
  2017-07-05 12:02 ` [PATCH v3 4/7] overlay/018: test lower hardlinks re-unite on copy up Amir Goldstein
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Amir Goldstein @ 2017-07-05 12:02 UTC (permalink / raw)
  To: Eryu Guan; +Cc: Miklos Szeredi, linux-unionfs, fstests

This test checks if overlayfs hardlinks are preserved across
copy up.  Check if they are preserved also after copy up and
mount cycle.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 tests/overlay/018     | 13 +++++++++++--
 tests/overlay/018.out |  5 +++++
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/tests/overlay/018 b/tests/overlay/018
index 7570a16..46097a9 100755
--- a/tests/overlay/018
+++ b/tests/overlay/018
@@ -96,11 +96,20 @@ cat $FILES
 record_ino_nlink $tmp.before
 
 # Modify content of one of the hardlinks
-echo "one" >> $foo
+# Intentionally modify the last hardlink in $FILES, so after mount cycle
+# when reading the first file in $FILES, last file won't be in inode/dcache
+echo "one" >> $bar
 
 echo "== After write one =="
 cat $FILES
-check_ino_nlink $tmp.before $tmp.after
+check_ino_nlink $tmp.before $tmp.after_one
+
+# Verify that the hardlinks survive a mount cycle
+_scratch_cycle_mount
+
+echo "== After mount cycle =="
+cat $FILES
+check_ino_nlink $tmp.after_one $tmp.after_cycle
 
 status=0
 exit
diff --git a/tests/overlay/018.out b/tests/overlay/018.out
index 784e8bc..5b74ee1 100644
--- a/tests/overlay/018.out
+++ b/tests/overlay/018.out
@@ -7,3 +7,8 @@ zero
 one
 zero
 one
+== After mount cycle ==
+zero
+one
+zero
+one
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 4/7] overlay/018: test lower hardlinks re-unite on copy up
  2017-07-05 12:01 [PATCH v3 0/7] overlay hardlink tests Amir Goldstein
                   ` (2 preceding siblings ...)
  2017-07-05 12:02 ` [PATCH v3 3/7] overlay/018: test broken hardlinks after mount cycle Amir Goldstein
@ 2017-07-05 12:02 ` Amir Goldstein
  2017-07-05 12:02 ` [PATCH v3 5/7] overlay: test concurrent copy up of lower hardlinks Amir Goldstein
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Amir Goldstein @ 2017-07-05 12:02 UTC (permalink / raw)
  To: Eryu Guan; +Cc: Miklos Szeredi, linux-unionfs, fstests

Test that when two lower hardlinks are copied up, they end up
as two upper hardlinks of the same upper inode.

Drop caches before copy up so there is no knowledge of the
copied up hardlink in inode/dcache.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 tests/overlay/018     | 10 ++++++++++
 tests/overlay/018.out |  7 +++++++
 2 files changed, 17 insertions(+)

diff --git a/tests/overlay/018 b/tests/overlay/018
index 46097a9..41855dc 100755
--- a/tests/overlay/018
+++ b/tests/overlay/018
@@ -111,5 +111,15 @@ echo "== After mount cycle =="
 cat $FILES
 check_ino_nlink $tmp.after_one $tmp.after_cycle
 
+# Drop caches to get the copied up hardlink out of cache
+echo 3 > /proc/sys/vm/drop_caches
+
+# Modify content of the other hardlink
+echo "two" >> $foo
+
+echo "== After write two =="
+cat $FILES
+check_ino_nlink $tmp.after_one $tmp.after_two
+
 status=0
 exit
diff --git a/tests/overlay/018.out b/tests/overlay/018.out
index 5b74ee1..adc7f72 100644
--- a/tests/overlay/018.out
+++ b/tests/overlay/018.out
@@ -12,3 +12,10 @@ zero
 one
 zero
 one
+== After write two ==
+zero
+one
+two
+zero
+one
+two
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 5/7] overlay: test concurrent copy up of lower hardlinks
  2017-07-05 12:01 [PATCH v3 0/7] overlay hardlink tests Amir Goldstein
                   ` (3 preceding siblings ...)
  2017-07-05 12:02 ` [PATCH v3 4/7] overlay/018: test lower hardlinks re-unite on copy up Amir Goldstein
@ 2017-07-05 12:02 ` Amir Goldstein
  2017-07-05 12:02 ` [PATCH v3 6/7] overlay: test nlink accounting of overlay hardlinks Amir Goldstein
  2017-07-05 12:02 ` [PATCH v3 7/7] overlay: test dropping nlink below zero Amir Goldstein
  6 siblings, 0 replies; 8+ messages in thread
From: Amir Goldstein @ 2017-07-05 12:02 UTC (permalink / raw)
  To: Eryu Guan; +Cc: Miklos Szeredi, linux-unionfs, fstests

Two tasks make a modification concurrently on two hardlinks of a large
lower inode.  The copy up should be triggered by one of the tasks and the
other should be waiting for copy up to complete.  Both copy up targets
should end up being upper hardlinks and both metadata changes should be
visible in both hardlinks.

With kernel <= v4.12, hardlinks are broken on copy up, meaning that copy up
is performed independetly and the resulting upper copy up targets each have
only one of the the metadata changes visible.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 tests/overlay/032     | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/overlay/032.out |   4 ++
 tests/overlay/group   |   1 +
 3 files changed, 114 insertions(+)
 create mode 100755 tests/overlay/032
 create mode 100644 tests/overlay/032.out

diff --git a/tests/overlay/032 b/tests/overlay/032
new file mode 100755
index 0000000..d986ef2
--- /dev/null
+++ b/tests/overlay/032
@@ -0,0 +1,109 @@
+#! /bin/bash
+# FS QA Test 032
+#
+# Test concurrent copy up of lower hardlinks.
+#
+# Two tasks make a metadata change concurrently on two hardlinks of a large
+# lower inode.  The copy up should be triggers by one of the tasks and the
+# other should be waiting for copy up to complete.  Both copy up targets
+# should end up being upper hardlinks and both metadata changes should be
+# applied.
+#
+#-----------------------------------------------------------------------
+# Copyright (C) 2017 CTERA Networks. All Rights Reserved.
+# Author: Amir Goldstein <amir73il@gmail.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+	cd /
+	rm -f $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+
+# remove previous $seqres.full before test
+rm -f $seqres.full
+
+# real QA test starts here
+_supported_fs overlay
+_supported_os Linux
+_require_scratch
+
+# Remove all files from previous tests
+_scratch_mkfs
+
+# overlay copy_up doesn't deal with sparse file well, holes will be filled by
+# zeros, so if both hardlinks are broken on copy up, we need (2*1G) free space
+# on $OVL_BASE_SCRATCH_MNT.
+_require_fs_space $OVL_BASE_SCRATCH_MNT $((1024*1024*2))
+
+# Create a large file in lower with 2 hardlinks.
+# Make the file have non zero blocks, so copy up won't be able to do
+# a naive sparse file copy up optimization.
+lowerdir=$OVL_BASE_SCRATCH_MNT/$OVL_LOWER
+mkdir -p $lowerdir
+$XFS_IO_PROG -fc "pwrite 1g 4k" $lowerdir/zero >> $seqres.full
+ln $lowerdir/zero $lowerdir/one
+ln $lowerdir/zero $lowerdir/two
+
+_scratch_mount
+
+do_cmd()
+{
+	echo "`date +%T` $1..." >> $seqres.full
+	eval "$1"
+	echo "`date +%T` ...$1" >> $seqres.full
+}
+
+# Perform one modification on each hardlink (size and owner)
+do_cmd "echo >> $SCRATCH_MNT/one" &
+#
+# When hardlinks are broken and overlayfs supports concurrent copy up,
+# $seqres.full will show that file two copy up started ~2s after file one
+# copy up started and ended ~2s after file one copy up ended.
+# With synchronized copy up of lower inodes, $seqres.full will show that
+# file two copy up ended at the same time as file one copy up.
+# Without sparse file copy up optimizations, copy of 1g on a standard disk
+# is expected to take more than 2s.
+# If underlying filesystem supports clone, overlay clone up with take less
+# than 1s and this test will not be doing concurrent copy up of hardlinks,
+# but rather consequent copy up of hardlinks.
+#
+sleep 2
+do_cmd "chown 100 $SCRATCH_MNT/two" &
+
+wait
+
+# Expect all hardlinks to show both metadata modifications (owner and size).
+# List <nlink> <owner> <size> <name>:
+for f in zero one two; do
+	_ls_l -n $SCRATCH_MNT/$f | awk '{ print $2, $3, $5, $9 }' | _filter_scratch
+done
+
+status=0
+exit
diff --git a/tests/overlay/032.out b/tests/overlay/032.out
new file mode 100644
index 0000000..a4cdc13
--- /dev/null
+++ b/tests/overlay/032.out
@@ -0,0 +1,4 @@
+QA output created by 032
+3 100 1073745921 SCRATCH_MNT/zero
+3 100 1073745921 SCRATCH_MNT/one
+3 100 1073745921 SCRATCH_MNT/two
diff --git a/tests/overlay/group b/tests/overlay/group
index 28df5b6..2baba3a 100644
--- a/tests/overlay/group
+++ b/tests/overlay/group
@@ -34,3 +34,4 @@
 029 auto quick
 030 auto quick perms
 031 auto quick whiteout
+032 auto quick copyup hardlink
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 6/7] overlay: test nlink accounting of overlay hardlinks
  2017-07-05 12:01 [PATCH v3 0/7] overlay hardlink tests Amir Goldstein
                   ` (4 preceding siblings ...)
  2017-07-05 12:02 ` [PATCH v3 5/7] overlay: test concurrent copy up of lower hardlinks Amir Goldstein
@ 2017-07-05 12:02 ` Amir Goldstein
  2017-07-05 12:02 ` [PATCH v3 7/7] overlay: test dropping nlink below zero Amir Goldstein
  6 siblings, 0 replies; 8+ messages in thread
From: Amir Goldstein @ 2017-07-05 12:02 UTC (permalink / raw)
  To: Eryu Guan; +Cc: Miklos Szeredi, linux-unionfs, fstests

nlink of overlay inode should account for the union of lower
and upper hardlinks.

persistent overlay union nlink is stored in an extended attribute
on the upper inode.

In order to test persistent overlay nlink accounting, the test is
repeated with both warm and cold dentry/inode cache.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 tests/overlay/033     | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/overlay/033.out |  69 +++++++++++++++++++++++
 tests/overlay/group   |   1 +
 3 files changed, 219 insertions(+)
 create mode 100755 tests/overlay/033
 create mode 100644 tests/overlay/033.out

diff --git a/tests/overlay/033 b/tests/overlay/033
new file mode 100755
index 0000000..743edc8
--- /dev/null
+++ b/tests/overlay/033
@@ -0,0 +1,149 @@
+#! /bin/bash
+# FS QA Test 033
+#
+# Test nlink accounting of overlay hardlinks.
+#
+# nlink of overlay inode should account for the union of lower and upper
+# hardlinks.
+#
+#-----------------------------------------------------------------------
+# Copyright (C) 2017 CTERA Networks. All Rights Reserved.
+# Author: Amir Goldstein <amir73il@gmail.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+	cd /
+	rm -f $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+
+# remove previous $seqres.full before test
+rm -f $seqres.full
+
+# real QA test starts here
+_supported_fs overlay
+_supported_os Linux
+_require_scratch
+
+report_nlink()
+{
+	when=$1
+
+	[ $DCACHETEMP != cold ] || echo 2 > /proc/sys/vm/drop_caches
+
+	# check nlink with warm dcache after overlay modification
+	echo "== $when - $DCACHETEMP dcache =="
+	for f in $HARDLINKS; do
+		_ls_l $SCRATCH_MNT/$f | awk '{ print $2, $9 }' | _filter_scratch
+	done
+}
+
+# Create lower hardlinks
+create_hardlinks()
+{
+	lowerdir=$OVL_BASE_SCRATCH_MNT/$OVL_LOWER
+	mkdir -p $lowerdir
+	touch $lowerdir/0
+	ln $lowerdir/0 $lowerdir/1
+	ln $lowerdir/0 $lowerdir/2
+	ln $lowerdir/0 $lowerdir/3
+}
+
+test_hardlinks()
+{
+	HARDLINKS=`seq 0 3`
+	report_nlink "all lower"
+
+	# Unlink lower hardlink
+	rm $SCRATCH_MNT/0
+	HARDLINKS=`seq 1 3`
+	report_nlink "unlink lower"
+
+	# Link to lower hardlink
+	ln $SCRATCH_MNT/3 $SCRATCH_MNT/4
+	HARDLINKS=`seq 1 4`
+	report_nlink "link lower"
+
+	# Link to upper hardlink
+	ln $SCRATCH_MNT/4 $SCRATCH_MNT/5
+	HARDLINKS=`seq 1 5`
+	report_nlink "link upper"
+
+	# Rename over lower hardlink
+	touch $SCRATCH_MNT/new
+	mv $SCRATCH_MNT/new $SCRATCH_MNT/1
+	HARDLINKS=`seq 2 5`
+	report_nlink "cover lower"
+
+	# Unlink upper hardlink
+	rm $SCRATCH_MNT/5
+	HARDLINKS=`seq 2 4`
+	report_nlink "unlink upper"
+
+	# Rename over upper hardlink
+	touch $SCRATCH_MNT/new
+	mv $SCRATCH_MNT/new $SCRATCH_MNT/4
+	HARDLINKS=`seq 2 3`
+	report_nlink "cover upper"
+
+	# Unlink last upper (union still has one lower)
+	rm $SCRATCH_MNT/3
+	HARDLINKS=2
+	report_nlink "unlink last upper"
+
+	# Unlink last lower and drop union nlink to zero (and hopefully not below)
+	rm $SCRATCH_MNT/2
+
+	# Verify that orphan index is cleaned when dropping nlink to zero
+	ls $OVL_BASE_SCRATCH_MNT/$OVL_WORK/index 2>/dev/null
+}
+
+# Remove all files from previous tests
+_scratch_mkfs
+
+# Create lower hardlinks
+create_hardlinks
+
+_scratch_mount
+# Test hardlinks with warm dcache
+DCACHETEMP=warm
+test_hardlinks
+
+# Reset to lower hardlinks
+_scratch_unmount
+_scratch_mkfs
+create_hardlinks
+_scratch_mount
+
+# Test hardlinks with cold dcache
+DCACHETEMP=cold
+test_hardlinks
+
+status=0
+exit
diff --git a/tests/overlay/033.out b/tests/overlay/033.out
new file mode 100644
index 0000000..506ccc1
--- /dev/null
+++ b/tests/overlay/033.out
@@ -0,0 +1,69 @@
+QA output created by 033
+== all lower - warm dcache ==
+4 SCRATCH_MNT/0
+4 SCRATCH_MNT/1
+4 SCRATCH_MNT/2
+4 SCRATCH_MNT/3
+== unlink lower - warm dcache ==
+3 SCRATCH_MNT/1
+3 SCRATCH_MNT/2
+3 SCRATCH_MNT/3
+== link lower - warm dcache ==
+4 SCRATCH_MNT/1
+4 SCRATCH_MNT/2
+4 SCRATCH_MNT/3
+4 SCRATCH_MNT/4
+== link upper - warm dcache ==
+5 SCRATCH_MNT/1
+5 SCRATCH_MNT/2
+5 SCRATCH_MNT/3
+5 SCRATCH_MNT/4
+5 SCRATCH_MNT/5
+== cover lower - warm dcache ==
+4 SCRATCH_MNT/2
+4 SCRATCH_MNT/3
+4 SCRATCH_MNT/4
+4 SCRATCH_MNT/5
+== unlink upper - warm dcache ==
+3 SCRATCH_MNT/2
+3 SCRATCH_MNT/3
+3 SCRATCH_MNT/4
+== cover upper - warm dcache ==
+2 SCRATCH_MNT/2
+2 SCRATCH_MNT/3
+== unlink last upper - warm dcache ==
+1 SCRATCH_MNT/2
+== all lower - cold dcache ==
+4 SCRATCH_MNT/0
+4 SCRATCH_MNT/1
+4 SCRATCH_MNT/2
+4 SCRATCH_MNT/3
+== unlink lower - cold dcache ==
+3 SCRATCH_MNT/1
+3 SCRATCH_MNT/2
+3 SCRATCH_MNT/3
+== link lower - cold dcache ==
+4 SCRATCH_MNT/1
+4 SCRATCH_MNT/2
+4 SCRATCH_MNT/3
+4 SCRATCH_MNT/4
+== link upper - cold dcache ==
+5 SCRATCH_MNT/1
+5 SCRATCH_MNT/2
+5 SCRATCH_MNT/3
+5 SCRATCH_MNT/4
+5 SCRATCH_MNT/5
+== cover lower - cold dcache ==
+4 SCRATCH_MNT/2
+4 SCRATCH_MNT/3
+4 SCRATCH_MNT/4
+4 SCRATCH_MNT/5
+== unlink upper - cold dcache ==
+3 SCRATCH_MNT/2
+3 SCRATCH_MNT/3
+3 SCRATCH_MNT/4
+== cover upper - cold dcache ==
+2 SCRATCH_MNT/2
+2 SCRATCH_MNT/3
+== unlink last upper - cold dcache ==
+1 SCRATCH_MNT/2
diff --git a/tests/overlay/group b/tests/overlay/group
index 2baba3a..35cd5a5 100644
--- a/tests/overlay/group
+++ b/tests/overlay/group
@@ -35,3 +35,4 @@
 030 auto quick perms
 031 auto quick whiteout
 032 auto quick copyup hardlink
+033 auto quick copyup hardlink
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 7/7] overlay: test dropping nlink below zero
  2017-07-05 12:01 [PATCH v3 0/7] overlay hardlink tests Amir Goldstein
                   ` (5 preceding siblings ...)
  2017-07-05 12:02 ` [PATCH v3 6/7] overlay: test nlink accounting of overlay hardlinks Amir Goldstein
@ 2017-07-05 12:02 ` Amir Goldstein
  6 siblings, 0 replies; 8+ messages in thread
From: Amir Goldstein @ 2017-07-05 12:02 UTC (permalink / raw)
  To: Eryu Guan; +Cc: Miklos Szeredi, linux-unionfs, fstests

nlink of overlay inode could be dropped indefinitely by adding
un-accounted lower hardlinks underneath a mounted overlay and
trying to remove them.

The simplest way to understand this test is this:
Imagine that you have a tool (e.g. xfs_db) with which you can add
hardlinks, without changing the value of nlink stored on-disk for the
inode. This is exactly what this test does when it adds lower hardlinks
underneath a mounted overlay.

Commit 5f8415d6b87e ("ovl: persistent overlay inode nlink for indexed
inodes") fixes this issue, although the issue was never exposed in any
released kernel.

With overlayfs indexed copy up and without the fix, the test triggers
WARN_ON(inode->i_nlink == 0) in drop_link().

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 tests/overlay/034     | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/overlay/034.out |   2 +
 tests/overlay/group   |   1 +
 3 files changed, 110 insertions(+)
 create mode 100755 tests/overlay/034
 create mode 100644 tests/overlay/034.out

diff --git a/tests/overlay/034 b/tests/overlay/034
new file mode 100755
index 0000000..2b4ca73
--- /dev/null
+++ b/tests/overlay/034
@@ -0,0 +1,107 @@
+#! /bin/bash
+# FS QA Test 034
+#
+# Test overlay nlink when adding lower hardlinks.
+#
+# nlink of overlay inode could be dropped indefinitely by adding
+# unaccounted lower hardlinks underneath a mounted overlay and
+# trying to remove them.
+#
+# The simplest way to understand this test is this:
+# Imagine that you have a tool (e.g. xfs_db) with which you can add
+# hardlinks, without changing the value of nlink stored on-disk for the
+# inode. This is exactly what this test does when it adds lower hardlinks
+# underneath a mounted overlay.
+#
+# Commit 5f8415d6b87e ("ovl: persistent overlay inode nlink for indexed
+# inodes") fixes this issue, although the issue was never exposed in any
+# released kernel.
+#
+# With overlayfs indexed copy up and without the fix, the test triggers
+# WARN_ON(inode->i_nlink == 0) in drop_link().
+#
+#-----------------------------------------------------------------------
+# Copyright (C) 2017 CTERA Networks. All Rights Reserved.
+# Author: Amir Goldstein <amir73il@gmail.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+	cd /
+	rm -f $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+
+# remove previous $seqres.full before test
+rm -f $seqres.full
+
+# real QA test starts here
+_supported_fs overlay
+_supported_os Linux
+_require_scratch
+
+# Remove all files from previous tests
+_scratch_mkfs
+
+# Create lower hardlink
+lowerdir=$OVL_BASE_SCRATCH_MNT/$OVL_LOWER
+mkdir -p $lowerdir
+touch $lowerdir/0
+ln $lowerdir/0 $lowerdir/1
+
+_scratch_mount
+
+# Copy up lower hardlink - overlay inode nlink 2 is copied from lower
+touch $SCRATCH_MNT/0
+
+# Add lower hardlinks while overlay is mounted - overlay inode nlink
+# is not being updated
+ln $lowerdir/0 $lowerdir/2
+ln $lowerdir/0 $lowerdir/3
+
+# Unlink the 2 un-accounted lower hardlinks - overlay inode nlinks
+# drops 2 and may reach 0 if the situation is not detected
+rm $SCRATCH_MNT/2
+rm $SCRATCH_MNT/3
+
+# Check if getting ENOENT when trying to link !I_LINKABLE with nlink 0
+ln $SCRATCH_MNT/0 $SCRATCH_MNT/4
+
+# Unlink all hardlinks - if overlay inode nlink is 0, this will trigger
+# WARN_ON() in drop_nlink()
+rm $SCRATCH_MNT/0
+rm $SCRATCH_MNT/1
+rm $SCRATCH_MNT/4
+
+# Verify that orphan index is cleaned on mount
+_scratch_cycle_mount
+ls $OVL_BASE_SCRATCH_MNT/$OVL_WORK/index 2>/dev/null
+
+echo "Silence is golden"
+status=0
+exit
diff --git a/tests/overlay/034.out b/tests/overlay/034.out
new file mode 100644
index 0000000..4c8873c
--- /dev/null
+++ b/tests/overlay/034.out
@@ -0,0 +1,2 @@
+QA output created by 034
+Silence is golden
diff --git a/tests/overlay/group b/tests/overlay/group
index 35cd5a5..b55ed0c 100644
--- a/tests/overlay/group
+++ b/tests/overlay/group
@@ -36,3 +36,4 @@
 031 auto quick whiteout
 032 auto quick copyup hardlink
 033 auto quick copyup hardlink
+034 auto quick copyup hardlink
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-07-05 12:02 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-07-05 12:01 [PATCH v3 0/7] overlay hardlink tests Amir Goldstein
2017-07-05 12:02 ` [PATCH v3 1/7] overlay/018: re-factor and add to hardlink group Amir Goldstein
2017-07-05 12:02 ` [PATCH v3 2/7] overlay/018: print hardlink content to golden output Amir Goldstein
2017-07-05 12:02 ` [PATCH v3 3/7] overlay/018: test broken hardlinks after mount cycle Amir Goldstein
2017-07-05 12:02 ` [PATCH v3 4/7] overlay/018: test lower hardlinks re-unite on copy up Amir Goldstein
2017-07-05 12:02 ` [PATCH v3 5/7] overlay: test concurrent copy up of lower hardlinks Amir Goldstein
2017-07-05 12:02 ` [PATCH v3 6/7] overlay: test nlink accounting of overlay hardlinks Amir Goldstein
2017-07-05 12:02 ` [PATCH v3 7/7] overlay: test dropping nlink below zero Amir Goldstein

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox