Skip to content

Commit c58b93d

Browse files
committed
zbd/014: Test recursive bio splitting
This test causes bio_split() to be called on the prefix returned by bio_split() and verifies that the LBA order is preserved in this case. Signed-off-by: Bart Van Assche <[email protected]>
1 parent fe9398a commit c58b93d

File tree

2 files changed

+205
-0
lines changed

2 files changed

+205
-0
lines changed

tests/zbd/014

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
#!/bin/bash
2+
# SPDX-License-Identifier: GPL-3.0+
3+
# Copyright (C) 2025 Google LLC
4+
#
5+
# Test the combination of inline encryption and bio splitting. About the values
6+
# of the parameters in this test:
7+
# - The zone size is 4 MiB and is larger than max_sectors_kb.
8+
# - The maximum bio size supported by the code in block/blk-crypto-fallback.c
9+
# is BIO_MAX_VECS * PAGE_SIZE or 1 MiB if the page size is 4 KiB.
10+
# - max_sectors_kb has been set to 512 KiB to cause further bio splitting.
11+
#
12+
# Without these two commits, this test triggers an I/O error:
13+
# - Commit e3290419d9be ("blk-crypto: convert to use
14+
# bio_submit_split_bioset()").
15+
# - Commit b2f5974079d8 ("block: fix ordering of recursive split IO").
16+
17+
. tests/zbd/rc
18+
. common/null_blk
19+
20+
DESCRIPTION="test inline encryption and bio splitting"
21+
QUICK=1
22+
23+
requires() {
24+
_have_driver f2fs
25+
_have_driver null_blk
26+
_have_program fscrypt
27+
_have_program getconf
28+
_have_program mkfs.f2fs
29+
for o in BLK_INLINE_ENCRYPTION_FALLBACK FS_ENCRYPTION_INLINE_CRYPT; do
30+
if ! _check_kernel_option "$o"; then
31+
SKIP_REASONS+=("Kernel option $o has not been enabled")
32+
fi
33+
done
34+
}
35+
36+
trace_block_io() {
37+
(
38+
set -e
39+
cd /sys/kernel/tracing
40+
lsof -t trace_pipe | xargs -r kill
41+
echo 1024 > buffer_size_kb
42+
echo nop > current_tracer
43+
echo 0 > tracing_on
44+
echo > trace
45+
echo 0 > events/enable
46+
echo 1 > events/block/enable
47+
echo 0 > events/block/block_dirty_buffer/enable
48+
echo 0 > events/block/block_plug/enable
49+
echo 0 > events/block/block_touch_buffer/enable
50+
echo 0 > events/block/block_unplug/enable
51+
grep -lw 1 events/block/*/enable | while read -r event_path; do
52+
filter_path="${event_path%enable}filter"
53+
echo "$1" > "$filter_path"
54+
done
55+
echo 1 > tracing_on
56+
echo "Tracing has been enabled" >>"$FULL"
57+
cat trace_pipe > "${FULL%.full}-block-trace.txt"
58+
)
59+
}
60+
61+
stop_tracing() {
62+
kill "$1"
63+
(
64+
set -e
65+
cd /sys/kernel/tracing
66+
echo 0 > tracing_on
67+
echo 0 > events/enable
68+
)
69+
}
70+
71+
report_stats() {
72+
local pfx=$1 before after
73+
read -r -a before <<<"$2"
74+
read -r -a after <<<"$3"
75+
local reads=$((after[0]-before[0]))
76+
local rmerge=$((after[1]-before[1]))
77+
local writes=$((after[4]-before[4]))
78+
local wmerge=$((after[5]-before[5]))
79+
echo "$pfx reads: $reads rmerge: $rmerge writes: $writes wmerge: $wmerge"
80+
}
81+
82+
devno() {
83+
IFS=: read -r maj min <"/sys/class/block/$(basename "$1")/dev"
84+
# From <linux/kdev_t.h>: MINORBITS=20.
85+
echo $(((maj << 20) + min))
86+
}
87+
88+
run_test() {
89+
# From <linux/bio.h>: BIO_MAX_VECS=256.
90+
local bio_max_vecs=256
91+
92+
local page_size
93+
page_size=$(getconf PAGE_SIZE)
94+
95+
# In bytes.
96+
local max_inl_encr_bio_size=$((bio_max_vecs * page_size))
97+
98+
if umount /dev/nullb1 >>"$FULL" 2>&1; then :; fi
99+
_remove_null_blk_devices
100+
101+
# A small conventional block device for the F2FS metadata.
102+
local null_blk_params=(
103+
blocksize=4096
104+
discard=1
105+
max_sectors=$(((1 << 32) - 1))
106+
memory_backed=1
107+
size=64 # MiB
108+
submit_queues=1
109+
power=1
110+
)
111+
_configure_null_blk nullb1 "${null_blk_params[@]}"
112+
local cdev=/dev/nullb1
113+
114+
# A larger zoned block device for the data.
115+
local null_blk_params=(
116+
blocksize=4096
117+
completion_nsec=10000000 # 10 ms
118+
irqmode=2
119+
# Half of the maximum bio size supported by the inline
120+
# encryption fallback code.
121+
max_sectors=$((max_inl_encr_bio_size >> 10))
122+
memory_backed=1
123+
hw_queue_depth=1
124+
size=1024 # MiB
125+
submit_queues=1
126+
# Four times the maximum bio size supported by the inline
127+
# encryption fallback code.
128+
zone_size="$(((4 * max_inl_encr_bio_size) >> 20))"
129+
zoned=1
130+
power=1
131+
)
132+
_configure_null_blk nullb2 "${null_blk_params[@]}"
133+
local zdev_basename=nullb2
134+
local zdev=/dev/${zdev_basename}
135+
local zdev_devno
136+
zdev_devno=$(devno "$zdev")
137+
138+
{
139+
ls -ld "${cdev}" "${zdev}"
140+
echo "${zdev_basename} settings:"
141+
(cd "/sys/class/block/$zdev_basename/queue" && grep -vw 0 ./*)
142+
} >>"${FULL}" 2>&1
143+
144+
trace_block_io "dev == ${zdev_devno}" &
145+
echo $! > "${trace_pid_file}"
146+
while [ "$(</sys/kernel/tracing/tracing_on)" = 0 ]; do
147+
sleep .1
148+
done
149+
150+
{
151+
mkfs.f2fs -q -O encrypt -m "${cdev}" -c "${zdev}"
152+
mkdir -p "${mount_dir}"
153+
mount -o inlinecrypt -t f2fs "${cdev}" "${mount_dir}"
154+
local encrypted_dir="${mount_dir}/encrypted"
155+
mkdir -p "${encrypted_dir}"
156+
fscrypt setup "${mount_dir}" </dev/null
157+
local keyfile=$TMPDIR/keyfile
158+
dd if=/dev/zero of="$keyfile" bs=32 count=1 status=none
159+
fscrypt encrypt "${encrypted_dir}" --source=raw_key \
160+
--name=protector --key="$keyfile"
161+
fscrypt status "${encrypted_dir}"
162+
163+
local before after
164+
read -r -a before <"/sys/class/block/${zdev_basename}/stat"
165+
echo "Starting IO"
166+
local cmd="dd if=/dev/zero of=${encrypted_dir}/file bs=64M count=15 conv=fdatasync status=none"
167+
echo "$cmd"
168+
} >>"$FULL" 2>&1
169+
eval "$cmd"
170+
{
171+
ls -ld "${mount_dir}/encrypted/file"
172+
read -r -a after <"/sys/class/block/${zdev_basename}/stat"
173+
report_stats "zdev:" "${before[*]}" "${after[*]}"
174+
} >>"$FULL" 2>&1
175+
}
176+
177+
test() {
178+
echo "Running ${TEST_NAME}"
179+
180+
# Global variables.
181+
mount_dir="$TMPDIR/mnt"
182+
trace_pid_file="$TMPDIR/trace_pid"
183+
184+
(
185+
set -e
186+
run_test
187+
)
188+
# shellcheck disable=SC2181
189+
(($? != 0)) && fail=true
190+
191+
umount "${mount_dir}" >>"${FULL}" 2>&1
192+
local trace_pid
193+
trace_pid=$(cat "${trace_pid_file}" 2>/dev/null)
194+
[ -n "${trace_pid}" ] && stop_tracing "${trace_pid}"
195+
_exit_null_blk
196+
197+
if [ -z "$fail" ]; then
198+
echo "Test complete"
199+
else
200+
echo "Test failed"
201+
return 1
202+
fi
203+
}

tests/zbd/014.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Running zbd/014
2+
Test complete

0 commit comments

Comments
 (0)