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 60068083..c2de185a 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::PollHandle; use crate::{ll, KernelConfig}; /// Request data structure @@ -522,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(), 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