Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Ming Lei and committed by
Jens Axboe
533c87e2 b465ae7b

+115 -5
+1
tools/testing/selftests/ublk/Makefile
··· 18 18 TEST_PROGS += test_generic_08.sh 19 19 TEST_PROGS += test_generic_09.sh 20 20 TEST_PROGS += test_generic_10.sh 21 + TEST_PROGS += test_generic_11.sh 21 22 22 23 TEST_PROGS += test_null_01.sh 23 24 TEST_PROGS += test_null_02.sh
+39
tools/testing/selftests/ublk/kublk.c
··· 228 228 return __ublk_ctrl_cmd(dev, &data); 229 229 } 230 230 231 + static int ublk_ctrl_quiesce_dev(struct ublk_dev *dev, 232 + unsigned int timeout_ms) 233 + { 234 + struct ublk_ctrl_cmd_data data = { 235 + .cmd_op = UBLK_U_CMD_QUIESCE_DEV, 236 + .flags = CTRL_CMD_HAS_DATA, 237 + }; 238 + 239 + data.data[0] = timeout_ms; 240 + return __ublk_ctrl_cmd(dev, &data); 241 + } 242 + 231 243 static const char *ublk_dev_state_desc(struct ublk_dev *dev) 232 244 { 233 245 switch (dev->dev_info.state) { ··· 1065 1053 info->nr_hw_queues = nr_queues; 1066 1054 info->queue_depth = depth; 1067 1055 info->flags = ctx->flags; 1056 + if ((features & UBLK_F_QUIESCE) && 1057 + (info->flags & UBLK_F_USER_RECOVERY)) 1058 + info->flags |= UBLK_F_QUIESCE; 1068 1059 dev->tgt.ops = ops; 1069 1060 dev->tgt.sq_depth = depth; 1070 1061 dev->tgt.cq_depth = depth; ··· 1265 1250 [const_ilog2(UBLK_F_USER_RECOVERY_FAIL_IO)] = "RECOVERY_FAIL_IO", 1266 1251 [const_ilog2(UBLK_F_UPDATE_SIZE)] = "UPDATE_SIZE", 1267 1252 [const_ilog2(UBLK_F_AUTO_BUF_REG)] = "AUTO_BUF_REG", 1253 + [const_ilog2(UBLK_F_QUIESCE)] = "QUIESCE", 1268 1254 }; 1269 1255 struct ublk_dev *dev; 1270 1256 __u64 features = 0; ··· 1332 1316 return ret; 1333 1317 } 1334 1318 1319 + static int cmd_dev_quiesce(struct dev_ctx *ctx) 1320 + { 1321 + struct ublk_dev *dev = ublk_ctrl_init(); 1322 + int ret = -EINVAL; 1323 + 1324 + if (!dev) 1325 + return -ENODEV; 1326 + 1327 + if (ctx->dev_id < 0) { 1328 + fprintf(stderr, "device id isn't provided for quiesce\n"); 1329 + goto out; 1330 + } 1331 + dev->dev_info.dev_id = ctx->dev_id; 1332 + ret = ublk_ctrl_quiesce_dev(dev, 10000); 1333 + 1334 + out: 1335 + ublk_ctrl_deinit(dev); 1336 + return ret; 1337 + } 1338 + 1335 1339 static void __cmd_create_help(char *exe, bool recovery) 1336 1340 { 1337 1341 int i; ··· 1395 1359 printf("\t -a list all devices, -n list specified device, default -a \n\n"); 1396 1360 printf("%s features\n", exe); 1397 1361 printf("%s update_size -n dev_id -s|--size size_in_bytes \n", exe); 1362 + printf("%s quiesce -n dev_id\n", exe); 1398 1363 return 0; 1399 1364 } 1400 1365 ··· 1560 1523 ret = cmd_dev_get_features(); 1561 1524 else if (!strcmp(cmd, "update_size")) 1562 1525 ret = cmd_dev_update_size(&ctx); 1526 + else if (!strcmp(cmd, "quiesce")) 1527 + ret = cmd_dev_quiesce(&ctx); 1563 1528 else 1564 1529 cmd_dev_help(argv[0]); 1565 1530
+29 -3
tools/testing/selftests/ublk/test_common.sh
··· 220 220 echo "$state" 221 221 } 222 222 223 + # quiesce device and return ublk device state 224 + __ublk_quiesce_dev() 225 + { 226 + local dev_id=$1 227 + local exp_state=$2 228 + local state 229 + 230 + if ! ${UBLK_PROG} quiesce -n "${dev_id}"; then 231 + state=$(_get_ublk_dev_state "${dev_id}") 232 + return "$state" 233 + fi 234 + 235 + for ((j=0;j<50;j++)); do 236 + state=$(_get_ublk_dev_state "${dev_id}") 237 + [ "$state" == "$exp_state" ] && break 238 + sleep 1 239 + done 240 + echo "$state" 241 + } 242 + 223 243 # kill the ublk daemon and return ublk device state 224 244 __ublk_kill_daemon() 225 245 { ··· 328 308 329 309 run_io_and_recover() 330 310 { 311 + local action=$1 331 312 local state 332 313 local dev_id 333 314 315 + shift 1 334 316 dev_id=$(_add_ublk_dev "$@") 335 317 _check_add_dev "$TID" $? 336 318 337 319 fio --name=job1 --filename=/dev/ublkb"${dev_id}" --ioengine=libaio \ 338 - --rw=readwrite --iodepth=256 --size="${size}" --numjobs=4 \ 320 + --rw=randread --iodepth=256 --size="${size}" --numjobs=4 \ 339 321 --runtime=20 --time_based > /dev/null 2>&1 & 340 322 sleep 4 341 323 342 - state=$(__ublk_kill_daemon "${dev_id}" "QUIESCED") 324 + if [ "$action" == "kill_daemon" ]; then 325 + state=$(__ublk_kill_daemon "${dev_id}" "QUIESCED") 326 + elif [ "$action" == "quiesce_dev" ]; then 327 + state=$(__ublk_quiesce_dev "${dev_id}" "QUIESCED") 328 + fi 343 329 if [ "$state" != "QUIESCED" ]; then 344 - echo "device isn't quiesced($state) after killing daemon" 330 + echo "device isn't quiesced($state) after $action" 345 331 return 255 346 332 fi 347 333
+1 -1
tools/testing/selftests/ublk/test_generic_04.sh
··· 8 8 9 9 ublk_run_recover_test() 10 10 { 11 - run_io_and_recover "$@" 11 + run_io_and_recover "kill_daemon" "$@" 12 12 ERR_CODE=$? 13 13 if [ ${ERR_CODE} -ne 0 ]; then 14 14 echo "$TID failure: $*"
+1 -1
tools/testing/selftests/ublk/test_generic_05.sh
··· 8 8 9 9 ublk_run_recover_test() 10 10 { 11 - run_io_and_recover "$@" 11 + run_io_and_recover "kill_daemon" "$@" 12 12 ERR_CODE=$? 13 13 if [ ${ERR_CODE} -ne 0 ]; then 14 14 echo "$TID failure: $*"
+44
tools/testing/selftests/ublk/test_generic_11.sh
··· 1 + #!/bin/bash 2 + # SPDX-License-Identifier: GPL-2.0 3 + 4 + . "$(cd "$(dirname "$0")" && pwd)"/test_common.sh 5 + 6 + TID="generic_11" 7 + ERR_CODE=0 8 + 9 + ublk_run_quiesce_recover() 10 + { 11 + run_io_and_recover "quiesce_dev" "$@" 12 + ERR_CODE=$? 13 + if [ ${ERR_CODE} -ne 0 ]; then 14 + echo "$TID failure: $*" 15 + _show_result $TID $ERR_CODE 16 + fi 17 + } 18 + 19 + if ! _have_feature "QUIESCE"; then 20 + exit "$UBLK_SKIP_CODE" 21 + fi 22 + 23 + if ! _have_program fio; then 24 + exit "$UBLK_SKIP_CODE" 25 + fi 26 + 27 + _prep_test "quiesce" "basic quiesce & recover function verification" 28 + 29 + _create_backfile 0 256M 30 + _create_backfile 1 128M 31 + _create_backfile 2 128M 32 + 33 + ublk_run_quiesce_recover -t null -q 2 -r 1 & 34 + ublk_run_quiesce_recover -t loop -q 2 -r 1 "${UBLK_BACKFILES[0]}" & 35 + ublk_run_quiesce_recover -t stripe -q 2 -r 1 "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" & 36 + wait 37 + 38 + ublk_run_quiesce_recover -t null -q 2 -r 1 -i 1 & 39 + ublk_run_quiesce_recover -t loop -q 2 -r 1 -i 1 "${UBLK_BACKFILES[0]}" & 40 + ublk_run_quiesce_recover -t stripe -q 2 -r 1 -i 1 "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" & 41 + wait 42 + 43 + _cleanup_test "quiesce" 44 + _show_result $TID $ERR_CODE