static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,

                                                  int64_t sector_num,

                                                  int nb_sectors, int *pnum)

{

    IscsiLun *iscsilun = bs->opaque;

    struct scsi_get_lba_status *lbas = NULL;

    struct scsi_lba_status_descriptor *lbasd = NULL;

    struct IscsiTask iTask;

    int64_t ret;



    iscsi_co_init_iscsitask(iscsilun, &iTask);



    if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {

        ret = -EINVAL;

        goto out;

    }



    /* default to all sectors allocated */

    ret = BDRV_BLOCK_DATA;

    ret |= (sector_num << BDRV_SECTOR_BITS) | BDRV_BLOCK_OFFSET_VALID;

    *pnum = nb_sectors;



    /* LUN does not support logical block provisioning */

    if (!iscsilun->lbpme) {

        goto out;

    }



retry:

    if (iscsi_get_lba_status_task(iscsilun->iscsi, iscsilun->lun,

                                  sector_qemu2lun(sector_num, iscsilun),

                                  8 + 16, iscsi_co_generic_cb,

                                  &iTask) == NULL) {

        ret = -ENOMEM;

        goto out;

    }



    while (!iTask.complete) {

        iscsi_set_events(iscsilun);

        qemu_coroutine_yield();

    }



    if (iTask.do_retry) {

        if (iTask.task != NULL) {

            scsi_free_scsi_task(iTask.task);

            iTask.task = NULL;

        }

        iTask.complete = 0;

        goto retry;

    }



    if (iTask.status != SCSI_STATUS_GOOD) {

        /* in case the get_lba_status_callout fails (i.e.

         * because the device is busy or the cmd is not

         * supported) we pretend all blocks are allocated

         * for backwards compatibility */

        goto out;

    }



    lbas = scsi_datain_unmarshall(iTask.task);

    if (lbas == NULL) {

        ret = -EIO;

        goto out;

    }



    lbasd = &lbas->descriptors[0];



    if (sector_qemu2lun(sector_num, iscsilun) != lbasd->lba) {

        ret = -EIO;

        goto out;

    }



    *pnum = sector_lun2qemu(lbasd->num_blocks, iscsilun);



    if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED ||

        lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) {

        ret &= ~BDRV_BLOCK_DATA;

        if (iscsilun->lbprz) {

            ret |= BDRV_BLOCK_ZERO;

        }

    }



    if (ret & BDRV_BLOCK_ZERO) {

        iscsi_allocationmap_clear(iscsilun, sector_num, *pnum);

    } else {

        iscsi_allocationmap_set(iscsilun, sector_num, *pnum);

    }



    if (*pnum > nb_sectors) {

        *pnum = nb_sectors;

    }

out:

    if (iTask.task != NULL) {

        scsi_free_scsi_task(iTask.task);

    }

    return ret;

}

static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,

                                                  int64_t sector_num,

                                                  int nb_sectors, int *pnum)

{

    IscsiLun *iscsilun = bs->opaque;

    struct scsi_get_lba_status *lbas = NULL;

    struct scsi_lba_status_descriptor *lbasd = NULL;

    struct IscsiTask iTask;

    int64_t ret;



    iscsi_co_init_iscsitask(iscsilun, &iTask);



    if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {

        ret = -EINVAL;

        goto out;

    }



    

    ret = BDRV_BLOCK_DATA;

    ret |= (sector_num << BDRV_SECTOR_BITS) | BDRV_BLOCK_OFFSET_VALID;

    *pnum = nb_sectors;



    

    if (!iscsilun->lbpme) {

        goto out;

    }



retry:

    if (iscsi_get_lba_status_task(iscsilun->iscsi, iscsilun->lun,

                                  sector_qemu2lun(sector_num, iscsilun),

                                  8 + 16, iscsi_co_generic_cb,

                                  &iTask) == NULL) {

        ret = -ENOMEM;

        goto out;

    }



    while (!iTask.complete) {

        iscsi_set_events(iscsilun);

        qemu_coroutine_yield();

    }



    if (iTask.do_retry) {

        if (iTask.task != NULL) {

            scsi_free_scsi_task(iTask.task);

            iTask.task = NULL;

        }

        iTask.complete = 0;

        goto retry;

    }



    if (iTask.status != SCSI_STATUS_GOOD) {

        







        goto out;

    }



    lbas = scsi_datain_unmarshall(iTask.task);

    if (lbas == NULL) {

        ret = -EIO;

        goto out;

    }



    lbasd = &lbas->descriptors[0];



    if (sector_qemu2lun(sector_num, iscsilun) != lbasd->lba) {

        ret = -EIO;

        goto out;

    }



    *pnum = sector_lun2qemu(lbasd->num_blocks, iscsilun);



    if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED ||

        lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) {

        ret &= ~BDRV_BLOCK_DATA;

        if (iscsilun->lbprz) {

            ret |= BDRV_BLOCK_ZERO;

        }

    }



    if (ret & BDRV_BLOCK_ZERO) {

        iscsi_allocationmap_clear(iscsilun, sector_num, *pnum);

    } else {

        iscsi_allocationmap_set(iscsilun, sector_num, *pnum);

    }



    if (*pnum > nb_sectors) {

        *pnum = nb_sectors;

    }

out:

    if (iTask.task != NULL) {

        scsi_free_scsi_task(iTask.task);

    }

    return ret;

}

static int64_t VAR_0 iscsi_co_get_block_status(BlockDriverState *bs,

                                                  int64_t sector_num,

                                                  int nb_sectors, int *pnum)

{

    IscsiLun *iscsilun = bs->opaque;

    struct scsi_get_lba_status *lbas = NULL;

    struct scsi_lba_status_descriptor *lbasd = NULL;

    struct IscsiTask iTask;

    int64_t ret;



    iscsi_co_init_iscsitask(iscsilun, &iTask);



    if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {

        ret = -EINVAL;

        goto out;

    }



    

    ret = BDRV_BLOCK_DATA;

    ret |= (sector_num << BDRV_SECTOR_BITS) | BDRV_BLOCK_OFFSET_VALID;

    *pnum = nb_sectors;



    

    if (!iscsilun->lbpme) {

        goto out;

    }



retry:

    if (iscsi_get_lba_status_task(iscsilun->iscsi, iscsilun->lun,

                                  sector_qemu2lun(sector_num, iscsilun),

                                  8 + 16, iscsi_co_generic_cb,

                                  &iTask) == NULL) {

        ret = -ENOMEM;

        goto out;

    }



    while (!iTask.complete) {

        iscsi_set_events(iscsilun);

        qemu_coroutine_yield();

    }



    if (iTask.do_retry) {

        if (iTask.task != NULL) {

            scsi_free_scsi_task(iTask.task);

            iTask.task = NULL;

        }

        iTask.complete = 0;

        goto retry;

    }



    if (iTask.status != SCSI_STATUS_GOOD) {

        







        goto out;

    }



    lbas = scsi_datain_unmarshall(iTask.task);

    if (lbas == NULL) {

        ret = -EIO;

        goto out;

    }



    lbasd = &lbas->descriptors[0];



    if (sector_qemu2lun(sector_num, iscsilun) != lbasd->lba) {

        ret = -EIO;

        goto out;

    }



    *pnum = sector_lun2qemu(lbasd->num_blocks, iscsilun);



    if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED ||

        lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) {

        ret &= ~BDRV_BLOCK_DATA;

        if (iscsilun->lbprz) {

            ret |= BDRV_BLOCK_ZERO;

        }

    }



    if (ret & BDRV_BLOCK_ZERO) {

        iscsi_allocationmap_clear(iscsilun, sector_num, *pnum);

    } else {

        iscsi_allocationmap_set(iscsilun, sector_num, *pnum);

    }



    if (*pnum > nb_sectors) {

        *pnum = nb_sectors;

    }

out:

    if (iTask.task != NULL) {

        scsi_free_scsi_task(iTask.task);

    }

    return ret;

}

static int64_t VAR_0 iscsi_co_get_block_status(BlockDriverState *bs,
int64_t sector_num,
int nb_sectors, int *pnum)
{ IscsiLun *iscsilun = bs->opaque; struct scsi_get_lba_status *lbas = NULL; struct scsi_lba_status_descriptor *lbasd = NULL; struct IscsiTask iTask; int64_t ret; iscsi_co_init_iscsitask(iscsilun, &iTask); if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) { ret = -EINVAL; goto out; } ret = BDRV_BLOCK_DATA; ret |= (sector_num << BDRV_SECTOR_BITS) | BDRV_BLOCK_OFFSET_VALID; *pnum = nb_sectors; if (!iscsilun->lbpme) { goto out; } retry:
if (iscsi_get_lba_status_task(iscsilun->iscsi, iscsilun->lun,
sector_qemu2lun(sector_num, iscsilun),
8 + 16, iscsi_co_generic_cb,
&iTask) == NULL) { ret = -ENOMEM; goto out; } while (!iTask.complete) { iscsi_set_events(iscsilun); qemu_coroutine_yield(); } if (iTask.do_retry) { if (iTask.task != NULL) { scsi_free_scsi_task(iTask.task); iTask.task = NULL; } iTask.complete = 0; goto retry; } if (iTask.status != SCSI_STATUS_GOOD) { goto out; } lbas = scsi_datain_unmarshall(iTask.task); if (lbas == NULL) { ret = -EIO; goto out; } lbasd = &lbas->descriptors[0]; if (sector_qemu2lun(sector_num, iscsilun) != lbasd->lba) { ret = -EIO; goto out; } *pnum = sector_lun2qemu(lbasd->num_blocks, iscsilun); if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED ||
lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) { ret &= ~BDRV_BLOCK_DATA; if (iscsilun->lbprz) { ret |= BDRV_BLOCK_ZERO; } } if (ret & BDRV_BLOCK_ZERO) { iscsi_allocationmap_clear(iscsilun, sector_num, *pnum); } else { iscsi_allocationmap_set(iscsilun, sector_num, *pnum); } if (*pnum > nb_sectors) { *pnum = nb_sectors; } out:
if (iTask.task != NULL) { scsi_free_scsi_task(iTask.task); } return ret; }