bdev/raid0: Support resize when increasing the size of base bdevs

Implement the resize function for RAID0. raid0_resize() calculate the
new raid_bdev's block count and if it is different from the old block
count, call spdk_bdev_notify_blockcnt_change() with the new block count.

A raid0 bdev always opens all base bdevs. Hence, if the size of base
bdevs are reduced, resize fails now. This limitation will be removed
later.

Add a simple functional test for this feature. The test is to create
a raid0 bdev with two null bdevs, resize one null bdev, check if the
raid0 bdev is not resize, resize another null bdev, check if the raid0
bdev is resized.

test/iscsi_tgt/resize/resize.sh was used a reference to write the test.
Using jq rather than grep&sed is better and hence replace grep&sed by jq
of test/iscsi_tgt/resize/resize.sh together in this patch.

Signed-off-by: Shuhei Matsumoto <smatsumoto@nvidia.com>
Change-Id: I07136648c4189b970843fc6da51ff40355423144
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16261
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Xiaodong Liu <xiaodong.liu@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Shuhei Matsumoto 2023-01-13 10:51:07 +09:00 committed by Jim Harris
parent c6d73b5aaf
commit c22b052b60
4 changed files with 73 additions and 2 deletions

View File

@ -384,12 +384,36 @@ raid0_start(struct raid_bdev *raid_bdev)
return 0;
}
static void
raid0_resize(struct raid_bdev *raid_bdev)
{
uint64_t blockcnt;
int rc;
blockcnt = raid0_calculate_blockcnt(raid_bdev);
if (blockcnt == raid_bdev->bdev.blockcnt) {
return;
}
SPDK_NOTICELOG("raid0 '%s': min blockcount was changed from %" PRIu64 " to %" PRIu64 "\n",
raid_bdev->bdev.name,
raid_bdev->bdev.blockcnt,
blockcnt);
rc = spdk_bdev_notify_blockcnt_change(&raid_bdev->bdev, blockcnt);
if (rc != 0) {
SPDK_ERRLOG("Failed to notify blockcount change\n");
}
}
static struct raid_bdev_module g_raid0_module = {
.level = RAID0,
.base_bdevs_min = 1,
.start = raid0_start,
.submit_rw_request = raid0_submit_rw_request,
.submit_null_payload_request = raid0_submit_null_payload_request,
.resize = raid0_resize,
};
RAID_MODULE_REGISTER(&g_raid0_module)

View File

@ -247,11 +247,57 @@ function raid_state_function_test() {
return 0
}
function raid0_resize_test() {
local blksize=512
local bdev_size_mb=32
local new_bdev_size_mb=$((bdev_size_mb * 2))
local blkcnt
local raid_size_mb
local new_raid_size_mb
$rootdir/test/app/bdev_svc/bdev_svc -r $rpc_server -i 0 -L bdev_raid &
raid_pid=$!
echo "Process raid pid: $raid_pid"
waitforlisten $raid_pid $rpc_server
$rpc_py bdev_null_create Base_1 $bdev_size_mb $blksize
$rpc_py bdev_null_create Base_2 $bdev_size_mb $blksize
$rpc_py bdev_raid_create -z 64 -r 0 -b "Base_1 Base_2" -n Raid
# Resize Base_1 first.
$rpc_py bdev_null_resize Base_1 $new_bdev_size_mb
# The size of Raid should not be changed.
blkcnt=$($rpc_py bdev_get_bdevs -b Raid | jq '.[].num_blocks')
raid_size_mb=$((blkcnt * blksize / 1048576))
if [ $raid_size_mb != $((bdev_size_mb * 2)) ]; then
echo "resize failed"
return 1
fi
# Resize Base_2 next.
$rpc_py bdev_null_resize Base_2 $new_bdev_size_mb
# The size of Raid should be updated to the expected value.
blkcnt=$($rpc_py bdev_get_bdevs -b Raid | jq '.[].num_blocks')
raid_size_mb=$((blkcnt * blksize / 1048576))
if [ $raid_size_mb != $((new_bdev_size_mb * 2)) ]; then
echo "resize failed"
return 1
fi
killprocess $raid_pid
return 0
}
trap 'on_error_exit;' ERR
raid_function_test raid0
raid_function_test concat
raid_state_function_test raid0
raid_state_function_test concat
raid0_resize_test
rm -f $tmp_file

View File

@ -49,7 +49,7 @@ waitforlisten $bdevperf_pid $RESIZE_SOCK
# Resize the Bdev from iSCSI target
$rpc_py bdev_null_resize Null0 $BDEV_NEW_SIZE
# Obtain the Bdev from bdevperf with iSCSI initiator
num_block=$($rpc_py -s $RESIZE_SOCK bdev_get_bdevs | grep num_blocks | sed 's/[^[:digit:]]//g')
num_block=$($rpc_py -s $RESIZE_SOCK bdev_get_bdevs | jq '.[].num_blocks')
# Size is not changed as no IO sent yet and resize notification is deferred.
total_size=$((num_block * BLOCK_SIZE / 1048576))
if [ $total_size != $BDEV_SIZE ]; then
@ -60,7 +60,7 @@ sleep 2
# Start the bdevperf IO
$rootdir/examples/bdev/bdevperf/bdevperf.py -s $RESIZE_SOCK perform_tests
# Obtain the Bdev from bdevperf with iSCSI initiator
num_block=$($rpc_py -s $RESIZE_SOCK bdev_get_bdevs | grep num_blocks | sed 's/[^[:digit:]]//g')
num_block=$($rpc_py -s $RESIZE_SOCK bdev_get_bdevs | jq '.[].num_blocks')
# Get the new bdev size in MiB.
total_size=$((num_block * BLOCK_SIZE / 1048576))
if [ $total_size != $BDEV_NEW_SIZE ]; then

View File

@ -120,6 +120,7 @@ DEFINE_STUB(spdk_bdev_is_md_interleaved, bool, (const struct spdk_bdev *bdev), f
DEFINE_STUB(spdk_bdev_get_dif_type, enum spdk_dif_type, (const struct spdk_bdev *bdev),
SPDK_DIF_DISABLE);
DEFINE_STUB(spdk_bdev_is_dif_head_of_md, bool, (const struct spdk_bdev *bdev), false);
DEFINE_STUB(spdk_bdev_notify_blockcnt_change, int, (struct spdk_bdev *bdev, uint64_t size), 0);
struct spdk_io_channel *
spdk_bdev_get_io_channel(struct spdk_bdev_desc *desc)