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
|
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2014 SUSE Linux Products GmbH. All Rights Reserved.
#
# FSQA Test No. 080
#
# Regression test for a btrfs issue where if right after the snapshot creation
# ioctl started, a file write followed by a file truncate happened, with both
# operations increasing the file's size, the created snapshot would capture an
# inconsistent state of the file system tree. That state reflected the file
# truncation but it didn't reflect the write operation, and left a gap between
# two file extent items (and that gap corresponded to the total or a partial
# area of the write operation's range).
#
# This issue was fixed by the following linux kernel patch:
#
# Btrfs: fix snapshot inconsistency after a file write followed by truncate
#
. ./common/preamble
_begin_fstest auto snapshot
# Override the default cleanup function.
_cleanup()
{
for p in ${cpu_stress_pids[*]}; do
kill $p &> /dev/null
done
rm -f $tmp.*
}
. ./common/filter
_supported_fs btrfs
_require_scratch_nocheck
create_snapshot()
{
local ts=`date +'%H_%M_%S_%N'`
_btrfs subvolume snapshot -r \
$SCRATCH_MNT $SCRATCH_MNT/"${ts}_snap"
}
create_file()
{
local name=$1
run_check $XFS_IO_PROG -f \
-c "pwrite -S 0xaa -b 32K 0 32K" \
-c "fsync" \
-c "pwrite -S 0xbb -b 32770 16K 32770" \
-c "truncate 90123" \
$SCRATCH_MNT/$name
}
workout()
{
local name=$1
create_file $name &
fpid=$!
create_snapshot &
spid=$!
wait $fpid
create_ret=$?
wait $spid
snap_ret=$?
if [ $create_ret != 0 -o $snap_ret != 0 ]; then
_fail "Failure creating file or snapshot, check $seqres.full for details"
fi
}
# If the installed btrfs mkfs supports the no-holes feature, make sure the
# created fs doesn't get that feature enabled. With it enabled, the below fsck
# call wouldn't fail. This feature hasn't been enabled by default since it was
# introduced, but be safe and explicitly disable it.
_scratch_mkfs -O list-all 2>&1 | grep -q '\bno-holes\b'
if [ $? -eq 0 ]; then
mkfs_options="-O ^no-holes"
fi
_scratch_mkfs "$mkfs_options" >>$seqres.full 2>&1
_scratch_mount
# Run some background load in order to make the issue easier to trigger.
# Specially needed when testing with non-debug kernels and there isn't
# any other significant load on the test machine other than this test.
num_cpus=`$here/src/feature -o`
num_procs=$(($num_cpus * 20))
for ((i = 0; i < $num_procs; i++)); do
while true; do
true
done &
cpu_stress_pids[$i]=$!
done
for ((i = 1; i <= 100; i++)); do
workout "foobar_$i"
done
for ((i = 0; i < $num_procs; i++)); do
kill ${cpu_stress_pids[$i]} &> /dev/null
unset cpu_stress_pids[$i]
done
for f in $(find $SCRATCH_MNT -type f -name 'foobar_*'); do
digest=`md5sum $f | cut -d ' ' -f 1`
case $digest in
"d41d8cd98f00b204e9800998ecf8427e")
# ok, empty file
;;
"c28418534a020122aca59fd3ff9581b5")
# ok, only first write captured
;;
"cd0032da89254cdc498fda396e6a9b54")
# ok, only 2 first writes captured
;;
"a1963f914baf4d2579d643425f4e54bc")
# ok, the 2 writes and the truncate were captured
;;
*)
# not ok, truncate captured but not one or both writes
_fail "Unexpected digest for file $f"
esac
done
# Check the filesystem for inconsistencies.
# Before the btrfs kernel fix mentioned above, we would very often get fsck
# error messages like: "root 306 inode 338 errors 100, file extent discount".
#
# This was because if right after the snapshot creation ioctl started, a file
# write followed by a file truncate, with both operations increasing the file's
# size, we would get a snapshot that reflected a state where the file truncation
# was visible but the previous file write was not visible, breaking expected
# total ordering of operations and causing a gap between 2 file extents, where a
# file extent item representing the range [32K .. ALIGN(16K + 32770, 4096)] was
# missing in the snapshot's btree.
_check_scratch_fs
echo "Silence is golden"
status=0
exit
|