use core::{any::Any, fmt::Debug, hash::Hash, ops::Deref}; use alloc::{ string::String, sync::{Arc, Weak}, }; use intertrait::CastFromSync; use crate::{ filesystem::{ kernfs::KernFSInode, sysfs::{sysfs_instance, Attribute, AttributeGroup, SysFSOps, SysFSOpsSupport}, }, kerror, libs::{ casting::DowncastArc, rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, }, syscall::SystemError, }; use super::kset::KSet; pub trait KObject: Any + Send + Sync + Debug + CastFromSync { fn as_any_ref(&self) -> &dyn core::any::Any; /// 设置当前kobject对应的sysfs inode(类型为KernFSInode) fn set_inode(&self, inode: Option>); /// 获取当前kobject对应的sysfs inode(类型为KernFSInode) fn inode(&self) -> Option>; fn parent(&self) -> Option>; /// 设置当前kobject的parent kobject(不一定与kset相同) fn set_parent(&self, parent: Option>); /// 当前kobject属于哪个kset fn kset(&self) -> Option>; /// 设置当前kobject所属的kset fn set_kset(&self, kset: Option>); fn kobj_type(&self) -> Option<&'static dyn KObjType>; fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>); fn name(&self) -> String; fn set_name(&self, name: String); fn kobj_state(&self) -> RwLockReadGuard; fn kobj_state_mut(&self) -> RwLockWriteGuard; fn set_kobj_state(&self, state: KObjectState); } impl dyn KObject { /// 更新kobject的状态 pub fn update_kobj_state(&self, insert: Option, remove: Option) { let insert = insert.unwrap_or(KObjectState::empty()); let remove = remove.unwrap_or(KObjectState::empty()); let mut state = self.kobj_state_mut(); *state = (*state | insert) & !remove; } } impl DowncastArc for dyn KObject { fn as_any_arc(self: Arc) -> Arc { self } } pub trait KObjType: Debug + Send + Sync { fn release(&self, _kobj: Arc) {} fn sysfs_ops(&self) -> Option<&dyn SysFSOps>; fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]>; } bitflags! { pub struct KObjectState: u32 { const IN_SYSFS = 1 << 0; const ADD_UEVENT_SENT = 1 << 1; const REMOVE_UEVENT_SENT = 1 << 2; const INITIALIZED = 1 << 3; } } #[derive(Debug)] pub struct LockedKObjectState(RwLock); impl LockedKObjectState { pub fn new(state: Option) -> LockedKObjectState { let state = state.unwrap_or(KObjectState::empty()); LockedKObjectState(RwLock::new(state)) } } impl Deref for LockedKObjectState { type Target = RwLock; fn deref(&self) -> &Self::Target { &self.0 } } pub trait KObjectAttribute: Attribute { fn support(&self) -> SysFSOpsSupport; fn show(&self, kobj: &dyn KObject, buf: &mut [u8]) -> Result; fn store(&self, kobj: &dyn KObject, buf: &[u8]) -> Result; } #[derive(Debug)] pub struct KObjectSysFSOps; impl SysFSOps for KObjectSysFSOps { fn support(&self, attr: &dyn Attribute) -> SysFSOpsSupport { return attr.support(); } fn show( &self, kobj: Arc, attr: &dyn Attribute, buf: &mut [u8], ) -> Result { let r = attr.show(kobj, buf).map_err(|e| { if e == SystemError::EOPNOTSUPP_OR_ENOTSUP { SystemError::EIO } else { e } }); return r; } fn store( &self, kobj: Arc, attr: &dyn Attribute, buf: &[u8], ) -> Result { let r = attr.store(kobj, buf).map_err(|e| { if e == SystemError::EOPNOTSUPP_OR_ENOTSUP { SystemError::EIO } else { e } }); return r; } } #[derive(Debug)] pub struct KObjectManager; impl KObjectManager { #[allow(dead_code)] pub fn init_and_add_kobj( kobj: Arc, join_kset: Option>, ) -> Result<(), SystemError> { Self::kobj_init(&kobj); Self::add_kobj(kobj, join_kset) } #[allow(dead_code)] pub fn kobj_init(kobj: &Arc) { kobj.set_kobj_type(Some(&DynamicKObjKType)); } pub fn add_kobj( kobj: Arc, join_kset: Option>, ) -> Result<(), SystemError> { if join_kset.is_some() { let kset = join_kset.unwrap(); kset.join(&kobj); // 如果kobject没有parent,那么就将这个kset作为parent if kobj.parent().is_none() { kobj.set_parent(Some(Arc::downgrade(&(kset as Arc)))); } } let r = Self::create_dir(kobj.clone()); if let Err(e) = r { // https://opengrok.ringotek.cn/xref/linux-6.1.9/lib/kobject.c?r=&mo=10426&fi=394#224 if let Some(kset) = kobj.kset() { kset.leave(&kobj); } kobj.set_parent(None); if e == SystemError::EEXIST { kerror!("KObjectManager::add_kobj() failed with error: {e:?}, kobj:{kobj:?}"); } return Err(e); } kobj.update_kobj_state(Some(KObjectState::IN_SYSFS), None); return Ok(()); } fn create_dir(kobj: Arc) -> Result<(), SystemError> { // create dir in sysfs sysfs_instance().create_dir(kobj.clone())?; // create default attributes in sysfs if let Some(ktype) = kobj.kobj_type() { let groups = ktype.attribute_groups(); if let Some(groups) = groups { let r = sysfs_instance().create_groups(&kobj, groups); if let Err(e) = r { sysfs_instance().remove_dir(&kobj); return Err(e); } } } return Ok(()); } } /// 动态创建的kobject对象的ktype #[derive(Debug)] pub struct DynamicKObjKType; impl KObjType for DynamicKObjKType { fn release(&self, kobj: Arc) { kdebug!("DynamicKObjKType::release() kobj:{:?}", kobj.name()); } fn sysfs_ops(&self) -> Option<&dyn SysFSOps> { Some(&KObjectSysFSOps) } fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { None } }