summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xold-school/grok-block4
-rw-r--r--old-school/mdadm-dup.sh165
2 files changed, 168 insertions, 1 deletions
diff --git a/old-school/grok-block b/old-school/grok-block
index 62b063f..3f61c4a 100755
--- a/old-school/grok-block
+++ b/old-school/grok-block
@@ -172,7 +172,9 @@ then
172 # Recognize and mount the Samizdat 172 # Recognize and mount the Samizdat
173 if ! mountpoint -q /cdrom; then 173 if ! mountpoint -q /cdrom; then
174 mkdir -p /cdrom 174 mkdir -p /cdrom
175 (retry_mount -t iso9660 -r "$DEVNAME" /cdrom && bootdone samizdat-cdrom) & 175 . mdadm-dup.sh
176 mount_cdrom "$DEVNAME" && bootdone samizdat-cdrom
177# (retry_mount -t iso9660 -r "$DEVNAME" /cdrom && bootdone samizdat-cdrom) &
176 fi 178 fi
177else 179else
178 grok_block & 180 grok_block &
diff --git a/old-school/mdadm-dup.sh b/old-school/mdadm-dup.sh
new file mode 100644
index 0000000..27a39ca
--- /dev/null
+++ b/old-school/mdadm-dup.sh
@@ -0,0 +1,165 @@
1dm_snapshot()
2{
3 # TODO: eliminate duplication; this function exists elsewhere in a less generalized form
4 local ro_file rw_file cutoff_size
5 ro_file=$1
6 rw_file=$2
7 cutoff_size=$3
8
9 local ro_dev rw_dev size new_dev_name persist chunksize
10
11 if [ -b "$ro_file" ];
12 then ro_dev=$ro_file
13 else ro_dev=$(LoSetup -r -f --show "$ro_file") || return
14 fi
15
16 if [ -b "$rw_file" ];
17 then rw_dev=$rw_file
18 else rw_dev=$(LoSetup -f --show "$rw_file") || return
19 fi
20
21 if [ "$cutoff_size" -a "$cutoff_size" -gt 0 ]; then
22 size=$cutoff_size
23 else
24 size=$(blockdev --getsz "$ro_dev") || return
25 fi
26
27 new_dev_name=${ro_dev##*/}
28 persist=p
29 chunksize=16
30 dmsetup create "$new_dev_name" --table "0 $size snapshot $ro_dev $rw_dev $persist $chunksize" || return
31 wait_for_dm_device /dev/mapper/"$new_dev_name";
32 echo /dev/mapper/"$new_dev_name"
33}
34
35dm_snapshot_teardown()
36{
37 local dev="$1"
38 case "$dev" in
39 /dev/dm-*)
40 dmsetup table "$dev" | (
41 read _ _ snapshot ro_dev rw_dev _ _
42 [ "$snapshot" = snapshot ] || exit 1
43 dmsetup remove "$dev" || exit 1
44 # errors ignored because the loop dev can be automatically removed upon disuse already
45 losetup -d /dev/block/"$rw_dev" || true
46 eject /dev/block/"$ro_dev" || exit 1
47 ) || return
48 ;;
49 *) return 1 ;;
50 esac
51}
52
53wait_for_dm_device()
54{
55 # TODO: improve
56 while ! [ -e "$1" ]; do
57 sleep 1
58 done
59}
60
61mount_cdrom()
62{
63 local cdrom_dev="$1"
64
65 local sectors md_dev=/dev/md0 cdrom_rw_file=/"${cdrom_dev##*/}".rw
66
67 sectors=$(get_cdrom_sizelimit "$cdrom_dev") || return
68
69 # TODO: do we even need this backing file? We do need to trick mdadm into
70 # thinking that this is a RW device, but previously we got away with just
71 # creating a loopback device.
72 dd if=/dev/zero of="$cdrom_rw_file" bs=1K count=32 || return
73 cdrom_rw_dev=$(dm_snapshot "$cdrom_dev" "$cdrom_rw_file" "$sectors") || return
74 mdadm_dup "$cdrom_rw_dev" "$md_dev" "$sectors" || return
75 mount -t iso9660 -r $md_dev /cdrom
76}
77
78get_cdrom_sizelimit()
79{
80 # returns 512-byte sectors
81 local dev="$1" sectors
82 sectors=$(blockdev --getsz "$dev") || return
83
84 # Check if we can read the last 8 sectors. With a TAO CDROM, we can't --
85 # these sectors are faux, and not part of the ISO fs. If mdadm is allowed to
86 # read them, it will mark the device failed.
87 if dd count=2 if="$dev" bs=2048 skip=$((sectors/4 - 2)) of=/dev/null 2>/dev/null; then
88 echo $sectors
89 else
90 echo $((sectors - 8))
91 fi
92}
93
94mdadm_dup()
95{
96 local input_dev="$1" md_name="$2" sectors="$3"
97
98 mdadm --build $md_name ${sectors:+--size=$((sectors / 2))} \
99 --level=1 --raid-devices=1 --force --write-mostly "$input_dev" || return
100}
101
102
103mdadm_subdevices()
104{
105 local md_dev="$1"
106 mdadm -D "$md_dev" -Y | sed -ne 's/MD_DEVICE_.*_DEV=//p'
107}
108
109Mdadm()
110{
111 mdadm "$@"
112 # r=$?
113 # mdadm -D "$1"
114 # sleep 2
115 # return $r
116}
117
118mdadm_copy_eject() # NOT INITRD; uses non-busybox "losetup"
119{
120 local md_dev="$1" output_file="$2"
121
122 [ -b "$md_dev" ] || return
123 [ ! -e "$output_file" ] || return
124
125 local output_dev sectors
126
127 old_subdev=$(mdadm_subdevices "$md_dev"|head -n1) || return
128 [ -b "$old_subdev" ] || return
129 sectors=$(blockdev --getsz "$md_dev") || return
130
131 truncate -s $((sectors * 512)) "$output_file" || return
132 output_dev=$(losetup -f --show "$output_file") || return
133
134 Mdadm "$md_dev" --add "$output_dev" || return
135 Mdadm "$md_dev" --grow -n2 || return
136
137 mdadm_wait_remove "$md_dev" "$old_subdev" || return
138
139 Mdadm "$md_dev" --grow -n1 --force || return
140 dm_snapshot_teardown "$old_subdev"
141}
142
143mdadm_wait_remove()
144{
145 # We should perhaps use mdadm --monitor's RebuildFinished event.
146
147 local dev="$1" disk="$2" tries
148 if ! mdadm --wait "$dev"; then
149 tries=1000
150 while ! mdadm --detail --test "$dev"; do
151 [ $tries -gt 0 ] || return 1
152 sleep 1
153 tries=$((tries-1))
154 done
155 fi
156
157 mdadm "$dev" --fail "$disk" || return 1
158 tries=100
159 while ! mdadm "$dev" --remove "$disk"; do
160 [ $tries -gt 0 ] || return 1
161 sleep 1
162 tries=$((tries-1))
163 done
164 return 0
165}