blob: fc654565d1ee68b988aad6cf2455868077113310 (
plain)
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
|
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2021 Facebook, Inc. All Rights Reserved.
#
# FS QA Test 291
#
# Test btrfs consistency after each FUA while enabling verity on a file
# This test works by following the pattern in log-writes/replay-individual.sh:
# 1. run a workload (verity + sync) while logging to the log device
# 2. replay an entry to the replay device
# 3. snapshot the replay device to the snapshot device
# 4. run destructive tests on the snapshot device (e.g. mount with orphans)
# 5. goto 2
#
. ./common/preamble
_begin_fstest auto verity recoveryloop
# Override the default cleanup function.
_cleanup()
{
cd /
_log_writes_cleanup &> /dev/null
$LVM_PROG vgremove -f -y $vgname >>$seqres.full 2>&1
losetup -d $loop_dev >>$seqres.full 2>&1
rm -f $img
_restore_fsverity_signatures
}
. ./common/filter
. ./common/attr
. ./common/dmlogwrites
. ./common/verity
_supported_fs btrfs
_require_scratch
_require_test
_require_loop
_require_log_writes
_require_dm_target snapshot
_require_command $LVM_PROG lvm
_require_scratch_verity
_require_btrfs_command inspect-internal dump-tree
_require_test_program "log-writes/replay-log"
_disable_fsverity_signatures
sync_loop() {
i=$1
[ -z "$i" ] && _fail "sync loop needs a number of iterations"
while [ $i -gt 0 ]
do
$XFS_IO_PROG -c sync $SCRATCH_MNT
let i-=1
done
}
dump_tree() {
local dev=$1
$BTRFS_UTIL_PROG inspect-internal dump-tree $dev
}
count_item() {
local dev=$1
local item=$2
dump_tree $dev | grep -c "$item"
}
count_merkle_items() {
local dev=$1
count_item $dev 'VERITY_\(DESC\|MERKLE\)_ITEM'
}
_log_writes_init $SCRATCH_DEV
_log_writes_mkfs
_log_writes_mount
f=$SCRATCH_MNT/fsv
MB=$((1024 * 1024))
img=$TEST_DIR/$$.img
$XFS_IO_PROG -fc "pwrite -q 0 $((10 * $MB))" $f
$XFS_IO_PROG -c sync $SCRATCH_MNT
sync_loop 10 &
sync_proc=$!
_fsv_enable $f
$XFS_IO_PROG -c sync $SCRATCH_MNT
wait $sync_proc
_log_writes_unmount
_log_writes_remove
# the snapshot and the replay will each be the size of the log writes dev
# so we create a loop device of size 2 * logwrites and then split it into
# replay and snapshot with lvm.
log_writes_blocks=$(blockdev --getsz $LOGWRITES_DEV)
replay_bytes=$((512 * $log_writes_blocks))
img_bytes=$((2 * $replay_bytes))
$XFS_IO_PROG -fc "pwrite -q -S 0 $img_bytes $MB" $img >>$seqres.full 2>&1 || \
_fail "failed to create image for loop device"
loop_dev=$(losetup -f --show $img)
vgname=vg_replay
lvname=lv_replay
replay_dev=/dev/mapper/vg_replay-lv_replay
snapname=lv_snap
snap_dev=/dev/mapper/vg_replay-$snapname
$LVM_PROG vgcreate -f $vgname $loop_dev >>$seqres.full 2>&1 || _fail "failed to vgcreate $vgname"
$LVM_PROG lvcreate -L "$replay_bytes"B -n $lvname $vgname -y >>$seqres.full 2>&1 || \
_fail "failed to lvcreate $lvname"
$UDEV_SETTLE_PROG >>$seqres.full 2>&1
replay_log_prog=$here/src/log-writes/replay-log
num_entries=$($replay_log_prog --log $LOGWRITES_DEV --num-entries)
entry=$($replay_log_prog --log $LOGWRITES_DEV --replay $replay_dev --find --end-mark mkfs | cut -d@ -f1)
prev=$(_log_writes_mark_to_entry_number mkfs)
[ -z "$prev" ] && _fail "failed to locate entry mark 'mkfs'"
cur=$(_log_writes_find_next_fua $prev)
# state = 0: verity hasn't started
# state = 1: verity underway
# state = 2: verity done
state=0
while [ ! -z "$cur" ];
do
_log_writes_replay_log_range $cur $replay_dev >> $seqres.full
$LVM_PROG lvcreate -s -L 4M -n $snapname $vgname/$lvname >>$seqres.full 2>&1 || \
_fail "Failed to create snapshot"
$UDEV_SETTLE_PROG >>$seqres.full 2>&1
orphan=$(count_item $snap_dev ORPHAN)
[ $state -eq 0 ] && [ $orphan -gt 0 ] && state=1
pre_mount=$(count_merkle_items $snap_dev)
_mount $snap_dev $SCRATCH_MNT || _fail "mount failed at entry $cur"
fsverity measure $SCRATCH_MNT/fsv >>$seqres.full 2>&1
measured=$?
umount $SCRATCH_MNT
[ $state -eq 1 ] && [ $measured -eq 0 ] && state=2
[ $state -eq 2 ] && ([ $measured -eq 0 ] || _fail "verity done, but measurement failed at entry $cur")
post_mount=$(count_merkle_items $snap_dev)
echo "entry: $cur, state: $state, orphan: $orphan, pre_mount: $pre_mount, post_mount: $post_mount" >> $seqres.full
if [ $state -eq 1 ]; then
[ $post_mount -eq 0 ] || \
_fail "mount failed to clear under-construction merkle items pre: $pre_mount, post: $post_mount at entry $cur";
fi
if [ $state -eq 2 ]; then
[ $pre_mount -gt 0 ] || \
_fail "expected to have verity items before mount at entry $cur"
[ $pre_mount -eq $post_mount ] || \
_fail "mount cleared merkle items after verity was enabled $pre_mount vs $post_mount at entry $cur";
fi
$LVM_PROG lvremove $vgname/$snapname -y >>$seqres.full
prev=$cur
cur=$(_log_writes_find_next_fua $(($cur + 1)))
done
[ $state -eq 2 ] || _fail "expected to reach verity done state"
echo "Silence is golden"
# success, all done
status=0
exit
|