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

Code before:
        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.advance_used_ring(mem, 1);
        Ok(())
    }

    /// Advance number of used descriptor heads by `n`.
    pub fn advance_used_ring<M: GuestMemory>(&mut self, mem: &M, n: u16) {
        self.num_added += Wrapping(n);
        self.next_used += Wrapping(n);

        // 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);
    }

    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,
        // }
        // We calculate offset into `ring` field.
        let used_ring_offset = std::mem::size_of::<u16>()
            + std::mem::size_of::<u16>()

Review comment (suggestion):
Please mention in the commit message why this now is getting a `u16` variable as an argument. I assume it is because in the next PR you will be calling this with something other than `1`.

Code after:
    }

    /// 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,
        // }
        // We calculate offset into `ring` field.
        let used_ring_offset = std::mem::size_of::<u16>()