Commit 02035b01 authored by Changqi Lu's avatar Changqi Lu Committed by Jim Harris
Browse files

lib/iscsi: Add RPC method iscsi_get_stats



In a production environment, the iscsi_get_connections RPC method is
commonly used to monitor the number of SPDK connections. It is often
necessary to issue an alarm when there are too many iSCSI connections.
By default, the maximum number of connections in SPDK is defined by
MAX_ISCSI_CONNECTIONS as 1024.

However, the return value of the iscsi_get_connections method contains
a significant amount of information. In certain cases, only the number
of connections is required, and the overhead of parsing JSON becomes
a considerable burden, especially when there are numerous connections.

To address this issue, the rpc method iscsi_get_stats has been added.
When this method is used, only the count of connections in each state
will be provided, eliminating the need for detailed information parsing.

Change-Id: I45f4a4ebb2d4a5a6fe9eee28a3cbeb4e05009b56
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/+/21629


Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <smatsumoto@nvidia.com>
Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
parent 7e64a4c6
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -15,6 +15,10 @@ Please use `spdk_subsystem_load_config` instead.

Added `bdev_uring_rescan` RPC to allow rescaning the size of uring bdev.

### iscsi

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

## v24.01

### accel
+48 −0
Original line number Diff line number Diff line
@@ -7798,6 +7798,54 @@ Example response:
}
~~~

### iscsi_get_stats method {#iscsi_get_stats}

Show stat information of iSCSI connections.

#### Parameters

This method has no parameters.

#### Results

Stat information of iSCSI connections.

Name                        | Type    | Description
--------------------------- | --------| -----------
invalid                     | number  | The number of invalid connections
running                     | number  | The number of running connections
exiting                     | number  | The number of exiting connections
exited                      | number  | The number of exited connections

#### Example

Example request:

~~~json
{
  "jsonrpc": "2.0",
  "method": "iscsi_get_stats",
  "id": 1
}
~~~

Example response:

~~~json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result":
    {
      "invalid": 0,
      "running": 5,
      "exiting": 0,
      "exited": 0
    }

}
~~~

### iscsi_target_node_add_lun method {#rpc_iscsi_target_node_add_lun}

Add an LUN to an existing iSCSI target node.
+94 −0
Original line number Diff line number Diff line
@@ -993,6 +993,100 @@ struct rpc_target_lun {
	int32_t lun_id;
};

struct rpc_iscsi_get_stats_ctx {
	struct spdk_jsonrpc_request *request;
	uint32_t invalid;
	uint32_t running;
	uint32_t exiting;
	uint32_t exited;
};

static void
_rpc_iscsi_get_stats_done(struct spdk_io_channel_iter *i, int status)
{
	struct spdk_json_write_ctx *w;
	struct rpc_iscsi_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i);

	w = spdk_jsonrpc_begin_result(ctx->request);
	spdk_json_write_object_begin(w);

	spdk_json_write_named_uint32(w, "invalid", ctx->invalid);
	spdk_json_write_named_uint32(w, "running", ctx->running);
	spdk_json_write_named_uint32(w, "exiting", ctx->exiting);
	spdk_json_write_named_uint32(w, "exited", ctx->exited);

	spdk_json_write_object_end(w);
	spdk_jsonrpc_end_result(ctx->request, w);

	free(ctx);
}

static void
_iscsi_get_stats(struct rpc_iscsi_get_stats_ctx *ctx,
		 struct spdk_iscsi_conn *conn)
{
	switch (conn->state) {
	case ISCSI_CONN_STATE_INVALID:
		ctx->invalid += 1;
		break;
	case ISCSI_CONN_STATE_RUNNING:
		ctx->running += 1;
		break;
	case ISCSI_CONN_STATE_EXITING:
		ctx->exiting += 1;
		break;
	case ISCSI_CONN_STATE_EXITED:
		ctx->exited += 1;
		break;
	}
}

static void
_rpc_iscsi_get_stats(struct spdk_io_channel_iter *i)
{
	struct rpc_iscsi_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
	struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
	struct spdk_iscsi_poll_group *pg = spdk_io_channel_get_ctx(ch);
	struct spdk_iscsi_conn *conn;

	STAILQ_FOREACH(conn, &pg->connections, pg_link) {
		_iscsi_get_stats(ctx, conn);
	}

	spdk_for_each_channel_continue(i, 0);
}



static void
rpc_iscsi_get_stats(struct spdk_jsonrpc_request *request,
		    const struct spdk_json_val *params)
{
	struct rpc_iscsi_get_stats_ctx *ctx;

	if (params != NULL) {
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
						 "iscsi_get_stats requires no parameters");
		return;
	}

	ctx = calloc(1, sizeof(struct rpc_iscsi_get_stats_ctx));
	if (ctx == NULL) {
		SPDK_ERRLOG("Failed to allocate rpc_iscsi_get_stats_ctx struct\n");
		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
		return;
	}

	ctx->request = request;

	spdk_for_each_channel(&g_iscsi,
			      _rpc_iscsi_get_stats,
			      ctx,
			      _rpc_iscsi_get_stats_done);

}
SPDK_RPC_REGISTER("iscsi_get_stats", rpc_iscsi_get_stats, SPDK_RPC_RUNTIME)

static void
free_rpc_target_lun(struct rpc_target_lun *req)
{
+9 −0
Original line number Diff line number Diff line
@@ -600,6 +600,15 @@ def iscsi_get_connections(client):
    return client.call('iscsi_get_connections')


def iscsi_get_stats(client):
    """Display stat information of iSCSI connections.

    Returns:
        Stat information of iSCSI connections.
    """
    return client.call('iscsi_get_stats')


def iscsi_get_options(client):
    """Display iSCSI global parameters.

+7 −0
Original line number Diff line number Diff line
@@ -1827,6 +1827,13 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
                              help='Display iSCSI connections')
    p.set_defaults(func=iscsi_get_connections)

    def iscsi_get_stats(args):
        print_dict(rpc.iscsi.iscsi_get_stats(args.client))

    p = subparsers.add_parser('iscsi_get_stats',
                              help='Display stat information of iSCSI connections.')
    p.set_defaults(func=iscsi_get_stats)

    def iscsi_get_options(args):
        print_dict(rpc.iscsi.iscsi_get_options(args.client))