Skip to content

Commit 6e40753

Browse files
eryugeyjiangliu
authored andcommitted
linuxsession: support mount in given mount namespace
So we could mount fuse in another mount namespace. Signed-off-by: Eryu Guan <[email protected]>
1 parent ecbd517 commit 6e40753

File tree

1 file changed

+48
-7
lines changed

1 file changed

+48
-7
lines changed

src/transport/fusedev/linux_session.rs

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub struct FuseSession {
5353
readonly: bool,
5454
wakers: Mutex<Vec<Arc<Waker>>>,
5555
auto_unmount: bool,
56+
target_mntns: Option<libc::pid_t>,
5657
}
5758

5859
impl FuseSession {
@@ -91,9 +92,16 @@ impl FuseSession {
9192
readonly,
9293
wakers: Mutex::new(Vec::new()),
9394
auto_unmount,
95+
target_mntns: None,
9496
})
9597
}
9698

99+
/// Set the target pid of mount namespace of the fuse session mount, the fuse will be mounted
100+
/// under the given mnt ns.
101+
pub fn set_target_mntns(&mut self, pid: Option<libc::pid_t>) {
102+
self.target_mntns = pid;
103+
}
104+
97105
/// Mount the fuse mountpoint, building connection with the in kernel fuse driver.
98106
pub fn mount(&mut self) -> Result<()> {
99107
let mut flags = MsFlags::MS_NOSUID | MsFlags::MS_NODEV | MsFlags::MS_NOATIME;
@@ -106,6 +114,7 @@ impl FuseSession {
106114
&self.subtype,
107115
flags,
108116
self.auto_unmount,
117+
self.target_mntns,
109118
)?;
110119

111120
fcntl(file.as_raw_fd(), FcntlArg::F_SETFL(OFlag::O_NONBLOCK))
@@ -346,6 +355,7 @@ fn fuse_kern_mount(
346355
subtype: &str,
347356
flags: MsFlags,
348357
auto_unmount: bool,
358+
target_mntns: Option<libc::pid_t>,
349359
) -> Result<(File, Option<UnixStream>)> {
350360
let file = OpenOptions::new()
351361
.create(false)
@@ -379,8 +389,20 @@ fn fuse_kern_mount(
379389
file.as_raw_fd(),
380390
);
381391
}
382-
if auto_unmount {
383-
fuse_fusermount_mount(mountpoint, fsname, subtype, opts, flags, auto_unmount)
392+
393+
// mount in another mntns requires mounting with fusermount3, which is a new process, as
394+
// multithreaded program is not allowed to join to another mntns, and the process running fuse
395+
// session might be multithreaded.
396+
if auto_unmount || target_mntns.is_some() {
397+
fuse_fusermount_mount(
398+
mountpoint,
399+
fsname,
400+
subtype,
401+
opts,
402+
flags,
403+
auto_unmount,
404+
target_mntns,
405+
)
384406
} else {
385407
match mount(
386408
Some(fsname),
@@ -390,9 +412,15 @@ fn fuse_kern_mount(
390412
Some(opts.deref()),
391413
) {
392414
Ok(()) => Ok((file, None)),
393-
Err(nix::errno::Errno::EPERM) => {
394-
fuse_fusermount_mount(mountpoint, fsname, subtype, opts, flags, auto_unmount)
395-
}
415+
Err(nix::errno::Errno::EPERM) => fuse_fusermount_mount(
416+
mountpoint,
417+
fsname,
418+
subtype,
419+
opts,
420+
flags,
421+
auto_unmount,
422+
target_mntns,
423+
),
396424
Err(e) => Err(SessionFailure(format!(
397425
"failed to mount {mountpoint:?}: {e}"
398426
))),
@@ -429,6 +457,7 @@ fn fuse_fusermount_mount(
429457
opts: String,
430458
flags: MsFlags,
431459
auto_unmount: bool,
460+
target_mntns: Option<libc::pid_t>,
432461
) -> Result<(File, Option<UnixStream>)> {
433462
let mut opts = vec![format!("fsname={fsname}"), opts, msflags_to_string(flags)];
434463
if !subtype.is_empty() {
@@ -448,15 +477,27 @@ fn fuse_fusermount_mount(
448477
nix::fcntl::fcntl(send.as_raw_fd(), FcntlArg::F_SETFD(FdFlag::empty()))
449478
.map_err(|e| SessionFailure(format!("Failed to remove close-on-exec flag: {e}")))?;
450479

451-
let mut proc = std::process::Command::new("fusermount3")
480+
let mut cmd = match target_mntns {
481+
Some(pid) => {
482+
let mut c = std::process::Command::new("nsenter");
483+
c.arg("-t")
484+
.arg(format!("{}", pid))
485+
.arg("-m")
486+
.arg("fusermount3");
487+
c
488+
}
489+
None => std::process::Command::new("fusermount3"),
490+
};
491+
// Old version of fusermount doesn't support long --options, yet.
492+
let mut proc = cmd
452493
.env("_FUSE_COMMFD", format!("{}", send.as_raw_fd()))
453-
// Old version of fusermount doesn't support long --options, yet.
454494
.arg("-o")
455495
.arg(opts)
456496
.arg("--")
457497
.arg(mountpoint)
458498
.spawn()
459499
.map_err(IoError)?;
500+
460501
if auto_unmount {
461502
std::thread::spawn(move || {
462503
let _ = proc.wait();

0 commit comments

Comments
 (0)