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