xref: /DragonOS/kernel/src/filesystem/sysfs/group.rs (revision 81294aa2e6b257f0de5e3c28c3f3c89798330836)
1 use core::intrinsics::unlikely;
2 
3 use alloc::{string::ToString, sync::Arc};
4 use system_error::SystemError;
5 
6 use crate::{
7     driver::base::kobject::KObject,
8     filesystem::{
9         kernfs::{callback::KernInodePrivateData, KernFSInode},
10         sysfs::{dir::SysKernDirPriv, sysfs_instance, SysFSKernPrivateData},
11         vfs::{syscall::ModeType, IndexNode},
12     },
13     kwarn,
14     libs::casting::DowncastArc,
15 };
16 
17 use super::{AttributeGroup, SysFS};
18 
19 impl SysFS {
20     /// 在sysfs中,为指定的kobject的属性组创建文件夹
21     pub fn create_groups(
22         &self,
23         kobj: &Arc<dyn KObject>,
24         groups: &[&'static dyn AttributeGroup],
25     ) -> Result<(), SystemError> {
26         return self.do_create_groups(kobj, groups, false);
27     }
28 
29     fn do_create_groups(
30         &self,
31         kobj: &Arc<dyn KObject>,
32         groups: &[&'static dyn AttributeGroup],
33         update: bool,
34     ) -> Result<(), SystemError> {
35         for i in 0..groups.len() {
36             let group = groups[i];
37             if group.attrs().is_empty() {
38                 continue;
39             }
40             if let Err(e) = self.do_create_group(kobj, group, update) {
41                 kerror!(
42                     "Failed to create group '{}', err={e:?}",
43                     group.name().unwrap_or("")
44                 );
45                 for j in (0..=i).rev() {
46                     self.remove_group(kobj, groups[j]).ok();
47                 }
48                 return Err(e);
49             }
50         }
51         return Ok(());
52     }
53 
54     fn do_create_group(
55         &self,
56         kobj: &Arc<dyn KObject>,
57         group: &'static dyn AttributeGroup,
58         update: bool,
59     ) -> Result<(), SystemError> {
60         // kobj的inode必须存在
61         let kobj_inode = kobj.inode().ok_or(SystemError::EINVAL)?;
62 
63         if group.attrs().is_empty() {
64             return Err(SystemError::EINVAL);
65         }
66 
67         let parent_inode: Arc<KernFSInode>;
68         if group.name().is_some() {
69             if update {
70                 // 如果是更新,那么group的name必须存在
71                 parent_inode = kobj_inode
72                     .find(group.name().unwrap())
73                     .map_err(|_| SystemError::EINVAL)?
74                     .downcast_arc()
75                     .unwrap();
76             } else {
77                 let private_data = KernInodePrivateData::SysFS(SysFSKernPrivateData::Dir(
78                     SysKernDirPriv::new(kobj.clone()),
79                 ));
80                 parent_inode = kobj_inode
81                     .add_dir(
82                         group.name().unwrap().to_string(),
83                         ModeType::S_IRWXU | ModeType::S_IRUGO | ModeType::S_IXUGO,
84                         Some(private_data),
85                         None,
86                     )
87                     .map_err(|e| {
88                         if e == SystemError::EEXIST {
89                             self.warn_duplicate(&kobj_inode, group.name().unwrap());
90                         }
91                         e
92                     })?;
93             }
94         } else {
95             parent_inode = kobj_inode.clone();
96         }
97 
98         if let Err(e) = self.group_create_files(parent_inode.clone(), kobj, group, update) {
99             if group.name().is_some() {
100                 parent_inode.remove_recursive();
101             }
102             return Err(e);
103         }
104 
105         return Ok(());
106     }
107 
108     pub fn remove_groups(
109         &self,
110         kobj: &Arc<dyn KObject>,
111         groups: &'static [&'static dyn AttributeGroup],
112     ) {
113         for group in groups.iter() {
114             self.remove_group(kobj, *group).ok();
115         }
116     }
117 
118     /// 从一个kobject中移除一个group
119     ///
120     /// This function removes a group of attributes from a kobject.  The attributes
121     /// previously have to have been created for this group, otherwise it will fail.
122     ///
123     /// ## 参数
124     ///
125     /// - `kobj` - 要移除group的kobject
126     /// - `group` - 要移除的group
127     ///
128     ///
129     pub fn remove_group(
130         &self,
131         kobj: &Arc<dyn KObject>,
132         group: &'static dyn AttributeGroup,
133     ) -> Result<(), SystemError> {
134         let inode = kobj.inode().unwrap();
135         let parent_inode: Arc<KernFSInode>;
136         if let Some(name) = group.name() {
137             parent_inode = inode
138                 .find(name)
139                 .map_err(|e| {
140                     kwarn!("sysfs group '{name}' not found for kobject {kobj:?}");
141                     e
142                 })?
143                 .downcast_arc()
144                 .unwrap();
145         } else {
146             parent_inode = inode;
147         }
148 
149         self.group_remove_files(&parent_inode, group);
150 
151         if group.name().is_some() {
152             parent_inode.remove_recursive();
153         }
154 
155         return Ok(());
156     }
157 
158     /// 创建属性组的文件
159     ///
160     /// ## 参数
161     ///
162     /// - `parent` - 属性组的父文件夹
163     /// - `kobj` - 属性组所属的kobject
164     /// - `group` - 属性组
165     /// - `update` - 当前是否正在更新属性
166     ///
167     /// https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/group.c#34
168     fn group_create_files(
169         &self,
170         parent: Arc<KernFSInode>,
171         kobj: &Arc<dyn KObject>,
172         group: &'static dyn AttributeGroup,
173         update: bool,
174     ) -> Result<(), SystemError> {
175         let mut e = Ok(());
176         for attr in group.attrs() {
177             let mut mode = attr.mode();
178 
179             // 由于我们在更新的时候,可能会更改visibility和permissions,所以需要先删除再创建
180             if update {
181                 parent.remove(attr.name()).ok();
182             }
183             if let Some(mt) = group.is_visible(kobj.clone(), *attr) {
184                 mode = mt;
185                 // 当前属性不可见,跳过
186                 if mode.is_empty() {
187                     continue;
188                 }
189             }
190 
191             if unlikely((mode.bits() & (!0o644)) != 0) {
192                 kwarn!(
193                     "Attribute '{name}' has invalid mode 0{mode:o}",
194                     name = attr.name(),
195                     mode = mode
196                 );
197             }
198 
199             mode = ModeType::from_bits_truncate(mode.bits() & 0o644);
200             e = sysfs_instance().add_file_with_mode(&parent, *attr, mode);
201             if e.is_err() {
202                 break;
203             }
204         }
205 
206         if let Err(e) = e {
207             kerror!(
208                 "Failed to create sysfs files for group '{}', err={e:?}",
209                 group.name().unwrap_or("")
210             );
211             self.group_remove_files(&parent, group);
212             return Err(e);
213         }
214 
215         return Ok(());
216     }
217 
218     fn group_remove_files(&self, _parent: &Arc<KernFSInode>, _group: &'static dyn AttributeGroup) {
219         todo!("group_remove_files")
220     }
221 }
222