123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 |
- use core::{any::Any, fmt::Debug, hash::Hash, ops::Deref};
- use alloc::{
- string::String,
- sync::{Arc, Weak},
- };
- use driver_base_macros::get_weak_or_clear;
- use intertrait::CastFromSync;
- use log::{debug, error};
- use crate::{
- filesystem::{
- kernfs::KernFSInode,
- sysfs::{sysfs_instance, Attribute, AttributeGroup, SysFSOps, SysFSOpsSupport},
- },
- libs::{
- casting::DowncastArc,
- rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
- },
- };
- use system_error::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<Arc<KernFSInode>>);
- /// 获取当前kobject对应的sysfs inode(类型为KernFSInode)
- fn inode(&self) -> Option<Arc<KernFSInode>>;
- fn parent(&self) -> Option<Weak<dyn KObject>>;
- /// 设置当前kobject的parent kobject(不一定与kset相同)
- fn set_parent(&self, parent: Option<Weak<dyn KObject>>);
- /// 当前kobject属于哪个kset
- fn kset(&self) -> Option<Arc<KSet>>;
- /// 设置当前kobject所属的kset
- fn set_kset(&self, kset: Option<Arc<KSet>>);
- 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<KObjectState>;
- fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState>;
- fn set_kobj_state(&self, state: KObjectState);
- }
- impl dyn KObject {
- /// 更新kobject的状态
- pub fn update_kobj_state(&self, insert: Option<KObjectState>, remove: Option<KObjectState>) {
- 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<Self>) -> Arc<dyn Any> {
- self
- }
- }
- /// kobject的公共数据
- #[derive(Debug, Default)]
- pub struct KObjectCommonData {
- pub kern_inode: Option<Arc<KernFSInode>>,
- pub parent: Option<Weak<dyn KObject>>,
- pub kset: Option<Arc<KSet>>,
- pub kobj_type: Option<&'static dyn KObjType>,
- }
- impl KObjectCommonData {
- pub fn get_parent_or_clear_weak(&mut self) -> Option<Weak<dyn KObject>> {
- get_weak_or_clear!(self.parent)
- }
- }
- pub trait KObjType: Debug + Send + Sync {
- /// 当指定的kobject被释放时,设备驱动模型会调用此方法
- fn release(&self, _kobj: Arc<dyn KObject>) {}
- 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;
- const UEVENT_SUPPRESS = 1 << 4;
- }
- }
- #[derive(Debug)]
- pub struct LockedKObjectState(RwLock<KObjectState>);
- impl LockedKObjectState {
- pub fn new(state: Option<KObjectState>) -> LockedKObjectState {
- let state = state.unwrap_or(KObjectState::empty());
- LockedKObjectState(RwLock::new(state))
- }
- }
- impl Deref for LockedKObjectState {
- type Target = RwLock<KObjectState>;
- fn deref(&self) -> &Self::Target {
- &self.0
- }
- }
- impl Default for LockedKObjectState {
- fn default() -> Self {
- LockedKObjectState::new(None)
- }
- }
- #[derive(Debug)]
- pub struct KObjectSysFSOps;
- impl SysFSOps for KObjectSysFSOps {
- fn support(&self, attr: &dyn Attribute) -> SysFSOpsSupport {
- return attr.support();
- }
- fn show(
- &self,
- kobj: Arc<dyn KObject>,
- attr: &dyn Attribute,
- buf: &mut [u8],
- ) -> Result<usize, SystemError> {
- let r = attr.show(kobj, buf).map_err(|e| {
- if e == SystemError::ENOSYS {
- SystemError::EIO
- } else {
- e
- }
- });
- return r;
- }
- fn store(
- &self,
- kobj: Arc<dyn KObject>,
- attr: &dyn Attribute,
- buf: &[u8],
- ) -> Result<usize, SystemError> {
- let r = attr.store(kobj, buf).map_err(|e| {
- if e == SystemError::ENOSYS {
- SystemError::EIO
- } else {
- e
- }
- });
- return r;
- }
- }
- #[derive(Debug)]
- pub struct KObjectManager;
- impl KObjectManager {
- pub fn init_and_add_kobj(
- kobj: Arc<dyn KObject>,
- join_kset: Option<Arc<KSet>>,
- kobj_type: Option<&'static dyn KObjType>,
- ) -> Result<(), SystemError> {
- Self::kobj_init(&kobj, kobj_type);
- Self::add_kobj(kobj, join_kset)
- }
- pub fn kobj_init(kobj: &Arc<dyn KObject>, kobj_type: Option<&'static dyn KObjType>) {
- kobj.set_kobj_type(kobj_type);
- }
- pub fn add_kobj(
- kobj: Arc<dyn KObject>,
- join_kset: Option<Arc<KSet>>,
- ) -> Result<(), SystemError> {
- if let Some(kset) = join_kset {
- kset.join(&kobj);
- // 如果kobject没有parent,那么就将这个kset作为parent
- if kobj.parent().is_none() {
- kobj.set_parent(Some(Arc::downgrade(&(kset as Arc<dyn KObject>))));
- }
- }
- let r = Self::create_dir(kobj.clone());
- if let Err(e) = r {
- // https://code.dragonos.org.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 {
- error!("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<dyn KObject>) -> 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(());
- }
- /// 从sysfs中移除kobject
- pub fn remove_kobj(kobj: Arc<dyn KObject>) {
- let ktype = kobj.kobj_type();
- if let Some(ktype) = ktype {
- if let Some(groups) = ktype.attribute_groups() {
- sysfs_instance().remove_groups(&kobj, groups);
- }
- }
- // todo: 发送uevent: KOBJ_REMOVE
- // kobject_uevent();
- sysfs_instance().remove_dir(&kobj);
- kobj.update_kobj_state(None, Some(KObjectState::IN_SYSFS));
- let kset = kobj.kset();
- if let Some(kset) = kset {
- kset.leave(&kobj);
- }
- kobj.set_parent(None);
- }
- fn get_kobj_path_length(kobj: &Arc<dyn KObject>) -> usize {
- log::info!("get_kobj_path_length() kobj:{:?}", kobj.name());
- let mut parent = kobj.parent().unwrap().upgrade().unwrap();
- /* walk up the ancestors until we hit the one pointing to the
- * root.
- * Add 1 to strlen for leading '/' of each level.
- */
- let mut length = 0; // 确保 length 被正确初始化
- let mut iteration_count = 0; // 用于记录迭代次数
- const MAX_ITERATIONS: usize = 10; // 最大迭代次数
- loop {
- log::info!(
- "Iteration {}: parent.name():{:?}",
- iteration_count,
- parent.name()
- );
- length += parent.name().len() + 1;
- if let Some(weak_parent) = parent.parent() {
- if let Some(upgraded_parent) = weak_parent.upgrade() {
- parent = upgraded_parent;
- } else {
- log::error!("Failed to upgrade weak reference to parent");
- break;
- }
- } else {
- log::error!("Parent has no parent");
- break;
- }
- iteration_count += 1;
- if iteration_count >= MAX_ITERATIONS {
- log::error!("Reached maximum iteration count, breaking to avoid infinite loop");
- break;
- }
- }
- return length;
- }
- /*
- static void fill_kobj_path(struct kobject *kobj, char *path, int length)
- {
- struct kobject *parent;
- --length;
- for (parent = kobj; parent; parent = parent->parent) {
- int cur = strlen(kobject_name(parent));
- /* back up enough to print this name with '/' */
- length -= cur;
- memcpy(path + length, kobject_name(parent), cur);
- *(path + --length) = '/';
- }
- pr_debug("kobject: '%s' (%p): %s: path = '%s'\n", kobject_name(kobj),
- kobj, __func__, path);
- }
- */
- fn fill_kobj_path(kobj: &Arc<dyn KObject>, path: &mut [u8], length: usize) {
- let mut parent = kobj.parent().unwrap().upgrade().unwrap();
- let mut length = length;
- length -= 1;
- loop {
- log::info!("fill_kobj_path parent.name():{:?}", parent.name());
- let cur = parent.name().len();
- if length < cur + 1 {
- // 如果剩余长度不足以容纳当前名称和分隔符,则退出
- break;
- }
- length -= cur;
- let parent_name = parent.name();
- let name = parent_name.as_bytes();
- path[length..(cur + length)].copy_from_slice(&name[..cur]);
- length -= 1;
- path[length] = b'/';
- if let Some(weak_parent) = parent.parent() {
- if let Some(upgraded_parent) = weak_parent.upgrade() {
- parent = upgraded_parent;
- } else {
- break;
- }
- } else {
- break;
- }
- }
- }
- // TODO: 实现kobject_get_path
- // https://code.dragonos.org.cn/xref/linux-6.1.9/lib/kobject.c#139
- pub fn kobject_get_path(kobj: &Arc<dyn KObject>) -> String {
- log::debug!("kobject_get_path() kobj:{:?}", kobj.name());
- let length = Self::get_kobj_path_length(kobj);
- let path: &mut [u8] = &mut vec![0; length];
- Self::fill_kobj_path(kobj, path, length);
- let path_string = String::from_utf8(path.to_vec()).unwrap();
- return path_string;
- }
- }
- /// 动态创建的kobject对象的ktype
- #[derive(Debug)]
- pub struct DynamicKObjKType;
- impl KObjType for DynamicKObjKType {
- fn release(&self, kobj: Arc<dyn KObject>) {
- debug!("DynamicKObjKType::release() kobj:{:?}", kobj.name());
- }
- fn sysfs_ops(&self) -> Option<&dyn SysFSOps> {
- Some(&KObjectSysFSOps)
- }
- fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
- None
- }
- }
|