summaryrefslogtreecommitdiff
path: root/tests/xfs/509
blob: d04dfbbfbaa17afb36e6a9def66084b74ff62f66 (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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2014 Red Hat, Inc.  All Rights Reserved.
# Copyright (c) 2019 Oracle, Inc.  All Rights Reserved.
#
# FS QA Test No. 509
#
# Use the xfs_io bulkstat utility to verify bulkstat finds all inodes in a
# filesystem.  Test under various inode counts, inobt record layouts and
# bulkstat batch sizes.  Test v1 and v5 ioctls explicitly, as well as the
# ioctl version autodetection code in libfrog.
#
. ./common/preamble
_begin_fstest auto ioctl

bstat_versions()
{
	echo "default"
	echo "v1 -v1"
	if [ -n "$has_v5" ]; then
		echo "v5 -v5"
	else
		echo "v5"
	fi
}

# Print the number of inodes counted by bulkstat
bstat_count()
{
	local batchsize="$1"
	local tag="$2"

	bstat_versions | while read v_tag v_flag; do
		echo "$tag($v_tag): passing \"$v_flag\" to bulkstat" >> $seqres.full
		echo -n "bulkstat $tag($v_tag): "
		$XFS_IO_PROG -c "bulkstat -n $batchsize $v_flag" $SCRATCH_MNT | grep ino | wc -l
	done
}

# Print the number of inodes counted by per-ag bulkstat
bstat_perag_count()
{
	local batchsize="$1"
	local tag="$2"

	local agcount=$(_xfs_mount_agcount $SCRATCH_MNT)

	bstat_versions | while read v_tag v_flag; do
		echo -n "bulkstat $tag($v_tag): "
		seq 0 $((agcount - 1)) | while read ag; do
			$XFS_IO_PROG -c "bulkstat -a $ag -n $batchsize $v_flag" $SCRATCH_MNT
		done | grep ino | wc -l
	done
}

# Sum the number of allocated inodes in each AG in a fs.
inumbers_ag()
{
	local agcount="$1"
	local batchsize="$2"
	local mount="$3"
	local v_flag="$4"

	seq 0 $((agcount - 1)) | while read ag; do
		$XFS_IO_PROG -c "inumbers -a $ag -n $batchsize $v_flag" $mount
	done | grep alloccount | awk '{x += $3} END { print(x) }'
}

# Sum the number of allocated inodes in the whole fs all at once.
inumbers_fs()
{
	local dir="$1"
	local v_flag="$2"

	$XFS_IO_PROG -c "inumbers $v_flag" "$dir" | grep alloccount | \
		awk '{x += $3} END { print(x) }'
}

# Print the number of inodes counted by inumbers
inumbers_count()
{
	local expect="$1"

	# There probably aren't more than 10 hidden inodes, right?
	local tolerance=10

	# Force all background unlinked inode cleanup to run so that we don't
	# race changes to the inode btree with our inumbers query.
	_scratch_cycle_mount

	bstat_versions | while read v_tag v_flag; do
		echo -n "inumbers all($v_tag): "
		nr=$(inumbers_fs $SCRATCH_MNT $v_flag)
		_within_tolerance "inumbers" $nr $expect $tolerance -v

		local agcount=$(_xfs_mount_agcount $SCRATCH_MNT)
		for batchsize in 71 2 1; do
			echo -n "inumbers $batchsize($v_tag): "
			nr=$(inumbers_ag $agcount $batchsize $SCRATCH_MNT $v_flag)
			_within_tolerance "inumbers" $nr $expect $tolerance -v
		done
	done
}

# Compare the src/bstat output against the xfs_io bstat output.
# This compares the actual inode numbers output by one tool against another,
# so we can't easily put the output in the golden output.
bstat_compare()
{
	bstat_versions | while read v_tag v_flag; do
		diff -u <($here/src/bstat $SCRATCH_MNT | grep ino | awk '{print $2}') \
			<($XFS_IO_PROG -c "bulkstat $v_flag" $SCRATCH_MNT | grep ino | awk '{print $3}')
	done
}

# Print bulkstat counts using varied batch sizes
bstat_test()
{
	expect=`find $SCRATCH_MNT -print | wc -l`
	echo
	echo "expect $expect"

	for sz in 4096 71 32 1; do
		bstat_count $sz "$sz all"
		bstat_perag_count $sz "$sz perag"
		bstat_compare
		inumbers_count $expect
	done
}

# Get standard environment, filters and checks
. ./common/filter

_require_scratch
_require_xfs_io_command bulkstat
_require_xfs_io_command bulkstat_single
_require_xfs_io_command inumbers

# Real QA test starts here

_supported_fs xfs

DIRCOUNT=8
INOCOUNT=$((2048 / DIRCOUNT))

_scratch_mkfs "-d agcount=$DIRCOUNT" >> $seqres.full 2>&1 || _fail "mkfs failed"
_scratch_mount

# Figure out if we have v5 bulkstat/inumbers ioctls.
has_v5=
bs_root_out="$($XFS_IO_PROG -c 'bulkstat_single root' $SCRATCH_MNT 2>>$seqres.full)"
test -n "$bs_root_out" && has_v5=1

echo "this will be 1 if we have v5 bulkstat: $has_v5" >> $seqres.full

# If v5 bulkstat is present, query the root inode and compare it to the stat
# output of $SCRATCH_MNT to make sure it gave us the correct number
if [ -n "$has_v5" ]; then
	bs_root=$(echo "$bs_root_out" | grep ino | awk '{print $3}')
	stat_root=$(stat -c '%i' $SCRATCH_MNT)
	if [ "$stat_root" -ne "$bs_root" ]; then
		echo "stat says root is $stat_root but bulkstat says $bs_root"
	fi
fi

# Create a set of directories and fill each with a fixed number of files
for dir in $(seq 1 $DIRCOUNT); do
	mkdir -p $SCRATCH_MNT/$dir
	for i in $(seq 1 $INOCOUNT); do
		touch $SCRATCH_MNT/$dir/$i
	done
done
bstat_test

# Remove every other file from each dir
for dir in $(seq 1 $DIRCOUNT); do
	for i in $(seq 2 2 $INOCOUNT); do
		rm -f $SCRATCH_MNT/$dir/$i
	done
done
bstat_test

# Remove the entire second half of files
for dir in $(seq 1 $DIRCOUNT); do
	for i in $(seq $((INOCOUNT / 2)) $INOCOUNT); do
		rm -f $SCRATCH_MNT/$dir/$i
	done
done
bstat_test

# Remove all regular files
for dir in $(seq 1 $DIRCOUNT); do
	rm -f $SCRATCH_MNT/$dir/*
done
bstat_test

# Success, all done
status=0
exit