Il 15/02/2013 15:35, Peter Lieven ha scritto: > this patch adds iscsi_truncate which effectively allows for online > resizing of iscsi volumes. for this to work you have to resize > the volume on your storage and then call block_resize command > in qemu which will issue a readcapacity16 to update the capacity. > > v2: > - add a general bdrv_drain_all() before bdrv_truncate() to avoid > in-flight AIOs while the device is truncated > - since no AIOs are in flight we can use a sync libiscsi call > to re-read the capacity > - factor out the readcapacity16 logic as it is redundant > to iscsi_open() and iscsi_truncate().
Please move the entire switch statement of iscsi_open, the code should be cleaner. Also please separate bdrv_drain_all() to a separate patch and Cc qemu-stable on that one (Kevin's message should provide a good skeleton for a commit messages). Paolo > Signed-off-by: Peter Lieven <p...@kamp.de> > --- > block.c | 4 ++++ > block/iscsi.c | 65 > +++++++++++++++++++++++++++++++++++++++++++++------------ > 2 files changed, 56 insertions(+), 13 deletions(-) > > diff --git a/block.c b/block.c > index 50dab8e..d8880e3 100644 > --- a/block.c > +++ b/block.c > @@ -2427,6 +2427,10 @@ int bdrv_truncate(BlockDriverState *bs, int64_t > offset) > return -EACCES; > if (bdrv_in_use(bs)) > return -EBUSY; > + > + /* there should be better no AIOs in flight when we truncate the > device */ > + bdrv_drain_all(); > + > ret = drv->bdrv_truncate(bs, offset); > if (ret == 0) { > ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); > diff --git a/block/iscsi.c b/block/iscsi.c > index deb3b68..dd41943 100644 > --- a/block/iscsi.c > +++ b/block/iscsi.c > @@ -823,6 +823,35 @@ static void iscsi_nop_timed_event(void *opaque) > } > #endif > > +static int iscsi_disk_readcapacity16_sync(IscsiLun *iscsilun) { > + struct scsi_task *task = NULL; > + struct scsi_readcapacity16 *rc16 = NULL; > + > + task = iscsi_readcapacity16_sync(iscsilun->iscsi, iscsilun->lun); > + if (task == NULL) { > + error_report("iSCSI: failed to send readcapacity16 command."); > + return -EINVAL; > + } > + if (task->status != SCSI_STATUS_GOOD) { > + error_report("iSCSI: failed to send readcapacity16 command."); > + scsi_free_scsi_task(task); > + return -EINVAL; > + } > + rc16 = scsi_datain_unmarshall(task); > + if (rc16 == NULL) { > + error_report("iSCSI: Failed to unmarshall readcapacity16 data."); > + scsi_free_scsi_task(task); > + return -EINVAL; > + } > + > + iscsilun->block_size = rc16->block_length; > + iscsilun->num_blocks = rc16->returned_lba + 1; > + > + scsi_free_scsi_task(task); > + > + return 0; > +} > + > /* > * We support iscsi url's on the form > * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun> > @@ -835,7 +864,6 @@ static int iscsi_open(BlockDriverState *bs, const > char *filename, int flags) > struct scsi_task *task = NULL; > struct scsi_inquiry_standard *inq = NULL; > struct scsi_readcapacity10 *rc10 = NULL; > - struct scsi_readcapacity16 *rc16 = NULL; > char *initiator_name = NULL; > int ret; > > @@ -926,23 +954,13 @@ static int iscsi_open(BlockDriverState *bs, const > char *filename, int flags) > iscsilun->type = inq->periperal_device_type; > > scsi_free_scsi_task(task); > + task = NULL; > > switch (iscsilun->type) { > case TYPE_DISK: > - task = iscsi_readcapacity16_sync(iscsi, iscsilun->lun); > - if (task == NULL || task->status != SCSI_STATUS_GOOD) { > - error_report("iSCSI: failed to send readcapacity16 command."); > - ret = -EINVAL; > + if ((ret = iscsi_disk_readcapacity16_sync(iscsilun))) { > goto out; > } > - rc16 = scsi_datain_unmarshall(task); > - if (rc16 == NULL) { > - error_report("iSCSI: Failed to unmarshall readcapacity16 > data."); > - ret = -EINVAL; > - goto out; > - } > - iscsilun->block_size = rc16->block_length; > - iscsilun->num_blocks = rc16->returned_lba + 1; > break; > case TYPE_ROM: > task = iscsi_readcapacity10_sync(iscsi, iscsilun->lun, 0, 0); > @@ -1023,6 +1041,26 @@ static void iscsi_close(BlockDriverState *bs) > memset(iscsilun, 0, sizeof(IscsiLun)); > } > > +static int iscsi_truncate(BlockDriverState *bs, int64_t offset) > +{ > + IscsiLun *iscsilun = bs->opaque; > + int ret = 0; > + > + if (iscsilun->type != TYPE_DISK) { > + return -ENOTSUP; > + } > + > + if ((ret = iscsi_disk_readcapacity16_sync(iscsilun))) { > + return ret; > + } > + > + if (offset > iscsi_getlength(bs)) { > + return -EINVAL; > + } > + > + return 0; > +} > + > static int iscsi_has_zero_init(BlockDriverState *bs) > { > return 0; > @@ -1093,6 +1131,7 @@ static BlockDriver bdrv_iscsi = { > .create_options = iscsi_create_options, > > .bdrv_getlength = iscsi_getlength, > + .bdrv_truncate = iscsi_truncate, > > .bdrv_aio_readv = iscsi_aio_readv, > .bdrv_aio_writev = iscsi_aio_writev,