Commit 0441ffcc authored by Jim Harris's avatar Jim Harris
Browse files

nbd: do not free spdk_nbd_disk with io outstanding



There is a race condition here, where kernel could have
outstanding I/O to nbd device at the same time we terminate
the nbd application.  In this case, we cannot free the
spdk_nbd_disk since it contains the io structure that
will be referenced when the SPDK poller completes one
of those I/O.

Signed-off-by: default avatarJim Harris <james.r.harris@intel.com>
Change-Id: I1bde240af904957f4d2bfa358dc673105d266986

Reviewed-on: https://review.gerrithub.io/385927


Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarZiye Yang <optimistyzy@gmail.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
parent fa952fcd
Loading
Loading
Loading
Loading
+24 −6
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@

struct nbd_io {
	enum spdk_bdev_io_type	type;
	int			ref;
	void			*payload;

	/* NOTE: for TRIM, this represents number of bytes to trim. */
@@ -97,13 +98,9 @@ is_write(enum spdk_bdev_io_type io_type)
	}
}

void
spdk_nbd_stop(struct spdk_nbd_disk *nbd)
static void
_nbd_stop(struct spdk_nbd_disk *nbd)
{
	if (nbd == NULL) {
		return;
	}

	if (nbd->ch) {
		spdk_put_io_channel(nbd->ch);
	}
@@ -119,6 +116,19 @@ spdk_nbd_stop(struct spdk_nbd_disk *nbd)
	free(nbd);
}

void
spdk_nbd_stop(struct spdk_nbd_disk *nbd)
{
	if (nbd == NULL) {
		return;
	}

	nbd->io.ref--;
	if (nbd->io.ref == 0) {
		_nbd_stop(nbd);
	}
}

static int64_t
read_from_socket(int fd, void *buf, size_t length)
{
@@ -169,6 +179,11 @@ nbd_io_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
	if (bdev_io != NULL) {
		spdk_bdev_free_io(bdev_io);
	}

	io->ref--;
	if (io->ref == 0) {
		_nbd_stop(SPDK_CONTAINEROF(io, struct spdk_nbd_disk, io));
	}
}

static void
@@ -177,6 +192,8 @@ nbd_submit_bdev_io(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
{
	int rc;

	io->ref++;

	switch (io->type) {
	case SPDK_BDEV_IO_TYPE_READ:
		rc = spdk_bdev_read(desc, ch, io->payload, from_be64(&io->req.from),
@@ -376,6 +393,7 @@ spdk_nbd_start(struct spdk_bdev *bdev, const char *nbd_path)
		goto err;
	}

	nbd->io.ref = 1;
	nbd->bdev = bdev;
	nbd->ch = spdk_bdev_get_io_channel(nbd->bdev_desc);
	nbd->buf_align = spdk_max(spdk_bdev_get_buf_align(bdev), 64);