Commit 2fe6d1d5 authored by Ben Walker's avatar Ben Walker Committed by Darek Stojaczyk
Browse files

nbd: Make spdk_nbd_start asynchronous



Add a callback to spdk_nbd_start so that it can complete
asynchronously. As of this patch, it always calls the
callback immediately.

Change-Id: I6156fb203145362afa5e4102183b6cf143051c0c
Signed-off-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-on: https://review.gerrithub.io/433937


Tested-by: default avatarDarek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: default avatarDarek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent 027a8e4b
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -59,16 +59,24 @@ int spdk_nbd_init(void);
 */
void spdk_nbd_fini(void);

/**
 * Called when an NBD device has been started.
 */
typedef void (*spdk_nbd_start_cb)(void *cb_arg, struct spdk_nbd_disk *nbd,
				  int rc);

/**
 * Start a network block device backed by the bdev.
 *
 * \param bdev_name Name of bdev exposed as a network block device.
 * \param nbd_path Path to the registered network block device.
 * \param cb_fn Called when the device has been started.
 * \param cb_arg Passed to cb_fn.
 *
 * \return a pointer to the configuration of the registered network block device
 * on success, or NULL on failure.
 * \return A negated error number is passed to cb_fn on failure.
 */
struct spdk_nbd_disk *spdk_nbd_start(const char *bdev_name, const char *nbd_path);
void spdk_nbd_start(const char *bdev_name, const char *nbd_path,
		    spdk_nbd_start_cb cb_fn, void *cb_arg);

/**
 * Stop the running network block device safely.
+27 −8
Original line number Diff line number Diff line
@@ -837,10 +837,11 @@ spdk_nbd_bdev_hot_remove(void *remove_ctx)
	spdk_nbd_stop(nbd);
}

struct spdk_nbd_disk *
spdk_nbd_start(const char *bdev_name, const char *nbd_path)
void
spdk_nbd_start(const char *bdev_name, const char *nbd_path,
	       spdk_nbd_start_cb cb_fn, void *cb_arg)
{
	struct spdk_nbd_disk	*nbd;
	struct spdk_nbd_disk	*nbd = NULL;
	struct spdk_bdev	*bdev;
	pthread_t		tid;
	int			rc;
@@ -850,12 +851,14 @@ spdk_nbd_start(const char *bdev_name, const char *nbd_path)
	bdev = spdk_bdev_get_by_name(bdev_name);
	if (bdev == NULL) {
		SPDK_ERRLOG("no bdev %s exists\n", bdev_name);
		return NULL;
		rc = -EINVAL;
		goto err;
	}

	nbd = calloc(1, sizeof(*nbd));
	if (nbd == NULL) {
		return NULL;
		rc = -ENOMEM;
		goto err;
	}

	nbd->dev_fd = -1;
@@ -884,6 +887,7 @@ spdk_nbd_start(const char *bdev_name, const char *nbd_path)
	nbd->nbd_path = strdup(nbd_path);
	if (!nbd->nbd_path) {
		SPDK_ERRLOG("strdup allocation failure\n");
		rc = -ENOMEM;
		goto err;
	}

@@ -899,24 +903,28 @@ spdk_nbd_start(const char *bdev_name, const char *nbd_path)
	nbd->dev_fd = open(nbd_path, O_RDWR);
	if (nbd->dev_fd == -1) {
		SPDK_ERRLOG("open(\"%s\") failed: %s\n", nbd_path, spdk_strerror(errno));
		rc = -errno;
		goto err;
	}

	rc = ioctl(nbd->dev_fd, NBD_SET_BLKSIZE, spdk_bdev_get_block_size(bdev));
	if (rc == -1) {
		SPDK_ERRLOG("ioctl(NBD_SET_BLKSIZE) failed: %s\n", spdk_strerror(errno));
		rc = -errno;
		goto err;
	}

	rc = ioctl(nbd->dev_fd, NBD_SET_SIZE_BLOCKS, spdk_bdev_get_num_blocks(bdev));
	if (rc == -1) {
		SPDK_ERRLOG("ioctl(NBD_SET_SIZE_BLOCKS) failed: %s\n", spdk_strerror(errno));
		rc = -errno;
		goto err;
	}

	rc = ioctl(nbd->dev_fd, NBD_CLEAR_SOCK);
	if (rc == -1) {
		SPDK_ERRLOG("ioctl(NBD_CLEAR_SOCK) failed: %s\n", spdk_strerror(errno));
		rc = -errno;
		goto err;
	}

@@ -926,6 +934,7 @@ spdk_nbd_start(const char *bdev_name, const char *nbd_path)
	rc = ioctl(nbd->dev_fd, NBD_SET_SOCK, nbd->kernel_sp_fd);
	if (rc == -1) {
		SPDK_ERRLOG("ioctl(NBD_SET_SOCK) failed: %s\n", spdk_strerror(errno));
		rc = -errno;
		goto err;
	}

@@ -933,6 +942,7 @@ spdk_nbd_start(const char *bdev_name, const char *nbd_path)
	rc = ioctl(nbd->dev_fd, NBD_SET_FLAGS, NBD_FLAG_SEND_TRIM);
	if (rc == -1) {
		SPDK_ERRLOG("ioctl(NBD_SET_FLAGS) failed: %s\n", spdk_strerror(errno));
		rc = -errno;
		goto err;
	}
#endif
@@ -953,17 +963,26 @@ spdk_nbd_start(const char *bdev_name, const char *nbd_path)
	if (fcntl(nbd->spdk_sp_fd, F_SETFL, flag | O_NONBLOCK) < 0) {
		SPDK_ERRLOG("fcntl can't set nonblocking mode for socket, fd: %d (%s)\n",
			    nbd->spdk_sp_fd, spdk_strerror(errno));
		rc = -errno;
		goto err;
	}

	nbd->nbd_poller = spdk_poller_register(spdk_nbd_poll, nbd, 0);

	return nbd;
	if (cb_fn) {
		cb_fn(cb_arg, nbd, 0);
	}

	return;

err:
	if (nbd) {
		spdk_nbd_stop(nbd);
	}

	return NULL;
	if (cb_fn) {
		cb_fn(cb_arg, NULL, rc);
	}
}

const char *
+22 −13
Original line number Diff line number Diff line
@@ -58,12 +58,31 @@ static const struct spdk_json_object_decoder rpc_start_nbd_disk_decoders[] = {
	{"nbd_device", offsetof(struct rpc_start_nbd_disk, nbd_device), spdk_json_decode_string},
};

static void
spdk_rpc_start_nbd_done(void *cb_arg, struct spdk_nbd_disk *nbd, int rc)
{
	struct spdk_jsonrpc_request *request = cb_arg;
	struct spdk_json_write_ctx *w;

	if (rc) {
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
		return;
	}

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

	spdk_json_write_string(w, spdk_nbd_get_path(nbd));
	spdk_jsonrpc_end_result(request, w);
}

static void
spdk_rpc_start_nbd_disk(struct spdk_jsonrpc_request *request,
			const struct spdk_json_val *params)
{
	struct rpc_start_nbd_disk req = {};
	struct spdk_json_write_ctx *w;
	struct spdk_nbd_disk *nbd;

	if (spdk_json_decode_object(params, rpc_start_nbd_disk_decoders,
@@ -83,19 +102,9 @@ spdk_rpc_start_nbd_disk(struct spdk_jsonrpc_request *request,
		goto invalid;
	}

	nbd = spdk_nbd_start(req.bdev_name, req.nbd_device);
	if (!nbd) {
		goto invalid;
	}
	spdk_nbd_start(req.bdev_name, req.nbd_device,
		       spdk_rpc_start_nbd_done, request);

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

	spdk_json_write_string(w, req.nbd_device);
	spdk_jsonrpc_end_result(request, w);
	free_rpc_start_nbd_disk(&req);
	return;