Commit 05b43152 authored by GangCao's avatar GangCao Committed by Ben Walker
Browse files

QoS/Bdev: add RPC support for Read/Write separate bandwidth limits



This patch adds the RPC support for the Read/Write separate
bandwidth limit controls. The basic usage as following:

usage:
rpc.py set_bdev_qos_limit [-h] [--rw_ios_per_sec RW_IOS_PER_SEC]
                               [--rw_mbytes_per_sec RW_MBYTES_PER_SEC]
                               [--r_mbytes_per_sec R_MBYTES_PER_SEC]
                               [--w_mbytes_per_sec W_MBYTES_PER_SEC]
                               name

positional arguments:
  name       Blockdev name to set QoS. Example: Malloc0

optional arguments:
  -h, --help show this help message and exit
  --rw_ios_per_sec RW_IOS_PER_SEC
             R/W IOs per second limit (>=10000, example: 20000).
             0 means unlimited.
  --rw_mbytes_per_sec RW_MBYTES_PER_SEC
             R/W megabytes per second limit (>=10, example: 100).
             0 means unlimited.
  --r_mbytes_per_sec R_MBYTES_PER_SEC
             Read megabytes per second limit (>=10, example: 100).
             0 means unlimited.
  --w_mbytes_per_sec W_MBYTES_PER_SEC
             Write megabytes per second limit (>=10, example: 100).
             0 means unlimited.

Change-Id: I822ec4814d21adff9826ce03a6af3783b1b98f44
Signed-off-by: default avatarGangCao <gang.cao@intel.com>
Reviewed-on: https://review.gerrithub.io/c/417650


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent 316cb3b1
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -676,6 +676,8 @@ Name | Optional | Type | Description
name                    | Required | string      | Block device name
rw_ios_per_sec          | Optional | number      | Number of R/W I/Os per second to allow. 0 means unlimited.
rw_mbytes_per_sec       | Optional | number      | Number of R/W megabytes per second to allow. 0 means unlimited.
r_mbytes_per_sec        | Optional | number      | Number of Read megabytes per second to allow. 0 means unlimited.
w_mbytes_per_sec        | Optional | number      | Number of Write megabytes per second to allow. 0 means unlimited.

### Example

@@ -689,6 +691,8 @@ Example request:
    "name": "Malloc0"
    "rw_ios_per_sec": 20000
    "rw_mbytes_per_sec": 100
    "r_mbytes_per_sec": 50
    "w_mbytes_per_sec": 50
  }
}
~~~
+10 −0
Original line number Diff line number Diff line
@@ -522,6 +522,16 @@ static const struct spdk_json_object_decoder rpc_set_bdev_qos_limit_decoders[] =
					      limits[SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT]),
		spdk_json_decode_uint64, true
	},
	{
		"r_mbytes_per_sec", offsetof(struct rpc_set_bdev_qos_limit,
					     limits[SPDK_BDEV_QOS_R_BPS_RATE_LIMIT]),
		spdk_json_decode_uint64, true
	},
	{
		"w_mbytes_per_sec", offsetof(struct rpc_set_bdev_qos_limit,
					     limits[SPDK_BDEV_QOS_W_BPS_RATE_LIMIT]),
		spdk_json_decode_uint64, true
	},
};

static void
+9 −1
Original line number Diff line number Diff line
@@ -447,7 +447,9 @@ if __name__ == "__main__":
        rpc.bdev.set_bdev_qos_limit(args.client,
                                    name=args.name,
                                    rw_ios_per_sec=args.rw_ios_per_sec,
                                    rw_mbytes_per_sec=args.rw_mbytes_per_sec)
                                    rw_mbytes_per_sec=args.rw_mbytes_per_sec,
                                    r_mbytes_per_sec=args.r_mbytes_per_sec,
                                    w_mbytes_per_sec=args.w_mbytes_per_sec)

    p = subparsers.add_parser('set_bdev_qos_limit', help='Set QoS rate limit on a blockdev')
    p.add_argument('name', help='Blockdev name to set QoS. Example: Malloc0')
@@ -457,6 +459,12 @@ if __name__ == "__main__":
    p.add_argument('--rw_mbytes_per_sec',
                   help="R/W megabytes per second limit (>=10, example: 100). 0 means unlimited.",
                   type=int, required=False)
    p.add_argument('--r_mbytes_per_sec',
                   help="Read megabytes per second limit (>=10, example: 100). 0 means unlimited.",
                   type=int, required=False)
    p.add_argument('--w_mbytes_per_sec',
                   help="Write megabytes per second limit (>=10, example: 100). 0 means unlimited.",
                   type=int, required=False)
    p.set_defaults(func=set_bdev_qos_limit)

    def bdev_inject_error(args):
+13 −1
Original line number Diff line number Diff line
@@ -518,13 +518,21 @@ def set_bdev_qd_sampling_period(client, name, period):
    return client.call('set_bdev_qd_sampling_period', params)


def set_bdev_qos_limit(client, name, rw_ios_per_sec=None, rw_mbytes_per_sec=None):
def set_bdev_qos_limit(
        client,
        name,
        rw_ios_per_sec=None,
        rw_mbytes_per_sec=None,
        r_mbytes_per_sec=None,
        w_mbytes_per_sec=None):
    """Set QoS rate limit on a block device.

    Args:
        name: name of block device
        rw_ios_per_sec: R/W IOs per second limit (>=10000, example: 20000). 0 means unlimited.
        rw_mbytes_per_sec: R/W megabytes per second limit (>=10, example: 100). 0 means unlimited.
        r_mbytes_per_sec: Read megabytes per second limit (>=10, example: 100). 0 means unlimited.
        w_mbytes_per_sec: Write megabytes per second limit (>=10, example: 100). 0 means unlimited.
    """
    params = {}
    params['name'] = name
@@ -532,6 +540,10 @@ def set_bdev_qos_limit(client, name, rw_ios_per_sec=None, rw_mbytes_per_sec=None
        params['rw_ios_per_sec'] = rw_ios_per_sec
    if rw_mbytes_per_sec is not None:
        params['rw_mbytes_per_sec'] = rw_mbytes_per_sec
    if r_mbytes_per_sec is not None:
        params['r_mbytes_per_sec'] = r_mbytes_per_sec
    if w_mbytes_per_sec is not None:
        params['w_mbytes_per_sec'] = w_mbytes_per_sec
    return client.call('set_bdev_qos_limit', params)


+6 −5
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ function check_qos_works_well() {
		start_io_count=$($rpc_py get_bdevs_iostat -b $3 | jq -r '.[1].bytes_read')
	fi

	$fio_py 512 64 randread 5
	$fio_py 1024 128 randread 5

	if [ $LIMIT_TYPE = IOPS ]; then
		end_io_count=$($rpc_py get_bdevs_iostat -b $3 | jq -r '.[1].num_read_ops')
@@ -61,7 +61,8 @@ timing_enter qos
MALLOC_BDEV_SIZE=64
MALLOC_BLOCK_SIZE=512
IOPS_LIMIT=20000
BANDWIDTH_LIMIT=10
BANDWIDTH_LIMIT=20
READ_BANDWIDTH_LIMIT=10
LIMIT_TYPE=IOPS
rpc_py="$rootdir/scripts/rpc.py"
fio_py="$rootdir/scripts/fio.py"
@@ -114,9 +115,9 @@ check_qos_works_well true $BANDWIDTH_LIMIT Malloc0
$rpc_py set_bdev_qos_limit Malloc0 --rw_mbytes_per_sec 0
check_qos_works_well false $BANDWIDTH_LIMIT Malloc0

# Limit the I/O bandwidth rate again.
$rpc_py set_bdev_qos_limit Malloc0 --rw_mbytes_per_sec $BANDWIDTH_LIMIT
check_qos_works_well true $BANDWIDTH_LIMIT Malloc0
# Limit the I/O bandwidth rate again with both read/write and read/only.
$rpc_py set_bdev_qos_limit Malloc0 --rw_mbytes_per_sec $BANDWIDTH_LIMIT --r_mbytes_per_sec $READ_BANDWIDTH_LIMIT
check_qos_works_well true $READ_BANDWIDTH_LIMIT Malloc0
echo "I/O bandwidth limiting tests successful"

iscsicleanup