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
110
111
112
113
114
115
116
117
118 | #!/bin/bash
#
## curtin bug http://pad.lv/1443542
## attempt to recreate bug / race between
## <change partition table>
## blockdev --rereadpt
## udevadm settle
## expect finishd
##
## setup creates 3 files:
## zero.img: 1M zeros
## pt1.img: 1M of disk with 1 partition in MBR format
## pt2.img: 1M of disk with 2 partitions in MBR format
##
## Then, loop over:
## for file in zero.img pt1.img pt2.img
## dd if=<file> of=<disk>
## blockdev --rereadpt <disk>
## udevadm settle
## check expected results
##
## we write 'command.log' annotated with messages and uptime
## so that you can see the commands and correlate uptime to udev log
COMMAND_LOG="command.log"
: > "$COMMAND_LOG"
error() { echo "$@" 1>&2; }
rq() {
#run quiet. only show output on error
local out="" ret=0 msg="$1"
shift
echo "$@" >> "$COMMAND_LOG"
out=$("$@" 2>&1)
ret=$?
[ $ret -eq 0 ] && return
error "$out"
error "failed[$ret]: $msg"
return $ret
}
partition() {
echo "2048," | rq partition sfdisk --unit=S --force "$1"
}
partition2() {
local n=$((1024*1024))
rq partition2 sfdisk --unit=S --force "$1" <<EOF
2048,$n
$(($n+2048)),
EOF
}
fail() { msg "$@"; exit 1; }
ptwrite() {
local dev="$1" f="$2" msg="$3" out="" ret=""
rq "ptwrite/zero: $msg" dd bs=1M if=$f of=$dev || return
rq "ptwrite/blockdev: $msg" blockdev --rereadpt "$1" || return
rq "ptwrite/udevsettle: $msg" udevadm settle || return
return 0
}
setup() {
# get 1 MB of partition table
rq mkzero dd if=/dev/zero of=zero.img bs=1M count=1 || fail
rq dopt1 partition "$dev" || fail "partition failed"
udevadm settle &&
blockdev --rereadpt "$dev" &&
udevadm settle || fail "failed getting pt1"
rq getpt1 dd if="$dev" of="pt1.img" bs=1M count=1 || fail
ptwrite "$dev" "zero.img" "wipe0" || fail
rq dopt2 partition2 "$dev" || fail "partition failed"
udevadm settle &&
blockdev --rereadpt "$dev" &&
udevadm settle || fail "failed getting pt2"
rq getpt2 dd if="$dev" of="pt2.img" bs=1M count=1 >/dev/null 2>&1
return 0
}
msg() {
local uptime idle
read uptime idle </proc/uptime
error "[$uptime]" "$@"
echo "# [$uptime]" "$@" >> "$COMMAND_LOG"
}
dev=${1:-/dev/vdb}
pt1=${dev}1
pt2=${dev}2
setup || fail
n=0
while n=$(($n+1)); do
# zero the disk header, and expect all partitions gone
msg "$n: zero"
ptwrite "$dev" "zero.img" "wipe" || fail
[ -b "$pt1" ] && fail "found $pt1 after wipe"
[ -b "$pt2" ] && fail "found $pt2 after wipe"
[ -b "$dev" ] || fail "$dev missing after wipe"
# write pt1 expect only one partition
msg "$n: pt1"
ptwrite "$dev" "pt1.img" "partition 1" || fail
[ -b "$pt1" ] || fail "$pt1 missing after partition1"
[ -b "$pt2" ] && fail "$pt2 found after partition1"
[ -b "${dev}" ] || fail "$dev missing after partition1"
# write pt2 expect 2 partitions
msg "$n: pt2"
ptwrite "$dev" "pt2.img" "partition 2" || fail
[ -b "$pt1" ] || fail "$pt1 missing after partition2"
[ -b "$pt2" ] || fail "$pt2 missing after partition2"
[ -b "${dev}" ] || fail "$dev missing after partition2"
msg "$n: run finished"
done
|