void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,

                               unsigned int *out_bytes,

                               unsigned max_in_bytes, unsigned max_out_bytes)

{

    VirtIODevice *vdev = vq->vdev;

    unsigned int max, idx;

    unsigned int total_bufs, in_total, out_total;

    VRingMemoryRegionCaches *caches;

    MemoryRegionCache indirect_desc_cache = MEMORY_REGION_CACHE_INVALID;

    int64_t len = 0;

    int rc;



    if (unlikely(!vq->vring.desc)) {

        if (in_bytes) {

            *in_bytes = 0;

        }

        if (out_bytes) {

            *out_bytes = 0;

        }

        return;

    }



    rcu_read_lock();

    idx = vq->last_avail_idx;

    total_bufs = in_total = out_total = 0;



    max = vq->vring.num;

    caches = atomic_rcu_read(&vq->vring.caches);

    if (caches->desc.len < max * sizeof(VRingDesc)) {

        virtio_error(vdev, "Cannot map descriptor ring");

        goto err;

    }



    while ((rc = virtqueue_num_heads(vq, idx)) > 0) {

        MemoryRegionCache *desc_cache = &caches->desc;

        unsigned int num_bufs;

        VRingDesc desc;

        unsigned int i;



        num_bufs = total_bufs;



        if (!virtqueue_get_head(vq, idx++, &i)) {

            goto err;

        }



        vring_desc_read(vdev, &desc, desc_cache, i);



        if (desc.flags & VRING_DESC_F_INDIRECT) {

            if (desc.len % sizeof(VRingDesc)) {

                virtio_error(vdev, "Invalid size for indirect buffer table");

                goto err;

            }



            /* If we've got too many, that implies a descriptor loop. */

            if (num_bufs >= max) {

                virtio_error(vdev, "Looped descriptor");

                goto err;

            }



            /* loop over the indirect descriptor table */

            len = address_space_cache_init(&indirect_desc_cache,

                                           vdev->dma_as,

                                           desc.addr, desc.len, false);

            desc_cache = &indirect_desc_cache;

            if (len < desc.len) {

                virtio_error(vdev, "Cannot map indirect buffer");

                goto err;

            }



            max = desc.len / sizeof(VRingDesc);

            num_bufs = i = 0;

            vring_desc_read(vdev, &desc, desc_cache, i);

        }



        do {

            /* If we've got too many, that implies a descriptor loop. */

            if (++num_bufs > max) {

                virtio_error(vdev, "Looped descriptor");

                goto err;

            }



            if (desc.flags & VRING_DESC_F_WRITE) {

                in_total += desc.len;

            } else {

                out_total += desc.len;

            }

            if (in_total >= max_in_bytes && out_total >= max_out_bytes) {

                goto done;

            }



            rc = virtqueue_read_next_desc(vdev, &desc, desc_cache, max, &i);

        } while (rc == VIRTQUEUE_READ_DESC_MORE);



        if (rc == VIRTQUEUE_READ_DESC_ERROR) {

            goto err;

        }



        if (desc_cache == &indirect_desc_cache) {

            address_space_cache_destroy(&indirect_desc_cache);

            total_bufs++;

        } else {

            total_bufs = num_bufs;

        }

    }



    if (rc < 0) {

        goto err;

    }



done:

    address_space_cache_destroy(&indirect_desc_cache);

    if (in_bytes) {

        *in_bytes = in_total;

    }

    if (out_bytes) {

        *out_bytes = out_total;

    }

    rcu_read_unlock();

    return;



err:

    in_total = out_total = 0;

    goto done;

}

void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,

                               unsigned int *out_bytes,

                               unsigned max_in_bytes, unsigned max_out_bytes)

{

    VirtIODevice *vdev = vq->vdev;

    unsigned int max, idx;

    unsigned int total_bufs, in_total, out_total;

    VRingMemoryRegionCaches *caches;

    MemoryRegionCache indirect_desc_cache = MEMORY_REGION_CACHE_INVALID;

    int64_t len = 0;

    int rc;



    if (unlikely(!vq->vring.desc)) {

        if (in_bytes) {

            *in_bytes = 0;

        }

        if (out_bytes) {

            *out_bytes = 0;

        }

        return;

    }



    rcu_read_lock();

    idx = vq->last_avail_idx;

    total_bufs = in_total = out_total = 0;



    max = vq->vring.num;

    caches = atomic_rcu_read(&vq->vring.caches);

    if (caches->desc.len < max * sizeof(VRingDesc)) {

        virtio_error(vdev, "Cannot map descriptor ring");

        goto err;

    }



    while ((rc = virtqueue_num_heads(vq, idx)) > 0) {

        MemoryRegionCache *desc_cache = &caches->desc;

        unsigned int num_bufs;

        VRingDesc desc;

        unsigned int i;



        num_bufs = total_bufs;



        if (!virtqueue_get_head(vq, idx++, &i)) {

            goto err;

        }



        vring_desc_read(vdev, &desc, desc_cache, i);



        if (desc.flags & VRING_DESC_F_INDIRECT) {

            if (desc.len % sizeof(VRingDesc)) {

                virtio_error(vdev, "Invalid size for indirect buffer table");

                goto err;

            }



            

            if (num_bufs >= max) {

                virtio_error(vdev, "Looped descriptor");

                goto err;

            }



            

            len = address_space_cache_init(&indirect_desc_cache,

                                           vdev->dma_as,

                                           desc.addr, desc.len, false);

            desc_cache = &indirect_desc_cache;

            if (len < desc.len) {

                virtio_error(vdev, "Cannot map indirect buffer");

                goto err;

            }



            max = desc.len / sizeof(VRingDesc);

            num_bufs = i = 0;

            vring_desc_read(vdev, &desc, desc_cache, i);

        }



        do {

            

            if (++num_bufs > max) {

                virtio_error(vdev, "Looped descriptor");

                goto err;

            }



            if (desc.flags & VRING_DESC_F_WRITE) {

                in_total += desc.len;

            } else {

                out_total += desc.len;

            }

            if (in_total >= max_in_bytes && out_total >= max_out_bytes) {

                goto done;

            }



            rc = virtqueue_read_next_desc(vdev, &desc, desc_cache, max, &i);

        } while (rc == VIRTQUEUE_READ_DESC_MORE);



        if (rc == VIRTQUEUE_READ_DESC_ERROR) {

            goto err;

        }



        if (desc_cache == &indirect_desc_cache) {

            address_space_cache_destroy(&indirect_desc_cache);

            total_bufs++;

        } else {

            total_bufs = num_bufs;

        }

    }



    if (rc < 0) {

        goto err;

    }



done:

    address_space_cache_destroy(&indirect_desc_cache);

    if (in_bytes) {

        *in_bytes = in_total;

    }

    if (out_bytes) {

        *out_bytes = out_total;

    }

    rcu_read_unlock();

    return;



err:

    in_total = out_total = 0;

    goto done;

}

    caches = atomic_rcu_read(&vq->vring.caches);     caches = atomic_rcu_read(&vq->vring.caches);     caches = atomic_rcu_read(&vq->vring.caches);
void FUNC_0(VirtQueue *VAR_0, unsigned int *VAR_1,

                               unsigned int *VAR_2,

                               unsigned VAR_3, unsigned VAR_4)

{

    VirtIODevice *vdev = VAR_0->vdev;

    unsigned int VAR_5, VAR_6;

    unsigned int VAR_7, VAR_8, VAR_9;

    VRingMemoryRegionCaches *caches;

    MemoryRegionCache indirect_desc_cache = MEMORY_REGION_CACHE_INVALID;

    int64_t len = 0;

    int VAR_10;



    if (unlikely(!VAR_0->vring.desc)) {

        if (VAR_1) {

            *VAR_1 = 0;

        }

        if (VAR_2) {

            *VAR_2 = 0;

        }

        return;

    }



    rcu_read_lock();

    VAR_6 = VAR_0->last_avail_idx;

    VAR_7 = VAR_8 = VAR_9 = 0;



    VAR_5 = VAR_0->vring.num;

    caches = atomic_rcu_read(&VAR_0->vring.caches);

    if (caches->desc.len < VAR_5 * sizeof(VRingDesc)) {

        virtio_error(vdev, "Cannot map descriptor ring");

        goto err;

    }



    while ((VAR_10 = virtqueue_num_heads(VAR_0, VAR_6)) > 0) {

        MemoryRegionCache *desc_cache = &caches->desc;

        unsigned int VAR_11;

        VRingDesc desc;

        unsigned int VAR_12;



        VAR_11 = VAR_7;



        if (!virtqueue_get_head(VAR_0, VAR_6++, &VAR_12)) {

            goto err;

        }



        vring_desc_read(vdev, &desc, desc_cache, VAR_12);



        if (desc.flags & VRING_DESC_F_INDIRECT) {

            if (desc.len % sizeof(VRingDesc)) {

                virtio_error(vdev, "Invalid size for indirect buffer table");

                goto err;

            }



            

            if (VAR_11 >= VAR_5) {

                virtio_error(vdev, "Looped descriptor");

                goto err;

            }



            

            len = address_space_cache_init(&indirect_desc_cache,

                                           vdev->dma_as,

                                           desc.addr, desc.len, false);

            desc_cache = &indirect_desc_cache;

            if (len < desc.len) {

                virtio_error(vdev, "Cannot map indirect buffer");

                goto err;

            }



            VAR_5 = desc.len / sizeof(VRingDesc);

            VAR_11 = VAR_12 = 0;

            vring_desc_read(vdev, &desc, desc_cache, VAR_12);

        }



        do {

            

            if (++VAR_11 > VAR_5) {

                virtio_error(vdev, "Looped descriptor");

                goto err;

            }



            if (desc.flags & VRING_DESC_F_WRITE) {

                VAR_8 += desc.len;

            } else {

                VAR_9 += desc.len;

            }

            if (VAR_8 >= VAR_3 && VAR_9 >= VAR_4) {

                goto done;

            }



            VAR_10 = virtqueue_read_next_desc(vdev, &desc, desc_cache, VAR_5, &VAR_12);

        } while (VAR_10 == VIRTQUEUE_READ_DESC_MORE);



        if (VAR_10 == VIRTQUEUE_READ_DESC_ERROR) {

            goto err;

        }



        if (desc_cache == &indirect_desc_cache) {

            address_space_cache_destroy(&indirect_desc_cache);

            VAR_7++;

        } else {

            VAR_7 = VAR_11;

        }

    }



    if (VAR_10 < 0) {

        goto err;

    }



done:

    address_space_cache_destroy(&indirect_desc_cache);

    if (VAR_1) {

        *VAR_1 = VAR_8;

    }

    if (VAR_2) {

        *VAR_2 = VAR_9;

    }

    rcu_read_unlock();

    return;



err:

    VAR_8 = VAR_9 = 0;

    goto done;

}

void FUNC_0(VirtQueue *VAR_0, unsigned int *VAR_1,
unsigned int *VAR_2,
unsigned VAR_3, unsigned VAR_4)
{ VirtIODevice *vdev = VAR_0->vdev; unsigned int VAR_5, VAR_6; unsigned int VAR_7, VAR_8, VAR_9; VRingMemoryRegionCaches *caches; MemoryRegionCache indirect_desc_cache = MEMORY_REGION_CACHE_INVALID; int64_t len = 0; int VAR_10; if (unlikely(!VAR_0->vring.desc)) { if (VAR_1) { *VAR_1 = 0; } if (VAR_2) { *VAR_2 = 0; } return; } rcu_read_lock(); VAR_6 = VAR_0->last_avail_idx; VAR_7 = VAR_8 = VAR_9 = 0; VAR_5 = VAR_0->vring.num; caches = atomic_rcu_read(&VAR_0->vring.caches); if (caches->desc.len < VAR_5 * sizeof(VRingDesc)) { virtio_error(vdev, "Cannot map descriptor ring"); goto err; } while ((VAR_10 = virtqueue_num_heads(VAR_0, VAR_6)) > 0) { MemoryRegionCache *desc_cache = &caches->desc; unsigned int VAR_11; VRingDesc desc; unsigned int VAR_12; VAR_11 = VAR_7; if (!virtqueue_get_head(VAR_0, VAR_6++, &VAR_12)) { goto err; } vring_desc_read(vdev, &desc, desc_cache, VAR_12); if (desc.flags & VRING_DESC_F_INDIRECT) { if (desc.len % sizeof(VRingDesc)) { virtio_error(vdev, "Invalid size for indirect buffer table"); goto err; } if (VAR_11 >= VAR_5) { virtio_error(vdev, "Looped descriptor"); goto err; } len = address_space_cache_init(&indirect_desc_cache,
vdev->dma_as,
desc.addr, desc.len, false); desc_cache = &indirect_desc_cache; if (len < desc.len) { virtio_error(vdev, "Cannot map indirect buffer"); goto err; } VAR_5 = desc.len / sizeof(VRingDesc); VAR_11 = VAR_12 = 0; vring_desc_read(vdev, &desc, desc_cache, VAR_12); } do { if (++VAR_11 > VAR_5) { virtio_error(vdev, "Looped descriptor"); goto err; } if (desc.flags & VRING_DESC_F_WRITE) { VAR_8 += desc.len; } else { VAR_9 += desc.len; } if (VAR_8 >= VAR_3 && VAR_9 >= VAR_4) { goto done; } VAR_10 = virtqueue_read_next_desc(vdev, &desc, desc_cache, VAR_5, &VAR_12); } while (VAR_10 == VIRTQUEUE_READ_DESC_MORE); if (VAR_10 == VIRTQUEUE_READ_DESC_ERROR) { goto err; } if (desc_cache == &indirect_desc_cache) { address_space_cache_destroy(&indirect_desc_cache); VAR_7++; } else { VAR_7 = VAR_11; } } if (VAR_10 < 0) { goto err; } done:
address_space_cache_destroy(&indirect_desc_cache); if (VAR_1) { *VAR_1 = VAR_8; } if (VAR_2) { *VAR_2 = VAR_9; } rcu_read_unlock(); return; err:
VAR_8 = VAR_9 = 0; goto done; }