mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 12:21:22 -05:00
selftests: ublk: add test for UBLK_F_QUIESCE
Add test generic_11 for covering new control command of UBLK_U_CMD_QUIESCE_DEV. Add 'quiesce -n dev_id' sub-command on ublk utility for transitioning device state to quiesce states, then verify the feature via generic_10 by doing quiesce and recovery. Cc: Yoav Cohen <yoav@nvidia.com> Link: https://lore.kernel.org/linux-block/DM4PR12MB632807AB7CDCE77D1E5AB7D0A9B92@DM4PR12MB6328.namprd12.prod.outlook.com/ Signed-off-by: Ming Lei <ming.lei@redhat.com> Link: https://lore.kernel.org/r/20250522163523.406289-4-ming.lei@redhat.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
@@ -18,6 +18,7 @@ TEST_PROGS += test_generic_07.sh
|
||||
TEST_PROGS += test_generic_08.sh
|
||||
TEST_PROGS += test_generic_09.sh
|
||||
TEST_PROGS += test_generic_10.sh
|
||||
TEST_PROGS += test_generic_11.sh
|
||||
|
||||
TEST_PROGS += test_null_01.sh
|
||||
TEST_PROGS += test_null_02.sh
|
||||
|
||||
@@ -228,6 +228,18 @@ static int ublk_ctrl_update_size(struct ublk_dev *dev,
|
||||
return __ublk_ctrl_cmd(dev, &data);
|
||||
}
|
||||
|
||||
static int ublk_ctrl_quiesce_dev(struct ublk_dev *dev,
|
||||
unsigned int timeout_ms)
|
||||
{
|
||||
struct ublk_ctrl_cmd_data data = {
|
||||
.cmd_op = UBLK_U_CMD_QUIESCE_DEV,
|
||||
.flags = CTRL_CMD_HAS_DATA,
|
||||
};
|
||||
|
||||
data.data[0] = timeout_ms;
|
||||
return __ublk_ctrl_cmd(dev, &data);
|
||||
}
|
||||
|
||||
static const char *ublk_dev_state_desc(struct ublk_dev *dev)
|
||||
{
|
||||
switch (dev->dev_info.state) {
|
||||
@@ -1053,6 +1065,9 @@ static int __cmd_dev_add(const struct dev_ctx *ctx)
|
||||
info->nr_hw_queues = nr_queues;
|
||||
info->queue_depth = depth;
|
||||
info->flags = ctx->flags;
|
||||
if ((features & UBLK_F_QUIESCE) &&
|
||||
(info->flags & UBLK_F_USER_RECOVERY))
|
||||
info->flags |= UBLK_F_QUIESCE;
|
||||
dev->tgt.ops = ops;
|
||||
dev->tgt.sq_depth = depth;
|
||||
dev->tgt.cq_depth = depth;
|
||||
@@ -1250,6 +1265,7 @@ static int cmd_dev_get_features(void)
|
||||
[const_ilog2(UBLK_F_USER_RECOVERY_FAIL_IO)] = "RECOVERY_FAIL_IO",
|
||||
[const_ilog2(UBLK_F_UPDATE_SIZE)] = "UPDATE_SIZE",
|
||||
[const_ilog2(UBLK_F_AUTO_BUF_REG)] = "AUTO_BUF_REG",
|
||||
[const_ilog2(UBLK_F_QUIESCE)] = "QUIESCE",
|
||||
};
|
||||
struct ublk_dev *dev;
|
||||
__u64 features = 0;
|
||||
@@ -1316,6 +1332,26 @@ static int cmd_dev_update_size(struct dev_ctx *ctx)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cmd_dev_quiesce(struct dev_ctx *ctx)
|
||||
{
|
||||
struct ublk_dev *dev = ublk_ctrl_init();
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
if (ctx->dev_id < 0) {
|
||||
fprintf(stderr, "device id isn't provided for quiesce\n");
|
||||
goto out;
|
||||
}
|
||||
dev->dev_info.dev_id = ctx->dev_id;
|
||||
ret = ublk_ctrl_quiesce_dev(dev, 10000);
|
||||
|
||||
out:
|
||||
ublk_ctrl_deinit(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __cmd_create_help(char *exe, bool recovery)
|
||||
{
|
||||
int i;
|
||||
@@ -1359,6 +1395,7 @@ static int cmd_dev_help(char *exe)
|
||||
printf("\t -a list all devices, -n list specified device, default -a \n\n");
|
||||
printf("%s features\n", exe);
|
||||
printf("%s update_size -n dev_id -s|--size size_in_bytes \n", exe);
|
||||
printf("%s quiesce -n dev_id\n", exe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1523,6 +1560,8 @@ int main(int argc, char *argv[])
|
||||
ret = cmd_dev_get_features();
|
||||
else if (!strcmp(cmd, "update_size"))
|
||||
ret = cmd_dev_update_size(&ctx);
|
||||
else if (!strcmp(cmd, "quiesce"))
|
||||
ret = cmd_dev_quiesce(&ctx);
|
||||
else
|
||||
cmd_dev_help(argv[0]);
|
||||
|
||||
|
||||
@@ -220,6 +220,26 @@ _recover_ublk_dev() {
|
||||
echo "$state"
|
||||
}
|
||||
|
||||
# quiesce device and return ublk device state
|
||||
__ublk_quiesce_dev()
|
||||
{
|
||||
local dev_id=$1
|
||||
local exp_state=$2
|
||||
local state
|
||||
|
||||
if ! ${UBLK_PROG} quiesce -n "${dev_id}"; then
|
||||
state=$(_get_ublk_dev_state "${dev_id}")
|
||||
return "$state"
|
||||
fi
|
||||
|
||||
for ((j=0;j<50;j++)); do
|
||||
state=$(_get_ublk_dev_state "${dev_id}")
|
||||
[ "$state" == "$exp_state" ] && break
|
||||
sleep 1
|
||||
done
|
||||
echo "$state"
|
||||
}
|
||||
|
||||
# kill the ublk daemon and return ublk device state
|
||||
__ublk_kill_daemon()
|
||||
{
|
||||
@@ -308,20 +328,26 @@ run_io_and_kill_daemon()
|
||||
|
||||
run_io_and_recover()
|
||||
{
|
||||
local action=$1
|
||||
local state
|
||||
local dev_id
|
||||
|
||||
shift 1
|
||||
dev_id=$(_add_ublk_dev "$@")
|
||||
_check_add_dev "$TID" $?
|
||||
|
||||
fio --name=job1 --filename=/dev/ublkb"${dev_id}" --ioengine=libaio \
|
||||
--rw=readwrite --iodepth=256 --size="${size}" --numjobs=4 \
|
||||
--rw=randread --iodepth=256 --size="${size}" --numjobs=4 \
|
||||
--runtime=20 --time_based > /dev/null 2>&1 &
|
||||
sleep 4
|
||||
|
||||
state=$(__ublk_kill_daemon "${dev_id}" "QUIESCED")
|
||||
if [ "$action" == "kill_daemon" ]; then
|
||||
state=$(__ublk_kill_daemon "${dev_id}" "QUIESCED")
|
||||
elif [ "$action" == "quiesce_dev" ]; then
|
||||
state=$(__ublk_quiesce_dev "${dev_id}" "QUIESCED")
|
||||
fi
|
||||
if [ "$state" != "QUIESCED" ]; then
|
||||
echo "device isn't quiesced($state) after killing daemon"
|
||||
echo "device isn't quiesced($state) after $action"
|
||||
return 255
|
||||
fi
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ ERR_CODE=0
|
||||
|
||||
ublk_run_recover_test()
|
||||
{
|
||||
run_io_and_recover "$@"
|
||||
run_io_and_recover "kill_daemon" "$@"
|
||||
ERR_CODE=$?
|
||||
if [ ${ERR_CODE} -ne 0 ]; then
|
||||
echo "$TID failure: $*"
|
||||
|
||||
@@ -8,7 +8,7 @@ ERR_CODE=0
|
||||
|
||||
ublk_run_recover_test()
|
||||
{
|
||||
run_io_and_recover "$@"
|
||||
run_io_and_recover "kill_daemon" "$@"
|
||||
ERR_CODE=$?
|
||||
if [ ${ERR_CODE} -ne 0 ]; then
|
||||
echo "$TID failure: $*"
|
||||
|
||||
44
tools/testing/selftests/ublk/test_generic_11.sh
Executable file
44
tools/testing/selftests/ublk/test_generic_11.sh
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
|
||||
|
||||
TID="generic_11"
|
||||
ERR_CODE=0
|
||||
|
||||
ublk_run_quiesce_recover()
|
||||
{
|
||||
run_io_and_recover "quiesce_dev" "$@"
|
||||
ERR_CODE=$?
|
||||
if [ ${ERR_CODE} -ne 0 ]; then
|
||||
echo "$TID failure: $*"
|
||||
_show_result $TID $ERR_CODE
|
||||
fi
|
||||
}
|
||||
|
||||
if ! _have_feature "QUIESCE"; then
|
||||
exit "$UBLK_SKIP_CODE"
|
||||
fi
|
||||
|
||||
if ! _have_program fio; then
|
||||
exit "$UBLK_SKIP_CODE"
|
||||
fi
|
||||
|
||||
_prep_test "quiesce" "basic quiesce & recover function verification"
|
||||
|
||||
_create_backfile 0 256M
|
||||
_create_backfile 1 128M
|
||||
_create_backfile 2 128M
|
||||
|
||||
ublk_run_quiesce_recover -t null -q 2 -r 1 &
|
||||
ublk_run_quiesce_recover -t loop -q 2 -r 1 "${UBLK_BACKFILES[0]}" &
|
||||
ublk_run_quiesce_recover -t stripe -q 2 -r 1 "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
|
||||
wait
|
||||
|
||||
ublk_run_quiesce_recover -t null -q 2 -r 1 -i 1 &
|
||||
ublk_run_quiesce_recover -t loop -q 2 -r 1 -i 1 "${UBLK_BACKFILES[0]}" &
|
||||
ublk_run_quiesce_recover -t stripe -q 2 -r 1 -i 1 "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
|
||||
wait
|
||||
|
||||
_cleanup_test "quiesce"
|
||||
_show_result $TID $ERR_CODE
|
||||
Reference in New Issue
Block a user