diff --git a/include/spdk/bdev.h b/include/spdk/bdev.h index 2f5642108..01d2631c8 100644 --- a/include/spdk/bdev.h +++ b/include/spdk/bdev.h @@ -389,4 +389,13 @@ void spdk_bdev_io_get_nvme_status(const struct spdk_bdev_io *bdev_io, int *sct, void spdk_bdev_io_get_scsi_status(const struct spdk_bdev_io *bdev_io, int *sc, int *sk, int *asc, int *ascq); +/** + * Get the iovec describing the data buffer of a bdev_io. + * + * \param bdev_io I/O to describe with iovec. + * \param iovp Pointer to be filled with iovec. + * \param iovcntp Pointer to be filled with number of iovec entries. + */ +void spdk_bdev_io_get_iovec(struct spdk_bdev_io *bdev_io, struct iovec **iovp, int *iovcntp); + #endif /* SPDK_BDEV_H_ */ diff --git a/lib/bdev/bdev.c b/lib/bdev/bdev.c index 911ef5e24..8027ded98 100644 --- a/lib/bdev/bdev.c +++ b/lib/bdev/bdev.c @@ -1105,6 +1105,39 @@ spdk_bdev_io_get_rbuf(struct spdk_bdev_io *bdev_io, spdk_bdev_io_get_rbuf_cb cb) } } +void +spdk_bdev_io_get_iovec(struct spdk_bdev_io *bdev_io, struct iovec **iovp, int *iovcntp) +{ + struct iovec *iovs; + int iovcnt; + + if (bdev_io == NULL) { + return; + } + + switch (bdev_io->type) { + case SPDK_BDEV_IO_TYPE_READ: + iovs = bdev_io->u.read.iovs; + iovcnt = bdev_io->u.read.iovcnt; + break; + case SPDK_BDEV_IO_TYPE_WRITE: + iovs = bdev_io->u.write.iovs; + iovcnt = bdev_io->u.write.iovcnt; + break; + default: + iovs = NULL; + iovcnt = 0; + break; + } + + if (iovp) { + *iovp = iovs; + } + if (iovcntp) { + *iovcntp = iovcnt; + } +} + void spdk_bdev_module_list_add(struct spdk_bdev_module_if *bdev_module) { TAILQ_INSERT_TAIL(&spdk_bdev_module_list, bdev_module, tailq); diff --git a/lib/scsi/scsi_bdev.c b/lib/scsi/scsi_bdev.c index c3c16e2a7..fa2b165dc 100644 --- a/lib/scsi/scsi_bdev.c +++ b/lib/scsi/scsi_bdev.c @@ -1225,6 +1225,8 @@ spdk_bdev_scsi_task_complete(struct spdk_bdev_io *bdev_io, enum spdk_bdev_io_sta void *cb_arg) { struct spdk_scsi_task *task = cb_arg; + struct iovec *iovs; + int iovcnt; if (task->type == SPDK_SCSI_TASK_TYPE_CMD) { int sc, sk, asc, ascq; @@ -1235,9 +1237,12 @@ spdk_bdev_scsi_task_complete(struct spdk_bdev_io *bdev_io, enum spdk_bdev_io_sta if (status == SPDK_BDEV_IO_STATUS_SUCCESS) task->response = SPDK_SCSI_TASK_MGMT_RESP_SUCCESS; } - if (bdev_io->type == SPDK_BDEV_IO_TYPE_READ && task->iovs != bdev_io->u.read.iovs) { - assert(task->iovcnt == bdev_io->u.read.iovcnt); - memcpy(task->iovs, bdev_io->u.read.iovs, sizeof(task->iovs[0]) * task->iovcnt); + + spdk_bdev_io_get_iovec(bdev_io, &iovs, &iovcnt); + if (task->dxfer_dir == SPDK_SCSI_DIR_FROM_DEV && task->iovs != iovs) { + assert(iovs != NULL); + assert(task->iovcnt == iovcnt); + memcpy(task->iovs, iovs, sizeof(task->iovs[0]) * task->iovcnt); } spdk_scsi_lun_complete_task(task->lun, task); diff --git a/test/lib/bdev/bdevperf/bdevperf.c b/test/lib/bdev/bdevperf/bdevperf.c index 1d3022e40..f373ba358 100644 --- a/test/lib/bdev/bdevperf/bdevperf.c +++ b/test/lib/bdev/bdevperf/bdevperf.c @@ -191,6 +191,8 @@ bdevperf_complete(struct spdk_bdev_io *bdev_io, enum spdk_bdev_io_status status, struct io_target *target; struct bdevperf_task *task = cb_arg; struct spdk_event *complete; + struct iovec *iovs; + int iovcnt; target = task->target; @@ -200,8 +202,10 @@ bdevperf_complete(struct spdk_bdev_io *bdev_io, enum spdk_bdev_io_status status, g_run_failed = true; } } else if (g_verify || g_reset || g_unmap) { - assert(bdev_io->u.read.iovcnt == 1); - if (memcmp(task->buf, bdev_io->u.read.iov.iov_base, g_io_size) != 0) { + spdk_bdev_io_get_iovec(bdev_io, &iovs, &iovcnt); + assert(iovcnt == 1); + assert(iovs != NULL); + if (memcmp(task->buf, iovs[0].iov_base, g_io_size) != 0) { printf("Buffer mismatch! Disk Offset: %lu\n", task->offset); target->is_draining = true; g_run_failed = true; diff --git a/test/lib/scsi/scsi_bdev/scsi_bdev_ut.c b/test/lib/scsi/scsi_bdev/scsi_bdev_ut.c index 7692d0531..b8fde492d 100644 --- a/test/lib/scsi/scsi_bdev/scsi_bdev_ut.c +++ b/test/lib/scsi/scsi_bdev/scsi_bdev_ut.c @@ -133,6 +133,13 @@ spdk_bdev_io_get_scsi_status(const struct spdk_bdev_io *bdev_io, } } +void +spdk_bdev_io_get_iovec(struct spdk_bdev_io *bdev_io, struct iovec **iovp, int *iovcntp) +{ + *iovp = NULL; + *iovcntp = 0; +} + struct spdk_bdev_io * spdk_bdev_read(struct spdk_bdev *bdev, struct spdk_io_channel *ch, void *buf, uint64_t offset, uint64_t nbytes,