Spdk/test/lvol/external_snapshot.sh
Mike Gerdts 68cde3b770 vbdev_lvol: external snapshot rpc interface
Add RPC interfaces for creation of esnap clone lvols. This also
exercises esnap clone creation and various operations involving
snapshots and clones of esnap clones to ensure that bdev_get_bdevs
reports state correctly.

Change-Id: Ib87d01026ef6e45203c4d9451759885a7be02d87
Signed-off-by: Mike Gerdts <mgerdts@nvidia.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14978
Reviewed-by: Michal Berger <michal.berger@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
2023-05-09 17:58:11 +08:00

233 lines
7.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
testdir=$(readlink -f "$(dirname "$0")")
rootdir=$(readlink -f "$testdir/../..")
source "$rootdir/test/common/autotest_common.sh"
source "$rootdir/test/lvol/common.sh"
source "$rootdir/test/bdev/nbd_common.sh"
set -u
g_nbd_dev=INVALID
g_cluster_size=INVALID
g_block_size=INVALID
function test_esnap_reload() {
local bs_dev esnap_dev
local block_size=512
local esnap_size_mb=1
local lvs_cluster_size=$((16 * 1024))
local lvs_uuid esnap_uuid eclone_uuid snap_uuid clone_uuid uuid
local aio_bdev=test_esnap_reload_aio0
# Create the lvstore on an aio device. Can't use malloc because we need to remove
# the device and re-add it to trigger an lvstore unload and then load.
rm -f $testdir/aio_bdev_0
truncate -s "${AIO_SIZE_MB}M" $testdir/aio_bdev_0
bs_dev=$(rpc_cmd bdev_aio_create "$testdir/aio_bdev_0" "$aio_bdev" "$block_size")
lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore -c "$lvs_cluster_size" "$bs_dev" lvs_test)
# Create a bdev that will be the external snapshot
esnap_uuid=e4b40d8b-f623-416d-8234-baf5a4c83cbd
esnap_dev=$(rpc_cmd bdev_malloc_create -u "$esnap_uuid" "$esnap_size_mb" "$block_size")
eclone_uuid=$(rpc_cmd bdev_lvol_clone_bdev "$esnap_uuid" lvs_test "eclone1")
# Unload the lvstore
rpc_cmd bdev_aio_delete "$aio_bdev"
NOT rpc_cmd bdev_lvol_get_lvstores -l lvs_test
# Load the lvstore, expect to see eclone1 again
bs_dev=$(rpc_cmd bdev_aio_create "$testdir/aio_bdev_0" "$aio_bdev" "$block_size")
lvs_uuid=$(rpc_cmd bdev_lvol_get_lvstores -l lvs_test)
uuid=$(rpc_cmd bdev_get_bdevs -b lvs_test/eclone1 | jq -r '.[].name')
[[ "$uuid" == "$eclone_uuid" ]]
# Create a snapshot of the eclone, reload, and verify all is there.
snap_uuid=$(rpc_cmd bdev_lvol_snapshot "$eclone_uuid" snap1)
rpc_cmd bdev_aio_delete "$aio_bdev"
NOT rpc_cmd bdev_lvol_get_lvstores -l lvs_test
bs_dev=$(rpc_cmd bdev_aio_create "$testdir/aio_bdev_0" "$aio_bdev" "$block_size")
lvs_uuid=$(rpc_cmd bdev_lvol_get_lvstores -l lvs_test)
uuid=$(rpc_cmd bdev_get_bdevs -b lvs_test/eclone1 | jq -r '.[].name')
[[ "$uuid" == "$eclone_uuid" ]]
uuid=$(rpc_cmd bdev_get_bdevs -b lvs_test/snap1 | jq -r '.[].name')
[[ "$uuid" == "$snap_uuid" ]]
# Create a clone of the snapshot, reload, and verify all is there.
clone_uuid=$(rpc_cmd bdev_lvol_clone "$snap_uuid" clone1)
rpc_cmd bdev_aio_delete "$aio_bdev"
NOT rpc_cmd bdev_lvol_get_lvstores -l lvs_test
bs_dev=$(rpc_cmd bdev_aio_create "$testdir/aio_bdev_0" "$aio_bdev" "$block_size")
lvs_uuid=$(rpc_cmd bdev_lvol_get_lvstores -l lvs_test)
uuid=$(rpc_cmd bdev_get_bdevs -b lvs_test/eclone1 | jq -r '.[].name')
[[ "$uuid" == "$eclone_uuid" ]]
uuid=$(rpc_cmd bdev_get_bdevs -b lvs_test/snap1 | jq -r '.[].name')
[[ "$uuid" == "$snap_uuid" ]]
uuid=$(rpc_cmd bdev_get_bdevs -b lvs_test/clone1 | jq -r '.[].name')
[[ "$uuid" == "$clone_uuid" ]]
rpc_cmd bdev_lvol_delete "$clone_uuid"
rpc_cmd bdev_lvol_delete "$snap_uuid"
rpc_cmd bdev_lvol_delete "$eclone_uuid"
rpc_cmd bdev_aio_delete "$aio_bdev"
rpc_cmd bdev_malloc_delete "$esnap_dev"
}
function log_jq_out() {
local key
xtrace_disable
while read -r key; do
printf '%50s = %s\n' "$key" "${jq_out[$key]}"
done < <(printf '%s\n' "${!jq_out[@]}" | sort)
xtrace_restore
}
function verify_clone() {
local bdev=$1
local parent=$2
rpc_cmd_simple_data_json bdev bdev_get_bdevs -b "$bdev"
log_jq_out
[[ "${jq_out["supported_io_types.read"]}" == true ]]
[[ "${jq_out["supported_io_types.write"]}" == true ]]
[[ "${jq_out["driver_specific.lvol.clone"]}" == true ]]
[[ "${jq_out["driver_specific.lvol.base_snapshot"]}" == "$parent" ]]
[[ "${jq_out["driver_specific.lvol.esnap_clone"]}" == false ]]
[[ "${jq_out["driver_specific.lvol.external_snapshot_name"]}" == null ]]
}
function verify_esnap_clone() {
local bdev=$1
local parent=$2
local writable=${3:-true}
rpc_cmd_simple_data_json bdev bdev_get_bdevs -b "$bdev"
log_jq_out
[[ "${jq_out["supported_io_types.read"]}" == true ]]
[[ "${jq_out["supported_io_types.write"]}" == "$writable" ]]
[[ "${jq_out["driver_specific.lvol.esnap_clone"]}" == true ]]
[[ "${jq_out["driver_specific.lvol.external_snapshot_name"]}" == "$parent" ]]
}
function test_esnap_clones() {
local bs_dev esnap_dev
local block_size=512
local lvs_size_mb=100
local esnap_size_mb=1
local lvs_cluster_size=$((16 * 1024))
local lvs_uuid esnap_uuid
local vol1_uuid vol2_uuid vol3_uuid vol3_uuid vol4_uuid vol5_uuid
# Create the lvstore on a malloc device.
bs_dev=$(rpc_cmd bdev_malloc_create $lvs_size_mb $block_size)
lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore -c "$lvs_cluster_size" "$bs_dev" lvs_test)
# Create a bdev that will be the external snapshot
# State:
# esnap1
esnap_uuid=2abddd12-c08d-40ad-bccf-ab131586ee4c
esnap_dev=$(rpc_cmd bdev_malloc_create -b esnap1 -u "$esnap_uuid" "$esnap_size_mb" \
"$block_size")
# Create an esnap clone: vol1
# New state:
# esnap1 <-- vol1(rw)
vol1_uuid=$(rpc_cmd bdev_lvol_clone_bdev "$esnap_uuid" lvs_test vol1)
verify_esnap_clone "$vol1_uuid" "$esnap_uuid"
# Create a snapshot of the esnap clone: vol2
# New state:
# esnap1 <-- vol2(ro) <-- vol1(rw)
vol2_uuid=$(rpc_cmd bdev_lvol_snapshot "$vol1_uuid" vol2)
verify_esnap_clone "$vol2_uuid" "$esnap_uuid" false
verify_clone "$vol1_uuid" vol2
# Delete vol2.
# New state:
# esnap1 <-- vol1(rw)
rpc_cmd bdev_lvol_delete "$vol2_uuid"
NOT rpc_cmd bdev_get_bdevs -b "$vol2_uuid"
verify_esnap_clone "$vol1_uuid" "$esnap_uuid"
vol2_uuid=
# Snapshot vol1: vol3
# New state:
# ensap1 <-- vol3(ro) <-- vol1(rw)
vol3_uuid=$(rpc_cmd bdev_lvol_snapshot "$vol1_uuid" vol3)
verify_esnap_clone "$vol3_uuid" "$esnap_uuid" false
verify_clone "$vol1_uuid" vol3
# Delete vol1
# New state:
# esnap1 <-- vol3(ro)
rpc_cmd bdev_lvol_delete $vol1_uuid
NOT rpc_cmd bdev_get_bdevs -b $vol1_uuid
verify_esnap_clone "$vol3_uuid" "$esnap_uuid" false
vol1_uuid=
# Create clone of vol3: vol4
# Verify vol3 is still a read-only esnap clone and vol4 is a normal clone.
# New state:
# ensap1 <-- vol3(ro) <-- vol4(rw)
vol4_uuid=$(rpc_cmd bdev_lvol_clone "$vol3_uuid" vol4)
rpc_cmd bdev_get_bdevs -b "$vol4_uuid"
verify_esnap_clone "$vol3_uuid" "$esnap_uuid" false
verify_clone "$vol4_uuid" vol3
# Create clone of vol3 (vol5).
# New state:
# ensap1 <-- vol3(ro) <-- vol4(rw)
# `<-- vol5(rw)
vol5_uuid=$(rpc_cmd bdev_lvol_clone "$vol3_uuid" vol5)
verify_esnap_clone "$vol3_uuid" "$esnap_uuid" false
verify_clone "$vol4_uuid" vol3
verify_clone "$vol5_uuid" vol3
# Cannot delete vol3 because it has multiple clones
NOT rpc_cmd bdev_lvol_delete "$vol3_uuid"
# Delete vol4
# New state:
# ensap1 <-- vol3(ro) <-- vol5(rw)
rpc_cmd bdev_lvol_delete "$vol4_uuid"
NOT rpc_cmd bdev_get_bdevs -b "$vol4_uuid"
verify_esnap_clone "$vol3_uuid" "$esnap_uuid" false
verify_clone "$vol5_uuid" vol3
# Delete vol3.
# New state:
# ensap1 <-- vol5(rw)
rpc_cmd bdev_lvol_delete "$vol3_uuid"
NOT rpc_cmd bdev_get_bdevs -b "$vol3_uuid"
verify_esnap_clone "$vol5_uuid" "$esnap_uuid"
# Delete vol5.
# New state:
# esnap1
rpc_cmd bdev_lvol_delete "$vol5_uuid"
NOT rpc_cmd bdev_get_bdevs -b "$vol5_uuid"
rpc_cmd bdev_malloc_delete "$bs_dev"
rpc_cmd bdev_malloc_delete "$esnap_dev"
}
$SPDK_BIN_DIR/spdk_tgt &
spdk_pid=$!
trap 'killprocess "$spdk_pid"; rm -f "$testdir/aio_bdev_0"; exit 1' SIGINT SIGTERM SIGPIPE EXIT
waitforlisten $spdk_pid
modprobe nbd
run_test "test_esnap_reload" test_esnap_reload
run_test "test_esnap_clones" test_esnap_clones
trap - SIGINT SIGTERM SIGPIPE EXIT
killprocess $spdk_pid
rm -f "$testdir/aio_bdev_0"