1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
|
summary: observe documented semantics of the bind mount operation
details: |
The kernel uses the following documented semantics for how bind-mount is
interpreted from the point of view of propagation settings. The table is
reproduced below for convenience:
--------------------------------------------------------------------------
| BIND MOUNT OPERATION |
|************************************************************************|
|source(A)->| shared | private | slave | unbindable |
| dest(B) | | | | |
| | | | | | |
| v | | | | |
|************************************************************************|
| shared | shared | shared | shared & slave | invalid |
| | | | | |
|non-shared| shared | private | slave | invalid |
**************************************************************************
Given a mount a and b that are prepared according to the data in the table,
what is the outcome of the mount --bind a b? What kind of propagation
settings are applied to the new mount at b?
environment:
# Source and destination are both shared.
ALTER_A/shared_to_shared: --make-shared
ALTER_B/shared_to_shared: --make-shared
EXPECTED_A/shared_to_shared: "/ /A shared:42 - tmpfs-A"
EXPECTED_B/shared_to_shared: "/ /B shared:43 - tmpfs-B"
# This test shows that the peer group of the new bind mount is taken from
# the source. One can think of this as a bind-mount that is followed by
# --make-shared. Because B/b is already shared then nothing changes and no
# new group is allocated.
EXPECTED_BIND/shared_to_shared: "/a /B/b shared:42 - tmpfs-A"
# Source is shared, destination is private.
ALTER_A/shared_to_private: --make-shared
ALTER_B/shared_to_private: --make-private
EXPECTED_A/shared_to_private: "/ /A shared:42 - tmpfs-A"
EXPECTED_B/shared_to_private: "/ /B - tmpfs-B"
EXPECTED_BIND/shared_to_private: "/a /B/b shared:42 - tmpfs-A"
# Source is private, destination is shared.
# NOTE: shared:42 is the /B mount that is created by mount --make-shared B.
# Here we are seeing that B/b is another shared mount but the underlying
# filesystem is tmpfs-A.
ALTER_A/private_to_shared: --make-private
ALTER_B/private_to_shared: --make-shared
EXPECTED_A/private_to_shared: "/ /A - tmpfs-A"
EXPECTED_B/private_to_shared: "/ /B shared:42 - tmpfs-B"
# This test shows that the peer group of the new bind mount is a new
# allocated group. One can think of this as a bind-mount followed by
# --make-shared. Because B/b is private, a new group _is_ allocated.
EXPECTED_BIND/private_to_shared: "/a /B/b shared:43 - tmpfs-A"
# Source and destination are both private.
ALTER_A/private_to_private: --make-private
ALTER_B/private_to_private: --make-private
EXPECTED_A/private_to_private: "/ /A - tmpfs-A"
EXPECTED_B/private_to_private: "/ /B - tmpfs-B"
EXPECTED_BIND/private_to_private: "/a /B/b - tmpfs-A"
# Source is a slave, destination is shared.
ALTER_A/slave_to_shared: --make-slave
ALTER_B/slave_to_shared: --make-shared
EXPECTED_A/slave_to_shared: "/ /A master:42 - tmpfs-A"
EXPECTED_B/slave_to_shared: "/ /B shared:43 - tmpfs-B"
# This test shows that the new bind-mount B/b becomes shared (shared:44),
# exactly as in the private_to_shared test, but also retains the slave peer
# group from A (master:42)
EXPECTED_BIND/slave_to_shared: "/a /B/b shared:44 master:42 - tmpfs-A"
# Source is a slave, destination is private.
ALTER_A/slave_to_private: --make-slave
ALTER_B/slave_to_private: --make-private
EXPECTED_A/slave_to_private: "/ /A master:42 - tmpfs-A"
EXPECTED_B/slave_to_private: "/ /B - tmpfs-B"
EXPECTED_BIND/slave_to_private: "/a /B/b master:42 - tmpfs-A"
prepare: |
mkdir A
mount -t tmpfs tmpfs-A A
# If A needs to be slave then we need some help to allow it to be a slave.
if [ "$ALTER_A" = --make-slave ]; then
mount --make-shared A
mkdir A-helper
mount --bind A A-helper
fi
mount "$ALTER_A" A
mkdir B
mount -t tmpfs tmpfs-B B
mount "$ALTER_B" B
mkdir A/a B/b
mount --bind A/a B/b
restore: |
umount -l A
rmdir A
umount -l B/b
umount -l B
rmdir B
if [ -d A-helper ]; then
umount -l A-helper
rmdir A-helper
fi
debug: |
cat /proc/self/mountinfo
execute: |
grep -F "$SPREAD_TASK" /proc/self/mountinfo | ../rewrite-peer-groups.awk | ../root-dir-mount-point-optional-fields-and-source.awk | grep -v A-helper >actual.txt
echo "Expected A mount is..."
test "$(tail -n 3 actual.txt | head -n 1)" = "${EXPECTED_A-}"
echo "Expected B mount is..."
test "$(tail -n 2 actual.txt | head -n 1)" = "${EXPECTED_B-}"
echo "Expected A/a -> B/b bind-mount is..."
test "$(tail -n 1 actual.txt)" = "${EXPECTED_BIND-}"
|