selftests: ublk: add selftest for UBLK_F_NO_AUTO_PART_SCAN

Add test_part_01.sh to test the UBLK_F_NO_AUTO_PART_SCAN feature
flag which allows suppressing automatic partition scanning during
device startup while still allowing manual partition probing.

The test verifies:
- Normal behavior: partitions are auto-detected without the flag
- With flag: partitions are not auto-detected during START_DEV
- Manual scan: blockdev --rereadpt works with the flag

Also update kublk tool to support --no_auto_part_scan option and
recognize the feature flag.

Signed-off-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Ming Lei
2026-01-30 00:19:53 +08:00
committed by Jens Axboe
parent 3a4d8bed0b
commit e07a2039b6
4 changed files with 113 additions and 2 deletions

View File

@@ -48,6 +48,8 @@ TEST_PROGS += test_stripe_04.sh
TEST_PROGS += test_stripe_05.sh
TEST_PROGS += test_stripe_06.sh
TEST_PROGS += test_part_01.sh
TEST_PROGS += test_stress_01.sh
TEST_PROGS += test_stress_02.sh
TEST_PROGS += test_stress_03.sh

View File

@@ -1615,6 +1615,7 @@ static int cmd_dev_get_features(void)
FEAT_NAME(UBLK_F_INTEGRITY),
FEAT_NAME(UBLK_F_SAFE_STOP_DEV),
FEAT_NAME(UBLK_F_BATCH_IO),
FEAT_NAME(UBLK_F_NO_AUTO_PART_SCAN),
};
struct ublk_dev *dev;
__u64 features = 0;
@@ -1712,7 +1713,7 @@ static void __cmd_create_help(char *exe, bool recovery)
printf("\t[--nthreads threads] [--per_io_tasks]\n");
printf("\t[--integrity_capable] [--integrity_reftag] [--metadata_size SIZE] "
"[--pi_offset OFFSET] [--csum_type ip|t10dif|nvme] [--tag_size SIZE]\n");
printf("\t[--batch|-b]\n");
printf("\t[--batch|-b] [--no_auto_part_scan]\n");
printf("\t[target options] [backfile1] [backfile2] ...\n");
printf("\tdefault: nr_queues=2(max 32), depth=128(max 1024), dev_id=-1(auto allocation)\n");
printf("\tdefault: nthreads=nr_queues");
@@ -1786,6 +1787,7 @@ int main(int argc, char *argv[])
{ "tag_size", 1, NULL, 0 },
{ "safe", 0, NULL, 0 },
{ "batch", 0, NULL, 'b'},
{ "no_auto_part_scan", 0, NULL, 0 },
{ 0, 0, 0, 0 }
};
const struct ublk_tgt_ops *ops = NULL;
@@ -1898,6 +1900,8 @@ int main(int argc, char *argv[])
ctx.tag_size = strtoul(optarg, NULL, 0);
if (!strcmp(longopts[option_idx].name, "safe"))
ctx.safe_stop = 1;
if (!strcmp(longopts[option_idx].name, "no_auto_part_scan"))
ctx.flags |= UBLK_F_NO_AUTO_PART_SCAN;
break;
case '?':
/*

View File

@@ -78,12 +78,13 @@ struct dev_ctx {
unsigned int auto_zc_fallback:1;
unsigned int per_io_tasks:1;
unsigned int no_ublk_fixed_fd:1;
unsigned int safe_stop:1;
unsigned int no_auto_part_scan:1;
__u32 integrity_flags;
__u8 metadata_size;
__u8 pi_offset;
__u8 csum_type;
__u8 tag_size;
unsigned int safe_stop:1;
int _evtfd;
int _shmid;

View File

@@ -0,0 +1,104 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
ERR_CODE=0
format_backing_file()
{
local backing_file=$1
# Create ublk device to write partition table
local tmp_dev=$(_add_ublk_dev -t loop "${backing_file}")
[ $? -ne 0 ] && return 1
# Write partition table with sfdisk
sfdisk /dev/ublkb"${tmp_dev}" > /dev/null 2>&1 <<EOF
label: dos
start=2048, size=100MiB, type=83
start=206848, size=100MiB, type=83
EOF
local ret=$?
"${UBLK_PROG}" del -n "${tmp_dev}"
return $ret
}
test_auto_part_scan()
{
local backing_file=$1
# Create device WITHOUT --no_auto_part_scan
local dev_id=$(_add_ublk_dev -t loop "${backing_file}")
[ $? -ne 0 ] && return 1
udevadm settle
# Partitions should be auto-detected
if [ ! -e /dev/ublkb"${dev_id}"p1 ] || [ ! -e /dev/ublkb"${dev_id}"p2 ]; then
"${UBLK_PROG}" del -n "${dev_id}"
return 1
fi
"${UBLK_PROG}" del -n "${dev_id}"
return 0
}
test_no_auto_part_scan()
{
local backing_file=$1
# Create device WITH --no_auto_part_scan
local dev_id=$(_add_ublk_dev -t loop --no_auto_part_scan "${backing_file}")
[ $? -ne 0 ] && return 1
udevadm settle
# Partitions should NOT be auto-detected
if [ -e /dev/ublkb"${dev_id}"p1 ]; then
"${UBLK_PROG}" del -n "${dev_id}"
return 1
fi
# Manual scan should work
blockdev --rereadpt /dev/ublkb"${dev_id}" > /dev/null 2>&1
udevadm settle
if [ ! -e /dev/ublkb"${dev_id}"p1 ] || [ ! -e /dev/ublkb"${dev_id}"p2 ]; then
"${UBLK_PROG}" del -n "${dev_id}"
return 1
fi
"${UBLK_PROG}" del -n "${dev_id}"
return 0
}
if ! _have_program sfdisk || ! _have_program blockdev; then
exit "$UBLK_SKIP_CODE"
fi
_prep_test "generic" "test UBLK_F_NO_AUTO_PART_SCAN"
if ! _have_feature "UBLK_F_NO_AUTO_PART_SCAN"; then
_cleanup_test "generic"
exit "$UBLK_SKIP_CODE"
fi
# Create and format backing file with partition table
_create_backfile 0 256M
format_backing_file "${UBLK_BACKFILES[0]}"
[ $? -ne 0 ] && ERR_CODE=255
# Test normal auto partition scan
[ "$ERR_CODE" -eq 0 ] && test_auto_part_scan "${UBLK_BACKFILES[0]}"
[ $? -ne 0 ] && ERR_CODE=255
# Test no auto partition scan with manual scan
[ "$ERR_CODE" -eq 0 ] && test_no_auto_part_scan "${UBLK_BACKFILES[0]}"
[ $? -ne 0 ] && ERR_CODE=255
_cleanup_test "generic"
_show_result $TID $ERR_CODE