1#!/bin/bash
2
3mount_count=128
4
5function print_usage()
6{
7    if [ -n "$2" ]; then
8        echo "Error: $2"
9        echo
10    fi
11    echo "Usage: $1 <scratch dir> [seed]"
12    echo "(If no seed is given, it will be randomly generated.)"
13}
14
15scratch_dir=$1
16if [ -z "$scratch_dir" ]; then
17    print_usage "$0" 'No scratch dir given' >&2
18    exit 1
19fi
20
21if [ ! -d "$scratch_dir" ]; then
22    print_usage "$0" "$scratch_dir is not a directory" >&2
23    exit 1
24fi
25
26seed=$2
27if [ -z "$seed" ]; then
28    seed=$RANDOM
29fi
30RANDOM=$seed
31
32echo "Seed: $seed"
33
34set -e
35shopt -s nullglob
36
37cd "$scratch_dir"
38if [ -d share ]; then
39    echo 'Error: This directory seems to be in use already' >&2
40    exit 1
41fi
42
43for ((i = 0; i < $mount_count; i++)); do
44    printf "Setting up fs %i/%i...\r" "$((i + 1))" "$mount_count"
45
46    rm -f fs$i.img
47    truncate -s 512M fs$i.img
48    mkfs.xfs -q fs$i.img
49    devs[i]=$(sudo losetup -f --show fs$i.img)
50done
51echo
52
53top_level_mounts=$((RANDOM % mount_count + 1))
54
55mkdir -p share
56echo 'root' > share/some-file
57
58for ((i = 0; i < $top_level_mounts; i++)); do
59    printf "Mounting fs %i/%i...\r" "$((i + 1))" "$mount_count"
60
61    mkdir -p share/mnt$i
62    touch share/mnt$i/not-mounted
63    sudo mount "${devs[i]}" share/mnt$i
64    sudo chown "$(id -u):$(id -g)" share/mnt$i
65
66    pushd share/mnt$i >/dev/null
67    path=mnt$i
68    nesting=$((RANDOM % 4))
69    for ((j = 0; j < $nesting; j++)); do
70        cat > some-file <<EOF
71$i
72$path
73EOF
74        mkdir sub
75        cd sub
76        path="$path/sub"
77    done
78cat > some-file <<EOF
79$i
80$path
81EOF
82    popd >/dev/null
83done
84
85for ((; i < $mount_count; i++)); do
86    printf "Mounting fs %i/%i...\r" "$((i + 1))" "$mount_count"
87
88    mp_i=$((i % top_level_mounts))
89
90    pushd share/mnt$mp_i >/dev/null
91    path=mnt$mp_i
92    while true; do
93        sub_mp="$(echo mnt*)"
94        if cd sub 2>/dev/null; then
95            path="$path/sub"
96        elif [ -n "$sub_mp" ] && cd "$sub_mp" 2>/dev/null; then
97            path="$path/$sub_mp"
98        else
99            break
100        fi
101    done
102    mkdir mnt$i
103    touch mnt$i/not-mounted
104    sudo mount "${devs[i]}" mnt$i
105    sudo chown "$(id -u):$(id -g)" mnt$i
106
107    cd mnt$i
108    path="$path/mnt$i"
109    nesting=$((RANDOM % 4))
110    for ((j = 0; j < $nesting; j++)); do
111        cat > some-file <<EOF
112$i
113$path
114EOF
115        mkdir sub
116        cd sub
117        path="$path/sub"
118    done
119    cat > some-file <<EOF
120$i
121$path
122EOF
123    popd >/dev/null
124done
125echo
126
127echo 'Done.'
128