Commit b860c8db authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Changpeng Liu
Browse files

bdev/gpt: call get buffer function before forwarding read I/O to the base bdev



iSCSI target does not allocate data buffer on read, and delegate
allocation to the bdev.

When the bdev is a split vbdev, the split vbdev does not allocate
data buffer and delegate allocation to the backend bdev.

In this case, iSCSI target expects the buffer is allocated until
notifying completion to the split vbdev. However, the split vbdev
notifies completion to the backend bdev when calling the callback
of iSCSI target. The backend bdev frees the buffer immediately,
but iSCSI target still uses the buffer. If the buffer is reused
by another I/O, data corruption will occur.

For this issue, vbdev_gpt_submti_request() calls
spdk_bdev_io_get_buf() when the I/O is read, and its callback
vbdev_gpt_get_buf_cb calls _vbdev_gpt_submit_request() then.

This will ensure the buffer is allocated before forwarding I/O
to the backed bdev.

Signed-off-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: Ifb2eac500276ab5012123b7d6f7eb033d87ad17c
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/461350


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
parent 25532d08
Loading
Loading
Loading
Loading
+30 −2
Original line number Diff line number Diff line
@@ -171,12 +171,15 @@ vbdev_gpt_destruct(void *ctx)
	return spdk_bdev_part_free(&gpt_disk->part);
}

static void
_vbdev_gpt_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io);

static void
vbdev_gpt_resubmit_request(void *arg)
{
	struct gpt_io *io = (struct gpt_io *)arg;

	vbdev_gpt_submit_request(io->ch, io->bdev_io);
	_vbdev_gpt_submit_request(io->ch, io->bdev_io);
}

static void
@@ -197,7 +200,18 @@ vbdev_gpt_queue_io(struct gpt_io *io)
}

static void
vbdev_gpt_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io)
vbdev_gpt_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io, bool success)
{
	if (!success) {
		spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
		return;
	}

	_vbdev_gpt_submit_request(ch, bdev_io);
}

static void
_vbdev_gpt_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io)
{
	struct gpt_channel *ch = spdk_io_channel_get_ctx(_ch);
	struct gpt_io *io = (struct gpt_io *)bdev_io->driver_ctx;
@@ -217,6 +231,20 @@ vbdev_gpt_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_
	}
}

static void
vbdev_gpt_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io)
{
	switch (bdev_io->type) {
	case SPDK_BDEV_IO_TYPE_READ:
		spdk_bdev_io_get_buf(bdev_io, vbdev_gpt_get_buf_cb,
				     bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
		break;
	default:
		_vbdev_gpt_submit_request(_ch, bdev_io);
		break;
	}
}

static void
write_guid(struct spdk_json_write_ctx *w, const struct spdk_gpt_guid *guid)
{