1#!/usr/bin/env bash 2 3testdir=$(readlink -f $(dirname $0)) 4rootdir=$(readlink -f $testdir/../..) 5source $rootdir/test/common/autotest_common.sh 6source $rootdir/test/lvol/common.sh 7source $rootdir/test/bdev/nbd_common.sh 8 9# resize an lvol a few times 10function test_resize_lvol() { 11 # create an lvol store 12 malloc_name=$(rpc_cmd bdev_malloc_create $MALLOC_SIZE_MB $MALLOC_BS) 13 lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore "$malloc_name" lvs_test) 14 15 # calculate lvol size 16 lvol_size_mb=$(round_down $((LVS_DEFAULT_CAPACITY_MB / 4))) 17 lvol_size=$((lvol_size_mb * 1024 * 1024)) 18 19 # create an lvol on top 20 lvol_uuid=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid" lvol_test "$lvol_size_mb") 21 lvol=$(rpc_cmd bdev_get_bdevs -b "$lvol_uuid") 22 [ "$(jq -r '.[0].name' <<< "$lvol")" = "$lvol_uuid" ] 23 [ "$(jq -r '.[0].uuid' <<< "$lvol")" = "$lvol_uuid" ] 24 [ "$(jq -r '.[0].aliases[0]' <<< "$lvol")" = "lvs_test/lvol_test" ] 25 [ "$(jq -r '.[0].block_size' <<< "$lvol")" = "$MALLOC_BS" ] 26 [ "$(jq -r '.[0].num_blocks' <<< "$lvol")" = "$((lvol_size / MALLOC_BS))" ] 27 28 # resize the lvol to twice its original size 29 lvol_size_mb=$((lvol_size_mb * 2)) 30 lvol_size=$((lvol_size_mb * 1024 * 1024)) 31 rpc_cmd bdev_lvol_resize "$lvol_uuid" "$lvol_size_mb" 32 lvol=$(rpc_cmd bdev_get_bdevs -b "$lvol_uuid") 33 [ "$(jq -r '.[0].num_blocks' <<< "$lvol")" = "$((lvol_size / MALLOC_BS))" ] 34 35 # resize the lvol to four times its original size, use its name instead of uuid 36 lvol_size_mb=$((lvol_size_mb * 2)) 37 lvol_size=$((lvol_size_mb * 1024 * 1024)) 38 rpc_cmd bdev_lvol_resize lvs_test/lvol_test "$lvol_size_mb" 39 lvol=$(rpc_cmd bdev_get_bdevs -b "$lvol_uuid") 40 [ "$(jq -r '.[0].num_blocks' <<< "$lvol")" = "$((lvol_size / MALLOC_BS))" ] 41 42 # resize the lvol to 0 using lvol bdev alias 43 lvol_size_mb=0 44 lvol_size=0 45 rpc_cmd bdev_lvol_resize "lvs_test/lvol_test" "$lvol_size_mb" 46 lvol=$(rpc_cmd bdev_get_bdevs -b "$lvol_uuid") 47 [ "$(jq -r '.[0].num_blocks' <<< "$lvol")" = "$((lvol_size / MALLOC_BS))" ] 48 49 # clean up 50 rpc_cmd bdev_lvol_delete "$lvol_uuid" 51 rpc_cmd bdev_get_bdevs -b "$lvol_uuid" && false 52 rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid" 53 rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid" && false 54 rpc_cmd bdev_malloc_delete "$malloc_name" 55} 56 57# negative test for resizing a logical volume 58# call bdev_lvol_resize with logical volume which does not exist in configuration 59# call bdev_lvol_resize with size argument bigger than size of base bdev 60function test_resize_lvol_negative() { 61 # create an lvol store 62 malloc_name=$(rpc_cmd bdev_malloc_create $MALLOC_SIZE_MB $MALLOC_BS) 63 lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore "$malloc_name" lvs_test) 64 65 # create an lvol on top 66 lvol_uuid=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid" lvol_test "$LVS_DEFAULT_CAPACITY_MB") 67 68 # try to resize another, inexistent lvol 69 dummy_uuid="00000000-0000-0000-0000-000000000000" 70 rpc_cmd bdev_lvol_resize "$dummy_uuid" 0 && false 71 # just make sure the size of the real lvol did not change 72 lvol=$(rpc_cmd bdev_get_bdevs -b "$lvol_uuid") 73 [ "$(jq -r '.[0].num_blocks' <<< "$lvol")" = "$((LVS_DEFAULT_CAPACITY / MALLOC_BS))" ] 74 75 # try to resize an lvol to a size bigger than lvs 76 rpc_cmd bdev_lvol_resize "$lvol_uuid" "$MALLOC_SIZE_MB" && false 77 # just make sure the size of the real lvol did not change 78 lvol=$(rpc_cmd bdev_get_bdevs -b "$lvol_uuid") 79 [ "$(jq -r '.[0].num_blocks' <<< "$lvol")" = "$((LVS_DEFAULT_CAPACITY / MALLOC_BS))" ] 80 81 # clean up 82 rpc_cmd bdev_lvol_delete "$lvol_uuid" 83 rpc_cmd bdev_get_bdevs -b "$lvol_uuid" && false 84 rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid" 85 rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid" && false 86 rpc_cmd bdev_malloc_delete "$malloc_name" 87} 88 89# resize an lvol a few times 90function test_resize_lvol_with_io_traffic() { 91 # create an lvol store 92 malloc_name=$(rpc_cmd bdev_malloc_create $MALLOC_SIZE_MB $MALLOC_BS) 93 lvs_uuid=$(rpc_cmd bdev_lvol_create_lvstore "$malloc_name" lvs_test) 94 95 # calculate lvol size 96 lvol_size_mb=$(round_down $((LVS_DEFAULT_CAPACITY_MB / 2))) 97 lvol_size=$((lvol_size_mb * 1024 * 1024)) 98 99 # create an lvol on top 100 lvol_uuid=$(rpc_cmd bdev_lvol_create -u "$lvs_uuid" lvol_test "$lvol_size_mb") 101 lvol=$(rpc_cmd bdev_get_bdevs -b "$lvol_uuid") 102 [ "$(jq -r '.[0].name' <<< "$lvol")" = "$lvol_uuid" ] 103 [ "$(jq -r '.[0].uuid' <<< "$lvol")" = "$lvol_uuid" ] 104 [ "$(jq -r '.[0].aliases[0]' <<< "$lvol")" = "lvs_test/lvol_test" ] 105 [ "$(jq -r '.[0].block_size' <<< "$lvol")" = "$MALLOC_BS" ] 106 [ "$(jq -r '.[0].num_blocks' <<< "$lvol")" = "$((lvol_size / MALLOC_BS))" ] 107 108 # prepare to do some I/O 109 trap 'nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0; exit 1' SIGINT SIGTERM EXIT 110 nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid" /dev/nbd0 111 112 # write to the entire lvol 113 count=$((lvol_size / LVS_DEFAULT_CLUSTER_SIZE)) 114 dd if=/dev/urandom of=/dev/nbd0 oflag=direct bs="$LVS_DEFAULT_CLUSTER_SIZE" count=$count 115 116 # writing beyond lvol size should fail 117 offset=$((lvol_size / LVS_DEFAULT_CLUSTER_SIZE + 1)) 118 dd if=/dev/urandom of=/dev/nbd0 oflag=direct bs="$LVS_DEFAULT_CLUSTER_SIZE" seek=$offset count=1 && false 119 120 # resize the lvol to twice its original size 121 lvol_size_mb=$((lvol_size_mb * 2)) 122 lvol_size=$((lvol_size_mb * 1024 * 1024)) 123 rpc_cmd bdev_lvol_resize "$lvol_uuid" "$lvol_size_mb" 124 lvol=$(rpc_cmd bdev_get_bdevs -b "$lvol_uuid") 125 [ "$(jq -r '.[0].num_blocks' <<< "$lvol")" = "$((lvol_size / MALLOC_BS))" ] 126 127 # writing beyond the original lvol size should now succeed, we need 128 # to restart NBD though as it may still use the old, cached size 129 nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0 130 nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid" /dev/nbd0 131 dd if=/dev/urandom of=/dev/nbd0 oflag=direct bs="$LVS_DEFAULT_CLUSTER_SIZE" seek=$offset count=1 132 133 # lvol can't be downsized if they have any open descriptors, so close them now 134 trap - SIGINT SIGTERM EXIT 135 nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0 136 137 # resize lvol down to a single cluster 138 rpc_cmd bdev_lvol_resize "$lvol_uuid" "$LVS_DEFAULT_CLUSTER_SIZE_MB" 139 lvol=$(rpc_cmd bdev_get_bdevs -b "$lvol_uuid") 140 [ "$(jq -r '.[0].num_blocks' <<< "$lvol")" = "$((LVS_DEFAULT_CLUSTER_SIZE / MALLOC_BS))" ] 141 142 # make sure we can't write beyond the first cluster 143 trap 'nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0; exit 1' SIGINT SIGTERM EXIT 144 nbd_start_disks "$DEFAULT_RPC_ADDR" "$lvol_uuid" /dev/nbd0 145 dd if=/dev/urandom of=/dev/nbd0 oflag=direct bs="$LVS_DEFAULT_CLUSTER_SIZE" seek=1 count=1 && false 146 147 # clean up 148 trap - SIGINT SIGTERM EXIT 149 nbd_stop_disks "$DEFAULT_RPC_ADDR" /dev/nbd0 150 rpc_cmd bdev_lvol_delete "$lvol_uuid" 151 rpc_cmd bdev_get_bdevs -b "$lvol_uuid" && false 152 rpc_cmd bdev_lvol_delete_lvstore -u "$lvs_uuid" 153 rpc_cmd bdev_lvol_get_lvstores -u "$lvs_uuid" && false 154 rpc_cmd bdev_malloc_delete "$malloc_name" 155} 156 157# Positive test for destroying a logical_volume after resizing. 158# Call bdev_lvol_delete_lvstore with correct logical_volumes name. 159function test_destroy_after_bdev_lvol_resize_positive() { 160 local malloc_dev 161 local lvstore_name=lvs_test lvstore_uuid 162 local lbd_name=lbd_test bdev_uuid bdev_size 163 164 malloc_dev=$(rpc_cmd bdev_malloc_create 256 "$MALLOC_BS") 165 lvstore_uuid=$(rpc_cmd bdev_lvol_create_lvstore "$malloc_dev" "$lvstore_name") 166 167 get_lvs_jq bdev_lvol_get_lvstores -u "$lvstore_uuid" 168 [[ ${jq_out["uuid"]} == "$lvstore_uuid" ]] 169 [[ ${jq_out["name"]} == "$lvstore_name" ]] 170 171 bdev_size=$(round_down $((LVS_DEFAULT_CAPACITY_MB / 4))) 172 bdev_uuid=$(rpc_cmd bdev_lvol_create -u "$lvstore_uuid" "$lbd_name" "$bdev_size") 173 174 # start resizing in the following fashion: 175 # - size is equal to one quarter of size malloc bdev plus 4 MB 176 # - size is equal half of size malloc bdev 177 # - size is equal to three quarters of size malloc bdev 178 # - size is equal to size if malloc bdev minus 4 MB 179 # - size is equal 0 MiB 180 local resize 181 for resize in \ 182 "$bdev_size" \ 183 $((bdev_size + 4)) \ 184 $((bdev_size * 2)) \ 185 $((bdev_size * 3)) \ 186 $((bdev_size * 4 - 4)) \ 187 0; do 188 resize=$(round_down $((resize / 4))) 189 rpc_cmd bdev_lvol_resize "$bdev_uuid" "$resize" 190 191 get_bdev_jq bdev_get_bdevs -b "$bdev_uuid" 192 [[ ${jq_out["name"]} == "$bdev_uuid" ]] 193 [[ ${jq_out["name"]} == "${jq_out["uuid"]}" ]] 194 ((jq_out["block_size"] == MALLOC_BS)) 195 ((jq_out["num_blocks"] * jq_out["block_size"] == resize * 1024 ** 2)) 196 done 197 198 # cleanup 199 rpc_cmd bdev_lvol_delete "$bdev_uuid" 200 rpc_cmd bdev_lvol_delete_lvstore -u "$lvstore_uuid" 201 rpc_cmd bdev_get_bdevs -b "$bdev_uuid" && false 202 rpc_cmd bdev_lvol_get_lvstores -u "$lvstore_uuid" && false 203 rpc_cmd bdev_malloc_delete "$malloc_dev" 204 check_leftover_devices 205} 206 207modprobe nbd 208$SPDK_BIN_DIR/spdk_tgt & 209spdk_pid=$! 210trap 'killprocess "$spdk_pid"; exit 1' SIGINT SIGTERM EXIT 211waitforlisten $spdk_pid 212 213run_test "test_resize_lvol" test_resize_lvol 214run_test "test_resize_lvol_negative" test_resize_lvol_negative 215run_test "test_resize_lvol_with_io_traffic" test_resize_lvol_with_io_traffic 216run_test "test_destroy_after_bdev_lvol_resize_positive" test_destroy_after_bdev_lvol_resize_positive 217 218trap - SIGINT SIGTERM EXIT 219killprocess $spdk_pid 220