Commit 83eb352b authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Tomasz Zawadzki
Browse files

lib/nvmf: Add nvmf_subsystem_get_qpairs RPC



Add an new RPC, nvmf_subsystem_get_qpairs to retrieve the list of
qpairs of an NVMe-oF subsystem.

This RPC will be usable to verify if NVMe ANA works.

Pause and resume the subsystem to access the qpairs safely.

One subtle issue remains. The JSON RPC returns success even if
resuming the subsystem fails. Write FIXME to address this.

Signed-off-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: I9d90a01b1117dee00d85b2e21b4f4d02d80db531
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4050


Community-CI: Broadcom CI
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent a9c0fdd7
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
@@ -4723,6 +4723,63 @@ Example response:
}
~~~

## nvmf_subsystem_get_qpairs {#rpc_nvmf_subsystem_get_qpairs}

### Parameters

Name                    | Optional | Type        | Description
----------------------- | -------- | ----------- | -----------
nqn                     | Required | string      | Subsystem NQN
tgt_name                | Optional | string      | Parent NVMe-oF target name.

### Example

Example request:

~~~
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "nvmf_subsystem_get_qpairs",
  "params": {
    "nqn": "nqn.2016-06.io.spdk:cnode1"
  }
}
~~~

Example response:

~~~
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    {
      "cntlid": 1,
      "qid": 0,
      "state": "active",
      "listen_address": {
        "trtype": "RDMA",
        "adrfam": "IPv4",
        "traddr": "192.168.0.123",
        "trsvcid": "4420"
      }
    },
    {
      "cntlid": 1,
      "qid": 1,
      "state": "active",
      "listen_address": {
        "trtype": "RDMA",
        "adrfam": "IPv4",
        "traddr": "192.168.0.123",
        "trsvcid": "4420"
      }
    }
  ]
}
~~~

## nvmf_set_max_subsystems {#rpc_nvmf_set_max_subsystems}

Set the maximum allowed subsystems for the NVMe-oF target.  This RPC may only be called
+103 −0
Original line number Diff line number Diff line
@@ -2107,6 +2107,49 @@ dump_nvmf_ctrlr(struct spdk_json_write_ctx *w, struct spdk_nvmf_ctrlr *ctrlr)
	spdk_json_write_object_end(w);
}

static const char *
nvmf_qpair_state_str(enum spdk_nvmf_qpair_state state)
{
	switch (state) {
	case SPDK_NVMF_QPAIR_UNINITIALIZED:
		return "uninitialized";
	case SPDK_NVMF_QPAIR_ACTIVE:
		return "active";
	case SPDK_NVMF_QPAIR_DEACTIVATING:
		return "deactivating";
	case SPDK_NVMF_QPAIR_ERROR:
		return "error";
	default:
		return NULL;
	}
}

static void
dump_nvmf_qpair(struct spdk_json_write_ctx *w, struct spdk_nvmf_qpair *qpair)
{
	const struct spdk_nvme_transport_id *trid = qpair->trid;
	const char *adrfam;

	spdk_json_write_object_begin(w);

	spdk_json_write_named_uint32(w, "cntlid", qpair->ctrlr->cntlid);
	spdk_json_write_named_uint32(w, "qid", qpair->qid);
	spdk_json_write_named_string(w, "state", nvmf_qpair_state_str(qpair->state));

	spdk_json_write_named_object_begin(w, "listen_address");
	adrfam = spdk_nvme_transport_id_adrfam_str(trid->adrfam);
	if (adrfam == NULL) {
		adrfam = "unknown";
	}
	spdk_json_write_named_string(w, "trtype", trid->trstring);
	spdk_json_write_named_string(w, "adrfam", adrfam);
	spdk_json_write_named_string(w, "traddr", trid->traddr);
	spdk_json_write_named_string(w, "trsvcid", trid->trsvcid);
	spdk_json_write_object_end(w);

	spdk_json_write_object_end(w);
}

struct rpc_subsystem_query_ctx {
	char *nqn;
	char *tgt_name;
@@ -2154,6 +2197,58 @@ rpc_nvmf_get_controllers_paused(struct spdk_nvmf_subsystem *subsystem,
	free_rpc_subsystem_query_ctx(ctx);
}

static void
rpc_nvmf_get_qpairs_done(struct spdk_io_channel_iter *i, int status)
{
	struct rpc_subsystem_query_ctx *ctx = spdk_io_channel_iter_get_ctx(i);

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

	if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) {
		SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn);
		/* FIXME: RPC should fail if resuming the subsystem failed. */
	}

	free_rpc_subsystem_query_ctx(ctx);
}

static void
rpc_nvmf_get_qpairs(struct spdk_io_channel_iter *i)
{
	struct rpc_subsystem_query_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
	struct spdk_io_channel *ch;
	struct spdk_nvmf_poll_group *group;
	struct spdk_nvmf_qpair *qpair;

	ch = spdk_get_io_channel(ctx->subsystem->tgt);
	group = spdk_io_channel_get_ctx(ch);

	TAILQ_FOREACH(qpair, &group->qpairs, link) {
		if (qpair->ctrlr->subsys == ctx->subsystem) {
			dump_nvmf_qpair(ctx->w, qpair);
		}
	}

	spdk_for_each_channel_continue(i, 0);
}

static void
rpc_nvmf_get_qpairs_paused(struct spdk_nvmf_subsystem *subsystem,
			   void *cb_arg, int status)
{
	struct rpc_subsystem_query_ctx *ctx = cb_arg;

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

	spdk_json_write_array_begin(ctx->w);

	spdk_for_each_channel(ctx->subsystem->tgt,
			      rpc_nvmf_get_qpairs,
			      ctx,
			      rpc_nvmf_get_qpairs_done);
}

static void
_rpc_nvmf_subsystem_query(struct spdk_jsonrpc_request *request,
			  const struct spdk_json_val *params,
@@ -2218,3 +2313,11 @@ rpc_nvmf_subsystem_get_controllers(struct spdk_jsonrpc_request *request,
}
SPDK_RPC_REGISTER("nvmf_subsystem_get_controllers", rpc_nvmf_subsystem_get_controllers,
		  SPDK_RPC_RUNTIME);

static void
rpc_nvmf_subsystem_get_qpairs(struct spdk_jsonrpc_request *request,
			      const struct spdk_json_val *params)
{
	_rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_qpairs_paused);
}
SPDK_RPC_REGISTER("nvmf_subsystem_get_qpairs", rpc_nvmf_subsystem_get_qpairs, SPDK_RPC_RUNTIME);
+11 −0
Original line number Diff line number Diff line
@@ -2001,6 +2001,17 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
    p.add_argument('-t', '--tgt-name', help='The name of the parent NVMe-oF target (optional)', type=str)
    p.set_defaults(func=nvmf_subsystem_get_controllers)

    def nvmf_subsystem_get_qpairs(args):
        print_dict(rpc.nvmf.nvmf_subsystem_get_qpairs(args.client,
                                                      nqn=args.nqn,
                                                      tgt_name=args.tgt_name))

    p = subparsers.add_parser('nvmf_subsystem_get_qpairs',
                              help='Display queue pairs of an NVMe-oF subsystem.')
    p.add_argument('nqn', help='NVMe-oF subsystem NQN')
    p.add_argument('-t', '--tgt-name', help='The name of the parent NVMe-oF target (optional)', type=str)
    p.set_defaults(func=nvmf_subsystem_get_qpairs)

    def nvmf_get_stats(args):
        print_dict(rpc.nvmf.nvmf_get_stats(args.client, tgt_name=args.tgt_name))

+18 −0
Original line number Diff line number Diff line
@@ -487,6 +487,24 @@ def nvmf_subsystem_get_controllers(client, nqn, tgt_name=None):
    return client.call('nvmf_subsystem_get_controllers', params)


def nvmf_subsystem_get_qpairs(client, nqn, tgt_name=None):
    """Get list of queue pairs of an NVMe-oF subsystem.

    Args:
        nqn: Subsystem NQN.
        tgt_name: name of the parent NVMe-oF target (optional).

    Returns:
        List of queue pair objects of an NVMe-oF subsystem.
    """
    params = {'nqn': nqn}

    if tgt_name:
        params['tgt_name'] = tgt_name

    return client.call('nvmf_subsystem_get_qpairs', params)


def nvmf_get_stats(client, tgt_name=None):
    """Query NVMf statistics.