From 3eefa9abc4987c49224998d0fb77a63ec0e8b0c0 Mon Sep 17 00:00:00 2001 From: Colin Marc Date: Sat, 12 Oct 2024 21:08:15 +0200 Subject: [PATCH 1/2] Allow users to create Notifier objects when handling requests --- src/request.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/request.rs b/src/request.rs index 60068083..a5ccfc9a 100644 --- a/src/request.rs +++ b/src/request.rs @@ -19,6 +19,8 @@ use crate::reply::ReplyDirectoryPlus; use crate::reply::{Reply, ReplyDirectory, ReplySender}; use crate::session::{Session, SessionACL}; use crate::Filesystem; +#[cfg(feature = "abi-7-11")] +use crate::Notifier; use crate::{ll, KernelConfig}; /// Request data structure @@ -643,6 +645,13 @@ impl<'a> Request<'a> { Reply::new(self.request.unique().into(), self.ch.clone()) } + /// Create a [Notifier] that can be used to send notifications back to the + /// kernel. + #[cfg(feature = "abi-7-11")] + pub fn notifier(&self) -> Notifier { + Notifier::new(self.ch.clone()) + } + /// Returns the unique identifier of this request #[inline] pub fn unique(&self) -> u64 { From 93ce6130efbd3b9dadee8a4632f63b0cdbb5a687 Mon Sep 17 00:00:00 2001 From: Colin Marc Date: Fri, 18 Oct 2024 15:55:59 +0200 Subject: [PATCH 2/2] Pass a Notifier to poll() implementations This allows filesystems to respond directly to poll requests without having saved a notifier at session creation time. --- examples/poll.rs | 6 +++--- src/lib.rs | 8 ++++---- src/notify.rs | 36 +++++++++++++++++++++++++++++++++++- src/request.rs | 13 ++++--------- src/session.rs | 2 +- 5 files changed, 47 insertions(+), 18 deletions(-) diff --git a/examples/poll.rs b/examples/poll.rs index 6ae3d1c2..a86e0879 100644 --- a/examples/poll.rs +++ b/examples/poll.rs @@ -23,7 +23,7 @@ use libc::{EACCES, EBADF, EBUSY, EINVAL, ENOENT, ENOTDIR}; use fuser::{ consts::{FOPEN_DIRECT_IO, FOPEN_NONSEEKABLE, FUSE_POLL_SCHEDULE_NOTIFY}, - FileAttr, FileType, MountOption, Request, FUSE_ROOT_ID, + FileAttr, FileType, MountOption, PollHandle, Request, FUSE_ROOT_ID, }; const NUMFILES: u8 = 16; @@ -251,7 +251,7 @@ impl fuser::Filesystem for FSelFS { _req: &Request, _ino: u64, fh: u64, - kh: u64, + ph: PollHandle, _events: u32, flags: u32, reply: fuser::ReplyPoll, @@ -271,7 +271,7 @@ impl fuser::Filesystem for FSelFS { if flags & FUSE_POLL_SCHEDULE_NOTIFY != 0 { d.notify_mask |= 1 << idx; - d.poll_handles[idx as usize] = kh; + d.poll_handles[idx as usize] = ph.into(); } let nbytes = d.bytecnt[idx as usize]; diff --git a/src/lib.rs b/src/lib.rs index d1f126bd..51480408 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,7 +28,7 @@ use crate::session::MAX_WRITE_SIZE; pub use ll::fuse_abi::fuse_forget_one; pub use mnt::mount_options::MountOption; #[cfg(feature = "abi-7-11")] -pub use notify::Notifier; +pub use notify::{Notifier, PollHandle}; #[cfg(feature = "abi-7-11")] pub use reply::ReplyPoll; #[cfg(target_os = "macos")] @@ -884,14 +884,14 @@ pub trait Filesystem { _req: &Request<'_>, ino: u64, fh: u64, - kh: u64, + ph: PollHandle, events: u32, flags: u32, reply: ReplyPoll, ) { debug!( - "[Not Implemented] poll(ino: {:#x?}, fh: {}, kh: {}, events: {}, flags: {})", - ino, fh, kh, events, flags + "[Not Implemented] poll(ino: {:#x?}, fh: {}, ph: {:?}, events: {}, flags: {})", + ino, fh, ph, events, flags ); reply.error(ENOSYS); } diff --git a/src/notify.rs b/src/notify.rs index 56380727..4442252a 100644 --- a/src/notify.rs +++ b/src/notify.rs @@ -13,8 +13,42 @@ use crate::{ reply::ReplySender, }; +/// A handle to a pending poll() request. Can be saved and used to notify the +/// kernel when a poll is ready. +#[derive(Clone)] +pub struct PollHandle { + handle: u64, + notifier: Notifier, +} + +impl PollHandle { + pub(crate) fn new(cs: ChannelSender, kh: u64) -> Self { + Self { + handle: kh, + notifier: Notifier::new(cs), + } + } + + /// Notify the kernel that the associated file handle is ready to be polled. + pub fn notify(self) -> io::Result<()> { + self.notifier.poll(self.handle) + } +} + +impl From for u64 { + fn from(value: PollHandle) -> Self { + value.handle + } +} + +impl std::fmt::Debug for PollHandle { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("PollHandle").field(&self.handle).finish() + } +} + /// A handle by which the application can send notifications to the server -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Notifier(ChannelSender); impl Notifier { diff --git a/src/request.rs b/src/request.rs index a5ccfc9a..c2de185a 100644 --- a/src/request.rs +++ b/src/request.rs @@ -20,7 +20,7 @@ use crate::reply::{Reply, ReplyDirectory, ReplySender}; use crate::session::{Session, SessionACL}; use crate::Filesystem; #[cfg(feature = "abi-7-11")] -use crate::Notifier; +use crate::PollHandle; use crate::{ll, KernelConfig}; /// Request data structure @@ -524,11 +524,13 @@ impl<'a> Request<'a> { } #[cfg(feature = "abi-7-11")] ll::Operation::Poll(x) => { + let ph = PollHandle::new(se.ch.sender(), x.kernel_handle()); + se.filesystem.poll( self, self.request.nodeid().into(), x.file_handle().into(), - x.kernel_handle(), + ph, x.events(), x.flags(), self.reply(), @@ -645,13 +647,6 @@ impl<'a> Request<'a> { Reply::new(self.request.unique().into(), self.ch.clone()) } - /// Create a [Notifier] that can be used to send notifications back to the - /// kernel. - #[cfg(feature = "abi-7-11")] - pub fn notifier(&self) -> Notifier { - Notifier::new(self.ch.clone()) - } - /// Returns the unique identifier of this request #[inline] pub fn unique(&self) -> u64 { diff --git a/src/session.rs b/src/session.rs index 44919264..9d632a96 100644 --- a/src/session.rs +++ b/src/session.rs @@ -44,7 +44,7 @@ pub struct Session { /// Filesystem operation implementations pub(crate) filesystem: FS, /// Communication channel to the kernel driver - ch: Channel, + pub(crate) ch: Channel, /// Handle to the mount. Dropping this unmounts. mount: Arc>>, /// Mount point