Skip to content

Commit b3e1c3b

Browse files
committed
Allow for raw marshalling of BackingIds
Adds methods to convert BackingIds from/to their raw `backing_id` values, which allows for marshalling of backing file references across process boundaries.
1 parent d203403 commit b3e1c3b

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

src/channel.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,8 @@ impl ChannelSender {
9595
pub(crate) fn open_backing(&self, fd: BorrowedFd<'_>) -> std::io::Result<BackingId> {
9696
BackingId::create(&self.0, fd)
9797
}
98+
99+
pub(crate) unsafe fn wrap_backing(&self, id: u32) -> BackingId {
100+
unsafe { BackingId::wrap_raw(&self.0, id) }
101+
}
98102
}

src/passthrough.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ pub struct BackingId {
3535
}
3636

3737
impl BackingId {
38+
pub(crate) unsafe fn wrap_raw(channel: &Arc<DevFuse>, id: u32) -> Self {
39+
Self {
40+
channel: Arc::downgrade(channel),
41+
backing_id: id,
42+
}
43+
}
44+
3845
pub(crate) fn create(channel: &Arc<DevFuse>, fd: impl AsFd) -> std::io::Result<Self> {
3946
if !cfg!(target_os = "linux") {
4047
return Err(std::io::Error::new(
@@ -54,6 +61,19 @@ impl BackingId {
5461
backing_id: id as u32,
5562
})
5663
}
64+
65+
/// Converts this backing file reference into the raw `backing_id` value as returned by the kernel.
66+
///
67+
/// This method transfers ownership of the backing file to the caller, who must invoke the
68+
/// `FUSE_DEV_IOC_BACKING_CLOSE` themselves once they wish to close the backing file.
69+
///
70+
/// The returned ID may subsequently be reopened using
71+
/// [`ReplyOpen::wrap_backing()`](crate::ReplyOpen::wrap_backing).
72+
pub fn into_raw(self) -> u32 {
73+
let id = self.backing_id;
74+
std::mem::forget(self);
75+
id
76+
}
5777
}
5878

5979
impl Drop for BackingId {

src/reply.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,17 @@ impl ReplySender {
6969
ReplySender::Sync(_) => unreachable!(),
7070
}
7171
}
72+
73+
/// Wraps a raw backing file ID
74+
pub(crate) unsafe fn wrap_backing(&self, id: u32) -> BackingId {
75+
match self {
76+
ReplySender::Channel(sender) => unsafe { sender.wrap_backing(id) },
77+
#[cfg(test)]
78+
ReplySender::Assert(_) => unreachable!(),
79+
#[cfg(test)]
80+
ReplySender::Sync(_) => unreachable!(),
81+
}
82+
}
7283
}
7384

7485
#[cfg(test)]
@@ -335,6 +346,24 @@ impl ReplyOpen {
335346
self.reply.sender.as_ref().unwrap().open_backing(fd.as_fd())
336347
}
337348

349+
/// Wraps a raw FUSE `backing_id` value, returning a `BackingId`. Once you have the backing ID,
350+
/// you can pass it as the 3rd parameter of [`ReplyOpen::opened_passthrough()`]. This is done in
351+
/// two separate steps because it may make sense to reuse backing IDs (to avoid having to
352+
/// repeatedly reopen the underlying file or potentially keep thousands of fds open).
353+
///
354+
/// This function takes ownership of the given backing ID value, automatically closing it once
355+
/// the returned `BackingId` is dropped. You may reobtain ownership of the backing ID by calling
356+
/// [`BackingId::into_raw()`].
357+
///
358+
/// # Safety
359+
///
360+
/// The given ID must be open and belong to this FUSE session, and may not be closed while the
361+
/// returned `BackingId` instance is still live.
362+
pub unsafe fn wrap_backing(&self, id: u32) -> BackingId {
363+
// TODO: assert passthrough capability is enabled.
364+
unsafe { self.reply.sender.as_ref().unwrap().wrap_backing(id) }
365+
}
366+
338367
/// Reply to a request with an opened backing id. Call [`ReplyOpen::open_backing()`]
339368
/// to get one of these.
340369
pub fn opened_passthrough(self, fh: ll::FileHandle, flags: FopenFlags, backing_id: &BackingId) {
@@ -474,6 +503,24 @@ impl ReplyCreate {
474503
self.reply.sender.as_ref().unwrap().open_backing(fd.as_fd())
475504
}
476505

506+
/// Wraps a raw FUSE `backing_id` value, returning a `BackingId`. Once you have the backing ID,
507+
/// you can pass it as the 3rd parameter of [`ReplyOpen::opened_passthrough()`]. This is done in
508+
/// two separate steps because it may make sense to reuse backing IDs (to avoid having to
509+
/// repeatedly reopen the underlying file or potentially keep thousands of fds open).
510+
///
511+
/// This function takes ownership of the given backing ID value, automatically closing it once
512+
/// the returned `BackingId` is dropped. You may reobtain ownership of the backing ID by calling
513+
/// [`BackingId::into_raw()`].
514+
///
515+
/// # Safety
516+
///
517+
/// The given ID must be open and belong to this FUSE session, and may not be closed while the
518+
/// returned `BackingId` instance is still live.
519+
pub unsafe fn wrap_backing(&self, id: u32) -> BackingId {
520+
// TODO: assert passthrough capability is enabled.
521+
unsafe { self.reply.sender.as_ref().unwrap().wrap_backing(id) }
522+
}
523+
477524
/// Reply to a request with an opened backing id. Call `ReplyCreate::open_backing()` to get one of
478525
/// these.
479526
pub fn created_passthrough(

0 commit comments

Comments
 (0)