[PATCH] test: check a case when a mount is propagated between exiting mounts

From: Andrei Vagin
Date: Tue May 16 2017 - 01:43:02 EST


This test checks two behaviour cases:

When a mount is propagated to a place which is already busy, the new
mount is inserted between parent and old mount.

When a mount that is being unmounted due to propagation has another
mount on top of it, it is replaced by the top mount.

Cc: Shuah Khan <shuah@xxxxxxxxxx>
Signed-off-by: Andrei Vagin <avagin@xxxxxxxxxx>
---
tools/testing/selftests/mount/Makefile | 19 +++--
tools/testing/selftests/mount/test-reparent-mounts | 92 ++++++++++++++++++++++
2 files changed, 105 insertions(+), 6 deletions(-)
create mode 100755 tools/testing/selftests/mount/test-reparent-mounts

diff --git a/tools/testing/selftests/mount/Makefile b/tools/testing/selftests/mount/Makefile
index 9093d7f..5927230 100644
--- a/tools/testing/selftests/mount/Makefile
+++ b/tools/testing/selftests/mount/Makefile
@@ -6,11 +6,18 @@ TEST_GEN_PROGS := unprivileged-remount-test

include ../lib.mk

-override RUN_TESTS := if [ -f /proc/self/uid_map ] ; \
- then \
- ./unprivileged-remount-test ; \
- else \
- echo "WARN: No /proc/self/uid_map exist, test skipped." ; \
- fi
+override define RUN_TESTS
+ if [ -f /proc/self/uid_map ] ; \
+ then \
+ ./unprivileged-remount-test ; \
+ else \
+ echo "WARN: No /proc/self/uid_map exist, test skipped." ; \
+ fi
+ unshare -Urm ./test-reparent-mounts
+ unshare -Urm ./test-reparent-mounts -c
+ unshare -Urm ./test-reparent-mounts -s
+ unshare -Urm ./test-reparent-mounts -s -S
+endef
+
override EMIT_TESTS := echo "$(RUN_TESTS)"

diff --git a/tools/testing/selftests/mount/test-reparent-mounts b/tools/testing/selftests/mount/test-reparent-mounts
new file mode 100755
index 0000000..57ae300
--- /dev/null
+++ b/tools/testing/selftests/mount/test-reparent-mounts
@@ -0,0 +1,92 @@
+#!/bin/sh
+
+# This test checks two following behaviour cases:
+#
+# When a mount is propagated to a place which is already busy, the new mount is
+# inserted between parent and old mount.
+#
+# When a mount that is being unmounted due to propagation has another mount on
+# top of it, it is replaced by the top mount.
+
+ITER=3
+
+set -e
+
+usage()
+{
+ echo " ./$0 [OPTIONS]
+This test checks a case when a mount has to be propagated under another mount.
+ -c - create a mount which is visible only from the second tree
+ -s - make a second tree as a slave to the first one
+ -S - create a sub-mount when the send tree is a slave to the first one
+ -i - how many times to call mount
+"
+}
+
+while getopts "csi:hS" opt; do
+ case $opt in
+ c ) with_child=1;;
+ s ) make_slave=1;;
+ S ) slave_child=1;;
+ i ) ITER=$OPTARG;;
+ h ) usage; exit 0 ;;
+ esac
+done
+
+shift $(($OPTIND - 1))
+
+if [ -n "$1" ]; then
+ usage
+ exit 1
+fi
+
+mount -t tmpfs test /mnt
+mkdir /mnt/main
+mkdir /mnt/second
+mount --bind /mnt/main /mnt/main
+mount --make-shared /mnt/main
+mount --bind /mnt/main /mnt/second
+mkdir -p /mnt/main/sub
+
+if [ -n "$make_slave" ]; then
+ mount --make-slave /mnt/second
+ if [ -n "slave_child" ]; then
+ mount -t tmpfs slave_child /mnt/second/sub/
+ touch /mnt/second/sub/slave_child
+ fi
+fi
+
+if [ -n "$make_slave" ]; then
+ mount --make-slave /mnt/second
+ if [ -n "$slave_child" ]; then
+ mount -t tmpfs test_slave /mnt/second/sub/
+ touch /mnt/second/sub/slave_child
+ fi
+fi
+
+for i in `seq $ITER`; do
+ mount --bind /mnt/main/sub /mnt/main/sub
+done
+
+if [ -n "$with_child" ]; then
+ mkdir /mnt/second/sub/child
+ mount --make-private /mnt/second/sub
+ mount --bind /mnt/second/sub/child /mnt/second/sub/child
+fi
+if [ -n "$slave_child" ]; then
+ test -f /mnt/second/sub/slave_child
+fi
+
+umount /mnt/main/sub
+
+if [ -n "$with_child" ]; then
+ umount /mnt/second/sub/child
+ umount /mnt/second/sub
+fi
+if [ -n "$slave_child" ]; then
+ test -f /mnt/second/sub/slave_child
+ umount /mnt/second/sub
+fi
+
+umount /mnt/second
+umount /mnt/main
--
2.9.3