Commit c959f72e authored by Mateusz Kozlowski's avatar Mateusz Kozlowski Committed by Ben Walker
Browse files

module/bdev/ftl: Add new RPC to set FTL property



This patch implements a new RPC to configure
FTL properties. The call name is bdev_ftl_set_property.

Change-Id: I99fc0c19b5b920285d4faa4e7bd4964ebea0031e
Signed-off-by: default avatarMariusz Barczak <Mariusz.Barczak@solidigmtechnology.com>
Signed-off-by: default avatarMateusz Kozlowski <mateusz.kozlowski@solidigm.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/19008


Reviewed-by: default avatarBen Walker <ben@nvidia.com>
Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
parent ecbceb22
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -484,6 +484,7 @@ Example response:
    "bdev_ftl_unmap",
    "bdev_ftl_get_stats",
    "bdev_ftl_get_properties",
    "bdev_ftl_set_property",
    "bdev_lvol_get_lvstores",
    "bdev_lvol_delete",
    "bdev_lvol_resize",
@@ -6160,6 +6161,45 @@ Example response:
}
~~~

### bdev_ftl_set_property {#rpc_bdev_ftl_set_property}

Set FTL property. Trying to set a read-only property will result in an error.

#### Parameters

Name                    | Optional | Type        | Description
----------------------- | -------- | ----------- | -----------
name                    | Required | string      | Bdev name
property                | Required | string      | Name of the property to modify
value                   | Required | string      | New value of the property to be set

#### Example

Example request:

~~~json
{
  "params": {
    "name": "ftl0"
    "property": "nv_cache.flush"
    "value": "true"
  },
  "jsonrpc": "2.0",
  "method": "bdev_ftl_set_property",
  "id": 1
}
~~~

Example response:

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

### bdev_passthru_create {#rpc_bdev_passthru_create}

Create passthru bdev. This bdev type redirects all IO to it's base bdev. It has no other purpose than being an example
+15 −0
Original line number Diff line number Diff line
@@ -340,6 +340,21 @@ int spdk_ftl_get_stats(struct spdk_ftl_dev *dev, struct ftl_stats *stats, spdk_f
int spdk_ftl_get_properties(struct spdk_ftl_dev *dev, struct spdk_jsonrpc_request *request,
			    spdk_ftl_fn cb_fn, void *cb_arg);

/**
 * Sets the property of the specified device.
 *
 * \param dev FTL device
 * \param property The property name to be modified
 * \param value The new value to property
 * \param value_size The size of the value buffer
 * \param cb_fn Callback function to invoke when the operation is completed
 * \param cb_arg Argument to pass to the callback function
 *
 * \return 0 if successfully submitted, negative errno otherwise.
 */
int spdk_ftl_set_property(struct spdk_ftl_dev *dev, const char *property, const char *value,
			  size_t value_size, spdk_ftl_fn cb_fn, void *cb_arg);

#ifdef __cplusplus
}
#endif
+109 −9
Original line number Diff line number Diff line
@@ -184,7 +184,8 @@ ftl_mngt_finalize_startup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mng
	}

	ftl_property_register(dev, "superblock_version", &dev->sb->header.version,
			      sizeof(dev->sb->header.version), ftl_property_dump_uint64);
			      sizeof(dev->sb->header.version), ftl_property_dump_uint64,
			      NULL, NULL);

	/* Clear the limit applications as they're incremented incorrectly by
	 * the initialization code.
@@ -327,31 +328,34 @@ ftl_mngt_deinit_unmap_map(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mng
	ftl_mngt_next_step(mngt);
}

struct ftl_get_properties_ctx {
struct ftl_mngt_property_caller_ctx {
	struct spdk_ftl_dev *dev;
	struct spdk_jsonrpc_request *request;
	spdk_ftl_fn cb_fn;
	void *cb_arg;
	struct spdk_thread *cb_thread;
	const char *property;
	const char *value;
	size_t value_size;
};

static void
ftl_get_properties_cb(void *arg)
{
	struct ftl_get_properties_ctx *ctx = arg;
	struct ftl_mngt_property_caller_ctx *cctx = arg;

	ctx->cb_fn(ctx->cb_arg, 0);
	free(ctx);
	cctx->cb_fn(cctx->cb_arg, 0);
	free(cctx);
}

static void
ftl_get_properties_msg(void *arg)
{
	struct ftl_get_properties_ctx *ctx = arg;
	struct ftl_mngt_property_caller_ctx *cctx = arg;
	int rc;

	ftl_property_dump(ctx->dev, ctx->request);
	rc = spdk_thread_send_msg(ctx->cb_thread, ftl_get_properties_cb, ctx);
	ftl_property_dump(cctx->dev, cctx->request);
	rc = spdk_thread_send_msg(cctx->cb_thread, ftl_get_properties_cb, cctx);
	ftl_bug(rc);
}

@@ -360,7 +364,7 @@ spdk_ftl_get_properties(struct spdk_ftl_dev *dev, struct spdk_jsonrpc_request *r
			spdk_ftl_fn cb_fn, void *cb_arg)
{
	int rc;
	struct ftl_get_properties_ctx *ctx = calloc(1, sizeof(*ctx));
	struct ftl_mngt_property_caller_ctx *ctx = calloc(1, sizeof(*ctx));

	if (ctx == NULL) {
		return -ENOMEM;
@@ -377,5 +381,101 @@ spdk_ftl_get_properties(struct spdk_ftl_dev *dev, struct spdk_jsonrpc_request *r
		return rc;
	}

	return 0;
}

struct ftl_set_property_process_ctx {
	void *value;
	size_t value_size;
};

static void
ftl_mngt_set_property_decode(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
{
	struct ftl_set_property_process_ctx *pctx = ftl_mngt_get_process_ctx(mngt);
	struct ftl_mngt_property_caller_ctx *cctx = ftl_mngt_get_caller_ctx(mngt);

	if (ftl_property_decode(dev, cctx->property, cctx->value, cctx->value_size,
				&pctx->value, &pctx->value_size)) {
		ftl_mngt_fail_step(mngt);
	} else {
		ftl_mngt_next_step(mngt);
	}
}

static void
ftl_mngt_set_property(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
{
	struct ftl_set_property_process_ctx *pctx = ftl_mngt_get_process_ctx(mngt);
	struct ftl_mngt_property_caller_ctx *cctx = ftl_mngt_get_caller_ctx(mngt);

	if (ftl_property_set(dev, mngt, cctx->property, pctx->value, pctx->value_size)) {
		ftl_mngt_fail_step(mngt);
	}
}

static void
ftl_mngt_set_property_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
{
	struct ftl_set_property_process_ctx *pctx = ftl_mngt_get_process_ctx(mngt);
	free(pctx->value);
	pctx->value = NULL;
	pctx->value_size = 0;
	ftl_mngt_next_step(mngt);
}

static const struct ftl_mngt_process_desc desc_set_property = {
	.name = "Set FTL property",
	.ctx_size = sizeof(struct ftl_set_property_process_ctx),
	.steps = {
		{
			.name = "Decode property",
			.action = ftl_mngt_set_property_decode,
			.cleanup = ftl_mngt_set_property_cleanup
		},
		{
			.name = "Set property",
			.action = ftl_mngt_set_property,
			.cleanup = ftl_mngt_set_property_cleanup
		},
		{
			.name = "Property setting cleanup",
			.action = ftl_mngt_set_property_cleanup,
		},
		{}
	}
};

static void
ftl_mngt_property_caller_cb(struct spdk_ftl_dev *dev, void *ctx, int status)
{
	struct ftl_mngt_property_caller_ctx *cctx = ctx;

	cctx->cb_fn(cctx->cb_arg, status);
	free(cctx);
}

int
spdk_ftl_set_property(struct spdk_ftl_dev *dev,
		      const char *property, const char *value, size_t value_size,
		      spdk_ftl_fn cb_fn, void *cb_arg)
{
	int rc;
	struct ftl_mngt_property_caller_ctx *cctx = calloc(1, sizeof(*cctx));

	if (cctx == NULL) {
		return -EAGAIN;
	}
	cctx->cb_fn = cb_fn;
	cctx->cb_arg = cb_arg;
	cctx->property = property;
	cctx->value = value;
	cctx->value_size = value_size;

	rc = ftl_mngt_process_execute(dev, &desc_set_property, ftl_mngt_property_caller_cb, cctx);
	if (rc) {
		free(cctx);
	}

	return rc;
}
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
	spdk_ftl_dev_set_fast_shutdown;
	spdk_ftl_get_stats;
	spdk_ftl_get_properties;
	spdk_ftl_set_property;

	local: *;
};
+113 −4
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@

#include "ftl_core.h"
#include "ftl_property.h"
#include "mngt/ftl_mngt.h"

struct ftl_properties {
	LIST_HEAD(, ftl_property) list;
@@ -29,12 +30,18 @@ struct ftl_property {
	/* The function to dump the value of property into the specified JSON RPC request */
	ftl_property_dump_fn dump;

	/* Decode property value and store it in output */
	ftl_property_decode_fn decode;

	/* Set the FTL property */
	ftl_property_set_fn set;

	/** Link to put the property to the list */
	LIST_ENTRY(ftl_property) entry;
};

static struct ftl_property *
get_property_item(struct ftl_properties *properties, const char *name)
get_property(struct ftl_properties *properties, const char *name)
{
	struct ftl_property *entry;

@@ -49,12 +56,15 @@ get_property_item(struct ftl_properties *properties, const char *name)
}

void
ftl_property_register(struct spdk_ftl_dev *dev, const char *name, void *value, size_t size,
		      ftl_property_dump_fn dump)
ftl_property_register(struct spdk_ftl_dev *dev,
		      const char *name, void *value, size_t size,
		      ftl_property_dump_fn dump,
		      ftl_property_decode_fn decode,
		      ftl_property_set_fn set)
{
	struct ftl_properties *properties = dev->properties;

	if (get_property_item(properties, name)) {
	if (get_property(properties, name)) {
		FTL_ERRLOG(dev, "FTL property registration ERROR, already exist, name %s\n", name);
		ftl_abort();
	} else {
@@ -68,6 +78,8 @@ ftl_property_register(struct spdk_ftl_dev *dev, const char *name, void *value, s
		prop->value = value;
		prop->size = size;
		prop->dump = dump;
		prop->decode = decode;
		prop->set = set;
		LIST_INSERT_HEAD(&properties->list, prop, entry);
	}
}
@@ -153,3 +165,100 @@ ftl_property_dump_uint32(const struct ftl_property *property,
	assert(property->size == sizeof(*value));
	spdk_json_write_named_uint32(w, property->name, *value);
}

int
ftl_property_decode(struct spdk_ftl_dev *dev, const char *name, const char *value,
		    size_t value_size, void **output, size_t *output_size)
{
	struct ftl_properties *properties = dev->properties;
	struct ftl_property *prop = get_property(properties, name);
	int rc;

	if (!prop) {
		FTL_ERRLOG(dev, "Property doesn't exist, name %s\n", name);
		return -ENOENT;
	}

	if (!prop->decode) {
		FTL_ERRLOG(dev, "Property is read only, name %s\n", name);
		return -EACCES;
	}

	assert(prop->size);
	assert(NULL == *output);

	/* Allocate buffer for the new value of the property */
	*output = calloc(1, prop->size);
	if (NULL == *output) {
		FTL_ERRLOG(dev, "Property allocation memory error, name %s\n", name);
		return -EACCES;
	}
	*output_size = prop->size;

	rc = prop->decode(dev, prop, value, value_size, *output, *output_size);
	if (rc) {
		FTL_ERRLOG(dev, "Property decode error, name %s\n", name);
		free(*output);
		*output = NULL;
		return rc;
	}

	return 0;
}

int
ftl_property_set(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt,
		 const char *name, void *value, size_t value_size)
{
	struct ftl_properties *properties = dev->properties;
	struct ftl_property *prop = get_property(properties, name);

	if (!prop) {
		FTL_ERRLOG(dev, "Property doesn't exist, name %s\n", name);
		return -ENOENT;
	}

	if (!prop->set) {
		FTL_ERRLOG(dev, "Property is read only, name %s\n", name);
		return -EACCES;
	}

	prop->set(dev, mngt, prop, value, value_size);
	return 0;
}

void
ftl_property_set_generic(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt,
			 const struct ftl_property *property, void *new_value, size_t new_value_size)
{
	ftl_bug(property->size != new_value_size);
	memcpy(property->value, new_value, property->size);
	ftl_mngt_next_step(mngt);
}

int
ftl_property_decode_bool(struct spdk_ftl_dev *dev, struct ftl_property *property,
			 const char *value, size_t value_size, void *output, size_t output_size)
{
	bool *out = output;

	if (sizeof(bool) != output_size) {
		return -ENOBUFS;
	}

	if (strnlen(value, value_size) == value_size) {
		return -EINVAL;
	}

	if (0 == strncmp(value, "true", strlen("true"))) {
		*out = true;
		return 0;
	}

	if (0 == strncmp(value, "false", strlen("false"))) {
		*out = false;
		return 0;
	}

	return -EINVAL;
}
Loading