Commit 2baeea7d authored by Maciej Szwed's avatar Maciej Szwed Committed by Jim Harris
Browse files

bdev: add callback to spdk bdev unregister and bdev destruct



Currently deleting bdev does not support asynchronous delete
operations. Because of that results are returned before device
is actually deleted and some operation can be peformed on that
device after removal of this device started.

Signed-off-by: default avatarMaciej Szwed <maciej.szwed@intel.com>
Change-Id: I305c302d8abd5d7c2c0f947fca70c58396872132
Reviewed-on: https://review.gerrithub.io/383732


Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent 32b35d99
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -124,6 +124,8 @@ struct spdk_bdev_module_if {
	TAILQ_ENTRY(spdk_bdev_module_if) tailq;
};

typedef void (*spdk_bdev_unregister_cb)(void *cb_arg, int rc);

/**
 * Function table for a block device backend.
 *
@@ -235,6 +237,12 @@ struct spdk_bdev {
	 */
	struct spdk_bdev_module_if *claim_module;

	/** Callback function that will be called after bdev destruct is completed. */
	spdk_bdev_unregister_cb	unregister_cb;

	/** Unregister call context */
	void *unregister_ctx;

	/** List of open descriptors for this block device. */
	TAILQ_HEAD(, spdk_bdev_desc) open_descs;

@@ -364,11 +372,11 @@ struct spdk_bdev_io {
};

void spdk_bdev_register(struct spdk_bdev *bdev);
void spdk_bdev_unregister(struct spdk_bdev *bdev);

void spdk_bdev_unregister(struct spdk_bdev *bdev, spdk_bdev_unregister_cb cb_fn, void *cb_arg);
void spdk_bdev_unregister_done(struct spdk_bdev *bdev, int bdeverrno);
void spdk_vbdev_register(struct spdk_bdev *vbdev, struct spdk_bdev **base_bdevs,
			 int base_bdev_count);
void spdk_vbdev_unregister(struct spdk_bdev *vbdev);
void spdk_vbdev_unregister(struct spdk_bdev *vbdev, spdk_bdev_unregister_cb cb_fn, void *cb_arg);

void spdk_bdev_module_examine_done(struct spdk_bdev_module_if *module);
void spdk_bdev_module_init_done(struct spdk_bdev_module_if *module);
+18 −5
Original line number Diff line number Diff line
@@ -1734,7 +1734,15 @@ spdk_vbdev_register(struct spdk_bdev *vbdev, struct spdk_bdev **base_bdevs, int
}

void
spdk_bdev_unregister(struct spdk_bdev *bdev)
spdk_bdev_unregister_done(struct spdk_bdev *bdev, int bdeverrno)
{
	if (bdev->unregister_cb != NULL) {
		bdev->unregister_cb(bdev->unregister_ctx, bdeverrno);
	}
}

void
spdk_bdev_unregister(struct spdk_bdev *bdev, spdk_bdev_unregister_cb cb_fn, void *cb_arg)
{
	struct spdk_bdev_desc	*desc, *tmp;
	int			rc;
@@ -1745,6 +1753,8 @@ spdk_bdev_unregister(struct spdk_bdev *bdev)
	pthread_mutex_lock(&bdev->mutex);

	bdev->status = SPDK_BDEV_STATUS_REMOVING;
	bdev->unregister_cb = cb_fn;
	bdev->unregister_ctx = cb_arg;

	TAILQ_FOREACH_SAFE(desc, &bdev->open_descs, link, tmp) {
		if (desc->remove_cb) {
@@ -1771,10 +1781,13 @@ spdk_bdev_unregister(struct spdk_bdev *bdev)
	if (rc < 0) {
		SPDK_ERRLOG("destruct failed\n");
	}
	if (rc <= 0 && cb_fn != NULL) {
		cb_fn(cb_arg, rc);
	}
}

void
spdk_vbdev_unregister(struct spdk_bdev *vbdev)
spdk_vbdev_unregister(struct spdk_bdev *vbdev, spdk_bdev_unregister_cb cb_fn, void *cb_arg)
{
	struct spdk_bdev *base_bdev;

@@ -1782,7 +1795,7 @@ spdk_vbdev_unregister(struct spdk_bdev *vbdev)
	TAILQ_FOREACH(base_bdev, &vbdev->base_bdevs, base_bdev_link) {
		TAILQ_REMOVE(&base_bdev->vbdevs, vbdev, vbdev_link);
	}
	spdk_bdev_unregister(vbdev);
	spdk_bdev_unregister(vbdev, cb_fn, cb_arg);
}

int
@@ -1835,7 +1848,7 @@ spdk_bdev_close(struct spdk_bdev_desc *desc)
	pthread_mutex_unlock(&bdev->mutex);

	if (do_unregister == true) {
		spdk_bdev_unregister(bdev);
		spdk_bdev_unregister(bdev, bdev->unregister_cb, bdev->unregister_ctx);
	}
}

@@ -1965,7 +1978,7 @@ spdk_bdev_part_base_hotremove(struct spdk_bdev *base_bdev, struct bdev_part_tail

	TAILQ_FOREACH_SAFE(part, tailq, tailq, tmp) {
		if (part->base->bdev == base_bdev) {
			spdk_vbdev_unregister(&part->bdev);
			spdk_vbdev_unregister(&part->bdev, NULL, NULL);
		}
	}
}
+21 −4
Original line number Diff line number Diff line
@@ -210,7 +210,7 @@ vbdev_lvs_destruct(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn,
		lvs->destruct_req->cb_arg = req;
		TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) {
			lvol->close_only = true;
			spdk_vbdev_unregister(lvol->bdev);
			spdk_vbdev_unregister(lvol->bdev, NULL, NULL);
		}
	}

@@ -316,16 +316,29 @@ _vbdev_lvol_close_cb(void *cb_arg, int lvserrno)
static void
_vbdev_lvol_destroy_cb(void *cb_arg, int lvserrno)
{
	struct spdk_bdev *bdev = cb_arg;

	SPDK_INFOLOG(SPDK_TRACE_VBDEV_LVOL, "Lvol destroyed\n");

	spdk_bdev_unregister_done(bdev, lvserrno);
	free(bdev);
}

static void
_vbdev_lvol_destroy_after_close_cb(void *cb_arg, int lvserrno)
{
	struct spdk_lvol *lvol = cb_arg;
	struct spdk_bdev *bdev = lvol->bdev;

	if (lvserrno != 0) {
		SPDK_INFOLOG(SPDK_TRACE_VBDEV_LVOL, "Could not close Lvol %s\n", lvol->old_name);
		spdk_bdev_unregister_done(bdev, lvserrno);
		free(bdev);
		return;
	}

	SPDK_INFOLOG(SPDK_TRACE_VBDEV_LVOL, "Lvol %s closed, begin destroying\n", lvol->old_name);
	spdk_lvol_destroy(lvol, _vbdev_lvol_destroy_cb, NULL);
	spdk_lvol_destroy(lvol, _vbdev_lvol_destroy_cb, bdev);
}

static int
@@ -334,14 +347,18 @@ vbdev_lvol_destruct(void *ctx)
	struct spdk_lvol *lvol = ctx;

	assert(lvol != NULL);
	free(lvol->bdev);

	if (lvol->close_only) {
		free(lvol->bdev);
		spdk_lvol_close(lvol, _vbdev_lvol_close_cb, NULL);
	} else {
		spdk_lvol_close(lvol, _vbdev_lvol_destroy_after_close_cb, lvol);
	}

	return 0;
	/* return 1 to indicate we have an operation that must finish asynchronously before the
	 *  lvol is closed
	 */
	return 1;
}

static int
+1 −1
Original line number Diff line number Diff line
@@ -875,7 +875,7 @@ remove_cb(void *cb_ctx, struct spdk_nvme_ctrlr *ctrlr)

	TAILQ_FOREACH_SAFE(nvme_bdev, &removed_bdevs, link, btmp) {
		TAILQ_REMOVE(&removed_bdevs, nvme_bdev, link);
		spdk_bdev_unregister(&nvme_bdev->disk);
		spdk_bdev_unregister(&nvme_bdev->disk, NULL, NULL);
	}
}

+16 −9
Original line number Diff line number Diff line
@@ -172,13 +172,27 @@ static const struct spdk_json_object_decoder rpc_delete_bdev_decoders[] = {
	{"name", offsetof(struct rpc_delete_bdev, name), spdk_json_decode_string},
};

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

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

	spdk_json_write_bool(w, bdeverrno == 0);
	spdk_jsonrpc_end_result(request, w);
}

static void
spdk_rpc_delete_bdev(struct spdk_jsonrpc_request *request,
		     const struct spdk_json_val *params)
{
	struct rpc_delete_bdev req = {};
	struct spdk_bdev *bdev;
	struct spdk_json_write_ctx *w;

	if (spdk_json_decode_object(params, rpc_delete_bdev_decoders,
				    sizeof(rpc_delete_bdev_decoders) / sizeof(*rpc_delete_bdev_decoders),
@@ -198,17 +212,10 @@ spdk_rpc_delete_bdev(struct spdk_jsonrpc_request *request,
		goto invalid;
	}

	spdk_bdev_unregister(bdev);
	spdk_bdev_unregister(bdev, _spdk_rpc_delete_bdev_cb, request);

	free_rpc_delete_bdev(&req);

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

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

invalid:
Loading