#!/bin/bash function print_usage() { if [ -n "$2" ]; then echo "Error: $2" echo fi echo "Usage: $1 " echo '(The shared directory is the "share" directory in the scratch' \ 'directory)' } shared_dir=$1 if [ -z "$shared_dir" ]; then print_usage "$0" 'Shared dir not given' >&2 exit 1 fi cd "$shared_dir" # FIXME: This should not be necessary, but it is. In order for all # submounts to be proper mount points, we need to visit them. # (Before we visit them, they will not be auto-mounted, and so just # appear as normal directories, with the catch that their st_ino will # be the st_ino of the filesystem they host, while the st_dev will # still be the st_dev of the parent.) # `find` does not work, because it will refuse to touch the mount # points as long as they are not mounted; their st_dev being shared # with the parent and st_ino just being the root node's inode ID # will practically ensure that this node exists elsewhere on the # filesystem, and `find` is required to recognize loops and not to # follow them. # Thus, we have to manually visit all nodes first. mnt_i=0 function recursively_visit() { pushd "$1" >/dev/null for entry in *; do if [[ "$entry" == mnt* ]]; then mnt_i=$((mnt_i + 1)) printf "Triggering auto-mount $mnt_i...\r" fi if [ -d "$entry" ]; then recursively_visit "$entry" fi done popd >/dev/null } recursively_visit . echo if [ -n "$(find -name not-mounted)" ]; then echo "Error: not-mounted files visible on mount points:" >&2 find -name not-mounted >&2 exit 1 fi if [ ! -f some-file -o "$(cat some-file)" != 'root' ]; then echo "Error: Bad file in the share root" >&2 exit 1 fi shopt -s nullglob function check_submounts() { local base_path=$1 for mp in mnt*; do printf "Checking submount %i...\r" "$((${#devs[@]} + 1))" mp_i=$(echo "$mp" | sed -e 's/mnt//') dev=$(stat -c '%D' "$mp") if [ -n "${devs[mp_i]}" ]; then echo "Error: $mp encountered twice" >&2 exit 1 fi devs[mp_i]=$dev pushd "$mp" >/dev/null path="$base_path$mp" while true; do expected_content="$(printf '%s\n%s\n' "$mp_i" "$path")" if [ ! -f some-file ]; then echo "Error: $PWD/some-file does not exist" >&2 exit 1 fi if [ "$(cat some-file)" != "$expected_content" ]; then echo "Error: Bad content in $PWD/some-file:" >&2 echo '--- found ---' cat some-file echo '--- expected ---' echo "$expected_content" exit 1 fi if [ "$(stat -c '%D' some-file)" != "$dev" ]; then echo "Error: $PWD/some-file has the wrong device ID" >&2 exit 1 fi if [ -d sub ]; then if [ "$(stat -c '%D' sub)" != "$dev" ]; then echo "Error: $PWD/some-file has the wrong device ID" >&2 exit 1 fi cd sub path="$path/sub" else if [ -n "$(echo mnt*)" ]; then check_submounts "$path/" fi break fi done popd >/dev/null done } root_dev=$(stat -c '%D' some-file) devs=() check_submounts '' echo reused_devs=$(echo "$root_dev ${devs[@]}" | tr ' ' '\n' | sort | uniq -d) if [ -n "$reused_devs" ]; then echo "Error: Reused device IDs: $reused_devs" >&2 exit 1 fi echo "Test passed for ${#devs[@]} submounts."