2 # Common btrfs specific functions
10 $BTRFS_UTIL_PROG sub list $mnt | grep $name | awk '{ print $2 }'
13 # We check for btrfs and (optionally) features of the btrfs command
17 _require_command "$BTRFS_UTIL_PROG" btrfs
21 $BTRFS_UTIL_PROG $cmd --help >/dev/null 2>&1
22 [ $? -eq 0 ] || _notrun "$BTRFS_UTIL_PROG too old (must support $cmd)"
25 _run_btrfs_util_prog()
27 run_check $BTRFS_UTIL_PROG $*
30 _require_btrfs_send_stream_version()
32 $BTRFS_UTIL_PROG send 2>&1 | \
33 grep '^[ \t]*\-\-stream\-version <version>' > /dev/null 2>&1
35 _notrun "Missing btrfs-progs send --stream-version command line option, skipped this test"
38 # test if btrfs kernel supports send stream version 2
39 if [ ! -f /sys/fs/btrfs/send/stream_version ]; then
40 _notrun "Missing btrfs kernel patch for send stream version 2, skipped this test"
44 _require_btrfs_mkfs_feature()
47 echo "Missing feature name argument for _require_btrfs_mkfs_feature"
51 $MKFS_BTRFS_PROG -O list-all 2>&1 | \
52 grep '^[ \t]*'"$feat"'\b' > /dev/null 2>&1
54 _notrun "Feature $feat not supported in the available version of mkfs.btrfs"
57 _require_btrfs_fs_feature()
60 echo "Missing feature name argument for _require_btrfs_fs_feature"
64 modprobe btrfs > /dev/null 2>&1
65 [ -e /sys/fs/btrfs/features/$feat ] || \
66 _notrun "Feature $feat not supported by the available btrfs version"
69 _check_btrfs_filesystem()
73 # If type is set, we're mounted
74 type=`_fs_type $device`
77 if [ "$type" = "$FSTYP" ]; then
79 mountpoint=`_umount_or_remount_ro $device`
82 btrfsck $device >$tmp.fsck 2>&1
84 echo "_check_btrfs_filesystem: filesystem on $device is inconsistent (see $seqres.full)"
86 echo "_check_btrfs_filesystem: filesystem on $device is inconsistent" >>$seqres.full
87 echo "*** fsck.$FSTYP output ***" >>$seqres.full
88 cat $tmp.fsck >>$seqres.full
89 echo "*** end fsck.$FSTYP output" >>$seqres.full
95 if [ $ok -eq 0 ]; then
96 echo "*** mount output ***" >>$seqres.full
98 echo "*** end mount output" >>$seqres.full
99 elif [ "$type" = "$FSTYP" ]; then
101 _mount_or_remount_rw "$MOUNT_OPTIONS" $device $mountpoint
105 if [ $ok -eq 0 ]; then
107 if [ "$iam" != "check" ]; then
116 _require_btrfs_dev_del_by_devid()
118 $BTRFS_UTIL_PROG device delete --help | egrep devid > /dev/null 2>&1
119 [ $? -eq 0 ] || _notrun "$BTRFS_UTIL_PROG too old "\
120 "(must support 'btrfs device delete <devid> /<mnt>')"
123 # get btrfs profile configs being tested
125 # A set of pre-set profile configs are exported via _btrfs_profile_configs
126 # array. Default configs can be overridden by setting BTRFS_PROFILE_CONFIGS
127 # var in the format "metadata_profile:data_profile", multiple configs can be
128 # seperated by space, e.g.
129 # export BTRFS_PROFILE_CONFIGS="raid0:raid0 raid1:raid1 dup:single"
130 _btrfs_get_profile_configs()
132 if [ "$FSTYP" != "btrfs" ]; then
136 if [ -z "$BTRFS_PROFILE_CONFIGS" ]; then
137 # Default configurations to test.
149 # User-provided configurations.
150 local configs=(${BTRFS_PROFILE_CONFIGS[@]})
153 _btrfs_profile_configs=()
154 for cfg in "${configs[@]}"; do
156 local profiles=(${cfg/:/ })
157 if [ "$1" == "replace" ]; then
158 # We can't do replace with these profiles because they
159 # imply only one device ($SCRATCH_DEV), and we need to
160 # keep $SCRATCH_DEV around for _scratch_mount
161 # and _check_scratch_fs.
165 elif [ "$1" == "replace-missing" ]; then
166 # We can't replace missing devices with these profiles
167 # because there isn't enough redundancy.
176 for unsupp in "${unsupported[@]}"; do
177 if [ "${profiles[0]}" == "$unsupp" -o "${profiles[1]}" == "$unsupp" ]; then
178 if [ -z "$BTRFS_PROFILE_CONFIGS" ]; then
179 # For the default config, just omit it.
182 # For user-provided config, don't run the test.
183 _notrun "Profile $unsupp not supported for $1"
187 if "$supported"; then
188 _btrfs_profile_configs+=("-m ${profiles[0]} -d ${profiles[1]}")
191 export _btrfs_profile_configs
194 # stress btrfs by running balance operation in a loop
195 _btrfs_stress_balance()
199 $BTRFS_UTIL_PROG balance start $options
203 # stress btrfs by creating/mounting/umounting/deleting subvolume in a loop
204 _btrfs_stress_subvolume()
213 while [ ! -e $stop_file ]; do
214 $BTRFS_UTIL_PROG subvolume create $btrfs_mnt/$subvol_name
215 $MOUNT_PROG -o subvol=$subvol_name $btrfs_dev $subvol_mnt
216 $UMOUNT_PROG $subvol_mnt
217 $BTRFS_UTIL_PROG subvolume delete $btrfs_mnt/$subvol_name
221 # stress btrfs by running scrub in a loop
222 _btrfs_stress_scrub()
226 $BTRFS_UTIL_PROG scrub start -B $btrfs_mnt
230 # stress btrfs by defragmenting every file/dir in a loop and compress file
231 # contents while defragmenting if second argument is not "nocompress"
232 _btrfs_stress_defrag()
238 if [ "$compress" == "nocompress" ]; then
239 find $btrfs_mnt \( -type f -o -type d \) -exec \
240 $BTRFS_UTIL_PROG filesystem defrag {} \;
242 find $btrfs_mnt \( -type f -o -type d \) -exec \
243 $BTRFS_UTIL_PROG filesystem defrag -clzo {} \;
244 find $btrfs_mnt \( -type f -o -type d \) -exec \
245 $BTRFS_UTIL_PROG filesystem defrag -czlib {} \;
250 # stress btrfs by remounting it with different compression algorithms in a loop
251 # run this with fsstress running at background could exercise the compression
252 # code path and ensure no race when switching compression algorithm with constant
254 _btrfs_stress_remount_compress()
258 for algo in no zlib lzo; do
259 $MOUNT_PROG -o remount,compress=$algo $btrfs_mnt
264 # stress btrfs by replacing devices in a loop
265 # Note that at least 3 devices are needed in SCRATCH_DEV_POOL and the last
266 # device should be free(not used by btrfs)
267 _btrfs_stress_replace()
271 # The device number in SCRATCH_DEV_POOL should be at least 3,
272 # one is SCRATCH_DEV, one is to be replaced, one is free device
273 # we won't replace SCRATCH_DEV, see below for reason
274 if [ "`echo $SCRATCH_DEV_POOL | wc -w`" -lt 3 ]; then
275 echo "_btrfs_stress_replace requires at least 3 devices in SCRATCH_DEV_POOL"
279 # take the last device as the first free_dev
280 local free_dev="`echo $SCRATCH_DEV_POOL | $AWK_PROG '{print $NF}'`"
282 # free_dev should be really free
283 if $BTRFS_UTIL_PROG filesystem show $btrfs_mnt | grep -q "$free_dev"; then
284 echo "_btrfs_stress_replace: $free_dev is used by btrfs"
288 # dev_pool is device list being currently used by btrfs (excluding SCRATCH_DEV)
289 # and can be replaced. We don't replace SCRATCH_DEV because it will be used in
290 # _scratch_mount and _check_scratch_fs etc.
291 local dev_pool=`echo $SCRATCH_DEV_POOL | sed -e "s# *$SCRATCH_DEV *##" \
292 -e "s# *$free_dev *##"`
294 # set the first device in dev_pool as the first src_dev to be replaced
295 local src_dev=`echo $dev_pool | $AWK_PROG '{print $1}'`
297 echo "dev_pool=$dev_pool"
298 echo "free_dev=$free_dev, src_dev=$src_dev"
300 echo "Replacing $src_dev with $free_dev"
301 $BTRFS_UTIL_PROG replace start -fB $src_dev $free_dev $btrfs_mnt
302 if [ $? -ne 0 ]; then
303 # don't update src_dev and free_dev if replace failed
306 dev_pool="$dev_pool $free_dev"
307 dev_pool=`echo $dev_pool | sed -e "s# *$src_dev *##"`
309 src_dev=`echo $dev_pool | $AWK_PROG '{print $1}'`
313 # find the right option to force output in bytes, older versions of btrfs-progs
314 # print that by default, newer print human readable numbers with unit suffix
315 _btrfs_qgroup_units()
317 $BTRFS_UTIL_PROG qgroup show --help 2>&1 | grep -q -- --raw && echo "--raw"
320 _require_btrfs_loadable()
322 modprobe -r btrfs || _notrun "btrfs unloadable"
323 modprobe btrfs || _notrun "Can't load btrfs"
328 modprobe -r btrfs || _fail "btrfs unload failed"
329 modprobe btrfs || _fail "btrfs load failed"