1#!/usr/bin/env bash 2# SPDX-License-Identifier: BSD-3-Clause 3# Copyright (C) 2019 Intel Corporation 4# All rights reserved. 5# 6testdir=$(readlink -f $(dirname $0)) 7rootdir=$(readlink -f $testdir/../..) 8source $rootdir/test/common/autotest_common.sh 9source $rootdir/test/lvol/common.sh 10source $rootdir/test/bdev/nbd_common.sh 11 12# Check if number of free clusters on lvol store decreases 13# if we write to created thin provisioned lvol bdev 14function test_thin_lvol_check_space() { 15 malloc_name=$(rpc_cmd bdev_malloc_create $MALLOC_SIZE_MB $MALLOC_BS) 16 lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore "$malloc_name" lvs_test) 17 lvs=$(rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid") 18 free_clusters_start="$(jq -r '.[0].free_clusters' <<< "$lvs")" 19 20 # Create thin provision lvol bdev with size equals to lvol store space 21 lvol_size_mb=$(round_down $((LVS_DEFAULT_CAPACITY_MB))) 22 lvol_uuid=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid" lvol_test "$lvol_size_mb" -t) 23 24 lvs=$(rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid") 25 free_clusters_create_lvol="$(jq -r '.[0].free_clusters' <<< "$lvs")" 26 [ $free_clusters_start == $free_clusters_create_lvol ] 27 28 # Write data (lvs cluster size) to created lvol bdev starting from offset 0. 29 size=$LVS_DEFAULT_CLUSTER_SIZE 30 nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid" /dev/nbd0 31 run_fio_test /dev/nbd0 0 $size "write" "0xcc" 32 lvs=$(rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid") 33 free_clusters_first_fio="$(jq -r '.[0].free_clusters' <<< "$lvs")" 34 [ $((free_clusters_first_fio + 1)) == $free_clusters_start ] 35 36 # Write data (lvs cluster size) to lvol bdev with offset set to one and half of cluster size 37 offset=$((LVS_DEFAULT_CLUSTER_SIZE * 3 / 2)) 38 size=$LVS_DEFAULT_CLUSTER_SIZE 39 run_fio_test /dev/nbd0 $offset $size "write" "0xcc" 40 lvs=$(rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid") 41 free_clusters_second_fio="$(jq -r '.[0].free_clusters' <<< "$lvs")" 42 [ $((free_clusters_second_fio + 3)) == $free_clusters_start ] 43 44 # write data to lvol bdev to the end of its size 45 size=$((LVS_DEFAULT_CLUSTER_SIZE * free_clusters_first_fio)) 46 offset=$((3 * LVS_DEFAULT_CLUSTER_SIZE)) 47 run_fio_test /dev/nbd0 $offset $size "write" "0xcc" 48 lvs=$(rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid") 49 # Check that lvol store free clusters number equals to 0 50 free_clusters_third_fio="$(jq -r '.[0].free_clusters' <<< "$lvs")" 51 [ $((free_clusters_third_fio)) == 0 ] 52 53 nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0 54 rpc_cmd bdev_lvol_delete "$lvol_uuid" 55 rpc_cmd bdev_get_bdevs -b "$lvol_uuid" && false 56 lvs=$(rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid") 57 free_clusters_end="$(jq -r '.[0].free_clusters' <<< "$lvs")" 58 [ $((free_clusters_end)) == $free_clusters_start ] 59 60 # Clean up 61 rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid" 62 rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid" && false 63 rpc_cmd bdev_malloc_delete "$malloc_name" 64} 65 66# Check if we can create thin provisioned bdev on empty lvol store 67# and check if we can read from this device and it returns zeroes. 68function test_thin_lvol_check_zeroes() { 69 malloc_name=$(rpc_cmd bdev_malloc_create $MALLOC_SIZE_MB $MALLOC_BS) 70 lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore "$malloc_name" lvs_test) 71 lvs=$(rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid") 72 free_clusters_start="$(jq -r '.[0].free_clusters' <<< "$lvs")" 73 74 # Create thick and thin provisioned lvol bdevs with size equals to lvol store space 75 lbd_name0=lvol_test0 76 lbd_name1=lvol_test1 77 lvol_size_mb=$((LVS_DEFAULT_CAPACITY_MB)) 78 # Round down lvol size to the nearest cluster size boundary 79 lvol_size_mb=$((lvol_size_mb / LVS_DEFAULT_CLUSTER_SIZE_MB * LVS_DEFAULT_CLUSTER_SIZE_MB)) 80 lvol_size=$((lvol_size_mb * 1024 * 1024)) 81 lvol_uuid0=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid" $lbd_name0 "$lvol_size_mb") 82 lvol_uuid1=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid" $lbd_name1 "$lvol_size_mb" -t) 83 84 nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid0" /dev/nbd0 85 nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid1" /dev/nbd1 86 87 # Fill the whole thick provisioned lvol bdev 88 run_fio_test /dev/nbd0 0 $lvol_size "write" "0xcc" 89 90 # Perform read operations on thin provisioned lvol bdev 91 # and check if they return zeroes 92 run_fio_test /dev/nbd1 0 $lvol_size "read" "0x00" 93 94 # Clean up 95 nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd1 96 nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0 97 rpc_cmd bdev_lvol_delete "$lvol_uuid1" 98 rpc_cmd bdev_lvol_delete "$lvol_uuid0" 99 rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid" 100 rpc_cmd bdev_malloc_delete "$malloc_name" 101} 102 103# Check if data written to thin provisioned lvol bdev 104# were properly written (fio test with verification) 105function test_thin_lvol_check_integrity() { 106 malloc_name=$(rpc_cmd bdev_malloc_create $MALLOC_SIZE_MB $MALLOC_BS) 107 lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore "$malloc_name" lvs_test) 108 109 # Create thin provisioned lvol bdev with size equals to lvol store space 110 lvol_size_mb=$((LVS_DEFAULT_CAPACITY_MB)) 111 # Round down lvol size to the nearest cluster size boundary 112 lvol_size_mb=$((lvol_size_mb / LVS_DEFAULT_CLUSTER_SIZE_MB * LVS_DEFAULT_CLUSTER_SIZE_MB)) 113 lvol_size=$((lvol_size_mb * 1024 * 1024)) 114 lvol_uuid=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid" lvol_test "$lvol_size_mb" -t) 115 116 nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid" /dev/nbd0 117 run_fio_test /dev/nbd0 0 $lvol_size "write" "0xcc" 118 119 # Clean up 120 nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0 121 rpc_cmd bdev_lvol_delete "$lvol_uuid" 122 rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid" 123 rpc_cmd bdev_malloc_delete "$malloc_name" 124} 125 126# Check thin provisioned bdev resize 127function test_thin_lvol_resize() { 128 malloc_name=$(rpc_cmd bdev_malloc_create $MALLOC_SIZE_MB $MALLOC_BS) 129 lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore "$malloc_name" lvs_test) 130 131 # Construct thin provisioned lvol bdevs on created lvol store 132 # with size equal to 50% of lvol store 133 lvol_size_mb=$(round_down $((LVS_DEFAULT_CAPACITY_MB / 2))) 134 lvol_size=$((lvol_size_mb * 1024 * 1024)) 135 lvol_uuid=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid" lvol_test "$lvol_size_mb" -t) 136 137 # Fill all free space of lvol bdev with data 138 nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid" /dev/nbd0 139 run_fio_test /dev/nbd0 0 $lvol_size "write" "0xcc" 140 nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0 141 142 # Save number of free clusters for lvs 143 lvs=$(rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid") 144 free_clusters_start="$(jq -r '.[0].free_clusters' <<< "$lvs")" 145 # Resize bdev to full size of lvs 146 lvol_size_full_mb=$(round_down $((LVS_DEFAULT_CAPACITY_MB))) 147 lvol_size_full=$((lvol_size_full_mb * 1024 * 1024)) 148 rpc_cmd bdev_lvol_resize $lvol_uuid $lvol_size_full_mb 149 150 # Check if bdev size changed (total_data_clusters*cluster_size 151 # equals to num_blocks*block_size) 152 lvol=$(rpc_cmd bdev_get_bdevs -b "$lvol_uuid") 153 [ "$(jq -r '.[0].block_size' <<< "$lvol")" = "$MALLOC_BS" ] 154 [ "$(jq -r '.[0].num_blocks' <<< "$lvol")" = $((lvol_size_full / MALLOC_BS)) ] 155 156 # Check if free_clusters on lvs remain unaffected 157 lvs=$(rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid") 158 free_clusters_resize="$(jq -r '.[0].free_clusters' <<< "$lvs")" 159 [ $free_clusters_start == $free_clusters_resize ] 160 161 # Perform write operation with verification 162 # to newly created free space of lvol bdev 163 nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid" /dev/nbd0 164 run_fio_test /dev/nbd0 0 $lvol_size_full "write" "0xcc" 165 nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0 166 167 # Check if free clusters on lvs equals to zero 168 lvs=$(rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid") 169 free_clusters_start="$(jq -r '.[0].free_clusters' <<< "$lvs")" 170 [ $free_clusters_start == 0 ] 171 172 # Resize bdev to 25% of lvs and check if it ended with success 173 lvol_size_quarter_mb=$(round_down $((LVS_DEFAULT_CAPACITY_MB / 4))) 174 rpc_cmd bdev_lvol_resize $lvol_uuid $lvol_size_quarter_mb 175 176 # Check free clusters on lvs 177 lvs=$(rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid") 178 free_clusters_resize_quarter="$(jq -r '.[0].free_clusters' <<< "$lvs")" 179 free_clusters_expected=$(((lvol_size_full_mb - lvol_size_quarter_mb) / LVS_DEFAULT_CLUSTER_SIZE_MB)) 180 [ $free_clusters_resize_quarter == $free_clusters_expected ] 181 182 rpc_cmd bdev_lvol_delete "$lvol_uuid" 183 rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid" 184 rpc_cmd bdev_malloc_delete "$malloc_name" 185} 186 187function test_thin_overprovisioning() { 188 malloc_name=$(rpc_cmd bdev_malloc_create $MALLOC_SIZE_MB $MALLOC_BS) 189 lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore "$malloc_name" lvs_test) 190 191 # Construct two thin provisioned lvol bdevs on created lvol store 192 # with size equal to free lvol store size 193 lvol_size_mb=$(round_down $((LVS_DEFAULT_CAPACITY_MB))) 194 lvol_size=$((lvol_size_mb * 1024 * 1024)) 195 lvol_uuid1=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid" lvol_test1 "$lvol_size_mb" -t) 196 lvol_uuid2=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid" lvol_test2 "$lvol_size_mb" -t) 197 198 nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid1" /dev/nbd0 199 nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid2" /dev/nbd1 200 # Fill first bdev to 50% of its space with specific pattern 201 fill_size=$((lvol_size_mb * 5 / 10 / LVS_DEFAULT_CLUSTER_SIZE_MB * LVS_DEFAULT_CLUSTER_SIZE_MB)) 202 fill_size=$((fill_size * 1024 * 1024)) 203 run_fio_test /dev/nbd0 0 $fill_size "write" "0xcc" 204 205 # Fill second bdev up to 50% of its space 206 run_fio_test /dev/nbd1 0 $fill_size "write" "0xcc" 207 208 # Fill rest of second bdev 209 # Check that error message occurred while filling second bdev with data 210 offset=$fill_size 211 fill_size_rest=$((lvol_size - fill_size)) 212 run_fio_test /dev/nbd1 "$offset" "$fill_size_rest" "write" "0xcc" && false 213 214 # Check if data on first disk stayed unchanged 215 run_fio_test /dev/nbd0 0 $fill_size "read" "0xcc" 216 run_fio_test /dev/nbd0 $offset $fill_size_rest "read" "0x00" 217 218 nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0 219 nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd1 220 221 rpc_cmd bdev_lvol_delete "$lvol_uuid2" 222 rpc_cmd bdev_lvol_delete "$lvol_uuid1" 223 rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid" 224 rpc_cmd bdev_malloc_delete "$malloc_name" 225} 226 227$SPDK_BIN_DIR/spdk_tgt & 228spdk_pid=$! 229trap 'killprocess "$spdk_pid"; exit 1' SIGINT SIGTERM EXIT 230waitforlisten $spdk_pid 231 232run_test "test_thin_lvol_check_space" test_thin_lvol_check_space 233run_test "test_thin_lvol_check_zeroes" test_thin_lvol_check_zeroes 234run_test "test_thin_lvol_check_integrity" test_thin_lvol_check_integrity 235run_test "test_thin_lvol_resize" test_thin_lvol_resize 236run_test "test_thin_overprovisioning" test_thin_overprovisioning 237 238trap - SIGINT SIGTERM EXIT 239killprocess $spdk_pid 240