static void scsi_write_same_complete(void *opaque, int ret)
{
    WriteSameCBData *data = opaque;
    SCSIDiskReq *r = data->r;
    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);

    assert(r->req.aiocb != NULL);
    r->req.aiocb = NULL;
    aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
    if (scsi_disk_req_check_error(r, ret, true)) {
        goto done;
    }

    block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);

    data->nb_sectors -= data->iov.iov_len / BDRV_SECTOR_SIZE;
    data->sector += data->iov.iov_len / BDRV_SECTOR_SIZE;
    data->iov.iov_len = MIN(data->nb_sectors * BDRV_SECTOR_SIZE,
                            data->iov.iov_len);
    if (data->iov.iov_len) {
        block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct,
                         data->iov.iov_len, BLOCK_ACCT_WRITE);
        /* Reinitialize qiov, to handle unaligned WRITE SAME request
         * where final qiov may need smaller size */
        qemu_iovec_init_external(&data->qiov, &data->iov, 1);
        r->req.aiocb = blk_aio_pwritev(s->qdev.conf.blk,
                                       data->sector << BDRV_SECTOR_BITS,
                                       &data->qiov, 0,
                                       scsi_write_same_complete, data);
        aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
        return;
    }

    scsi_req_complete(&r->req, GOOD);

done:
    scsi_req_unref(&r->req);
    qemu_vfree(data->iov.iov_base);
    g_free(data);
    aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
}
Unknown