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:
codeironman
2024-10-31 00:50:34 +08:00
committed by GitHub
parent 84c528f53d
commit f5b2038871
43 changed files with 2279 additions and 56 deletions

View 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
}
}