Commit f3cef5e1 authored by Atul Malakar's avatar Atul Malakar Committed by Jim Harris
Browse files

bdev: Add bdev_enable_histogram filter



Added new --opc  parameter to bdev_enable_histogram RPC.
It facilitates user to capture histogram data points for the specified
IO type.

Refer to bdev_get_bdevs RPC for list of io types.

Change-Id: I3b70296ae32adc80f894e19426af22da0ac70802
Signed-off-by: default avatarAtul Malakar <a.malakar@samsung.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/23488


Reviewed-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 0e983c56
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -2704,6 +2704,7 @@ 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

#### Example

@@ -2717,6 +2718,7 @@ Example request:
  "params": {
    "name": "Nvme0n1"
    "enable": true
    "opc": "read"
  }
}
~~~
+44 −0
Original line number Diff line number Diff line
@@ -125,6 +125,17 @@ enum spdk_bdev_io_type {
	SPDK_BDEV_NUM_IO_TYPES /* Keep last */
};

/**
 * Structure with optional enable histogram parameters
 */
struct spdk_bdev_enable_histogram_opts {
	/** Size of this structure in bytes */
	size_t size;

	uint8_t io_type;
} __attribute__((packed));
SPDK_STATIC_ASSERT(sizeof(struct spdk_bdev_enable_histogram_opts) == 9, "Incorrect size");

/** bdev QoS rate limit type */
enum spdk_bdev_qos_rate_limit_type {
	/** IOPS rate limit for both read and write */
@@ -582,6 +593,15 @@ bool spdk_bdev_io_type_supported(struct spdk_bdev *bdev, enum spdk_bdev_io_type
 */
const char *spdk_bdev_get_io_type_name(enum spdk_bdev_io_type io_type);

/**
 * Return the io_type based on the io_type_string.
 *
 * \param io_type_string Name of the IO type as a null-terminated string.
 * \return io_type The specific I/O type like read, write, flush, unmap etc.
 * This will map to enum spdk_bdev_io_type.
 */
int spdk_bdev_get_io_type(const char *io_type_string);

/**
 * Output driver-specific information to a JSON stream.
 *
@@ -2096,6 +2116,30 @@ uint64_t spdk_bdev_io_get_seek_offset(const struct spdk_bdev_io *bdev_io);
void spdk_bdev_histogram_enable(struct spdk_bdev *bdev, spdk_bdev_histogram_status_cb cb_fn,
				void *cb_arg, bool enable);

/**
 * Enable or disable collecting histogram data on a bdev. This differs from
 * spdk_bdev_histogram_enable by allowing Optional structure with extended enable
 * histogram options.
 *
 * \param bdev Block device.
 * \param cb_fn Callback function to be called when histograms are enabled.
 * \param cb_arg Argument to pass to cb_fn.
 * \param enable Enable/disable flag
 * \param opts Optional structure with extended enable histogram options. `size` member of this structure
 *             is used for ABI compatibility and must be set to sizeof(struct spdk_bdev_enable_histogram_opts).
 */
void spdk_bdev_histogram_enable_ext(struct spdk_bdev *bdev, spdk_bdev_histogram_status_cb cb_fn,
				    void *cb_arg, bool enable, struct spdk_bdev_enable_histogram_opts *opts);

/**
 * Initialize bdev enable histogram options structure.
 *
 * \param opts The structure to initialize.
 * \param size The size of *opts.
 */
void
spdk_bdev_enable_histogram_opts_init(struct spdk_bdev_enable_histogram_opts *opts, size_t size);

/**
 * Get aggregated histogram data from a bdev. Callback provides merged histogram
 * for specified bdev.
+1 −0
Original line number Diff line number Diff line
@@ -740,6 +740,7 @@ struct spdk_bdev {
		/** histogram enabled on this bdev */
		bool	histogram_enabled;
		bool	histogram_in_progress;
		uint8_t	histogram_io_type;

		/** Currently locked ranges for this bdev.  Used to populate new channels. */
		lba_range_tailq_t locked_ranges;
+2 −2
Original line number Diff line number Diff line
@@ -7,8 +7,8 @@
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk

SO_VER := 15
SO_MINOR := 1
SO_VER := 16
SO_MINOR := 0

C_SRCS = bdev.c bdev_rpc.c bdev_zone.c part.c scsi_nvme.c
C_SRCS-$(CONFIG_VTUNE) += vtune.c
+75 −3
Original line number Diff line number Diff line
@@ -1886,6 +1886,12 @@ bdev_enable_histogram_config_json(struct spdk_bdev *bdev, struct spdk_json_write
	spdk_json_write_named_string(w, "name", bdev->name);

	spdk_json_write_named_bool(w, "enable", bdev->internal.histogram_enabled);

	if (bdev->internal.histogram_io_type) {
		spdk_json_write_named_string(w, "opc",
					     spdk_bdev_get_io_type_name(bdev->internal.histogram_io_type));
	}

	spdk_json_write_object_end(w);

	spdk_json_write_object_end(w);
@@ -3737,6 +3743,20 @@ spdk_bdev_get_io_type_name(enum spdk_bdev_io_type io_type)
	return g_io_type_strings[io_type];
}

int
spdk_bdev_get_io_type(const char *io_type_string)
{
	int i;

	for (i = SPDK_BDEV_IO_TYPE_READ; i < SPDK_BDEV_NUM_IO_TYPES; ++i) {
		if (!strcmp(io_type_string, g_io_type_strings[i])) {
			return i;
		}
	}

	return -1;
}

uint64_t
spdk_bdev_io_get_submit_tsc(struct spdk_bdev_io *bdev_io)
{
@@ -7290,8 +7310,14 @@ bdev_io_complete(void *ctx)
			      bdev_io->internal.caller_ctx, bdev_ch->queue_depth);

	if (bdev_ch->histogram) {
		if (bdev_io->bdev->internal.histogram_io_type == 0 ||
		    bdev_io->bdev->internal.histogram_io_type == bdev_io->type) {
			/*
			 * Tally all I/O types if the histogram_io_type is set to 0.
			 */
			spdk_histogram_data_tally(bdev_ch->histogram, tsc_diff);
		}
	}

	bdev_io_update_io_stat(bdev_io, tsc_diff);
	_bdev_io_complete(bdev_io);
@@ -9475,8 +9501,8 @@ bdev_histogram_enable_channel(struct spdk_bdev_channel_iter *i, struct spdk_bdev
}

void
spdk_bdev_histogram_enable(struct spdk_bdev *bdev, spdk_bdev_histogram_status_cb cb_fn,
			   void *cb_arg, bool enable)
spdk_bdev_histogram_enable_ext(struct spdk_bdev *bdev, spdk_bdev_histogram_status_cb cb_fn,
			       void *cb_arg, bool enable, struct spdk_bdev_enable_histogram_opts *opts)
{
	struct spdk_bdev_histogram_ctx *ctx;

@@ -9503,6 +9529,7 @@ spdk_bdev_histogram_enable(struct spdk_bdev *bdev, spdk_bdev_histogram_status_cb
	spdk_spin_unlock(&bdev->internal.spinlock);

	bdev->internal.histogram_enabled = enable;
	bdev->internal.histogram_io_type = opts->io_type;

	if (enable) {
		/* Allocate histogram for each channel */
@@ -9514,6 +9541,51 @@ spdk_bdev_histogram_enable(struct spdk_bdev *bdev, spdk_bdev_histogram_status_cb
	}
}

void
spdk_bdev_enable_histogram_opts_init(struct spdk_bdev_enable_histogram_opts *opts, size_t size)
{
	if (opts == NULL) {
		SPDK_ERRLOG("opts should not be NULL\n");
		assert(opts != NULL);
		return;
	}
	if (size == 0) {
		SPDK_ERRLOG("size should not be zero\n");
		assert(size != 0);
		return;
	}

	memset(opts, 0, size);
	opts->size = size;

#define FIELD_OK(field) \
        offsetof(struct spdk_bdev_enable_histogram_opts, field) + sizeof(opts->field) <= size

#define SET_FIELD(field, value) \
        if (FIELD_OK(field)) { \
                opts->field = value; \
        } \

	SET_FIELD(io_type, 0);

	/* 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");

#undef FIELD_OK
#undef SET_FIELD
}

void
spdk_bdev_histogram_enable(struct spdk_bdev *bdev, spdk_bdev_histogram_status_cb cb_fn,
			   void *cb_arg, bool enable)
{
	struct spdk_bdev_enable_histogram_opts opts;

	spdk_bdev_enable_histogram_opts_init(&opts, sizeof(opts));
	spdk_bdev_histogram_enable_ext(bdev, cb_fn, cb_arg, enable, &opts);
}

struct spdk_bdev_histogram_data_ctx {
	spdk_bdev_histogram_data_cb cb_fn;
	void *cb_arg;
Loading