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: Jim Harris <james.r.harris@intel.com>
Change-Id: I1bde240af904957f4d2bfa358dc673105d266986

Reviewed-on: https://review.gerrithub.io/385927
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Ziye Yang <optimistyzy@gmail.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
This commit is contained in:
Jim Harris 2017-11-06 10:51:31 -07:00
parent fa952fcd5a
commit 0441ffcc05

View File

@ -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);