mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-22 11:13:22 +00:00
ospp project (feature) add namespace overlayfs cgroup (#949)
## 开发进展: ## namespace - pid_namespace 基本实现,基于pid_struct等数据结构实现隔离 - mnt_namespace 基本实现,挂载点的隔离通过不同的挂载树来实现 - usernamespace 作为支持性的namespace,目前受限实现全局静态 ## overlayfs - 实现若干个文件系统的叠加,在mount中传入多个路径作为多个fs的mount路径以及最后merge层的fs路径 - copy-up机制的,除最上层外其他层为只读层,满足写时拷贝,需要修改的时候copy到上层修改 - whiteout特殊文件,用于标记在下层需要被删除的文件用来掩盖需要删除的文件 ## cgroups - 目前cgroups还处于框架阶段,之后具体实现具体的内存、CPU等子系统
This commit is contained in:
206
kernel/src/namespaces/mnt_namespace.rs
Normal file
206
kernel/src/namespaces/mnt_namespace.rs
Normal file
@ -0,0 +1,206 @@
|
||||
#![allow(dead_code, unused_variables, unused_imports)]
|
||||
use core::sync::atomic::AtomicU64;
|
||||
use core::sync::atomic::Ordering;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::ToString;
|
||||
|
||||
use alloc::string::String;
|
||||
|
||||
use alloc::sync::Arc;
|
||||
use system_error::SystemError;
|
||||
|
||||
use super::namespace::Namespace;
|
||||
use super::namespace::NsOperations;
|
||||
use super::ucount::Ucount::MntNamespaces;
|
||||
use super::{namespace::NsCommon, ucount::UCounts, user_namespace::UserNamespace};
|
||||
use crate::container_of;
|
||||
use crate::filesystem::vfs::mount::MountFSInode;
|
||||
use crate::filesystem::vfs::IndexNode;
|
||||
use crate::filesystem::vfs::InodeId;
|
||||
use crate::filesystem::vfs::MountFS;
|
||||
use crate::filesystem::vfs::ROOT_INODE;
|
||||
use crate::libs::rbtree::RBTree;
|
||||
use crate::libs::wait_queue::WaitQueue;
|
||||
use crate::process::fork::CloneFlags;
|
||||
use crate::process::ProcessManager;
|
||||
use crate::syscall::Syscall;
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub struct MntNamespace {
|
||||
/// namespace 共有的部分
|
||||
ns_common: Arc<NsCommon>,
|
||||
/// 关联的用户名字空间
|
||||
user_ns: Arc<UserNamespace>,
|
||||
/// 资源计数器
|
||||
ucounts: Arc<UCounts>,
|
||||
/// 根文件系统
|
||||
root: Option<Arc<MountFS>>,
|
||||
/// 红黑树用于挂载所有挂载点
|
||||
mounts: RBTree<InodeId, MountFSInode>,
|
||||
/// 等待队列
|
||||
poll: WaitQueue,
|
||||
/// 挂载序列号
|
||||
seq: AtomicU64,
|
||||
/// 挂载点的数量
|
||||
nr_mounts: u32,
|
||||
/// 待处理的挂载点
|
||||
pending_mounts: u32,
|
||||
}
|
||||
|
||||
impl Default for MntNamespace {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct MntNsOperations {
|
||||
name: String,
|
||||
clone_flags: CloneFlags,
|
||||
}
|
||||
|
||||
/// 使用该结构体的时候加spinlock
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FsStruct {
|
||||
umask: u32, //文件权限掩码
|
||||
pub root: Arc<dyn IndexNode>,
|
||||
pub pwd: Arc<dyn IndexNode>,
|
||||
}
|
||||
impl Default for FsStruct {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl FsStruct {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
umask: 0o22,
|
||||
root: ROOT_INODE(),
|
||||
pwd: ROOT_INODE(),
|
||||
}
|
||||
}
|
||||
pub fn set_root(&mut self, inode: Arc<dyn IndexNode>) {
|
||||
self.root = inode;
|
||||
}
|
||||
pub fn set_pwd(&mut self, inode: Arc<dyn IndexNode>) {
|
||||
self.pwd = inode;
|
||||
}
|
||||
}
|
||||
|
||||
impl Namespace for MntNamespace {
|
||||
fn ns_common_to_ns(ns_common: Arc<NsCommon>) -> Arc<Self> {
|
||||
let ns_common_ptr = Arc::as_ptr(&ns_common);
|
||||
container_of!(ns_common_ptr, MntNamespace, ns_common)
|
||||
}
|
||||
}
|
||||
|
||||
impl MntNsOperations {
|
||||
pub fn new(name: String) -> Self {
|
||||
Self {
|
||||
name,
|
||||
clone_flags: CloneFlags::CLONE_NEWNS,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NsOperations for MntNsOperations {
|
||||
fn get(&self, pid: crate::process::Pid) -> Option<Arc<NsCommon>> {
|
||||
let pcb = ProcessManager::find(pid);
|
||||
pcb.map(|pcb| pcb.get_nsproxy().read().mnt_namespace.ns_common.clone())
|
||||
}
|
||||
// 不存在这个方法
|
||||
fn get_parent(&self, _ns_common: Arc<NsCommon>) -> Result<Arc<NsCommon>, SystemError> {
|
||||
unreachable!()
|
||||
}
|
||||
fn install(
|
||||
&self,
|
||||
nsset: &mut super::NsSet,
|
||||
ns_common: Arc<NsCommon>,
|
||||
) -> Result<(), SystemError> {
|
||||
let nsproxy = &mut nsset.nsproxy;
|
||||
let mnt_ns = MntNamespace::ns_common_to_ns(ns_common);
|
||||
if mnt_ns.is_anon_ns() {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
nsproxy.mnt_namespace = mnt_ns;
|
||||
|
||||
nsset.fs.lock().set_pwd(ROOT_INODE());
|
||||
nsset.fs.lock().set_root(ROOT_INODE());
|
||||
Ok(())
|
||||
}
|
||||
fn owner(&self, ns_common: Arc<NsCommon>) -> Arc<UserNamespace> {
|
||||
let mnt_ns = MntNamespace::ns_common_to_ns(ns_common);
|
||||
mnt_ns.user_ns.clone()
|
||||
}
|
||||
fn put(&self, ns_common: Arc<NsCommon>) {
|
||||
let pid_ns = MntNamespace::ns_common_to_ns(ns_common);
|
||||
}
|
||||
}
|
||||
impl MntNamespace {
|
||||
pub fn new() -> Self {
|
||||
let ns_common = Arc::new(NsCommon::new(Box::new(MntNsOperations::new(
|
||||
"mnt".to_string(),
|
||||
))));
|
||||
|
||||
Self {
|
||||
ns_common,
|
||||
user_ns: Arc::new(UserNamespace::new()),
|
||||
ucounts: Arc::new(UCounts::new()),
|
||||
root: None,
|
||||
mounts: RBTree::new(),
|
||||
poll: WaitQueue::default(),
|
||||
seq: AtomicU64::new(0),
|
||||
nr_mounts: 0,
|
||||
pending_mounts: 0,
|
||||
}
|
||||
}
|
||||
/// anon 用来判断是否是匿名的.匿名函数的问题还需要考虑
|
||||
pub fn create_mnt_namespace(
|
||||
&self,
|
||||
user_ns: Arc<UserNamespace>,
|
||||
anon: bool,
|
||||
) -> Result<Self, SystemError> {
|
||||
let ucounts = self.inc_mnt_namespace(user_ns.clone())?;
|
||||
if ucounts.is_none() {
|
||||
return Err(SystemError::ENOSPC);
|
||||
}
|
||||
let ucounts = ucounts.unwrap();
|
||||
let ns_common = Arc::new(NsCommon::new(Box::new(MntNsOperations::new(
|
||||
"mnt".to_string(),
|
||||
))));
|
||||
let seq = AtomicU64::new(0);
|
||||
if !anon {
|
||||
seq.fetch_add(1, core::sync::atomic::Ordering::SeqCst);
|
||||
}
|
||||
Ok(Self {
|
||||
ns_common,
|
||||
user_ns,
|
||||
ucounts,
|
||||
root: None,
|
||||
mounts: RBTree::new(),
|
||||
poll: WaitQueue::default(),
|
||||
seq,
|
||||
nr_mounts: 0,
|
||||
pending_mounts: 0,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn inc_mnt_namespace(
|
||||
&self,
|
||||
user_ns: Arc<UserNamespace>,
|
||||
) -> Result<Option<Arc<UCounts>>, SystemError> {
|
||||
Ok(self
|
||||
.ucounts
|
||||
.inc_ucounts(user_ns, Syscall::geteuid()?, MntNamespaces))
|
||||
}
|
||||
|
||||
pub fn dec_mnt_namespace(&self, uc: Arc<UCounts>) {
|
||||
UCounts::dec_ucount(uc, super::ucount::Ucount::MntNamespaces)
|
||||
}
|
||||
//判断是不是匿名空间
|
||||
pub fn is_anon_ns(&self) -> bool {
|
||||
self.seq.load(Ordering::SeqCst) == 0
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user