1 use core::{any::Any, fmt::Debug, hash::Hash, ops::Deref}; 2 3 use alloc::{ 4 string::String, 5 sync::{Arc, Weak}, 6 }; 7 use intertrait::CastFromSync; 8 9 use crate::{ 10 filesystem::{ 11 kernfs::KernFSInode, 12 sysfs::{sysfs_instance, Attribute, AttributeGroup, SysFSOps, SysFSOpsSupport}, 13 }, 14 kerror, 15 libs::{ 16 casting::DowncastArc, 17 rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, 18 }, 19 }; 20 21 use system_error::SystemError; 22 23 use super::kset::KSet; 24 25 pub trait KObject: Any + Send + Sync + Debug + CastFromSync { as_any_ref(&self) -> &dyn core::any::Any26 fn as_any_ref(&self) -> &dyn core::any::Any; 27 28 /// 设置当前kobject对应的sysfs inode(类型为KernFSInode) set_inode(&self, inode: Option<Arc<KernFSInode>>)29 fn set_inode(&self, inode: Option<Arc<KernFSInode>>); 30 31 /// 获取当前kobject对应的sysfs inode(类型为KernFSInode) inode(&self) -> Option<Arc<KernFSInode>>32 fn inode(&self) -> Option<Arc<KernFSInode>>; 33 parent(&self) -> Option<Weak<dyn KObject>>34 fn parent(&self) -> Option<Weak<dyn KObject>>; 35 36 /// 设置当前kobject的parent kobject(不一定与kset相同) set_parent(&self, parent: Option<Weak<dyn KObject>>)37 fn set_parent(&self, parent: Option<Weak<dyn KObject>>); 38 39 /// 当前kobject属于哪个kset kset(&self) -> Option<Arc<KSet>>40 fn kset(&self) -> Option<Arc<KSet>>; 41 42 /// 设置当前kobject所属的kset set_kset(&self, kset: Option<Arc<KSet>>)43 fn set_kset(&self, kset: Option<Arc<KSet>>); 44 kobj_type(&self) -> Option<&'static dyn KObjType>45 fn kobj_type(&self) -> Option<&'static dyn KObjType>; 46 set_kobj_type(&self, ktype: Option<&'static dyn KObjType>)47 fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>); 48 name(&self) -> String49 fn name(&self) -> String; 50 set_name(&self, name: String)51 fn set_name(&self, name: String); 52 kobj_state(&self) -> RwLockReadGuard<KObjectState>53 fn kobj_state(&self) -> RwLockReadGuard<KObjectState>; 54 kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState>55 fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState>; 56 set_kobj_state(&self, state: KObjectState)57 fn set_kobj_state(&self, state: KObjectState); 58 } 59 60 impl dyn KObject { 61 /// 更新kobject的状态 update_kobj_state(&self, insert: Option<KObjectState>, remove: Option<KObjectState>)62 pub fn update_kobj_state(&self, insert: Option<KObjectState>, remove: Option<KObjectState>) { 63 let insert = insert.unwrap_or(KObjectState::empty()); 64 let remove = remove.unwrap_or(KObjectState::empty()); 65 let mut state = self.kobj_state_mut(); 66 *state = (*state | insert) & !remove; 67 } 68 } 69 70 impl DowncastArc for dyn KObject { as_any_arc(self: Arc<Self>) -> Arc<dyn Any>71 fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any> { 72 self 73 } 74 } 75 76 pub trait KObjType: Debug + Send + Sync { 77 /// 当指定的kobject被释放时,设备驱动模型会调用此方法 release(&self, _kobj: Arc<dyn KObject>)78 fn release(&self, _kobj: Arc<dyn KObject>) {} sysfs_ops(&self) -> Option<&dyn SysFSOps>79 fn sysfs_ops(&self) -> Option<&dyn SysFSOps>; 80 attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]>81 fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]>; 82 } 83 84 bitflags! { 85 pub struct KObjectState: u32 { 86 const IN_SYSFS = 1 << 0; 87 const ADD_UEVENT_SENT = 1 << 1; 88 const REMOVE_UEVENT_SENT = 1 << 2; 89 const INITIALIZED = 1 << 3; 90 } 91 92 } 93 94 #[derive(Debug)] 95 pub struct LockedKObjectState(RwLock<KObjectState>); 96 97 impl LockedKObjectState { new(state: Option<KObjectState>) -> LockedKObjectState98 pub fn new(state: Option<KObjectState>) -> LockedKObjectState { 99 let state = state.unwrap_or(KObjectState::empty()); 100 LockedKObjectState(RwLock::new(state)) 101 } 102 } 103 104 impl Deref for LockedKObjectState { 105 type Target = RwLock<KObjectState>; 106 deref(&self) -> &Self::Target107 fn deref(&self) -> &Self::Target { 108 &self.0 109 } 110 } 111 112 impl Default for LockedKObjectState { default() -> Self113 fn default() -> Self { 114 LockedKObjectState::new(None) 115 } 116 } 117 118 #[derive(Debug)] 119 pub struct KObjectSysFSOps; 120 121 impl SysFSOps for KObjectSysFSOps { support(&self, attr: &dyn Attribute) -> SysFSOpsSupport122 fn support(&self, attr: &dyn Attribute) -> SysFSOpsSupport { 123 return attr.support(); 124 } 125 show( &self, kobj: Arc<dyn KObject>, attr: &dyn Attribute, buf: &mut [u8], ) -> Result<usize, SystemError>126 fn show( 127 &self, 128 kobj: Arc<dyn KObject>, 129 attr: &dyn Attribute, 130 buf: &mut [u8], 131 ) -> Result<usize, SystemError> { 132 let r = attr.show(kobj, buf).map_err(|e| { 133 if e == SystemError::EOPNOTSUPP_OR_ENOTSUP { 134 SystemError::EIO 135 } else { 136 e 137 } 138 }); 139 140 return r; 141 } 142 store( &self, kobj: Arc<dyn KObject>, attr: &dyn Attribute, buf: &[u8], ) -> Result<usize, SystemError>143 fn store( 144 &self, 145 kobj: Arc<dyn KObject>, 146 attr: &dyn Attribute, 147 buf: &[u8], 148 ) -> Result<usize, SystemError> { 149 let r = attr.store(kobj, buf).map_err(|e| { 150 if e == SystemError::EOPNOTSUPP_OR_ENOTSUP { 151 SystemError::EIO 152 } else { 153 e 154 } 155 }); 156 157 return r; 158 } 159 } 160 161 #[derive(Debug)] 162 pub struct KObjectManager; 163 164 impl KObjectManager { 165 #[allow(dead_code)] init_and_add_kobj( kobj: Arc<dyn KObject>, join_kset: Option<Arc<KSet>>, ) -> Result<(), SystemError>166 pub fn init_and_add_kobj( 167 kobj: Arc<dyn KObject>, 168 join_kset: Option<Arc<KSet>>, 169 ) -> Result<(), SystemError> { 170 Self::kobj_init(&kobj); 171 Self::add_kobj(kobj, join_kset) 172 } 173 174 #[allow(dead_code)] kobj_init(kobj: &Arc<dyn KObject>)175 pub fn kobj_init(kobj: &Arc<dyn KObject>) { 176 kobj.set_kobj_type(Some(&DynamicKObjKType)); 177 } 178 add_kobj( kobj: Arc<dyn KObject>, join_kset: Option<Arc<KSet>>, ) -> Result<(), SystemError>179 pub fn add_kobj( 180 kobj: Arc<dyn KObject>, 181 join_kset: Option<Arc<KSet>>, 182 ) -> Result<(), SystemError> { 183 if join_kset.is_some() { 184 let kset = join_kset.unwrap(); 185 kset.join(&kobj); 186 // 如果kobject没有parent,那么就将这个kset作为parent 187 if kobj.parent().is_none() { 188 kobj.set_parent(Some(Arc::downgrade(&(kset as Arc<dyn KObject>)))); 189 } 190 } 191 192 let r = Self::create_dir(kobj.clone()); 193 194 if let Err(e) = r { 195 // https://code.dragonos.org.cn/xref/linux-6.1.9/lib/kobject.c?r=&mo=10426&fi=394#224 196 if let Some(kset) = kobj.kset() { 197 kset.leave(&kobj); 198 } 199 kobj.set_parent(None); 200 if e == SystemError::EEXIST { 201 kerror!("KObjectManager::add_kobj() failed with error: {e:?}, kobj:{kobj:?}"); 202 } 203 204 return Err(e); 205 } 206 207 kobj.update_kobj_state(Some(KObjectState::IN_SYSFS), None); 208 return Ok(()); 209 } 210 create_dir(kobj: Arc<dyn KObject>) -> Result<(), SystemError>211 fn create_dir(kobj: Arc<dyn KObject>) -> Result<(), SystemError> { 212 // create dir in sysfs 213 sysfs_instance().create_dir(kobj.clone())?; 214 215 // create default attributes in sysfs 216 if let Some(ktype) = kobj.kobj_type() { 217 let groups = ktype.attribute_groups(); 218 if let Some(groups) = groups { 219 let r = sysfs_instance().create_groups(&kobj, groups); 220 if let Err(e) = r { 221 sysfs_instance().remove_dir(&kobj); 222 return Err(e); 223 } 224 } 225 } 226 227 return Ok(()); 228 } 229 230 /// 从sysfs中移除kobject remove_kobj(kobj: Arc<dyn KObject>)231 pub fn remove_kobj(kobj: Arc<dyn KObject>) { 232 let ktype = kobj.kobj_type(); 233 if let Some(ktype) = ktype { 234 if let Some(groups) = ktype.attribute_groups() { 235 sysfs_instance().remove_groups(&kobj, groups); 236 } 237 } 238 239 // todo: 发送uevent: KOBJ_REMOVE 240 241 sysfs_instance().remove_dir(&kobj); 242 kobj.update_kobj_state(None, Some(KObjectState::IN_SYSFS)); 243 let kset = kobj.kset(); 244 if let Some(kset) = kset { 245 kset.leave(&kobj); 246 } 247 kobj.set_parent(None); 248 } 249 } 250 251 /// 动态创建的kobject对象的ktype 252 #[derive(Debug)] 253 pub struct DynamicKObjKType; 254 255 impl KObjType for DynamicKObjKType { release(&self, kobj: Arc<dyn KObject>)256 fn release(&self, kobj: Arc<dyn KObject>) { 257 kdebug!("DynamicKObjKType::release() kobj:{:?}", kobj.name()); 258 } 259 sysfs_ops(&self) -> Option<&dyn SysFSOps>260 fn sysfs_ops(&self) -> Option<&dyn SysFSOps> { 261 Some(&KObjectSysFSOps) 262 } 263 attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]>264 fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { 265 None 266 } 267 } 268