* [PATCH 1/4] block: add SCSI COMPARE_AND_WRITE support
2019-10-25 9:35 [PATCH 0/4] SCSI COMPARE_AND_WRITE support Yaowei Bai
@ 2019-10-25 9:35 ` Yaowei Bai
2019-10-25 9:36 ` [PATCH 2/4] block/rbd: implement bdrv_aio_compare_and_write interface Yaowei Bai
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Yaowei Bai @ 2019-10-25 9:35 UTC (permalink / raw)
To: pbonzini, fam, dillaman, kwolf, mreitz
Cc: baiyaowei, yangjun, qemu-devel, qemu-block
Some storages(i.e. librbd) already have interfaces to handle some SCSI
commands directly. This patch adds COMPARE_AND_WRITE command support
through the write path in the block io layer by introducing a new element
BDRV_REQ_COMPARE_AND_WRITE into BdrvRequestFlags which indicates a
COMPARE_AND_WRITE request. In this way we could easily extend to other
SCSI commands support like WRITE_SAME in the future.
Signed-off-by: Yaowei Bai <baiyaowei@cmss.chinamobile.com>
---
block/io.c | 20 ++++++++++++++++++++
include/block/block.h | 5 +++--
include/block/block_int.h | 3 +++
3 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/block/io.c b/block/io.c
index f0b86c1..667b5ea 100644
--- a/block/io.c
+++ b/block/io.c
@@ -1168,6 +1168,26 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
goto emulate_flags;
}
+ if (drv->bdrv_aio_compare_and_write &&
+ (flags & BDRV_REQ_COMPARE_AND_WRITE)) {
+ BlockAIOCB *acb;
+ CoroutineIOCompletion co = {
+ .coroutine = qemu_coroutine_self(),
+ };
+
+ acb = drv->bdrv_aio_compare_and_write(bs, offset, bytes, qiov,
+ flags & bs->supported_write_flags,
+ bdrv_co_io_em_complete, &co);
+ flags &= ~bs->supported_write_flags;
+ if (acb == NULL) {
+ ret = -EIO;
+ } else {
+ qemu_coroutine_yield();
+ ret = co.ret;
+ }
+ goto emulate_flags;
+ }
+
if (drv->bdrv_aio_pwritev) {
BlockAIOCB *acb;
CoroutineIOCompletion co = {
diff --git a/include/block/block.h b/include/block/block.h
index 89606bd..7159e03 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -92,9 +92,10 @@ typedef enum {
* on read request and means that caller doesn't really need data to be
* written to qiov parameter which may be NULL.
*/
- BDRV_REQ_PREFETCH = 0x200,
+ BDRV_REQ_PREFETCH = 0x200,
+ BDRV_REQ_COMPARE_AND_WRITE = 0x400,
/* Mask of valid flags */
- BDRV_REQ_MASK = 0x3ff,
+ BDRV_REQ_MASK = 0x7ff,
} BdrvRequestFlags;
typedef struct BlockSizes {
diff --git a/include/block/block_int.h b/include/block/block_int.h
index ca4ccac..a039b68 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -189,6 +189,9 @@ struct BlockDriver {
BlockAIOCB *(*bdrv_aio_pdiscard)(BlockDriverState *bs,
int64_t offset, int bytes,
BlockCompletionFunc *cb, void *opaque);
+ BlockAIOCB *(*bdrv_aio_compare_and_write)(BlockDriverState *bs,
+ uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags,
+ BlockCompletionFunc *cb, void *opaque);
int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs,
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/4] block/rbd: implement bdrv_aio_compare_and_write interface
2019-10-25 9:35 [PATCH 0/4] SCSI COMPARE_AND_WRITE support Yaowei Bai
2019-10-25 9:35 ` [PATCH 1/4] block: add " Yaowei Bai
@ 2019-10-25 9:36 ` Yaowei Bai
2019-10-25 9:36 ` [PATCH 3/4] hw/scsi: add SCSI COMPARE_AND_WRITE support Yaowei Bai
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Yaowei Bai @ 2019-10-25 9:36 UTC (permalink / raw)
To: pbonzini, fam, dillaman, kwolf, mreitz
Cc: baiyaowei, yangjun, qemu-devel, qemu-block
This patch adds librbd's SCSI COMPARE_AND_WRITE command interface
support with bdrv_aio_compare_and_write function pointer. Note
currently when a miscompare happens a mismatch offset of 0 is
always reported rather than the actual mismatch offset. This
should not be a big issue contemporarily and will be fixed
accordingly in the future.
Signed-off-by: Yaowei Bai <baiyaowei@cmss.chinamobile.com>
---
block/raw-format.c | 3 ++-
block/rbd.c | 41 +++++++++++++++++++++++++++++++++++++++--
2 files changed, 41 insertions(+), 3 deletions(-)
diff --git a/block/raw-format.c b/block/raw-format.c
index 42c28cc..3d8f201 100644
--- a/block/raw-format.c
+++ b/block/raw-format.c
@@ -438,7 +438,8 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
bs->sg = bs->file->bs->sg;
bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
- (BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
+ (BDRV_REQ_FUA & bs->file->bs->supported_write_flags) |
+ (BDRV_REQ_COMPARE_AND_WRITE & bs->file->bs->supported_write_flags);
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
bs->file->bs->supported_zero_flags);
diff --git a/block/rbd.c b/block/rbd.c
index c71e45d..7065343 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -73,11 +73,18 @@
#define LIBRBD_USE_IOVEC 0
#endif
+#ifdef LIBRBD_SUPPORTS_COMPARE_AND_WRITE
+#define LIBRBD_HAVE_COMPARE_AND_WRITE 1
+#else
+#define LIBRBD_HAVE_COMPARE_AND_WRITE 0
+#endif
+
typedef enum {
RBD_AIO_READ,
RBD_AIO_WRITE,
RBD_AIO_DISCARD,
- RBD_AIO_FLUSH
+ RBD_AIO_FLUSH,
+ RBD_AIO_COMPARE_AND_WRITE
} RBDAIOCmd;
typedef struct RBDAIOCB {
@@ -798,6 +805,9 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
}
}
+ if (LIBRBD_HAVE_COMPARE_AND_WRITE)
+ bs->supported_write_flags = BDRV_REQ_COMPARE_AND_WRITE;
+
r = 0;
goto out;
@@ -933,7 +943,15 @@ static BlockAIOCB *rbd_start_aio(BlockDriverState *bs,
rcb = g_new(RADOSCB, 1);
- if (!LIBRBD_USE_IOVEC) {
+ if (cmd == RBD_AIO_COMPARE_AND_WRITE) {
+ acb->bounce = qemu_try_blockalign(bs, qiov->size);
+ if (acb->bounce == NULL) {
+ goto failed;
+ }
+
+ qemu_iovec_to_buf(acb->qiov, 0, acb->bounce, qiov->size);
+ rcb->buf = acb->bounce;
+ } else if (!LIBRBD_USE_IOVEC) {
if (cmd == RBD_AIO_DISCARD || cmd == RBD_AIO_FLUSH) {
acb->bounce = NULL;
} else {
@@ -993,6 +1011,9 @@ static BlockAIOCB *rbd_start_aio(BlockDriverState *bs,
case RBD_AIO_FLUSH:
r = rbd_aio_flush_wrapper(s->image, c);
break;
+ case RBD_AIO_COMPARE_AND_WRITE:
+ r = rbd_aio_compare_and_write(s->image, off, size/2, rcb->buf, (rcb->buf + size/2), c, 0, 0);
+ break;
default:
r = -EINVAL;
}
@@ -1056,6 +1077,18 @@ static int qemu_rbd_co_flush(BlockDriverState *bs)
}
#endif
+#ifdef LIBRBD_SUPPORTS_COMPARE_AND_WRITE
+static BlockAIOCB *qemu_rbd_aio_compare_and_write(BlockDriverState *bs,
+ uint64_t offset, uint64_t bytes,
+ QEMUIOVector *qiov, int flags,
+ BlockCompletionFunc *cb,
+ void *opaque)
+{
+ return rbd_start_aio(bs, offset, qiov, bytes, cb, opaque,
+ RBD_AIO_COMPARE_AND_WRITE);
+}
+#endif
+
static int qemu_rbd_getinfo(BlockDriverState *bs, BlockDriverInfo *bdi)
{
BDRVRBDState *s = bs->opaque;
@@ -1309,6 +1342,10 @@ static BlockDriver bdrv_rbd = {
.bdrv_aio_pdiscard = qemu_rbd_aio_pdiscard,
#endif
+#ifdef LIBRBD_SUPPORTS_COMPARE_AND_WRITE
+ .bdrv_aio_compare_and_write = qemu_rbd_aio_compare_and_write,
+#endif
+
.bdrv_snapshot_create = qemu_rbd_snap_create,
.bdrv_snapshot_delete = qemu_rbd_snap_remove,
.bdrv_snapshot_list = qemu_rbd_snap_list,
--
1.8.3.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/4] hw/scsi: add SCSI COMPARE_AND_WRITE support
2019-10-25 9:35 [PATCH 0/4] SCSI COMPARE_AND_WRITE support Yaowei Bai
2019-10-25 9:35 ` [PATCH 1/4] block: add " Yaowei Bai
2019-10-25 9:36 ` [PATCH 2/4] block/rbd: implement bdrv_aio_compare_and_write interface Yaowei Bai
@ 2019-10-25 9:36 ` Yaowei Bai
2019-10-25 9:53 ` Yaowei Bai
2019-10-25 9:36 ` [PATCH 4/4] scsi-disk: add FUA support for COMPARE_AND_WRITE Yaowei Bai
2019-10-25 23:38 ` [PATCH 0/4] SCSI COMPARE_AND_WRITE support no-reply
4 siblings, 1 reply; 7+ messages in thread
From: Yaowei Bai @ 2019-10-25 9:36 UTC (permalink / raw)
To: pbonzini, fam, dillaman, kwolf, mreitz
Cc: baiyaowei, yangjun, qemu-devel, qemu-block
This patch emulates COMPARE_AND_WRITE command with the
BDRV_REQ_COMPARE_AND_WRITE flag introduced by last patch. It matches
the SBC-4 standard except the FUA bit support, it'll be finished in
the next patch.
Note that cmd->xfer is set 2 * the number got by scsi_data_cdb_xfer
so we could touch the least code.
Signed-off-by: Yaowei Bai <baiyaowei@cmss.chinamobile.com>
---
hw/scsi/emulation.c | 1 +
hw/scsi/scsi-bus.c | 4 +++
hw/scsi/scsi-disk.c | 88 +++++++++++++++++++++++++++++++++++++++++++++
hw/scsi/trace-events | 1 +
include/hw/scsi/emulation.h | 3 ++
include/scsi/utils.h | 2 ++
include/tcmu/tcmu.h | 14 ++++++++
scsi/utils.c | 5 +++
8 files changed, 118 insertions(+)
create mode 100644 include/tcmu/tcmu.h
diff --git a/hw/scsi/emulation.c b/hw/scsi/emulation.c
index 06d62f3..1f53c4a 100644
--- a/hw/scsi/emulation.c
+++ b/hw/scsi/emulation.c
@@ -9,6 +9,7 @@ int scsi_emulate_block_limits(uint8_t *outbuf, const SCSIBlockLimits *bl)
memset(outbuf, 0, 0x3c);
outbuf[0] = bl->wsnz; /* wsnz */
+ outbuf[1] = MAX_COMPARE_AND_WRITE_LENGTH;
if (bl->max_io_sectors) {
/* optimal transfer length granularity. This field and the optimal
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index bccb7cc..15aab8a 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -987,6 +987,9 @@ static int scsi_req_xfer(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
case WRITE_VERIFY_16:
cmd->xfer *= dev->blocksize;
break;
+ case COMPARE_AND_WRITE:
+ cmd->xfer *= 2 * dev->blocksize;
+ break;
case READ_6:
case READ_REVERSE:
/* length 0 means 256 blocks */
@@ -1206,6 +1209,7 @@ static void scsi_cmd_xfer_mode(SCSICommand *cmd)
case PERSISTENT_RESERVE_OUT:
case MAINTENANCE_OUT:
case SET_WINDOW:
+ case COMPARE_AND_WRITE:
case SCAN:
/* SCAN conflicts with START_STOP. START_STOP has cmd->xfer set to 0 for
* non-scanner devices, so we only get here for SCAN and not for START_STOP.
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 68b1675..4bff862 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -477,6 +477,9 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed)
case ENOSPC:
scsi_check_condition(r, SENSE_CODE(SPACE_ALLOC_FAILED));
break;
+ case EILSEQ:
+ scsi_check_condition(r, SENSE_CODE(MISCOMPARE_DURING_VERIFY));
+ break;
default:
scsi_check_condition(r, SENSE_CODE(IO_ERROR));
break;
@@ -1824,6 +1827,84 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf)
scsi_write_same_complete, data);
}
+typedef struct CompareAndWriteCBData {
+ SCSIDiskReq *r;
+ int64_t sector;
+ int nb_sectors;
+ QEMUIOVector qiov;
+ struct iovec iov;
+} CompareAndWriteCBData;
+
+static void scsi_compare_and_write_complete(void *opaque, int ret)
+{
+ CompareAndWriteCBData *data = opaque;
+ SCSIDiskReq *r = data->r;
+ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
+
+ assert(r->req.aiocb != NULL);
+ r->req.aiocb = NULL;
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
+ if (scsi_disk_req_check_error(r, ret, true)) {
+ goto done;
+ }
+
+ block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
+ scsi_req_complete(&r->req, GOOD);
+
+done:
+ scsi_req_unref(&r->req);
+ qemu_vfree(data->iov.iov_base);
+ g_free(data);
+ aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
+}
+
+static void scsi_disk_emulate_compare_and_write(SCSIDiskReq *r, uint8_t *inbuf)
+{
+ SCSIRequest *req = &r->req;
+ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
+ uint32_t nb_sectors = scsi_data_cdb_xfer(r->req.cmd.buf);
+ CompareAndWriteCBData *data;
+ uint8_t *buf;
+ int i;
+
+ if (nb_sectors > MAX_COMPARE_AND_WRITE_LENGTH) {
+ scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
+ return;
+ }
+
+ if (blk_is_read_only(s->qdev.conf.blk)) {
+ scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED));
+ return;
+ }
+
+ if (r->req.cmd.lba > s->qdev.max_lba ||
+ !check_lba_range(s, r->req.cmd.lba, nb_sectors)) {
+ scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
+ return;
+ }
+
+ data = g_new0(CompareAndWriteCBData, 1);
+ data->r = r;
+ data->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
+ data->nb_sectors = r->req.cmd.xfer * (s->qdev.blocksize / 512);
+ data->iov.iov_len = data->nb_sectors;
+ data->iov.iov_base = buf = blk_blockalign(s->qdev.conf.blk,
+ data->iov.iov_len);
+ qemu_iovec_init_external(&data->qiov, &data->iov, 1);
+
+ for (i = 0; i < data->iov.iov_len; i += s->qdev.blocksize) {
+ memcpy(&buf[i], &inbuf[i], s->qdev.blocksize);
+ }
+
+ scsi_req_ref(&r->req);
+ block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct,
+ data->iov.iov_len, BLOCK_ACCT_WRITE);
+ r->req.aiocb = blk_aio_pwritev(s->qdev.conf.blk,
+ data->sector << BDRV_SECTOR_BITS,
+ &data->qiov, BDRV_REQ_COMPARE_AND_WRITE,
+ scsi_compare_and_write_complete, data);
+}
+
static void scsi_disk_emulate_write_data(SCSIRequest *req)
{
SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
@@ -1860,6 +1941,9 @@ static void scsi_disk_emulate_write_data(SCSIRequest *req)
scsi_disk_emulate_write_same(r, r->iov.iov_base);
break;
+ case COMPARE_AND_WRITE:
+ scsi_disk_emulate_compare_and_write(r, r->iov.iov_base);
+ break;
default:
abort();
}
@@ -2114,6 +2198,9 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
trace_scsi_disk_emulate_command_WRITE_SAME(
req->cmd.buf[0] == WRITE_SAME_10 ? 10 : 16, r->req.cmd.xfer);
break;
+ case COMPARE_AND_WRITE:
+ trace_scsi_disk_emulate_command_COMPARE_AND_WRITE(r->req.cmd.xfer);
+ break;
default:
trace_scsi_disk_emulate_command_UNKNOWN(buf[0],
scsi_command_name(buf[0]));
@@ -2531,6 +2618,7 @@ static const SCSIReqOps *const scsi_disk_reqops_dispatch[256] = {
[VERIFY_10] = &scsi_disk_emulate_reqops,
[VERIFY_12] = &scsi_disk_emulate_reqops,
[VERIFY_16] = &scsi_disk_emulate_reqops,
+ [COMPARE_AND_WRITE] = &scsi_disk_emulate_reqops,
[READ_6] = &scsi_disk_dma_reqops,
[READ_10] = &scsi_disk_dma_reqops,
diff --git a/hw/scsi/trace-events b/hw/scsi/trace-events
index b082005..0783e58 100644
--- a/hw/scsi/trace-events
+++ b/hw/scsi/trace-events
@@ -317,6 +317,7 @@ scsi_disk_emulate_command_MODE_SELECT_10(size_t xfer) "Mode Select(10) (len %zd)
scsi_disk_emulate_command_UNMAP(size_t xfer) "Unmap (len %zd)"
scsi_disk_emulate_command_VERIFY(int bytchk) "Verify (bytchk %d)"
scsi_disk_emulate_command_WRITE_SAME(int cmd, size_t xfer) "WRITE SAME %d (len %zd)"
+scsi_disk_emulate_command_COMPARE_AND_WRITE(size_t xfer) "COMPARE AND WRITE (len %zd)"
scsi_disk_emulate_command_UNKNOWN(int cmd, const char *name) "Unknown SCSI command (0x%2.2x=%s)"
scsi_disk_dma_command_READ(uint64_t lba, uint32_t len) "Read (sector %" PRId64 ", count %u)"
scsi_disk_dma_command_WRITE(const char *cmd, uint64_t lba, int len) "Write %s(sector %" PRId64 ", count %u)"
diff --git a/include/hw/scsi/emulation.h b/include/hw/scsi/emulation.h
index 9521704..2148316 100644
--- a/include/hw/scsi/emulation.h
+++ b/include/hw/scsi/emulation.h
@@ -1,6 +1,9 @@
#ifndef HW_SCSI_EMULATION_H
#define HW_SCSI_EMULATION_H
+/* maximum compare and write length : 64kb */
+#define MAX_COMPARE_AND_WRITE_LENGTH 128
+
typedef struct SCSIBlockLimits {
bool wsnz;
uint16_t min_io_size;
diff --git a/include/scsi/utils.h b/include/scsi/utils.h
index fbc5588..35f554e 100644
--- a/include/scsi/utils.h
+++ b/include/scsi/utils.h
@@ -101,6 +101,8 @@ extern const struct SCSISense sense_code_DEVICE_INTERNAL_RESET;
extern const struct SCSISense sense_code_WRITE_PROTECTED;
/* Data Protection, Space Allocation Failed Write Protect */
extern const struct SCSISense sense_code_SPACE_ALLOC_FAILED;
+/* Miscompare, Miscompare During Verify Operation */
+extern const struct SCSISense sense_code_MISCOMPARE_DURING_VERIFY;
#define SENSE_CODE(x) sense_code_ ## x
diff --git a/include/tcmu/tcmu.h b/include/tcmu/tcmu.h
new file mode 100644
index 0000000..656a545
--- /dev/null
+++ b/include/tcmu/tcmu.h
@@ -0,0 +1,14 @@
+#ifndef QEMU_TCMU_H
+#define QEMU_TCMU_H
+
+#include "qemu-common.h"
+
+typedef struct TCMUExport TCMUExport;
+extern QemuOptsList qemu_tcmu_export_opts;
+
+void qemu_tcmu_stop(void);
+void qemu_tcmu_start(const char *subtype, Error **errp);
+TCMUExport *tcmu_export_new(BlockBackend *blk, bool writable, Error **errp);
+int export_init_func(void *opaque, QemuOpts *all_opts, Error **errp);
+
+#endif
diff --git a/scsi/utils.c b/scsi/utils.c
index c50e81f..c142a53 100644
--- a/scsi/utils.c
+++ b/scsi/utils.c
@@ -311,6 +311,11 @@ const struct SCSISense sense_code_SPACE_ALLOC_FAILED = {
.key = DATA_PROTECT, .asc = 0x27, .ascq = 0x07
};
+/* Miscompare, Miscompare During Verify Operation */
+const struct SCSISense sense_code_MISCOMPARE_DURING_VERIFY = {
+ .key = MISCOMPARE, .asc = 0x1d, .ascq = 0x00
+};
+
/*
* scsi_convert_sense
*
--
1.8.3.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 3/4] hw/scsi: add SCSI COMPARE_AND_WRITE support
2019-10-25 9:36 ` [PATCH 3/4] hw/scsi: add SCSI COMPARE_AND_WRITE support Yaowei Bai
@ 2019-10-25 9:53 ` Yaowei Bai
0 siblings, 0 replies; 7+ messages in thread
From: Yaowei Bai @ 2019-10-25 9:53 UTC (permalink / raw)
To: pbonzini, fam, dillaman, kwolf, mreitz
Cc: baiyaowei, yangjun, qemu-devel, qemu-block
On Fri, Oct 25, 2019 at 05:36:01PM +0800, Yaowei Bai wrote:
>
> diff --git a/include/tcmu/tcmu.h b/include/tcmu/tcmu.h
> new file mode 100644
> index 0000000..656a545
> --- /dev/null
> +++ b/include/tcmu/tcmu.h
> @@ -0,0 +1,14 @@
> +#ifndef QEMU_TCMU_H
> +#define QEMU_TCMU_H
> +
> +#include "qemu-common.h"
> +
> +typedef struct TCMUExport TCMUExport;
> +extern QemuOptsList qemu_tcmu_export_opts;
> +
> +void qemu_tcmu_stop(void);
> +void qemu_tcmu_start(const char *subtype, Error **errp);
> +TCMUExport *tcmu_export_new(BlockBackend *blk, bool writable, Error **errp);
> +int export_init_func(void *opaque, QemuOpts *all_opts, Error **errp);
> +
> +#endif
Please ignore this odd part.
> --
> 1.8.3.1
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 4/4] scsi-disk: add FUA support for COMPARE_AND_WRITE
2019-10-25 9:35 [PATCH 0/4] SCSI COMPARE_AND_WRITE support Yaowei Bai
` (2 preceding siblings ...)
2019-10-25 9:36 ` [PATCH 3/4] hw/scsi: add SCSI COMPARE_AND_WRITE support Yaowei Bai
@ 2019-10-25 9:36 ` Yaowei Bai
2019-10-25 23:38 ` [PATCH 0/4] SCSI COMPARE_AND_WRITE support no-reply
4 siblings, 0 replies; 7+ messages in thread
From: Yaowei Bai @ 2019-10-25 9:36 UTC (permalink / raw)
To: pbonzini, fam, dillaman, kwolf, mreitz
Cc: baiyaowei, yangjun, qemu-devel, qemu-block
It is implemented in the blk_aio_pwritev's callback function in a way
similar to its emulation in scsi_write_do_fua function
Signed-off-by: Yaowei Bai <baiyaowei@cmss.chinamobile.com>
---
hw/scsi/scsi-disk.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 4bff862..ef9c257 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -228,6 +228,7 @@ static bool scsi_is_cmd_fua(SCSICommand *cmd)
case WRITE_10:
case WRITE_12:
case WRITE_16:
+ case COMPARE_AND_WRITE:
return (cmd->buf[1] & 8) != 0;
case VERIFY_10:
@@ -1849,10 +1850,17 @@ static void scsi_compare_and_write_complete(void *opaque, int ret)
}
block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
+ if (r->need_fua_emulation) {
+ block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, 0,
+ BLOCK_ACCT_FLUSH);
+ r->req.aiocb = blk_aio_flush(s->qdev.conf.blk, scsi_aio_complete, r);
+ goto free;
+ }
scsi_req_complete(&r->req, GOOD);
done:
scsi_req_unref(&r->req);
+free:
qemu_vfree(data->iov.iov_base);
g_free(data);
aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
@@ -1953,6 +1961,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
{
SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
+ SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s));
uint64_t nb_sectors;
uint8_t *outbuf;
int buflen;
@@ -2208,6 +2217,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
return 0;
}
assert(!r->req.aiocb);
+ r->need_fua_emulation = sdc->need_fua_emulation(&r->req.cmd);
r->iov.iov_len = MIN(r->buflen, req->cmd.xfer);
if (r->iov.iov_len == 0) {
scsi_req_complete(&r->req, GOOD);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 0/4] SCSI COMPARE_AND_WRITE support
2019-10-25 9:35 [PATCH 0/4] SCSI COMPARE_AND_WRITE support Yaowei Bai
` (3 preceding siblings ...)
2019-10-25 9:36 ` [PATCH 4/4] scsi-disk: add FUA support for COMPARE_AND_WRITE Yaowei Bai
@ 2019-10-25 23:38 ` no-reply
4 siblings, 0 replies; 7+ messages in thread
From: no-reply @ 2019-10-25 23:38 UTC (permalink / raw)
To: baiyaowei
Cc: fam, kwolf, qemu-block, qemu-devel, mreitz, yangjun, baiyaowei,
pbonzini, dillaman
Patchew URL: https://patchew.org/QEMU/1571996163-27688-1-git-send-email-baiyaowei@cmss.chinamobile.com/
Hi,
This series seems to have some coding style problems. See output below for
more information:
Subject: [PATCH 0/4] SCSI COMPARE_AND_WRITE support
Type: series
Message-id: 1571996163-27688-1-git-send-email-baiyaowei@cmss.chinamobile.com
=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===
Switched to a new branch 'test'
9dec556 scsi-disk: add FUA support for COMPARE_AND_WRITE
8ee0b25 hw/scsi: add SCSI COMPARE_AND_WRITE support
6c2bd51 block/rbd: implement bdrv_aio_compare_and_write interface
f2cafca block: add SCSI COMPARE_AND_WRITE support
=== OUTPUT BEGIN ===
1/4 Checking commit f2cafca98400 (block: add SCSI COMPARE_AND_WRITE support)
2/4 Checking commit 6c2bd51ede14 (block/rbd: implement bdrv_aio_compare_and_write interface)
ERROR: braces {} are necessary for all arms of this statement
#59: FILE: block/rbd.c:808:
+ if (LIBRBD_HAVE_COMPARE_AND_WRITE)
[...]
ERROR: line over 90 characters
#87: FILE: block/rbd.c:1015:
+ r = rbd_aio_compare_and_write(s->image, off, size/2, rcb->buf, (rcb->buf + size/2), c, 0, 0);
ERROR: spaces required around that '/' (ctx:VxV)
#87: FILE: block/rbd.c:1015:
+ r = rbd_aio_compare_and_write(s->image, off, size/2, rcb->buf, (rcb->buf + size/2), c, 0, 0);
^
ERROR: spaces required around that '/' (ctx:VxV)
#87: FILE: block/rbd.c:1015:
+ r = rbd_aio_compare_and_write(s->image, off, size/2, rcb->buf, (rcb->buf + size/2), c, 0, 0);
^
WARNING: line over 80 characters
#98: FILE: block/rbd.c:1082:
+ uint64_t offset, uint64_t bytes,
total: 4 errors, 1 warnings, 90 lines checked
Patch 2/4 has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
3/4 Checking commit 8ee0b25d3d83 (hw/scsi: add SCSI COMPARE_AND_WRITE support)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#219:
new file mode 100644
total: 0 errors, 1 warnings, 190 lines checked
Patch 3/4 has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
4/4 Checking commit 9dec556b752c (scsi-disk: add FUA support for COMPARE_AND_WRITE)
=== OUTPUT END ===
Test command exited with code: 1
The full log is available at
http://patchew.org/logs/1571996163-27688-1-git-send-email-baiyaowei@cmss.chinamobile.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com
^ permalink raw reply [flat|nested] 7+ messages in thread