Commit 4bef621e authored by Pawel Wodkowski's avatar Pawel Wodkowski Committed by Ben Walker
Browse files

bdev/nvme: Add set_bdev_nvme_options



Change-Id: I5ab027d5204f9c4991eacaea631367783d1ad115
Signed-off-by: default avatarPawel Wodkowski <pawelx.wodkowski@intel.com>
Reviewed-on: https://review.gerrithub.io/418723


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarSeth Howell <seth.howell5141@gmail.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
parent 911c042d
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
@@ -892,6 +892,48 @@ Example response:
}
~~~

## set_bdev_nvme_options {#rpc_set_bdev_nvme_options}

Set global parameters for all bdev NVMe. This RPC may only be called before SPDK subsystems have been initialized.

### Parameters

Name                       | Optional | Type        | Description
-------------------------- | -------- | ----------- | -----------
action_on_timeout          | Optional | string      | Action to take on command time out: none, reset or abort
timeout_us                 | Optional | number      | Timeout for each command, in microseconds. If 0, don't track timeouts
retry_count                | Optional | number      | The number of attempts per I/O before an I/O fails
nvme_adminq_poll_period_us | Optional | number      | How often the admin queue is polled for asynchronous events in microsecond

### Example

Example request:

~~~
request:
{
  "params": {
    "retry_count": 5,
    "nvme_adminq_poll_period_us": 2000,
    "timeout_us": 10000000,
    "action_on_timeout": "reset"
  },
  "jsonrpc": "2.0",
  "method": "set_bdev_nvme_options",
  "id": 1
}
~~~

Example response:

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

## construct_nvme_bdev {#rpc_construct_nvme_bdev}

Construct @ref bdev_config_nvme
+2 −2
Original line number Diff line number Diff line
@@ -108,8 +108,8 @@
  # The number of attempts per I/O when an I/O fails. Do not include
  # this key to get the default behavior.
  RetryCount 4
  # Timeout for each command, in seconds. If 0, don't track timeouts.
  Timeout 0
  # Timeout for each command, in microseconds. If 0, don't track timeouts.
  TimeoutUsec 0
  # Action to take on command time out. Only valid when Timeout is greater
  # than 0. This may be 'Reset' to reset the controller, 'Abort' to abort
  # the command, or 'None' to just print a message but do nothing.
+2 −2
Original line number Diff line number Diff line
@@ -99,8 +99,8 @@
  # The number of attempts per I/O when an I/O fails. Do not include
  # this key to get the default behavior.
  RetryCount 4
  # Timeout for each command, in seconds. If 0, don't track timeouts.
  Timeout 0
  # Timeout for each command, in microseconds. If 0, don't track timeouts.
  TimeoutUsec 0
  # Action to take on command time out. Only valid when Timeout is greater
  # than 0. This may be 'Reset' to reset the controller, 'Abort' to abort
  # the command, or 'None' to just print a message but do nothing.
+2 −2
Original line number Diff line number Diff line
@@ -89,8 +89,8 @@
  # The number of attempts per I/O when an I/O fails. Do not include
  # this key to get the default behavior.
  RetryCount 4
  # Timeout for each command, in seconds. If 0, don't track timeouts.
  Timeout 0
  # Timeout for each command, in microseconds. If 0, don't track timeouts.
  TimeoutUsec 0
  # Action to take on command time out. Only valid when Timeout is greater
  # than 0. This may be 'Reset' to reset the controller, 'Abort' to abort
  # the command, or 'None' to just print a message but do nothing.
+95 −41
Original line number Diff line number Diff line
@@ -94,18 +94,18 @@ struct nvme_probe_ctx {
	const char *hostnqn;
};

enum timeout_action {
	TIMEOUT_ACTION_NONE = 0,
	TIMEOUT_ACTION_RESET,
	TIMEOUT_ACTION_ABORT,
static struct spdk_bdev_nvme_opts g_opts = {
	.action_on_timeout = SPDK_BDEV_NVME_TIMEOUT_ACTION_NONE,
	.timeout_us = 0,
	.retry_count = SPDK_NVME_DEFAULT_RETRY_COUNT,
	.nvme_adminq_poll_period_us = 1000000ULL,
};

static bool g_bdev_nvme_init_done = false;

static int g_hot_insert_nvme_controller_index = 0;
static enum timeout_action g_action_on_timeout = TIMEOUT_ACTION_NONE;
static uint64_t g_timeout_us = 0;
static int g_nvme_adminq_poll_timeout_us = 0;
static bool g_nvme_hotplug_enabled = false;
static int g_nvme_hotplug_poll_timeout_us = 0;
static bool g_nvme_hotplug_enabled = false;
static struct spdk_poller *g_hotplug_poller;
static char *g_nvme_hostnqn = NULL;
static pthread_mutex_t g_bdev_nvme_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -850,8 +850,8 @@ timeout_cb(void *cb_arg, struct spdk_nvme_ctrlr *ctrlr,

	SPDK_WARNLOG("Warning: Detected a timeout. ctrlr=%p qpair=%p cid=%u\n", ctrlr, qpair, cid);

	switch (g_action_on_timeout) {
	case TIMEOUT_ACTION_ABORT:
	switch (g_opts.action_on_timeout) {
	case SPDK_BDEV_NVME_TIMEOUT_ACTION_ABORT:
		if (qpair) {
			rc = spdk_nvme_ctrlr_cmd_abort(ctrlr, qpair, cid,
						       spdk_nvme_abort_cpl, ctrlr);
@@ -863,13 +863,13 @@ timeout_cb(void *cb_arg, struct spdk_nvme_ctrlr *ctrlr,
		}

	/* FALLTHROUGH */
	case TIMEOUT_ACTION_RESET:
	case SPDK_BDEV_NVME_TIMEOUT_ACTION_RESET:
		rc = spdk_nvme_ctrlr_reset(ctrlr);
		if (rc) {
			SPDK_ERRLOG("Resetting controller failed.\n");
		}
		break;
	case TIMEOUT_ACTION_NONE:
	case SPDK_BDEV_NVME_TIMEOUT_ACTION_NONE:
		break;
	}
}
@@ -959,12 +959,12 @@ create_ctrlr(struct spdk_nvme_ctrlr *ctrlr,
	}

	nvme_ctrlr->adminq_timer_poller = spdk_poller_register(bdev_nvme_poll_adminq, ctrlr,
					  g_nvme_adminq_poll_timeout_us);
					  g_opts.nvme_adminq_poll_period_us);

	TAILQ_INSERT_TAIL(&g_nvme_ctrlrs, nvme_ctrlr, tailq);

	if (g_action_on_timeout != TIMEOUT_ACTION_NONE) {
		spdk_nvme_ctrlr_register_timeout_callback(ctrlr, g_timeout_us,
	if (g_opts.timeout_us > 0 && g_opts.action_on_timeout != SPDK_BDEV_NVME_TIMEOUT_ACTION_NONE) {
		spdk_nvme_ctrlr_register_timeout_callback(ctrlr, g_opts.timeout_us,
				timeout_cb, NULL);
	}

@@ -1039,6 +1039,24 @@ bdev_nvme_hotplug(void *arg)
	return -1;
}

void
spdk_bdev_nvme_get_opts(struct spdk_bdev_nvme_opts *opts)
{
	*opts = g_opts;
}

int
spdk_bdev_nvme_set_opts(const struct spdk_bdev_nvme_opts *opts)
{
	if (g_bdev_nvme_init_done) {
		return -EPERM;
	}

	g_opts = *opts;

	return 0;
}

int
spdk_bdev_nvme_create(struct spdk_nvme_transport_id *trid,
		      const char *base_name,
@@ -1133,12 +1151,14 @@ bdev_nvme_library_init(void)
	struct spdk_conf_section *sp;
	const char *val;
	int rc = 0;
	int64_t intval;
	size_t i;
	struct nvme_probe_ctx *probe_ctx = NULL;
	int retry_count;
	int timeout;
	uint32_t local_nvme_num = 0;

	g_bdev_nvme_init_done = true;

	sp = spdk_conf_find_section(NULL, "Nvme");
	if (sp == NULL) {
		goto end;
@@ -1160,37 +1180,47 @@ bdev_nvme_library_init(void)
		}
	}

	spdk_nvme_retry_count = retry_count;
	g_opts.retry_count = retry_count;

	val = spdk_conf_section_get_val(sp, "TimeoutUsec");
	if (val != NULL) {
		g_timeout_us = strtoll(val, NULL, 10);
		intval = strtoll(val, NULL, 10);
		if (intval == LLONG_MIN || intval == LLONG_MAX) {
			SPDK_ERRLOG("Invalid TimeoutUsec value\n");
			rc = -1;
			goto end;
		} else if (intval < 0) {
			intval = 0;
		}
	} else {
		/* Check old name for backward compatibility */
		timeout = spdk_conf_section_get_intval(sp, "Timeout");
		if (timeout < 0) {
			timeout = spdk_conf_section_get_intval(sp, "NvmeTimeoutValue");
			if (timeout < 0) {
				g_timeout_us = 0;
		intval = spdk_conf_section_get_intval(sp, "Timeout");
		if (intval < 0) {
			intval = spdk_conf_section_get_intval(sp, "NvmeTimeoutValue");
			if (intval < 0) {
				intval = 0;
			} else {
				g_timeout_us = timeout * 1000000ULL;
				intval *= 1000000ULL;
				SPDK_WARNLOG("NvmeTimeoutValue (in seconds) was renamed to TimeoutUsec (in microseconds)\n");
				SPDK_WARNLOG("Please update your configuration file\n");
			}
		} else {
			g_timeout_us = timeout * 1000000ULL;
			intval *= 1000000ULL;
			SPDK_WARNLOG("Timeout (in seconds) was renamed to TimeoutUsec (in microseconds)\n");
			SPDK_WARNLOG("Please update your configuration file\n");
		}
	}

	if (g_timeout_us > 0) {

	g_opts.timeout_us = intval;

	if (g_opts.timeout_us > 0) {
		val = spdk_conf_section_get_val(sp, "ActionOnTimeout");
		if (val != NULL) {
			if (!strcasecmp(val, "Reset")) {
				g_action_on_timeout = TIMEOUT_ACTION_RESET;
				g_opts.action_on_timeout = SPDK_BDEV_NVME_TIMEOUT_ACTION_RESET;
			} else if (!strcasecmp(val, "Abort")) {
				g_action_on_timeout = TIMEOUT_ACTION_ABORT;
				g_opts.action_on_timeout = SPDK_BDEV_NVME_TIMEOUT_ACTION_ABORT;
			}
		} else {
			/* Handle old name for backward compatibility */
@@ -1200,15 +1230,15 @@ bdev_nvme_library_init(void)
				SPDK_WARNLOG("Please update your configuration file\n");

				if (spdk_conf_section_get_boolval(sp, "ResetControllerOnTimeout", false)) {
					g_action_on_timeout = TIMEOUT_ACTION_RESET;
					g_opts.action_on_timeout = SPDK_BDEV_NVME_TIMEOUT_ACTION_RESET;
				}
			}
		}
	}

	g_nvme_adminq_poll_timeout_us = spdk_conf_section_get_intval(sp, "AdminPollRate");
	if (g_nvme_adminq_poll_timeout_us <= 0) {
		g_nvme_adminq_poll_timeout_us = 1000000;
	intval = spdk_conf_section_get_intval(sp, "AdminPollRate");
	if (intval > 0) {
		g_opts.nvme_adminq_poll_period_us = intval;
	}

	if (spdk_process_is_primary()) {
@@ -1221,9 +1251,7 @@ bdev_nvme_library_init(void)
	}

	g_nvme_hostnqn = spdk_conf_section_get_val(sp, "HostNQN");
	if (g_nvme_hostnqn) {
	probe_ctx->hostnqn = g_nvme_hostnqn;
	}

	for (i = 0; i < NVME_MAX_CONTROLLERS; i++) {
		val = spdk_conf_section_get_nmval(sp, "TransportID", i, 0);
@@ -1313,6 +1341,10 @@ bdev_nvme_library_init(void)
	}

end:
	if (rc == 0) {
		spdk_nvme_retry_count = g_opts.retry_count;
	}

	free(probe_ctx);
	return rc;
}
@@ -1617,21 +1649,21 @@ bdev_nvme_get_spdk_running_config(FILE *fp)
	fprintf(fp, "RetryCount %d\n", spdk_nvme_retry_count);
	fprintf(fp, "\n"
		"# Timeout for each command, in microseconds. If 0, don't track timeouts.\n");
	fprintf(fp, "Timeout %"PRIu64"\n", g_timeout_us);
	fprintf(fp, "TimeoutUsec %"PRIu64"\n", g_opts.timeout_us);

	fprintf(fp, "\n"
		"# Action to take on command time out. Only valid when Timeout is greater\n"
		"# than 0. This may be 'Reset' to reset the controller, 'Abort' to abort\n"
		"# the command, or 'None' to just print a message but do nothing.\n"
		"# Admin command timeouts will always result in a reset.\n");
	switch (g_action_on_timeout) {
	case TIMEOUT_ACTION_NONE:
	switch (g_opts.action_on_timeout) {
	case SPDK_BDEV_NVME_TIMEOUT_ACTION_NONE:
		fprintf(fp, "ActionOnTimeout None\n");
		break;
	case TIMEOUT_ACTION_RESET:
	case SPDK_BDEV_NVME_TIMEOUT_ACTION_RESET:
		fprintf(fp, "ActionOnTimeout Reset\n");
		break;
	case TIMEOUT_ACTION_ABORT:
	case SPDK_BDEV_NVME_TIMEOUT_ACTION_ABORT:
		fprintf(fp, "ActionOnTimeout Abort\n");
		break;
	}
@@ -1639,7 +1671,7 @@ bdev_nvme_get_spdk_running_config(FILE *fp)
	fprintf(fp, "\n"
		"# Set how often the admin queue is polled for asynchronous events.\n"
		"# Units in microseconds.\n");
	fprintf(fp, "AdminPollRate %d\n", g_nvme_adminq_poll_timeout_us);
	fprintf(fp, "AdminPollRate %"PRIu64"\n", g_opts.nvme_adminq_poll_period_us);
	fprintf(fp, "\n"
		"# Disable handling of hotplug (runtime insert and remove) events,\n"
		"# users can set to Yes if want to enable it.\n"
@@ -1662,6 +1694,28 @@ bdev_nvme_config_json(struct spdk_json_write_ctx *w)
	struct nvme_ctrlr		*nvme_ctrlr;
	struct spdk_nvme_transport_id	*trid;
	const char			*adrfam;
	const char			*action;

	if (g_opts.action_on_timeout == SPDK_BDEV_NVME_TIMEOUT_ACTION_RESET) {
		action = "reset";
	} else if (g_opts.action_on_timeout == SPDK_BDEV_NVME_TIMEOUT_ACTION_ABORT) {
		action = "abort";
	} else {
		action = "none";
	}

	spdk_json_write_object_begin(w);

	spdk_json_write_named_string(w, "method", "set_bdev_nvme_options");

	spdk_json_write_named_object_begin(w, "params");
	spdk_json_write_named_string(w, "action_on_timeout", action);
	spdk_json_write_named_uint64(w, "timeout_us", g_opts.timeout_us);
	spdk_json_write_named_uint32(w, "retry_count", g_opts.retry_count);
	spdk_json_write_named_uint64(w, "nvme_adminq_poll_period_us", g_opts.nvme_adminq_poll_period_us);
	spdk_json_write_object_end(w);

	spdk_json_write_object_end(w);

	pthread_mutex_lock(&g_bdev_nvme_mutex);
	TAILQ_FOREACH(nvme_ctrlr, &g_nvme_ctrlrs, tailq) {
Loading