From 95c98e9cd2ee3d8c7e2f13c636572ea91d0966a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Wed, 22 May 2024 13:21:18 +0200 Subject: [PATCH 1/7] fd: specify unspecified bits in file permissions --- src/fd/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/fd/mod.rs b/src/fd/mod.rs index a501d3ae83..5e366d0c1c 100644 --- a/src/fd/mod.rs +++ b/src/fd/mod.rs @@ -135,6 +135,8 @@ bitflags! { const S_IWOTH = 0o002; const S_IXOTH = 0o001; const S_IRWXO = 0o007; + // Allow bits unknown to us to be set externally. See bitflags documentation for further explanation. + const _ = !0; } } From 34ff76d1fcb689e4851764ffef6df3086d3fb7b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Thu, 16 May 2024 16:32:12 +0200 Subject: [PATCH 2/7] virtq: use `self: Rc` instead of taking a rc_self argument --- src/drivers/virtio/virtqueue/mod.rs | 280 +++++++++---------------- src/drivers/virtio/virtqueue/packed.rs | 2 +- src/drivers/virtio/virtqueue/split.rs | 2 +- 3 files changed, 104 insertions(+), 180 deletions(-) diff --git a/src/drivers/virtio/virtqueue/mod.rs b/src/drivers/virtio/virtqueue/mod.rs index 70fd3f2a2a..783d55f8bc 100644 --- a/src/drivers/virtio/virtqueue/mod.rs +++ b/src/drivers/virtio/virtqueue/mod.rs @@ -272,10 +272,7 @@ pub trait Virtq: VirtqPrivate { return Err(VirtqError::BufferSizeWrong(send_data.len())); } - let desc = match self - .mem_pool() - .pull_from_raw(Rc::clone(&self.mem_pool()), send_data) - { + let desc = match self.mem_pool().pull_from_raw(send_data) { Ok(desc) => desc, Err(vq_err) => return Err(vq_err), }; @@ -307,10 +304,7 @@ pub trait Virtq: VirtqPrivate { None => return Err(VirtqError::BufferSizeWrong(send_data.len())), }; - match self - .mem_pool() - .pull_from_raw(Rc::clone(&self.mem_pool()), next_slice) - { + match self.mem_pool().pull_from_raw(next_slice) { Ok(desc) => desc_lst.push(desc), Err(vq_err) => return Err(vq_err), }; @@ -346,12 +340,7 @@ pub trait Virtq: VirtqPrivate { None => return Err(VirtqError::BufferSizeWrong(send_data.len())), }; - desc_lst.push( - self.mem_pool().pull_from_raw_untracked( - Rc::clone(&self.mem_pool()), - next_slice, - ), - ); + desc_lst.push(self.mem_pool().pull_from_raw_untracked(next_slice)); // update the starting index for the next iteration index += usize::from(*byte); @@ -389,10 +378,7 @@ pub trait Virtq: VirtqPrivate { return Err(VirtqError::BufferSizeWrong(recv_data.len())); } - let desc = match self - .mem_pool() - .pull_from_raw(Rc::clone(&self.mem_pool()), recv_data) - { + let desc = match self.mem_pool().pull_from_raw(recv_data) { Ok(desc) => desc, Err(vq_err) => return Err(vq_err), }; @@ -424,10 +410,7 @@ pub trait Virtq: VirtqPrivate { None => return Err(VirtqError::BufferSizeWrong(recv_data.len())), }; - match self - .mem_pool() - .pull_from_raw(Rc::clone(&self.mem_pool()), next_slice) - { + match self.mem_pool().pull_from_raw(next_slice) { Ok(desc) => desc_lst.push(desc), Err(vq_err) => return Err(vq_err), }; @@ -463,12 +446,7 @@ pub trait Virtq: VirtqPrivate { None => return Err(VirtqError::BufferSizeWrong(recv_data.len())), }; - desc_lst.push( - self.mem_pool().pull_from_raw_untracked( - Rc::clone(&self.mem_pool()), - next_slice, - ), - ); + desc_lst.push(self.mem_pool().pull_from_raw_untracked(next_slice)); // update the starting index for the next iteration index += usize::from(*byte); @@ -506,10 +484,7 @@ pub trait Virtq: VirtqPrivate { return Err(VirtqError::BufferSizeWrong(send_data.len())); } - let send_desc = match self - .mem_pool() - .pull_from_raw(Rc::clone(&self.mem_pool()), send_data) - { + let send_desc = match self.mem_pool().pull_from_raw(send_data) { Ok(desc) => desc, Err(vq_err) => return Err(vq_err), }; @@ -519,10 +494,7 @@ pub trait Virtq: VirtqPrivate { return Err(VirtqError::BufferSizeWrong(recv_data.len())); } - let recv_desc = match self - .mem_pool() - .pull_from_raw(Rc::clone(&self.mem_pool()), recv_data) - { + let recv_desc = match self.mem_pool().pull_from_raw(recv_data) { Ok(desc) => desc, Err(vq_err) => return Err(vq_err), }; @@ -553,10 +525,7 @@ pub trait Virtq: VirtqPrivate { return Err(VirtqError::BufferSizeWrong(send_data.len())); } - let send_desc = match self - .mem_pool() - .pull_from_raw(Rc::clone(&self.mem_pool()), send_data) - { + let send_desc = match self.mem_pool().pull_from_raw(send_data) { Ok(desc) => desc, Err(vq_err) => return Err(vq_err), }; @@ -572,10 +541,7 @@ pub trait Virtq: VirtqPrivate { None => return Err(VirtqError::BufferSizeWrong(recv_data.len())), }; - match self - .mem_pool() - .pull_from_raw(Rc::clone(&self.mem_pool()), next_slice) - { + match self.mem_pool().pull_from_raw(next_slice) { Ok(desc) => recv_desc_lst.push(desc), Err(vq_err) => return Err(vq_err), }; @@ -616,10 +582,7 @@ pub trait Virtq: VirtqPrivate { None => return Err(VirtqError::BufferSizeWrong(send_data.len())), }; - match self - .mem_pool() - .pull_from_raw(Rc::clone(&self.mem_pool()), next_slice) - { + match self.mem_pool().pull_from_raw(next_slice) { Ok(desc) => send_desc_lst.push(desc), Err(vq_err) => return Err(vq_err), }; @@ -639,10 +602,7 @@ pub trait Virtq: VirtqPrivate { None => return Err(VirtqError::BufferSizeWrong(recv_data.len())), }; - match self - .mem_pool() - .pull_from_raw(Rc::clone(&self.mem_pool()), next_slice) - { + match self.mem_pool().pull_from_raw(next_slice) { Ok(desc) => recv_desc_lst.push(desc), Err(vq_err) => return Err(vq_err), }; @@ -683,10 +643,7 @@ pub trait Virtq: VirtqPrivate { None => return Err(VirtqError::BufferSizeWrong(send_data.len())), }; - match self - .mem_pool() - .pull_from_raw(Rc::clone(&self.mem_pool()), next_slice) - { + match self.mem_pool().pull_from_raw(next_slice) { Ok(desc) => send_desc_lst.push(desc), Err(vq_err) => return Err(vq_err), }; @@ -700,10 +657,7 @@ pub trait Virtq: VirtqPrivate { return Err(VirtqError::BufferSizeWrong(recv_data.len())); } - let recv_desc = match self - .mem_pool() - .pull_from_raw(Rc::clone(&self.mem_pool()), recv_data) - { + let recv_desc = match self.mem_pool().pull_from_raw(recv_data) { Ok(desc) => desc, Err(vq_err) => return Err(vq_err), }; @@ -740,12 +694,7 @@ pub trait Virtq: VirtqPrivate { None => return Err(VirtqError::BufferSizeWrong(send_data.len())), }; - send_desc_lst.push( - self.mem_pool().pull_from_raw_untracked( - Rc::clone(&self.mem_pool()), - next_slice, - ), - ); + send_desc_lst.push(self.mem_pool().pull_from_raw_untracked(next_slice)); // update the starting index for the next iteration index += usize::from(*byte); @@ -762,12 +711,7 @@ pub trait Virtq: VirtqPrivate { None => return Err(VirtqError::BufferSizeWrong(recv_data.len())), }; - recv_desc_lst.push( - self.mem_pool().pull_from_raw_untracked( - Rc::clone(&self.mem_pool()), - next_slice, - ), - ); + recv_desc_lst.push(self.mem_pool().pull_from_raw_untracked(next_slice)); // update the starting index for the next iteration index += usize::from(*byte); @@ -875,33 +819,31 @@ pub trait Virtq: VirtqPrivate { // Send buffer specified, No recv buffer (Some(spec), None) => { match spec { - BuffSpec::Single(size) => { - match self.mem_pool().pull(Rc::clone(&self.mem_pool()), size) { - Ok(desc) => { - let buffer = Buffer::Single { - desc_lst: vec![desc].into_boxed_slice(), - len: size.into(), - next_write: 0, - }; - - Ok(BufferToken { - send_buff: Some(buffer), - recv_buff: None, - vq: self.clone(), - ret_send: true, - ret_recv: false, - reusable: true, - }) - } - Err(vq_err) => Err(vq_err), + BuffSpec::Single(size) => match self.mem_pool().pull(size) { + Ok(desc) => { + let buffer = Buffer::Single { + desc_lst: vec![desc].into_boxed_slice(), + len: size.into(), + next_write: 0, + }; + + Ok(BufferToken { + send_buff: Some(buffer), + recv_buff: None, + vq: self.clone(), + ret_send: true, + ret_recv: false, + reusable: true, + }) } - } + Err(vq_err) => Err(vq_err), + }, BuffSpec::Multiple(size_lst) => { let mut desc_lst: Vec = Vec::with_capacity(size_lst.len()); let mut len = 0usize; for size in size_lst { - match self.mem_pool().pull(Rc::clone(&self.mem_pool()), *size) { + match self.mem_pool().pull(*size) { Ok(desc) => desc_lst.push(desc), Err(vq_err) => return Err(vq_err), } @@ -930,10 +872,7 @@ pub trait Virtq: VirtqPrivate { for size in size_lst { // As the indirect list does only consume one descriptor for the // control descriptor, the actual list is untracked - desc_lst.push( - self.mem_pool() - .pull_untracked(Rc::clone(&self.mem_pool()), *size), - ); + desc_lst.push(self.mem_pool().pull_untracked(*size)); len += usize::from(*size); } @@ -963,33 +902,31 @@ pub trait Virtq: VirtqPrivate { // No send buffer, recv buffer is specified (None, Some(spec)) => { match spec { - BuffSpec::Single(size) => { - match self.mem_pool().pull(Rc::clone(&self.mem_pool()), size) { - Ok(desc) => { - let buffer = Buffer::Single { - desc_lst: vec![desc].into_boxed_slice(), - len: size.into(), - next_write: 0, - }; - - Ok(BufferToken { - send_buff: None, - recv_buff: Some(buffer), - vq: self.clone(), - ret_send: false, - ret_recv: true, - reusable: true, - }) - } - Err(vq_err) => Err(vq_err), + BuffSpec::Single(size) => match self.mem_pool().pull(size) { + Ok(desc) => { + let buffer = Buffer::Single { + desc_lst: vec![desc].into_boxed_slice(), + len: size.into(), + next_write: 0, + }; + + Ok(BufferToken { + send_buff: None, + recv_buff: Some(buffer), + vq: self.clone(), + ret_send: false, + ret_recv: true, + reusable: true, + }) } - } + Err(vq_err) => Err(vq_err), + }, BuffSpec::Multiple(size_lst) => { let mut desc_lst: Vec = Vec::with_capacity(size_lst.len()); let mut len = 0usize; for size in size_lst { - match self.mem_pool().pull(Rc::clone(&self.mem_pool()), *size) { + match self.mem_pool().pull(*size) { Ok(desc) => desc_lst.push(desc), Err(vq_err) => return Err(vq_err), } @@ -1018,10 +955,7 @@ pub trait Virtq: VirtqPrivate { for size in size_lst { // As the indirect list does only consume one descriptor for the // control descriptor, the actual list is untracked - desc_lst.push( - self.mem_pool() - .pull_untracked(Rc::clone(&self.mem_pool()), *size), - ); + desc_lst.push(self.mem_pool().pull_untracked(*size)); len += usize::from(*size); } @@ -1052,25 +986,23 @@ pub trait Virtq: VirtqPrivate { (Some(send_spec), Some(recv_spec)) => { match (send_spec, recv_spec) { (BuffSpec::Single(send_size), BuffSpec::Single(recv_size)) => { - let send_buff = - match self.mem_pool().pull(Rc::clone(&self.mem_pool()), send_size) { - Ok(send_desc) => Some(Buffer::Single { - desc_lst: vec![send_desc].into_boxed_slice(), - len: send_size.into(), - next_write: 0, - }), - Err(vq_err) => return Err(vq_err), - }; + let send_buff = match self.mem_pool().pull(send_size) { + Ok(send_desc) => Some(Buffer::Single { + desc_lst: vec![send_desc].into_boxed_slice(), + len: send_size.into(), + next_write: 0, + }), + Err(vq_err) => return Err(vq_err), + }; - let recv_buff = - match self.mem_pool().pull(Rc::clone(&self.mem_pool()), recv_size) { - Ok(recv_desc) => Some(Buffer::Single { - desc_lst: vec![recv_desc].into_boxed_slice(), - len: recv_size.into(), - next_write: 0, - }), - Err(vq_err) => return Err(vq_err), - }; + let recv_buff = match self.mem_pool().pull(recv_size) { + Ok(recv_desc) => Some(Buffer::Single { + desc_lst: vec![recv_desc].into_boxed_slice(), + len: recv_size.into(), + next_write: 0, + }), + Err(vq_err) => return Err(vq_err), + }; Ok(BufferToken { send_buff, @@ -1082,22 +1014,21 @@ pub trait Virtq: VirtqPrivate { }) } (BuffSpec::Single(send_size), BuffSpec::Multiple(recv_size_lst)) => { - let send_buff = - match self.mem_pool().pull(Rc::clone(&self.mem_pool()), send_size) { - Ok(send_desc) => Some(Buffer::Single { - desc_lst: vec![send_desc].into_boxed_slice(), - len: send_size.into(), - next_write: 0, - }), - Err(vq_err) => return Err(vq_err), - }; + let send_buff = match self.mem_pool().pull(send_size) { + Ok(send_desc) => Some(Buffer::Single { + desc_lst: vec![send_desc].into_boxed_slice(), + len: send_size.into(), + next_write: 0, + }), + Err(vq_err) => return Err(vq_err), + }; let mut recv_desc_lst: Vec = Vec::with_capacity(recv_size_lst.len()); let mut recv_len = 0usize; for size in recv_size_lst { - match self.mem_pool().pull(Rc::clone(&self.mem_pool()), *size) { + match self.mem_pool().pull(*size) { Ok(desc) => recv_desc_lst.push(desc), Err(vq_err) => return Err(vq_err), } @@ -1124,7 +1055,7 @@ pub trait Virtq: VirtqPrivate { Vec::with_capacity(send_size_lst.len()); let mut send_len = 0usize; for size in send_size_lst { - match self.mem_pool().pull(Rc::clone(&self.mem_pool()), *size) { + match self.mem_pool().pull(*size) { Ok(desc) => send_desc_lst.push(desc), Err(vq_err) => return Err(vq_err), } @@ -1142,7 +1073,7 @@ pub trait Virtq: VirtqPrivate { let mut recv_len = 0usize; for size in recv_size_lst { - match self.mem_pool().pull(Rc::clone(&self.mem_pool()), *size) { + match self.mem_pool().pull(*size) { Ok(desc) => recv_desc_lst.push(desc), Err(vq_err) => return Err(vq_err), } @@ -1170,7 +1101,7 @@ pub trait Virtq: VirtqPrivate { let mut send_len = 0usize; for size in send_size_lst { - match self.mem_pool().pull(Rc::clone(&self.mem_pool()), *size) { + match self.mem_pool().pull(*size) { Ok(desc) => send_desc_lst.push(desc), Err(vq_err) => return Err(vq_err), } @@ -1183,15 +1114,14 @@ pub trait Virtq: VirtqPrivate { next_write: 0, }); - let recv_buff = - match self.mem_pool().pull(Rc::clone(&self.mem_pool()), recv_size) { - Ok(recv_desc) => Some(Buffer::Single { - desc_lst: vec![recv_desc].into_boxed_slice(), - len: recv_size.into(), - next_write: 0, - }), - Err(vq_err) => return Err(vq_err), - }; + let recv_buff = match self.mem_pool().pull(recv_size) { + Ok(recv_desc) => Some(Buffer::Single { + desc_lst: vec![recv_desc].into_boxed_slice(), + len: recv_size.into(), + next_write: 0, + }), + Err(vq_err) => return Err(vq_err), + }; Ok(BufferToken { send_buff, @@ -1210,10 +1140,7 @@ pub trait Virtq: VirtqPrivate { for size in send_size_lst { // As the indirect list does only consume one descriptor for the // control descriptor, the actual list is untracked - send_desc_lst.push( - self.mem_pool() - .pull_untracked(Rc::clone(&self.mem_pool()), *size), - ); + send_desc_lst.push(self.mem_pool().pull_untracked(*size)); send_len += usize::from(*size); } @@ -1224,10 +1151,7 @@ pub trait Virtq: VirtqPrivate { for size in recv_size_lst { // As the indirect list does only consume one descriptor for the // control descriptor, the actual list is untracked - recv_desc_lst.push( - self.mem_pool() - .pull_untracked(Rc::clone(&self.mem_pool()), *size), - ); + recv_desc_lst.push(self.mem_pool().pull_untracked(*size)); recv_len += usize::from(*size); } @@ -2714,7 +2638,7 @@ impl MemPool { /// /// * The descriptor will consume one element of the pool. /// * The referred to memory area will NOT be deallocated upon drop. - fn pull_from_raw(&self, rc_self: Rc, slice: &[u8]) -> Result { + fn pull_from_raw(self: Rc, slice: &[u8]) -> Result { // Zero sized descriptors are NOT allowed // This also prohibids a panic due to accessing wrong index below assert!(!slice.is_empty()); @@ -2739,7 +2663,7 @@ impl MemPool { _mem_len: slice.len(), id: Some(desc_id), dealloc: Dealloc::Not, - pool: rc_self, + pool: self.clone(), }) } @@ -2756,7 +2680,7 @@ impl MemPool { /// /// * The descriptor will consume one element of the pool. /// * The referred to memory area will NOT be deallocated upon drop. - fn pull_from_raw_untracked(&self, rc_self: Rc, slice: &[u8]) -> MemDescr { + fn pull_from_raw_untracked(self: Rc, slice: &[u8]) -> MemDescr { // Zero sized descriptors are NOT allowed // This also prohibids a panic due to accessing wrong index below assert!(!slice.is_empty()); @@ -2776,7 +2700,7 @@ impl MemPool { _mem_len: slice.len(), id: None, dealloc: Dealloc::Not, - pool: rc_self, + pool: self.clone(), } } @@ -2792,7 +2716,7 @@ impl MemPool { /// * First MemPool.pull -> MemDesc with id = 3 /// * Second MemPool.pull -> MemDesc with id = 100 /// * Third MemPool.pull -> MemDesc with id = 2, - fn pull(&self, rc_self: Rc, bytes: Bytes) -> Result { + fn pull(self: Rc, bytes: Bytes) -> Result { let id = match self.pool.borrow_mut().pop() { Some(id) => id, None => return Err(VirtqError::NoDescrAvail), @@ -2819,7 +2743,7 @@ impl MemPool { _mem_len, id: Some(id), dealloc: Dealloc::AsPage, - pool: rc_self, + pool: self.clone(), }) } @@ -2832,7 +2756,7 @@ impl MemPool { /// * First MemPool.pull -> MemDesc with id = 3 /// * Second MemPool.pull -> MemDesc with id = 100 /// * Third MemPool.pull -> MemDesc with id = 2, - fn pull_untracked(&self, rc_self: Rc, bytes: Bytes) -> MemDescr { + fn pull_untracked(self: Rc, bytes: Bytes) -> MemDescr { let len = bytes.0; // Allocate heap memory via a vec, leak and cast @@ -2854,7 +2778,7 @@ impl MemPool { _mem_len, id: None, dealloc: Dealloc::AsPage, - pool: rc_self, + pool: self.clone(), } } } diff --git a/src/drivers/virtio/virtqueue/packed.rs b/src/drivers/virtio/virtqueue/packed.rs index ae52c879f3..98a5314bdc 100644 --- a/src/drivers/virtio/virtqueue/packed.rs +++ b/src/drivers/virtio/virtqueue/packed.rs @@ -1208,7 +1208,7 @@ impl VirtqPrivate for PackedVq { None => return Err(VirtqError::BufferToLarge), }; - let ctrl_desc = match self.mem_pool.pull(Rc::clone(&self.mem_pool), sz_indrct_lst) { + let ctrl_desc = match self.mem_pool.clone().pull(sz_indrct_lst) { Ok(desc) => desc, Err(vq_err) => return Err(vq_err), }; diff --git a/src/drivers/virtio/virtqueue/split.rs b/src/drivers/virtio/virtqueue/split.rs index 3eb49be836..22dd08e27f 100644 --- a/src/drivers/virtio/virtqueue/split.rs +++ b/src/drivers/virtio/virtqueue/split.rs @@ -559,7 +559,7 @@ impl VirtqPrivate for SplitVq { None => return Err(VirtqError::BufferToLarge), }; - let ctrl_desc = match self.mem_pool.pull(Rc::clone(&self.mem_pool), sz_indrct_lst) { + let ctrl_desc = match self.mem_pool.clone().pull(sz_indrct_lst) { Ok(desc) => desc, Err(vq_err) => return Err(vq_err), }; From dba22133488be39a5df6a28c5591d710553be1c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Thu, 16 May 2024 17:30:26 +0200 Subject: [PATCH 3/7] virtq: don't allow splitting contigous buffers to multiple descriptors Remove the functionality in prep_transfer_from_raw for splitting a single buffer into multiple descriptors, as it does not have an advantage and complicates the method quite a bit. --- src/drivers/fs/virtio_fs.rs | 15 +- src/drivers/virtio/virtqueue/mod.rs | 624 ++++++------------------- src/drivers/virtio/virtqueue/packed.rs | 11 +- src/drivers/virtio/virtqueue/split.rs | 9 +- 4 files changed, 169 insertions(+), 490 deletions(-) diff --git a/src/drivers/fs/virtio_fs.rs b/src/drivers/fs/virtio_fs.rs index 2cfd472a5a..890b91b92b 100644 --- a/src/drivers/fs/virtio_fs.rs +++ b/src/drivers/fs/virtio_fs.rs @@ -15,7 +15,7 @@ use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg}; use crate::drivers::virtio::transport::pci::{ComCfg, IsrStatus, NotifCfg}; use crate::drivers::virtio::virtqueue::error::VirtqError; use crate::drivers::virtio::virtqueue::split::SplitVq; -use crate::drivers::virtio::virtqueue::{AsSliceU8, BuffSpec, Bytes, Virtq, VqIndex, VqSize}; +use crate::drivers::virtio::virtqueue::{AsSliceU8, BufferType, Virtq, VqIndex, VqSize}; use crate::fs::fuse::{self, FuseInterface}; /// A wrapper struct for the raw configuration structure. @@ -146,18 +146,11 @@ impl FuseInterface for VirtioFsDriver { cmd: &fuse::Cmd, rsp: &mut fuse::Rsp, ) -> Result<(), VirtqError> { - let send = ( - cmd.as_slice_u8(), - BuffSpec::Single(Bytes::new(cmd.len()).ok_or(VirtqError::BufferToLarge)?), - ); - let rsp_len = rsp.len(); - let recv = ( - rsp.as_slice_u8_mut(), - BuffSpec::Single(Bytes::new(rsp_len).ok_or(VirtqError::BufferToLarge)?), - ); + let send = cmd.as_slice_u8(); + let recv = rsp.as_slice_u8_mut(); let transfer_tkn = self.vqueues[1] .clone() - .prep_transfer_from_raw(Some(send), Some(recv)) + .prep_transfer_from_raw(Some(send), Some(recv), BufferType::Direct) .unwrap(); transfer_tkn.dispatch_blocking()?; Ok(()) diff --git a/src/drivers/virtio/virtqueue/mod.rs b/src/drivers/virtio/virtqueue/mod.rs index 783d55f8bc..f7739165b3 100644 --- a/src/drivers/virtio/virtqueue/mod.rs +++ b/src/drivers/virtio/virtqueue/mod.rs @@ -247,8 +247,9 @@ pub trait Virtq: VirtqPrivate { /// part via the recv argument. fn prep_transfer_from_raw( self: Rc, - send: Option<(&[u8], BuffSpec<'_>)>, - recv: Option<(&mut [u8], BuffSpec<'_>)>, + send: Option<&[u8]>, + recv: Option<&mut [u8]>, + buffer_type: BufferType, ) -> Result; /// The implementation of the method requires constraints that are incompatible with a trait object. @@ -256,502 +257,180 @@ pub trait Virtq: VirtqPrivate { /// of [Self::prep_buffer] inside the implementor. fn prep_transfer_from_raw_static( self: Rc, - send: Option<(&[u8], BuffSpec<'_>)>, - recv: Option<(&mut [u8], BuffSpec<'_>)>, + send: Option<&[u8]>, + recv: Option<&mut [u8]>, + buffer_type: BufferType, ) -> Result where Self: Sized + 'static, { match (send, recv) { (None, None) => Err(VirtqError::BufferNotSpecified), - (Some((send_data, send_spec)), None) => { - match send_spec { - BuffSpec::Single(size) => { - // Buffer must have the right size - if send_data.len() != size.into() { - return Err(VirtqError::BufferSizeWrong(send_data.len())); - } - - let desc = match self.mem_pool().pull_from_raw(send_data) { - Ok(desc) => desc, - Err(vq_err) => return Err(vq_err), - }; - - Ok(TransferToken { - buff_tkn: Some(BufferToken { - send_buff: Some(Buffer::Single { - desc_lst: vec![desc].into_boxed_slice(), - len: send_data.len(), - next_write: 0, - }), - recv_buff: None, - vq: self, - ret_send: false, - ret_recv: false, - reusable: false, - }), - await_queue: None, - }) - } - BuffSpec::Multiple(size_lst) => { - let mut desc_lst: Vec = Vec::with_capacity(size_lst.len()); - let mut index = 0usize; - - for byte in size_lst { - let end_index = index + usize::from(*byte); - let next_slice = match send_data.get(index..end_index) { - Some(slice) => slice, - None => return Err(VirtqError::BufferSizeWrong(send_data.len())), - }; - - match self.mem_pool().pull_from_raw(next_slice) { - Ok(desc) => desc_lst.push(desc), - Err(vq_err) => return Err(vq_err), - }; - - // update the starting index for the next iteration - index += usize::from(*byte); - } - - Ok(TransferToken { - buff_tkn: Some(BufferToken { - send_buff: Some(Buffer::Multiple { - desc_lst: desc_lst.into_boxed_slice(), - len: send_data.len(), - next_write: 0, - }), - recv_buff: None, - vq: self, - ret_send: false, - ret_recv: false, - reusable: false, - }), - await_queue: None, - }) - } - BuffSpec::Indirect(size_lst) => { - let mut desc_lst: Vec = Vec::with_capacity(size_lst.len()); - let mut index = 0usize; - - for byte in size_lst { - let end_index = index + usize::from(*byte); - let next_slice = match send_data.get(index..end_index) { - Some(slice) => slice, - None => return Err(VirtqError::BufferSizeWrong(send_data.len())), - }; - - desc_lst.push(self.mem_pool().pull_from_raw_untracked(next_slice)); - - // update the starting index for the next iteration - index += usize::from(*byte); - } - - let ctrl_desc = match self.create_indirect_ctrl(Some(&desc_lst), None) { - Ok(desc) => desc, - Err(vq_err) => return Err(vq_err), - }; + (Some(send_data), None) => match buffer_type { + BufferType::Direct => { + let desc = match self.mem_pool().pull_from_raw(send_data) { + Ok(desc) => desc, + Err(vq_err) => return Err(vq_err), + }; - Ok(TransferToken { - buff_tkn: Some(BufferToken { - send_buff: Some(Buffer::Indirect { - desc_lst: desc_lst.into_boxed_slice(), - ctrl_desc, - len: send_data.len(), - next_write: 0, - }), - recv_buff: None, - vq: self, - ret_send: false, - ret_recv: false, - reusable: false, + Ok(TransferToken { + buff_tkn: Some(BufferToken { + send_buff: Some(Buffer::Single { + desc_lst: vec![desc].into_boxed_slice(), + len: send_data.len(), + next_write: 0, }), - await_queue: None, - }) - } + recv_buff: None, + vq: self, + ret_send: false, + ret_recv: false, + reusable: false, + }), + await_queue: None, + }) } - } - (None, Some((recv_data, recv_spec))) => { - match recv_spec { - BuffSpec::Single(size) => { - // Buffer must have the right size - if recv_data.len() != size.into() { - return Err(VirtqError::BufferSizeWrong(recv_data.len())); - } + BufferType::Indirect => { + let desc_lst = vec![self.mem_pool().pull_from_raw_untracked(send_data)]; - let desc = match self.mem_pool().pull_from_raw(recv_data) { - Ok(desc) => desc, - Err(vq_err) => return Err(vq_err), - }; - - Ok(TransferToken { - buff_tkn: Some(BufferToken { - send_buff: None, - recv_buff: Some(Buffer::Single { - desc_lst: vec![desc].into_boxed_slice(), - len: recv_data.len(), - next_write: 0, - }), - vq: self, - ret_send: false, - ret_recv: false, - reusable: false, - }), - await_queue: None, - }) - } - BuffSpec::Multiple(size_lst) => { - let mut desc_lst: Vec = Vec::with_capacity(size_lst.len()); - let mut index = 0usize; - - for byte in size_lst { - let end_index = index + usize::from(*byte); - let next_slice = match recv_data.get(index..end_index) { - Some(slice) => slice, - None => return Err(VirtqError::BufferSizeWrong(recv_data.len())), - }; - - match self.mem_pool().pull_from_raw(next_slice) { - Ok(desc) => desc_lst.push(desc), - Err(vq_err) => return Err(vq_err), - }; - - // update the starting index for the next iteration - index += usize::from(*byte); - } + let ctrl_desc = match self.create_indirect_ctrl(Some(&desc_lst), None) { + Ok(desc) => desc, + Err(vq_err) => return Err(vq_err), + }; - Ok(TransferToken { - buff_tkn: Some(BufferToken { - send_buff: None, - recv_buff: Some(Buffer::Multiple { - desc_lst: desc_lst.into_boxed_slice(), - len: recv_data.len(), - next_write: 0, - }), - vq: self, - ret_send: false, - ret_recv: false, - reusable: false, + Ok(TransferToken { + buff_tkn: Some(BufferToken { + send_buff: Some(Buffer::Indirect { + desc_lst: desc_lst.into_boxed_slice(), + ctrl_desc, + len: send_data.len(), + next_write: 0, }), - await_queue: None, - }) - } - BuffSpec::Indirect(size_lst) => { - let mut desc_lst: Vec = Vec::with_capacity(size_lst.len()); - let mut index = 0usize; - - for byte in size_lst { - let end_index = index + usize::from(*byte); - let next_slice = match recv_data.get(index..end_index) { - Some(slice) => slice, - None => return Err(VirtqError::BufferSizeWrong(recv_data.len())), - }; - - desc_lst.push(self.mem_pool().pull_from_raw_untracked(next_slice)); - - // update the starting index for the next iteration - index += usize::from(*byte); - } - - let ctrl_desc = match self.create_indirect_ctrl(None, Some(&desc_lst)) { - Ok(desc) => desc, - Err(vq_err) => return Err(vq_err), - }; + recv_buff: None, + vq: self, + ret_send: false, + ret_recv: false, + reusable: false, + }), + await_queue: None, + }) + } + }, + (None, Some(recv_data)) => match buffer_type { + BufferType::Direct => { + let desc = match self.mem_pool().pull_from_raw(recv_data) { + Ok(desc) => desc, + Err(vq_err) => return Err(vq_err), + }; - Ok(TransferToken { - buff_tkn: Some(BufferToken { - send_buff: None, - recv_buff: Some(Buffer::Indirect { - desc_lst: desc_lst.into_boxed_slice(), - ctrl_desc, - len: recv_data.len(), - next_write: 0, - }), - vq: self, - ret_send: false, - ret_recv: false, - reusable: false, + Ok(TransferToken { + buff_tkn: Some(BufferToken { + send_buff: None, + recv_buff: Some(Buffer::Single { + desc_lst: vec![desc].into_boxed_slice(), + len: recv_data.len(), + next_write: 0, }), - await_queue: None, - }) - } + vq: self, + ret_send: false, + ret_recv: false, + reusable: false, + }), + await_queue: None, + }) } - } - (Some((send_data, send_spec)), Some((recv_data, recv_spec))) => { - match (send_spec, recv_spec) { - (BuffSpec::Single(send_size), BuffSpec::Single(recv_size)) => { - // Buffer must have the right size - if send_data.len() != send_size.into() { - return Err(VirtqError::BufferSizeWrong(send_data.len())); - } - - let send_desc = match self.mem_pool().pull_from_raw(send_data) { - Ok(desc) => desc, - Err(vq_err) => return Err(vq_err), - }; + BufferType::Indirect => { + let desc_lst = vec![self.mem_pool().pull_from_raw_untracked(recv_data)]; - // Buffer must have the right size - if recv_data.len() != recv_size.into() { - return Err(VirtqError::BufferSizeWrong(recv_data.len())); - } - - let recv_desc = match self.mem_pool().pull_from_raw(recv_data) { - Ok(desc) => desc, - Err(vq_err) => return Err(vq_err), - }; + let ctrl_desc = match self.create_indirect_ctrl(None, Some(&desc_lst)) { + Ok(desc) => desc, + Err(vq_err) => return Err(vq_err), + }; - Ok(TransferToken { - buff_tkn: Some(BufferToken { - send_buff: Some(Buffer::Single { - desc_lst: vec![send_desc].into_boxed_slice(), - len: send_data.len(), - next_write: 0, - }), - recv_buff: Some(Buffer::Single { - desc_lst: vec![recv_desc].into_boxed_slice(), - len: recv_data.len(), - next_write: 0, - }), - vq: self, - ret_send: false, - ret_recv: false, - reusable: false, + Ok(TransferToken { + buff_tkn: Some(BufferToken { + send_buff: None, + recv_buff: Some(Buffer::Indirect { + desc_lst: desc_lst.into_boxed_slice(), + ctrl_desc, + len: recv_data.len(), + next_write: 0, }), - await_queue: None, - }) - } - (BuffSpec::Single(send_size), BuffSpec::Multiple(recv_size_lst)) => { - // Buffer must have the right size - if send_data.len() != send_size.into() { - return Err(VirtqError::BufferSizeWrong(send_data.len())); - } - - let send_desc = match self.mem_pool().pull_from_raw(send_data) { - Ok(desc) => desc, - Err(vq_err) => return Err(vq_err), - }; - - let mut recv_desc_lst: Vec = - Vec::with_capacity(recv_size_lst.len()); - let mut index = 0usize; - - for byte in recv_size_lst { - let end_index = index + usize::from(*byte); - let next_slice = match recv_data.get(index..end_index) { - Some(slice) => slice, - None => return Err(VirtqError::BufferSizeWrong(recv_data.len())), - }; - - match self.mem_pool().pull_from_raw(next_slice) { - Ok(desc) => recv_desc_lst.push(desc), - Err(vq_err) => return Err(vq_err), - }; + vq: self, + ret_send: false, + ret_recv: false, + reusable: false, + }), + await_queue: None, + }) + } + }, + (Some(send_data), Some(recv_data)) => match buffer_type { + BufferType::Direct => { + let send_desc = match self.mem_pool().pull_from_raw(send_data) { + Ok(desc) => desc, + Err(vq_err) => return Err(vq_err), + }; - // update the starting index for the next iteration - index += usize::from(*byte); - } + let recv_desc = match self.mem_pool().pull_from_raw(recv_data) { + Ok(desc) => desc, + Err(vq_err) => return Err(vq_err), + }; - Ok(TransferToken { - buff_tkn: Some(BufferToken { - send_buff: Some(Buffer::Single { - desc_lst: vec![send_desc].into_boxed_slice(), - len: send_data.len(), - next_write: 0, - }), - recv_buff: Some(Buffer::Multiple { - desc_lst: recv_desc_lst.into_boxed_slice(), - len: recv_data.len(), - next_write: 0, - }), - vq: self, - ret_send: false, - ret_recv: false, - reusable: false, + Ok(TransferToken { + buff_tkn: Some(BufferToken { + send_buff: Some(Buffer::Single { + desc_lst: vec![send_desc].into_boxed_slice(), + len: send_data.len(), + next_write: 0, }), - await_queue: None, - }) - } - (BuffSpec::Multiple(send_size_lst), BuffSpec::Multiple(recv_size_lst)) => { - let mut send_desc_lst: Vec = - Vec::with_capacity(send_size_lst.len()); - let mut index = 0usize; - - for byte in send_size_lst { - let end_index = index + usize::from(*byte); - let next_slice = match send_data.get(index..end_index) { - Some(slice) => slice, - None => return Err(VirtqError::BufferSizeWrong(send_data.len())), - }; - - match self.mem_pool().pull_from_raw(next_slice) { - Ok(desc) => send_desc_lst.push(desc), - Err(vq_err) => return Err(vq_err), - }; - - // update the starting index for the next iteration - index += usize::from(*byte); - } - - let mut recv_desc_lst: Vec = - Vec::with_capacity(recv_size_lst.len()); - let mut index = 0usize; - - for byte in recv_size_lst { - let end_index = index + usize::from(*byte); - let next_slice = match recv_data.get(index..end_index) { - Some(slice) => slice, - None => return Err(VirtqError::BufferSizeWrong(recv_data.len())), - }; - - match self.mem_pool().pull_from_raw(next_slice) { - Ok(desc) => recv_desc_lst.push(desc), - Err(vq_err) => return Err(vq_err), - }; - - // update the starting index for the next iteration - index += usize::from(*byte); - } - - Ok(TransferToken { - buff_tkn: Some(BufferToken { - send_buff: Some(Buffer::Multiple { - desc_lst: send_desc_lst.into_boxed_slice(), - len: send_data.len(), - next_write: 0, - }), - recv_buff: Some(Buffer::Multiple { - desc_lst: recv_desc_lst.into_boxed_slice(), - len: recv_data.len(), - next_write: 0, - }), - vq: self, - ret_send: false, - ret_recv: false, - reusable: false, + recv_buff: Some(Buffer::Single { + desc_lst: vec![recv_desc].into_boxed_slice(), + len: recv_data.len(), + next_write: 0, }), - await_queue: None, - }) - } - (BuffSpec::Multiple(send_size_lst), BuffSpec::Single(recv_size)) => { - let mut send_desc_lst: Vec = - Vec::with_capacity(send_size_lst.len()); - let mut index = 0usize; - - for byte in send_size_lst { - let end_index = index + usize::from(*byte); - let next_slice = match send_data.get(index..end_index) { - Some(slice) => slice, - None => return Err(VirtqError::BufferSizeWrong(send_data.len())), - }; - - match self.mem_pool().pull_from_raw(next_slice) { - Ok(desc) => send_desc_lst.push(desc), - Err(vq_err) => return Err(vq_err), - }; - - // update the starting index for the next iteration - index += usize::from(*byte); - } + vq: self, + ret_send: false, + ret_recv: false, + reusable: false, + }), + await_queue: None, + }) + } + BufferType::Indirect => { + let send_desc_lst = vec![self.mem_pool().pull_from_raw_untracked(send_data)]; - // Buffer must have the right size - if recv_data.len() != recv_size.into() { - return Err(VirtqError::BufferSizeWrong(recv_data.len())); - } + let recv_desc_lst = vec![self.mem_pool().pull_from_raw_untracked(recv_data)]; - let recv_desc = match self.mem_pool().pull_from_raw(recv_data) { - Ok(desc) => desc, - Err(vq_err) => return Err(vq_err), - }; + let ctrl_desc = match self + .create_indirect_ctrl(Some(&send_desc_lst), Some(&recv_desc_lst)) + { + Ok(desc) => desc, + Err(vq_err) => return Err(vq_err), + }; - Ok(TransferToken { - buff_tkn: Some(BufferToken { - send_buff: Some(Buffer::Multiple { - desc_lst: send_desc_lst.into_boxed_slice(), - len: send_data.len(), - next_write: 0, - }), - recv_buff: Some(Buffer::Single { - desc_lst: vec![recv_desc].into_boxed_slice(), - len: recv_data.len(), - next_write: 0, - }), - vq: self, - ret_send: false, - ret_recv: false, - reusable: false, + Ok(TransferToken { + buff_tkn: Some(BufferToken { + recv_buff: Some(Buffer::Indirect { + desc_lst: recv_desc_lst.into_boxed_slice(), + ctrl_desc: ctrl_desc.no_dealloc_clone(), + len: recv_data.len(), + next_write: 0, }), - await_queue: None, - }) - } - (BuffSpec::Indirect(send_size_lst), BuffSpec::Indirect(recv_size_lst)) => { - let mut send_desc_lst: Vec = - Vec::with_capacity(send_size_lst.len()); - let mut index = 0usize; - - for byte in send_size_lst { - let end_index = index + usize::from(*byte); - let next_slice = match send_data.get(index..end_index) { - Some(slice) => slice, - None => return Err(VirtqError::BufferSizeWrong(send_data.len())), - }; - - send_desc_lst.push(self.mem_pool().pull_from_raw_untracked(next_slice)); - - // update the starting index for the next iteration - index += usize::from(*byte); - } - - let mut recv_desc_lst: Vec = - Vec::with_capacity(recv_size_lst.len()); - let mut index = 0usize; - - for byte in recv_size_lst { - let end_index = index + usize::from(*byte); - let next_slice = match recv_data.get(index..end_index) { - Some(slice) => slice, - None => return Err(VirtqError::BufferSizeWrong(recv_data.len())), - }; - - recv_desc_lst.push(self.mem_pool().pull_from_raw_untracked(next_slice)); - - // update the starting index for the next iteration - index += usize::from(*byte); - } - - let ctrl_desc = match self - .create_indirect_ctrl(Some(&send_desc_lst), Some(&recv_desc_lst)) - { - Ok(desc) => desc, - Err(vq_err) => return Err(vq_err), - }; - - Ok(TransferToken { - buff_tkn: Some(BufferToken { - recv_buff: Some(Buffer::Indirect { - desc_lst: recv_desc_lst.into_boxed_slice(), - ctrl_desc: ctrl_desc.no_dealloc_clone(), - len: recv_data.len(), - next_write: 0, - }), - send_buff: Some(Buffer::Indirect { - desc_lst: send_desc_lst.into_boxed_slice(), - ctrl_desc, - len: send_data.len(), - next_write: 0, - }), - vq: self, - ret_send: false, - ret_recv: false, - reusable: false, + send_buff: Some(Buffer::Indirect { + desc_lst: send_desc_lst.into_boxed_slice(), + ctrl_desc, + len: send_data.len(), + next_write: 0, }), - await_queue: None, - }) - } - (BuffSpec::Indirect(_), BuffSpec::Single(_)) - | (BuffSpec::Indirect(_), BuffSpec::Multiple(_)) => Err(VirtqError::BufferInWithDirect), - (BuffSpec::Single(_), BuffSpec::Indirect(_)) - | (BuffSpec::Multiple(_), BuffSpec::Indirect(_)) => Err(VirtqError::BufferInWithDirect), + vq: self, + ret_send: false, + ret_recv: false, + reusable: false, + }), + await_queue: None, + }) } - } + }, } } @@ -2191,6 +1870,11 @@ impl BufferToken { } } +pub enum BufferType { + Direct, + Indirect, +} + /// Describes the type of a buffer and unifies them. enum Buffer { /// A buffer consisting of a single [Memory Descriptor](MemDescr). diff --git a/src/drivers/virtio/virtqueue/packed.rs b/src/drivers/virtio/virtqueue/packed.rs index 98a5314bdc..52b7be4149 100644 --- a/src/drivers/virtio/virtqueue/packed.rs +++ b/src/drivers/virtio/virtqueue/packed.rs @@ -18,8 +18,8 @@ use super::super::transport::mmio::{ComCfg, NotifCfg, NotifCtrl}; use super::super::transport::pci::{ComCfg, NotifCfg, NotifCtrl}; use super::error::VirtqError; use super::{ - BuffSpec, Buffer, BufferToken, Bytes, DescrFlags, MemDescr, MemPool, TransferToken, Virtq, - VirtqPrivate, VqIndex, VqSize, + BuffSpec, Buffer, BufferToken, BufferType, Bytes, DescrFlags, MemDescr, MemPool, TransferToken, + Virtq, VirtqPrivate, VqIndex, VqSize, }; use crate::arch::mm::paging::{BasePageSize, PageSize}; use crate::arch::mm::{paging, VirtAddr}; @@ -1166,10 +1166,11 @@ impl Virtq for PackedVq { fn prep_transfer_from_raw( self: Rc, - send: Option<(&[u8], BuffSpec<'_>)>, - recv: Option<(&mut [u8], BuffSpec<'_>)>, + send: Option<&[u8]>, + recv: Option<&mut [u8]>, + buffer_type: BufferType, ) -> Result { - self.prep_transfer_from_raw_static(send, recv) + self.prep_transfer_from_raw_static(send, recv, buffer_type) } fn prep_buffer( diff --git a/src/drivers/virtio/virtqueue/split.rs b/src/drivers/virtio/virtqueue/split.rs index 22dd08e27f..92e4dbc0df 100644 --- a/src/drivers/virtio/virtqueue/split.rs +++ b/src/drivers/virtio/virtqueue/split.rs @@ -20,7 +20,7 @@ use super::super::transport::mmio::{ComCfg, NotifCfg, NotifCtrl}; use super::super::transport::pci::{ComCfg, NotifCfg, NotifCtrl}; use super::error::VirtqError; use super::{ - BuffSpec, BufferToken, Bytes, DescrFlags, MemDescr, MemPool, TransferToken, Virtq, + BuffSpec, BufferToken, BufferType, Bytes, DescrFlags, MemDescr, MemPool, TransferToken, Virtq, VirtqPrivate, VqIndex, VqSize, }; use crate::arch::memory_barrier; @@ -521,10 +521,11 @@ impl Virtq for SplitVq { fn prep_transfer_from_raw( self: Rc, - send: Option<(&[u8], BuffSpec<'_>)>, - recv: Option<(&mut [u8], BuffSpec<'_>)>, + send: Option<&[u8]>, + recv: Option<&mut [u8]>, + buffer_type: BufferType, ) -> Result { - self.prep_transfer_from_raw_static(send, recv) + self.prep_transfer_from_raw_static(send, recv, buffer_type) } fn prep_buffer( From f6bd10e21377f246980649d2cf2cc962c9680252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Thu, 16 May 2024 18:47:46 +0200 Subject: [PATCH 4/7] virtq: match on individual enums rather than their combinations Match cases made out of combinations cause a lot of code duplication. --- src/drivers/virtio/virtqueue/mod.rs | 241 +++++++++------------------- 1 file changed, 80 insertions(+), 161 deletions(-) diff --git a/src/drivers/virtio/virtqueue/mod.rs b/src/drivers/virtio/virtqueue/mod.rs index f7739165b3..1b28c09f58 100644 --- a/src/drivers/virtio/virtqueue/mod.rs +++ b/src/drivers/virtio/virtqueue/mod.rs @@ -264,174 +264,93 @@ pub trait Virtq: VirtqPrivate { where Self: Sized + 'static, { - match (send, recv) { - (None, None) => Err(VirtqError::BufferNotSpecified), - (Some(send_data), None) => match buffer_type { - BufferType::Direct => { - let desc = match self.mem_pool().pull_from_raw(send_data) { - Ok(desc) => desc, - Err(vq_err) => return Err(vq_err), - }; - - Ok(TransferToken { - buff_tkn: Some(BufferToken { - send_buff: Some(Buffer::Single { - desc_lst: vec![desc].into_boxed_slice(), - len: send_data.len(), - next_write: 0, - }), - recv_buff: None, - vq: self, - ret_send: false, - ret_recv: false, - reusable: false, - }), - await_queue: None, - }) - } - BufferType::Indirect => { - let desc_lst = vec![self.mem_pool().pull_from_raw_untracked(send_data)]; - - let ctrl_desc = match self.create_indirect_ctrl(Some(&desc_lst), None) { - Ok(desc) => desc, - Err(vq_err) => return Err(vq_err), - }; - - Ok(TransferToken { - buff_tkn: Some(BufferToken { - send_buff: Some(Buffer::Indirect { - desc_lst: desc_lst.into_boxed_slice(), - ctrl_desc, - len: send_data.len(), - next_write: 0, - }), - recv_buff: None, - vq: self, - ret_send: false, - ret_recv: false, - reusable: false, - }), - await_queue: None, - }) - } - }, - (None, Some(recv_data)) => match buffer_type { - BufferType::Direct => { - let desc = match self.mem_pool().pull_from_raw(recv_data) { - Ok(desc) => desc, - Err(vq_err) => return Err(vq_err), - }; + if let (None, None) = (&send, &recv) { + return Err(VirtqError::BufferNotSpecified); + } - Ok(TransferToken { - buff_tkn: Some(BufferToken { - send_buff: None, - recv_buff: Some(Buffer::Single { - desc_lst: vec![desc].into_boxed_slice(), - len: recv_data.len(), - next_write: 0, - }), - vq: self, - ret_send: false, - ret_recv: false, - reusable: false, - }), - await_queue: None, + let send_buff; + let recv_buff; + match buffer_type { + BufferType::Direct => { + send_buff = if let Some(send_data) = send { + Some(Buffer::Single { + desc_lst: vec![self.mem_pool().pull_from_raw(send_data)?] + .into_boxed_slice(), + len: send_data.len(), + next_write: 0, }) - } - BufferType::Indirect => { - let desc_lst = vec![self.mem_pool().pull_from_raw_untracked(recv_data)]; - - let ctrl_desc = match self.create_indirect_ctrl(None, Some(&desc_lst)) { - Ok(desc) => desc, - Err(vq_err) => return Err(vq_err), - }; - - Ok(TransferToken { - buff_tkn: Some(BufferToken { - send_buff: None, - recv_buff: Some(Buffer::Indirect { - desc_lst: desc_lst.into_boxed_slice(), - ctrl_desc, - len: recv_data.len(), - next_write: 0, - }), - vq: self, - ret_send: false, - ret_recv: false, - reusable: false, - }), - await_queue: None, + } else { + None + }; + + recv_buff = if let Some(recv_data) = recv { + Some(Buffer::Single { + desc_lst: vec![self.mem_pool().pull_from_raw(recv_data)?] + .into_boxed_slice(), + len: recv_data.len(), + next_write: 0, }) + } else { + None } - }, - (Some(send_data), Some(recv_data)) => match buffer_type { - BufferType::Direct => { - let send_desc = match self.mem_pool().pull_from_raw(send_data) { - Ok(desc) => desc, - Err(vq_err) => return Err(vq_err), - }; - - let recv_desc = match self.mem_pool().pull_from_raw(recv_data) { - Ok(desc) => desc, - Err(vq_err) => return Err(vq_err), - }; - - Ok(TransferToken { - buff_tkn: Some(BufferToken { - send_buff: Some(Buffer::Single { - desc_lst: vec![send_desc].into_boxed_slice(), - len: send_data.len(), - next_write: 0, - }), - recv_buff: Some(Buffer::Single { - desc_lst: vec![recv_desc].into_boxed_slice(), - len: recv_data.len(), - next_write: 0, - }), - vq: self, - ret_send: false, - ret_recv: false, - reusable: false, - }), - await_queue: None, - }) + } + BufferType::Indirect => { + let send_desc_lst = send + .as_ref() + .map(|send_data| vec![self.mem_pool().pull_from_raw_untracked(send_data)]); + let recv_desc_lst = recv + .as_ref() + .map(|recv_data| vec![self.mem_pool().pull_from_raw_untracked(recv_data)]); + + let ctrl_desc = + self.create_indirect_ctrl(send_desc_lst.as_ref(), recv_desc_lst.as_ref())?; + + let mut send_ctrl_desc = None; + let mut recv_ctrl_desc = None; + match (&send, &recv) { + (Some(_), None) => { + send_ctrl_desc = Some(ctrl_desc); + } + (None, Some(_)) => { + recv_ctrl_desc = Some(ctrl_desc); + } + (Some(_), Some(_)) => { + send_ctrl_desc = Some(ctrl_desc.no_dealloc_clone()); + recv_ctrl_desc = Some(ctrl_desc); + } + // We have already checked at the beginning of the function + (None, None) => unreachable!(), } - BufferType::Indirect => { - let send_desc_lst = vec![self.mem_pool().pull_from_raw_untracked(send_data)]; - let recv_desc_lst = vec![self.mem_pool().pull_from_raw_untracked(recv_data)]; - - let ctrl_desc = match self - .create_indirect_ctrl(Some(&send_desc_lst), Some(&recv_desc_lst)) - { - Ok(desc) => desc, - Err(vq_err) => return Err(vq_err), - }; + send_buff = send.map(|send_data| Buffer::Indirect { + // If send is Some, so is send_desc_lst + desc_lst: send_desc_lst.unwrap().into_boxed_slice(), + ctrl_desc: send_ctrl_desc.unwrap(), + len: send_data.len(), + next_write: 0, + }); + + recv_buff = recv.map(|recv_data| Buffer::Indirect { + // If recv is Some, so is recv_desc_lst + desc_lst: recv_desc_lst.unwrap().into_boxed_slice(), + ctrl_desc: recv_ctrl_desc.unwrap(), + len: recv_data.len(), + next_write: 0, + }); + } + }; - Ok(TransferToken { - buff_tkn: Some(BufferToken { - recv_buff: Some(Buffer::Indirect { - desc_lst: recv_desc_lst.into_boxed_slice(), - ctrl_desc: ctrl_desc.no_dealloc_clone(), - len: recv_data.len(), - next_write: 0, - }), - send_buff: Some(Buffer::Indirect { - desc_lst: send_desc_lst.into_boxed_slice(), - ctrl_desc, - len: send_data.len(), - next_write: 0, - }), - vq: self, - ret_send: false, - ret_recv: false, - reusable: false, - }), - await_queue: None, - }) - } - }, - } + Ok(TransferToken { + buff_tkn: Some(BufferToken { + recv_buff, + send_buff, + vq: self, + ret_send: false, + ret_recv: false, + reusable: false, + }), + await_queue: None, + }) } /// Provides the calley with empty buffers as specified via the `send` and `recv` function parameters, (see [BuffSpec]), in form of From 65cbb173f7963fa16e37c128726afa0d008a26df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Fri, 17 May 2024 12:31:09 +0200 Subject: [PATCH 5/7] virtq: allow providing multiple slices to from-raw transfers This will allow providing transfer data that has an unsized field as a pair of sized and unsized objects, rather than having to create the whole transfer as a dynamically-sized object, as is the case in virtiofs. --- src/drivers/fs/virtio_fs.rs | 2 +- src/drivers/virtio/virtqueue/mod.rs | 118 +++++++++++++++---------- src/drivers/virtio/virtqueue/packed.rs | 4 +- src/drivers/virtio/virtqueue/split.rs | 4 +- 4 files changed, 78 insertions(+), 50 deletions(-) diff --git a/src/drivers/fs/virtio_fs.rs b/src/drivers/fs/virtio_fs.rs index 890b91b92b..7273316eea 100644 --- a/src/drivers/fs/virtio_fs.rs +++ b/src/drivers/fs/virtio_fs.rs @@ -150,7 +150,7 @@ impl FuseInterface for VirtioFsDriver { let recv = rsp.as_slice_u8_mut(); let transfer_tkn = self.vqueues[1] .clone() - .prep_transfer_from_raw(Some(send), Some(recv), BufferType::Direct) + .prep_transfer_from_raw(&[send], &[recv], BufferType::Direct) .unwrap(); transfer_tkn.dispatch_blocking()?; Ok(()) diff --git a/src/drivers/virtio/virtqueue/mod.rs b/src/drivers/virtio/virtqueue/mod.rs index 1b28c09f58..d5837a354e 100644 --- a/src/drivers/virtio/virtqueue/mod.rs +++ b/src/drivers/virtio/virtqueue/mod.rs @@ -247,8 +247,8 @@ pub trait Virtq: VirtqPrivate { /// part via the recv argument. fn prep_transfer_from_raw( self: Rc, - send: Option<&[u8]>, - recv: Option<&mut [u8]>, + send: &[&[u8]], + recv: &[&mut [u8]], buffer_type: BufferType, ) -> Result; @@ -257,37 +257,46 @@ pub trait Virtq: VirtqPrivate { /// of [Self::prep_buffer] inside the implementor. fn prep_transfer_from_raw_static( self: Rc, - send: Option<&[u8]>, - recv: Option<&mut [u8]>, + send: &[&[u8]], + recv: &[&mut [u8]], buffer_type: BufferType, ) -> Result where Self: Sized + 'static, { - if let (None, None) = (&send, &recv) { + if send.is_empty() && recv.is_empty() { return Err(VirtqError::BufferNotSpecified); } + let total_send_len = send.iter().map(|slice| slice.len()).sum(); + let total_recv_len = recv.iter().map(|slice| slice.len()).sum(); + let send_buff; let recv_buff; match buffer_type { BufferType::Direct => { - send_buff = if let Some(send_data) = send { - Some(Buffer::Single { - desc_lst: vec![self.mem_pool().pull_from_raw(send_data)?] - .into_boxed_slice(), - len: send_data.len(), + let send_desc_lst = send + .iter() + .map(|slice| self.mem_pool().pull_from_raw(slice)) + .collect::, VirtqError>>()?; + send_buff = if !send.is_empty() { + Some(Buffer::Multiple { + desc_lst: send_desc_lst.into_boxed_slice(), + len: total_send_len, next_write: 0, }) } else { None }; - recv_buff = if let Some(recv_data) = recv { - Some(Buffer::Single { - desc_lst: vec![self.mem_pool().pull_from_raw(recv_data)?] - .into_boxed_slice(), - len: recv_data.len(), + let recv_desc_lst: Vec<_> = recv + .iter() + .map(|slice| self.mem_pool().pull_from_raw(slice)) + .collect::, VirtqError>>()?; + recv_buff = if !recv.is_empty() { + Some(Buffer::Multiple { + desc_lst: recv_desc_lst.into_boxed_slice(), + len: total_recv_len, next_write: 0, }) } else { @@ -295,48 +304,67 @@ pub trait Virtq: VirtqPrivate { } } BufferType::Indirect => { - let send_desc_lst = send - .as_ref() - .map(|send_data| vec![self.mem_pool().pull_from_raw_untracked(send_data)]); - let recv_desc_lst = recv - .as_ref() - .map(|recv_data| vec![self.mem_pool().pull_from_raw_untracked(recv_data)]); - - let ctrl_desc = - self.create_indirect_ctrl(send_desc_lst.as_ref(), recv_desc_lst.as_ref())?; + let send_desc_lst: Vec<_> = send + .iter() + .map(|slice| self.mem_pool().pull_from_raw_untracked(slice)) + .collect(); + let recv_desc_lst: Vec<_> = recv + .iter() + .map(|slice| self.mem_pool().pull_from_raw_untracked(slice)) + .collect(); + + let ctrl_desc = self.create_indirect_ctrl( + if !send.is_empty() { + Some(&send_desc_lst) + } else { + None + }, + if !recv.is_empty() { + Some(&recv_desc_lst) + } else { + None + }, + )?; let mut send_ctrl_desc = None; let mut recv_ctrl_desc = None; - match (&send, &recv) { - (Some(_), None) => { + match (!send.is_empty(), !recv.is_empty()) { + (true, false) => { send_ctrl_desc = Some(ctrl_desc); } - (None, Some(_)) => { + (false, true) => { recv_ctrl_desc = Some(ctrl_desc); } - (Some(_), Some(_)) => { + // Both send and recv have content + (true, true) => { send_ctrl_desc = Some(ctrl_desc.no_dealloc_clone()); recv_ctrl_desc = Some(ctrl_desc); } - // We have already checked at the beginning of the function - (None, None) => unreachable!(), + // We checked at the beginning of the function. + (false, false) => unreachable!(), } - send_buff = send.map(|send_data| Buffer::Indirect { - // If send is Some, so is send_desc_lst - desc_lst: send_desc_lst.unwrap().into_boxed_slice(), - ctrl_desc: send_ctrl_desc.unwrap(), - len: send_data.len(), - next_write: 0, - }); - - recv_buff = recv.map(|recv_data| Buffer::Indirect { - // If recv is Some, so is recv_desc_lst - desc_lst: recv_desc_lst.unwrap().into_boxed_slice(), - ctrl_desc: recv_ctrl_desc.unwrap(), - len: recv_data.len(), - next_write: 0, - }); + send_buff = if !send.is_empty() { + Some(Buffer::Indirect { + desc_lst: send_desc_lst.into_boxed_slice(), + ctrl_desc: send_ctrl_desc.unwrap(), + len: total_send_len, + next_write: 0, + }) + } else { + None + }; + + recv_buff = if !recv.is_empty() { + Some(Buffer::Indirect { + desc_lst: recv_desc_lst.into_boxed_slice(), + ctrl_desc: recv_ctrl_desc.unwrap(), + len: total_recv_len, + next_write: 0, + }) + } else { + None + }; } }; diff --git a/src/drivers/virtio/virtqueue/packed.rs b/src/drivers/virtio/virtqueue/packed.rs index 52b7be4149..4273f60e88 100644 --- a/src/drivers/virtio/virtqueue/packed.rs +++ b/src/drivers/virtio/virtqueue/packed.rs @@ -1166,8 +1166,8 @@ impl Virtq for PackedVq { fn prep_transfer_from_raw( self: Rc, - send: Option<&[u8]>, - recv: Option<&mut [u8]>, + send: &[&[u8]], + recv: &[&mut [u8]], buffer_type: BufferType, ) -> Result { self.prep_transfer_from_raw_static(send, recv, buffer_type) diff --git a/src/drivers/virtio/virtqueue/split.rs b/src/drivers/virtio/virtqueue/split.rs index 92e4dbc0df..e121fb596f 100644 --- a/src/drivers/virtio/virtqueue/split.rs +++ b/src/drivers/virtio/virtqueue/split.rs @@ -521,8 +521,8 @@ impl Virtq for SplitVq { fn prep_transfer_from_raw( self: Rc, - send: Option<&[u8]>, - recv: Option<&mut [u8]>, + send: &[&[u8]], + recv: &[&mut [u8]], buffer_type: BufferType, ) -> Result { self.prep_transfer_from_raw_static(send, recv, buffer_type) From 58da42656a910a913605ecac7119a3f0f6c41b35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Fri, 17 May 2024 13:20:13 +0200 Subject: [PATCH 6/7] fuse: move common path calculation to function and simplify --- src/fs/fuse.rs | 153 +++++++------------------------------------------ 1 file changed, 20 insertions(+), 133 deletions(-) diff --git a/src/fs/fuse.rs b/src/fs/fuse.rs index 88eecdad3f..65e91e0eaf 100644 --- a/src/fs/fuse.rs +++ b/src/fs/fuse.rs @@ -973,6 +973,19 @@ impl FuseDirectory { }, } } + + fn traversal_path(&self, components: &[&str]) -> String { + let prefix_deref = self.prefix.as_deref(); + let components_with_prefix = prefix_deref.iter().chain(components.iter().rev()); + let path: String = components_with_prefix + .flat_map(|component| ["/", component]) + .collect(); + if path.is_empty() { + String::from("/") + } else { + path + } + } } impl VfsNode for FuseDirectory { @@ -990,25 +1003,7 @@ impl VfsNode for FuseDirectory { } fn traverse_readdir(&self, components: &mut Vec<&str>) -> Result, IoError> { - let path: String = if components.is_empty() { - if let Some(prefix) = &self.prefix { - "/".to_string() + prefix - } else { - "/".to_string() - } - } else { - let path: String = components - .iter() - .rev() - .map(|v| "/".to_owned() + v) - .collect(); - - if let Some(prefix) = &self.prefix { - "/".to_owned() + &prefix.to_owned() + &path - } else { - path - } - }; + let path: String = self.traversal_path(components); debug!("FUSE opendir: {}", path); @@ -1087,25 +1082,7 @@ impl VfsNode for FuseDirectory { } fn traverse_stat(&self, components: &mut Vec<&str>) -> Result { - let path: String = if components.is_empty() { - if let Some(prefix) = &self.prefix { - "/".to_string() + prefix - } else { - "/".to_string() - } - } else { - let path: String = components - .iter() - .rev() - .map(|v| "/".to_owned() + v) - .collect(); - - if let Some(prefix) = &self.prefix { - "/".to_owned() + &prefix.to_owned() + &path - } else { - path - } - }; + let path: String = self.traversal_path(components); debug!("FUSE stat: {}", path); @@ -1134,25 +1111,7 @@ impl VfsNode for FuseDirectory { } fn traverse_lstat(&self, components: &mut Vec<&str>) -> Result { - let path: String = if components.is_empty() { - if let Some(prefix) = &self.prefix { - "/".to_string() + prefix - } else { - "/".to_string() - } - } else { - let path: String = components - .iter() - .rev() - .map(|v| "/".to_owned() + v) - .collect(); - - if let Some(prefix) = &self.prefix { - "/".to_owned() + &prefix.to_owned() + &path - } else { - path - } - }; + let path: String = self.traversal_path(components); debug!("FUSE lstat: {}", path); @@ -1172,25 +1131,7 @@ impl VfsNode for FuseDirectory { opt: OpenOption, mode: AccessPermission, ) -> Result, IoError> { - let mut path: String = if components.is_empty() { - if let Some(prefix) = &self.prefix { - "/".to_string() + prefix - } else { - "/".to_string() - } - } else { - let path: String = components - .iter() - .rev() - .map(|v| "/".to_owned() + v) - .collect(); - - if let Some(prefix) = &self.prefix { - "/".to_owned() + &prefix.to_owned() + &path - } else { - path - } - }; + let mut path: String = self.traversal_path(components); debug!("FUSE lstat: {}", path); @@ -1258,25 +1199,7 @@ impl VfsNode for FuseDirectory { } fn traverse_unlink(&self, components: &mut Vec<&str>) -> core::result::Result<(), IoError> { - let path: String = if components.is_empty() { - if let Some(prefix) = &self.prefix { - "/".to_string() + prefix - } else { - "/".to_string() - } - } else { - let path: String = components - .iter() - .rev() - .map(|v| "/".to_owned() + v) - .collect(); - - if let Some(prefix) = &self.prefix { - "/".to_owned() + &prefix.to_owned() + &path - } else { - path - } - }; + let path: String = self.traversal_path(components); let (cmd, mut rsp) = ops::Unlink::create(&path); get_filesystem_driver() @@ -1289,25 +1212,7 @@ impl VfsNode for FuseDirectory { } fn traverse_rmdir(&self, components: &mut Vec<&str>) -> core::result::Result<(), IoError> { - let path: String = if components.is_empty() { - if let Some(prefix) = &self.prefix { - "/".to_string() + prefix - } else { - "/".to_string() - } - } else { - let path: String = components - .iter() - .rev() - .map(|v| "/".to_owned() + v) - .collect(); - - if let Some(prefix) = &self.prefix { - "/".to_owned() + &prefix.to_owned() + &path - } else { - path - } - }; + let path: String = self.traversal_path(components); let (cmd, mut rsp) = ops::Rmdir::create(&path); get_filesystem_driver() @@ -1324,25 +1229,7 @@ impl VfsNode for FuseDirectory { components: &mut Vec<&str>, mode: AccessPermission, ) -> Result<(), IoError> { - let path: String = if components.is_empty() { - if let Some(prefix) = &self.prefix { - "/".to_string() + prefix - } else { - "/".to_string() - } - } else { - let path: String = components - .iter() - .rev() - .map(|v| "/".to_owned() + v) - .collect(); - - if let Some(prefix) = &self.prefix { - "/".to_owned() + &prefix.to_owned() + &path - } else { - path - } - }; + let path: String = self.traversal_path(components); let (cmd, mut rsp) = ops::Mkdir::create(&path, mode.bits()); get_filesystem_driver() From 21c7a2b998d85d4cf8a63f8e2eb1d2eb658389b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Wed, 22 May 2024 10:22:43 +0200 Subject: [PATCH 7/7] fuse: use multi descriptor transfers instead of DSTs Virtio allows a single transfer to be split into multiple buffers. Using this functionality, we can provide the header and the payload in FUSE requests separately. This in turn allows us to avoid the unsafe operations associated with dynamically-sized object creation. --- src/drivers/fs/virtio_fs.rs | 14 +- src/fs/fuse.rs | 407 ++++++++++++++++-------------------- 2 files changed, 191 insertions(+), 230 deletions(-) diff --git a/src/drivers/fs/virtio_fs.rs b/src/drivers/fs/virtio_fs.rs index 7273316eea..fe3ba4a34e 100644 --- a/src/drivers/fs/virtio_fs.rs +++ b/src/drivers/fs/virtio_fs.rs @@ -1,3 +1,4 @@ +use alloc::boxed::Box; use alloc::rc::Rc; use alloc::string::{String, ToString}; use alloc::vec::Vec; @@ -143,14 +144,19 @@ impl VirtioFsDriver { impl FuseInterface for VirtioFsDriver { fn send_command( &mut self, - cmd: &fuse::Cmd, + cmd: (Box>, Option>), rsp: &mut fuse::Rsp, ) -> Result<(), VirtqError> { - let send = cmd.as_slice_u8(); - let recv = rsp.as_slice_u8_mut(); + let (cmd_header, cmd_payload_opt) = cmd; + let send: &[&[u8]] = if let Some(cmd_payload) = cmd_payload_opt.as_deref() { + &[cmd_header.as_slice_u8(), cmd_payload] + } else { + &[cmd_header.as_slice_u8()] + }; + let recv = &[rsp.as_slice_u8_mut()]; let transfer_tkn = self.vqueues[1] .clone() - .prep_transfer_from_raw(&[send], &[recv], BufferType::Direct) + .prep_transfer_from_raw(send, recv, BufferType::Direct) .unwrap(); transfer_tkn.dispatch_blocking()?; Ok(()) diff --git a/src/fs/fuse.rs b/src/fs/fuse.rs index 65e91e0eaf..3d4bcaa930 100644 --- a/src/fs/fuse.rs +++ b/src/fs/fuse.rs @@ -1,10 +1,10 @@ use alloc::alloc::{alloc, Layout}; use alloc::borrow::ToOwned; use alloc::boxed::Box; +use alloc::ffi::CString; use alloc::string::String; use alloc::sync::Arc; use alloc::vec::Vec; -use core::ffi::CStr; use core::future; use core::mem::MaybeUninit; use core::sync::atomic::{AtomicU64, Ordering}; @@ -44,7 +44,7 @@ const S_IFMT: u32 = 61440; pub(crate) trait FuseInterface { fn send_command( &mut self, - cmd: &Cmd, + cmd: (Box>, Option>), rsp: &mut Rsp, ) -> Result<(), VirtqError>; @@ -52,11 +52,12 @@ pub(crate) trait FuseInterface { } pub(crate) mod ops { + #![allow(clippy::type_complexity)] use alloc::boxed::Box; - use core::ffi::CStr; + use alloc::ffi::CString; use core::mem::MaybeUninit; - use super::{Cmd, Rsp}; + use super::{CmdHeader, Rsp}; use crate::fd::PollEvent; use crate::fs::{fuse_abi, SeekWhence}; @@ -81,8 +82,8 @@ pub(crate) mod ops { } impl Init { - pub(crate) fn create() -> (Box>, Box>) { - let cmd = Cmd::::new( + pub(crate) fn create() -> ((Box>, Option>), Box>) { + let cmd = CmdHeader::::new( fuse_abi::ROOT_ID, fuse_abi::InitIn { major: 7, @@ -93,7 +94,7 @@ pub(crate) mod ops { ); let rsp = unsafe { Box::new_uninit().assume_init() }; - (cmd, rsp) + ((cmd, None), rsp) } } @@ -103,7 +104,7 @@ pub(crate) mod ops { impl Op for Create { const OP_CODE: fuse_abi::Opcode = fuse_abi::Opcode::Create; type InStruct = fuse_abi::CreateIn; - type InPayload = CStr; + type InPayload = CString; type OutStruct = fuse_abi::CreateOut; type OutPayload = (); } @@ -111,22 +112,23 @@ pub(crate) mod ops { impl Create { #[allow(clippy::self_named_constructors)] pub(crate) fn create( - path: &str, + path: CString, flags: u32, mode: u32, - ) -> (Box>, Box>) { - let cmd = Cmd::::from_str( + ) -> ((Box>, Option>), Box>) { + let path_bytes = path.into_bytes_with_nul().into_boxed_slice(); + let cmd = CmdHeader::::with_payload_size( fuse_abi::ROOT_ID, fuse_abi::CreateIn { flags, mode, ..Default::default() }, - path, + path_bytes.len(), ); let rsp = unsafe { Box::new_uninit().assume_init() }; - (cmd, rsp) + ((cmd, Some(path_bytes)), rsp) } } @@ -142,8 +144,11 @@ pub(crate) mod ops { } impl Open { - pub(crate) fn create(nid: u64, flags: u32) -> (Box>, Box>) { - let cmd = Cmd::::new( + pub(crate) fn create( + nid: u64, + flags: u32, + ) -> ((Box>, Option>), Box>) { + let cmd = CmdHeader::::new( nid, fuse_abi::OpenIn { flags, @@ -152,7 +157,7 @@ pub(crate) mod ops { ); let rsp = unsafe { Box::new_uninit().assume_init() }; - (cmd, rsp) + ((cmd, None), rsp) } } @@ -171,10 +176,10 @@ pub(crate) mod ops { pub(crate) fn create( nid: u64, fh: u64, - buf: &[u8], + buf: Box<[u8]>, offset: u64, - ) -> (Box>, Box>) { - let cmd = Cmd::::from_array( + ) -> ((Box>, Option>), Box>) { + let cmd = CmdHeader::::with_payload_size( nid, fuse_abi::WriteIn { fh, @@ -182,11 +187,11 @@ pub(crate) mod ops { size: buf.len().try_into().unwrap(), ..Default::default() }, - buf, + buf.len(), ); let rsp = unsafe { Box::new_uninit().assume_init() }; - (cmd, rsp) + ((cmd, Some(buf)), rsp) } } @@ -210,8 +215,8 @@ pub(crate) mod ops { fh: u64, size: u32, offset: u64, - ) -> (Box>, Box>) { - let cmd = Cmd::::new( + ) -> ((Box>, Option>), Box>) { + let cmd = CmdHeader::::new( nid, fuse_abi::ReadIn { fh, @@ -222,7 +227,7 @@ pub(crate) mod ops { ); let rsp = unsafe { Rsp::::new_uninit(size.try_into().unwrap()) }; - (cmd, rsp) + ((cmd, None), rsp) } } @@ -243,8 +248,8 @@ pub(crate) mod ops { fh: u64, offset: isize, whence: SeekWhence, - ) -> (Box>, Box>) { - let cmd = Cmd::::new( + ) -> ((Box>, Option>), Box>) { + let cmd = CmdHeader::::new( nid, fuse_abi::LseekIn { fh, @@ -255,7 +260,7 @@ pub(crate) mod ops { ); let rsp = unsafe { Box::new_uninit().assume_init() }; - (cmd, rsp) + ((cmd, None), rsp) } } @@ -274,11 +279,14 @@ pub(crate) mod ops { } impl Readlink { - pub(crate) fn create(nid: u64, size: u32) -> (Box>, Box>) { - let cmd = Cmd::::new(nid, fuse_abi::ReadlinkIn {}); + pub(crate) fn create( + nid: u64, + size: u32, + ) -> ((Box>, Option>), Box>) { + let cmd = CmdHeader::::new(nid, fuse_abi::ReadlinkIn {}); let rsp = unsafe { Rsp::::new_uninit(size.try_into().unwrap()) }; - (cmd, rsp) + ((cmd, None), rsp) } } @@ -294,8 +302,11 @@ pub(crate) mod ops { } impl Release { - pub(crate) fn create(nid: u64, fh: u64) -> (Box>, Box>) { - let cmd = Cmd::::new( + pub(crate) fn create( + nid: u64, + fh: u64, + ) -> ((Box>, Option>), Box>) { + let cmd = CmdHeader::::new( nid, fuse_abi::ReleaseIn { fh, @@ -304,7 +315,7 @@ pub(crate) mod ops { ); let rsp = unsafe { Box::new_uninit().assume_init() }; - (cmd, rsp) + ((cmd, None), rsp) } } @@ -325,8 +336,8 @@ pub(crate) mod ops { fh: u64, kh: u64, event: PollEvent, - ) -> (Box>, Box>) { - let cmd = Cmd::::new( + ) -> ((Box>, Option>), Box>) { + let cmd = CmdHeader::::new( nid, fuse_abi::PollIn { fh, @@ -337,7 +348,7 @@ pub(crate) mod ops { ); let rsp = unsafe { Box::new_uninit().assume_init() }; - (cmd, rsp) + ((cmd, None), rsp) } } @@ -347,24 +358,28 @@ pub(crate) mod ops { impl Op for Mkdir { const OP_CODE: fuse_abi::Opcode = fuse_abi::Opcode::Mkdir; type InStruct = fuse_abi::MkdirIn; - type InPayload = CStr; + type InPayload = CString; type OutStruct = fuse_abi::EntryOut; type OutPayload = (); } impl Mkdir { - pub(crate) fn create(path: &str, mode: u32) -> (Box>, Box>) { - let cmd = Cmd::::from_str( + pub(crate) fn create( + path: CString, + mode: u32, + ) -> ((Box>, Option>), Box>) { + let path_bytes = path.into_bytes_with_nul().into_boxed_slice(); + let cmd = CmdHeader::::with_payload_size( fuse_abi::ROOT_ID, fuse_abi::MkdirIn { mode, ..Default::default() }, - path, + path_bytes.len(), ); let rsp = unsafe { Box::new_uninit().assume_init() }; - (cmd, rsp) + ((cmd, Some(path_bytes)), rsp) } } @@ -374,17 +389,24 @@ pub(crate) mod ops { impl Op for Unlink { const OP_CODE: fuse_abi::Opcode = fuse_abi::Opcode::Unlink; type InStruct = fuse_abi::UnlinkIn; - type InPayload = CStr; + type InPayload = CString; type OutStruct = fuse_abi::UnlinkOut; type OutPayload = (); } impl Unlink { - pub(crate) fn create(name: &str) -> (Box>, Box>) { - let cmd = Cmd::::from_str(fuse_abi::ROOT_ID, fuse_abi::UnlinkIn {}, name); + pub(crate) fn create( + name: CString, + ) -> ((Box>, Option>), Box>) { + let name_bytes = name.into_bytes_with_nul().into_boxed_slice(); + let cmd = CmdHeader::::with_payload_size( + fuse_abi::ROOT_ID, + fuse_abi::UnlinkIn {}, + name_bytes.len(), + ); let rsp = unsafe { Box::new_uninit().assume_init() }; - (cmd, rsp) + ((cmd, Some(name_bytes)), rsp) } } @@ -394,17 +416,24 @@ pub(crate) mod ops { impl Op for Rmdir { const OP_CODE: fuse_abi::Opcode = fuse_abi::Opcode::Rmdir; type InStruct = fuse_abi::RmdirIn; - type InPayload = CStr; + type InPayload = CString; type OutStruct = fuse_abi::RmdirOut; type OutPayload = (); } impl Rmdir { - pub(crate) fn create(name: &str) -> (Box>, Box>) { - let cmd = Cmd::::from_str(fuse_abi::ROOT_ID, fuse_abi::RmdirIn {}, name); + pub(crate) fn create( + name: CString, + ) -> ((Box>, Option>), Box>) { + let name_bytes = name.into_bytes_with_nul().into_boxed_slice(); + let cmd = CmdHeader::::with_payload_size( + fuse_abi::ROOT_ID, + fuse_abi::RmdirIn {}, + name_bytes.len(), + ); let rsp = unsafe { Box::new_uninit().assume_init() }; - (cmd, rsp) + ((cmd, Some(name_bytes)), rsp) } } @@ -414,17 +443,24 @@ pub(crate) mod ops { impl Op for Lookup { const OP_CODE: fuse_abi::Opcode = fuse_abi::Opcode::Lookup; type InStruct = fuse_abi::LookupIn; - type InPayload = CStr; + type InPayload = CString; type OutStruct = fuse_abi::EntryOut; type OutPayload = (); } impl Lookup { - pub(crate) fn create(name: &str) -> (Box>, Box>) { - let cmd = Cmd::::from_str(fuse_abi::ROOT_ID, fuse_abi::LookupIn {}, name); + pub(crate) fn create( + name: CString, + ) -> ((Box>, Option>), Box>) { + let name_bytes = name.into_bytes_with_nul().into_boxed_slice(); + let cmd = CmdHeader::::with_payload_size( + fuse_abi::ROOT_ID, + fuse_abi::LookupIn {}, + name_bytes.len(), + ); let rsp = unsafe { Box::new_uninit().assume_init() }; - (cmd, rsp) + ((cmd, Some(name_bytes)), rsp) } } } @@ -460,122 +496,41 @@ impl From for FileAttr { #[repr(C)] #[derive(Debug)] -pub(crate) struct Cmd { - in_header: fuse_abi::InHeader, +pub(crate) struct CmdHeader { + pub in_header: fuse_abi::InHeader, op_header: O::InStruct, - payload: O::InPayload, } -#[repr(C)] -#[derive(Debug)] -pub(crate) struct UninitCmd { - in_header: MaybeUninit, - op_header: MaybeUninit, - payload: [MaybeUninit], -} - -// We use this struct to obtain the layout of the type without the payload. -#[repr(C)] -#[derive(Debug)] -pub(crate) struct PayloadlessCmd { - in_header: MaybeUninit, - op_header: MaybeUninit, - payload: (), -} - -impl Cmd +impl CmdHeader where O: ops::Op, { fn new(nodeid: u64, op_header: O::InStruct) -> Box { - Box::new(Cmd { + Self::with_payload_size(nodeid, op_header, 0) + } +} + +impl CmdHeader { + fn with_payload_size(nodeid: u64, op_header: O::InStruct, len: usize) -> Box> { + Box::new(CmdHeader { in_header: fuse_abi::InHeader { // The length we need the provide in the header is not the same as the size of the struct because of padding, so we need to calculate it manually. len: (core::mem::size_of::() - + core::mem::size_of::()) as u32, + + core::mem::size_of::() + + len) + .try_into() + .expect("The command is too large"), opcode: O::OP_CODE as u32, nodeid, unique: 1, ..Default::default() }, op_header, - payload: (), }) } } -impl Cmd { - fn with_capacity(nodeid: u64, op_header: O::InStruct, len: usize) -> Box> { - let mut cmd = unsafe { Self::new_uninit(len) }; - cmd.in_header = MaybeUninit::new(fuse_abi::InHeader { - // The length we need the provide in the header is not the same as the size of the struct because of padding, so we need to calculate it manually. - len: (core::mem::size_of::() - + core::mem::size_of::() - + len) - .try_into() - .expect("The command is too large"), - opcode: O::OP_CODE as u32, - nodeid, - unique: 1, - ..Default::default() - }); - cmd.op_header = MaybeUninit::new(op_header); - cmd - } -} - -impl Cmd -where - O: ops::Op, -{ - fn from_array(nodeid: u64, op_header: O::InStruct, data: &[u8]) -> Box> { - let mut cmd = Self::with_capacity(nodeid, op_header, data.len()); - for (target, source) in cmd.payload.iter_mut().zip(data) { - *target = MaybeUninit::new(*source); - } - unsafe { core::intrinsics::transmute(cmd) } - } -} - -impl Cmd -where - O: ops::Op, -{ - fn from_str(nodeid: u64, op_header: O::InStruct, str: &str) -> Box> { - let str_bytes = str.as_bytes(); - // Plus one for the NUL terminator - let mut cmd = Self::with_capacity(nodeid, op_header, str_bytes.len() + 1); - for (target, source) in cmd.payload[..str_bytes.len()].iter_mut().zip(str_bytes) { - *target = MaybeUninit::new(*source); - } - cmd.payload[str_bytes.len()] = MaybeUninit::new(b'\0'); - unsafe { core::intrinsics::transmute(cmd) } - } -} - -impl AsSliceU8 for Cmd { - fn len(&self) -> usize { - self.in_header.len.try_into().unwrap() - } -} - -impl Cmd { - // MaybeUninit does not accept DSTs as type parameter - unsafe fn new_uninit(len: usize) -> Box> { - unsafe { - Box::from_raw(core::ptr::slice_from_raw_parts_mut( - alloc( - Layout::new::>() - .extend(Layout::array::(len).expect("The length is too much.")) - .expect("The layout size overflowed.") - .0 // We don't need the offset of `data_header` inside the type (the second element of the tuple) - .pad_to_align(), - ), - len, - ) as *mut UninitCmd) - } - } -} +impl AsSliceU8 for CmdHeader {} #[repr(C)] #[derive(Debug)] @@ -616,12 +571,12 @@ where } } -fn lookup(name: &str) -> Option { +fn lookup(name: CString) -> Option { let (cmd, mut rsp) = ops::Lookup::create(name); get_filesystem_driver() .unwrap() .lock() - .send_command(cmd.as_ref(), rsp.as_mut()) + .send_command(cmd, rsp.as_mut()) .ok()?; if unsafe { rsp.out_header.assume_init_ref().error } == 0 { Some(unsafe { rsp.op_header.assume_init_ref().nodeid }) @@ -636,7 +591,7 @@ fn readlink(nid: u64) -> Result { get_filesystem_driver() .unwrap() .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; let len: usize = if unsafe { rsp.out_header.assume_init_ref().len } as usize - ::core::mem::size_of::() - ::core::mem::size_of::() @@ -681,7 +636,7 @@ impl FuseFileHandleInner { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; if unsafe { rsp.out_header.assume_init_ref().error } < 0 { Poll::Ready(Err(IoError::EIO)) @@ -721,7 +676,7 @@ impl FuseFileHandleInner { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; let len: usize = if (unsafe { rsp.out_header.assume_init_ref().len } as usize) - ::core::mem::size_of::() - ::core::mem::size_of::() @@ -748,34 +703,35 @@ impl FuseFileHandleInner { fn write(&mut self, buf: &[u8]) -> Result { debug!("FUSE write!"); - let mut len = buf.len(); - if len > MAX_WRITE_LEN { + let mut truncated_len = buf.len(); + if truncated_len > MAX_WRITE_LEN { debug!( "Writing longer than max_write_len: {} > {}", buf.len(), MAX_WRITE_LEN ); - len = MAX_WRITE_LEN; + truncated_len = MAX_WRITE_LEN; } if let (Some(nid), Some(fh)) = (self.fuse_nid, self.fuse_fh) { - let (cmd, mut rsp) = ops::Write::create(nid, fh, &buf[..len], self.offset as u64); + let truncated_buf = Box::<[u8]>::from(&buf[..truncated_len]); + let (cmd, mut rsp) = ops::Write::create(nid, fh, truncated_buf, self.offset as u64); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; if unsafe { rsp.out_header.assume_init_ref().error } < 0 { return Err(IoError::EIO); } let rsp_size = unsafe { rsp.op_header.assume_init_ref().size }; - let len: usize = if rsp_size > buf.len().try_into().unwrap() { - buf.len() + let rsp_len: usize = if rsp_size > truncated_len.try_into().unwrap() { + truncated_len } else { rsp_size.try_into().unwrap() }; - self.offset += len; - Ok(len) + self.offset += rsp_len; + Ok(rsp_len) } else { warn!("File not open, cannot read!"); Err(IoError::ENOENT) @@ -790,7 +746,7 @@ impl FuseFileHandleInner { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; if unsafe { rsp.out_header.assume_init_ref().error } < 0 { return Err(IoError::EIO); @@ -813,7 +769,7 @@ impl Drop for FuseFileHandleInner { get_filesystem_driver() .unwrap() .lock() - .send_command(cmd.as_ref(), rsp.as_mut()) + .send_command(cmd, rsp.as_mut()) .unwrap(); } } @@ -868,27 +824,27 @@ impl FuseDirectoryHandle { #[async_trait] impl ObjectInterface for FuseDirectoryHandle { fn readdir(&self) -> Result, IoError> { - let path: String = if let Some(name) = &self.name { - "/".to_string() + name + let path: CString = if let Some(name) = &self.name { + CString::new("/".to_string() + name).unwrap() } else { - "/".to_string() + CString::new("/".to_string()).unwrap() }; - debug!("FUSE opendir: {}", path); + debug!("FUSE opendir: {path:#?}"); - let fuse_nid = lookup(&path).ok_or(IoError::ENOENT)?; + let fuse_nid = lookup(path.clone()).ok_or(IoError::ENOENT)?; // Opendir // Flag 0x10000 for O_DIRECTORY might not be necessary let (mut cmd, mut rsp) = ops::Open::create(fuse_nid, 0x10000); - cmd.in_header.opcode = fuse_abi::Opcode::Opendir as u32; + cmd.0.in_header.opcode = fuse_abi::Opcode::Opendir as u32; get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; let fuse_fh = unsafe { rsp.op_header.assume_init_ref().fh }; - debug!("FUSE readdir: {}", path); + debug!("FUSE readdir: {path:#?}"); // Linux seems to allocate a single page to store the dirfile let len = MAX_READ_LEN as u32; @@ -896,11 +852,11 @@ impl ObjectInterface for FuseDirectoryHandle { // read content of the directory let (mut cmd, mut rsp) = ops::Read::create(fuse_nid, fuse_fh, len, 0); - cmd.in_header.opcode = fuse_abi::Opcode::Readdir as u32; + cmd.0.in_header.opcode = fuse_abi::Opcode::Readdir as u32; get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; let len: usize = if unsafe { rsp.out_header.assume_init_ref().len } as usize - ::core::mem::size_of::() @@ -945,7 +901,7 @@ impl ObjectInterface for FuseDirectoryHandle { get_filesystem_driver() .unwrap() .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; Ok(entries) } @@ -974,16 +930,16 @@ impl FuseDirectory { } } - fn traversal_path(&self, components: &[&str]) -> String { + fn traversal_path(&self, components: &[&str]) -> CString { let prefix_deref = self.prefix.as_deref(); let components_with_prefix = prefix_deref.iter().chain(components.iter().rev()); let path: String = components_with_prefix .flat_map(|component| ["/", component]) .collect(); if path.is_empty() { - String::from("/") + CString::new("/").unwrap() } else { - path + CString::new(path).unwrap() } } } @@ -1003,23 +959,23 @@ impl VfsNode for FuseDirectory { } fn traverse_readdir(&self, components: &mut Vec<&str>) -> Result, IoError> { - let path: String = self.traversal_path(components); + let path = self.traversal_path(components); - debug!("FUSE opendir: {}", path); + debug!("FUSE opendir: {path:#?}"); - let fuse_nid = lookup(&path).ok_or(IoError::ENOENT)?; + let fuse_nid = lookup(path.clone()).ok_or(IoError::ENOENT)?; // Opendir // Flag 0x10000 for O_DIRECTORY might not be necessary let (mut cmd, mut rsp) = ops::Open::create(fuse_nid, 0x10000); - cmd.in_header.opcode = fuse_abi::Opcode::Opendir as u32; + cmd.0.in_header.opcode = fuse_abi::Opcode::Opendir as u32; get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; let fuse_fh = unsafe { rsp.op_header.assume_init_ref().fh }; - debug!("FUSE readdir: {}", path); + debug!("FUSE readdir: {path:#?}"); // Linux seems to allocate a single page to store the dirfile let len = MAX_READ_LEN as u32; @@ -1027,11 +983,11 @@ impl VfsNode for FuseDirectory { // read content of the directory let (mut cmd, mut rsp) = ops::Read::create(fuse_nid, fuse_fh, len, 0); - cmd.in_header.opcode = fuse_abi::Opcode::Readdir as u32; + cmd.0.in_header.opcode = fuse_abi::Opcode::Readdir as u32; get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; let len: usize = if unsafe { rsp.out_header.assume_init_ref().len } as usize - ::core::mem::size_of::() @@ -1076,22 +1032,22 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .unwrap() .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; Ok(entries) } fn traverse_stat(&self, components: &mut Vec<&str>) -> Result { - let path: String = self.traversal_path(components); + let path = self.traversal_path(components); - debug!("FUSE stat: {}", path); + debug!("FUSE stat: {path:#?}"); // Is there a better way to implement this? - let (cmd, mut rsp) = ops::Lookup::create(&path); + let (cmd, mut rsp) = ops::Lookup::create(path); get_filesystem_driver() .unwrap() .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; if unsafe { rsp.out_header.assume_init_ref().error } != 0 { // TODO: Correct error handling @@ -1111,15 +1067,15 @@ impl VfsNode for FuseDirectory { } fn traverse_lstat(&self, components: &mut Vec<&str>) -> Result { - let path: String = self.traversal_path(components); + let path = self.traversal_path(components); - debug!("FUSE lstat: {}", path); + debug!("FUSE lstat: {path:#?}"); - let (cmd, mut rsp) = ops::Lookup::create(&path); + let (cmd, mut rsp) = ops::Lookup::create(path); get_filesystem_driver() .unwrap() .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; let attr = unsafe { rsp.op_header.assume_init().attr }; Ok(FileAttr::from(attr)) @@ -1131,22 +1087,23 @@ impl VfsNode for FuseDirectory { opt: OpenOption, mode: AccessPermission, ) -> Result, IoError> { - let mut path: String = self.traversal_path(components); + let path = self.traversal_path(components); - debug!("FUSE lstat: {}", path); + debug!("FUSE lstat: {path:#?}"); - let (cmd, mut rsp) = ops::Lookup::create(&path); + let (cmd, mut rsp) = ops::Lookup::create(path.clone()); get_filesystem_driver() .unwrap() .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; let attr = unsafe { FileAttr::from(rsp.op_header.assume_init().attr) }; let is_dir = attr.st_mode.contains(AccessPermission::S_IFDIR); - debug!("FUSE open: {}, {:?} {:?}", path, opt, mode); + debug!("FUSE open: {path:#?}, {opt:?} {mode:?}"); if is_dir { + let mut path = path.into_string().unwrap(); path.remove(0); Ok(Arc::new(FuseDirectoryHandle::new(Some(path)))) } else { @@ -1163,7 +1120,7 @@ impl VfsNode for FuseDirectory { // Differentiate between opening and creating new file, since fuse does not support O_CREAT on open. if !opt.contains(OpenOption::O_CREAT) { // 2.FUSE_LOOKUP(FUSE_ROOT_ID, “foo”) -> nodeid - file_guard.fuse_nid = lookup(&path); + file_guard.fuse_nid = lookup(path); if file_guard.fuse_nid.is_none() { warn!("Fuse lookup seems to have failed!"); @@ -1176,16 +1133,16 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; file_guard.fuse_fh = Some(unsafe { rsp.op_header.assume_init_ref().fh }); } else { // Create file (opens implicitly, returns results from both lookup and open calls) let (cmd, mut rsp) = - ops::Create::create(&path, opt.bits().try_into().unwrap(), mode.bits()); + ops::Create::create(path, opt.bits().try_into().unwrap(), mode.bits()); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; let inner = unsafe { rsp.op_header.assume_init() }; file_guard.fuse_nid = Some(inner.entry.nodeid); @@ -1199,26 +1156,26 @@ impl VfsNode for FuseDirectory { } fn traverse_unlink(&self, components: &mut Vec<&str>) -> core::result::Result<(), IoError> { - let path: String = self.traversal_path(components); + let path = self.traversal_path(components); - let (cmd, mut rsp) = ops::Unlink::create(&path); + let (cmd, mut rsp) = ops::Unlink::create(path); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; trace!("unlink answer {:?}", rsp); Ok(()) } fn traverse_rmdir(&self, components: &mut Vec<&str>) -> core::result::Result<(), IoError> { - let path: String = self.traversal_path(components); + let path = self.traversal_path(components); - let (cmd, mut rsp) = ops::Rmdir::create(&path); + let (cmd, mut rsp) = ops::Rmdir::create(path); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; trace!("rmdir answer {:?}", rsp); Ok(()) @@ -1229,13 +1186,13 @@ impl VfsNode for FuseDirectory { components: &mut Vec<&str>, mode: AccessPermission, ) -> Result<(), IoError> { - let path: String = self.traversal_path(components); - let (cmd, mut rsp) = ops::Mkdir::create(&path, mode.bits()); + let path = self.traversal_path(components); + let (cmd, mut rsp) = ops::Mkdir::create(path, mode.bits()); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut())?; + .send_command(cmd, rsp.as_mut())?; if unsafe { rsp.out_header.assume_init_ref().error } == 0 { Ok(()) } else { @@ -1252,23 +1209,20 @@ pub(crate) fn init() { if let Some(driver) = get_filesystem_driver() { let (cmd, mut rsp) = ops::Init::create(); - driver - .lock() - .send_command(cmd.as_ref(), rsp.as_mut()) - .unwrap(); + driver.lock().send_command(cmd, rsp.as_mut()).unwrap(); trace!("fuse init answer: {:?}", rsp); let mount_point = driver.lock().get_mount_point().to_string(); if mount_point == "/" { - let fuse_nid = lookup("/").unwrap(); + let fuse_nid = lookup(c"/".to_owned()).unwrap(); // Opendir // Flag 0x10000 for O_DIRECTORY might not be necessary let (mut cmd, mut rsp) = ops::Open::create(fuse_nid, 0x10000); - cmd.in_header.opcode = fuse_abi::Opcode::Opendir as u32; + cmd.0.in_header.opcode = fuse_abi::Opcode::Opendir as u32; get_filesystem_driver() .unwrap() .lock() - .send_command(cmd.as_ref(), rsp.as_mut()) + .send_command(cmd, rsp.as_mut()) .unwrap(); let fuse_fh = unsafe { rsp.op_header.assume_init_ref().fh }; @@ -1278,11 +1232,11 @@ pub(crate) fn init() { // read content of the directory let (mut cmd, mut rsp) = ops::Read::create(fuse_nid, fuse_fh, len, 0); - cmd.in_header.opcode = fuse_abi::Opcode::Readdir as u32; + cmd.0.in_header.opcode = fuse_abi::Opcode::Readdir as u32; get_filesystem_driver() .unwrap() .lock() - .send_command(cmd.as_ref(), rsp.as_mut()) + .send_command(cmd, rsp.as_mut()) .unwrap(); let len: usize = if unsafe { rsp.out_header.assume_init_ref().len } as usize @@ -1325,7 +1279,7 @@ pub(crate) fn init() { get_filesystem_driver() .unwrap() .lock() - .send_command(cmd.as_ref(), rsp.as_mut()) + .send_command(cmd, rsp.as_mut()) .unwrap(); // remove predefined directories @@ -1336,11 +1290,12 @@ pub(crate) fn init() { warn!("Fuse don't mount the host directories 'tmp' and 'proc' into the guest file system!"); for i in entries { - let (cmd, mut rsp) = ops::Lookup::create(&i); + let i_cstr = CString::new(i.clone()).unwrap(); + let (cmd, mut rsp) = ops::Lookup::create(i_cstr); get_filesystem_driver() .unwrap() .lock() - .send_command(cmd.as_ref(), rsp.as_mut()) + .send_command(cmd, rsp.as_mut()) .unwrap(); let attr = unsafe { rsp.op_header.assume_init().attr };