Merge remote-tracking branch 'bonzini/scsi-next' into staging

# By Paolo Bonzini (4) and Peter Lieven (1)
# Via Paolo Bonzini
* bonzini/scsi-next:
  help: add id suboption to -iscsi
  scsi-disk: fix WRITE SAME with large non-zero payload
  block/iscsi: introduce bdrv_co_{readv, writev, flush_to_disk}
  scsi-disk: fix VERIFY emulation
  scsi-bus: fix transfer length and direction for VERIFY command

Message-id: 1386594157-17535-1-git-send-email-pbonzini@redhat.com
Signed-off-by: Anthony Liguori <aliguori@amazon.com>
This commit is contained in:
Anthony Liguori 2013-12-13 11:10:02 -08:00
commit bf6e3cc4fa
5 changed files with 151 additions and 317 deletions

View file

@ -239,44 +239,6 @@ iscsi_process_write(void *arg)
iscsi_set_events(iscsilun); iscsi_set_events(iscsilun);
} }
static int
iscsi_aio_writev_acb(IscsiAIOCB *acb);
static void
iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
void *command_data, void *opaque)
{
IscsiAIOCB *acb = opaque;
trace_iscsi_aio_write16_cb(iscsi, status, acb, acb->canceled);
g_free(acb->buf);
acb->buf = NULL;
if (acb->canceled != 0) {
return;
}
acb->status = 0;
if (status != 0) {
if (status == SCSI_STATUS_CHECK_CONDITION
&& acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
&& acb->retries-- > 0) {
scsi_free_scsi_task(acb->task);
acb->task = NULL;
if (iscsi_aio_writev_acb(acb) == 0) {
iscsi_set_events(acb->iscsilun);
return;
}
}
error_report("Failed to write16 data to iSCSI lun. %s",
iscsi_get_error(iscsi));
acb->status = -EIO;
}
iscsi_schedule_bh(acb);
}
static int64_t sector_lun2qemu(int64_t sector, IscsiLun *iscsilun) static int64_t sector_lun2qemu(int64_t sector, IscsiLun *iscsilun)
{ {
return sector * iscsilun->block_size / BDRV_SECTOR_SIZE; return sector * iscsilun->block_size / BDRV_SECTOR_SIZE;
@ -301,324 +263,172 @@ static bool is_request_lun_aligned(int64_t sector_num, int nb_sectors,
return 1; return 1;
} }
static int static int coroutine_fn iscsi_co_writev(BlockDriverState *bs,
iscsi_aio_writev_acb(IscsiAIOCB *acb) int64_t sector_num, int nb_sectors,
QEMUIOVector *iov)
{ {
struct iscsi_context *iscsi = acb->iscsilun->iscsi; IscsiLun *iscsilun = bs->opaque;
size_t size; struct IscsiTask iTask;
uint32_t num_sectors;
uint64_t lba; uint64_t lba;
uint32_t num_sectors;
uint8_t *data = NULL;
uint8_t *buf = NULL;
if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
return -EINVAL;
}
lba = sector_qemu2lun(sector_num, iscsilun);
num_sectors = sector_qemu2lun(nb_sectors, iscsilun);
#if !defined(LIBISCSI_FEATURE_IOVECTOR) #if !defined(LIBISCSI_FEATURE_IOVECTOR)
struct iscsi_data data;
#endif
int ret;
acb->canceled = 0;
acb->bh = NULL;
acb->status = -EINPROGRESS;
acb->buf = NULL;
/* this will allow us to get rid of 'buf' completely */
size = acb->nb_sectors * BDRV_SECTOR_SIZE;
#if !defined(LIBISCSI_FEATURE_IOVECTOR)
data.size = MIN(size, acb->qiov->size);
/* if the iovec only contains one buffer we can pass it directly */ /* if the iovec only contains one buffer we can pass it directly */
if (acb->qiov->niov == 1) { if (iov->niov == 1) {
data.data = acb->qiov->iov[0].iov_base; data = iov->iov[0].iov_base;
} else { } else {
acb->buf = g_malloc(data.size); size_t size = MIN(nb_sectors * BDRV_SECTOR_SIZE, iov->size);
qemu_iovec_to_buf(acb->qiov, 0, acb->buf, data.size); buf = g_malloc(size);
data.data = acb->buf; qemu_iovec_to_buf(iov, 0, buf, size);
data = buf;
} }
#endif #endif
iscsi_co_init_iscsitask(iscsilun, &iTask);
acb->task = malloc(sizeof(struct scsi_task)); retry:
if (acb->task == NULL) { iTask.task = iscsi_write16_task(iscsilun->iscsi, iscsilun->lun, lba,
error_report("iSCSI: Failed to allocate task for scsi WRITE16 " data, num_sectors * iscsilun->block_size,
"command. %s", iscsi_get_error(iscsi)); iscsilun->block_size, 0, 0, 0, 0, 0,
return -1; iscsi_co_generic_cb, &iTask);
if (iTask.task == NULL) {
g_free(buf);
return -EIO;
} }
memset(acb->task, 0, sizeof(struct scsi_task));
acb->task->xfer_dir = SCSI_XFER_WRITE;
acb->task->cdb_size = 16;
acb->task->cdb[0] = 0x8a;
lba = sector_qemu2lun(acb->sector_num, acb->iscsilun);
*(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32);
*(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff);
num_sectors = sector_qemu2lun(acb->nb_sectors, acb->iscsilun);
*(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
acb->task->expxferlen = size;
#if defined(LIBISCSI_FEATURE_IOVECTOR) #if defined(LIBISCSI_FEATURE_IOVECTOR)
ret = iscsi_scsi_command_async(iscsi, acb->iscsilun->lun, acb->task, scsi_task_set_iov_out(iTask.task, (struct scsi_iovec *) iov->iov,
iscsi_aio_write16_cb, iov->niov);
NULL,
acb);
#else
ret = iscsi_scsi_command_async(iscsi, acb->iscsilun->lun, acb->task,
iscsi_aio_write16_cb,
&data,
acb);
#endif #endif
if (ret != 0) { while (!iTask.complete) {
scsi_free_scsi_task(acb->task); iscsi_set_events(iscsilun);
g_free(acb->buf); qemu_coroutine_yield();
return -1;
} }
#if defined(LIBISCSI_FEATURE_IOVECTOR) if (iTask.task != NULL) {
scsi_task_set_iov_out(acb->task, (struct scsi_iovec*) acb->qiov->iov, acb->qiov->niov); scsi_free_scsi_task(iTask.task);
#endif iTask.task = NULL;
}
if (iTask.do_retry) {
goto retry;
}
g_free(buf);
if (iTask.status != SCSI_STATUS_GOOD) {
return -EIO;
}
return 0; return 0;
} }
static BlockDriverAIOCB * static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num, int64_t sector_num, int nb_sectors,
QEMUIOVector *qiov, int nb_sectors, QEMUIOVector *iov)
BlockDriverCompletionFunc *cb,
void *opaque)
{ {
IscsiLun *iscsilun = bs->opaque; IscsiLun *iscsilun = bs->opaque;
IscsiAIOCB *acb; struct IscsiTask iTask;
if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
return NULL;
}
acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
trace_iscsi_aio_writev(iscsilun->iscsi, sector_num, nb_sectors, opaque, acb);
acb->iscsilun = iscsilun;
acb->qiov = qiov;
acb->nb_sectors = nb_sectors;
acb->sector_num = sector_num;
acb->retries = ISCSI_CMD_RETRIES;
if (iscsi_aio_writev_acb(acb) != 0) {
qemu_aio_release(acb);
return NULL;
}
iscsi_set_events(iscsilun);
return &acb->common;
}
static int
iscsi_aio_readv_acb(IscsiAIOCB *acb);
static void
iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
void *command_data, void *opaque)
{
IscsiAIOCB *acb = opaque;
trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled);
if (acb->canceled != 0) {
return;
}
acb->status = 0;
if (status != 0) {
if (status == SCSI_STATUS_CHECK_CONDITION
&& acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
&& acb->retries-- > 0) {
scsi_free_scsi_task(acb->task);
acb->task = NULL;
if (iscsi_aio_readv_acb(acb) == 0) {
iscsi_set_events(acb->iscsilun);
return;
}
}
error_report("Failed to read16 data from iSCSI lun. %s",
iscsi_get_error(iscsi));
acb->status = -EIO;
}
iscsi_schedule_bh(acb);
}
static int
iscsi_aio_readv_acb(IscsiAIOCB *acb)
{
struct iscsi_context *iscsi = acb->iscsilun->iscsi;
size_t size;
uint64_t lba; uint64_t lba;
uint32_t num_sectors; uint32_t num_sectors;
int ret;
#if !defined(LIBISCSI_FEATURE_IOVECTOR) #if !defined(LIBISCSI_FEATURE_IOVECTOR)
int i; int i;
#endif #endif
acb->canceled = 0; if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
acb->bh = NULL; return -EINVAL;
acb->status = -EINPROGRESS;
acb->buf = NULL;
size = acb->nb_sectors * BDRV_SECTOR_SIZE;
acb->task = malloc(sizeof(struct scsi_task));
if (acb->task == NULL) {
error_report("iSCSI: Failed to allocate task for scsi READ16 "
"command. %s", iscsi_get_error(iscsi));
return -1;
} }
memset(acb->task, 0, sizeof(struct scsi_task));
acb->task->xfer_dir = SCSI_XFER_READ; lba = sector_qemu2lun(sector_num, iscsilun);
acb->task->expxferlen = size; num_sectors = sector_qemu2lun(nb_sectors, iscsilun);
lba = sector_qemu2lun(acb->sector_num, acb->iscsilun);
num_sectors = sector_qemu2lun(acb->nb_sectors, acb->iscsilun);
switch (acb->iscsilun->type) { iscsi_co_init_iscsitask(iscsilun, &iTask);
retry:
switch (iscsilun->type) {
case TYPE_DISK: case TYPE_DISK:
acb->task->cdb_size = 16; iTask.task = iscsi_read16_task(iscsilun->iscsi, iscsilun->lun, lba,
acb->task->cdb[0] = 0x88; num_sectors * iscsilun->block_size,
*(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32); iscsilun->block_size, 0, 0, 0, 0, 0,
*(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff); iscsi_co_generic_cb, &iTask);
*(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
break; break;
default: default:
acb->task->cdb_size = 10; iTask.task = iscsi_read10_task(iscsilun->iscsi, iscsilun->lun, lba,
acb->task->cdb[0] = 0x28; num_sectors * iscsilun->block_size,
*(uint32_t *)&acb->task->cdb[2] = htonl(lba); iscsilun->block_size, 0, 0, 0, 0, 0,
*(uint16_t *)&acb->task->cdb[7] = htons(num_sectors); iscsi_co_generic_cb, &iTask);
break; break;
} }
if (iTask.task == NULL) {
ret = iscsi_scsi_command_async(iscsi, acb->iscsilun->lun, acb->task, return -EIO;
iscsi_aio_read16_cb,
NULL,
acb);
if (ret != 0) {
scsi_free_scsi_task(acb->task);
return -1;
} }
#if defined(LIBISCSI_FEATURE_IOVECTOR) #if defined(LIBISCSI_FEATURE_IOVECTOR)
scsi_task_set_iov_in(acb->task, (struct scsi_iovec*) acb->qiov->iov, acb->qiov->niov); scsi_task_set_iov_in(iTask.task, (struct scsi_iovec *) iov->iov, iov->niov);
#else #else
for (i = 0; i < acb->qiov->niov; i++) { for (i = 0; i < iov->niov; i++) {
scsi_task_add_data_in_buffer(acb->task, scsi_task_add_data_in_buffer(iTask.task,
acb->qiov->iov[i].iov_len, iov->iov[i].iov_len,
acb->qiov->iov[i].iov_base); iov->iov[i].iov_base);
} }
#endif #endif
return 0;
}
static BlockDriverAIOCB * while (!iTask.complete) {
iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num, iscsi_set_events(iscsilun);
QEMUIOVector *qiov, int nb_sectors, qemu_coroutine_yield();
BlockDriverCompletionFunc *cb,
void *opaque)
{
IscsiLun *iscsilun = bs->opaque;
IscsiAIOCB *acb;
if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
return NULL;
} }
acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque); if (iTask.task != NULL) {
trace_iscsi_aio_readv(iscsilun->iscsi, sector_num, nb_sectors, opaque, acb); scsi_free_scsi_task(iTask.task);
iTask.task = NULL;
acb->nb_sectors = nb_sectors;
acb->sector_num = sector_num;
acb->iscsilun = iscsilun;
acb->qiov = qiov;
acb->retries = ISCSI_CMD_RETRIES;
if (iscsi_aio_readv_acb(acb) != 0) {
qemu_aio_release(acb);
return NULL;
} }
iscsi_set_events(iscsilun); if (iTask.do_retry) {
return &acb->common; goto retry;
}
static int
iscsi_aio_flush_acb(IscsiAIOCB *acb);
static void
iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
void *command_data, void *opaque)
{
IscsiAIOCB *acb = opaque;
if (acb->canceled != 0) {
return;
} }
acb->status = 0; if (iTask.status != SCSI_STATUS_GOOD) {
if (status != 0) { return -EIO;
if (status == SCSI_STATUS_CHECK_CONDITION
&& acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
&& acb->retries-- > 0) {
scsi_free_scsi_task(acb->task);
acb->task = NULL;
if (iscsi_aio_flush_acb(acb) == 0) {
iscsi_set_events(acb->iscsilun);
return;
}
}
error_report("Failed to sync10 data on iSCSI lun. %s",
iscsi_get_error(iscsi));
acb->status = -EIO;
}
iscsi_schedule_bh(acb);
}
static int
iscsi_aio_flush_acb(IscsiAIOCB *acb)
{
struct iscsi_context *iscsi = acb->iscsilun->iscsi;
acb->canceled = 0;
acb->bh = NULL;
acb->status = -EINPROGRESS;
acb->buf = NULL;
acb->task = iscsi_synchronizecache10_task(iscsi, acb->iscsilun->lun,
0, 0, 0, 0,
iscsi_synccache10_cb,
acb);
if (acb->task == NULL) {
error_report("iSCSI: Failed to send synchronizecache10 command. %s",
iscsi_get_error(iscsi));
return -1;
} }
return 0; return 0;
} }
static BlockDriverAIOCB * static int coroutine_fn iscsi_co_flush(BlockDriverState *bs)
iscsi_aio_flush(BlockDriverState *bs,
BlockDriverCompletionFunc *cb, void *opaque)
{ {
IscsiLun *iscsilun = bs->opaque; IscsiLun *iscsilun = bs->opaque;
struct IscsiTask iTask;
IscsiAIOCB *acb; iscsi_co_init_iscsitask(iscsilun, &iTask);
acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque); retry:
if (iscsi_synchronizecache10_task(iscsilun->iscsi, iscsilun->lun, 0, 0, 0,
acb->iscsilun = iscsilun; 0, iscsi_co_generic_cb, &iTask) == NULL) {
acb->retries = ISCSI_CMD_RETRIES; return -EIO;
if (iscsi_aio_flush_acb(acb) != 0) {
qemu_aio_release(acb);
return NULL;
} }
iscsi_set_events(iscsilun); while (!iTask.complete) {
iscsi_set_events(iscsilun);
qemu_coroutine_yield();
}
return &acb->common; if (iTask.task != NULL) {
scsi_free_scsi_task(iTask.task);
iTask.task = NULL;
}
if (iTask.do_retry) {
goto retry;
}
if (iTask.status != SCSI_STATUS_GOOD) {
return -EIO;
}
return 0;
} }
#ifdef __linux__ #ifdef __linux__
@ -1624,10 +1434,9 @@ static BlockDriver bdrv_iscsi = {
#if defined(SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED) #if defined(SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED)
.bdrv_co_write_zeroes = iscsi_co_write_zeroes, .bdrv_co_write_zeroes = iscsi_co_write_zeroes,
#endif #endif
.bdrv_co_readv = iscsi_co_readv,
.bdrv_aio_readv = iscsi_aio_readv, .bdrv_co_writev = iscsi_co_writev,
.bdrv_aio_writev = iscsi_aio_writev, .bdrv_co_flush_to_disk = iscsi_co_flush,
.bdrv_aio_flush = iscsi_aio_flush,
#ifdef __linux__ #ifdef __linux__
.bdrv_ioctl = iscsi_ioctl, .bdrv_ioctl = iscsi_ioctl,

6
configure vendored
View file

@ -3053,13 +3053,13 @@ fi
########################################## ##########################################
# Do we have libiscsi # Do we have libiscsi
# We check for iscsi_unmap_sync() to make sure we have a # We check for iscsi_write16_sync() to make sure we have a
# recent enough version of libiscsi. # at least version 1.4.0 of libiscsi.
if test "$libiscsi" != "no" ; then if test "$libiscsi" != "no" ; then
cat > $TMPC << EOF cat > $TMPC << EOF
#include <stdio.h> #include <stdio.h>
#include <iscsi/iscsi.h> #include <iscsi/iscsi.h>
int main(void) { iscsi_unmap_sync(NULL,0,0,0,NULL,0); return 0; } int main(void) { iscsi_write16_sync(NULL,0,0,NULL,0,0,0,0,0,0,0); return 0; }
EOF EOF
if $pkg_config --atleast-version=1.7.0 libiscsi; then if $pkg_config --atleast-version=1.7.0 libiscsi; then
libiscsi="yes" libiscsi="yes"

View file

@ -886,7 +886,6 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
case RELEASE: case RELEASE:
case ERASE: case ERASE:
case ALLOW_MEDIUM_REMOVAL: case ALLOW_MEDIUM_REMOVAL:
case VERIFY_10:
case SEEK_10: case SEEK_10:
case SYNCHRONIZE_CACHE: case SYNCHRONIZE_CACHE:
case SYNCHRONIZE_CACHE_16: case SYNCHRONIZE_CACHE_16:
@ -903,6 +902,16 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
case ALLOW_OVERWRITE: case ALLOW_OVERWRITE:
cmd->xfer = 0; cmd->xfer = 0;
break; break;
case VERIFY_10:
case VERIFY_12:
case VERIFY_16:
if ((buf[1] & 2) == 0) {
cmd->xfer = 0;
} else if ((buf[1] & 4) == 1) {
cmd->xfer = 1;
}
cmd->xfer *= dev->blocksize;
break;
case MODE_SENSE: case MODE_SENSE:
break; break;
case WRITE_SAME_10: case WRITE_SAME_10:
@ -1100,6 +1109,9 @@ static void scsi_cmd_xfer_mode(SCSICommand *cmd)
case WRITE_VERIFY_12: case WRITE_VERIFY_12:
case WRITE_16: case WRITE_16:
case WRITE_VERIFY_16: case WRITE_VERIFY_16:
case VERIFY_10:
case VERIFY_12:
case VERIFY_16:
case COPY: case COPY:
case COPY_VERIFY: case COPY_VERIFY:
case COMPARE: case COMPARE:

View file

@ -1626,7 +1626,7 @@ static void scsi_write_same_complete(void *opaque, int ret)
bdrv_acct_start(s->qdev.conf.bs, &r->acct, data->iov.iov_len, BDRV_ACCT_WRITE); bdrv_acct_start(s->qdev.conf.bs, &r->acct, data->iov.iov_len, BDRV_ACCT_WRITE);
r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, data->sector, r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, data->sector,
&data->qiov, data->iov.iov_len / 512, &data->qiov, data->iov.iov_len / 512,
scsi_write_same_complete, r); scsi_write_same_complete, data);
return; return;
} }
@ -1720,10 +1720,19 @@ static void scsi_disk_emulate_write_data(SCSIRequest *req)
scsi_disk_emulate_unmap(r, r->iov.iov_base); scsi_disk_emulate_unmap(r, r->iov.iov_base);
break; break;
case VERIFY_10:
case VERIFY_12:
case VERIFY_16:
if (r->req.status == -1) {
scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
}
break;
case WRITE_SAME_10: case WRITE_SAME_10:
case WRITE_SAME_16: case WRITE_SAME_16:
scsi_disk_emulate_write_same(r, r->iov.iov_base); scsi_disk_emulate_write_same(r, r->iov.iov_base);
break; break;
default: default:
abort(); abort();
} }
@ -1964,6 +1973,14 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
case UNMAP: case UNMAP:
DPRINTF("Unmap (len %lu)\n", (long)r->req.cmd.xfer); DPRINTF("Unmap (len %lu)\n", (long)r->req.cmd.xfer);
break; break;
case VERIFY_10:
case VERIFY_12:
case VERIFY_16:
DPRINTF("Verify (bytchk %lu)\n", (r->req.buf[1] >> 1) & 3);
if (req->cmd.buf[1] & 6) {
goto illegal_request;
}
break;
case WRITE_SAME_10: case WRITE_SAME_10:
case WRITE_SAME_16: case WRITE_SAME_16:
DPRINTF("WRITE SAME %d (len %lu)\n", DPRINTF("WRITE SAME %d (len %lu)\n",
@ -2044,10 +2061,6 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf)
scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED)); scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED));
return 0; return 0;
} }
/* fallthrough */
case VERIFY_10:
case VERIFY_12:
case VERIFY_16:
DPRINTF("Write %s(sector %" PRId64 ", count %u)\n", DPRINTF("Write %s(sector %" PRId64 ", count %u)\n",
(command & 0xe) == 0xe ? "And Verify " : "", (command & 0xe) == 0xe ? "And Verify " : "",
r->req.cmd.lba, len); r->req.cmd.lba, len);
@ -2315,14 +2328,14 @@ static const SCSIReqOps *const scsi_disk_reqops_dispatch[256] = {
[UNMAP] = &scsi_disk_emulate_reqops, [UNMAP] = &scsi_disk_emulate_reqops,
[WRITE_SAME_10] = &scsi_disk_emulate_reqops, [WRITE_SAME_10] = &scsi_disk_emulate_reqops,
[WRITE_SAME_16] = &scsi_disk_emulate_reqops, [WRITE_SAME_16] = &scsi_disk_emulate_reqops,
[VERIFY_10] = &scsi_disk_emulate_reqops,
[VERIFY_12] = &scsi_disk_emulate_reqops,
[VERIFY_16] = &scsi_disk_emulate_reqops,
[READ_6] = &scsi_disk_dma_reqops, [READ_6] = &scsi_disk_dma_reqops,
[READ_10] = &scsi_disk_dma_reqops, [READ_10] = &scsi_disk_dma_reqops,
[READ_12] = &scsi_disk_dma_reqops, [READ_12] = &scsi_disk_dma_reqops,
[READ_16] = &scsi_disk_dma_reqops, [READ_16] = &scsi_disk_dma_reqops,
[VERIFY_10] = &scsi_disk_dma_reqops,
[VERIFY_12] = &scsi_disk_dma_reqops,
[VERIFY_16] = &scsi_disk_dma_reqops,
[WRITE_6] = &scsi_disk_dma_reqops, [WRITE_6] = &scsi_disk_dma_reqops,
[WRITE_10] = &scsi_disk_dma_reqops, [WRITE_10] = &scsi_disk_dma_reqops,
[WRITE_12] = &scsi_disk_dma_reqops, [WRITE_12] = &scsi_disk_dma_reqops,

View file

@ -2096,7 +2096,7 @@ ETEXI
DEF("iscsi", HAS_ARG, QEMU_OPTION_iscsi, DEF("iscsi", HAS_ARG, QEMU_OPTION_iscsi,
"-iscsi [user=user][,password=password]\n" "-iscsi [user=user][,password=password]\n"
" [,header-digest=CRC32C|CR32C-NONE|NONE-CRC32C|NONE\n" " [,header-digest=CRC32C|CR32C-NONE|NONE-CRC32C|NONE\n"
" [,initiator-name=iqn]\n" " [,initiator-name=initiator-iqn][,id=target-iqn]\n"
" iSCSI session parameters\n", QEMU_ARCH_ALL) " iSCSI session parameters\n", QEMU_ARCH_ALL)
STEXI STEXI