Support MS_PRIVATE flag for mount
This commit is contained in:
parent
2b18c893a8
commit
07d2d1db02
|
|
@ -58,7 +58,6 @@ Partially supported mount flags:
|
|||
Unsupported mount flags:
|
||||
* `MS_REMOUNT`
|
||||
* `MS_SHARED`
|
||||
* `MS_PRIVATE`
|
||||
* `MS_SLAVE`
|
||||
* `MS_UNBINDABLE`
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
use core::time::Duration;
|
||||
|
||||
use inherit_methods_macro::inherit_methods;
|
||||
pub use mount::Mount;
|
||||
pub use mount::{Mount, MountPropType};
|
||||
pub use mount_namespace::MountNamespace;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -321,6 +321,28 @@ impl Path {
|
|||
self.mount.graft_mount_tree(dst_path)
|
||||
}
|
||||
|
||||
/// Sets the propagation type of the mount of this `Path`.
|
||||
pub fn set_mount_propagation(
|
||||
&self,
|
||||
prop: MountPropType,
|
||||
recursive: bool,
|
||||
ctx: &Context,
|
||||
) -> Result<()> {
|
||||
if !self.is_mount_root() {
|
||||
return_errno_with_message!(Errno::EINVAL, "the path is not a mount root");
|
||||
};
|
||||
|
||||
let current_ns_proxy = ctx.thread_local.borrow_ns_proxy();
|
||||
let current_mnt_ns = current_ns_proxy.unwrap().mnt_ns();
|
||||
if !current_mnt_ns.owns(&self.mount) {
|
||||
return_errno_with_message!(Errno::EINVAL, "the path is not in this mount namespace");
|
||||
}
|
||||
|
||||
self.mount.set_propagation(prop, recursive);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Creates a `Path` by making an inode of the `type_` with the `mode`.
|
||||
pub fn mknod(&self, name: &str, mode: InodeMode, type_: MknodType) -> Result<Self> {
|
||||
let inner = self.dentry.mknod(name, mode, type_)?;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,24 @@ use crate::{
|
|||
prelude::*,
|
||||
};
|
||||
|
||||
/// Mount propagation types.
|
||||
///
|
||||
/// This type defines how mount and unmount events are propagated
|
||||
/// from this mount to other mounts.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum MountPropType {
|
||||
/// A private type is the default mount type. Mount and unmount events
|
||||
/// do not propagate to or from the private mounts.
|
||||
Private,
|
||||
// TODO: Implement other propagation types.
|
||||
}
|
||||
|
||||
impl Default for MountPropType {
|
||||
fn default() -> Self {
|
||||
Self::Private
|
||||
}
|
||||
}
|
||||
|
||||
/// A `Mount` represents a mounted filesystem instance in the VFS.
|
||||
///
|
||||
/// Each `Mount` can be viewed as a node in the mount tree, maintaining
|
||||
|
|
@ -32,6 +50,8 @@ pub struct Mount {
|
|||
pub(super) children: RwLock<HashMap<DentryKey, Arc<Self>>>,
|
||||
/// The associated mount namespace.
|
||||
mnt_ns: Weak<MountNamespace>,
|
||||
/// Propagation type of this mount (e.g., private, shared).
|
||||
propagation: RwLock<MountPropType>,
|
||||
/// Reference to self.
|
||||
this: Weak<Self>,
|
||||
}
|
||||
|
|
@ -69,6 +89,7 @@ impl Mount {
|
|||
mountpoint: RwLock::new(None),
|
||||
parent: RwLock::new(parent_mount),
|
||||
children: RwLock::new(HashMap::new()),
|
||||
propagation: RwLock::new(MountPropType::default()),
|
||||
fs,
|
||||
mnt_ns,
|
||||
this: weak_self.clone(),
|
||||
|
|
@ -135,6 +156,7 @@ impl Mount {
|
|||
mountpoint: RwLock::new(None),
|
||||
parent: RwLock::new(None),
|
||||
children: RwLock::new(HashMap::new()),
|
||||
propagation: RwLock::new(MountPropType::default()),
|
||||
fs: self.fs.clone(),
|
||||
mnt_ns: new_ns.cloned().unwrap_or_else(|| self.mnt_ns.clone()),
|
||||
this: weak_self.clone(),
|
||||
|
|
@ -190,6 +212,20 @@ impl Mount {
|
|||
new_root_mount
|
||||
}
|
||||
|
||||
/// Sets the propagation type of this mount.
|
||||
pub(super) fn set_propagation(&self, prop: MountPropType, recursive: bool) {
|
||||
*self.propagation.write() = prop;
|
||||
if !recursive {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut worklist: VecDeque<Arc<Mount>> = self.children.read().values().cloned().collect();
|
||||
while let Some(mount) = worklist.pop_front() {
|
||||
*mount.propagation.write() = prop;
|
||||
worklist.extend(mount.children.read().values().cloned());
|
||||
}
|
||||
}
|
||||
|
||||
/// Detaches the mount node from the parent mount node.
|
||||
pub(super) fn detach_from_parent(&self) {
|
||||
if let Some(parent) = self.parent() {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use super::SyscallReturn;
|
|||
use crate::{
|
||||
fs::{
|
||||
fs_resolver::{FsPath, AT_FDCWD},
|
||||
path::Path,
|
||||
path::{MountPropType, Path},
|
||||
registry::FsProperties,
|
||||
utils::{FileSystem, InodeType},
|
||||
},
|
||||
|
|
@ -57,12 +57,8 @@ pub fn sys_mount(
|
|||
mount_flags.contains(MountFlags::MS_REC),
|
||||
ctx,
|
||||
)?;
|
||||
} else if mount_flags.contains(MountFlags::MS_SHARED)
|
||||
| mount_flags.contains(MountFlags::MS_PRIVATE)
|
||||
| mount_flags.contains(MountFlags::MS_SLAVE)
|
||||
| mount_flags.contains(MountFlags::MS_UNBINDABLE)
|
||||
{
|
||||
do_change_type()?;
|
||||
} else if mount_flags.intersects(MS_PROPAGATION) {
|
||||
do_change_type(dst_path, mount_flags, ctx)?;
|
||||
} else if mount_flags.contains(MountFlags::MS_MOVE) {
|
||||
do_move_mount_old(devname, dst_path, ctx)?;
|
||||
} else {
|
||||
|
|
@ -106,8 +102,37 @@ fn do_bind_mount(src_name: CString, dst_path: Path, recursive: bool, ctx: &Conte
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn do_change_type() -> Result<()> {
|
||||
return_errno_with_message!(Errno::EINVAL, "do_change_type is not supported");
|
||||
// All valid propagation flags.
|
||||
const MS_PROPAGATION: MountFlags = MountFlags::MS_SHARED
|
||||
.union(MountFlags::MS_PRIVATE)
|
||||
.union(MountFlags::MS_SLAVE)
|
||||
.union(MountFlags::MS_UNBINDABLE);
|
||||
|
||||
fn do_change_type(target_path: Path, flags: MountFlags, ctx: &Context) -> Result<()> {
|
||||
// All flags that are allowed during a propagation change.
|
||||
const ALLOWED_FLAGS: MountFlags = MS_PROPAGATION
|
||||
.union(MountFlags::MS_REC)
|
||||
.union(MountFlags::MS_SILENT);
|
||||
|
||||
if !(flags & !ALLOWED_FLAGS).is_empty() {
|
||||
return_errno_with_message!(Errno::EINVAL, "the mount propagation flags are unsupported");
|
||||
}
|
||||
|
||||
let propagation_flags = flags & MS_PROPAGATION;
|
||||
if propagation_flags.bits().count_ones() > 1 {
|
||||
return_errno_with_message!(
|
||||
Errno::EINVAL,
|
||||
"mount flags includes more than one of MS_SHARED, MS_PRIVATE, MS_SLAVE, or MS_UNBINDABLE"
|
||||
);
|
||||
}
|
||||
|
||||
if flags.contains(MountFlags::MS_PRIVATE) {
|
||||
let recursive = flags.contains(MountFlags::MS_REC);
|
||||
target_path.set_mount_propagation(MountPropType::Private, recursive, ctx)?;
|
||||
Ok(())
|
||||
} else {
|
||||
return_errno_with_message!(Errno::EINVAL, "the mount propagation type is unsupported");
|
||||
}
|
||||
}
|
||||
|
||||
/// Move a mount from src location to dst location.
|
||||
|
|
|
|||
Loading…
Reference in New Issue