mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-09 02:24:58 -06:00
scsi-disk: Add native FUA write support
Simply propagate the FUA flag on write requests to the driver. The block layer will emulate it if necessary. Signed-off-by: Alberto Faria <afaria@redhat.com> Message-ID: <20250502121115.3613717-2-afaria@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
f0737158b4
commit
e460991883
1 changed files with 15 additions and 38 deletions
|
@ -74,7 +74,7 @@ struct SCSIDiskClass {
|
|||
*/
|
||||
DMAIOFunc *dma_readv;
|
||||
DMAIOFunc *dma_writev;
|
||||
bool (*need_fua_emulation)(SCSICommand *cmd);
|
||||
bool (*need_fua)(SCSICommand *cmd);
|
||||
void (*update_sense)(SCSIRequest *r);
|
||||
};
|
||||
|
||||
|
@ -85,7 +85,7 @@ typedef struct SCSIDiskReq {
|
|||
uint32_t sector_count;
|
||||
uint32_t buflen;
|
||||
bool started;
|
||||
bool need_fua_emulation;
|
||||
bool need_fua;
|
||||
struct iovec iov;
|
||||
QEMUIOVector qiov;
|
||||
BlockAcctCookie acct;
|
||||
|
@ -389,24 +389,6 @@ static bool scsi_is_cmd_fua(SCSICommand *cmd)
|
|||
}
|
||||
}
|
||||
|
||||
static void scsi_write_do_fua(SCSIDiskReq *r)
|
||||
{
|
||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
|
||||
|
||||
assert(r->req.aiocb == NULL);
|
||||
assert(!r->req.io_canceled);
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
scsi_req_complete(&r->req, GOOD);
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
|
||||
static void scsi_dma_complete_noio(SCSIDiskReq *r, int ret)
|
||||
{
|
||||
assert(r->req.aiocb == NULL);
|
||||
|
@ -416,12 +398,7 @@ static void scsi_dma_complete_noio(SCSIDiskReq *r, int ret)
|
|||
|
||||
r->sector += r->sector_count;
|
||||
r->sector_count = 0;
|
||||
if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
|
||||
scsi_write_do_fua(r);
|
||||
return;
|
||||
} else {
|
||||
scsi_req_complete(&r->req, GOOD);
|
||||
}
|
||||
|
||||
done:
|
||||
scsi_req_unref(&r->req);
|
||||
|
@ -564,7 +541,7 @@ static void scsi_read_data(SCSIRequest *req)
|
|||
|
||||
first = !r->started;
|
||||
r->started = true;
|
||||
if (first && r->need_fua_emulation) {
|
||||
if (first && r->need_fua) {
|
||||
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_do_read_cb, r);
|
||||
|
@ -589,8 +566,7 @@ static void scsi_write_complete_noio(SCSIDiskReq *r, int ret)
|
|||
r->sector += n;
|
||||
r->sector_count -= n;
|
||||
if (r->sector_count == 0) {
|
||||
scsi_write_do_fua(r);
|
||||
return;
|
||||
scsi_req_complete(&r->req, GOOD);
|
||||
} else {
|
||||
scsi_init_iovec(r, SCSI_DMA_BUF_SIZE);
|
||||
trace_scsi_disk_write_complete_noio(r->req.tag, r->qiov.size);
|
||||
|
@ -623,6 +599,7 @@ static void scsi_write_data(SCSIRequest *req)
|
|||
SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
|
||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
|
||||
SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s));
|
||||
BlockCompletionFunc *cb;
|
||||
|
||||
/* No data transfer may already be in progress */
|
||||
assert(r->req.aiocb == NULL);
|
||||
|
@ -648,11 +625,10 @@ static void scsi_write_data(SCSIRequest *req)
|
|||
|
||||
if (r->req.cmd.buf[0] == VERIFY_10 || r->req.cmd.buf[0] == VERIFY_12 ||
|
||||
r->req.cmd.buf[0] == VERIFY_16) {
|
||||
if (r->req.sg) {
|
||||
scsi_dma_complete_noio(r, 0);
|
||||
} else {
|
||||
scsi_write_complete_noio(r, 0);
|
||||
}
|
||||
block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, 0,
|
||||
BLOCK_ACCT_FLUSH);
|
||||
cb = r->req.sg ? scsi_dma_complete : scsi_write_complete;
|
||||
r->req.aiocb = blk_aio_flush(s->qdev.conf.blk, cb, r);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2391,7 +2367,7 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf)
|
|||
scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
|
||||
return 0;
|
||||
}
|
||||
r->need_fua_emulation = sdc->need_fua_emulation(&r->req.cmd);
|
||||
r->need_fua = sdc->need_fua(&r->req.cmd);
|
||||
if (r->sector_count == 0) {
|
||||
scsi_req_complete(&r->req, GOOD);
|
||||
}
|
||||
|
@ -3137,7 +3113,8 @@ BlockAIOCB *scsi_dma_writev(int64_t offset, QEMUIOVector *iov,
|
|||
{
|
||||
SCSIDiskReq *r = opaque;
|
||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
|
||||
return blk_aio_pwritev(s->qdev.conf.blk, offset, iov, 0, cb, cb_opaque);
|
||||
int flags = r->need_fua ? BDRV_REQ_FUA : 0;
|
||||
return blk_aio_pwritev(s->qdev.conf.blk, offset, iov, flags, cb, cb_opaque);
|
||||
}
|
||||
|
||||
static char *scsi_property_get_loadparm(Object *obj, Error **errp)
|
||||
|
@ -3186,7 +3163,7 @@ static void scsi_disk_base_class_initfn(ObjectClass *klass, const void *data)
|
|||
device_class_set_legacy_reset(dc, scsi_disk_reset);
|
||||
sdc->dma_readv = scsi_dma_readv;
|
||||
sdc->dma_writev = scsi_dma_writev;
|
||||
sdc->need_fua_emulation = scsi_is_cmd_fua;
|
||||
sdc->need_fua = scsi_is_cmd_fua;
|
||||
}
|
||||
|
||||
static const TypeInfo scsi_disk_base_info = {
|
||||
|
@ -3338,7 +3315,7 @@ static void scsi_block_class_initfn(ObjectClass *klass, const void *data)
|
|||
sdc->dma_readv = scsi_block_dma_readv;
|
||||
sdc->dma_writev = scsi_block_dma_writev;
|
||||
sdc->update_sense = scsi_block_update_sense;
|
||||
sdc->need_fua_emulation = scsi_block_no_fua;
|
||||
sdc->need_fua = scsi_block_no_fua;
|
||||
dc->desc = "SCSI block device passthrough";
|
||||
device_class_set_props(dc, scsi_block_properties);
|
||||
dc->vmsd = &vmstate_scsi_disk_state;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue