Skip to content

Commit cd627af

Browse files
loheagnjiangliu
authored andcommitted
linux_session: add clone_fuse_file method to FuseSession
This patch adds `clone_fuse_file` method to `FuseSession`. This function obtains a new file descriptor by opening `/dev/fuse` and associates the file descriptor with the original fuse connection of fuse session using the ioctl `FUSE_DEV_IOC_CLONE` command. Signed-off-by: Nan Li <[email protected]>
1 parent cc0a191 commit cd627af

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

src/transport/fusedev/linux_session.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,35 @@ impl FuseSession {
133133
self.file = Some(file);
134134
}
135135

136+
/// Clone fuse file using ioctl FUSE_DEV_IOC_CLONE.
137+
pub fn clone_fuse_file(&self) -> Result<File> {
138+
let mut old_fd = self
139+
.file
140+
.as_ref()
141+
.ok_or(SessionFailure(
142+
"fuse session file doesn't exist".to_string(),
143+
))?
144+
.as_raw_fd();
145+
146+
let cloned_file = OpenOptions::new()
147+
.create(false)
148+
.read(true)
149+
.write(true)
150+
.open(FUSE_DEVICE)
151+
.map_err(|e| SessionFailure(format!("open {FUSE_DEVICE}: {e}")))?;
152+
153+
// define the function which invokes "ioctl FUSE_DEV_IOC_CLONE"
154+
// refer: https://github.com/torvalds/linux/blob/c42d9eeef8e5ba9292eda36fd8e3c11f35ee065c/include/uapi/linux/fuse.h#L1051-L1052
155+
// #define FUSE_DEV_IOC_MAGIC 229
156+
// #define FUSE_DEV_IOC_CLONE _IOR(FUSE_DEV_IOC_MAGIC, 0, uint32_t)
157+
nix::ioctl_read!(clone_fuse_fd, 229, 0, i32);
158+
159+
unsafe { clone_fuse_fd(cloned_file.as_raw_fd(), (&mut old_fd) as *mut i32) }
160+
.map_err(|e| SessionFailure(format!("failed to clone fuse file: {:?}", e)))?;
161+
162+
Ok(cloned_file)
163+
}
164+
136165
/// Get the mountpoint of the session.
137166
pub fn mountpoint(&self) -> &Path {
138167
&self.mountpoint
@@ -643,6 +672,20 @@ mod tests {
643672
se.set_fusermount("fusermount");
644673
assert_eq!(se.get_fusermount(), "fusermount");
645674
}
675+
676+
#[test]
677+
fn test_clone_fuse_file() {
678+
let dir = TempDir::new().unwrap();
679+
let mut se = FuseSession::new(dir.as_path(), "foo", "bar", true).unwrap();
680+
se.mount().unwrap();
681+
682+
let cloned_file = se.clone_fuse_file().unwrap();
683+
assert!(cloned_file.as_raw_fd() > 0);
684+
685+
se.umount().unwrap();
686+
se.set_fuse_file(cloned_file);
687+
se.mount().unwrap();
688+
}
646689
}
647690

648691
#[cfg(feature = "async_io")]

0 commit comments

Comments
 (0)