qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCHv2 07/11] iscsi: let bdrv_create conditionally ze


From: Paolo Bonzini
Subject: Re: [Qemu-devel] [PATCHv2 07/11] iscsi: let bdrv_create conditionally zero out the device
Date: Mon, 01 Jul 2013 22:20:45 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130514 Thunderbird/17.0.6

Il 27/06/2013 15:11, Peter Lieven ha scritto:
> if the device supports unmapping and unmapped blocks read as
> zero ensure that the whole device is unmapped and report
> .has_zero_init = 1 in this case to speed up qemu-img convert.

This can still take several minutes.  Do you need any special timeout in
libiscsi?

Perhaps we can have a new "discard_zeroes" field in bdrv_get_info, and
the unmap functionality can be moved up to qemu-img convert?

Paolo

> 
> Signed-off-by: Peter Lieven <address@hidden>
> ---
>  block/iscsi.c |   72 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 71 insertions(+), 1 deletion(-)
> 
> diff --git a/block/iscsi.c b/block/iscsi.c
> index 92e66a6..621ca40 100644
> --- a/block/iscsi.c
> +++ b/block/iscsi.c
> @@ -1436,7 +1436,8 @@ static int iscsi_truncate(BlockDriverState *bs, int64_t 
> offset)
>  
>  static int iscsi_has_zero_init(BlockDriverState *bs)
>  {
> -    return 0;
> +    IscsiLun *iscsilun = bs->opaque;
> +    return (iscsilun->lbpu && iscsilun->lbprz) ? 1 : 0;
>  }
>  
>  static int iscsi_create(const char *filename, QEMUOptionParameter *options)
> @@ -1446,6 +1447,7 @@ static int iscsi_create(const char *filename, 
> QEMUOptionParameter *options)
>      BlockDriverState bs;
>      IscsiLun *iscsilun = NULL;
>      QDict *bs_options;
> +    struct scsi_task *task = NULL;
>  
>      memset(&bs, 0, sizeof(BlockDriverState));
>  
> @@ -1481,7 +1483,75 @@ static int iscsi_create(const char *filename, 
> QEMUOptionParameter *options)
>      }
>  
>      ret = 0;
> +
> +    if (iscsilun->lbpu && iscsilun->lbprz) {
> +        uint64_t lba = 0;
> +        while (lba < iscsilun->num_blocks) {
> +            struct scsi_get_lba_status *lbas = NULL;
> +            struct scsi_lba_status_descriptor *lbasd = NULL;
> +            enum scsi_provisioning_type provisioning;
> +            uint32_t nb_sectors;
> +
> +            task = iscsi_get_lba_status_sync(iscsilun->iscsi, iscsilun->lun,
> +                                             lba, 8 + 16);
> +            if (task == NULL || task->status != SCSI_STATUS_GOOD) {
> +                error_report("iSCSI: Failed to get_lba_status on iSCSI lun. 
> %s",
> +                             iscsi_get_error(iscsilun->iscsi));
> +                ret = -EINVAL;
> +                goto out;
> +            }
> +
> +            lbas = scsi_datain_unmarshall(task);
> +            if (lbas == NULL) {
> +                error_report("iSCSI: failed to unmarshall inquiry datain 
> blob");
> +                ret = -EINVAL;
> +                goto out;
> +            }
> +            lbasd = &lbas->descriptors[0];
> +            if (lbasd->lba != lba) {
> +                ret = -EINVAL;
> +                goto out;
> +            }
> +            nb_sectors = lbasd->num_blocks;
> +            provisioning = lbasd->provisioning;
> +            scsi_free_scsi_task(task);
> +            task = NULL;
> +
> +            /* blocks from lba to lba + nb_sectors - 1 are not mapped
> +             * and read as zero (lbprz==1) so we can skip them */
> +            if (provisioning != SCSI_PROVISIONING_TYPE_MAPPED) {
> +                lba += nb_sectors;
> +                continue;
> +            }
> +
> +            uint64_t lba2 = lba + nb_sectors;
> +            while (lba < lba2) {
> +                struct unmap_list list[1];
> +                list[0].lba = lba;
> +                list[0].num = iscsilun->max_unmap;
> +                if (lba + list[0].num > iscsilun->num_blocks) {
> +                    list[0].num = iscsilun->num_blocks - lba;
> +                }
> +                task = iscsi_unmap_sync(iscsilun->iscsi,
> +                                        iscsilun->lun,
> +                                        0, 0, &list[0], 1);
> +                if (task == NULL || task->status != SCSI_STATUS_GOOD) {
> +                    error_report("iSCSI: Failed to unmap data on iSCSI lun. 
> %s",
> +                                 iscsi_get_error(iscsilun->iscsi));
> +                    ret = -EINVAL;
> +                    goto out;
> +                }
> +                scsi_free_scsi_task(task);
> +                task = NULL;
> +                lba += list[0].num;
> +            }
> +        }
> +    }
> +
>  out:
> +    if (task) {
> +        scsi_free_scsi_task(task);
> +    }
>      if (iscsilun->iscsi != NULL) {
>          iscsi_destroy_context(iscsilun->iscsi);
>      }
> 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]