@@ -53,6 +53,7 @@ pub struct FuseSession {
53
53
readonly : bool ,
54
54
wakers : Mutex < Vec < Arc < Waker > > > ,
55
55
auto_unmount : bool ,
56
+ target_mntns : Option < libc:: pid_t > ,
56
57
}
57
58
58
59
impl FuseSession {
@@ -91,9 +92,16 @@ impl FuseSession {
91
92
readonly,
92
93
wakers : Mutex :: new ( Vec :: new ( ) ) ,
93
94
auto_unmount,
95
+ target_mntns : None ,
94
96
} )
95
97
}
96
98
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
+
97
105
/// Mount the fuse mountpoint, building connection with the in kernel fuse driver.
98
106
pub fn mount ( & mut self ) -> Result < ( ) > {
99
107
let mut flags = MsFlags :: MS_NOSUID | MsFlags :: MS_NODEV | MsFlags :: MS_NOATIME ;
@@ -106,6 +114,7 @@ impl FuseSession {
106
114
& self . subtype ,
107
115
flags,
108
116
self . auto_unmount ,
117
+ self . target_mntns ,
109
118
) ?;
110
119
111
120
fcntl ( file. as_raw_fd ( ) , FcntlArg :: F_SETFL ( OFlag :: O_NONBLOCK ) )
@@ -346,6 +355,7 @@ fn fuse_kern_mount(
346
355
subtype : & str ,
347
356
flags : MsFlags ,
348
357
auto_unmount : bool ,
358
+ target_mntns : Option < libc:: pid_t > ,
349
359
) -> Result < ( File , Option < UnixStream > ) > {
350
360
let file = OpenOptions :: new ( )
351
361
. create ( false )
@@ -379,8 +389,20 @@ fn fuse_kern_mount(
379
389
file. as_raw_fd( ) ,
380
390
) ;
381
391
}
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
+ )
384
406
} else {
385
407
match mount (
386
408
Some ( fsname) ,
@@ -390,9 +412,15 @@ fn fuse_kern_mount(
390
412
Some ( opts. deref ( ) ) ,
391
413
) {
392
414
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
+ ) ,
396
424
Err ( e) => Err ( SessionFailure ( format ! (
397
425
"failed to mount {mountpoint:?}: {e}"
398
426
) ) ) ,
@@ -429,6 +457,7 @@ fn fuse_fusermount_mount(
429
457
opts : String ,
430
458
flags : MsFlags ,
431
459
auto_unmount : bool ,
460
+ target_mntns : Option < libc:: pid_t > ,
432
461
) -> Result < ( File , Option < UnixStream > ) > {
433
462
let mut opts = vec ! [ format!( "fsname={fsname}" ) , opts, msflags_to_string( flags) ] ;
434
463
if !subtype. is_empty ( ) {
@@ -448,15 +477,27 @@ fn fuse_fusermount_mount(
448
477
nix:: fcntl:: fcntl ( send. as_raw_fd ( ) , FcntlArg :: F_SETFD ( FdFlag :: empty ( ) ) )
449
478
. map_err ( |e| SessionFailure ( format ! ( "Failed to remove close-on-exec flag: {e}" ) ) ) ?;
450
479
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
452
493
. env ( "_FUSE_COMMFD" , format ! ( "{}" , send. as_raw_fd( ) ) )
453
- // Old version of fusermount doesn't support long --options, yet.
454
494
. arg ( "-o" )
455
495
. arg ( opts)
456
496
. arg ( "--" )
457
497
. arg ( mountpoint)
458
498
. spawn ( )
459
499
. map_err ( IoError ) ?;
500
+
460
501
if auto_unmount {
461
502
std:: thread:: spawn ( move || {
462
503
let _ = proc. wait ( ) ;
0 commit comments