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 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
|
#!/bin/bash
source "$TEST_TOP/common"
check_prereq mkfs.btrfs
check_prereq btrfs
check_prereq btrfstune
check_prereq btrfs-image
check_global_prereq udevadm
setup_root_helper
prepare_test_dev
if [ ! -f /sys/fs/btrfs/features/metadata_uuid ] ; then
_not_run "METADATA_UUID feature not supported"
fi
read_fsid() {
local dev="$1"
echo $(run_check_stdout $SUDO_HELPER "$TOP/btrfs" inspect-internal \
dump-super "$dev" | awk '/fsid/ {print $2}' | head -n 1)
}
read_metadata_uuid() {
local dev="$1"
echo $(run_check_stdout $SUDO_HELPER "$TOP/btrfs" inspect-internal \
dump-super "$dev" | awk '/metadata_uuid/ {print $2}')
}
check_btrfstune() {
local fsid
_log "Checking btrfstune logic"
# test with random uuid
run_check $SUDO_HELPER "$TOP/btrfstune" -m "$TEST_DEV"
# check that specific uuid can set
run_check $SUDO_HELPER "$TOP/btrfstune" -M d88c8333-a652-4476-b225-2e9284eb59f1 "$TEST_DEV"
# test that having seed on already changed device doesn't work
run_mustfail "Managed to set seed on metadata uuid fs" \
$SUDO_HELPER "$TOP/btrfstune" -S 1 "$TEST_DEV"
# test that setting both seed and -m|M is forbidden
run_check_mkfs_test_dev
run_mustfail "Succeeded setting seed and changing fs uuid" \
$SUDO_HELPER "$TOP/btrfstune" -S 1 -m "$TEST_DEV"
# test that having -m|-M on seed device is forbidden
run_check_mkfs_test_dev
run_check $SUDO_HELPER "$TOP/btrfstune" -S 1 "$TEST_DEV"
run_mustfail "Succeeded changing fsid on a seed device" \
$SUDO_HELPER "$TOP/btrfstune" -m "$TEST_DEV"
# test that using -U|-u on an fs with METADATA_UUID flag is forbidden
run_check_mkfs_test_dev
run_check $SUDO_HELPER "$TOP/btrfstune" -m "$TEST_DEV"
run_mustfail "Succeeded triggering FSID rewrite while METADATA_UUID is active" \
$SUDO_HELPER "$TOP/btrfstune" -u "$TEST_DEV"
}
check_dump_super_output() {
local fsid
local metadata_uuid
local dev_item_match
local old_metadata_uuid
_log "Checking dump-super output"
# assert that metadata/fsid match on non-changed fs
fsid=$(read_fsid "$TEST_DEV")
metadata_uuid=$(read_metadata_uuid "$TEST_DEV")
[ "$fsid" = "$metadata_uuid" ] || _fail "fsid ("$fsid") doesn't match metadata_uuid ("$metadata_uuid")"
dev_item_match=$(run_check_stdout $SUDO_HELPER "$TOP/btrfs" inspect-internal dump-super \
"$TEST_DEV" | awk '/dev_item.fsid/ {print $3}')
[ $dev_item_match = "[match]" ] || _fail "dev_item.fsid doesn't match on non-metadata uuid fs"
_log "Checking output after fsid change"
# change metadatauuid and ensure everything in the output is still correct
old_metadata_uuid=$metadata_uuid
run_check $SUDO_HELPER "$TOP/btrfstune" -M d88c8333-a652-4476-b225-2e9284eb59f1 "$TEST_DEV"
fsid=$(read_fsid "$TEST_DEV")
metadata_uuid=$(read_metadata_uuid "$TEST_DEV")
dev_item_match=$(run_check_stdout $SUDO_HELPER "$TOP/btrfs" \
inspect-internal dump-super "$TEST_DEV" | awk '/dev_item.fsid/ {print $3}')
[ "$dev_item_match" = "[match]" ] || _fail "dev_item.fsid doesn't match on metadata_uuid fs"
[ "$fsid" = "d88c8333-a652-4476-b225-2e9284eb59f1" ] || _fail "btrfstune metadata_uuid change failed"
[ "$old_metadata_uuid" = "$metadata_uuid" ] || _fail "metadata_uuid changed unexpectedly"
_log "Checking for incompat textual representation"
# check for textual output of the new incompat feature
run_check_stdout $SUDO_HELPER "$TOP/btrfs" inspect-internal dump-super \
"$TEST_DEV" | grep -q METADATA_UUID
[ $? -eq 0 ] || _fail "Didn't find textual representation of METADATA_UUID feature"
_log "Checking setting fsid back to original"
# ensure that setting the fsid back to the original works
run_check $SUDO_HELPER "$TOP/btrfstune" -M "$old_metadata_uuid" "$TEST_DEV"
fsid=$(read_fsid "$TEST_DEV")
metadata_uuid=$(read_metadata_uuid "$TEST_DEV")
[ "$fsid" = "$metadata_uuid" ] || _fail "fsid and metadata_uuid don't match"
run_check_stdout $SUDO_HELPER "$TOP/btrfs" inspect-internal dump-super \
"$TEST_DEV" | grep -q METADATA_UUID
[ $? -eq 1 ] || _fail "METADATA_UUID feature still shown as enabled"
}
check_image_restore() {
local metadata_uuid
local fsid
local fsid_restored
local metadata_uuid_restored
_log "Testing btrfs-image restore"
run_check_mkfs_test_dev
run_check $SUDO_HELPER "$TOP/btrfstune" -m "$TEST_DEV"
fsid=$(read_fsid "$TEST_DEV")
metadata_uuid=$(read_metadata_uuid "$TEST_DEV")
run_mayfail $SUDO_HELPER "$TOP/btrfs-image" "$TEST_DEV" /tmp/test-img.dump
# erase the fs by creating a new one, wipefs is not sufficient as it just
# deletes the fs magic string
run_check_mkfs_test_dev
run_check $SUDO_HELPER "$TOP/btrfs-image" -r /tmp/test-img.dump "$TEST_DEV"
fsid_restored=$(read_fsid "$TEST_DEV")
metadata_uuid_restored=$(read_metadata_uuid "$TEST_DEV")
[ "$fsid" = "$fsid_restored" ] || _fail "fsid don't match after restore"
[ "$metadata_uuid" = "$metadata_uuid_restored" ] || _fail "metadata_uuids don't match after restore"
}
check_inprogress_flag() {
# check the flag is indeed cleared
run_check_stdout $SUDO_HELPER "$TOP/btrfs" inspect-internal dump-super \
"$1" | grep -q 0x1000000001
[ $? -eq 1 ] || _fail "Found BTRFS_SUPER_FLAG_CHANGING_FSID_V2 set for $1"
run_check_stdout $SUDO_HELPER $TOP/btrfs inspect-internal dump-super \
"$2" | grep -q 0x1000000001
[ $? -eq 1 ] || _fail "Found BTRFS_SUPER_FLAG_CHANGING_FSID_V2 set for $2"
}
check_completed() {
# check that metadata uuid is indeed completed
run_check_stdout $SUDO_HELPER "$TOP/btrfs" inspect-internal dump-super \
"$1" | grep -q METADATA_UUID
[ $? -eq 0 ] || _fail "metadata_uuid not set on $1"
run_check_stdout $SUDO_HELPER "$TOP/btrfs" inspect-internal dump-super \
"$2" | grep -q METADATA_UUID
[ $? -eq 0 ] || _fail "metadata_uuid not set on $2"
}
check_flag_cleared() {
# Ensure METADATA_UUID is not set
run_check_stdout $SUDO_HELPER "$TOP/btrfs" inspect-internal dump-super \
"$1" | grep -q METADATA_UUID
[ $? -eq 1 ] || _fail "metadata_uuid not set on $1"
run_check_stdout $SUDO_HELPER "$TOP/btrfs" inspect-internal dump-super \
"$2" | grep -q METADATA_UUID
[ $? -eq 1 ] || _fail "metadata_uuid not set on $2"
}
check_multi_fsid_change() {
check_inprogress_flag "$1" "$2"
check_completed "$1" "$2"
}
check_multi_fsid_unchanged() {
check_inprogress_flag "$1" "$2"
check_flag_cleared "$1" "$2"
}
failure_recovery() {
local image1
local image2
local loop1
local loop2
local devcount
image1=$(extract_image "$1")
image2=$(extract_image "$2")
loop1=$(run_check_stdout $SUDO_HELPER losetup --find --show "$image1")
loop2=$(run_check_stdout $SUDO_HELPER losetup --find --show "$image2")
run_check $SUDO_HELPER udevadm settle
# Mount and unmount, on trans commit all disks should be consistent
run_check $SUDO_HELPER mount "$loop1" "$TEST_MNT"
run_check $SUDO_HELPER umount "$TEST_MNT"
# perform any specific check
"$3" "$loop1" "$loop2"
# cleanup
run_check $SUDO_HELPER losetup -d "$loop1"
run_check $SUDO_HELPER losetup -d "$loop2"
rm -f -- "$image1" "$image2"
}
reload_btrfs() {
run_check $SUDO_HELPER rmmod btrfs
run_check $SUDO_HELPER modprobe btrfs
}
# for full coverage we need btrfs to actually be a module
modinfo btrfs > /dev/null 2>&1 || _not_run "btrfs must be a module"
run_mayfail $SUDO_HELPER modprobe -r btrfs || _not_run "btrfs must be unloadable"
run_mayfail $SUDO_HELPER modprobe btrfs || _not_run "loading btrfs module failed"
run_check_mkfs_test_dev
check_btrfstune
run_check_mkfs_test_dev
check_dump_super_output
run_check_mkfs_test_dev
check_image_restore
# disk1 is an image which has no metadata uuid flags set and disk2 is part of
# the same fs but has the in-progress flag set. Test that whicever is scanned
# first will result in consistent filesystem.
failure_recovery "./disk1.raw.xz" "./disk2.raw.xz" check_inprogress_flag
reload_btrfs
failure_recovery "./disk2.raw.xz" "./disk1.raw.xz" check_inprogress_flag
# disk4 contains an image in with the in-progress flag set and disk 3 is part
# of the same filesystem but has both METADATA_UUID incompat and a new
# metadata uuid set. So disk 3 must always take precedence
reload_btrfs
failure_recovery "./disk3.raw.xz" "./disk4.raw.xz" check_completed
reload_btrfs
failure_recovery "./disk4.raw.xz" "./disk3.raw.xz" check_completed
# disk5 contains an image which has undergone a successful fsid change more
# than once, disk6 on the other hand is member of the same filesystem but
# hasn't completed its last change. Thus it has both the FSID_CHANGING flag set
# and METADATA_UUID flag set.
reload_btrfs
failure_recovery "./disk5.raw.xz" "./disk6.raw.xz" check_multi_fsid_change
reload_btrfs
failure_recovery "./disk6.raw.xz" "./disk5.raw.xz" check_multi_fsid_change
# disk7 contains an image which has undergone a successful fsid change once to
# a different value and once back to the original one, disk8 is part of the
# same filesystem but in this case it has missed the second transaction commit
# during the process change. So disk 7 looks as if it never underwent fsid change
# and disk 8 has FSID_CHANGING_FLAG and METADATA_UUID but is stale.
failure_recovery "./disk7.raw.xz" "./disk8.raw.xz" check_multi_fsid_unchanged
reload_btrfs
failure_recovery "./disk8.raw.xz" "./disk7.raw.xz" check_multi_fsid_unchanged
|