From 0ff3d2c9b75335b0f8315d69c18beed6157d8aa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Sat, 3 Feb 2024 20:11:32 +0100 Subject: [PATCH 01/11] fuse: move ABI definitions to a separate module Moving the ABI definitions to a separate module helps keeping track of what is our design and what is dictated by the FUSE ABI. --- src/fs/fuse.rs | 365 +++------------------------------------------ src/fs/fuse_abi.rs | 314 ++++++++++++++++++++++++++++++++++++++ src/fs/mod.rs | 1 + 3 files changed, 337 insertions(+), 343 deletions(-) create mode 100644 src/fs/fuse_abi.rs diff --git a/src/fs/fuse.rs b/src/fs/fuse.rs index 7ef39732c4..93322c80e8 100644 --- a/src/fs/fuse.rs +++ b/src/fs/fuse.rs @@ -20,6 +20,7 @@ use crate::drivers::pci::get_filesystem_driver; use crate::drivers::virtio::virtqueue::AsSliceU8; use crate::executor::block_on; use crate::fd::{IoError, PollEvent}; +use crate::fs::fuse_abi::*; use crate::fs::{ self, AccessPermission, DirectoryEntry, FileAttr, NodeKind, ObjectInterface, OpenOption, SeekWhence, VfsNode, @@ -29,7 +30,6 @@ use crate::fs::{ // op in/out sizes/layout: https://github.com/hanwen/go-fuse/blob/204b45dba899dfa147235c255908236d5fde2d32/fuse/opcode.go#L439 // possible responses for command: qemu/tools/virtiofsd/fuse_lowlevel.h -const FUSE_ROOT_ID: u64 = 1; const MAX_READ_LEN: usize = 1024 * 64; const MAX_WRITE_LEN: usize = 1024 * 64; @@ -38,19 +38,6 @@ const U64_SIZE: usize = ::core::mem::size_of::(); const S_IFLNK: u32 = 40960; const S_IFMT: u32 = 61440; -#[allow(dead_code)] -const FUSE_GETATTR_FH: u32 = 1 << 0; - -#[repr(C)] -#[derive(Debug)] -struct fuse_dirent { - pub d_ino: u64, - pub d_off: u64, - pub d_namelen: u32, - pub d_type: u32, - pub d_name: [u8; 0], -} - pub(crate) trait FuseInterface { fn send_command(&mut self, cmd: &Cmd, rsp: &mut Rsp) where @@ -60,166 +47,39 @@ pub(crate) trait FuseInterface { fn get_mount_point(&self) -> String; } -#[repr(C)] -#[derive(Debug, Default)] -struct fuse_in_header { - pub len: u32, - pub opcode: u32, - pub unique: u64, - pub nodeid: u64, - pub uid: u32, - pub gid: u32, - pub pid: u32, - pub padding: u32, -} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_out_header { - pub len: u32, - pub error: i32, - pub unique: u64, -} - -#[repr(C)] -#[derive(Debug, Default)] -struct fuse_init_in { - pub major: u32, - pub minor: u32, - pub max_readahead: u32, - pub flags: u32, -} +/// Marker trait, which signals that a struct is a valid Fuse command. +/// Struct has to be repr(C)! +pub(crate) unsafe trait FuseIn {} +/// Marker trait, which signals that a struct is a valid Fuse response. +/// Struct has to be repr(C)! +pub(crate) unsafe trait FuseOut {} unsafe impl FuseIn for fuse_init_in {} - -#[repr(C)] -#[derive(Debug, Default)] -struct fuse_init_out { - pub major: u32, - pub minor: u32, - pub max_readahead: u32, - pub flags: u32, - pub max_background: u16, - pub congestion_threshold: u16, - pub max_write: u32, - pub time_gran: u32, - pub unused: [u32; 9], -} unsafe impl FuseOut for fuse_init_out {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_read_in { - pub fh: u64, - pub offset: u64, - pub size: u32, - pub read_flags: u32, - pub lock_owner: u64, - pub flags: u32, - pub padding: u32, -} - unsafe impl FuseIn for fuse_read_in {} - -#[repr(C)] -#[derive(Default, Debug)] -pub struct fuse_write_in { - pub fh: u64, - pub offset: u64, - pub size: u32, - pub write_flags: u32, - pub lock_owner: u64, - pub flags: u32, - pub padding: u32, -} unsafe impl FuseIn for fuse_write_in {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_write_out { - pub size: u32, - pub padding: u32, -} unsafe impl FuseOut for fuse_write_out {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_read_out {} unsafe impl FuseOut for fuse_read_out {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_lookup_in {} unsafe impl FuseIn for fuse_lookup_in {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_readlink_in {} - unsafe impl FuseIn for fuse_readlink_in {} - -#[repr(C)] -#[derive(Default, Debug)] -pub struct fuse_readlink_out {} unsafe impl FuseOut for fuse_readlink_out {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_attr_out { - pub attr_valid: u64, - pub attr_valid_nsec: u32, - pub dummy: u32, - pub attr: fuse_attr, -} - unsafe impl FuseOut for fuse_attr_out {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_entry_out { - pub nodeid: u64, - pub generation: u64, - pub entry_valid: u64, - pub attr_valid: u64, - pub entry_valid_nsec: u32, - pub attr_valid_nsec: u32, - pub attr: fuse_attr, -} - unsafe impl FuseOut for fuse_entry_out {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_attr { - /// inode number - pub ino: u64, - /// size in bytes - pub size: u64, - /// size in blocks - pub blocks: u64, - /// time of last access - pub atime: u64, - /// time of last modification - pub mtime: u64, - /// time of last status change - pub ctime: u64, - pub atimensec: u32, - pub mtimensec: u32, - pub ctimensec: u32, - /// access permissions - pub mode: u32, - /// number of hard links - pub nlink: u32, - /// user id - pub uid: u32, - /// group id - pub gid: u32, - /// device id - pub rdev: u32, - /// block size - pub blksize: u32, - pub padding: u32, -} +unsafe impl FuseIn for fuse_create_in {} +unsafe impl FuseOut for fuse_create_out {} +unsafe impl FuseIn for fuse_open_in {} +unsafe impl FuseOut for fuse_open_out {} +unsafe impl FuseIn for fuse_release_in {} +unsafe impl FuseOut for fuse_release_out {} +unsafe impl FuseIn for fuse_rmdir_in {} +unsafe impl FuseOut for fuse_rmdir_out {} +unsafe impl FuseIn for fuse_mkdir_in {} +unsafe impl FuseIn for fuse_unlink_in {} +unsafe impl FuseOut for fuse_unlink_out {} +unsafe impl FuseIn for fuse_lseek_in {} +unsafe impl FuseOut for fuse_lseek_out {} +unsafe impl FuseIn for fuse_poll_in {} +unsafe impl FuseOut for fuse_poll_out {} impl From for FileAttr { fn from(attr: fuse_attr) -> FileAttr { @@ -244,187 +104,6 @@ impl From for FileAttr { } } -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_create_in { - pub flags: u32, - pub mode: u32, - pub umask: u32, - pub open_flags: u32, -} -unsafe impl FuseIn for fuse_create_in {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_create_out { - pub entry: fuse_entry_out, - pub open: fuse_open_out, -} - -unsafe impl FuseOut for fuse_create_out {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_open_in { - pub flags: u32, - pub unused: u32, -} - -unsafe impl FuseIn for fuse_open_in {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_open_out { - pub fh: u64, - pub open_flags: u32, - pub padding: u32, -} - -unsafe impl FuseOut for fuse_open_out {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_release_in { - pub fh: u64, - pub flags: u32, - pub release_flags: u32, - pub lock_owner: u64, -} - -unsafe impl FuseIn for fuse_release_in {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_release_out {} -unsafe impl FuseOut for fuse_release_out {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_rmdir_in {} -unsafe impl FuseIn for fuse_rmdir_in {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_rmdir_out {} -unsafe impl FuseOut for fuse_rmdir_out {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_mkdir_in { - pub mode: u32, - pub umask: u32, -} -unsafe impl FuseIn for fuse_mkdir_in {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_unlink_in {} -unsafe impl FuseIn for fuse_unlink_in {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_unlink_out {} -unsafe impl FuseOut for fuse_unlink_out {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_lseek_in { - pub fh: u64, - pub offset: u64, - pub whence: u32, - pub padding: u32, -} -unsafe impl FuseIn for fuse_lseek_in {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_lseek_out { - offset: u64, -} -unsafe impl FuseOut for fuse_lseek_out {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_poll_in { - pub fh: u64, - pub kh: u64, - pub flags: u32, - pub events: u32, -} -unsafe impl FuseIn for fuse_poll_in {} - -#[repr(C)] -#[derive(Default, Debug)] -struct fuse_poll_out { - revents: u32, - padding: u32, -} -unsafe impl FuseOut for fuse_poll_out {} - -#[repr(u32)] -#[derive(Debug, Copy, Clone)] -#[allow(non_camel_case_types)] -#[allow(dead_code)] -enum Opcode { - FUSE_LOOKUP = 1, - FUSE_FORGET = 2, // no reply - FUSE_GETATTR = 3, - FUSE_SETATTR = 4, - FUSE_READLINK = 5, - FUSE_SYMLINK = 6, - FUSE_MKNOD = 8, - FUSE_MKDIR = 9, - FUSE_UNLINK = 10, - FUSE_RMDIR = 11, - FUSE_RENAME = 12, - FUSE_LINK = 13, - FUSE_OPEN = 14, - FUSE_READ = 15, - FUSE_WRITE = 16, - FUSE_STATFS = 17, - FUSE_RELEASE = 18, - FUSE_FSYNC = 20, - FUSE_SETXATTR = 21, - FUSE_GETXATTR = 22, - FUSE_LISTXATTR = 23, - FUSE_REMOVEXATTR = 24, - FUSE_FLUSH = 25, - FUSE_INIT = 26, - FUSE_OPENDIR = 27, - FUSE_READDIR = 28, - FUSE_RELEASEDIR = 29, - FUSE_FSYNCDIR = 30, - FUSE_GETLK = 31, - FUSE_SETLK = 32, - FUSE_SETLKW = 33, - FUSE_ACCESS = 34, - FUSE_CREATE = 35, - FUSE_INTERRUPT = 36, - FUSE_BMAP = 37, - FUSE_DESTROY = 38, - FUSE_IOCTL = 39, - FUSE_POLL = 40, - FUSE_NOTIFY_REPLY = 41, - FUSE_BATCH_FORGET = 42, - FUSE_FALLOCATE = 43, - FUSE_READDIRPLUS = 44, - FUSE_RENAME2 = 45, - FUSE_LSEEK = 46, - - FUSE_SETVOLNAME = 61, - FUSE_GETXTIMES = 62, - FUSE_EXCHANGE = 63, - - CUSE_INIT = 4096, -} - -/// Marker trait, which signals that a struct is a valid Fuse command. -/// Struct has to be repr(C)! -pub(crate) unsafe trait FuseIn {} -/// Marker trait, which signals that a struct is a valid Fuse response. -/// Struct has to be repr(C)! -pub(crate) unsafe trait FuseOut {} - #[repr(C)] #[derive(Debug)] pub(crate) struct Cmd { diff --git a/src/fs/fuse_abi.rs b/src/fs/fuse_abi.rs new file mode 100644 index 0000000000..60254328db --- /dev/null +++ b/src/fs/fuse_abi.rs @@ -0,0 +1,314 @@ +pub(super) const FUSE_ROOT_ID: u64 = 1; + +#[allow(dead_code)] +pub(super) const FUSE_GETATTR_FH: u32 = 1 << 0; + +#[repr(C)] +#[derive(Debug)] +pub(super) struct fuse_dirent { + pub d_ino: u64, + pub d_off: u64, + pub d_namelen: u32, + pub d_type: u32, + pub d_name: [u8; 0], +} + +#[repr(C)] +#[derive(Debug, Default)] +pub(super) struct fuse_in_header { + pub len: u32, + pub opcode: u32, + pub unique: u64, + pub nodeid: u64, + pub uid: u32, + pub gid: u32, + pub pid: u32, + pub padding: u32, +} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_out_header { + pub len: u32, + pub error: i32, + pub unique: u64, +} + +#[repr(C)] +#[derive(Debug, Default)] +pub(super) struct fuse_init_in { + pub major: u32, + pub minor: u32, + pub max_readahead: u32, + pub flags: u32, +} + +#[repr(C)] +#[derive(Debug, Default)] +pub(super) struct fuse_init_out { + pub major: u32, + pub minor: u32, + pub max_readahead: u32, + pub flags: u32, + pub max_background: u16, + pub congestion_threshold: u16, + pub max_write: u32, + pub time_gran: u32, + pub unused: [u32; 9], +} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_read_in { + pub fh: u64, + pub offset: u64, + pub size: u32, + pub read_flags: u32, + pub lock_owner: u64, + pub flags: u32, + pub padding: u32, +} + +#[repr(C)] +#[derive(Default, Debug)] +pub struct fuse_write_in { + pub fh: u64, + pub offset: u64, + pub size: u32, + pub write_flags: u32, + pub lock_owner: u64, + pub flags: u32, + pub padding: u32, +} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_write_out { + pub size: u32, + pub padding: u32, +} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_read_out {} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_lookup_in {} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_readlink_in {} + +#[repr(C)] +#[derive(Default, Debug)] +pub struct fuse_readlink_out {} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_attr_out { + pub attr_valid: u64, + pub attr_valid_nsec: u32, + pub dummy: u32, + pub attr: fuse_attr, +} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_entry_out { + pub nodeid: u64, + pub generation: u64, + pub entry_valid: u64, + pub attr_valid: u64, + pub entry_valid_nsec: u32, + pub attr_valid_nsec: u32, + pub attr: fuse_attr, +} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_attr { + /// inode number + pub ino: u64, + /// size in bytes + pub size: u64, + /// size in blocks + pub blocks: u64, + /// time of last access + pub atime: u64, + /// time of last modification + pub mtime: u64, + /// time of last status change + pub ctime: u64, + pub atimensec: u32, + pub mtimensec: u32, + pub ctimensec: u32, + /// access permissions + pub mode: u32, + /// number of hard links + pub nlink: u32, + /// user id + pub uid: u32, + /// group id + pub gid: u32, + /// device id + pub rdev: u32, + /// block size + pub blksize: u32, + pub padding: u32, +} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_create_in { + pub flags: u32, + pub mode: u32, + pub umask: u32, + pub open_flags: u32, +} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_create_out { + pub entry: fuse_entry_out, + pub open: fuse_open_out, +} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_open_in { + pub flags: u32, + pub unused: u32, +} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_open_out { + pub fh: u64, + pub open_flags: u32, + pub padding: u32, +} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_release_in { + pub fh: u64, + pub flags: u32, + pub release_flags: u32, + pub lock_owner: u64, +} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_release_out {} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_rmdir_in {} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_rmdir_out {} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_mkdir_in { + pub mode: u32, + pub umask: u32, +} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_unlink_in {} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_unlink_out {} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_lseek_in { + pub fh: u64, + pub offset: u64, + pub whence: u32, + pub padding: u32, +} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_lseek_out { + pub(super) offset: u64, +} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_poll_in { + pub fh: u64, + pub kh: u64, + pub flags: u32, + pub events: u32, +} + +#[repr(C)] +#[derive(Default, Debug)] +pub(super) struct fuse_poll_out { + pub revents: u32, + padding: u32, +} + +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +#[allow(non_camel_case_types)] +#[allow(dead_code)] +pub(super) enum Opcode { + FUSE_LOOKUP = 1, + FUSE_FORGET = 2, // no reply + FUSE_GETATTR = 3, + FUSE_SETATTR = 4, + FUSE_READLINK = 5, + FUSE_SYMLINK = 6, + FUSE_MKNOD = 8, + FUSE_MKDIR = 9, + FUSE_UNLINK = 10, + FUSE_RMDIR = 11, + FUSE_RENAME = 12, + FUSE_LINK = 13, + FUSE_OPEN = 14, + FUSE_READ = 15, + FUSE_WRITE = 16, + FUSE_STATFS = 17, + FUSE_RELEASE = 18, + FUSE_FSYNC = 20, + FUSE_SETXATTR = 21, + FUSE_GETXATTR = 22, + FUSE_LISTXATTR = 23, + FUSE_REMOVEXATTR = 24, + FUSE_FLUSH = 25, + FUSE_INIT = 26, + FUSE_OPENDIR = 27, + FUSE_READDIR = 28, + FUSE_RELEASEDIR = 29, + FUSE_FSYNCDIR = 30, + FUSE_GETLK = 31, + FUSE_SETLK = 32, + FUSE_SETLKW = 33, + FUSE_ACCESS = 34, + FUSE_CREATE = 35, + FUSE_INTERRUPT = 36, + FUSE_BMAP = 37, + FUSE_DESTROY = 38, + FUSE_IOCTL = 39, + FUSE_POLL = 40, + FUSE_NOTIFY_REPLY = 41, + FUSE_BATCH_FORGET = 42, + FUSE_FALLOCATE = 43, + FUSE_READDIRPLUS = 44, + FUSE_RENAME2 = 45, + FUSE_LSEEK = 46, + + FUSE_SETVOLNAME = 61, + FUSE_GETXTIMES = 62, + FUSE_EXCHANGE = 63, + + CUSE_INIT = 4096, +} diff --git a/src/fs/mod.rs b/src/fs/mod.rs index 0f0a77c653..c9ce5382ce 100644 --- a/src/fs/mod.rs +++ b/src/fs/mod.rs @@ -1,5 +1,6 @@ #[cfg(all(feature = "fuse", feature = "pci"))] pub(crate) mod fuse; +mod fuse_abi; mod mem; mod uhyve; From e093de4903a76b6e7932add0cfe346ed497326d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Sat, 3 Feb 2024 20:34:01 +0100 Subject: [PATCH 02/11] fuse: follow Rust naming convention Since the convention removes the module prefix from the identifiers, qualified names are used at use-sites. --- src/fs/fuse.rs | 480 ++++++++++++++++++++++++--------------------- src/fs/fuse_abi.rs | 173 ++++++++-------- 2 files changed, 343 insertions(+), 310 deletions(-) diff --git a/src/fs/fuse.rs b/src/fs/fuse.rs index 93322c80e8..b9769bdad2 100644 --- a/src/fs/fuse.rs +++ b/src/fs/fuse.rs @@ -20,10 +20,9 @@ use crate::drivers::pci::get_filesystem_driver; use crate::drivers::virtio::virtqueue::AsSliceU8; use crate::executor::block_on; use crate::fd::{IoError, PollEvent}; -use crate::fs::fuse_abi::*; use crate::fs::{ - self, AccessPermission, DirectoryEntry, FileAttr, NodeKind, ObjectInterface, OpenOption, - SeekWhence, VfsNode, + self, fuse_abi, AccessPermission, DirectoryEntry, FileAttr, NodeKind, ObjectInterface, + OpenOption, SeekWhence, VfsNode, }; // response out layout eg @ https://github.com/zargony/fuse-rs/blob/bf6d1cf03f3277e35b580f3c7b9999255d72ecf3/src/ll/request.rs#L44 @@ -54,35 +53,35 @@ pub(crate) unsafe trait FuseIn {} /// Struct has to be repr(C)! pub(crate) unsafe trait FuseOut {} -unsafe impl FuseIn for fuse_init_in {} -unsafe impl FuseOut for fuse_init_out {} -unsafe impl FuseIn for fuse_read_in {} -unsafe impl FuseIn for fuse_write_in {} -unsafe impl FuseOut for fuse_write_out {} -unsafe impl FuseOut for fuse_read_out {} -unsafe impl FuseIn for fuse_lookup_in {} -unsafe impl FuseIn for fuse_readlink_in {} -unsafe impl FuseOut for fuse_readlink_out {} -unsafe impl FuseOut for fuse_attr_out {} -unsafe impl FuseOut for fuse_entry_out {} -unsafe impl FuseIn for fuse_create_in {} -unsafe impl FuseOut for fuse_create_out {} -unsafe impl FuseIn for fuse_open_in {} -unsafe impl FuseOut for fuse_open_out {} -unsafe impl FuseIn for fuse_release_in {} -unsafe impl FuseOut for fuse_release_out {} -unsafe impl FuseIn for fuse_rmdir_in {} -unsafe impl FuseOut for fuse_rmdir_out {} -unsafe impl FuseIn for fuse_mkdir_in {} -unsafe impl FuseIn for fuse_unlink_in {} -unsafe impl FuseOut for fuse_unlink_out {} -unsafe impl FuseIn for fuse_lseek_in {} -unsafe impl FuseOut for fuse_lseek_out {} -unsafe impl FuseIn for fuse_poll_in {} -unsafe impl FuseOut for fuse_poll_out {} - -impl From for FileAttr { - fn from(attr: fuse_attr) -> FileAttr { +unsafe impl FuseIn for fuse_abi::InitIn {} +unsafe impl FuseOut for fuse_abi::InitOut {} +unsafe impl FuseIn for fuse_abi::ReadIn {} +unsafe impl FuseIn for fuse_abi::WriteIn {} +unsafe impl FuseOut for fuse_abi::WriteOut {} +unsafe impl FuseOut for fuse_abi::ReadOut {} +unsafe impl FuseIn for fuse_abi::LookupIn {} +unsafe impl FuseIn for fuse_abi::ReadlinkIn {} +unsafe impl FuseOut for fuse_abi::ReadlinkOut {} +unsafe impl FuseOut for fuse_abi::AttrOut {} +unsafe impl FuseOut for fuse_abi::EntryOut {} +unsafe impl FuseIn for fuse_abi::CreateIn {} +unsafe impl FuseOut for fuse_abi::CreateOut {} +unsafe impl FuseIn for fuse_abi::OpenIn {} +unsafe impl FuseOut for fuse_abi::OpenOut {} +unsafe impl FuseIn for fuse_abi::ReleaseIn {} +unsafe impl FuseOut for fuse_abi::ReleaseOut {} +unsafe impl FuseIn for fuse_abi::RmdirIn {} +unsafe impl FuseOut for fuse_abi::RmdirOut {} +unsafe impl FuseIn for fuse_abi::MkdirIn {} +unsafe impl FuseIn for fuse_abi::UnlinkIn {} +unsafe impl FuseOut for fuse_abi::UnlinkOut {} +unsafe impl FuseIn for fuse_abi::LseekIn {} +unsafe impl FuseOut for fuse_abi::LseekOut {} +unsafe impl FuseIn for fuse_abi::PollIn {} +unsafe impl FuseOut for fuse_abi::PollOut {} + +impl From for FileAttr { + fn from(attr: fuse_abi::Attr) -> FileAttr { FileAttr { st_ino: attr.ino, st_nlink: attr.nlink as u64, @@ -107,7 +106,7 @@ impl From for FileAttr { #[repr(C)] #[derive(Debug)] pub(crate) struct Cmd { - header: fuse_in_header, + header: fuse_abi::InHeader, cmd: T, extra_buffer: [u8], } @@ -121,7 +120,7 @@ impl AsSliceU8 for Cmd { #[repr(C)] #[derive(Debug)] pub(crate) struct Rsp { - header: fuse_out_header, + header: fuse_abi::OutHeader, rsp: MaybeUninit, extra_buffer: [MaybeUninit], } @@ -132,12 +131,12 @@ impl AsSliceU8 for Rsp { } } -fn create_in_header(nodeid: u64, opcode: Opcode) -> fuse_in_header +fn create_in_header(nodeid: u64, opcode: fuse_abi::Opcode) -> fuse_abi::InHeader where T: FuseIn, { - fuse_in_header { - len: (core::mem::size_of::() + core::mem::size_of::()) as u32, + fuse_abi::InHeader { + len: (core::mem::size_of::() + core::mem::size_of::()) as u32, opcode: opcode as u32, unique: 1, nodeid, @@ -145,23 +144,24 @@ where } } -fn create_init() -> (Box>, Box>) { - let len = core::mem::size_of::() + core::mem::size_of::(); +fn create_init() -> (Box>, Box>) { + let len = core::mem::size_of::() + core::mem::size_of::(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let cmd = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; - (*raw).header = create_in_header::(FUSE_ROOT_ID, Opcode::FUSE_INIT); + let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; + (*raw).header = + create_in_header::(fuse_abi::ROOT_ID, fuse_abi::Opcode::Init); (*raw).header.len = len.try_into().unwrap(); - (*raw).cmd = fuse_init_in { + (*raw).cmd = fuse_abi::InitIn { major: 7, minor: 31, max_readahead: 0, @@ -172,20 +172,21 @@ fn create_init() -> (Box>, Box>) { }; assert_eq!(layout, Layout::for_value(&*cmd)); - let len = core::mem::size_of::() + core::mem::size_of::(); + let len = + core::mem::size_of::() + core::mem::size_of::(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let rsp = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - (*raw).header = fuse_out_header { + let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; + (*raw).header = fuse_abi::OutHeader { len: len.try_into().unwrap(), ..Default::default() }; @@ -201,28 +202,29 @@ fn create_create( path: &str, flags: u32, mode: u32, -) -> (Box>, Box>) { +) -> (Box>, Box>) { let slice = path.as_bytes(); - let len = core::mem::size_of::() - + core::mem::size_of::() + let len = core::mem::size_of::() + + core::mem::size_of::() + slice.len() + 1; let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let cmd = unsafe { let data = alloc(layout); - let raw = - core::ptr::slice_from_raw_parts_mut(data, slice.len() + 1) as *mut Cmd; - (*raw).header = create_in_header::(FUSE_ROOT_ID, Opcode::FUSE_CREATE); + let raw = core::ptr::slice_from_raw_parts_mut(data, slice.len() + 1) + as *mut Cmd; + (*raw).header = + create_in_header::(fuse_abi::ROOT_ID, fuse_abi::Opcode::Create); (*raw).header.len = len.try_into().unwrap(); - (*raw).cmd = fuse_create_in { + (*raw).cmd = fuse_abi::CreateIn { flags, mode, ..Default::default() @@ -234,20 +236,21 @@ fn create_create( }; assert_eq!(layout, Layout::for_value(&*cmd)); - let len = core::mem::size_of::() + core::mem::size_of::(); + let len = + core::mem::size_of::() + core::mem::size_of::(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let rsp = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - (*raw).header = fuse_out_header { + let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; + (*raw).header = fuse_abi::OutHeader { len: len.try_into().unwrap(), ..Default::default() }; @@ -259,22 +262,22 @@ fn create_create( (cmd, rsp) } -fn create_open(nid: u64, flags: u32) -> (Box>, Box>) { - let len = core::mem::size_of::() + core::mem::size_of::(); +fn create_open(nid: u64, flags: u32) -> (Box>, Box>) { + let len = core::mem::size_of::() + core::mem::size_of::(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let cmd = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; - (*raw).header = create_in_header::(nid, Opcode::FUSE_OPEN); - (*raw).cmd = fuse_open_in { + let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; + (*raw).header = create_in_header::(nid, fuse_abi::Opcode::Open); + (*raw).cmd = fuse_abi::OpenIn { flags, ..Default::default() }; @@ -283,20 +286,21 @@ fn create_open(nid: u64, flags: u32) -> (Box>, Box() + core::mem::size_of::(); + let len = + core::mem::size_of::() + core::mem::size_of::(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let rsp = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - (*raw).header = fuse_out_header { + let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; + (*raw).header = fuse_abi::OutHeader { len: len.try_into().unwrap(), ..Default::default() }; @@ -314,29 +318,31 @@ fn create_write( fh: u64, buf: &[u8], offset: u64, -) -> (Box>, Box>) { - let len = - core::mem::size_of::() + core::mem::size_of::() + buf.len(); +) -> (Box>, Box>) { + let len = core::mem::size_of::() + + core::mem::size_of::() + + buf.len(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let cmd = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, buf.len()) as *mut Cmd; - (*raw).header = fuse_in_header { + let raw = + core::ptr::slice_from_raw_parts_mut(data, buf.len()) as *mut Cmd; + (*raw).header = fuse_abi::InHeader { len: len.try_into().unwrap(), - opcode: Opcode::FUSE_WRITE as u32, + opcode: fuse_abi::Opcode::Write as u32, unique: 1, nodeid: nid, ..Default::default() }; - (*raw).cmd = fuse_write_in { + (*raw).cmd = fuse_abi::WriteIn { fh, offset, size: buf.len().try_into().unwrap(), @@ -348,20 +354,21 @@ fn create_write( }; assert_eq!(layout, Layout::for_value(&*cmd)); - let len = core::mem::size_of::() + core::mem::size_of::(); + let len = + core::mem::size_of::() + core::mem::size_of::(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let rsp = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - (*raw).header = fuse_out_header { + let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; + (*raw).header = fuse_abi::OutHeader { len: len.try_into().unwrap(), ..Default::default() }; @@ -378,22 +385,22 @@ fn create_read( fh: u64, size: u32, offset: u64, -) -> (Box>, Box>) { - let len = core::mem::size_of::() + core::mem::size_of::(); +) -> (Box>, Box>) { + let len = core::mem::size_of::() + core::mem::size_of::(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let cmd = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; - (*raw).header = create_in_header::(nid, Opcode::FUSE_READ); - (*raw).cmd = fuse_read_in { + let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; + (*raw).header = create_in_header::(nid, fuse_abi::Opcode::Read); + (*raw).cmd = fuse_abi::ReadIn { fh, offset, size, @@ -404,14 +411,14 @@ fn create_read( }; assert_eq!(layout, Layout::for_value(&*cmd)); - let len = core::mem::size_of::() - + core::mem::size_of::() + let len = core::mem::size_of::() + + core::mem::size_of::() + usize::try_from(size).unwrap(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() @@ -419,8 +426,8 @@ fn create_read( let rsp = unsafe { let data = alloc(layout); let raw = core::ptr::slice_from_raw_parts_mut(data, size.try_into().unwrap()) - as *mut Rsp; - (*raw).header = fuse_out_header { + as *mut Rsp; + (*raw).header = fuse_abi::OutHeader { len: len.try_into().unwrap(), ..Default::default() }; @@ -437,28 +444,29 @@ fn create_lseek( fh: u64, offset: isize, whence: SeekWhence, -) -> (Box>, Box>) { - let len = core::mem::size_of::() + core::mem::size_of::(); +) -> (Box>, Box>) { + let len = + core::mem::size_of::() + core::mem::size_of::(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let cmd = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; - (*raw).header = fuse_in_header { + let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; + (*raw).header = fuse_abi::InHeader { len: len.try_into().unwrap(), - opcode: Opcode::FUSE_LSEEK as u32, + opcode: fuse_abi::Opcode::Lseek as u32, unique: 1, nodeid: nid, ..Default::default() }; - (*raw).cmd = fuse_lseek_in { + (*raw).cmd = fuse_abi::LseekIn { fh, offset: offset.try_into().unwrap(), whence: num::ToPrimitive::to_u32(&whence).unwrap(), @@ -469,20 +477,21 @@ fn create_lseek( }; assert_eq!(layout, Layout::for_value(&*cmd)); - let len = core::mem::size_of::() + core::mem::size_of::(); + let len = + core::mem::size_of::() + core::mem::size_of::(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let rsp = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - (*raw).header = fuse_out_header { + let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; + (*raw).header = fuse_abi::OutHeader { len: len.try_into().unwrap(), ..Default::default() }; @@ -497,35 +506,39 @@ fn create_lseek( fn create_readlink( nid: u64, size: u32, -) -> (Box>, Box>) { - let len = core::mem::size_of::() + core::mem::size_of::(); +) -> ( + Box>, + Box>, +) { + let len = + core::mem::size_of::() + core::mem::size_of::(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let cmd = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; - (*raw).header = create_in_header::(nid, Opcode::FUSE_READLINK); + let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; + (*raw).header = create_in_header::(nid, fuse_abi::Opcode::Readlink); (*raw).header.len = len.try_into().unwrap(); Box::from_raw(raw) }; assert_eq!(layout, Layout::for_value(&*cmd)); - let len = core::mem::size_of::() - + core::mem::size_of::() + let len = core::mem::size_of::() + + core::mem::size_of::() + usize::try_from(size).unwrap(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() @@ -533,8 +546,8 @@ fn create_readlink( let rsp = unsafe { let data = alloc(layout); let raw = core::ptr::slice_from_raw_parts_mut(data, size.try_into().unwrap()) - as *mut Rsp; - (*raw).header = fuse_out_header { + as *mut Rsp; + (*raw).header = fuse_abi::OutHeader { len: len.try_into().unwrap(), ..Default::default() }; @@ -546,22 +559,29 @@ fn create_readlink( (cmd, rsp) } -fn create_release(nid: u64, fh: u64) -> (Box>, Box>) { - let len = core::mem::size_of::() + core::mem::size_of::(); +fn create_release( + nid: u64, + fh: u64, +) -> ( + Box>, + Box>, +) { + let len = + core::mem::size_of::() + core::mem::size_of::(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let cmd = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; - (*raw).header = create_in_header::(nid, Opcode::FUSE_RELEASE); - (*raw).cmd = fuse_release_in { + let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; + (*raw).header = create_in_header::(nid, fuse_abi::Opcode::Release); + (*raw).cmd = fuse_abi::ReleaseIn { fh, ..Default::default() }; @@ -570,20 +590,21 @@ fn create_release(nid: u64, fh: u64) -> (Box>, Box() + core::mem::size_of::(); + let len = + core::mem::size_of::() + core::mem::size_of::(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let rsp = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - (*raw).header = fuse_out_header { + let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; + (*raw).header = fuse_abi::OutHeader { len: len.try_into().unwrap(), ..Default::default() }; @@ -600,22 +621,22 @@ fn create_poll( fh: u64, kh: u64, event: PollEvent, -) -> (Box>, Box>) { - let len = core::mem::size_of::() + core::mem::size_of::(); +) -> (Box>, Box>) { + let len = core::mem::size_of::() + core::mem::size_of::(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let cmd = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; - (*raw).header = create_in_header::(nid, Opcode::FUSE_POLL); - (*raw).cmd = fuse_poll_in { + let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; + (*raw).header = create_in_header::(nid, fuse_abi::Opcode::Poll); + (*raw).cmd = fuse_abi::PollIn { fh, kh, events: event.bits() as u32, @@ -626,20 +647,21 @@ fn create_poll( }; assert_eq!(layout, Layout::for_value(&*cmd)); - let len = core::mem::size_of::() + core::mem::size_of::(); + let len = + core::mem::size_of::() + core::mem::size_of::(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let rsp = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - (*raw).header = fuse_out_header { + let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; + (*raw).header = fuse_abi::OutHeader { len: len.try_into().unwrap(), ..Default::default() }; @@ -651,28 +673,32 @@ fn create_poll( (cmd, rsp) } -fn create_mkdir(path: &str, mode: u32) -> (Box>, Box>) { +fn create_mkdir( + path: &str, + mode: u32, +) -> (Box>, Box>) { let slice = path.as_bytes(); - let len = core::mem::size_of::() - + core::mem::size_of::() + let len = core::mem::size_of::() + + core::mem::size_of::() + slice.len() + 1; let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let cmd = unsafe { let data = alloc(layout); - let raw = - core::ptr::slice_from_raw_parts_mut(data, slice.len() + 1) as *mut Cmd; - (*raw).header = create_in_header::(FUSE_ROOT_ID, Opcode::FUSE_MKDIR); + let raw = core::ptr::slice_from_raw_parts_mut(data, slice.len() + 1) + as *mut Cmd; + (*raw).header = + create_in_header::(fuse_abi::ROOT_ID, fuse_abi::Opcode::Mkdir); (*raw).header.len = len.try_into().unwrap(); - (*raw).cmd = fuse_mkdir_in { + (*raw).cmd = fuse_abi::MkdirIn { mode, ..Default::default() }; @@ -683,20 +709,21 @@ fn create_mkdir(path: &str, mode: u32) -> (Box>, Box() + core::mem::size_of::(); + let len = + core::mem::size_of::() + core::mem::size_of::(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let rsp = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - (*raw).header = fuse_out_header { + let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; + (*raw).header = fuse_abi::OutHeader { len: len.try_into().unwrap(), ..Default::default() }; @@ -708,26 +735,27 @@ fn create_mkdir(path: &str, mode: u32) -> (Box>, Box (Box>, Box>) { +fn create_unlink(name: &str) -> (Box>, Box>) { let slice = name.as_bytes(); - let len = core::mem::size_of::() - + core::mem::size_of::() + let len = core::mem::size_of::() + + core::mem::size_of::() + slice.len() + 1; let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let cmd = unsafe { let data = alloc(layout); - let raw = - core::ptr::slice_from_raw_parts_mut(data, slice.len() + 1) as *mut Cmd; - (*raw).header = create_in_header::(FUSE_ROOT_ID, Opcode::FUSE_UNLINK); + let raw = core::ptr::slice_from_raw_parts_mut(data, slice.len() + 1) + as *mut Cmd; + (*raw).header = + create_in_header::(fuse_abi::ROOT_ID, fuse_abi::Opcode::Unlink); (*raw).header.len = len.try_into().unwrap(); (*raw).extra_buffer[..slice.len()].copy_from_slice(slice); (*raw).extra_buffer[slice.len()] = 0; @@ -736,20 +764,21 @@ fn create_unlink(name: &str) -> (Box>, Box() + core::mem::size_of::(); + let len = + core::mem::size_of::() + core::mem::size_of::(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let rsp = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - (*raw).header = fuse_out_header { + let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; + (*raw).header = fuse_abi::OutHeader { len: len.try_into().unwrap(), ..Default::default() }; @@ -761,26 +790,27 @@ fn create_unlink(name: &str) -> (Box>, Box (Box>, Box>) { +fn create_rmdir(name: &str) -> (Box>, Box>) { let slice = name.as_bytes(); - let len = core::mem::size_of::() - + core::mem::size_of::() + let len = core::mem::size_of::() + + core::mem::size_of::() + slice.len() + 1; let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let cmd = unsafe { let data = alloc(layout); - let raw = - core::ptr::slice_from_raw_parts_mut(data, slice.len() + 1) as *mut Cmd; - (*raw).header = create_in_header::(FUSE_ROOT_ID, Opcode::FUSE_RMDIR); + let raw = core::ptr::slice_from_raw_parts_mut(data, slice.len() + 1) + as *mut Cmd; + (*raw).header = + create_in_header::(fuse_abi::ROOT_ID, fuse_abi::Opcode::Rmdir); (*raw).header.len = len.try_into().unwrap(); (*raw).extra_buffer[..slice.len()].copy_from_slice(slice); (*raw).extra_buffer[slice.len()] = 0; @@ -789,20 +819,21 @@ fn create_rmdir(name: &str) -> (Box>, Box }; assert_eq!(layout, Layout::for_value(&*cmd)); - let len = core::mem::size_of::() + core::mem::size_of::(); + let len = + core::mem::size_of::() + core::mem::size_of::(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let rsp = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - (*raw).header = fuse_out_header { + let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; + (*raw).header = fuse_abi::OutHeader { len: len.try_into().unwrap(), ..Default::default() }; @@ -814,26 +845,27 @@ fn create_rmdir(name: &str) -> (Box>, Box (cmd, rsp) } -fn create_lookup(name: &str) -> (Box>, Box>) { +fn create_lookup(name: &str) -> (Box>, Box>) { let slice = name.as_bytes(); - let len = core::mem::size_of::() - + core::mem::size_of::() + let len = core::mem::size_of::() + + core::mem::size_of::() + slice.len() + 1; let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let cmd = unsafe { let data = alloc(layout); - let raw = - core::ptr::slice_from_raw_parts_mut(data, slice.len() + 1) as *mut Cmd; - (*raw).header = create_in_header::(FUSE_ROOT_ID, Opcode::FUSE_LOOKUP); + let raw = core::ptr::slice_from_raw_parts_mut(data, slice.len() + 1) + as *mut Cmd; + (*raw).header = + create_in_header::(fuse_abi::ROOT_ID, fuse_abi::Opcode::Lookup); (*raw).header.len = len.try_into().unwrap(); (*raw).extra_buffer[..slice.len()].copy_from_slice(slice); (*raw).extra_buffer[slice.len()] = 0; @@ -842,20 +874,21 @@ fn create_lookup(name: &str) -> (Box>, Box() + core::mem::size_of::(); + let len = + core::mem::size_of::() + core::mem::size_of::(); let layout = Layout::from_size_align( len, core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), + core::mem::align_of::(), + core::mem::align_of::(), ), ) .unwrap() .pad_to_align(); let rsp = unsafe { let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - (*raw).header = fuse_out_header { + let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; + (*raw).header = fuse_abi::OutHeader { len: len.try_into().unwrap(), ..Default::default() }; @@ -888,15 +921,15 @@ fn readlink(nid: u64) -> Result { .lock() .send_command(cmd.as_ref(), rsp.as_mut()); let len: usize = if rsp.header.len as usize - - ::core::mem::size_of::() - - ::core::mem::size_of::() + - ::core::mem::size_of::() + - ::core::mem::size_of::() >= len.try_into().unwrap() { len.try_into().unwrap() } else { rsp.header.len as usize - - ::core::mem::size_of::() - - ::core::mem::size_of::() + - ::core::mem::size_of::() + - ::core::mem::size_of::() }; Ok(String::from_utf8(unsafe { @@ -970,15 +1003,15 @@ impl FuseFileHandleInner { .lock() .send_command(cmd.as_ref(), rsp.as_mut()); let len: usize = if rsp.header.len as usize - - ::core::mem::size_of::() - - ::core::mem::size_of::() + - ::core::mem::size_of::() + - ::core::mem::size_of::() >= len { len } else { rsp.header.len as usize - - ::core::mem::size_of::() - - ::core::mem::size_of::() + - ::core::mem::size_of::() + - ::core::mem::size_of::() }; self.offset += len; @@ -1132,7 +1165,7 @@ impl VfsNode for FuseDirectory { // Opendir // Flag 0x10000 for O_DIRECTORY might not be necessary let (mut cmd, mut rsp) = create_open(fuse_nid, 0x10000); - cmd.header.opcode = Opcode::FUSE_OPENDIR as u32; + cmd.header.opcode = fuse_abi::Opcode::Opendir as u32; get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() @@ -1147,35 +1180,36 @@ impl VfsNode for FuseDirectory { // read content of the directory let (mut cmd, mut rsp) = create_read(fuse_nid, fuse_fh, len, 0); - cmd.header.opcode = Opcode::FUSE_READDIR as u32; + cmd.header.opcode = fuse_abi::Opcode::Readdir as u32; get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() .send_command(cmd.as_ref(), rsp.as_mut()); let len: usize = if rsp.header.len as usize - - ::core::mem::size_of::() - - ::core::mem::size_of::() + - ::core::mem::size_of::() + - ::core::mem::size_of::() >= len.try_into().unwrap() { len.try_into().unwrap() } else { rsp.header.len as usize - - ::core::mem::size_of::() - - ::core::mem::size_of::() + - ::core::mem::size_of::() + - ::core::mem::size_of::() }; - if len <= core::mem::size_of::() { + if len <= core::mem::size_of::() { debug!("FUSE no new dirs"); return Err(IoError::ENOENT); } let mut entries: Vec = Vec::new(); - while rsp.header.len as usize - offset > core::mem::size_of::() { - let dirent = - unsafe { &*(rsp.extra_buffer.as_ptr().byte_add(offset) as *const fuse_dirent) }; + while rsp.header.len as usize - offset > core::mem::size_of::() { + let dirent = unsafe { + &*(rsp.extra_buffer.as_ptr().byte_add(offset) as *const fuse_abi::Dirent) + }; - offset += core::mem::size_of::() + dirent.d_namelen as usize; + offset += core::mem::size_of::() + dirent.d_namelen as usize; // Allign to dirent struct offset = ((offset) + U64_SIZE - 1) & (!(U64_SIZE - 1)); diff --git a/src/fs/fuse_abi.rs b/src/fs/fuse_abi.rs index 60254328db..b09ce9311a 100644 --- a/src/fs/fuse_abi.rs +++ b/src/fs/fuse_abi.rs @@ -1,11 +1,11 @@ -pub(super) const FUSE_ROOT_ID: u64 = 1; +pub(super) const ROOT_ID: u64 = 1; #[allow(dead_code)] -pub(super) const FUSE_GETATTR_FH: u32 = 1 << 0; +pub(super) const GETATTR_FH: u32 = 1 << 0; #[repr(C)] #[derive(Debug)] -pub(super) struct fuse_dirent { +pub(super) struct Dirent { pub d_ino: u64, pub d_off: u64, pub d_namelen: u32, @@ -15,7 +15,7 @@ pub(super) struct fuse_dirent { #[repr(C)] #[derive(Debug, Default)] -pub(super) struct fuse_in_header { +pub(super) struct InHeader { pub len: u32, pub opcode: u32, pub unique: u64, @@ -28,7 +28,7 @@ pub(super) struct fuse_in_header { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_out_header { +pub(super) struct OutHeader { pub len: u32, pub error: i32, pub unique: u64, @@ -36,7 +36,7 @@ pub(super) struct fuse_out_header { #[repr(C)] #[derive(Debug, Default)] -pub(super) struct fuse_init_in { +pub(super) struct InitIn { pub major: u32, pub minor: u32, pub max_readahead: u32, @@ -45,7 +45,7 @@ pub(super) struct fuse_init_in { #[repr(C)] #[derive(Debug, Default)] -pub(super) struct fuse_init_out { +pub(super) struct InitOut { pub major: u32, pub minor: u32, pub max_readahead: u32, @@ -59,7 +59,7 @@ pub(super) struct fuse_init_out { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_read_in { +pub(super) struct ReadIn { pub fh: u64, pub offset: u64, pub size: u32, @@ -71,7 +71,7 @@ pub(super) struct fuse_read_in { #[repr(C)] #[derive(Default, Debug)] -pub struct fuse_write_in { +pub struct WriteIn { pub fh: u64, pub offset: u64, pub size: u32, @@ -83,51 +83,51 @@ pub struct fuse_write_in { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_write_out { +pub(super) struct WriteOut { pub size: u32, pub padding: u32, } #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_read_out {} +pub(super) struct ReadOut {} #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_lookup_in {} +pub(super) struct LookupIn {} #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_readlink_in {} +pub(super) struct ReadlinkIn {} #[repr(C)] #[derive(Default, Debug)] -pub struct fuse_readlink_out {} +pub struct ReadlinkOut {} #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_attr_out { +pub(super) struct AttrOut { pub attr_valid: u64, pub attr_valid_nsec: u32, pub dummy: u32, - pub attr: fuse_attr, + pub attr: Attr, } #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_entry_out { +pub(super) struct EntryOut { pub nodeid: u64, pub generation: u64, pub entry_valid: u64, pub attr_valid: u64, pub entry_valid_nsec: u32, pub attr_valid_nsec: u32, - pub attr: fuse_attr, + pub attr: Attr, } #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_attr { +pub(super) struct Attr { /// inode number pub ino: u64, /// size in bytes @@ -160,7 +160,7 @@ pub(super) struct fuse_attr { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_create_in { +pub(super) struct CreateIn { pub flags: u32, pub mode: u32, pub umask: u32, @@ -169,21 +169,21 @@ pub(super) struct fuse_create_in { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_create_out { - pub entry: fuse_entry_out, - pub open: fuse_open_out, +pub(super) struct CreateOut { + pub entry: EntryOut, + pub open: OpenOut, } #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_open_in { +pub(super) struct OpenIn { pub flags: u32, pub unused: u32, } #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_open_out { +pub(super) struct OpenOut { pub fh: u64, pub open_flags: u32, pub padding: u32, @@ -191,7 +191,7 @@ pub(super) struct fuse_open_out { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_release_in { +pub(super) struct ReleaseIn { pub fh: u64, pub flags: u32, pub release_flags: u32, @@ -200,34 +200,34 @@ pub(super) struct fuse_release_in { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_release_out {} +pub(super) struct ReleaseOut {} #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_rmdir_in {} +pub(super) struct RmdirIn {} #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_rmdir_out {} +pub(super) struct RmdirOut {} #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_mkdir_in { +pub(super) struct MkdirIn { pub mode: u32, pub umask: u32, } #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_unlink_in {} +pub(super) struct UnlinkIn {} #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_unlink_out {} +pub(super) struct UnlinkOut {} #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_lseek_in { +pub(super) struct LseekIn { pub fh: u64, pub offset: u64, pub whence: u32, @@ -236,13 +236,13 @@ pub(super) struct fuse_lseek_in { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_lseek_out { +pub(super) struct LseekOut { pub(super) offset: u64, } #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_poll_in { +pub(super) struct PollIn { pub fh: u64, pub kh: u64, pub flags: u32, @@ -251,64 +251,63 @@ pub(super) struct fuse_poll_in { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct fuse_poll_out { +pub(super) struct PollOut { pub revents: u32, padding: u32, } #[repr(u32)] #[derive(Debug, Copy, Clone)] -#[allow(non_camel_case_types)] #[allow(dead_code)] pub(super) enum Opcode { - FUSE_LOOKUP = 1, - FUSE_FORGET = 2, // no reply - FUSE_GETATTR = 3, - FUSE_SETATTR = 4, - FUSE_READLINK = 5, - FUSE_SYMLINK = 6, - FUSE_MKNOD = 8, - FUSE_MKDIR = 9, - FUSE_UNLINK = 10, - FUSE_RMDIR = 11, - FUSE_RENAME = 12, - FUSE_LINK = 13, - FUSE_OPEN = 14, - FUSE_READ = 15, - FUSE_WRITE = 16, - FUSE_STATFS = 17, - FUSE_RELEASE = 18, - FUSE_FSYNC = 20, - FUSE_SETXATTR = 21, - FUSE_GETXATTR = 22, - FUSE_LISTXATTR = 23, - FUSE_REMOVEXATTR = 24, - FUSE_FLUSH = 25, - FUSE_INIT = 26, - FUSE_OPENDIR = 27, - FUSE_READDIR = 28, - FUSE_RELEASEDIR = 29, - FUSE_FSYNCDIR = 30, - FUSE_GETLK = 31, - FUSE_SETLK = 32, - FUSE_SETLKW = 33, - FUSE_ACCESS = 34, - FUSE_CREATE = 35, - FUSE_INTERRUPT = 36, - FUSE_BMAP = 37, - FUSE_DESTROY = 38, - FUSE_IOCTL = 39, - FUSE_POLL = 40, - FUSE_NOTIFY_REPLY = 41, - FUSE_BATCH_FORGET = 42, - FUSE_FALLOCATE = 43, - FUSE_READDIRPLUS = 44, - FUSE_RENAME2 = 45, - FUSE_LSEEK = 46, - - FUSE_SETVOLNAME = 61, - FUSE_GETXTIMES = 62, - FUSE_EXCHANGE = 63, - - CUSE_INIT = 4096, + Lookup = 1, + Forget = 2, // no reply + Getattr = 3, + Setattr = 4, + Readlink = 5, + Symlink = 6, + Mknod = 8, + Mkdir = 9, + Unlink = 10, + Rmdir = 11, + Rename = 12, + Link = 13, + Open = 14, + Read = 15, + Write = 16, + Statfs = 17, + Release = 18, + Fsync = 20, + Setxattr = 21, + Getxattr = 22, + Listxattr = 23, + Removexattr = 24, + Flush = 25, + Init = 26, + Opendir = 27, + Readdir = 28, + Releasedir = 29, + Fsyncdir = 30, + Getlk = 31, + Setlk = 32, + Setlkw = 33, + Access = 34, + Create = 35, + Interrupt = 36, + Bmap = 37, + Destroy = 38, + Ioctl = 39, + Poll = 40, + NotifyReply = 41, + BatchForget = 42, + Fallocate = 43, + Readdirplus = 44, + Rename2 = 45, + Lseek = 46, + + Setvolname = 61, + Getxtimes = 62, + Exchange = 63, + + CuseInit = 4096, } From 24c425b5e825ca5e2c91bdd863df9b5cdf33717f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Sat, 3 Feb 2024 21:25:35 +0100 Subject: [PATCH 03/11] fuse: specify in/out structs of ops in type system --- src/drivers/fs/virtio_fs.rs | 5 +- src/fs/fuse.rs | 109 +++++++++++++++++++++++++++++------- src/fs/fuse_abi.rs | 60 ++++++++++---------- src/lib.rs | 1 + 4 files changed, 122 insertions(+), 53 deletions(-) diff --git a/src/drivers/fs/virtio_fs.rs b/src/drivers/fs/virtio_fs.rs index 8a30c3d540..a4663da8cb 100644 --- a/src/drivers/fs/virtio_fs.rs +++ b/src/drivers/fs/virtio_fs.rs @@ -153,10 +153,9 @@ impl VirtioFsDriver { } impl FuseInterface for VirtioFsDriver { - fn send_command(&mut self, cmd: &fuse::Cmd, rsp: &mut fuse::Rsp) + fn send_command(&mut self, cmd: & as fuse::OpTrait>::Cmd, rsp: &mut as fuse::OpTrait>::Rsp) where - S: fuse::FuseIn + core::fmt::Debug, - T: fuse::FuseOut + core::fmt::Debug, + fuse::Op: fuse::OpTrait { if let Some(mut buff_tkn) = self.ready_queue.pop() { let cmd_len = Some(cmd.len()); diff --git a/src/fs/fuse.rs b/src/fs/fuse.rs index b9769bdad2..e3cb79930a 100644 --- a/src/fs/fuse.rs +++ b/src/fs/fuse.rs @@ -38,10 +38,9 @@ const S_IFLNK: u32 = 40960; const S_IFMT: u32 = 61440; pub(crate) trait FuseInterface { - fn send_command(&mut self, cmd: &Cmd, rsp: &mut Rsp) + fn send_command(&mut self, cmd: & as OpTrait>::Cmd, rsp: &mut as OpTrait>::Rsp) where - S: FuseIn + core::fmt::Debug, - T: FuseOut + core::fmt::Debug; + Op: OpTrait; fn get_mount_point(&self) -> String; } @@ -80,6 +79,76 @@ unsafe impl FuseOut for fuse_abi::LseekOut {} unsafe impl FuseIn for fuse_abi::PollIn {} unsafe impl FuseOut for fuse_abi::PollOut {} +pub(crate) trait OpTrait { + type InStruct: FuseIn + core::fmt::Debug; + type OutStruct: FuseOut + core::fmt::Debug; + + type Cmd: ?Sized + AsSliceU8 = Cmd; + type Rsp: ?Sized + AsSliceU8 = Rsp; +} + +pub(crate) struct Op; + +impl OpTrait for Op<{fuse_abi::Opcode::Init as u32}> { + type InStruct = fuse_abi::InitIn; + type OutStruct = fuse_abi::InitOut; +} + +impl OpTrait for Op<{fuse_abi::Opcode::Create as u32}> { + type InStruct = fuse_abi::CreateIn; + type OutStruct = fuse_abi::CreateOut; +} + +impl OpTrait for Op<{fuse_abi::Opcode::Open as u32}> { + type InStruct = fuse_abi::OpenIn; + type OutStruct = fuse_abi::OpenOut; +} + +impl OpTrait for Op<{fuse_abi::Opcode::Write as u32}> { + type InStruct = fuse_abi::WriteIn; + type OutStruct = fuse_abi::WriteOut; +} + +impl OpTrait for Op<{fuse_abi::Opcode::Read as u32}> { + type InStruct = fuse_abi::ReadIn; + type OutStruct = fuse_abi::ReadOut; +} + +impl OpTrait for Op<{fuse_abi::Opcode::Lseek as u32}> { + type InStruct = fuse_abi::LseekIn; + type OutStruct = fuse_abi::LseekOut; +} + +impl OpTrait for Op<{fuse_abi::Opcode::Readlink as u32}> { + type InStruct = fuse_abi::ReadlinkIn; + type OutStruct = fuse_abi::ReadlinkOut; +} + +impl OpTrait for Op<{fuse_abi::Opcode::Release as u32}> { + type InStruct = fuse_abi::ReleaseIn; + type OutStruct = fuse_abi::ReleaseOut; +} + +impl OpTrait for Op<{fuse_abi::Opcode::Mkdir as u32}> { + type InStruct = fuse_abi::MkdirIn; + type OutStruct = fuse_abi::EntryOut; +} + +impl OpTrait for Op<{fuse_abi::Opcode::Unlink as u32}> { + type InStruct = fuse_abi::UnlinkIn; + type OutStruct = fuse_abi::UnlinkOut; +} + +impl OpTrait for Op<{fuse_abi::Opcode::Rmdir as u32}> { + type InStruct = fuse_abi::RmdirIn; + type OutStruct = fuse_abi::RmdirOut; +} + +impl OpTrait for Op<{fuse_abi::Opcode::Lookup as u32}> { + type InStruct = fuse_abi::LookupIn; + type OutStruct = fuse_abi::EntryOut; +} + impl From for FileAttr { fn from(attr: fuse_abi::Attr) -> FileAttr { FileAttr { @@ -905,7 +974,7 @@ fn lookup(name: &str) -> Option { get_filesystem_driver() .unwrap() .lock() - .send_command(cmd.as_ref(), rsp.as_mut()); + .send_command::<{fuse_abi::Opcode::Lookup as u32}>(cmd.as_ref(), rsp.as_mut()); if rsp.header.error == 0 { Some(unsafe { rsp.rsp.assume_init().nodeid }) } else { @@ -919,7 +988,7 @@ fn readlink(nid: u64) -> Result { get_filesystem_driver() .unwrap() .lock() - .send_command(cmd.as_ref(), rsp.as_mut()); + .send_command::<{fuse_abi::Opcode::Readlink as u32}>(cmd.as_ref(), rsp.as_mut()); let len: usize = if rsp.header.len as usize - ::core::mem::size_of::() - ::core::mem::size_of::() @@ -1001,7 +1070,7 @@ impl FuseFileHandleInner { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut()); + .send_command::<{fuse_abi::Opcode::Read as u32}>(cmd.as_ref(), rsp.as_mut()); let len: usize = if rsp.header.len as usize - ::core::mem::size_of::() - ::core::mem::size_of::() @@ -1042,7 +1111,7 @@ impl FuseFileHandleInner { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut()); + .send_command::<{fuse_abi::Opcode::Write as u32}>(cmd.as_ref(), rsp.as_mut()); if rsp.header.error < 0 { return Err(IoError::EIO); @@ -1070,7 +1139,7 @@ impl FuseFileHandleInner { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut()); + .send_command::<{fuse_abi::Opcode::Lseek as u32}>(cmd.as_ref(), rsp.as_mut()); if rsp.header.error < 0 { return Err(IoError::EIO); @@ -1092,7 +1161,7 @@ impl Drop for FuseFileHandleInner { get_filesystem_driver() .unwrap() .lock() - .send_command(cmd.as_ref(), rsp.as_mut()); + .send_command::<{fuse_abi::Opcode::Release as u32}>(cmd.as_ref(), rsp.as_mut()); } } } @@ -1169,7 +1238,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut()); + .send_command::<{fuse_abi::Opcode::Open as u32}>(cmd.as_ref(), rsp.as_mut()); let fuse_fh = unsafe { rsp.rsp.assume_init().fh }; debug!("FUSE readdir: {}", path); @@ -1184,7 +1253,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut()); + .send_command::<{fuse_abi::Opcode::Read as u32}>(cmd.as_ref(), rsp.as_mut()); let len: usize = if rsp.header.len as usize - ::core::mem::size_of::() @@ -1228,7 +1297,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .unwrap() .lock() - .send_command(cmd.as_ref(), rsp.as_mut()); + .send_command::<{fuse_abi::Opcode::Release as u32}>(cmd.as_ref(), rsp.as_mut()); Ok(entries) } @@ -1251,7 +1320,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .unwrap() .lock() - .send_command(cmd.as_ref(), rsp.as_mut()); + .send_command::<{fuse_abi::Opcode::Lookup as u32}>(cmd.as_ref(), rsp.as_mut()); if rsp.header.error != 0 { // TODO: Correct error handling @@ -1287,7 +1356,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .unwrap() .lock() - .send_command(cmd.as_ref(), rsp.as_mut()); + .send_command::<{fuse_abi::Opcode::Lookup as u32}>(cmd.as_ref(), rsp.as_mut()); let attr = unsafe { rsp.rsp.assume_init().attr }; Ok(FileAttr::from(attr)) @@ -1333,7 +1402,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut()); + .send_command::<{fuse_abi::Opcode::Open as u32}>(cmd.as_ref(), rsp.as_mut()); file_guard.fuse_fh = Some(unsafe { rsp.rsp.assume_init().fh }); } else { // Create file (opens implicitly, returns results from both lookup and open calls) @@ -1341,7 +1410,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut()); + .send_command::<{fuse_abi::Opcode::Create as u32}>(cmd.as_ref(), rsp.as_mut()); let inner = unsafe { rsp.rsp.assume_init() }; file_guard.fuse_nid = Some(inner.entry.nodeid); @@ -1368,7 +1437,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut()); + .send_command::<{fuse_abi::Opcode::Unlink as u32}>(cmd.as_ref(), rsp.as_mut()); trace!("unlink answer {:?}", rsp); Ok(()) @@ -1389,7 +1458,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut()); + .send_command::<{fuse_abi::Opcode::Rmdir as u32}>(cmd.as_ref(), rsp.as_mut()); trace!("rmdir answer {:?}", rsp); Ok(()) @@ -1414,7 +1483,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut()); + .send_command::<{fuse_abi::Opcode::Mkdir as u32}>(cmd.as_ref(), rsp.as_mut()); if rsp.header.error == 0 { Ok(()) } else { @@ -1428,7 +1497,7 @@ pub(crate) fn init() { if let Some(driver) = get_filesystem_driver() { let (cmd, mut rsp) = create_init(); - driver.lock().send_command(cmd.as_ref(), rsp.as_mut()); + driver.lock().send_command::<{fuse_abi::Opcode::Init as u32}>(cmd.as_ref(), rsp.as_mut()); trace!("fuse init answer: {:?}", rsp); let mount_point = format!("/{}", driver.lock().get_mount_point()); diff --git a/src/fs/fuse_abi.rs b/src/fs/fuse_abi.rs index b09ce9311a..49a97d75ec 100644 --- a/src/fs/fuse_abi.rs +++ b/src/fs/fuse_abi.rs @@ -1,11 +1,11 @@ -pub(super) const ROOT_ID: u64 = 1; +pub(crate) const ROOT_ID: u64 = 1; #[allow(dead_code)] -pub(super) const GETATTR_FH: u32 = 1 << 0; +pub(crate) const GETATTR_FH: u32 = 1 << 0; #[repr(C)] #[derive(Debug)] -pub(super) struct Dirent { +pub(crate) struct Dirent { pub d_ino: u64, pub d_off: u64, pub d_namelen: u32, @@ -15,7 +15,7 @@ pub(super) struct Dirent { #[repr(C)] #[derive(Debug, Default)] -pub(super) struct InHeader { +pub(crate) struct InHeader { pub len: u32, pub opcode: u32, pub unique: u64, @@ -28,7 +28,7 @@ pub(super) struct InHeader { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct OutHeader { +pub(crate) struct OutHeader { pub len: u32, pub error: i32, pub unique: u64, @@ -36,7 +36,7 @@ pub(super) struct OutHeader { #[repr(C)] #[derive(Debug, Default)] -pub(super) struct InitIn { +pub(crate) struct InitIn { pub major: u32, pub minor: u32, pub max_readahead: u32, @@ -45,7 +45,7 @@ pub(super) struct InitIn { #[repr(C)] #[derive(Debug, Default)] -pub(super) struct InitOut { +pub(crate) struct InitOut { pub major: u32, pub minor: u32, pub max_readahead: u32, @@ -59,7 +59,7 @@ pub(super) struct InitOut { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct ReadIn { +pub(crate) struct ReadIn { pub fh: u64, pub offset: u64, pub size: u32, @@ -83,22 +83,22 @@ pub struct WriteIn { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct WriteOut { +pub(crate) struct WriteOut { pub size: u32, pub padding: u32, } #[repr(C)] #[derive(Default, Debug)] -pub(super) struct ReadOut {} +pub(crate) struct ReadOut {} #[repr(C)] #[derive(Default, Debug)] -pub(super) struct LookupIn {} +pub(crate) struct LookupIn {} #[repr(C)] #[derive(Default, Debug)] -pub(super) struct ReadlinkIn {} +pub(crate) struct ReadlinkIn {} #[repr(C)] #[derive(Default, Debug)] @@ -106,7 +106,7 @@ pub struct ReadlinkOut {} #[repr(C)] #[derive(Default, Debug)] -pub(super) struct AttrOut { +pub(crate) struct AttrOut { pub attr_valid: u64, pub attr_valid_nsec: u32, pub dummy: u32, @@ -115,7 +115,7 @@ pub(super) struct AttrOut { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct EntryOut { +pub(crate) struct EntryOut { pub nodeid: u64, pub generation: u64, pub entry_valid: u64, @@ -127,7 +127,7 @@ pub(super) struct EntryOut { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct Attr { +pub(crate) struct Attr { /// inode number pub ino: u64, /// size in bytes @@ -160,7 +160,7 @@ pub(super) struct Attr { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct CreateIn { +pub(crate) struct CreateIn { pub flags: u32, pub mode: u32, pub umask: u32, @@ -169,21 +169,21 @@ pub(super) struct CreateIn { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct CreateOut { +pub(crate) struct CreateOut { pub entry: EntryOut, pub open: OpenOut, } #[repr(C)] #[derive(Default, Debug)] -pub(super) struct OpenIn { +pub(crate) struct OpenIn { pub flags: u32, pub unused: u32, } #[repr(C)] #[derive(Default, Debug)] -pub(super) struct OpenOut { +pub(crate) struct OpenOut { pub fh: u64, pub open_flags: u32, pub padding: u32, @@ -191,7 +191,7 @@ pub(super) struct OpenOut { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct ReleaseIn { +pub(crate) struct ReleaseIn { pub fh: u64, pub flags: u32, pub release_flags: u32, @@ -200,34 +200,34 @@ pub(super) struct ReleaseIn { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct ReleaseOut {} +pub(crate) struct ReleaseOut {} #[repr(C)] #[derive(Default, Debug)] -pub(super) struct RmdirIn {} +pub(crate) struct RmdirIn {} #[repr(C)] #[derive(Default, Debug)] -pub(super) struct RmdirOut {} +pub(crate) struct RmdirOut {} #[repr(C)] #[derive(Default, Debug)] -pub(super) struct MkdirIn { +pub(crate) struct MkdirIn { pub mode: u32, pub umask: u32, } #[repr(C)] #[derive(Default, Debug)] -pub(super) struct UnlinkIn {} +pub(crate) struct UnlinkIn {} #[repr(C)] #[derive(Default, Debug)] -pub(super) struct UnlinkOut {} +pub(crate) struct UnlinkOut {} #[repr(C)] #[derive(Default, Debug)] -pub(super) struct LseekIn { +pub(crate) struct LseekIn { pub fh: u64, pub offset: u64, pub whence: u32, @@ -236,8 +236,8 @@ pub(super) struct LseekIn { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct LseekOut { - pub(super) offset: u64, +pub(crate) struct LseekOut { + pub(crate) offset: u64, } #[repr(C)] @@ -259,7 +259,7 @@ pub(super) struct PollOut { #[repr(u32)] #[derive(Debug, Copy, Clone)] #[allow(dead_code)] -pub(super) enum Opcode { +pub(crate) enum Opcode { Lookup = 1, Forget = 2, // no reply Getattr = 3, diff --git a/src/lib.rs b/src/lib.rs index 2626d9d374..c584c92547 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,7 @@ #![cfg_attr(target_arch = "riscv64", feature(offset_of))] #![feature(allocator_api)] #![feature(asm_const)] +#![feature(associated_type_defaults)] #![feature(exposed_provenance)] #![feature(linked_list_cursors)] #![feature(maybe_uninit_slice)] From fbb5789508286aa5a019f8b9e5371c3ecbf108d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Sat, 3 Feb 2024 22:03:30 +0100 Subject: [PATCH 04/11] fuse: don't fill in the Rsp skeleton The host does not use the len field of the header of the Rsp (relies on the size field in the In struct if necessary instead). It is not necessary to fill it in during creation and copy it during dispatch. --- src/drivers/fs/virtio_fs.rs | 13 ++-- src/fs/fuse.rs | 133 ++++++++++-------------------------- 2 files changed, 46 insertions(+), 100 deletions(-) diff --git a/src/drivers/fs/virtio_fs.rs b/src/drivers/fs/virtio_fs.rs index a4663da8cb..3ff9578e8e 100644 --- a/src/drivers/fs/virtio_fs.rs +++ b/src/drivers/fs/virtio_fs.rs @@ -153,16 +153,21 @@ impl VirtioFsDriver { } impl FuseInterface for VirtioFsDriver { - fn send_command(&mut self, cmd: & as fuse::OpTrait>::Cmd, rsp: &mut as fuse::OpTrait>::Rsp) - where - fuse::Op: fuse::OpTrait + fn send_command( + &mut self, + cmd: & as fuse::OpTrait>::Cmd, + rsp: &mut as fuse::OpTrait>::Rsp, + ) where + fuse::Op: fuse::OpTrait, { if let Some(mut buff_tkn) = self.ready_queue.pop() { let cmd_len = Some(cmd.len()); let rsp_len = Some(rsp.len()); buff_tkn.restr_size(cmd_len, rsp_len).unwrap(); - let transfer_tkn = buff_tkn.write(Some(cmd), Some(rsp)).unwrap(); + let transfer_tkn = buff_tkn + .write(Some(cmd), None::<& as fuse::OpTrait>::Rsp>) + .unwrap(); let transfer = transfer_tkn.dispatch_blocking().unwrap(); let (_, response) = transfer.ret_cpy().unwrap(); let tkn = transfer.reuse().unwrap(); diff --git a/src/fs/fuse.rs b/src/fs/fuse.rs index e3cb79930a..0896b78479 100644 --- a/src/fs/fuse.rs +++ b/src/fs/fuse.rs @@ -38,8 +38,11 @@ const S_IFLNK: u32 = 40960; const S_IFMT: u32 = 61440; pub(crate) trait FuseInterface { - fn send_command(&mut self, cmd: & as OpTrait>::Cmd, rsp: &mut as OpTrait>::Rsp) - where + fn send_command( + &mut self, + cmd: & as OpTrait>::Cmd, + rsp: &mut as OpTrait>::Rsp, + ) where Op: OpTrait; fn get_mount_point(&self) -> String; @@ -89,62 +92,62 @@ pub(crate) trait OpTrait { pub(crate) struct Op; -impl OpTrait for Op<{fuse_abi::Opcode::Init as u32}> { +impl OpTrait for Op<{ fuse_abi::Opcode::Init as u32 }> { type InStruct = fuse_abi::InitIn; type OutStruct = fuse_abi::InitOut; } -impl OpTrait for Op<{fuse_abi::Opcode::Create as u32}> { +impl OpTrait for Op<{ fuse_abi::Opcode::Create as u32 }> { type InStruct = fuse_abi::CreateIn; type OutStruct = fuse_abi::CreateOut; } -impl OpTrait for Op<{fuse_abi::Opcode::Open as u32}> { +impl OpTrait for Op<{ fuse_abi::Opcode::Open as u32 }> { type InStruct = fuse_abi::OpenIn; type OutStruct = fuse_abi::OpenOut; } -impl OpTrait for Op<{fuse_abi::Opcode::Write as u32}> { +impl OpTrait for Op<{ fuse_abi::Opcode::Write as u32 }> { type InStruct = fuse_abi::WriteIn; type OutStruct = fuse_abi::WriteOut; } -impl OpTrait for Op<{fuse_abi::Opcode::Read as u32}> { +impl OpTrait for Op<{ fuse_abi::Opcode::Read as u32 }> { type InStruct = fuse_abi::ReadIn; type OutStruct = fuse_abi::ReadOut; } -impl OpTrait for Op<{fuse_abi::Opcode::Lseek as u32}> { +impl OpTrait for Op<{ fuse_abi::Opcode::Lseek as u32 }> { type InStruct = fuse_abi::LseekIn; type OutStruct = fuse_abi::LseekOut; } -impl OpTrait for Op<{fuse_abi::Opcode::Readlink as u32}> { +impl OpTrait for Op<{ fuse_abi::Opcode::Readlink as u32 }> { type InStruct = fuse_abi::ReadlinkIn; type OutStruct = fuse_abi::ReadlinkOut; } -impl OpTrait for Op<{fuse_abi::Opcode::Release as u32}> { +impl OpTrait for Op<{ fuse_abi::Opcode::Release as u32 }> { type InStruct = fuse_abi::ReleaseIn; type OutStruct = fuse_abi::ReleaseOut; } -impl OpTrait for Op<{fuse_abi::Opcode::Mkdir as u32}> { +impl OpTrait for Op<{ fuse_abi::Opcode::Mkdir as u32 }> { type InStruct = fuse_abi::MkdirIn; type OutStruct = fuse_abi::EntryOut; } -impl OpTrait for Op<{fuse_abi::Opcode::Unlink as u32}> { +impl OpTrait for Op<{ fuse_abi::Opcode::Unlink as u32 }> { type InStruct = fuse_abi::UnlinkIn; type OutStruct = fuse_abi::UnlinkOut; } -impl OpTrait for Op<{fuse_abi::Opcode::Rmdir as u32}> { +impl OpTrait for Op<{ fuse_abi::Opcode::Rmdir as u32 }> { type InStruct = fuse_abi::RmdirIn; type OutStruct = fuse_abi::RmdirOut; } -impl OpTrait for Op<{fuse_abi::Opcode::Lookup as u32}> { +impl OpTrait for Op<{ fuse_abi::Opcode::Lookup as u32 }> { type InStruct = fuse_abi::LookupIn; type OutStruct = fuse_abi::EntryOut; } @@ -194,11 +197,7 @@ pub(crate) struct Rsp { extra_buffer: [MaybeUninit], } -impl AsSliceU8 for Rsp { - fn len(&self) -> usize { - self.header.len.try_into().unwrap() - } -} +impl AsSliceU8 for Rsp {} fn create_in_header(nodeid: u64, opcode: fuse_abi::Opcode) -> fuse_abi::InHeader where @@ -255,11 +254,6 @@ fn create_init() -> (Box>, Box>) { let rsp = unsafe { let data = alloc(layout); let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - (*raw).header = fuse_abi::OutHeader { - len: len.try_into().unwrap(), - ..Default::default() - }; - Box::from_raw(raw) }; assert_eq!(layout, Layout::for_value(&*rsp)); @@ -319,11 +313,6 @@ fn create_create( let rsp = unsafe { let data = alloc(layout); let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - (*raw).header = fuse_abi::OutHeader { - len: len.try_into().unwrap(), - ..Default::default() - }; - Box::from_raw(raw) }; assert_eq!(layout, Layout::for_value(&*rsp)); @@ -369,11 +358,6 @@ fn create_open(nid: u64, flags: u32) -> (Box>, Box; - (*raw).header = fuse_abi::OutHeader { - len: len.try_into().unwrap(), - ..Default::default() - }; - Box::from_raw(raw) }; assert_eq!(layout, Layout::for_value(&*rsp)); @@ -437,11 +421,6 @@ fn create_write( let rsp = unsafe { let data = alloc(layout); let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - (*raw).header = fuse_abi::OutHeader { - len: len.try_into().unwrap(), - ..Default::default() - }; - Box::from_raw(raw) }; assert_eq!(layout, Layout::for_value(&*rsp)); @@ -496,11 +475,6 @@ fn create_read( let data = alloc(layout); let raw = core::ptr::slice_from_raw_parts_mut(data, size.try_into().unwrap()) as *mut Rsp; - (*raw).header = fuse_abi::OutHeader { - len: len.try_into().unwrap(), - ..Default::default() - }; - Box::from_raw(raw) }; assert_eq!(layout, Layout::for_value(&*rsp)); @@ -560,11 +534,6 @@ fn create_lseek( let rsp = unsafe { let data = alloc(layout); let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - (*raw).header = fuse_abi::OutHeader { - len: len.try_into().unwrap(), - ..Default::default() - }; - Box::from_raw(raw) }; assert_eq!(layout, Layout::for_value(&*rsp)); @@ -616,11 +585,6 @@ fn create_readlink( let data = alloc(layout); let raw = core::ptr::slice_from_raw_parts_mut(data, size.try_into().unwrap()) as *mut Rsp; - (*raw).header = fuse_abi::OutHeader { - len: len.try_into().unwrap(), - ..Default::default() - }; - Box::from_raw(raw) }; assert_eq!(layout, Layout::for_value(&*rsp)); @@ -673,11 +637,6 @@ fn create_release( let rsp = unsafe { let data = alloc(layout); let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - (*raw).header = fuse_abi::OutHeader { - len: len.try_into().unwrap(), - ..Default::default() - }; - Box::from_raw(raw) }; assert_eq!(layout, Layout::for_value(&*rsp)); @@ -792,11 +751,6 @@ fn create_mkdir( let rsp = unsafe { let data = alloc(layout); let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - (*raw).header = fuse_abi::OutHeader { - len: len.try_into().unwrap(), - ..Default::default() - }; - Box::from_raw(raw) }; assert_eq!(layout, Layout::for_value(&*rsp)); @@ -847,11 +801,6 @@ fn create_unlink(name: &str) -> (Box>, Box; - (*raw).header = fuse_abi::OutHeader { - len: len.try_into().unwrap(), - ..Default::default() - }; - Box::from_raw(raw) }; assert_eq!(layout, Layout::for_value(&*rsp)); @@ -902,11 +851,6 @@ fn create_rmdir(name: &str) -> (Box>, Box; - (*raw).header = fuse_abi::OutHeader { - len: len.try_into().unwrap(), - ..Default::default() - }; - Box::from_raw(raw) }; assert_eq!(layout, Layout::for_value(&*rsp)); @@ -957,11 +901,6 @@ fn create_lookup(name: &str) -> (Box>, Box; - (*raw).header = fuse_abi::OutHeader { - len: len.try_into().unwrap(), - ..Default::default() - }; - Box::from_raw(raw) }; assert_eq!(layout, Layout::for_value(&*rsp)); @@ -974,7 +913,7 @@ fn lookup(name: &str) -> Option { get_filesystem_driver() .unwrap() .lock() - .send_command::<{fuse_abi::Opcode::Lookup as u32}>(cmd.as_ref(), rsp.as_mut()); + .send_command::<{ fuse_abi::Opcode::Lookup as u32 }>(cmd.as_ref(), rsp.as_mut()); if rsp.header.error == 0 { Some(unsafe { rsp.rsp.assume_init().nodeid }) } else { @@ -988,7 +927,7 @@ fn readlink(nid: u64) -> Result { get_filesystem_driver() .unwrap() .lock() - .send_command::<{fuse_abi::Opcode::Readlink as u32}>(cmd.as_ref(), rsp.as_mut()); + .send_command::<{ fuse_abi::Opcode::Readlink as u32 }>(cmd.as_ref(), rsp.as_mut()); let len: usize = if rsp.header.len as usize - ::core::mem::size_of::() - ::core::mem::size_of::() @@ -1070,7 +1009,7 @@ impl FuseFileHandleInner { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{fuse_abi::Opcode::Read as u32}>(cmd.as_ref(), rsp.as_mut()); + .send_command::<{ fuse_abi::Opcode::Read as u32 }>(cmd.as_ref(), rsp.as_mut()); let len: usize = if rsp.header.len as usize - ::core::mem::size_of::() - ::core::mem::size_of::() @@ -1111,7 +1050,7 @@ impl FuseFileHandleInner { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{fuse_abi::Opcode::Write as u32}>(cmd.as_ref(), rsp.as_mut()); + .send_command::<{ fuse_abi::Opcode::Write as u32 }>(cmd.as_ref(), rsp.as_mut()); if rsp.header.error < 0 { return Err(IoError::EIO); @@ -1139,7 +1078,7 @@ impl FuseFileHandleInner { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{fuse_abi::Opcode::Lseek as u32}>(cmd.as_ref(), rsp.as_mut()); + .send_command::<{ fuse_abi::Opcode::Lseek as u32 }>(cmd.as_ref(), rsp.as_mut()); if rsp.header.error < 0 { return Err(IoError::EIO); @@ -1161,7 +1100,7 @@ impl Drop for FuseFileHandleInner { get_filesystem_driver() .unwrap() .lock() - .send_command::<{fuse_abi::Opcode::Release as u32}>(cmd.as_ref(), rsp.as_mut()); + .send_command::<{ fuse_abi::Opcode::Release as u32 }>(cmd.as_ref(), rsp.as_mut()); } } } @@ -1238,7 +1177,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{fuse_abi::Opcode::Open as u32}>(cmd.as_ref(), rsp.as_mut()); + .send_command::<{ fuse_abi::Opcode::Open as u32 }>(cmd.as_ref(), rsp.as_mut()); let fuse_fh = unsafe { rsp.rsp.assume_init().fh }; debug!("FUSE readdir: {}", path); @@ -1253,7 +1192,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{fuse_abi::Opcode::Read as u32}>(cmd.as_ref(), rsp.as_mut()); + .send_command::<{ fuse_abi::Opcode::Read as u32 }>(cmd.as_ref(), rsp.as_mut()); let len: usize = if rsp.header.len as usize - ::core::mem::size_of::() @@ -1297,7 +1236,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .unwrap() .lock() - .send_command::<{fuse_abi::Opcode::Release as u32}>(cmd.as_ref(), rsp.as_mut()); + .send_command::<{ fuse_abi::Opcode::Release as u32 }>(cmd.as_ref(), rsp.as_mut()); Ok(entries) } @@ -1320,7 +1259,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .unwrap() .lock() - .send_command::<{fuse_abi::Opcode::Lookup as u32}>(cmd.as_ref(), rsp.as_mut()); + .send_command::<{ fuse_abi::Opcode::Lookup as u32 }>(cmd.as_ref(), rsp.as_mut()); if rsp.header.error != 0 { // TODO: Correct error handling @@ -1356,7 +1295,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .unwrap() .lock() - .send_command::<{fuse_abi::Opcode::Lookup as u32}>(cmd.as_ref(), rsp.as_mut()); + .send_command::<{ fuse_abi::Opcode::Lookup as u32 }>(cmd.as_ref(), rsp.as_mut()); let attr = unsafe { rsp.rsp.assume_init().attr }; Ok(FileAttr::from(attr)) @@ -1402,7 +1341,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{fuse_abi::Opcode::Open as u32}>(cmd.as_ref(), rsp.as_mut()); + .send_command::<{ fuse_abi::Opcode::Open as u32 }>(cmd.as_ref(), rsp.as_mut()); file_guard.fuse_fh = Some(unsafe { rsp.rsp.assume_init().fh }); } else { // Create file (opens implicitly, returns results from both lookup and open calls) @@ -1410,7 +1349,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{fuse_abi::Opcode::Create as u32}>(cmd.as_ref(), rsp.as_mut()); + .send_command::<{ fuse_abi::Opcode::Create as u32 }>(cmd.as_ref(), rsp.as_mut()); let inner = unsafe { rsp.rsp.assume_init() }; file_guard.fuse_nid = Some(inner.entry.nodeid); @@ -1437,7 +1376,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{fuse_abi::Opcode::Unlink as u32}>(cmd.as_ref(), rsp.as_mut()); + .send_command::<{ fuse_abi::Opcode::Unlink as u32 }>(cmd.as_ref(), rsp.as_mut()); trace!("unlink answer {:?}", rsp); Ok(()) @@ -1458,7 +1397,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{fuse_abi::Opcode::Rmdir as u32}>(cmd.as_ref(), rsp.as_mut()); + .send_command::<{ fuse_abi::Opcode::Rmdir as u32 }>(cmd.as_ref(), rsp.as_mut()); trace!("rmdir answer {:?}", rsp); Ok(()) @@ -1483,7 +1422,7 @@ impl VfsNode for FuseDirectory { get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{fuse_abi::Opcode::Mkdir as u32}>(cmd.as_ref(), rsp.as_mut()); + .send_command::<{ fuse_abi::Opcode::Mkdir as u32 }>(cmd.as_ref(), rsp.as_mut()); if rsp.header.error == 0 { Ok(()) } else { @@ -1497,7 +1436,9 @@ pub(crate) fn init() { if let Some(driver) = get_filesystem_driver() { let (cmd, mut rsp) = create_init(); - driver.lock().send_command::<{fuse_abi::Opcode::Init as u32}>(cmd.as_ref(), rsp.as_mut()); + driver + .lock() + .send_command::<{ fuse_abi::Opcode::Init as u32 }>(cmd.as_ref(), rsp.as_mut()); trace!("fuse init answer: {:?}", rsp); let mount_point = format!("/{}", driver.lock().get_mount_point()); From a2212c010250c69ce581a9459683ae14a7b963ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Sun, 4 Feb 2024 16:43:58 +0100 Subject: [PATCH 05/11] fuse: simplify Cmd creation --- src/fs/fuse.rs | 618 ++++++++++++++++++++----------------------------- src/lib.rs | 1 + 2 files changed, 258 insertions(+), 361 deletions(-) diff --git a/src/fs/fuse.rs b/src/fs/fuse.rs index 0896b78479..743b04f94b 100644 --- a/src/fs/fuse.rs +++ b/src/fs/fuse.rs @@ -4,6 +4,7 @@ use alloc::boxed::Box; use alloc::string::String; use alloc::sync::Arc; use alloc::vec::Vec; +use core::ffi::CStr; use core::mem::MaybeUninit; use core::sync::atomic::{AtomicU64, Ordering}; use core::task::Poll; @@ -84,9 +85,10 @@ unsafe impl FuseOut for fuse_abi::PollOut {} pub(crate) trait OpTrait { type InStruct: FuseIn + core::fmt::Debug; + type InPayload: ?Sized; type OutStruct: FuseOut + core::fmt::Debug; - type Cmd: ?Sized + AsSliceU8 = Cmd; + type Cmd: ?Sized + AsSliceU8 = Cmd; type Rsp: ?Sized + AsSliceU8 = Rsp; } @@ -94,61 +96,73 @@ pub(crate) struct Op; impl OpTrait for Op<{ fuse_abi::Opcode::Init as u32 }> { type InStruct = fuse_abi::InitIn; + type InPayload = (); type OutStruct = fuse_abi::InitOut; } impl OpTrait for Op<{ fuse_abi::Opcode::Create as u32 }> { type InStruct = fuse_abi::CreateIn; + type InPayload = CStr; type OutStruct = fuse_abi::CreateOut; } impl OpTrait for Op<{ fuse_abi::Opcode::Open as u32 }> { type InStruct = fuse_abi::OpenIn; + type InPayload = (); type OutStruct = fuse_abi::OpenOut; } impl OpTrait for Op<{ fuse_abi::Opcode::Write as u32 }> { type InStruct = fuse_abi::WriteIn; + type InPayload = [u8]; type OutStruct = fuse_abi::WriteOut; } impl OpTrait for Op<{ fuse_abi::Opcode::Read as u32 }> { type InStruct = fuse_abi::ReadIn; + type InPayload = (); type OutStruct = fuse_abi::ReadOut; } impl OpTrait for Op<{ fuse_abi::Opcode::Lseek as u32 }> { type InStruct = fuse_abi::LseekIn; + type InPayload = (); type OutStruct = fuse_abi::LseekOut; } impl OpTrait for Op<{ fuse_abi::Opcode::Readlink as u32 }> { type InStruct = fuse_abi::ReadlinkIn; + type InPayload = (); type OutStruct = fuse_abi::ReadlinkOut; } impl OpTrait for Op<{ fuse_abi::Opcode::Release as u32 }> { type InStruct = fuse_abi::ReleaseIn; + type InPayload = (); type OutStruct = fuse_abi::ReleaseOut; } impl OpTrait for Op<{ fuse_abi::Opcode::Mkdir as u32 }> { type InStruct = fuse_abi::MkdirIn; + type InPayload = CStr; type OutStruct = fuse_abi::EntryOut; } impl OpTrait for Op<{ fuse_abi::Opcode::Unlink as u32 }> { type InStruct = fuse_abi::UnlinkIn; + type InPayload = CStr; type OutStruct = fuse_abi::UnlinkOut; } impl OpTrait for Op<{ fuse_abi::Opcode::Rmdir as u32 }> { type InStruct = fuse_abi::RmdirIn; + type InPayload = CStr; type OutStruct = fuse_abi::RmdirOut; } impl OpTrait for Op<{ fuse_abi::Opcode::Lookup as u32 }> { type InStruct = fuse_abi::LookupIn; + type InPayload = CStr; type OutStruct = fuse_abi::EntryOut; } @@ -177,68 +191,138 @@ impl From for FileAttr { #[repr(C)] #[derive(Debug)] -pub(crate) struct Cmd { - header: fuse_abi::InHeader, - cmd: T, - extra_buffer: [u8], +pub(crate) struct ReqPart { + common_header: H, + op_header: T, + payload: P, } -impl AsSliceU8 for Cmd { +type Cmd = ReqPart; +type Rsp = ReqPart, [MaybeUninit]>; + +impl AsSliceU8 for Cmd { fn len(&self) -> usize { - self.header.len.try_into().unwrap() + self.common_header.len.try_into().unwrap() } } -#[repr(C)] -#[derive(Debug)] -pub(crate) struct Rsp { - header: fuse_abi::OutHeader, - rsp: MaybeUninit, - extra_buffer: [MaybeUninit], +impl AsSliceU8 for Rsp {} + +impl ReqPart +where + Self: core::ptr::Pointee, +{ + // MaybeUninit does not accept DSTs as type parameter + unsafe fn new_uninit(len: usize) -> Box { + unsafe { + Box::from_raw(core::ptr::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(), + ) as *mut (), + len, + )) + } + } } -impl AsSliceU8 for Rsp {} +// We create the objects through the Operation struct rather than the Cmd struct to be able access the Opcode. -fn create_in_header(nodeid: u64, opcode: fuse_abi::Opcode) -> fuse_abi::InHeader +impl Op where - T: FuseIn, + Self: OpTrait::InStruct, ()>>, { - fuse_abi::InHeader { - len: (core::mem::size_of::() + core::mem::size_of::()) as u32, - opcode: opcode as u32, - unique: 1, - nodeid, - ..Default::default() + fn new_cmd( + nodeid: u64, + op_header: ::InStruct, + ) -> Box::InStruct, ()>> { + Box::new(ReqPart { + common_header: fuse_abi::InHeader { + len: Layout::new::<::Cmd>().size() as u32, + opcode: O, + nodeid, + unique: 1, + ..Default::default() + }, + op_header, + payload: (), + }) } } -fn create_init() -> (Box>, Box>) { - let len = core::mem::size_of::() + core::mem::size_of::(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let cmd = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; - (*raw).header = - create_in_header::(fuse_abi::ROOT_ID, fuse_abi::Opcode::Init); - (*raw).header.len = len.try_into().unwrap(); - (*raw).cmd = fuse_abi::InitIn { +impl Op +where + Self: OpTrait, +{ + fn cmd_with_capacity( + nodeid: u64, + op_header: as OpTrait>::InStruct, + len: usize, + ) -> Box::InStruct, [u8]>> { + let mut cmd = unsafe { Cmd::new_uninit(len) }; + cmd.common_header = fuse_abi::InHeader { + len: core::mem::size_of_val(cmd.as_ref()) + .try_into() + .expect("The command is too large"), + opcode: O, + nodeid, + unique: 1, + ..Default::default() + }; + cmd.op_header = op_header; + cmd + } +} + +impl Op +where + Self: OpTrait::InStruct, [u8]>>, +{ + fn cmd_from_array( + nodeid: u64, + op_header: ::InStruct, + data: &[u8], + ) -> Box<::Cmd> { + let mut cmd = Self::cmd_with_capacity(nodeid, op_header, data.len()); + cmd.payload.copy_from_slice(data); + cmd + } +} + +impl Op +where + Self: OpTrait::InStruct, CStr>>, +{ + fn cmd_from_str( + nodeid: u64, + op_header: ::InStruct, + str: &str, + ) -> Box<::Cmd> { + let str_bytes = str.as_bytes(); + // Plus one for the NUL terminator + let mut cmd = Self::cmd_with_capacity(nodeid, op_header, str_bytes.len() + 1); + cmd.payload[..str_bytes.len()].copy_from_slice(str_bytes); + cmd.payload[str_bytes.len()] = b'\0'; + unsafe { core::intrinsics::transmute(cmd) } + } +} + +fn create_init() -> ( + Box< as OpTrait>::Cmd>, + Box>, +) { + let cmd = Op::<{ fuse_abi::Opcode::Init as u32 }>::new_cmd( + fuse_abi::ROOT_ID, + fuse_abi::InitIn { major: 7, minor: 31, max_readahead: 0, flags: 0, - }; - - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*cmd)); + }, + ); let len = core::mem::size_of::() + core::mem::size_of::(); @@ -265,39 +349,19 @@ fn create_create( path: &str, flags: u32, mode: u32, -) -> (Box>, Box>) { - let slice = path.as_bytes(); - let len = core::mem::size_of::() - + core::mem::size_of::() - + slice.len() - + 1; - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let cmd = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, slice.len() + 1) - as *mut Cmd; - (*raw).header = - create_in_header::(fuse_abi::ROOT_ID, fuse_abi::Opcode::Create); - (*raw).header.len = len.try_into().unwrap(); - (*raw).cmd = fuse_abi::CreateIn { +) -> ( + Box< as OpTrait>::Cmd>, + Box>, +) { + let cmd = Op::<{ fuse_abi::Opcode::Create as u32 }>::cmd_from_str( + fuse_abi::ROOT_ID, + fuse_abi::CreateIn { flags, mode, ..Default::default() - }; - (*raw).extra_buffer[..slice.len()].copy_from_slice(slice); - (*raw).extra_buffer[slice.len()] = 0; - - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*cmd)); + }, + path, + ); let len = core::mem::size_of::() + core::mem::size_of::(); @@ -320,29 +384,20 @@ fn create_create( (cmd, rsp) } -fn create_open(nid: u64, flags: u32) -> (Box>, Box>) { - let len = core::mem::size_of::() + core::mem::size_of::(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let cmd = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; - (*raw).header = create_in_header::(nid, fuse_abi::Opcode::Open); - (*raw).cmd = fuse_abi::OpenIn { +fn create_open( + nid: u64, + flags: u32, +) -> ( + Box< as OpTrait>::Cmd>, + Box>, +) { + let cmd = Op::<{ fuse_abi::Opcode::Open as u32 }>::new_cmd( + nid, + fuse_abi::OpenIn { flags, ..Default::default() - }; - - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*cmd)); + }, + ); let len = core::mem::size_of::() + core::mem::size_of::(); @@ -371,41 +426,20 @@ fn create_write( fh: u64, buf: &[u8], offset: u64, -) -> (Box>, Box>) { - let len = core::mem::size_of::() - + core::mem::size_of::() - + buf.len(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let cmd = unsafe { - let data = alloc(layout); - let raw = - core::ptr::slice_from_raw_parts_mut(data, buf.len()) as *mut Cmd; - (*raw).header = fuse_abi::InHeader { - len: len.try_into().unwrap(), - opcode: fuse_abi::Opcode::Write as u32, - unique: 1, - nodeid: nid, - ..Default::default() - }; - (*raw).cmd = fuse_abi::WriteIn { +) -> ( + Box< as OpTrait>::Cmd>, + Box>, +) { + let cmd = Op::<{ fuse_abi::Opcode::Write as u32 }>::cmd_from_array( + nid, + fuse_abi::WriteIn { fh, offset, size: buf.len().try_into().unwrap(), ..Default::default() - }; - (*raw).extra_buffer.copy_from_slice(buf); - - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*cmd)); + }, + buf, + ); let len = core::mem::size_of::() + core::mem::size_of::(); @@ -433,31 +467,19 @@ fn create_read( fh: u64, size: u32, offset: u64, -) -> (Box>, Box>) { - let len = core::mem::size_of::() + core::mem::size_of::(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let cmd = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; - (*raw).header = create_in_header::(nid, fuse_abi::Opcode::Read); - (*raw).cmd = fuse_abi::ReadIn { +) -> ( + Box< as OpTrait>::Cmd>, + Box>, +) { + let cmd = Op::<{ fuse_abi::Opcode::Read as u32 }>::new_cmd( + nid, + fuse_abi::ReadIn { fh, offset, size, ..Default::default() - }; - - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*cmd)); + }, + ); let len = core::mem::size_of::() + core::mem::size_of::() @@ -487,38 +509,19 @@ fn create_lseek( fh: u64, offset: isize, whence: SeekWhence, -) -> (Box>, Box>) { - let len = - core::mem::size_of::() + core::mem::size_of::(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let cmd = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; - (*raw).header = fuse_abi::InHeader { - len: len.try_into().unwrap(), - opcode: fuse_abi::Opcode::Lseek as u32, - unique: 1, - nodeid: nid, - ..Default::default() - }; - (*raw).cmd = fuse_abi::LseekIn { +) -> ( + Box< as OpTrait>::Cmd>, + Box>, +) { + let cmd = Op::<{ fuse_abi::Opcode::Lseek as u32 }>::new_cmd( + nid, + fuse_abi::LseekIn { fh, offset: offset.try_into().unwrap(), whence: num::ToPrimitive::to_u32(&whence).unwrap(), ..Default::default() - }; - - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*cmd)); + }, + ); let len = core::mem::size_of::() + core::mem::size_of::(); @@ -545,29 +548,10 @@ fn create_readlink( nid: u64, size: u32, ) -> ( - Box>, + Box< as OpTrait>::Cmd>, Box>, ) { - let len = - core::mem::size_of::() + core::mem::size_of::(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let cmd = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; - (*raw).header = create_in_header::(nid, fuse_abi::Opcode::Readlink); - (*raw).header.len = len.try_into().unwrap(); - - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*cmd)); + let cmd = Op::<{ fuse_abi::Opcode::Readlink as u32 }>::new_cmd(nid, fuse_abi::ReadlinkIn {}); let len = core::mem::size_of::() + core::mem::size_of::() @@ -596,32 +580,16 @@ fn create_release( nid: u64, fh: u64, ) -> ( - Box>, + Box< as OpTrait>::Cmd>, Box>, ) { - let len = - core::mem::size_of::() + core::mem::size_of::(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let cmd = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; - (*raw).header = create_in_header::(nid, fuse_abi::Opcode::Release); - (*raw).cmd = fuse_abi::ReleaseIn { + let cmd = Op::<{ fuse_abi::Opcode::Release as u32 }>::new_cmd( + nid, + fuse_abi::ReleaseIn { fh, ..Default::default() - }; - - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*cmd)); + }, + ); let len = core::mem::size_of::() + core::mem::size_of::(); @@ -704,38 +672,18 @@ fn create_poll( fn create_mkdir( path: &str, mode: u32, -) -> (Box>, Box>) { - let slice = path.as_bytes(); - let len = core::mem::size_of::() - + core::mem::size_of::() - + slice.len() - + 1; - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let cmd = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, slice.len() + 1) - as *mut Cmd; - (*raw).header = - create_in_header::(fuse_abi::ROOT_ID, fuse_abi::Opcode::Mkdir); - (*raw).header.len = len.try_into().unwrap(); - (*raw).cmd = fuse_abi::MkdirIn { +) -> ( + Box< as OpTrait>::Cmd>, + Box>, +) { + let cmd = Op::<{ fuse_abi::Opcode::Mkdir as u32 }>::cmd_from_str( + fuse_abi::ROOT_ID, + fuse_abi::MkdirIn { mode, ..Default::default() - }; - (*raw).extra_buffer[..slice.len()].copy_from_slice(slice); - (*raw).extra_buffer[slice.len()] = 0; - - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*cmd)); + }, + path, + ); let len = core::mem::size_of::() + core::mem::size_of::(); @@ -758,34 +706,17 @@ fn create_mkdir( (cmd, rsp) } -fn create_unlink(name: &str) -> (Box>, Box>) { - let slice = name.as_bytes(); - let len = core::mem::size_of::() - + core::mem::size_of::() - + slice.len() - + 1; - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let cmd = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, slice.len() + 1) - as *mut Cmd; - (*raw).header = - create_in_header::(fuse_abi::ROOT_ID, fuse_abi::Opcode::Unlink); - (*raw).header.len = len.try_into().unwrap(); - (*raw).extra_buffer[..slice.len()].copy_from_slice(slice); - (*raw).extra_buffer[slice.len()] = 0; - - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*cmd)); +fn create_unlink( + name: &str, +) -> ( + Box< as OpTrait>::Cmd>, + Box>, +) { + let cmd = Op::<{ fuse_abi::Opcode::Unlink as u32 }>::cmd_from_str( + fuse_abi::ROOT_ID, + fuse_abi::UnlinkIn {}, + name, + ); let len = core::mem::size_of::() + core::mem::size_of::(); @@ -808,34 +739,17 @@ fn create_unlink(name: &str) -> (Box>, Box (Box>, Box>) { - let slice = name.as_bytes(); - let len = core::mem::size_of::() - + core::mem::size_of::() - + slice.len() - + 1; - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let cmd = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, slice.len() + 1) - as *mut Cmd; - (*raw).header = - create_in_header::(fuse_abi::ROOT_ID, fuse_abi::Opcode::Rmdir); - (*raw).header.len = len.try_into().unwrap(); - (*raw).extra_buffer[..slice.len()].copy_from_slice(slice); - (*raw).extra_buffer[slice.len()] = 0; - - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*cmd)); +fn create_rmdir( + name: &str, +) -> ( + Box< as OpTrait>::Cmd>, + Box>, +) { + let cmd = Op::<{ fuse_abi::Opcode::Rmdir as u32 }>::cmd_from_str( + fuse_abi::ROOT_ID, + fuse_abi::RmdirIn {}, + name, + ); let len = core::mem::size_of::() + core::mem::size_of::(); @@ -858,34 +772,17 @@ fn create_rmdir(name: &str) -> (Box>, Box (Box>, Box>) { - let slice = name.as_bytes(); - let len = core::mem::size_of::() - + core::mem::size_of::() - + slice.len() - + 1; - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let cmd = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, slice.len() + 1) - as *mut Cmd; - (*raw).header = - create_in_header::(fuse_abi::ROOT_ID, fuse_abi::Opcode::Lookup); - (*raw).header.len = len.try_into().unwrap(); - (*raw).extra_buffer[..slice.len()].copy_from_slice(slice); - (*raw).extra_buffer[slice.len()] = 0; - - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*cmd)); +fn create_lookup( + name: &str, +) -> ( + Box< as OpTrait>::Cmd>, + Box>, +) { + let cmd = Op::<{ fuse_abi::Opcode::Lookup as u32 }>::cmd_from_str( + fuse_abi::ROOT_ID, + fuse_abi::LookupIn {}, + name, + ); let len = core::mem::size_of::() + core::mem::size_of::(); @@ -914,8 +811,8 @@ fn lookup(name: &str) -> Option { .unwrap() .lock() .send_command::<{ fuse_abi::Opcode::Lookup as u32 }>(cmd.as_ref(), rsp.as_mut()); - if rsp.header.error == 0 { - Some(unsafe { rsp.rsp.assume_init().nodeid }) + if rsp.common_header.error == 0 { + Some(unsafe { rsp.op_header.assume_init().nodeid }) } else { None } @@ -928,20 +825,20 @@ fn readlink(nid: u64) -> Result { .unwrap() .lock() .send_command::<{ fuse_abi::Opcode::Readlink as u32 }>(cmd.as_ref(), rsp.as_mut()); - let len: usize = if rsp.header.len as usize + let len: usize = if rsp.common_header.len as usize - ::core::mem::size_of::() - ::core::mem::size_of::() >= len.try_into().unwrap() { len.try_into().unwrap() } else { - rsp.header.len as usize + rsp.common_header.len as usize - ::core::mem::size_of::() - ::core::mem::size_of::() }; Ok(String::from_utf8(unsafe { - MaybeUninit::slice_assume_init_ref(&rsp.extra_buffer[..len]).to_vec() + MaybeUninit::slice_assume_init_ref(&rsp.payload[..len]).to_vec() }) .unwrap()) } @@ -1010,21 +907,21 @@ impl FuseFileHandleInner { .ok_or(IoError::ENOSYS)? .lock() .send_command::<{ fuse_abi::Opcode::Read as u32 }>(cmd.as_ref(), rsp.as_mut()); - let len: usize = if rsp.header.len as usize + let len: usize = if rsp.common_header.len as usize - ::core::mem::size_of::() - ::core::mem::size_of::() >= len { len } else { - rsp.header.len as usize + rsp.common_header.len as usize - ::core::mem::size_of::() - ::core::mem::size_of::() }; self.offset += len; buf[..len].copy_from_slice(unsafe { - MaybeUninit::slice_assume_init_ref(&rsp.extra_buffer[..len]) + MaybeUninit::slice_assume_init_ref(&rsp.payload[..len]) }); Ok(len) @@ -1052,11 +949,11 @@ impl FuseFileHandleInner { .lock() .send_command::<{ fuse_abi::Opcode::Write as u32 }>(cmd.as_ref(), rsp.as_mut()); - if rsp.header.error < 0 { + if rsp.common_header.error < 0 { return Err(IoError::EIO); } - let rsp_size = unsafe { rsp.rsp.assume_init().size }; + let rsp_size = unsafe { rsp.op_header.assume_init().size }; let len: usize = if rsp_size > buf.len().try_into().unwrap() { buf.len() } else { @@ -1080,11 +977,11 @@ impl FuseFileHandleInner { .lock() .send_command::<{ fuse_abi::Opcode::Lseek as u32 }>(cmd.as_ref(), rsp.as_mut()); - if rsp.header.error < 0 { + if rsp.common_header.error < 0 { return Err(IoError::EIO); } - let rsp_offset = unsafe { rsp.rsp.assume_init().offset }; + let rsp_offset = unsafe { rsp.op_header.assume_init().offset }; Ok(rsp_offset.try_into().unwrap()) } else { @@ -1173,12 +1070,12 @@ impl VfsNode for FuseDirectory { // Opendir // Flag 0x10000 for O_DIRECTORY might not be necessary let (mut cmd, mut rsp) = create_open(fuse_nid, 0x10000); - cmd.header.opcode = fuse_abi::Opcode::Opendir as u32; + cmd.common_header.opcode = fuse_abi::Opcode::Opendir as u32; get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() .send_command::<{ fuse_abi::Opcode::Open as u32 }>(cmd.as_ref(), rsp.as_mut()); - let fuse_fh = unsafe { rsp.rsp.assume_init().fh }; + let fuse_fh = unsafe { rsp.op_header.assume_init().fh }; debug!("FUSE readdir: {}", path); @@ -1188,20 +1085,20 @@ impl VfsNode for FuseDirectory { // read content of the directory let (mut cmd, mut rsp) = create_read(fuse_nid, fuse_fh, len, 0); - cmd.header.opcode = fuse_abi::Opcode::Readdir as u32; + cmd.common_header.opcode = fuse_abi::Opcode::Readdir as u32; get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() .send_command::<{ fuse_abi::Opcode::Read as u32 }>(cmd.as_ref(), rsp.as_mut()); - let len: usize = if rsp.header.len as usize + let len: usize = if rsp.common_header.len as usize - ::core::mem::size_of::() - ::core::mem::size_of::() >= len.try_into().unwrap() { len.try_into().unwrap() } else { - rsp.header.len as usize + rsp.common_header.len as usize - ::core::mem::size_of::() - ::core::mem::size_of::() }; @@ -1212,10 +1109,9 @@ impl VfsNode for FuseDirectory { } let mut entries: Vec = Vec::new(); - while rsp.header.len as usize - offset > core::mem::size_of::() { - let dirent = unsafe { - &*(rsp.extra_buffer.as_ptr().byte_add(offset) as *const fuse_abi::Dirent) - }; + while rsp.common_header.len as usize - offset > core::mem::size_of::() { + let dirent = + unsafe { &*(rsp.payload.as_ptr().byte_add(offset) as *const fuse_abi::Dirent) }; offset += core::mem::size_of::() + dirent.d_namelen as usize; // Allign to dirent struct @@ -1261,12 +1157,12 @@ impl VfsNode for FuseDirectory { .lock() .send_command::<{ fuse_abi::Opcode::Lookup as u32 }>(cmd.as_ref(), rsp.as_mut()); - if rsp.header.error != 0 { + if rsp.common_header.error != 0 { // TODO: Correct error handling return Err(IoError::EIO); } - let rsp = unsafe { rsp.rsp.assume_init() }; + let rsp = unsafe { rsp.op_header.assume_init() }; let attr = rsp.attr; if attr.mode & S_IFMT != S_IFLNK { @@ -1297,7 +1193,7 @@ impl VfsNode for FuseDirectory { .lock() .send_command::<{ fuse_abi::Opcode::Lookup as u32 }>(cmd.as_ref(), rsp.as_mut()); - let attr = unsafe { rsp.rsp.assume_init().attr }; + let attr = unsafe { rsp.op_header.assume_init().attr }; Ok(FileAttr::from(attr)) } @@ -1342,7 +1238,7 @@ impl VfsNode for FuseDirectory { .ok_or(IoError::ENOSYS)? .lock() .send_command::<{ fuse_abi::Opcode::Open as u32 }>(cmd.as_ref(), rsp.as_mut()); - file_guard.fuse_fh = Some(unsafe { rsp.rsp.assume_init().fh }); + file_guard.fuse_fh = Some(unsafe { rsp.op_header.assume_init().fh }); } else { // Create file (opens implicitly, returns results from both lookup and open calls) let (cmd, mut rsp) = create_create(&path, opt.bits().try_into().unwrap(), mode.bits()); @@ -1351,7 +1247,7 @@ impl VfsNode for FuseDirectory { .lock() .send_command::<{ fuse_abi::Opcode::Create as u32 }>(cmd.as_ref(), rsp.as_mut()); - let inner = unsafe { rsp.rsp.assume_init() }; + let inner = unsafe { rsp.op_header.assume_init() }; file_guard.fuse_nid = Some(inner.entry.nodeid); file_guard.fuse_fh = Some(inner.open.fh); } @@ -1423,10 +1319,10 @@ impl VfsNode for FuseDirectory { .ok_or(IoError::ENOSYS)? .lock() .send_command::<{ fuse_abi::Opcode::Mkdir as u32 }>(cmd.as_ref(), rsp.as_mut()); - if rsp.header.error == 0 { + if rsp.common_header.error == 0 { Ok(()) } else { - Err(num::FromPrimitive::from_i32(rsp.header.error).unwrap()) + Err(num::FromPrimitive::from_i32(rsp.common_header.error).unwrap()) } } } diff --git a/src/lib.rs b/src/lib.rs index c584c92547..607803afb5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,7 @@ #![feature(new_uninit)] #![feature(noop_waker)] #![feature(pointer_is_aligned)] +#![feature(ptr_metadata)] #![feature(slice_from_ptr_range)] #![cfg_attr( any(target_arch = "aarch64", target_arch = "riscv64"), From 3a93d4a843fa9e9af340ff4432f461265d90f508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Sun, 4 Feb 2024 18:16:41 +0100 Subject: [PATCH 06/11] fuse: simplify Rsp allocation --- src/fs/fuse.rs | 293 ++++++++++--------------------------------------- 1 file changed, 57 insertions(+), 236 deletions(-) diff --git a/src/fs/fuse.rs b/src/fs/fuse.rs index 743b04f94b..e43042f6d4 100644 --- a/src/fs/fuse.rs +++ b/src/fs/fuse.rs @@ -87,9 +87,11 @@ pub(crate) trait OpTrait { type InStruct: FuseIn + core::fmt::Debug; type InPayload: ?Sized; type OutStruct: FuseOut + core::fmt::Debug; + type OutPayload: ?Sized; - type Cmd: ?Sized + AsSliceU8 = Cmd; - type Rsp: ?Sized + AsSliceU8 = Rsp; + type Cmd: ?Sized + AsSliceU8 = ReqPart; + type Rsp: ?Sized + AsSliceU8 = + ReqPart, Self::OutPayload>; } pub(crate) struct Op; @@ -98,72 +100,90 @@ impl OpTrait for Op<{ fuse_abi::Opcode::Init as u32 }> { type InStruct = fuse_abi::InitIn; type InPayload = (); type OutStruct = fuse_abi::InitOut; + type OutPayload = (); } impl OpTrait for Op<{ fuse_abi::Opcode::Create as u32 }> { type InStruct = fuse_abi::CreateIn; type InPayload = CStr; type OutStruct = fuse_abi::CreateOut; + type OutPayload = (); } impl OpTrait for Op<{ fuse_abi::Opcode::Open as u32 }> { type InStruct = fuse_abi::OpenIn; type InPayload = (); type OutStruct = fuse_abi::OpenOut; + type OutPayload = (); } impl OpTrait for Op<{ fuse_abi::Opcode::Write as u32 }> { type InStruct = fuse_abi::WriteIn; type InPayload = [u8]; type OutStruct = fuse_abi::WriteOut; + type OutPayload = (); } impl OpTrait for Op<{ fuse_abi::Opcode::Read as u32 }> { type InStruct = fuse_abi::ReadIn; type InPayload = (); type OutStruct = fuse_abi::ReadOut; + + // Since at the time of writing MaybeUninit does not support DSTs as type parameters, we have to define `OutPayload` as [MaybeUninit<_>] + // instead of a MaybeUninit<[_]>. + type OutPayload = [MaybeUninit]; } impl OpTrait for Op<{ fuse_abi::Opcode::Lseek as u32 }> { type InStruct = fuse_abi::LseekIn; type InPayload = (); type OutStruct = fuse_abi::LseekOut; + type OutPayload = (); } impl OpTrait for Op<{ fuse_abi::Opcode::Readlink as u32 }> { type InStruct = fuse_abi::ReadlinkIn; type InPayload = (); type OutStruct = fuse_abi::ReadlinkOut; + + // Since at the time of writing MaybeUninit does not support DSTs as type parameters, we have to define `OutPayload` as [MaybeUninit<_>] + // instead of a MaybeUninit<[_]>. + type OutPayload = [MaybeUninit]; } impl OpTrait for Op<{ fuse_abi::Opcode::Release as u32 }> { type InStruct = fuse_abi::ReleaseIn; type InPayload = (); type OutStruct = fuse_abi::ReleaseOut; + type OutPayload = (); } impl OpTrait for Op<{ fuse_abi::Opcode::Mkdir as u32 }> { type InStruct = fuse_abi::MkdirIn; type InPayload = CStr; type OutStruct = fuse_abi::EntryOut; + type OutPayload = (); } impl OpTrait for Op<{ fuse_abi::Opcode::Unlink as u32 }> { type InStruct = fuse_abi::UnlinkIn; type InPayload = CStr; type OutStruct = fuse_abi::UnlinkOut; + type OutPayload = (); } impl OpTrait for Op<{ fuse_abi::Opcode::Rmdir as u32 }> { type InStruct = fuse_abi::RmdirIn; type InPayload = CStr; type OutStruct = fuse_abi::RmdirOut; + type OutPayload = (); } impl OpTrait for Op<{ fuse_abi::Opcode::Lookup as u32 }> { type InStruct = fuse_abi::LookupIn; type InPayload = CStr; type OutStruct = fuse_abi::EntryOut; + type OutPayload = (); } impl From for FileAttr { @@ -197,16 +217,17 @@ pub(crate) struct ReqPart { payload: P, } -type Cmd = ReqPart; -type Rsp = ReqPart, [MaybeUninit]>; - -impl AsSliceU8 for Cmd { +impl AsSliceU8 for ReqPart { fn len(&self) -> usize { self.common_header.len.try_into().unwrap() } } -impl AsSliceU8 for Rsp {} +// Since we don't bother with initializing the len field, we use the default len implementation. +impl AsSliceU8 + for ReqPart, P> +{ +} impl ReqPart where @@ -262,7 +283,7 @@ where op_header: as OpTrait>::InStruct, len: usize, ) -> Box::InStruct, [u8]>> { - let mut cmd = unsafe { Cmd::new_uninit(len) }; + let mut cmd = unsafe { ReqPart::new_uninit(len) }; cmd.common_header = fuse_abi::InHeader { len: core::mem::size_of_val(cmd.as_ref()) .try_into() @@ -312,7 +333,7 @@ where fn create_init() -> ( Box< as OpTrait>::Cmd>, - Box>, + Box< as OpTrait>::Rsp>, ) { let cmd = Op::<{ fuse_abi::Opcode::Init as u32 }>::new_cmd( fuse_abi::ROOT_ID, @@ -323,24 +344,7 @@ fn create_init() -> ( flags: 0, }, ); - - let len = - core::mem::size_of::() + core::mem::size_of::(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let rsp = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*rsp)); + let rsp = unsafe { Box::new_uninit().assume_init() }; (cmd, rsp) } @@ -351,7 +355,7 @@ fn create_create( mode: u32, ) -> ( Box< as OpTrait>::Cmd>, - Box>, + Box< as OpTrait>::Rsp>, ) { let cmd = Op::<{ fuse_abi::Opcode::Create as u32 }>::cmd_from_str( fuse_abi::ROOT_ID, @@ -362,24 +366,7 @@ fn create_create( }, path, ); - - let len = - core::mem::size_of::() + core::mem::size_of::(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let rsp = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*rsp)); + let rsp = unsafe { Box::new_uninit().assume_init() }; (cmd, rsp) } @@ -389,7 +376,7 @@ fn create_open( flags: u32, ) -> ( Box< as OpTrait>::Cmd>, - Box>, + Box< as OpTrait>::Rsp>, ) { let cmd = Op::<{ fuse_abi::Opcode::Open as u32 }>::new_cmd( nid, @@ -398,24 +385,7 @@ fn create_open( ..Default::default() }, ); - - let len = - core::mem::size_of::() + core::mem::size_of::(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let rsp = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*rsp)); + let rsp = unsafe { Box::new_uninit().assume_init() }; (cmd, rsp) } @@ -428,7 +398,7 @@ fn create_write( offset: u64, ) -> ( Box< as OpTrait>::Cmd>, - Box>, + Box< as OpTrait>::Rsp>, ) { let cmd = Op::<{ fuse_abi::Opcode::Write as u32 }>::cmd_from_array( nid, @@ -440,24 +410,7 @@ fn create_write( }, buf, ); - - let len = - core::mem::size_of::() + core::mem::size_of::(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let rsp = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*rsp)); + let rsp = unsafe { Box::new_uninit().assume_init() }; (cmd, rsp) } @@ -469,7 +422,7 @@ fn create_read( offset: u64, ) -> ( Box< as OpTrait>::Cmd>, - Box>, + Box< as OpTrait>::Rsp>, ) { let cmd = Op::<{ fuse_abi::Opcode::Read as u32 }>::new_cmd( nid, @@ -480,26 +433,11 @@ fn create_read( ..Default::default() }, ); - - let len = core::mem::size_of::() - + core::mem::size_of::() - + usize::try_from(size).unwrap(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); let rsp = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, size.try_into().unwrap()) - as *mut Rsp; - Box::from_raw(raw) + as OpTrait>::Rsp::new_uninit( + size.try_into().unwrap(), + ) }; - assert_eq!(layout, Layout::for_value(&*rsp)); (cmd, rsp) } @@ -511,7 +449,7 @@ fn create_lseek( whence: SeekWhence, ) -> ( Box< as OpTrait>::Cmd>, - Box>, + Box< as OpTrait>::Rsp>, ) { let cmd = Op::<{ fuse_abi::Opcode::Lseek as u32 }>::new_cmd( nid, @@ -522,24 +460,7 @@ fn create_lseek( ..Default::default() }, ); - - let len = - core::mem::size_of::() + core::mem::size_of::(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let rsp = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*rsp)); + let rsp = unsafe { Box::new_uninit().assume_init() }; (cmd, rsp) } @@ -549,29 +470,14 @@ fn create_readlink( size: u32, ) -> ( Box< as OpTrait>::Cmd>, - Box>, + Box< as OpTrait>::Rsp>, ) { let cmd = Op::<{ fuse_abi::Opcode::Readlink as u32 }>::new_cmd(nid, fuse_abi::ReadlinkIn {}); - - let len = core::mem::size_of::() - + core::mem::size_of::() - + usize::try_from(size).unwrap(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); let rsp = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, size.try_into().unwrap()) - as *mut Rsp; - Box::from_raw(raw) + as OpTrait>::Rsp::new_uninit( + size.try_into().unwrap(), + ) }; - assert_eq!(layout, Layout::for_value(&*rsp)); (cmd, rsp) } @@ -581,7 +487,7 @@ fn create_release( fh: u64, ) -> ( Box< as OpTrait>::Cmd>, - Box>, + Box< as OpTrait>::Rsp>, ) { let cmd = Op::<{ fuse_abi::Opcode::Release as u32 }>::new_cmd( nid, @@ -590,24 +496,7 @@ fn create_release( ..Default::default() }, ); - - let len = - core::mem::size_of::() + core::mem::size_of::(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let rsp = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*rsp)); + let rsp = unsafe { Box::new_uninit().assume_init() }; (cmd, rsp) } @@ -674,7 +563,7 @@ fn create_mkdir( mode: u32, ) -> ( Box< as OpTrait>::Cmd>, - Box>, + Box< as OpTrait>::Rsp>, ) { let cmd = Op::<{ fuse_abi::Opcode::Mkdir as u32 }>::cmd_from_str( fuse_abi::ROOT_ID, @@ -684,24 +573,7 @@ fn create_mkdir( }, path, ); - - let len = - core::mem::size_of::() + core::mem::size_of::(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let rsp = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*rsp)); + let rsp = unsafe { Box::new_uninit().assume_init() }; (cmd, rsp) } @@ -710,31 +582,14 @@ fn create_unlink( name: &str, ) -> ( Box< as OpTrait>::Cmd>, - Box>, + Box< as OpTrait>::Rsp>, ) { let cmd = Op::<{ fuse_abi::Opcode::Unlink as u32 }>::cmd_from_str( fuse_abi::ROOT_ID, fuse_abi::UnlinkIn {}, name, ); - - let len = - core::mem::size_of::() + core::mem::size_of::(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let rsp = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*rsp)); + let rsp = unsafe { Box::new_uninit().assume_init() }; (cmd, rsp) } @@ -743,31 +598,14 @@ fn create_rmdir( name: &str, ) -> ( Box< as OpTrait>::Cmd>, - Box>, + Box< as OpTrait>::Rsp>, ) { let cmd = Op::<{ fuse_abi::Opcode::Rmdir as u32 }>::cmd_from_str( fuse_abi::ROOT_ID, fuse_abi::RmdirIn {}, name, ); - - let len = - core::mem::size_of::() + core::mem::size_of::(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let rsp = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*rsp)); + let rsp = unsafe { Box::new_uninit().assume_init() }; (cmd, rsp) } @@ -776,31 +614,14 @@ fn create_lookup( name: &str, ) -> ( Box< as OpTrait>::Cmd>, - Box>, + Box< as OpTrait>::Rsp>, ) { let cmd = Op::<{ fuse_abi::Opcode::Lookup as u32 }>::cmd_from_str( fuse_abi::ROOT_ID, fuse_abi::LookupIn {}, name, ); - - let len = - core::mem::size_of::() + core::mem::size_of::(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let rsp = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*rsp)); + let rsp = unsafe { Box::new_uninit().assume_init() }; (cmd, rsp) } From f13bf48f06817a2a44f5dc903f4cd8ac8163fe2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Sun, 4 Feb 2024 19:23:13 +0100 Subject: [PATCH 07/11] fuse: associate creation functions with structs Turning the Cmd/Rsp creation functions into associated functions for the Op structs allows us to refer to the Op struct in the function signature and body in a more concise manner. --- src/fs/fuse.rs | 589 +++++++++++++++++++++------------------------ src/fs/fuse_abi.rs | 4 +- 2 files changed, 273 insertions(+), 320 deletions(-) diff --git a/src/fs/fuse.rs b/src/fs/fuse.rs index e43042f6d4..a545ccb607 100644 --- a/src/fs/fuse.rs +++ b/src/fs/fuse.rs @@ -103,6 +103,23 @@ impl OpTrait for Op<{ fuse_abi::Opcode::Init as u32 }> { type OutPayload = (); } +impl Op<{ fuse_abi::Opcode::Init as u32 }> { + fn create() -> (Box<::Cmd>, Box<::Rsp>) { + let cmd = Self::new_cmd( + fuse_abi::ROOT_ID, + fuse_abi::InitIn { + major: 7, + minor: 31, + max_readahead: 0, + flags: 0, + }, + ); + let rsp = unsafe { Box::new_uninit().assume_init() }; + + (cmd, rsp) + } +} + impl OpTrait for Op<{ fuse_abi::Opcode::Create as u32 }> { type InStruct = fuse_abi::CreateIn; type InPayload = CStr; @@ -110,6 +127,27 @@ impl OpTrait for Op<{ fuse_abi::Opcode::Create as u32 }> { type OutPayload = (); } +impl Op<{ fuse_abi::Opcode::Create as u32 }> { + fn create( + path: &str, + flags: u32, + mode: u32, + ) -> (Box<::Cmd>, Box<::Rsp>) { + let cmd = Self::cmd_from_str( + fuse_abi::ROOT_ID, + fuse_abi::CreateIn { + flags, + mode, + ..Default::default() + }, + path, + ); + let rsp = unsafe { Box::new_uninit().assume_init() }; + + (cmd, rsp) + } +} + impl OpTrait for Op<{ fuse_abi::Opcode::Open as u32 }> { type InStruct = fuse_abi::OpenIn; type InPayload = (); @@ -117,6 +155,21 @@ impl OpTrait for Op<{ fuse_abi::Opcode::Open as u32 }> { type OutPayload = (); } +impl Op<{ fuse_abi::Opcode::Open as u32 }> { + fn create(nid: u64, flags: u32) -> (Box<::Cmd>, Box<::Rsp>) { + let cmd = Self::new_cmd( + nid, + fuse_abi::OpenIn { + flags, + ..Default::default() + }, + ); + let rsp = unsafe { Box::new_uninit().assume_init() }; + + (cmd, rsp) + } +} + impl OpTrait for Op<{ fuse_abi::Opcode::Write as u32 }> { type InStruct = fuse_abi::WriteIn; type InPayload = [u8]; @@ -124,6 +177,29 @@ impl OpTrait for Op<{ fuse_abi::Opcode::Write as u32 }> { type OutPayload = (); } +impl Op<{ fuse_abi::Opcode::Write as u32 }> { + fn create( + nid: u64, + fh: u64, + buf: &[u8], + offset: u64, + ) -> (Box<::Cmd>, Box<::Rsp>) { + let cmd = Self::cmd_from_array( + nid, + fuse_abi::WriteIn { + fh, + offset, + size: buf.len().try_into().unwrap(), + ..Default::default() + }, + buf, + ); + let rsp = unsafe { Box::new_uninit().assume_init() }; + + (cmd, rsp) + } +} + impl OpTrait for Op<{ fuse_abi::Opcode::Read as u32 }> { type InStruct = fuse_abi::ReadIn; type InPayload = (); @@ -134,6 +210,32 @@ impl OpTrait for Op<{ fuse_abi::Opcode::Read as u32 }> { type OutPayload = [MaybeUninit]; } +impl Op<{ fuse_abi::Opcode::Read as u32 }> { + fn create( + nid: u64, + fh: u64, + size: u32, + offset: u64, + ) -> (Box<::Cmd>, Box<::Rsp>) { + let cmd = Self::new_cmd( + nid, + fuse_abi::ReadIn { + fh, + offset, + size, + ..Default::default() + }, + ); + let rsp = unsafe { + as OpTrait>::Rsp::new_uninit( + size.try_into().unwrap(), + ) + }; + + (cmd, rsp) + } +} + impl OpTrait for Op<{ fuse_abi::Opcode::Lseek as u32 }> { type InStruct = fuse_abi::LseekIn; type InPayload = (); @@ -141,6 +243,28 @@ impl OpTrait for Op<{ fuse_abi::Opcode::Lseek as u32 }> { type OutPayload = (); } +impl Op<{ fuse_abi::Opcode::Lseek as u32 }> { + fn create( + nid: u64, + fh: u64, + offset: isize, + whence: SeekWhence, + ) -> (Box<::Cmd>, Box<::Rsp>) { + let cmd = Self::new_cmd( + nid, + fuse_abi::LseekIn { + fh, + offset: offset.try_into().unwrap(), + whence: num::ToPrimitive::to_u32(&whence).unwrap(), + ..Default::default() + }, + ); + let rsp = unsafe { Box::new_uninit().assume_init() }; + + (cmd, rsp) + } +} + impl OpTrait for Op<{ fuse_abi::Opcode::Readlink as u32 }> { type InStruct = fuse_abi::ReadlinkIn; type InPayload = (); @@ -151,6 +275,19 @@ impl OpTrait for Op<{ fuse_abi::Opcode::Readlink as u32 }> { type OutPayload = [MaybeUninit]; } +impl Op<{ fuse_abi::Opcode::Readlink as u32 }> { + fn create(nid: u64, size: u32) -> (Box<::Cmd>, Box<::Rsp>) { + let cmd = Self::new_cmd(nid, fuse_abi::ReadlinkIn {}); + let rsp = unsafe { + as OpTrait>::Rsp::new_uninit( + size.try_into().unwrap(), + ) + }; + + (cmd, rsp) + } +} + impl OpTrait for Op<{ fuse_abi::Opcode::Release as u32 }> { type InStruct = fuse_abi::ReleaseIn; type InPayload = (); @@ -158,6 +295,50 @@ impl OpTrait for Op<{ fuse_abi::Opcode::Release as u32 }> { type OutPayload = (); } +impl Op<{ fuse_abi::Opcode::Release as u32 }> { + fn create(nid: u64, fh: u64) -> (Box<::Cmd>, Box<::Rsp>) { + let cmd = Self::new_cmd( + nid, + fuse_abi::ReleaseIn { + fh, + ..Default::default() + }, + ); + let rsp = unsafe { Box::new_uninit().assume_init() }; + + (cmd, rsp) + } +} + +impl OpTrait for Op<{ fuse_abi::Opcode::Poll as u32 }> { + type InStruct = fuse_abi::PollIn; + type InPayload = (); + type OutStruct = fuse_abi::PollOut; + type OutPayload = (); +} + +impl Op<{ fuse_abi::Opcode::Poll as u32 }> { + fn create( + nid: u64, + fh: u64, + kh: u64, + event: PollEvent, + ) -> (Box<::Cmd>, Box<::Rsp>) { + let cmd = Self::new_cmd( + nid, + fuse_abi::PollIn { + fh, + kh, + events: event.bits() as u32, + ..Default::default() + }, + ); + let rsp = unsafe { Box::new_uninit().assume_init() }; + + (cmd, rsp) + } +} + impl OpTrait for Op<{ fuse_abi::Opcode::Mkdir as u32 }> { type InStruct = fuse_abi::MkdirIn; type InPayload = CStr; @@ -165,6 +346,22 @@ impl OpTrait for Op<{ fuse_abi::Opcode::Mkdir as u32 }> { type OutPayload = (); } +impl Op<{ fuse_abi::Opcode::Mkdir as u32 }> { + fn create(path: &str, mode: u32) -> (Box<::Cmd>, Box<::Rsp>) { + let cmd = Self::cmd_from_str( + fuse_abi::ROOT_ID, + fuse_abi::MkdirIn { + mode, + ..Default::default() + }, + path, + ); + let rsp = unsafe { Box::new_uninit().assume_init() }; + + (cmd, rsp) + } +} + impl OpTrait for Op<{ fuse_abi::Opcode::Unlink as u32 }> { type InStruct = fuse_abi::UnlinkIn; type InPayload = CStr; @@ -172,6 +369,15 @@ impl OpTrait for Op<{ fuse_abi::Opcode::Unlink as u32 }> { type OutPayload = (); } +impl Op<{ fuse_abi::Opcode::Unlink as u32 }> { + fn create(name: &str) -> (Box<::Cmd>, Box<::Rsp>) { + let cmd = Self::cmd_from_str(fuse_abi::ROOT_ID, fuse_abi::UnlinkIn {}, name); + let rsp = unsafe { Box::new_uninit().assume_init() }; + + (cmd, rsp) + } +} + impl OpTrait for Op<{ fuse_abi::Opcode::Rmdir as u32 }> { type InStruct = fuse_abi::RmdirIn; type InPayload = CStr; @@ -179,6 +385,15 @@ impl OpTrait for Op<{ fuse_abi::Opcode::Rmdir as u32 }> { type OutPayload = (); } +impl Op<{ fuse_abi::Opcode::Rmdir as u32 }> { + fn create(name: &str) -> (Box<::Cmd>, Box<::Rsp>) { + let cmd = Self::cmd_from_str(fuse_abi::ROOT_ID, fuse_abi::RmdirIn {}, name); + let rsp = unsafe { Box::new_uninit().assume_init() }; + + (cmd, rsp) + } +} + impl OpTrait for Op<{ fuse_abi::Opcode::Lookup as u32 }> { type InStruct = fuse_abi::LookupIn; type InPayload = CStr; @@ -186,6 +401,15 @@ impl OpTrait for Op<{ fuse_abi::Opcode::Lookup as u32 }> { type OutPayload = (); } +impl Op<{ fuse_abi::Opcode::Lookup as u32 }> { + fn create(name: &str) -> (Box<::Cmd>, Box<::Rsp>) { + let cmd = Self::cmd_from_str(fuse_abi::ROOT_ID, fuse_abi::LookupIn {}, name); + let rsp = unsafe { Box::new_uninit().assume_init() }; + + (cmd, rsp) + } +} + impl From for FileAttr { fn from(attr: fuse_abi::Attr) -> FileAttr { FileAttr { @@ -331,303 +555,8 @@ where } } -fn create_init() -> ( - Box< as OpTrait>::Cmd>, - Box< as OpTrait>::Rsp>, -) { - let cmd = Op::<{ fuse_abi::Opcode::Init as u32 }>::new_cmd( - fuse_abi::ROOT_ID, - fuse_abi::InitIn { - major: 7, - minor: 31, - max_readahead: 0, - flags: 0, - }, - ); - let rsp = unsafe { Box::new_uninit().assume_init() }; - - (cmd, rsp) -} - -fn create_create( - path: &str, - flags: u32, - mode: u32, -) -> ( - Box< as OpTrait>::Cmd>, - Box< as OpTrait>::Rsp>, -) { - let cmd = Op::<{ fuse_abi::Opcode::Create as u32 }>::cmd_from_str( - fuse_abi::ROOT_ID, - fuse_abi::CreateIn { - flags, - mode, - ..Default::default() - }, - path, - ); - let rsp = unsafe { Box::new_uninit().assume_init() }; - - (cmd, rsp) -} - -fn create_open( - nid: u64, - flags: u32, -) -> ( - Box< as OpTrait>::Cmd>, - Box< as OpTrait>::Rsp>, -) { - let cmd = Op::<{ fuse_abi::Opcode::Open as u32 }>::new_cmd( - nid, - fuse_abi::OpenIn { - flags, - ..Default::default() - }, - ); - let rsp = unsafe { Box::new_uninit().assume_init() }; - - (cmd, rsp) -} - -// TODO: do write zerocopy? -fn create_write( - nid: u64, - fh: u64, - buf: &[u8], - offset: u64, -) -> ( - Box< as OpTrait>::Cmd>, - Box< as OpTrait>::Rsp>, -) { - let cmd = Op::<{ fuse_abi::Opcode::Write as u32 }>::cmd_from_array( - nid, - fuse_abi::WriteIn { - fh, - offset, - size: buf.len().try_into().unwrap(), - ..Default::default() - }, - buf, - ); - let rsp = unsafe { Box::new_uninit().assume_init() }; - - (cmd, rsp) -} - -fn create_read( - nid: u64, - fh: u64, - size: u32, - offset: u64, -) -> ( - Box< as OpTrait>::Cmd>, - Box< as OpTrait>::Rsp>, -) { - let cmd = Op::<{ fuse_abi::Opcode::Read as u32 }>::new_cmd( - nid, - fuse_abi::ReadIn { - fh, - offset, - size, - ..Default::default() - }, - ); - let rsp = unsafe { - as OpTrait>::Rsp::new_uninit( - size.try_into().unwrap(), - ) - }; - - (cmd, rsp) -} - -fn create_lseek( - nid: u64, - fh: u64, - offset: isize, - whence: SeekWhence, -) -> ( - Box< as OpTrait>::Cmd>, - Box< as OpTrait>::Rsp>, -) { - let cmd = Op::<{ fuse_abi::Opcode::Lseek as u32 }>::new_cmd( - nid, - fuse_abi::LseekIn { - fh, - offset: offset.try_into().unwrap(), - whence: num::ToPrimitive::to_u32(&whence).unwrap(), - ..Default::default() - }, - ); - let rsp = unsafe { Box::new_uninit().assume_init() }; - - (cmd, rsp) -} - -fn create_readlink( - nid: u64, - size: u32, -) -> ( - Box< as OpTrait>::Cmd>, - Box< as OpTrait>::Rsp>, -) { - let cmd = Op::<{ fuse_abi::Opcode::Readlink as u32 }>::new_cmd(nid, fuse_abi::ReadlinkIn {}); - let rsp = unsafe { - as OpTrait>::Rsp::new_uninit( - size.try_into().unwrap(), - ) - }; - - (cmd, rsp) -} - -fn create_release( - nid: u64, - fh: u64, -) -> ( - Box< as OpTrait>::Cmd>, - Box< as OpTrait>::Rsp>, -) { - let cmd = Op::<{ fuse_abi::Opcode::Release as u32 }>::new_cmd( - nid, - fuse_abi::ReleaseIn { - fh, - ..Default::default() - }, - ); - let rsp = unsafe { Box::new_uninit().assume_init() }; - - (cmd, rsp) -} - -fn create_poll( - nid: u64, - fh: u64, - kh: u64, - event: PollEvent, -) -> (Box>, Box>) { - let len = core::mem::size_of::() + core::mem::size_of::(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let cmd = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Cmd; - (*raw).header = create_in_header::(nid, fuse_abi::Opcode::Poll); - (*raw).cmd = fuse_abi::PollIn { - fh, - kh, - events: event.bits() as u32, - ..Default::default() - }; - - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*cmd)); - - let len = - core::mem::size_of::() + core::mem::size_of::(); - let layout = Layout::from_size_align( - len, - core::cmp::max( - core::mem::align_of::(), - core::mem::align_of::(), - ), - ) - .unwrap() - .pad_to_align(); - let rsp = unsafe { - let data = alloc(layout); - let raw = core::ptr::slice_from_raw_parts_mut(data, 0) as *mut Rsp; - (*raw).header = fuse_abi::OutHeader { - len: len.try_into().unwrap(), - ..Default::default() - }; - - Box::from_raw(raw) - }; - assert_eq!(layout, Layout::for_value(&*rsp)); - - (cmd, rsp) -} - -fn create_mkdir( - path: &str, - mode: u32, -) -> ( - Box< as OpTrait>::Cmd>, - Box< as OpTrait>::Rsp>, -) { - let cmd = Op::<{ fuse_abi::Opcode::Mkdir as u32 }>::cmd_from_str( - fuse_abi::ROOT_ID, - fuse_abi::MkdirIn { - mode, - ..Default::default() - }, - path, - ); - let rsp = unsafe { Box::new_uninit().assume_init() }; - - (cmd, rsp) -} - -fn create_unlink( - name: &str, -) -> ( - Box< as OpTrait>::Cmd>, - Box< as OpTrait>::Rsp>, -) { - let cmd = Op::<{ fuse_abi::Opcode::Unlink as u32 }>::cmd_from_str( - fuse_abi::ROOT_ID, - fuse_abi::UnlinkIn {}, - name, - ); - let rsp = unsafe { Box::new_uninit().assume_init() }; - - (cmd, rsp) -} - -fn create_rmdir( - name: &str, -) -> ( - Box< as OpTrait>::Cmd>, - Box< as OpTrait>::Rsp>, -) { - let cmd = Op::<{ fuse_abi::Opcode::Rmdir as u32 }>::cmd_from_str( - fuse_abi::ROOT_ID, - fuse_abi::RmdirIn {}, - name, - ); - let rsp = unsafe { Box::new_uninit().assume_init() }; - - (cmd, rsp) -} - -fn create_lookup( - name: &str, -) -> ( - Box< as OpTrait>::Cmd>, - Box< as OpTrait>::Rsp>, -) { - let cmd = Op::<{ fuse_abi::Opcode::Lookup as u32 }>::cmd_from_str( - fuse_abi::ROOT_ID, - fuse_abi::LookupIn {}, - name, - ); - let rsp = unsafe { Box::new_uninit().assume_init() }; - - (cmd, rsp) -} - fn lookup(name: &str) -> Option { - let (cmd, mut rsp) = create_lookup(name); + let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Lookup as u32 }>::create(name); get_filesystem_driver() .unwrap() .lock() @@ -641,7 +570,7 @@ fn lookup(name: &str) -> Option { fn readlink(nid: u64) -> Result { let len = MAX_READ_LEN as u32; - let (cmd, mut rsp) = create_readlink(nid, len); + let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Readlink as u32 }>::create(nid, len); get_filesystem_driver() .unwrap() .lock() @@ -686,18 +615,21 @@ impl FuseFileHandleInner { future::poll_fn(|cx| { if let (Some(nid), Some(fh)) = (self.fuse_nid, self.fuse_fh) { - let (cmd, mut rsp) = create_poll(nid, fh, kh, events); + let (cmd, mut rsp) = + Op::<{ fuse_abi::Opcode::Poll as u32 }>::create(nid, fh, kh, events); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command(cmd.as_ref(), rsp.as_mut()); + .send_command::<{ fuse_abi::Opcode::Poll as u32 }>(cmd.as_ref(), rsp.as_mut()); - if rsp.header.error < 0 { + if rsp.common_header.error < 0 { Poll::Ready(Err(IoError::EIO)) } else { let revents = unsafe { - PollEvent::from_bits(i16::try_from(rsp.rsp.assume_init().revents).unwrap()) - .unwrap() + PollEvent::from_bits( + i16::try_from(rsp.op_header.assume_init().revents).unwrap(), + ) + .unwrap() }; if !revents.intersects(events) && !revents.intersects( @@ -723,7 +655,12 @@ impl FuseFileHandleInner { len = MAX_READ_LEN; } if let (Some(nid), Some(fh)) = (self.fuse_nid, self.fuse_fh) { - let (cmd, mut rsp) = create_read(nid, fh, len.try_into().unwrap(), self.offset as u64); + let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Read as u32 }>::create( + nid, + fh, + len.try_into().unwrap(), + self.offset as u64, + ); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() @@ -764,7 +701,12 @@ impl FuseFileHandleInner { len = MAX_WRITE_LEN; } if let (Some(nid), Some(fh)) = (self.fuse_nid, self.fuse_fh) { - let (cmd, mut rsp) = create_write(nid, fh, &buf[..len], self.offset as u64); + let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Write as u32 }>::create( + nid, + fh, + &buf[..len], + self.offset as u64, + ); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() @@ -792,7 +734,8 @@ impl FuseFileHandleInner { debug!("FUSE lseek"); if let (Some(nid), Some(fh)) = (self.fuse_nid, self.fuse_fh) { - let (cmd, mut rsp) = create_lseek(nid, fh, offset, whence); + let (cmd, mut rsp) = + Op::<{ fuse_abi::Opcode::Lseek as u32 }>::create(nid, fh, offset, whence); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() @@ -814,7 +757,10 @@ impl FuseFileHandleInner { impl Drop for FuseFileHandleInner { fn drop(&mut self) { if self.fuse_nid.is_some() && self.fuse_fh.is_some() { - let (cmd, mut rsp) = create_release(self.fuse_nid.unwrap(), self.fuse_fh.unwrap()); + let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Release as u32 }>::create( + self.fuse_nid.unwrap(), + self.fuse_fh.unwrap(), + ); get_filesystem_driver() .unwrap() .lock() @@ -890,7 +836,7 @@ impl VfsNode for FuseDirectory { // Opendir // Flag 0x10000 for O_DIRECTORY might not be necessary - let (mut cmd, mut rsp) = create_open(fuse_nid, 0x10000); + let (mut cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Open as u32 }>::create(fuse_nid, 0x10000); cmd.common_header.opcode = fuse_abi::Opcode::Opendir as u32; get_filesystem_driver() .ok_or(IoError::ENOSYS)? @@ -905,7 +851,8 @@ impl VfsNode for FuseDirectory { let mut offset: usize = 0; // read content of the directory - let (mut cmd, mut rsp) = create_read(fuse_nid, fuse_fh, len, 0); + let (mut cmd, mut rsp) = + Op::<{ fuse_abi::Opcode::Read as u32 }>::create(fuse_nid, fuse_fh, len, 0); cmd.common_header.opcode = fuse_abi::Opcode::Readdir as u32; get_filesystem_driver() .ok_or(IoError::ENOSYS)? @@ -949,7 +896,7 @@ impl VfsNode for FuseDirectory { })); } - let (cmd, mut rsp) = create_release(fuse_nid, fuse_fh); + let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Release as u32 }>::create(fuse_nid, fuse_fh); get_filesystem_driver() .unwrap() .lock() @@ -972,7 +919,7 @@ impl VfsNode for FuseDirectory { debug!("FUSE stat: {}", path); // Is there a better way to implement this? - let (cmd, mut rsp) = create_lookup(&path); + let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Lookup as u32 }>::create(&path); get_filesystem_driver() .unwrap() .lock() @@ -1008,7 +955,7 @@ impl VfsNode for FuseDirectory { debug!("FUSE lstat: {}", path); - let (cmd, mut rsp) = create_lookup(&path); + let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Lookup as u32 }>::create(&path); get_filesystem_driver() .unwrap() .lock() @@ -1053,8 +1000,10 @@ impl VfsNode for FuseDirectory { } // 3.FUSE_OPEN(nodeid, O_RDONLY) -> fh - let (cmd, mut rsp) = - create_open(file_guard.fuse_nid.unwrap(), opt.bits().try_into().unwrap()); + let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Open as u32 }>::create( + file_guard.fuse_nid.unwrap(), + opt.bits().try_into().unwrap(), + ); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() @@ -1062,7 +1011,11 @@ impl VfsNode for FuseDirectory { file_guard.fuse_fh = Some(unsafe { rsp.op_header.assume_init().fh }); } else { // Create file (opens implicitly, returns results from both lookup and open calls) - let (cmd, mut rsp) = create_create(&path, opt.bits().try_into().unwrap(), mode.bits()); + let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Create as u32 }>::create( + &path, + opt.bits().try_into().unwrap(), + mode.bits(), + ); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() @@ -1089,7 +1042,7 @@ impl VfsNode for FuseDirectory { .collect() }; - let (cmd, mut rsp) = create_unlink(&path); + let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Unlink as u32 }>::create(&path); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() @@ -1110,7 +1063,7 @@ impl VfsNode for FuseDirectory { .collect() }; - let (cmd, mut rsp) = create_rmdir(&path); + let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Rmdir as u32 }>::create(&path); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() @@ -1134,7 +1087,7 @@ impl VfsNode for FuseDirectory { .map(|v| "/".to_owned() + v) .collect() }; - let (cmd, mut rsp) = create_mkdir(&path, mode.bits()); + let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Mkdir as u32 }>::create(&path, mode.bits()); get_filesystem_driver() .ok_or(IoError::ENOSYS)? @@ -1152,7 +1105,7 @@ pub(crate) fn init() { debug!("Try to initialize fuse filesystem"); if let Some(driver) = get_filesystem_driver() { - let (cmd, mut rsp) = create_init(); + let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Init as u32 }>::create(); driver .lock() .send_command::<{ fuse_abi::Opcode::Init as u32 }>(cmd.as_ref(), rsp.as_mut()); diff --git a/src/fs/fuse_abi.rs b/src/fs/fuse_abi.rs index 49a97d75ec..98d759910d 100644 --- a/src/fs/fuse_abi.rs +++ b/src/fs/fuse_abi.rs @@ -242,7 +242,7 @@ pub(crate) struct LseekOut { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct PollIn { +pub(crate) struct PollIn { pub fh: u64, pub kh: u64, pub flags: u32, @@ -251,7 +251,7 @@ pub(super) struct PollIn { #[repr(C)] #[derive(Default, Debug)] -pub(super) struct PollOut { +pub(crate) struct PollOut { pub revents: u32, padding: u32, } From 4146a334068164760ee858e8a899a56c7741be55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Tue, 13 Feb 2024 16:05:38 +0100 Subject: [PATCH 08/11] fuse: remove unused marker trait --- src/fs/fuse.rs | 45 ++++----------------------------------------- 1 file changed, 4 insertions(+), 41 deletions(-) diff --git a/src/fs/fuse.rs b/src/fs/fuse.rs index a545ccb607..e4b0610423 100644 --- a/src/fs/fuse.rs +++ b/src/fs/fuse.rs @@ -49,44 +49,10 @@ pub(crate) trait FuseInterface { fn get_mount_point(&self) -> String; } -/// Marker trait, which signals that a struct is a valid Fuse command. -/// Struct has to be repr(C)! -pub(crate) unsafe trait FuseIn {} -/// Marker trait, which signals that a struct is a valid Fuse response. -/// Struct has to be repr(C)! -pub(crate) unsafe trait FuseOut {} - -unsafe impl FuseIn for fuse_abi::InitIn {} -unsafe impl FuseOut for fuse_abi::InitOut {} -unsafe impl FuseIn for fuse_abi::ReadIn {} -unsafe impl FuseIn for fuse_abi::WriteIn {} -unsafe impl FuseOut for fuse_abi::WriteOut {} -unsafe impl FuseOut for fuse_abi::ReadOut {} -unsafe impl FuseIn for fuse_abi::LookupIn {} -unsafe impl FuseIn for fuse_abi::ReadlinkIn {} -unsafe impl FuseOut for fuse_abi::ReadlinkOut {} -unsafe impl FuseOut for fuse_abi::AttrOut {} -unsafe impl FuseOut for fuse_abi::EntryOut {} -unsafe impl FuseIn for fuse_abi::CreateIn {} -unsafe impl FuseOut for fuse_abi::CreateOut {} -unsafe impl FuseIn for fuse_abi::OpenIn {} -unsafe impl FuseOut for fuse_abi::OpenOut {} -unsafe impl FuseIn for fuse_abi::ReleaseIn {} -unsafe impl FuseOut for fuse_abi::ReleaseOut {} -unsafe impl FuseIn for fuse_abi::RmdirIn {} -unsafe impl FuseOut for fuse_abi::RmdirOut {} -unsafe impl FuseIn for fuse_abi::MkdirIn {} -unsafe impl FuseIn for fuse_abi::UnlinkIn {} -unsafe impl FuseOut for fuse_abi::UnlinkOut {} -unsafe impl FuseIn for fuse_abi::LseekIn {} -unsafe impl FuseOut for fuse_abi::LseekOut {} -unsafe impl FuseIn for fuse_abi::PollIn {} -unsafe impl FuseOut for fuse_abi::PollOut {} - pub(crate) trait OpTrait { - type InStruct: FuseIn + core::fmt::Debug; + type InStruct: core::fmt::Debug; type InPayload: ?Sized; - type OutStruct: FuseOut + core::fmt::Debug; + type OutStruct: core::fmt::Debug; type OutPayload: ?Sized; type Cmd: ?Sized + AsSliceU8 = ReqPart; @@ -441,17 +407,14 @@ pub(crate) struct ReqPart { payload: P, } -impl AsSliceU8 for ReqPart { +impl AsSliceU8 for ReqPart { fn len(&self) -> usize { self.common_header.len.try_into().unwrap() } } // Since we don't bother with initializing the len field, we use the default len implementation. -impl AsSliceU8 - for ReqPart, P> -{ -} +impl AsSliceU8 for ReqPart, P> {} impl ReqPart where From 92bf4c1a7618631cff7f55832c44cfdcf4bd4ce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Tue, 13 Feb 2024 20:48:58 +0100 Subject: [PATCH 09/11] fuse: use empty structs instead of const generic To specify operations, use structs instead of const generic arguments to reduce verbosity. --- src/drivers/fs/virtio_fs.rs | 12 +- src/fs/fuse.rs | 936 +++++++++++++++++++----------------- src/fs/fuse_abi.rs | 1 + src/lib.rs | 2 +- 4 files changed, 505 insertions(+), 446 deletions(-) diff --git a/src/drivers/fs/virtio_fs.rs b/src/drivers/fs/virtio_fs.rs index 3ff9578e8e..f4502a4608 100644 --- a/src/drivers/fs/virtio_fs.rs +++ b/src/drivers/fs/virtio_fs.rs @@ -153,21 +153,13 @@ impl VirtioFsDriver { } impl FuseInterface for VirtioFsDriver { - fn send_command( - &mut self, - cmd: & as fuse::OpTrait>::Cmd, - rsp: &mut as fuse::OpTrait>::Rsp, - ) where - fuse::Op: fuse::OpTrait, - { + fn send_command(&mut self, cmd: &fuse::Cmd, rsp: &mut fuse::Rsp) { if let Some(mut buff_tkn) = self.ready_queue.pop() { let cmd_len = Some(cmd.len()); let rsp_len = Some(rsp.len()); buff_tkn.restr_size(cmd_len, rsp_len).unwrap(); - let transfer_tkn = buff_tkn - .write(Some(cmd), None::<& as fuse::OpTrait>::Rsp>) - .unwrap(); + let transfer_tkn = buff_tkn.write(Some(cmd), None::<&fuse::Rsp>).unwrap(); let transfer = transfer_tkn.dispatch_blocking().unwrap(); let (_, response) = transfer.ret_cpy().unwrap(); let tkn = transfer.reuse().unwrap(); diff --git a/src/fs/fuse.rs b/src/fs/fuse.rs index e4b0610423..a91d22ef09 100644 --- a/src/fs/fuse.rs +++ b/src/fs/fuse.rs @@ -8,7 +8,7 @@ use core::ffi::CStr; use core::mem::MaybeUninit; use core::sync::atomic::{AtomicU64, Ordering}; use core::task::Poll; -use core::{fmt, future, u32, u8}; +use core::{future, u32, u8}; use async_lock::Mutex; use async_trait::async_trait; @@ -39,340 +39,386 @@ const S_IFLNK: u32 = 40960; const S_IFMT: u32 = 61440; pub(crate) trait FuseInterface { - fn send_command( - &mut self, - cmd: & as OpTrait>::Cmd, - rsp: &mut as OpTrait>::Rsp, - ) where - Op: OpTrait; + fn send_command(&mut self, cmd: &Cmd, rsp: &mut Rsp); fn get_mount_point(&self) -> String; } -pub(crate) trait OpTrait { - type InStruct: core::fmt::Debug; - type InPayload: ?Sized; - type OutStruct: core::fmt::Debug; - type OutPayload: ?Sized; +pub(crate) mod ops { + use alloc::boxed::Box; + use core::ffi::CStr; + use core::mem::MaybeUninit; - type Cmd: ?Sized + AsSliceU8 = ReqPart; - type Rsp: ?Sized + AsSliceU8 = - ReqPart, Self::OutPayload>; -} + use super::{Cmd, Rsp}; + use crate::fd::PollEvent; + use crate::fs::{fuse_abi, SeekWhence}; -pub(crate) struct Op; + pub(crate) trait Op { + const OP_CODE: fuse_abi::Opcode; -impl OpTrait for Op<{ fuse_abi::Opcode::Init as u32 }> { - type InStruct = fuse_abi::InitIn; - type InPayload = (); - type OutStruct = fuse_abi::InitOut; - type OutPayload = (); -} + type InStruct: core::fmt::Debug; + type InPayload: ?Sized; + type OutStruct: core::fmt::Debug; + type OutPayload: ?Sized; + } -impl Op<{ fuse_abi::Opcode::Init as u32 }> { - fn create() -> (Box<::Cmd>, Box<::Rsp>) { - let cmd = Self::new_cmd( - fuse_abi::ROOT_ID, - fuse_abi::InitIn { - major: 7, - minor: 31, - max_readahead: 0, - flags: 0, - }, - ); - let rsp = unsafe { Box::new_uninit().assume_init() }; + #[derive(Debug)] + pub(crate) struct Init; - (cmd, rsp) + impl Op for Init { + const OP_CODE: fuse_abi::Opcode = fuse_abi::Opcode::Init; + type InStruct = fuse_abi::InitIn; + type InPayload = (); + type OutStruct = fuse_abi::InitOut; + type OutPayload = (); } -} -impl OpTrait for Op<{ fuse_abi::Opcode::Create as u32 }> { - type InStruct = fuse_abi::CreateIn; - type InPayload = CStr; - type OutStruct = fuse_abi::CreateOut; - type OutPayload = (); -} + impl Init { + pub(crate) fn create() -> (Box>, Box>) { + let cmd = Cmd::::new( + fuse_abi::ROOT_ID, + fuse_abi::InitIn { + major: 7, + minor: 31, + max_readahead: 0, + flags: 0, + }, + ); + let rsp = unsafe { Box::new_uninit().assume_init() }; -impl Op<{ fuse_abi::Opcode::Create as u32 }> { - fn create( - path: &str, - flags: u32, - mode: u32, - ) -> (Box<::Cmd>, Box<::Rsp>) { - let cmd = Self::cmd_from_str( - fuse_abi::ROOT_ID, - fuse_abi::CreateIn { - flags, - mode, - ..Default::default() - }, - path, - ); - let rsp = unsafe { Box::new_uninit().assume_init() }; + (cmd, rsp) + } + } + + #[derive(Debug)] + pub(crate) struct Create; - (cmd, rsp) + impl Op for Create { + const OP_CODE: fuse_abi::Opcode = fuse_abi::Opcode::Create; + type InStruct = fuse_abi::CreateIn; + type InPayload = CStr; + type OutStruct = fuse_abi::CreateOut; + type OutPayload = (); } -} -impl OpTrait for Op<{ fuse_abi::Opcode::Open as u32 }> { - type InStruct = fuse_abi::OpenIn; - type InPayload = (); - type OutStruct = fuse_abi::OpenOut; - type OutPayload = (); -} + impl Create { + #[allow(clippy::self_named_constructors)] + pub(crate) fn create( + path: &str, + flags: u32, + mode: u32, + ) -> (Box>, Box>) { + let cmd = Cmd::::from_str( + fuse_abi::ROOT_ID, + fuse_abi::CreateIn { + flags, + mode, + ..Default::default() + }, + path, + ); + let rsp = unsafe { Box::new_uninit().assume_init() }; -impl Op<{ fuse_abi::Opcode::Open as u32 }> { - fn create(nid: u64, flags: u32) -> (Box<::Cmd>, Box<::Rsp>) { - let cmd = Self::new_cmd( - nid, - fuse_abi::OpenIn { - flags, - ..Default::default() - }, - ); - let rsp = unsafe { Box::new_uninit().assume_init() }; + (cmd, rsp) + } + } - (cmd, rsp) + #[derive(Debug)] + pub(crate) struct Open; + + impl Op for Open { + const OP_CODE: fuse_abi::Opcode = fuse_abi::Opcode::Open; + type InStruct = fuse_abi::OpenIn; + type InPayload = (); + type OutStruct = fuse_abi::OpenOut; + type OutPayload = (); } -} -impl OpTrait for Op<{ fuse_abi::Opcode::Write as u32 }> { - type InStruct = fuse_abi::WriteIn; - type InPayload = [u8]; - type OutStruct = fuse_abi::WriteOut; - type OutPayload = (); -} + impl Open { + pub(crate) fn create(nid: u64, flags: u32) -> (Box>, Box>) { + let cmd = Cmd::::new( + nid, + fuse_abi::OpenIn { + flags, + ..Default::default() + }, + ); + let rsp = unsafe { Box::new_uninit().assume_init() }; -impl Op<{ fuse_abi::Opcode::Write as u32 }> { - fn create( - nid: u64, - fh: u64, - buf: &[u8], - offset: u64, - ) -> (Box<::Cmd>, Box<::Rsp>) { - let cmd = Self::cmd_from_array( - nid, - fuse_abi::WriteIn { - fh, - offset, - size: buf.len().try_into().unwrap(), - ..Default::default() - }, - buf, - ); - let rsp = unsafe { Box::new_uninit().assume_init() }; + (cmd, rsp) + } + } + + #[derive(Debug)] + pub(crate) struct Write; - (cmd, rsp) + impl Op for Write { + const OP_CODE: fuse_abi::Opcode = fuse_abi::Opcode::Write; + type InStruct = fuse_abi::WriteIn; + type InPayload = [u8]; + type OutStruct = fuse_abi::WriteOut; + type OutPayload = (); } -} -impl OpTrait for Op<{ fuse_abi::Opcode::Read as u32 }> { - type InStruct = fuse_abi::ReadIn; - type InPayload = (); - type OutStruct = fuse_abi::ReadOut; + impl Write { + pub(crate) fn create( + nid: u64, + fh: u64, + buf: &[u8], + offset: u64, + ) -> (Box>, Box>) { + let cmd = Cmd::::from_array( + nid, + fuse_abi::WriteIn { + fh, + offset, + size: buf.len().try_into().unwrap(), + ..Default::default() + }, + buf, + ); + let rsp = unsafe { Box::new_uninit().assume_init() }; - // Since at the time of writing MaybeUninit does not support DSTs as type parameters, we have to define `OutPayload` as [MaybeUninit<_>] - // instead of a MaybeUninit<[_]>. - type OutPayload = [MaybeUninit]; -} + (cmd, rsp) + } + } -impl Op<{ fuse_abi::Opcode::Read as u32 }> { - fn create( - nid: u64, - fh: u64, - size: u32, - offset: u64, - ) -> (Box<::Cmd>, Box<::Rsp>) { - let cmd = Self::new_cmd( - nid, - fuse_abi::ReadIn { - fh, - offset, - size, - ..Default::default() - }, - ); - let rsp = unsafe { - as OpTrait>::Rsp::new_uninit( - size.try_into().unwrap(), - ) - }; + #[derive(Debug)] + pub(crate) struct Read; + + impl Op for Read { + const OP_CODE: fuse_abi::Opcode = fuse_abi::Opcode::Read; + type InStruct = fuse_abi::ReadIn; + type InPayload = (); + type OutStruct = fuse_abi::ReadOut; - (cmd, rsp) + // Since at the time of writing MaybeUninit does not support DSTs as type parameters, we have to define `OutPayload` as [MaybeUninit<_>] + // instead of a MaybeUninit<[_]>. + type OutPayload = [MaybeUninit]; } -} -impl OpTrait for Op<{ fuse_abi::Opcode::Lseek as u32 }> { - type InStruct = fuse_abi::LseekIn; - type InPayload = (); - type OutStruct = fuse_abi::LseekOut; - type OutPayload = (); -} + impl Read { + pub(crate) fn create( + nid: u64, + fh: u64, + size: u32, + offset: u64, + ) -> (Box>, Box>) { + let cmd = Cmd::::new( + nid, + fuse_abi::ReadIn { + fh, + offset, + size, + ..Default::default() + }, + ); + let rsp = unsafe { Rsp::::new_uninit(size.try_into().unwrap()) }; -impl Op<{ fuse_abi::Opcode::Lseek as u32 }> { - fn create( - nid: u64, - fh: u64, - offset: isize, - whence: SeekWhence, - ) -> (Box<::Cmd>, Box<::Rsp>) { - let cmd = Self::new_cmd( - nid, - fuse_abi::LseekIn { - fh, - offset: offset.try_into().unwrap(), - whence: num::ToPrimitive::to_u32(&whence).unwrap(), - ..Default::default() - }, - ); - let rsp = unsafe { Box::new_uninit().assume_init() }; + (cmd, rsp) + } + } + + #[derive(Debug)] + pub(crate) struct Lseek; - (cmd, rsp) + impl Op for Lseek { + const OP_CODE: fuse_abi::Opcode = fuse_abi::Opcode::Lseek; + type InStruct = fuse_abi::LseekIn; + type InPayload = (); + type OutStruct = fuse_abi::LseekOut; + type OutPayload = (); } -} -impl OpTrait for Op<{ fuse_abi::Opcode::Readlink as u32 }> { - type InStruct = fuse_abi::ReadlinkIn; - type InPayload = (); - type OutStruct = fuse_abi::ReadlinkOut; + impl Lseek { + pub(crate) fn create( + nid: u64, + fh: u64, + offset: isize, + whence: SeekWhence, + ) -> (Box>, Box>) { + let cmd = Cmd::::new( + nid, + fuse_abi::LseekIn { + fh, + offset: offset.try_into().unwrap(), + whence: num::ToPrimitive::to_u32(&whence).unwrap(), + ..Default::default() + }, + ); + let rsp = unsafe { Box::new_uninit().assume_init() }; - // Since at the time of writing MaybeUninit does not support DSTs as type parameters, we have to define `OutPayload` as [MaybeUninit<_>] - // instead of a MaybeUninit<[_]>. - type OutPayload = [MaybeUninit]; -} + (cmd, rsp) + } + } -impl Op<{ fuse_abi::Opcode::Readlink as u32 }> { - fn create(nid: u64, size: u32) -> (Box<::Cmd>, Box<::Rsp>) { - let cmd = Self::new_cmd(nid, fuse_abi::ReadlinkIn {}); - let rsp = unsafe { - as OpTrait>::Rsp::new_uninit( - size.try_into().unwrap(), - ) - }; + #[derive(Debug)] + pub(crate) struct Readlink; - (cmd, rsp) + impl Op for Readlink { + const OP_CODE: fuse_abi::Opcode = fuse_abi::Opcode::Readlink; + type InStruct = fuse_abi::ReadlinkIn; + type InPayload = (); + type OutStruct = fuse_abi::ReadlinkOut; + + // Since at the time of writing MaybeUninit does not support DSTs as type parameters, we have to define `OutPayload` as [MaybeUninit<_>] + // instead of a MaybeUninit<[_]>. + type OutPayload = [MaybeUninit]; } -} -impl OpTrait for Op<{ fuse_abi::Opcode::Release as u32 }> { - type InStruct = fuse_abi::ReleaseIn; - type InPayload = (); - type OutStruct = fuse_abi::ReleaseOut; - type OutPayload = (); -} + impl Readlink { + pub(crate) fn create(nid: u64, size: u32) -> (Box>, Box>) { + let cmd = Cmd::::new(nid, fuse_abi::ReadlinkIn {}); + let rsp = unsafe { Rsp::::new_uninit(size.try_into().unwrap()) }; -impl Op<{ fuse_abi::Opcode::Release as u32 }> { - fn create(nid: u64, fh: u64) -> (Box<::Cmd>, Box<::Rsp>) { - let cmd = Self::new_cmd( - nid, - fuse_abi::ReleaseIn { - fh, - ..Default::default() - }, - ); - let rsp = unsafe { Box::new_uninit().assume_init() }; + (cmd, rsp) + } + } + + #[derive(Debug)] + pub(crate) struct Release; - (cmd, rsp) + impl Op for Release { + const OP_CODE: fuse_abi::Opcode = fuse_abi::Opcode::Release; + type InStruct = fuse_abi::ReleaseIn; + type InPayload = (); + type OutStruct = fuse_abi::ReleaseOut; + type OutPayload = (); } -} -impl OpTrait for Op<{ fuse_abi::Opcode::Poll as u32 }> { - type InStruct = fuse_abi::PollIn; - type InPayload = (); - type OutStruct = fuse_abi::PollOut; - type OutPayload = (); -} + impl Release { + pub(crate) fn create(nid: u64, fh: u64) -> (Box>, Box>) { + let cmd = Cmd::::new( + nid, + fuse_abi::ReleaseIn { + fh, + ..Default::default() + }, + ); + let rsp = unsafe { Box::new_uninit().assume_init() }; -impl Op<{ fuse_abi::Opcode::Poll as u32 }> { - fn create( - nid: u64, - fh: u64, - kh: u64, - event: PollEvent, - ) -> (Box<::Cmd>, Box<::Rsp>) { - let cmd = Self::new_cmd( - nid, - fuse_abi::PollIn { - fh, - kh, - events: event.bits() as u32, - ..Default::default() - }, - ); - let rsp = unsafe { Box::new_uninit().assume_init() }; + (cmd, rsp) + } + } + + #[derive(Debug)] + pub(crate) struct Poll; - (cmd, rsp) + impl Op for Poll { + const OP_CODE: fuse_abi::Opcode = fuse_abi::Opcode::Poll; + type InStruct = fuse_abi::PollIn; + type InPayload = (); + type OutStruct = fuse_abi::PollOut; + type OutPayload = (); } -} -impl OpTrait for Op<{ fuse_abi::Opcode::Mkdir as u32 }> { - type InStruct = fuse_abi::MkdirIn; - type InPayload = CStr; - type OutStruct = fuse_abi::EntryOut; - type OutPayload = (); -} + impl Poll { + pub(crate) fn create( + nid: u64, + fh: u64, + kh: u64, + event: PollEvent, + ) -> (Box>, Box>) { + let cmd = Cmd::::new( + nid, + fuse_abi::PollIn { + fh, + kh, + events: event.bits() as u32, + ..Default::default() + }, + ); + let rsp = unsafe { Box::new_uninit().assume_init() }; -impl Op<{ fuse_abi::Opcode::Mkdir as u32 }> { - fn create(path: &str, mode: u32) -> (Box<::Cmd>, Box<::Rsp>) { - let cmd = Self::cmd_from_str( - fuse_abi::ROOT_ID, - fuse_abi::MkdirIn { - mode, - ..Default::default() - }, - path, - ); - let rsp = unsafe { Box::new_uninit().assume_init() }; + (cmd, rsp) + } + } + + #[derive(Debug)] + pub(crate) struct Mkdir; - (cmd, rsp) + impl Op for Mkdir { + const OP_CODE: fuse_abi::Opcode = fuse_abi::Opcode::Mkdir; + type InStruct = fuse_abi::MkdirIn; + type InPayload = CStr; + type OutStruct = fuse_abi::EntryOut; + type OutPayload = (); } -} -impl OpTrait for Op<{ fuse_abi::Opcode::Unlink as u32 }> { - type InStruct = fuse_abi::UnlinkIn; - type InPayload = CStr; - type OutStruct = fuse_abi::UnlinkOut; - type OutPayload = (); -} + impl Mkdir { + pub(crate) fn create(path: &str, mode: u32) -> (Box>, Box>) { + let cmd = Cmd::::from_str( + fuse_abi::ROOT_ID, + fuse_abi::MkdirIn { + mode, + ..Default::default() + }, + path, + ); + let rsp = unsafe { Box::new_uninit().assume_init() }; + + (cmd, rsp) + } + } -impl Op<{ fuse_abi::Opcode::Unlink as u32 }> { - fn create(name: &str) -> (Box<::Cmd>, Box<::Rsp>) { - let cmd = Self::cmd_from_str(fuse_abi::ROOT_ID, fuse_abi::UnlinkIn {}, name); - let rsp = unsafe { Box::new_uninit().assume_init() }; + #[derive(Debug)] + pub(crate) struct Unlink; - (cmd, rsp) + impl Op for Unlink { + const OP_CODE: fuse_abi::Opcode = fuse_abi::Opcode::Unlink; + type InStruct = fuse_abi::UnlinkIn; + type InPayload = CStr; + type OutStruct = fuse_abi::UnlinkOut; + type OutPayload = (); } -} -impl OpTrait for Op<{ fuse_abi::Opcode::Rmdir as u32 }> { - type InStruct = fuse_abi::RmdirIn; - type InPayload = CStr; - type OutStruct = fuse_abi::RmdirOut; - 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); + let rsp = unsafe { Box::new_uninit().assume_init() }; + + (cmd, rsp) + } + } -impl Op<{ fuse_abi::Opcode::Rmdir as u32 }> { - fn create(name: &str) -> (Box<::Cmd>, Box<::Rsp>) { - let cmd = Self::cmd_from_str(fuse_abi::ROOT_ID, fuse_abi::RmdirIn {}, name); - let rsp = unsafe { Box::new_uninit().assume_init() }; + #[derive(Debug)] + pub(crate) struct Rmdir; - (cmd, rsp) + impl Op for Rmdir { + const OP_CODE: fuse_abi::Opcode = fuse_abi::Opcode::Rmdir; + type InStruct = fuse_abi::RmdirIn; + type InPayload = CStr; + type OutStruct = fuse_abi::RmdirOut; + type OutPayload = (); } -} -impl OpTrait for Op<{ fuse_abi::Opcode::Lookup as u32 }> { - type InStruct = fuse_abi::LookupIn; - type InPayload = CStr; - type OutStruct = fuse_abi::EntryOut; - 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); + let rsp = unsafe { Box::new_uninit().assume_init() }; + + (cmd, rsp) + } + } -impl Op<{ fuse_abi::Opcode::Lookup as u32 }> { - fn create(name: &str) -> (Box<::Cmd>, Box<::Rsp>) { - let cmd = Self::cmd_from_str(fuse_abi::ROOT_ID, fuse_abi::LookupIn {}, name); - let rsp = unsafe { Box::new_uninit().assume_init() }; + #[derive(Debug)] + pub(crate) struct Lookup; - (cmd, rsp) + impl Op for Lookup { + const OP_CODE: fuse_abi::Opcode = fuse_abi::Opcode::Lookup; + type InStruct = fuse_abi::LookupIn; + type InPayload = CStr; + 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); + let rsp = unsafe { Box::new_uninit().assume_init() }; + + (cmd, rsp) + } } } @@ -401,56 +447,38 @@ impl From for FileAttr { #[repr(C)] #[derive(Debug)] -pub(crate) struct ReqPart { - common_header: H, - op_header: T, - payload: P, +pub(crate) struct Cmd { + in_header: fuse_abi::InHeader, + op_header: O::InStruct, + payload: O::InPayload, } -impl AsSliceU8 for ReqPart { - fn len(&self) -> usize { - self.common_header.len.try_into().unwrap() - } +#[repr(C)] +#[derive(Debug)] +pub(crate) struct UninitCmd { + in_header: MaybeUninit, + op_header: MaybeUninit, + payload: [MaybeUninit], } -// Since we don't bother with initializing the len field, we use the default len implementation. -impl AsSliceU8 for ReqPart, P> {} - -impl ReqPart -where - Self: core::ptr::Pointee, -{ - // MaybeUninit does not accept DSTs as type parameter - unsafe fn new_uninit(len: usize) -> Box { - unsafe { - Box::from_raw(core::ptr::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(), - ) as *mut (), - len, - )) - } - } +// 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: (), } -// We create the objects through the Operation struct rather than the Cmd struct to be able access the Opcode. - -impl Op +impl Cmd where - Self: OpTrait::InStruct, ()>>, + O: ops::Op, { - fn new_cmd( - nodeid: u64, - op_header: ::InStruct, - ) -> Box::InStruct, ()>> { - Box::new(ReqPart { - common_header: fuse_abi::InHeader { - len: Layout::new::<::Cmd>().size() as u32, - opcode: O, + fn new(nodeid: u64, op_header: O::InStruct) -> Box { + Box::new(Cmd { + in_header: fuse_abi::InHeader { + len: Layout::new::().size() as u32, + opcode: O::OP_CODE as u32, nodeid, unique: 1, ..Default::default() @@ -461,71 +489,125 @@ where } } -impl Op -where - Self: OpTrait, -{ - fn cmd_with_capacity( - nodeid: u64, - op_header: as OpTrait>::InStruct, - len: usize, - ) -> Box::InStruct, [u8]>> { - let mut cmd = unsafe { ReqPart::new_uninit(len) }; - cmd.common_header = fuse_abi::InHeader { +impl Cmd { + fn with_capacity(nodeid: u64, op_header: O::InStruct, len: usize) -> Box> + where + Cmd: core::ptr::Pointee, + { + let mut cmd = unsafe { Self::new_uninit(len) }; + cmd.in_header = MaybeUninit::new(fuse_abi::InHeader { len: core::mem::size_of_val(cmd.as_ref()) .try_into() .expect("The command is too large"), - opcode: O, + opcode: O::OP_CODE as u32, nodeid, unique: 1, ..Default::default() - }; - cmd.op_header = op_header; + }); + cmd.op_header = MaybeUninit::new(op_header); cmd } } -impl Op +impl Cmd where - Self: OpTrait::InStruct, [u8]>>, + O: ops::Op, { - fn cmd_from_array( - nodeid: u64, - op_header: ::InStruct, - data: &[u8], - ) -> Box<::Cmd> { - let mut cmd = Self::cmd_with_capacity(nodeid, op_header, data.len()); - cmd.payload.copy_from_slice(data); - cmd + fn from_array(nodeid: u64, op_header: O::InStruct, data: &[u8]) -> Box> { + let mut cmd = Self::with_capacity(nodeid, op_header, data.len()); + MaybeUninit::write_slice(&mut cmd.payload, data); + unsafe { core::intrinsics::transmute(cmd) } } } -impl Op +impl Cmd where - Self: OpTrait::InStruct, CStr>>, + O: ops::Op, { - fn cmd_from_str( - nodeid: u64, - op_header: ::InStruct, - str: &str, - ) -> Box<::Cmd> { + 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::cmd_with_capacity(nodeid, op_header, str_bytes.len() + 1); - cmd.payload[..str_bytes.len()].copy_from_slice(str_bytes); - cmd.payload[str_bytes.len()] = b'\0'; + let mut cmd = Self::with_capacity(nodeid, op_header, str_bytes.len() + 1); + MaybeUninit::write_slice(&mut cmd.payload[..str_bytes.len()], str_bytes); + 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 +where + Self: core::ptr::Pointee, +{ + // MaybeUninit does not accept DSTs as type parameter + unsafe fn new_uninit(len: usize) -> Box> { + unsafe { + Box::from_raw(core::ptr::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(), + ) as *mut (), + len, + )) + } + } +} + +#[repr(C)] +#[derive(Debug)] +pub(crate) struct Rsp { + out_header: MaybeUninit, + op_header: MaybeUninit, + payload: O::OutPayload, +} + +#[repr(C)] +#[derive(Debug)] +pub(crate) struct PayloadlessRsp { + out_header: MaybeUninit, + op_header: MaybeUninit, + payload: (), +} + +// Since we don't bother with initializing the len field, we use the default len implementation. +impl AsSliceU8 for Rsp {} + +impl Rsp +where + Self: core::ptr::Pointee, +{ + unsafe fn new_uninit(len: usize) -> Box { + unsafe { + Box::from_raw(core::ptr::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(), + ) as *mut (), + len, + )) + } + } +} + fn lookup(name: &str) -> Option { - let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Lookup as u32 }>::create(name); + let (cmd, mut rsp) = ops::Lookup::create(name); get_filesystem_driver() .unwrap() .lock() - .send_command::<{ fuse_abi::Opcode::Lookup as u32 }>(cmd.as_ref(), rsp.as_mut()); - if rsp.common_header.error == 0 { - Some(unsafe { rsp.op_header.assume_init().nodeid }) + .send_command(cmd.as_ref(), rsp.as_mut()); + if unsafe { rsp.out_header.assume_init_ref().error } == 0 { + Some(unsafe { rsp.op_header.assume_init_ref().nodeid }) } else { None } @@ -533,19 +615,19 @@ fn lookup(name: &str) -> Option { fn readlink(nid: u64) -> Result { let len = MAX_READ_LEN as u32; - let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Readlink as u32 }>::create(nid, len); + let (cmd, mut rsp) = ops::Readlink::create(nid, len); get_filesystem_driver() .unwrap() .lock() - .send_command::<{ fuse_abi::Opcode::Readlink as u32 }>(cmd.as_ref(), rsp.as_mut()); - let len: usize = if rsp.common_header.len as usize + .send_command(cmd.as_ref(), 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::() >= len.try_into().unwrap() { len.try_into().unwrap() } else { - rsp.common_header.len as usize + (unsafe { rsp.out_header.assume_init_ref().len } as usize) - ::core::mem::size_of::() - ::core::mem::size_of::() }; @@ -578,19 +660,18 @@ impl FuseFileHandleInner { future::poll_fn(|cx| { if let (Some(nid), Some(fh)) = (self.fuse_nid, self.fuse_fh) { - let (cmd, mut rsp) = - Op::<{ fuse_abi::Opcode::Poll as u32 }>::create(nid, fh, kh, events); + let (cmd, mut rsp) = ops::Poll::create(nid, fh, kh, events); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{ fuse_abi::Opcode::Poll as u32 }>(cmd.as_ref(), rsp.as_mut()); + .send_command(cmd.as_ref(), rsp.as_mut()); - if rsp.common_header.error < 0 { + if unsafe { rsp.out_header.assume_init_ref().error } < 0 { Poll::Ready(Err(IoError::EIO)) } else { let revents = unsafe { PollEvent::from_bits( - i16::try_from(rsp.op_header.assume_init().revents).unwrap(), + i16::try_from(rsp.op_header.assume_init_ref().revents).unwrap(), ) .unwrap() }; @@ -618,24 +699,20 @@ impl FuseFileHandleInner { len = MAX_READ_LEN; } if let (Some(nid), Some(fh)) = (self.fuse_nid, self.fuse_fh) { - let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Read as u32 }>::create( - nid, - fh, - len.try_into().unwrap(), - self.offset as u64, - ); + let (cmd, mut rsp) = + ops::Read::create(nid, fh, len.try_into().unwrap(), self.offset as u64); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{ fuse_abi::Opcode::Read as u32 }>(cmd.as_ref(), rsp.as_mut()); - let len: usize = if rsp.common_header.len as usize + .send_command(cmd.as_ref(), 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::() >= len { len } else { - rsp.common_header.len as usize + (unsafe { rsp.out_header.assume_init_ref().len } as usize) - ::core::mem::size_of::() - ::core::mem::size_of::() }; @@ -664,22 +741,17 @@ impl FuseFileHandleInner { len = MAX_WRITE_LEN; } if let (Some(nid), Some(fh)) = (self.fuse_nid, self.fuse_fh) { - let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Write as u32 }>::create( - nid, - fh, - &buf[..len], - self.offset as u64, - ); + let (cmd, mut rsp) = ops::Write::create(nid, fh, &buf[..len], self.offset as u64); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{ fuse_abi::Opcode::Write as u32 }>(cmd.as_ref(), rsp.as_mut()); + .send_command(cmd.as_ref(), rsp.as_mut()); - if rsp.common_header.error < 0 { + if unsafe { rsp.out_header.assume_init_ref().error } < 0 { return Err(IoError::EIO); } - let rsp_size = unsafe { rsp.op_header.assume_init().size }; + let rsp_size = unsafe { rsp.op_header.assume_init_ref().size }; let len: usize = if rsp_size > buf.len().try_into().unwrap() { buf.len() } else { @@ -697,18 +769,17 @@ impl FuseFileHandleInner { debug!("FUSE lseek"); if let (Some(nid), Some(fh)) = (self.fuse_nid, self.fuse_fh) { - let (cmd, mut rsp) = - Op::<{ fuse_abi::Opcode::Lseek as u32 }>::create(nid, fh, offset, whence); + let (cmd, mut rsp) = ops::Lseek::create(nid, fh, offset, whence); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{ fuse_abi::Opcode::Lseek as u32 }>(cmd.as_ref(), rsp.as_mut()); + .send_command(cmd.as_ref(), rsp.as_mut()); - if rsp.common_header.error < 0 { + if unsafe { rsp.out_header.assume_init_ref().error } < 0 { return Err(IoError::EIO); } - let rsp_offset = unsafe { rsp.op_header.assume_init().offset }; + let rsp_offset = unsafe { rsp.op_header.assume_init_ref().offset }; Ok(rsp_offset.try_into().unwrap()) } else { @@ -720,14 +791,12 @@ impl FuseFileHandleInner { impl Drop for FuseFileHandleInner { fn drop(&mut self) { if self.fuse_nid.is_some() && self.fuse_fh.is_some() { - let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Release as u32 }>::create( - self.fuse_nid.unwrap(), - self.fuse_fh.unwrap(), - ); + let (cmd, mut rsp) = + ops::Release::create(self.fuse_nid.unwrap(), self.fuse_fh.unwrap()); get_filesystem_driver() .unwrap() .lock() - .send_command::<{ fuse_abi::Opcode::Release as u32 }>(cmd.as_ref(), rsp.as_mut()); + .send_command(cmd.as_ref(), rsp.as_mut()); } } } @@ -799,13 +868,13 @@ impl VfsNode for FuseDirectory { // Opendir // Flag 0x10000 for O_DIRECTORY might not be necessary - let (mut cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Open as u32 }>::create(fuse_nid, 0x10000); - cmd.common_header.opcode = fuse_abi::Opcode::Opendir as u32; + let (mut cmd, mut rsp) = ops::Open::create(fuse_nid, 0x10000); + cmd.in_header.opcode = fuse_abi::Opcode::Opendir as u32; get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{ fuse_abi::Opcode::Open as u32 }>(cmd.as_ref(), rsp.as_mut()); - let fuse_fh = unsafe { rsp.op_header.assume_init().fh }; + .send_command(cmd.as_ref(), rsp.as_mut()); + let fuse_fh = unsafe { rsp.op_header.assume_init_ref().fh }; debug!("FUSE readdir: {}", path); @@ -814,22 +883,21 @@ impl VfsNode for FuseDirectory { let mut offset: usize = 0; // read content of the directory - let (mut cmd, mut rsp) = - Op::<{ fuse_abi::Opcode::Read as u32 }>::create(fuse_nid, fuse_fh, len, 0); - cmd.common_header.opcode = fuse_abi::Opcode::Readdir as u32; + let (mut cmd, mut rsp) = ops::Read::create(fuse_nid, fuse_fh, len, 0); + cmd.in_header.opcode = fuse_abi::Opcode::Readdir as u32; get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{ fuse_abi::Opcode::Read as u32 }>(cmd.as_ref(), rsp.as_mut()); + .send_command(cmd.as_ref(), rsp.as_mut()); - let len: usize = if rsp.common_header.len as usize + let len: usize = if unsafe { rsp.out_header.assume_init_ref().len } as usize - ::core::mem::size_of::() - ::core::mem::size_of::() >= len.try_into().unwrap() { len.try_into().unwrap() } else { - rsp.common_header.len as usize + (unsafe { rsp.out_header.assume_init_ref().len } as usize) - ::core::mem::size_of::() - ::core::mem::size_of::() }; @@ -840,7 +908,9 @@ impl VfsNode for FuseDirectory { } let mut entries: Vec = Vec::new(); - while rsp.common_header.len as usize - offset > core::mem::size_of::() { + while (unsafe { rsp.out_header.assume_init_ref().len } as usize) - offset + > core::mem::size_of::() + { let dirent = unsafe { &*(rsp.payload.as_ptr().byte_add(offset) as *const fuse_abi::Dirent) }; @@ -859,11 +929,11 @@ impl VfsNode for FuseDirectory { })); } - let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Release as u32 }>::create(fuse_nid, fuse_fh); + let (cmd, mut rsp) = ops::Release::create(fuse_nid, fuse_fh); get_filesystem_driver() .unwrap() .lock() - .send_command::<{ fuse_abi::Opcode::Release as u32 }>(cmd.as_ref(), rsp.as_mut()); + .send_command(cmd.as_ref(), rsp.as_mut()); Ok(entries) } @@ -882,13 +952,13 @@ impl VfsNode for FuseDirectory { debug!("FUSE stat: {}", path); // Is there a better way to implement this? - let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Lookup as u32 }>::create(&path); + let (cmd, mut rsp) = ops::Lookup::create(&path); get_filesystem_driver() .unwrap() .lock() - .send_command::<{ fuse_abi::Opcode::Lookup as u32 }>(cmd.as_ref(), rsp.as_mut()); + .send_command(cmd.as_ref(), rsp.as_mut()); - if rsp.common_header.error != 0 { + if unsafe { rsp.out_header.assume_init_ref().error } != 0 { // TODO: Correct error handling return Err(IoError::EIO); } @@ -918,11 +988,11 @@ impl VfsNode for FuseDirectory { debug!("FUSE lstat: {}", path); - let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Lookup as u32 }>::create(&path); + let (cmd, mut rsp) = ops::Lookup::create(&path); get_filesystem_driver() .unwrap() .lock() - .send_command::<{ fuse_abi::Opcode::Lookup as u32 }>(cmd.as_ref(), rsp.as_mut()); + .send_command(cmd.as_ref(), rsp.as_mut()); let attr = unsafe { rsp.op_header.assume_init().attr }; Ok(FileAttr::from(attr)) @@ -963,26 +1033,21 @@ impl VfsNode for FuseDirectory { } // 3.FUSE_OPEN(nodeid, O_RDONLY) -> fh - let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Open as u32 }>::create( - file_guard.fuse_nid.unwrap(), - opt.bits().try_into().unwrap(), - ); + let (cmd, mut rsp) = + ops::Open::create(file_guard.fuse_nid.unwrap(), opt.bits().try_into().unwrap()); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{ fuse_abi::Opcode::Open as u32 }>(cmd.as_ref(), rsp.as_mut()); - file_guard.fuse_fh = Some(unsafe { rsp.op_header.assume_init().fh }); + .send_command(cmd.as_ref(), 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) = Op::<{ fuse_abi::Opcode::Create as u32 }>::create( - &path, - opt.bits().try_into().unwrap(), - mode.bits(), - ); + let (cmd, mut rsp) = + ops::Create::create(&path, opt.bits().try_into().unwrap(), mode.bits()); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{ fuse_abi::Opcode::Create as u32 }>(cmd.as_ref(), rsp.as_mut()); + .send_command(cmd.as_ref(), rsp.as_mut()); let inner = unsafe { rsp.op_header.assume_init() }; file_guard.fuse_nid = Some(inner.entry.nodeid); @@ -1005,11 +1070,11 @@ impl VfsNode for FuseDirectory { .collect() }; - let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Unlink as u32 }>::create(&path); + let (cmd, mut rsp) = ops::Unlink::create(&path); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{ fuse_abi::Opcode::Unlink as u32 }>(cmd.as_ref(), rsp.as_mut()); + .send_command(cmd.as_ref(), rsp.as_mut()); trace!("unlink answer {:?}", rsp); Ok(()) @@ -1026,11 +1091,11 @@ impl VfsNode for FuseDirectory { .collect() }; - let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Rmdir as u32 }>::create(&path); + let (cmd, mut rsp) = ops::Rmdir::create(&path); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{ fuse_abi::Opcode::Rmdir as u32 }>(cmd.as_ref(), rsp.as_mut()); + .send_command(cmd.as_ref(), rsp.as_mut()); trace!("rmdir answer {:?}", rsp); Ok(()) @@ -1050,16 +1115,19 @@ impl VfsNode for FuseDirectory { .map(|v| "/".to_owned() + v) .collect() }; - let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Mkdir as u32 }>::create(&path, mode.bits()); + let (cmd, mut rsp) = ops::Mkdir::create(&path, mode.bits()); get_filesystem_driver() .ok_or(IoError::ENOSYS)? .lock() - .send_command::<{ fuse_abi::Opcode::Mkdir as u32 }>(cmd.as_ref(), rsp.as_mut()); - if rsp.common_header.error == 0 { + .send_command(cmd.as_ref(), rsp.as_mut()); + if unsafe { rsp.out_header.assume_init_ref().error } == 0 { Ok(()) } else { - Err(num::FromPrimitive::from_i32(rsp.common_header.error).unwrap()) + Err( + num::FromPrimitive::from_i32(unsafe { rsp.out_header.assume_init_ref().error }) + .unwrap(), + ) } } } @@ -1068,10 +1136,8 @@ pub(crate) fn init() { debug!("Try to initialize fuse filesystem"); if let Some(driver) = get_filesystem_driver() { - let (cmd, mut rsp) = Op::<{ fuse_abi::Opcode::Init as u32 }>::create(); - driver - .lock() - .send_command::<{ fuse_abi::Opcode::Init as u32 }>(cmd.as_ref(), rsp.as_mut()); + let (cmd, mut rsp) = ops::Init::create(); + driver.lock().send_command(cmd.as_ref(), rsp.as_mut()); trace!("fuse init answer: {:?}", rsp); let mount_point = format!("/{}", driver.lock().get_mount_point()); diff --git a/src/fs/fuse_abi.rs b/src/fs/fuse_abi.rs index 98d759910d..d4628dcd18 100644 --- a/src/fs/fuse_abi.rs +++ b/src/fs/fuse_abi.rs @@ -1,3 +1,4 @@ +#[cfg(all(feature = "fuse", feature = "pci"))] pub(crate) const ROOT_ID: u64 = 1; #[allow(dead_code)] diff --git a/src/lib.rs b/src/lib.rs index 607803afb5..f2486bab23 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,10 +15,10 @@ #![cfg_attr(target_arch = "riscv64", feature(offset_of))] #![feature(allocator_api)] #![feature(asm_const)] -#![feature(associated_type_defaults)] #![feature(exposed_provenance)] #![feature(linked_list_cursors)] #![feature(maybe_uninit_slice)] +#![feature(maybe_uninit_write_slice)] #![feature(naked_functions)] #![feature(new_uninit)] #![feature(noop_waker)] From 93fc6cbb2ab2432b3d895a28fd1507226823734c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Wed, 14 Feb 2024 15:54:59 +0100 Subject: [PATCH 10/11] fuse: remove dependency on unstable ptr_metadata --- src/fs/fuse.rs | 28 +++++++++++----------------- src/lib.rs | 1 - 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/fs/fuse.rs b/src/fs/fuse.rs index a91d22ef09..15dd2e1db1 100644 --- a/src/fs/fuse.rs +++ b/src/fs/fuse.rs @@ -490,10 +490,7 @@ where } impl Cmd { - fn with_capacity(nodeid: u64, op_header: O::InStruct, len: usize) -> Box> - where - Cmd: core::ptr::Pointee, - { + 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 { len: core::mem::size_of_val(cmd.as_ref()) @@ -540,23 +537,20 @@ impl AsSliceU8 for Cmd { } } -impl Cmd -where - Self: core::ptr::Pointee, -{ +impl Cmd { // MaybeUninit does not accept DSTs as type parameter unsafe fn new_uninit(len: usize) -> Box> { unsafe { - Box::from_raw(core::ptr::from_raw_parts_mut( + 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(), - ) as *mut (), - len, - )) + ), + 0, + ) as *mut UninitCmd) } } } @@ -582,20 +576,20 @@ impl AsSliceU8 for Rsp {} impl Rsp where - Self: core::ptr::Pointee, + O: ops::Op]>, { unsafe fn new_uninit(len: usize) -> Box { unsafe { - Box::from_raw(core::ptr::from_raw_parts_mut( + 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(), - ) as *mut (), - len, - )) + ), + 0, + ) as *mut Rsp) } } } diff --git a/src/lib.rs b/src/lib.rs index f2486bab23..945416afa1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,7 +23,6 @@ #![feature(new_uninit)] #![feature(noop_waker)] #![feature(pointer_is_aligned)] -#![feature(ptr_metadata)] #![feature(slice_from_ptr_range)] #![cfg_attr( any(target_arch = "aarch64", target_arch = "riscv64"), From bd900cd4428193b5f81e2ed1901b8acc0315d155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Wed, 14 Feb 2024 16:10:56 +0100 Subject: [PATCH 11/11] fuse: remove dependency on unstable maybe_uninit_write_slice --- src/fs/fuse.rs | 8 ++++++-- src/lib.rs | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/fs/fuse.rs b/src/fs/fuse.rs index 15dd2e1db1..d9bdfebd86 100644 --- a/src/fs/fuse.rs +++ b/src/fs/fuse.rs @@ -512,7 +512,9 @@ where { fn from_array(nodeid: u64, op_header: O::InStruct, data: &[u8]) -> Box> { let mut cmd = Self::with_capacity(nodeid, op_header, data.len()); - MaybeUninit::write_slice(&mut cmd.payload, data); + for (target, source) in cmd.payload.iter_mut().zip(data) { + *target = MaybeUninit::new(*source); + } unsafe { core::intrinsics::transmute(cmd) } } } @@ -525,7 +527,9 @@ where 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); - MaybeUninit::write_slice(&mut cmd.payload[..str_bytes.len()], str_bytes); + 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) } } diff --git a/src/lib.rs b/src/lib.rs index 945416afa1..2626d9d374 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,7 +18,6 @@ #![feature(exposed_provenance)] #![feature(linked_list_cursors)] #![feature(maybe_uninit_slice)] -#![feature(maybe_uninit_write_slice)] #![feature(naked_functions)] #![feature(new_uninit)] #![feature(noop_waker)]