Commit 90ba272c authored by Changqi Lu's avatar Changqi Lu Committed by Tomasz Zawadzki
Browse files

lib/iscsi: add rpc method iscsi_enable_histogram



SPDK provides a histogram function about io delay in the bdev layer,
but when using the iscsi protocol, especially when the io size is large
and io splitting is required, we need to be more concerned about
the end-to-end io latency of the iscsi layer.

An example of WRITE16 command with bulk data:
    I                T
 WRITE16        ->
                <- R2T
 DATAOUT        ->
 DATAOUT        ->
   ...
 DATAOUT(FINAL) ->

Therefore, a new rpc method is added to control the opening or
closing of the histogram function.

Change-Id: Iec96a54a8da2a58c0542e7b38e2161ade505f09f
Signed-off-by: default avatarChangqi Lu <luchangqi.123@bytedance.com>
Signed-off-by: default avatarzhenwei pi <pizhenwei@bytedance.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/21002


Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarShuhei Matsumoto <smatsumoto@nvidia.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 8e8f0434
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@ Added `bdev_uring_rescan` RPC to allow rescaning the size of uring bdev.

Added `iscsi_get_stats` RPC method to get stat information about all active connections.

Added `iscsi_enable_histogram` RPC method to enable or disable histogram for specified iscsi target.

### trace

Merged `struct spdk_trace_flags` and `struct spdk_trace_histories` into
+37 −0
Original line number Diff line number Diff line
@@ -7978,6 +7978,43 @@ Example response:
}
~~~

### iscsi_enable_histogram {#rpc_iscsi_enable_histogram}

Control whether collecting data for histogram is enabled for specified iscsi target node.

#### Parameters

Name                    | Optional | Type        | Description
----------------------- | -------- | ----------- | -----------
name                    | Required | string      | Iscsi target node name
enable                  | Required | boolean     | Enable or disable histogram on specified target node

#### Example

Example request:

~~~json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "iscsi_enable_histogram",
  "params": {
    "name": "iqn.2016-06.io.spdk:target1"
    "enable": true
  }
}
~~~

Example response:

~~~json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": true
}
~~~

## NVMe-oF Target {#jsonrpc_components_nvmf_tgt}

### nvmf_create_transport method {#rpc_nvmf_create_transport}
+121 −0
Original line number Diff line number Diff line
@@ -1794,3 +1794,124 @@ rpc_iscsi_set_options(struct spdk_jsonrpc_request *request,
	spdk_jsonrpc_send_bool_response(request, true);
}
SPDK_RPC_REGISTER("iscsi_set_options", rpc_iscsi_set_options, SPDK_RPC_STARTUP)

struct rpc_iscsi_enable_histogram_request {
	char *name;
	bool enable;
};

static const struct spdk_json_object_decoder rpc_iscsi_enable_histogram_request_decoders[] = {
	{"name", offsetof(struct rpc_iscsi_enable_histogram_request, name), spdk_json_decode_string},
	{"enable", offsetof(struct rpc_iscsi_enable_histogram_request, enable), spdk_json_decode_bool},
};

struct iscsi_enable_histogram_ctx {
	struct spdk_jsonrpc_request *request;
	struct spdk_iscsi_tgt_node *target;
	bool enable;
	int status;
	struct spdk_thread *orig_thread;
};

static void
rpc_iscsi_enable_histogram_done(void *_ctx)
{
	struct iscsi_enable_histogram_ctx *ctx = _ctx;

	if (ctx->status == 0) {
		spdk_jsonrpc_send_bool_response(ctx->request, true);
	} else {
		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
						 spdk_strerror(-ctx->status));
	}

	free(ctx);
}

static void
_iscsi_enable_histogram(void *_ctx)
{
	struct iscsi_enable_histogram_ctx *ctx = _ctx;

	ctx->status = iscsi_tgt_node_enable_histogram(ctx->target, ctx->enable);
}

static void
_rpc_iscsi_enable_histogram(void *_ctx)
{
	struct iscsi_enable_histogram_ctx *ctx = _ctx;

	pthread_mutex_lock(&ctx->target->mutex);
	_iscsi_enable_histogram(ctx);
	ctx->target->num_active_conns--;
	pthread_mutex_unlock(&ctx->target->mutex);

	spdk_thread_send_msg(ctx->orig_thread, rpc_iscsi_enable_histogram_done, ctx);
}

static void
rpc_iscsi_enable_histogram(struct spdk_jsonrpc_request *request,
			   const struct spdk_json_val *params)
{
	struct rpc_iscsi_enable_histogram_request req = {NULL};
	struct iscsi_enable_histogram_ctx *ctx;
	struct spdk_iscsi_tgt_node *target;
	struct spdk_thread *thread;
	spdk_msg_fn fn;

	if (spdk_json_decode_object(params, rpc_iscsi_enable_histogram_request_decoders,
				    SPDK_COUNTOF(rpc_iscsi_enable_histogram_request_decoders),
				    &req)) {
		SPDK_ERRLOG("spdk_json_decode_object failed\n");
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
						 "spdk_json_decode_object failed");
		return;
	}

	ctx = calloc(1, sizeof(*ctx));
	if (ctx == NULL) {
		SPDK_ERRLOG("Memory allocation failed\n");
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
						 "Memory allocation failed");
		return;
	}

	target = iscsi_find_tgt_node(req.name);

	free(req.name);

	if (target == NULL) {
		SPDK_ERRLOG("target is not found\n");
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
						 "Invalid parameters");
		free(ctx);
		return;
	}

	ctx->request = request;
	ctx->target = target;
	ctx->enable = req.enable;
	ctx->orig_thread = spdk_get_thread();

	pthread_mutex_lock(&ctx->target->mutex);
	if (target->pg == NULL) {
		_iscsi_enable_histogram(ctx);
		thread = ctx->orig_thread;
		fn = rpc_iscsi_enable_histogram_done;
	} else {
		/**
		 * We get spdk thread of the target by using target->pg.
		 * If target->num_active_conns >= 1, target->pg will not change.
		 * So, It is safer to increase and decrease target->num_active_conns
		 * while updating target->histogram.
		 */
		target->num_active_conns++;
		thread = spdk_io_channel_get_thread(spdk_io_channel_from_ctx(target->pg));
		fn = _rpc_iscsi_enable_histogram;
	}
	pthread_mutex_unlock(&ctx->target->mutex);

	spdk_thread_send_msg(thread, fn, ctx);
}

SPDK_RPC_REGISTER("iscsi_enable_histogram", rpc_iscsi_enable_histogram, SPDK_RPC_RUNTIME)
+8 −0
Original line number Diff line number Diff line
@@ -8,12 +8,19 @@
#include "spdk/log.h"
#include "iscsi/conn.h"
#include "iscsi/task.h"
#include "iscsi/tgt_node.h"

static void
iscsi_task_free(struct spdk_scsi_task *scsi_task)
{
	uint64_t tsc_diff;
	struct spdk_iscsi_task *task = iscsi_task_from_scsi_task(scsi_task);

	if (task->conn->target->histogram) {
		tsc_diff = spdk_get_ticks() - task->start_tsc;
		spdk_histogram_data_tally(task->conn->target->histogram, tsc_diff);
	}

	if (task->parent) {
		if (task->scsi.dxfer_dir == SPDK_SCSI_DIR_FROM_DEV) {
			assert(task->conn->data_in_cnt > 0);
@@ -48,6 +55,7 @@ iscsi_task_get(struct spdk_iscsi_conn *conn, struct spdk_iscsi_task *parent,

	assert(conn != NULL);
	memset(task, 0, sizeof(*task));
	task->start_tsc = spdk_get_ticks();
	task->conn = conn;
	assert(conn->pending_task_cnt < UINT32_MAX);
	conn->pending_task_cnt++;
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ struct spdk_iscsi_task {
	struct spdk_iscsi_conn *conn;
	struct spdk_iscsi_pdu *pdu;
	struct spdk_mobj *mobj;
	uint64_t start_tsc;
	uint32_t outstanding_r2t;

	uint32_t desired_data_transfer_length;
Loading