Commit 1ca1a8c7 authored by Vasilii Ivanov's avatar Vasilii Ivanov Committed by Tomasz Zawadzki
Browse files

bdev: extend bdev_enable_histogram API



Extend API to provide granularity and min/max values
during histogram enabling for bdev. It allows to lower
histogram size and save memory by reducing accuracy.

Change-Id: I10ce6cba0f4e6dba5c83f6b9117ed3df8d2b91f7
Signed-off-by: default avatarVasilii Ivanov <iwanovvvasilij@gmail.com>
Reviewed-on: https://review.spdk.io/c/spdk/spdk/+/25384


Reviewed-by: default avatarJim Harris <jim.harris@nvidia.com>
Tested-by: default avatarSPDK Automated Test System <spdkbot@gmail.com>
Reviewed-by: default avatarShuhei Matsumoto <smatsumoto@nvidia.com>
parent b42c45d8
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -2813,6 +2813,9 @@ Name | Optional | Type | Description
name                    | Required | string      | Block device name
enable                  | Required | boolean     | Enable or disable histogram on specified device
opc                     | Optional | string      | IO type name
granularity             | Optional | number      | Histogram bucket granularity. Default: 7
min_nsec                | Optional | number      | Min value in nanoseconds to track. Default: 0
max_nsec                | Optional | number      | Max value in nanoseconds to track. Default: UINT64_T (max possible value)

#### Example

@@ -2824,9 +2827,12 @@ Example request:
  "id": 1,
  "method": "bdev_enable_histogram",
  "params": {
    "name": "Nvme0n1"
    "enable": true
    "opc": "read"
    "name": "Nvme0n1",
    "enable": true,
    "opc": "read",
    "granularity": 7,
    "min_nsec": 1000,
    "max_nsec": 1000000000,
  }
}
~~~
@@ -2857,6 +2863,8 @@ Name | Description
------------------------| -----------
histogram               | Base64 encoded histogram
granularity             | Granularity of the histogram buckets
min_range               | Minimal range tracked in histogram
max_range               | Maximal range tracked in histogram
tsc_rate                | Ticks per second

#### Example
@@ -2885,6 +2893,9 @@ Note that histogram field is trimmed, actual encoded histogram length is ~80kb.
    "histogram": "AAAAAAAAAAAAAA...AAAAAAAAA==",
    "tsc_rate": 2300000000,
    "granularity": 7
    "min_range": 5,
    "max_range": 25,
    "tsc_rate": 2300000000
  }
}
~~~
+6 −1
Original line number Diff line number Diff line
@@ -132,9 +132,14 @@ struct spdk_bdev_enable_histogram_opts {
	/** Size of this structure in bytes */
	size_t size;

	/** Min value in nanoseconds to track in histogram */
	uint64_t min_nsec;
	/** Max value in nanoseconds to track in histogram */
	uint64_t max_nsec;
	uint8_t io_type;
	uint8_t granularity;
} __attribute__((packed));
SPDK_STATIC_ASSERT(sizeof(struct spdk_bdev_enable_histogram_opts) == 9, "Incorrect size");
SPDK_STATIC_ASSERT(sizeof(struct spdk_bdev_enable_histogram_opts) == 26, "Incorrect size");

/** bdev QoS rate limit type */
enum spdk_bdev_qos_rate_limit_type {
+6 −3
Original line number Diff line number Diff line
@@ -768,6 +768,9 @@ struct spdk_bdev {
		bool	 histogram_enabled;
		bool	 histogram_in_progress;
		uint8_t	 histogram_io_type;
		uint8_t	 histogram_granularity;
		uint64_t histogram_min_val;
		uint64_t histogram_max_val;

		/** Currently locked ranges for this bdev.  Used to populate new channels. */
		lba_range_tailq_t locked_ranges;
+13 −2
Original line number Diff line number Diff line
@@ -10033,7 +10033,8 @@ bdev_histogram_enable_channel(struct spdk_bdev_channel_iter *i, struct spdk_bdev
	int status = 0;

	if (ch->histogram == NULL) {
		ch->histogram = spdk_histogram_data_alloc();
		ch->histogram = spdk_histogram_data_alloc_sized_ext(bdev->internal.histogram_granularity,
				bdev->internal.histogram_min_val, bdev->internal.histogram_max_val);
		if (ch->histogram == NULL) {
			status = -ENOMEM;
		}
@@ -10072,6 +10073,13 @@ spdk_bdev_histogram_enable_ext(struct spdk_bdev *bdev, spdk_bdev_histogram_statu

	bdev->internal.histogram_enabled = enable;
	bdev->internal.histogram_io_type = opts->io_type;
	bdev->internal.histogram_granularity = opts->granularity;
	bdev->internal.histogram_min_val = opts->min_nsec * spdk_get_ticks_hz() / SPDK_SEC_TO_NSEC;
	if (opts->max_nsec == UINT64_MAX) {
		bdev->internal.histogram_max_val = UINT64_MAX;
	} else {
		bdev->internal.histogram_max_val = opts->max_nsec * spdk_get_ticks_hz() / SPDK_SEC_TO_NSEC;
	}

	if (enable) {
		/* Allocate histogram for each channel */
@@ -10109,10 +10117,13 @@ spdk_bdev_enable_histogram_opts_init(struct spdk_bdev_enable_histogram_opts *opt
        } \

	SET_FIELD(io_type, 0);
	SET_FIELD(granularity, SPDK_HISTOGRAM_GRANULARITY_DEFAULT);
	SET_FIELD(min_nsec, 0);
	SET_FIELD(max_nsec, UINT64_MAX);

	/* You should not remove this statement, but need to update the assert statement
	 * if you add a new field, and also add a corresponding SET_FIELD statement */
	SPDK_STATIC_ASSERT(sizeof(struct spdk_bdev_enable_histogram_opts) == 9, "Incorrect size");
	SPDK_STATIC_ASSERT(sizeof(struct spdk_bdev_enable_histogram_opts) == 26, "Incorrect size");

#undef FIELD_OK
#undef SET_FIELD
+22 −3
Original line number Diff line number Diff line
@@ -991,6 +991,9 @@ struct rpc_bdev_enable_histogram_request {
	char *name;
	bool enable;
	char *opc;
	uint8_t granularity;
	uint64_t min_nsec;
	uint64_t max_nsec;
};

static void
@@ -1004,6 +1007,9 @@ static const struct spdk_json_object_decoder rpc_bdev_enable_histogram_request_d
	{"name", offsetof(struct rpc_bdev_enable_histogram_request, name), spdk_json_decode_string},
	{"enable", offsetof(struct rpc_bdev_enable_histogram_request, enable), spdk_json_decode_bool},
	{"opc", offsetof(struct rpc_bdev_enable_histogram_request, opc), spdk_json_decode_string, true},
	{"granularity", offsetof(struct rpc_bdev_enable_histogram_request, granularity), spdk_json_decode_uint8, true},
	{"min_nsec", offsetof(struct rpc_bdev_enable_histogram_request, min_nsec), spdk_json_decode_uint64, true},
	{"max_nsec", offsetof(struct rpc_bdev_enable_histogram_request, max_nsec), spdk_json_decode_uint64, true},
};

static void
@@ -1022,7 +1028,10 @@ static void
rpc_bdev_enable_histogram(struct spdk_jsonrpc_request *request,
			  const struct spdk_json_val *params)
{
	struct rpc_bdev_enable_histogram_request req = {NULL};
	struct rpc_bdev_enable_histogram_request req = {.granularity = SPDK_HISTOGRAM_GRANULARITY_DEFAULT,
		       .min_nsec = 0,
		       .max_nsec = UINT64_MAX
	};
	struct spdk_bdev_desc *desc;
	int rc;
	struct spdk_bdev_enable_histogram_opts opts = {};
@@ -1056,6 +1065,10 @@ rpc_bdev_enable_histogram(struct spdk_jsonrpc_request *request,
		opts.io_type = (uint8_t) io_type;
	}

	opts.granularity = req.granularity;
	opts.min_nsec = req.min_nsec;
	opts.max_nsec = req.max_nsec;

	spdk_bdev_histogram_enable_ext(spdk_bdev_desc_get_bdev(desc), bdev_histogram_status_cb,
				       request, req.enable, &opts);

@@ -1120,6 +1133,8 @@ _rpc_bdev_histogram_data_cb(void *cb_arg, int status, struct spdk_histogram_data
	spdk_json_write_object_begin(w);
	spdk_json_write_named_string(w, "histogram", encoded_histogram);
	spdk_json_write_named_int64(w, "granularity", histogram->granularity);
	spdk_json_write_named_uint32(w, "min_range", histogram->min_range);
	spdk_json_write_named_uint32(w, "max_range", histogram->max_range);
	spdk_json_write_named_int64(w, "tsc_rate", spdk_get_ticks_hz());
	spdk_json_write_object_end(w);
	spdk_jsonrpc_end_result(request, w);
@@ -1137,6 +1152,7 @@ rpc_bdev_get_histogram(struct spdk_jsonrpc_request *request,
	struct rpc_bdev_get_histogram_request req = {NULL};
	struct spdk_histogram_data *histogram;
	struct spdk_bdev_desc *desc;
	struct spdk_bdev *bdev;
	int rc;

	if (spdk_json_decode_object(params, rpc_bdev_get_histogram_request_decoders,
@@ -1154,14 +1170,17 @@ rpc_bdev_get_histogram(struct spdk_jsonrpc_request *request,
		goto cleanup;
	}

	histogram = spdk_histogram_data_alloc();
	bdev = spdk_bdev_desc_get_bdev(desc);

	histogram = spdk_histogram_data_alloc_sized_ext(bdev->internal.histogram_granularity,
			bdev->internal.histogram_min_val, bdev->internal.histogram_max_val);
	if (histogram == NULL) {
		spdk_bdev_close(desc);
		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
		goto cleanup;
	}

	spdk_bdev_histogram_get(spdk_bdev_desc_get_bdev(desc), histogram,
	spdk_bdev_histogram_get(bdev, histogram,
				_rpc_bdev_histogram_data_cb, request);

	spdk_bdev_close(desc);
Loading