sma: support bdev-based QoS for NVMe/vfiouser devices
test/sma verifies that bdev-based QoS settings are correctly applied on vfio-user devices. Signed-off-by: Sebastian Brzezinka <sebastian.brzezinka@intel.com> Change-Id: I0109bfdbcb95d6e683c45c3dbdb2c3c175f10aa2 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14337 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com> Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com>
This commit is contained in:
parent
045152b220
commit
dfc5461741
@ -7,6 +7,7 @@ from socket import AddressFamily
|
||||
import grpc
|
||||
from google.protobuf import wrappers_pb2 as wrap
|
||||
from spdk.rpc.client import JSONRPCException
|
||||
from spdk.sma import qos
|
||||
|
||||
from ..common import format_volume_id, volume_id_to_nguid
|
||||
from ..proto import sma_pb2
|
||||
@ -279,3 +280,34 @@ class NvmfVfioDeviceManager(DeviceManager):
|
||||
|
||||
def owns_device(self, id):
|
||||
return id.startswith(self._prefix)
|
||||
|
||||
def set_qos(self, request):
|
||||
nqn = request.device_handle[len(f'{self._prefix}:'):]
|
||||
volume = format_volume_id(request.volume_id)
|
||||
if volume is None:
|
||||
raise DeviceException(grpc.StatusCode.INVALID_ARGUMENT,
|
||||
'Invalid volume ID')
|
||||
try:
|
||||
with self._client() as client:
|
||||
# Make sure that a volume exists and is attached to the device
|
||||
bdev = self._get_bdev(client, volume)
|
||||
if bdev is None:
|
||||
raise DeviceException(grpc.StatusCode.NOT_FOUND,
|
||||
'No volume associated with volume_id could be found')
|
||||
subsys = self._get_subsys(client, nqn)
|
||||
if subsys is None:
|
||||
raise DeviceException(grpc.StatusCode.NOT_FOUND,
|
||||
'No device associated with device_handle could be found')
|
||||
ns = self._get_ns(bdev, subsys)
|
||||
if ns is None:
|
||||
raise DeviceException(grpc.StatusCode.INVALID_ARGUMENT,
|
||||
'Specified volume is not attached to the device')
|
||||
qos.set_volume_bdev_qos(client, request)
|
||||
except qos.QosException as ex:
|
||||
raise DeviceException(ex.code, ex.message)
|
||||
except JSONRPCException:
|
||||
raise DeviceException(grpc.StatusCode.INTERNAL,
|
||||
'Failed to set QoS')
|
||||
|
||||
def get_qos_capabilities(self, request):
|
||||
return qos.get_bdev_qos_capabilities()
|
||||
|
@ -295,5 +295,57 @@ detach_volume "$device0" "$uuid0"
|
||||
delete_device "$device0"
|
||||
[[ $(rpc_cmd bdev_get_bdevs | jq -r '.[] | select(.product_name == "crypto")' | jq -r length) -eq 0 ]]
|
||||
|
||||
# Test qos
|
||||
device_vfio_user=1
|
||||
device0=$(create_device 0 0 | jq -r '.handle')
|
||||
attach_volume "$device0" "$uuid0"
|
||||
|
||||
# First check the capabilities
|
||||
diff <(get_qos_caps $device_vfio_user | jq --sort-keys) <(
|
||||
jq --sort-keys <<- CAPS
|
||||
{
|
||||
"max_volume_caps": {
|
||||
"rw_iops": true,
|
||||
"rd_bandwidth": true,
|
||||
"wr_bandwidth": true,
|
||||
"rw_bandwidth": true
|
||||
}
|
||||
}
|
||||
CAPS
|
||||
)
|
||||
|
||||
"$rootdir/scripts/sma-client.py" <<- EOF
|
||||
{
|
||||
"method": "SetQos",
|
||||
"params": {
|
||||
"device_handle": "$device0",
|
||||
"volume_id": "$(uuid2base64 $uuid0)",
|
||||
"maximum": {
|
||||
"rd_iops": 0,
|
||||
"wr_iops": 0,
|
||||
"rw_iops": 3,
|
||||
"rd_bandwidth": 4,
|
||||
"wr_bandwidth": 5,
|
||||
"rw_bandwidth": 6
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# Make sure that limits were changed
|
||||
diff <(rpc_cmd bdev_get_bdevs -b null0 | jq --sort-keys '.[].assigned_rate_limits') <(
|
||||
jq --sort-keys <<- EOF
|
||||
{
|
||||
"rw_ios_per_sec": 3000,
|
||||
"rw_mbytes_per_sec": 6,
|
||||
"r_mbytes_per_sec": 4,
|
||||
"w_mbytes_per_sec": 5
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
detach_volume "$device0" "$uuid0"
|
||||
delete_device "$device0"
|
||||
|
||||
cleanup
|
||||
trap - SIGINT SIGTERM EXIT
|
||||
|
Loading…
Reference in New Issue
Block a user