[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCHv4] iscsi: add iscsi_truncate support
From: |
Paolo Bonzini |
Subject: |
Re: [Qemu-devel] [PATCHv4] iscsi: add iscsi_truncate support |
Date: |
Mon, 25 Feb 2013 12:11:40 +0100 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130110 Thunderbird/17.0.2 |
Il 18/02/2013 14:50, 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.
>
> v4:
> - factor out complete readcapacity logic into a separate function
> - handle capacity change check condition in readcapacity function
> (this happens if the block_resize cmd is the first iscsi task
> executed after a resize on the storage)
>
> v3:
> - remove switch statement in iscsi_open
> - create separate patch for brdv_drain_all() in bdrv_truncate()
>
> 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().
>
> Signed-off-by: Peter Lieven <address@hidden>
Applied to scsi-next branch, thanks.
Paolo
> ---
> block/iscsi.c | 133
> +++++++++++++++++++++++++++++++++++++--------------------
> 1 file changed, 87 insertions(+), 46 deletions(-)
>
> diff --git a/block/iscsi.c b/block/iscsi.c
> index deb3b68..1ea290e 100644
> --- a/block/iscsi.c
> +++ b/block/iscsi.c
> @@ -823,6 +823,70 @@ static void iscsi_nop_timed_event(void *opaque)
> }
> #endif
>
> +static int iscsi_readcapacity_sync(IscsiLun *iscsilun) {
> + struct scsi_task *task = NULL;
> + struct scsi_readcapacity10 *rc10 = NULL;
> + struct scsi_readcapacity16 *rc16 = NULL;
> + int ret = 0;
> +
> +try_again:
> + switch (iscsilun->type) {
> + case TYPE_DISK:
> + task = iscsi_readcapacity16_sync(iscsilun->iscsi, iscsilun->lun);
> + if (task == NULL || task->status != SCSI_STATUS_GOOD) {
> + /* Capacity data has changed */
> + if (task != NULL && task->status ==
> SCSI_STATUS_CHECK_CONDITION
> + && task->sense.key == SCSI_SENSE_UNIT_ATTENTION
> + && task->sense.ascq == 0x2a09) {
> + scsi_free_scsi_task(task);
> + goto try_again;
> + }
> + error_report("iSCSI: failed to send readcapacity16 command.");
> + ret = -EINVAL;
> + 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(iscsilun->iscsi,
> iscsilun->lun, 0, 0);
> + if (task == NULL || task->status != SCSI_STATUS_GOOD) {
> + error_report("iSCSI: failed to send readcapacity10 command.");
> + ret = -EINVAL;
> + goto out;
> + }
> + rc10 = scsi_datain_unmarshall(task);
> + if (rc10 == NULL) {
> + error_report("iSCSI: Failed to unmarshall readcapacity10
> data.");
> + ret = -EINVAL;
> + goto out;
> + }
> + iscsilun->block_size = rc10->block_size;
> + if (rc10->lba == 0) {
> + /* blank disk loaded */
> + iscsilun->num_blocks = 0;
> + } else {
> + iscsilun->num_blocks = rc10->lba + 1;
> + }
> + break;
> + default:
> + break;
> + }
> +
> +out:
> + if (task) {
> + scsi_free_scsi_task(task);
> + }
> +
> + return ret;
> +}
> +
> /*
> * We support iscsi url's on the form
> * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
> @@ -834,8 +898,6 @@ static int iscsi_open(BlockDriverState *bs, const
> char *filename, int flags)
> struct iscsi_url *iscsi_url = NULL;
> 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;
>
> @@ -925,48 +987,8 @@ static int iscsi_open(BlockDriverState *bs, const
> char *filename, int flags)
>
> iscsilun->type = inq->periperal_device_type;
>
> - scsi_free_scsi_task(task);
> -
> - 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;
> - 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);
> - if (task == NULL || task->status != SCSI_STATUS_GOOD) {
> - error_report("iSCSI: failed to send readcapacity10 command.");
> - ret = -EINVAL;
> - goto out;
> - }
> - rc10 = scsi_datain_unmarshall(task);
> - if (rc10 == NULL) {
> - error_report("iSCSI: Failed to unmarshall readcapacity10
> data.");
> - ret = -EINVAL;
> - goto out;
> - }
> - iscsilun->block_size = rc10->block_size;
> - if (rc10->lba == 0) {
> - /* blank disk loaded */
> - iscsilun->num_blocks = 0;
> - } else {
> - iscsilun->num_blocks = rc10->lba + 1;
> - }
> - break;
> - default:
> - break;
> + if ((ret = iscsi_readcapacity_sync(iscsilun)) != 0) {
> + goto out;
> }
>
> bs->total_sectors = iscsilun->num_blocks *
> @@ -981,8 +1003,6 @@ static int iscsi_open(BlockDriverState *bs, const
> char *filename, int flags)
> bs->sg = 1;
> }
>
> - ret = 0;
> -
> #if defined(LIBISCSI_FEATURE_NOP_COUNTER)
> /* Set up a timer for sending out iSCSI NOPs */
> iscsilun->nop_timer = qemu_new_timer_ms(rt_clock,
> iscsi_nop_timed_event, iscsilun);
> @@ -1023,6 +1043,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_readcapacity_sync(iscsilun)) != 0) {
> + return ret;
> + }
> +
> + if (offset > iscsi_getlength(bs)) {
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> static int iscsi_has_zero_init(BlockDriverState *bs)
> {
> return 0;
> @@ -1093,6 +1133,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,
- Re: [Qemu-devel] [PATCHv2] iscsi: add iscsi_truncate support, (continued)
- Re: [Qemu-devel] [PATCH] block: complete all IOs before .bdrv_truncate, Eric Blake, 2013/02/18
- [Qemu-devel] [PATCHv3] iscsi: add iscsi_truncate support, Peter Lieven, 2013/02/18
- Re: [Qemu-devel] [PATCHv3] iscsi: add iscsi_truncate support, Paolo Bonzini, 2013/02/18
- Re: [Qemu-devel] [PATCHv3] iscsi: add iscsi_truncate support, Peter Lieven, 2013/02/18
- Re: [Qemu-devel] [PATCHv3] iscsi: add iscsi_truncate support, Paolo Bonzini, 2013/02/18
- [Qemu-devel] [PATCHv4] iscsi: add iscsi_truncate support, Peter Lieven, 2013/02/18
- Re: [Qemu-devel] [PATCHv4] iscsi: add iscsi_truncate support,
Paolo Bonzini <=