Commit 6eed119e authored by Artur Paszkiewicz's avatar Artur Paszkiewicz Committed by Tomasz Zawadzki
Browse files

module/raid: wait for base bdev callbacks when creating raid bdev



Errors reported asynchronously (like when reading the superblock) would
be ignored. Now, bdev_raid_create RPC will not return until all base
bdev callbacks have completed.

Change-Id: Icc53d88d965b878f18889ed2b6030bf37a2b915c
Signed-off-by: default avatarArtur Paszkiewicz <artur.paszkiewicz@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/20521


Tested-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
parent d6fa87ae
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -3096,14 +3096,17 @@ raid_bdev_attach_base_bdev(struct raid_bdev *raid_bdev, struct spdk_bdev *base_b
 * raid_bdev - pointer to raid bdev
 * name - name of the base bdev
 * slot - position to add base bdev
 * cb_fn - callback function
 * cb_ctx - argument to callback function
 * returns:
 * 0 - success
 * non zero - failure
 */
int
raid_bdev_add_base_device(struct raid_bdev *raid_bdev, const char *name, uint8_t slot)
raid_bdev_add_base_device(struct raid_bdev *raid_bdev, const char *name, uint8_t slot,
			  raid_base_bdev_cb cb_fn, void *cb_ctx)
{
	return _raid_bdev_add_base_device(raid_bdev, name, slot, 0, 0, NULL, NULL);
	return _raid_bdev_add_base_device(raid_bdev, name, slot, 0, 0, cb_fn, cb_ctx);
}

static int
+2 −1
Original line number Diff line number Diff line
@@ -253,7 +253,8 @@ int raid_bdev_create(const char *name, uint32_t strip_size, uint8_t num_base_bde
		     enum raid_level level, bool superblock, const struct spdk_uuid *uuid,
		     struct raid_bdev **raid_bdev_out);
void raid_bdev_delete(struct raid_bdev *raid_bdev, raid_bdev_destruct_cb cb_fn, void *cb_ctx);
int raid_bdev_add_base_device(struct raid_bdev *raid_bdev, const char *name, uint8_t slot);
int raid_bdev_add_base_device(struct raid_bdev *raid_bdev, const char *name, uint8_t slot,
			      raid_base_bdev_cb cb_fn, void *cb_ctx);
struct raid_bdev *raid_bdev_find_by_name(const char *name);
enum raid_level raid_bdev_str_to_level(const char *str);
const char *raid_bdev_level_to_str(enum raid_level level);
+89 −37
Original line number Diff line number Diff line
@@ -139,25 +139,6 @@ struct rpc_bdev_raid_create {
	bool                                 superblock_enabled;
};

/*
 * brief:
 * free_rpc_bdev_raid_create function is to free RPC bdev_raid_create related parameters
 * params:
 * req - pointer to RPC request
 * returns:
 * none
 */
static void
free_rpc_bdev_raid_create(struct rpc_bdev_raid_create *req)
{
	size_t i;

	free(req->name);
	for (i = 0; i < req->base_bdevs.num_base_bdevs; i++) {
		free(req->base_bdevs.base_bdevs[i]);
	}
}

/*
 * Decoder function for RPC bdev_raid_create to decode raid level
 */
@@ -205,6 +186,61 @@ static const struct spdk_json_object_decoder rpc_bdev_raid_create_decoders[] = {
	{"superblock", offsetof(struct rpc_bdev_raid_create, superblock_enabled), spdk_json_decode_bool, true},
};

struct rpc_bdev_raid_create_ctx {
	struct rpc_bdev_raid_create req;
	struct raid_bdev *raid_bdev;
	struct spdk_jsonrpc_request *request;
	uint8_t remaining;
	int status;
};

static void
free_rpc_bdev_raid_create_ctx(struct rpc_bdev_raid_create_ctx *ctx)
{
	struct rpc_bdev_raid_create *req;
	size_t i;

	if (!ctx) {
		return;
	}

	req = &ctx->req;

	free(req->name);
	for (i = 0; i < req->base_bdevs.num_base_bdevs; i++) {
		free(req->base_bdevs.base_bdevs[i]);
	}

	free(ctx);
}

static void
rpc_bdev_raid_create_add_base_bdev_cb(void *_ctx, int status)
{
	struct rpc_bdev_raid_create_ctx *ctx = _ctx;

	if (status != 0) {
		ctx->status = status;
	}

	assert(ctx->remaining != 0);
	if (--ctx->remaining > 0) {
		return;
	}

	if (ctx->status != 0) {
		raid_bdev_delete(ctx->raid_bdev, NULL, NULL);
		spdk_jsonrpc_send_error_response_fmt(ctx->request, ctx->status,
						     "Failed to create RAID bdev %s: %s",
						     ctx->req.name,
						     spdk_strerror(-ctx->status));
	} else {
		spdk_jsonrpc_send_bool_response(ctx->request, true);
	}

	free_rpc_bdev_raid_create_ctx(ctx);
}

/*
 * brief:
 * rpc_bdev_raid_create function is the RPC for creating RAID bdevs. It takes
@@ -219,48 +255,64 @@ static void
rpc_bdev_raid_create(struct spdk_jsonrpc_request *request,
		     const struct spdk_json_val *params)
{
	struct rpc_bdev_raid_create	req = {};
	struct rpc_bdev_raid_create	*req;
	struct raid_bdev		*raid_bdev;
	int				rc;
	size_t				i;
	struct rpc_bdev_raid_create_ctx *ctx;
	uint8_t				num_base_bdevs;

	ctx = calloc(1, sizeof(*ctx));
	if (ctx == NULL) {
		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
		goto cleanup;
	}
	req = &ctx->req;

	if (spdk_json_decode_object(params, rpc_bdev_raid_create_decoders,
				    SPDK_COUNTOF(rpc_bdev_raid_create_decoders),
				    &req)) {
				    req)) {
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
						 "spdk_json_decode_object failed");
		goto cleanup;
	}
	num_base_bdevs = req->base_bdevs.num_base_bdevs;

	rc = raid_bdev_create(req.name, req.strip_size_kb, req.base_bdevs.num_base_bdevs,
			      req.level, req.superblock_enabled, &req.uuid, &raid_bdev);
	rc = raid_bdev_create(req->name, req->strip_size_kb, num_base_bdevs,
			      req->level, req->superblock_enabled, &req->uuid, &raid_bdev);
	if (rc != 0) {
		spdk_jsonrpc_send_error_response_fmt(request, rc,
						     "Failed to create RAID bdev %s: %s",
						     req.name, spdk_strerror(-rc));
						     req->name, spdk_strerror(-rc));
		goto cleanup;
	}

	for (i = 0; i < req.base_bdevs.num_base_bdevs; i++) {
		const char *base_bdev_name = req.base_bdevs.base_bdevs[i];
	ctx->raid_bdev = raid_bdev;
	ctx->request = request;
	ctx->remaining = num_base_bdevs;

	assert(num_base_bdevs > 0);

		rc = raid_bdev_add_base_device(raid_bdev, base_bdev_name, i);
	for (i = 0; i < num_base_bdevs; i++) {
		const char *base_bdev_name = req->base_bdevs.base_bdevs[i];

		rc = raid_bdev_add_base_device(raid_bdev, base_bdev_name, i,
					       rpc_bdev_raid_create_add_base_bdev_cb, ctx);
		if (rc == -ENODEV) {
			SPDK_DEBUGLOG(bdev_raid, "base bdev %s doesn't exist now\n", base_bdev_name);
			assert(ctx->remaining > 1 || i + 1 == num_base_bdevs);
			rpc_bdev_raid_create_add_base_bdev_cb(ctx, 0);
		} else if (rc != 0) {
			raid_bdev_delete(raid_bdev, NULL, NULL);
			spdk_jsonrpc_send_error_response_fmt(request, rc,
							     "Failed to add base bdev %s to RAID bdev %s: %s",
							     base_bdev_name, req.name,
							     spdk_strerror(-rc));
			goto cleanup;
			SPDK_DEBUGLOG(bdev_raid, "Failed to add base bdev %s to RAID bdev %s: %s",
				      base_bdev_name, req->name, spdk_strerror(-rc));
			ctx->remaining -= (num_base_bdevs - i - 1);
			rpc_bdev_raid_create_add_base_bdev_cb(ctx, rc);
			break;
		}
	}

	spdk_jsonrpc_send_bool_response(request, true);

	return;
cleanup:
	free_rpc_bdev_raid_create(&req);
	free_rpc_bdev_raid_create_ctx(ctx);
}
SPDK_RPC_REGISTER("bdev_raid_create", rpc_bdev_raid_create, SPDK_RPC_RUNTIME)

+2 −5
Original line number Diff line number Diff line
@@ -397,12 +397,9 @@ function raid_superblock_test() {
	fi

	# Try to create new RAID bdev from malloc bdevs
	# Should not reach online state due to superblock still present on base bdevs
	$rpc_py bdev_raid_create $strip_size_create_arg -r $raid_level -b "${base_bdevs_malloc[*]}" -n $raid_bdev_name
	verify_raid_bdev_state $raid_bdev_name "configuring" $raid_level $strip_size $num_base_bdevs
	# Should fail due to superblock still present on base bdevs
	NOT $rpc_py bdev_raid_create $strip_size_create_arg -r $raid_level -b "${base_bdevs_malloc[*]}" -n $raid_bdev_name

	# Stop the RAID bdev
	$rpc_py bdev_raid_delete $raid_bdev_name
	raid_bdev=$($rpc_py bdev_raid_get_bdevs all | jq -r '.[]')
	if [ -n "$raid_bdev" ]; then
		return 1