Repository: firecracker-microvm/firecracker
File: src/vmm/src/devices/virtio/queue.rs (Rust)

Code before:
        &mut self,
        mem: &M,
        desc_index: u16,
        len: u32,
    ) -> Result<(), QueueError> {
        debug_assert!(self.is_layout_valid(mem));

        let next_used = self.next_used.0 % self.actual_size();
        self.write_used_ring(mem, next_used, desc_index, len)?;

        self.num_added += Wrapping(1);
        self.next_used += Wrapping(1);

        // This fence ensures all descriptor writes are visible before the index update is.
        fence(Ordering::Release);

        self.set_next_used(self.next_used.0, mem);
        Ok(())
    }

    fn write_used_ring<M: GuestMemory>(
        &self,
        mem: &M,
        index: u16,
        id: u16,
        len: u32,
    ) -> Result<(), QueueError> {
        if id >= self.actual_size() {
            error!(
                "attempted to add out of bounds descriptor to used ring: {}",
                id
            );
            return Err(QueueError::DescIndexOutOfBounds(id));
        }

        // Used ring has layout:
        // struct UsedRing {
        //     flags: u16,
        //     idx: u16,
        //     ring: [UsedElement; <queue size>],
        //     avail_event: u16,
        // }
        // We calculate offset into `ring` field.
        let used_ring_offset = std::mem::size_of::<u16>()
            + std::mem::size_of::<u16>()
            + std::mem::size_of::<UsedElement>() * usize::from(index);
        let used_element_address = self.used_ring.unchecked_add(usize_to_u64(used_ring_offset));
        let used_element = UsedElement {
            id: u32::from(id),
            len,
        };

Review comment (suggestion):
I would pass here a `UsedElement` type instead of the fields of it.

Code after:
    pub fn undo_pop(&mut self) {
        self.next_avail -= Wrapping(1);
    }

    /// Puts an available descriptor head into the used ring for use by the guest.
    pub fn add_used<M: GuestMemory>(
        &mut self,
        mem: &M,
        desc_index: u16,
        len: u32,
    ) -> Result<(), QueueError> {
        debug_assert!(self.is_layout_valid(mem));

        let next_used = self.next_used.0 % self.actual_size();
        let used_element = UsedElement {
            id: u32::from(desc_index),
            len,
        };
        self.write_used_ring(mem, next_used, used_element)?;

        self.num_added += Wrapping(1);
        self.next_used += Wrapping(1);

        // This fence ensures all descriptor writes are visible before the index update is.
        fence(Ordering::Release);

        self.set_used_ring_idx(self.next_used.0, mem);
        Ok(())
    }

    fn write_used_ring<M: GuestMemory>(
        &self,
        mem: &M,
        index: u16,
        used_element: UsedElement,
    ) -> Result<(), QueueError> {
        if used_element.id >= u32::from(self.actual_size()) {
            error!(
                "attempted to add out of bounds descriptor to used ring: {}",
                used_element.id
            );
            return Err(QueueError::DescIndexOutOfBounds(used_element.id));
        }

        // Used ring has layout:
        // struct UsedRing {
        //     flags: u16,
        //     idx: u16,
        //     ring: [UsedElement; <queue size>],
        //     avail_event: u16,
        // }