pub struct Virtqueue<'a, R: Copy> { /* private fields */ }
Expand description

A virtqueue of a virtio device.

R is used to store device-specific per-request data (like the request header or status byte) in memory shared with the device and is copied on completion. Don’t put things there that the device doesn’t have to access, in the interest of both security and performance.

Implementations§

Creates a new virtqueue in the passed memory buffer.

buf has to be memory that is visible for the device. It is used to store all descriptors, rings and device-specific per-request data for the queue.

Examples found in repository?
src/devices/virtio_blk.rs (line 289)
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
    pub fn setup_queues(
        transport: &mut VirtioBlkTransport,
        num_queues: usize,
        queue_size: u16,
    ) -> Result<Vec<Self>, Error> {
        if virtio_blk_max_queues(transport)? < num_queues {
            return Err(Error::new(
                ErrorKind::InvalidInput,
                "Too many queues requested",
            ));
        }

        let layout = VirtqueueLayout::new::<VirtioBlkReqBuf>(num_queues, queue_size as usize)?;
        let queues: Vec<_> = {
            // Not actually needless: must drop the borrow on the transport before alloc_queue_mem()
            #[allow(clippy::needless_collect)]
            let iova_translators: Vec<_> = iter::repeat_with(|| transport.iova_translator())
                .take(num_queues)
                .collect();

            let mem = transport.alloc_queue_mem(&layout)?;

            iova_translators
                .into_iter()
                .enumerate()
                .map(|(i, iova_translator)| {
                    let mem_queue = unsafe {
                        std::slice::from_raw_parts_mut(
                            &mut mem[i * layout.end_offset] as *mut u8,
                            layout.end_offset,
                        )
                    };
                    Virtqueue::new(iova_translator, mem_queue, queue_size)
                })
                .collect::<Result<_, _>>()?
        };
        transport.setup_queues(&queues)?;

        Ok(queues.into_iter().map(Self::new).collect())
    }

Returns the number of entries in each of the descriptor table and rings.

Examples found in repository?
src/devices/virtio_blk.rs (line 250)
249
250
251
252
253
254
    fn new(vq: Virtqueue<'a, VirtioBlkReqBuf>) -> Self {
        let queue_size = vq.queue_size().into();
        let req_contexts = iter::repeat_with(|| None).take(queue_size).collect();

        Self { vq, req_contexts }
    }

Returns a raw pointer to the start of the descriptor table.

Returns a raw pointer to the start of the available ring.

Returns a raw pointer to the start of the used ring.

Enqueues a new request.

prepare is a function or closure that gets a reference to the device-specific per-request data in its final location in the virtqueue memory and a FnMut to add virtio descriptors to the request. It can set up the per-request data as necessary and must add all descriptors needed for the request.

The parameters of the FnMut it received are the iovec describing the buffer to be added and a boolean from_dev that is true if this buffer is written by the device and false if it is read by the device.

Examples found in repository?
src/devices/virtio_blk.rs (lines 308-346)
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
    fn queue_request_full(
        &mut self,
        req_type: VirtioBlkReqType,
        offset: u64,
        buf: &[iovec],
        dwz_data: Option<DiscardWriteZeroesData>,
        context: C,
    ) -> Result<(), Error> {
        let lba = to_lba(offset)?;

        let desc_idx = self.vq.add_request(|req, add_desc| {
            *req = VirtioBlkReqBuf {
                header: VirtioBlkReqHeader::new(req_type, lba),
                status: 0,
                dwz_data: dwz_data.unwrap_or_default(),
            };

            add_desc(
                iovec {
                    iov_base: &mut req.header as *mut _ as *mut c_void,
                    iov_len: mem::size_of::<VirtioBlkReqHeader>(),
                },
                false,
            )?;

            if dwz_data.is_some() {
                add_desc(
                    iovec {
                        iov_base: &mut req.dwz_data as *mut _ as *mut c_void,
                        iov_len: mem::size_of::<DiscardWriteZeroesData>(),
                    },
                    false,
                )?;
            }

            for b in buf {
                add_desc(*b, req_type.is_from_dev())?;
            }

            add_desc(
                iovec {
                    iov_base: &mut req.status as *mut _ as *mut c_void,
                    iov_len: 1,
                },
                true,
            )?;

            Ok(())
        })?;

        let old = self.req_contexts[desc_idx as usize].replace(context);
        assert!(old.is_none());

        Ok(())
    }

Returns an iterator that returns all completed requests.

Examples found in repository?
src/devices/virtio_blk.rs (line 518)
516
517
518
519
520
521
    pub fn completions(&mut self) -> CompletionIter<'_, 'a, C> {
        CompletionIter {
            it: self.vq.completions(),
            req_contexts: &mut self.req_contexts,
        }
    }

Trait Implementations§

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.