Commit f9d52c9e authored by Daniel Verkamp's avatar Daniel Verkamp
Browse files

lvol: add destroy_lvol_bdev RPC method



This is the first step toward fixing the behavior of the lvol bdev
module so that it handles spdk_bdev_unregister() correctly.

Currently, when an lvol bdev is unregistered, this causes the associated
lvol to be deleted; this isn't the desired behavior, since
spdk_bdev_unregister() is just meant to drop the currently-exposed bdev,
as in a hot-unplug event, not destroy the backing storage.

The current implementation of the new destroy_lvol_bdev method still
calls into the exsting (broken) spdk_bdev_unregister() path, but this at
least lets us fix the existing delete_bdev RPC callers that really
intended to destroy the lvol.

The next step is to make vbdev_lvol_destroy() call spdk_lvol_destroy()
instead of unregistering the bdev, which will require cleanup in the
generic lvol layer to remove the close_only flag.

Change-Id: Ic4cb51305d31f6d7366a82ba7bf7b19ebbcd3e9c
Signed-off-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Reviewed-on: https://review.gerrithub.io/408084


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent c2b66a83
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -62,6 +62,10 @@ spdk_blob_resize() is now an asynchronous operation to enable resizing a blob wh
are in progress to that blob on other threads.  An explicit spdk_blob_sync_md() is still
required to sync the updated metadata to disk.

### Logical Volumes

A new `destroy_lvol_bdev` RPC method to delete logical volumes has been added.

### Lib

A set of changes were made in the SPDK's lib code altering,
+3 −3
Original line number Diff line number Diff line
@@ -58,7 +58,7 @@ destroy_lvol_store [-h] [-u UUID] [-l LVS_NAME]
    Destroy lvolstore on specified bdev. Removes lvolstore along with lvols on
    it. User can identify lvol store by UUID or its name. Note that destroying
    lvolstore requires using this call, while deleting single lvol requires
    using delete_bdev rpc call.
    using destroy_lvol_bdev rpc call.
    optional arguments:
    -h, --help  show help
get_lvol_stores [-h] [-u UUID] [-l LVS_NAME]
@@ -88,8 +88,8 @@ get_bdevs [-h] [-b NAME]
    optional arguments:
    -h, --help  show help
    -b NAME, --name NAME  Name of the block device. Example: Nvme0n1
delete_bdev [-h] bdev_name
    Deletes spdk bdev
destroy_lvol_bdev [-h] bdev_name
    Deletes a logical volume previously created by construct_lvol_bdev.
    optional arguments:
    -h, --help  show help
snapshot_lvol_bdev [-h] lvol_name snapshot_name
+10 −0
Original line number Diff line number Diff line
@@ -562,6 +562,16 @@ vbdev_lvol_destruct(void *ctx)
	return 1;
}

void
vbdev_lvol_destroy(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
{
	/*
	 * TODO: This should call spdk_lvol_destroy() directly, and the bdev unregister path
	 * should be changed so that it does not destroy the lvol.
	 */
	spdk_bdev_unregister(lvol->bdev, cb_fn, cb_arg);
}

static char *
vbdev_lvol_find_name(struct spdk_lvol *lvol, spdk_blob_id blob_id)
{
+8 −0
Original line number Diff line number Diff line
@@ -75,6 +75,14 @@ void vbdev_lvol_resize(struct spdk_lvol *lvol, uint64_t sz, spdk_lvol_op_complet
void vbdev_lvol_rename(struct spdk_lvol *lvol, const char *new_lvol_name,
		       spdk_lvol_op_complete cb_fn, void *cb_arg);

/**
 * Destroy a logical volume
 * \param lvol Handle to lvol
 * \param cb_fn Completion callback
 * \param cb_arg Completion callback custom arguments
 */
void vbdev_lvol_destroy(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg);

/**
 * \brief Renames given lvolstore.
 *
+81 −0
Original line number Diff line number Diff line
@@ -768,6 +768,87 @@ invalid:

SPDK_RPC_REGISTER("resize_lvol_bdev", spdk_rpc_resize_lvol_bdev)

struct rpc_destroy_lvol_bdev {
	char *name;
};

static void
free_rpc_destroy_lvol_bdev(struct rpc_destroy_lvol_bdev *req)
{
	free(req->name);
}

static const struct spdk_json_object_decoder rpc_destroy_lvol_bdev_decoders[] = {
	{"name", offsetof(struct rpc_destroy_lvol_bdev, name), spdk_json_decode_string},
};

static void
_spdk_rpc_destroy_lvol_bdev_cb(void *cb_arg, int lvolerrno)
{
	struct spdk_json_write_ctx *w;
	struct spdk_jsonrpc_request *request = cb_arg;

	if (lvolerrno != 0) {
		goto invalid;
	}

	w = spdk_jsonrpc_begin_result(request);
	if (w == NULL) {
		return;
	}

	spdk_json_write_bool(w, true);
	spdk_jsonrpc_end_result(request, w);
	return;

invalid:
	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
					 spdk_strerror(-lvolerrno));
}

static void
spdk_rpc_destroy_lvol_bdev(struct spdk_jsonrpc_request *request,
			   const struct spdk_json_val *params)
{
	struct rpc_destroy_lvol_bdev req = {};
	struct spdk_bdev *bdev;
	struct spdk_lvol *lvol;
	int rc;

	if (spdk_json_decode_object(params, rpc_destroy_lvol_bdev_decoders,
				    SPDK_COUNTOF(rpc_destroy_lvol_bdev_decoders),
				    &req)) {
		SPDK_INFOLOG(SPDK_LOG_LVOL_RPC, "spdk_json_decode_object failed\n");
		rc = -EINVAL;
		goto invalid;
	}

	bdev = spdk_bdev_get_by_name(req.name);
	if (bdev == NULL) {
		SPDK_ERRLOG("no bdev for provided name %s\n", req.name);
		rc = -ENODEV;
		goto invalid;
	}

	lvol = vbdev_lvol_get_from_bdev(bdev);
	if (lvol == NULL) {
		rc = -ENODEV;
		goto invalid;
	}

	vbdev_lvol_destroy(lvol, _spdk_rpc_destroy_lvol_bdev_cb, request);

	free_rpc_destroy_lvol_bdev(&req);
	return;

invalid:
	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
					 spdk_strerror(-rc));
	free_rpc_destroy_lvol_bdev(&req);
}

SPDK_RPC_REGISTER("destroy_lvol_bdev", spdk_rpc_destroy_lvol_bdev)

struct rpc_get_lvol_stores {
	char *uuid;
	char *lvs_name;
Loading