blob: cd927dc4b8230af8f997d34b6ab495f5c1befc67 (
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
169
170
171
172
173
174
175
176
|
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2010 Dave Chinner. All Rights Reserved.
#
# FS QA Test No. 227
#
# xfs_fsr QA tests
# run xfs_fsr over the test filesystem to give it a wide and varied set of
# inodes to try to defragment. This is effectively a crash/assert failure
# test looking for corruption induced by the kernel inadequately checking
# the indoes to be swapped. It also is good for validating fsr's attribute fork
# generation code.
#
. ./common/preamble
_begin_fstest auto fsr
# Import common functions.
. ./common/filter
# real QA test starts here
_supported_fs xfs
_require_scratch
[ "$XFS_FSR_PROG" = "" ] && _notrun "xfs_fsr not found"
# create freespace holes of 1-3 blocks in length
#
# This is done to ensure that defragmented files have roughly 1/3 the
# number of extents they started with. This will ensure we get
# transistions from btree format (say 15 extents) to extent format
# (say 5 extents) and lots of variations around that dependent on the
# number of attributes in the files being defragmented.
#
# We have to make sure there are enough free inodes for the test to
# pass without needing to allocate new clusters during the test.
# With such fragemented free space, that will fail.
#
fragment_freespace()
{
_file="$SCRATCH_MNT/not_free"
_dir="$SCRATCH_MNT/saved"
# allocate inode space
mkdir -p $_dir
for i in `seq 0 1 1000`; do
touch $_file.$i
done
for i in `seq 0 63 1000`; do
mv $_file.$i $_dir
done
for i in `seq 0 1 1000`; do
rm -f $_file.$i
done
$XFS_IO_PROG -fs -c "resvsp 0 40000k" $_file > /dev/null 2>&1
for i in `seq 0 8 40000`; do
$XFS_IO_PROG -f -c "unresvsp ${i}k 4k" $_file \
> /dev/null 2>&1
done
for i in `seq 0 28 40000`; do
$XFS_IO_PROG -f -c "unresvsp ${i}k 4k" $_file \
> /dev/null 2>&1
done
sync
# and now use up all the remaining extents larger than 3 blocks
$XFS_IO_PROG -fs -c "resvsp 0 4m" $_file.large > /dev/null 2>&1
}
create_attrs()
{
for foo in `seq 0 1 $1`; do
$SETFATTR_PROG -n user.$foo -v 0xbabe $2
done
}
create_data()
{
size=`expr \( $1 + 1 \) \* 4096`
$XFS_IO_PROG -f -c "truncate $size" $2 > /dev/null 2>&1
for foo in `seq $1 -1 0`; do
let offset=$foo*4096
$XFS_IO_PROG -f -c "resvsp $offset 4096" $2 > /dev/null 2>&1
done
}
# create the designated file with a certain number of attributes and a certain
# number of data extents. Reverse order synchronous data writes are used to
# create fragmented files, though with the way the filesystem freespace is
# fragmented, this is probably not necessary. Create the attributes first so
# that they cause the initial fork offset pressure to move it about.
#
create_target_attr_first()
{
nattrs=$1
file_blocks=$2
target=$3
rm -f $target
touch $target
create_attrs $nattrs $target
create_data $file_blocks $target
}
# Same as create_target_attr_first, but this time put the attributes on after
# the data extents have been created. This puts different pressure on the
# inode fork offset, so should exercise the kernel code differently and give us
# a different pattern of fork offsets to work with compared to creating the
# attrs first.
#
create_target_attr_last()
{
nattrs=$1
file_blocks=$2
target=$3
rm -f $target
touch $target
create_data $file_blocks $target
create_attrs $nattrs $target
}
# use a small filesystem so we can control freespace easily
_scratch_mkfs_sized $((50 * 1024 * 1024)) >> $seqres.full 2>&1
_scratch_mount
fragment_freespace
# unmount and remount to reset all allocator indexes
_scratch_unmount
_scratch_mount
# create a range of source files, then fsr them to a known size
#
# This assumes 256 byte inodes.
#
# n = number of target fragments for xfs_fsr
# - only a guideline, but forces multiple fragments via sync writes
# - start at 4 as that typically covers all extent format situations
# - end at 12 as that is beyond the maximum that canbe fit in extent
# format
# i = number of 2 byte attributes on the file
# - it takes 6 attributes to change the fork offset from the start value
# of 120 bytes to 112 bytes, so we start at 5.
# - 15 is enough to push to btree format, so we stop there.
# j = number of data extents on the file
# - start in extent format, but we also want btree format as well, so
# start at 5 so that the number of attributes determines the starting
# format.
# - need enough extents that if they are all 3 blocks in length the final
# format will be dependent on the number of attributes on the inode. 20
# initial single block extents gives us 6-8 extents after defrag which
# puts us right on the threshold of what the extent format can hold.
targ=$SCRATCH_MNT/fsr_test_file.$$
for n in `seq 4 1 12`; do
echo "*** n == $n ***" >> $seqres.full
for i in `seq 5 1 15`; do
for j in `seq 5 1 20`; do
create_target_attr_first $i $j $targ.$i.$j >> $seqres.full 2>&1
done
xfs_bmap -vp $targ.$i.* >> $seqres.full 2>&1
FSRXFSTEST=true xfs_fsr -d -v -C $n $targ.$i.* >> $seqres.full 2>&1
xfs_bmap -vp $targ.$i.* >> $seqres.full 2>&1
for j in `seq 5 1 20`; do
create_target_attr_last $i $j $targ.$i.$j >> $seqres.full 2>&1
done
xfs_bmap -vp $targ.$i.* >> $seqres.full 2>&1
FSRXFSTEST=true xfs_fsr -d -v -C $n $targ.$i.* >> $seqres.full 2>&1
xfs_bmap -vp $targ.$i.* >> $seqres.full 2>&1
done
done
_scratch_unmount
echo "--- silence is golden ---"
status=0 ; exit
|