xref: /DragonOS/kernel/src/filesystem/sysfs/group.rs (revision bd70d2d1f490aabd570a5301b858bd5eb04149fa)
1 use core::intrinsics::unlikely;
2 
3 use alloc::{string::ToString, sync::Arc};
4 use log::{error, warn};
5 use system_error::SystemError;
6 
7 use crate::{
8     driver::base::kobject::KObject,
9     filesystem::{
10         kernfs::{callback::KernInodePrivateData, KernFSInode},
11         sysfs::{dir::SysKernDirPriv, sysfs_instance, SysFSKernPrivateData},
12         vfs::{syscall::ModeType, IndexNode},
13     },
14     libs::casting::DowncastArc,
15 };
16 
17 use super::{AttributeGroup, SysFS};
18 
19 impl SysFS {
20     /// 在sysfs中,为指定的kobject的属性组创建文件夹
create_groups( &self, kobj: &Arc<dyn KObject>, groups: &[&'static dyn AttributeGroup], ) -> Result<(), SystemError>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 
do_create_groups( &self, kobj: &Arc<dyn KObject>, groups: &[&'static dyn AttributeGroup], update: bool, ) -> Result<(), SystemError>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                 error!(
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 
do_create_group( &self, kobj: &Arc<dyn KObject>, group: &'static dyn AttributeGroup, update: bool, ) -> Result<(), SystemError>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 
remove_groups( &self, kobj: &Arc<dyn KObject>, groups: &'static [&'static dyn AttributeGroup], )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     ///
remove_group( &self, kobj: &Arc<dyn KObject>, group: &'static dyn AttributeGroup, ) -> Result<(), SystemError>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                 .inspect_err(|_e| {
140                     warn!("sysfs group '{name}' not found for kobject {kobj:?}");
141                 })?
142                 .downcast_arc()
143                 .unwrap();
144         } else {
145             parent_inode = inode;
146         }
147 
148         self.group_remove_files(&parent_inode, group);
149 
150         if group.name().is_some() {
151             parent_inode.remove_recursive();
152         }
153 
154         return Ok(());
155     }
156 
157     /// 创建属性组的文件
158     ///
159     /// ## 参数
160     ///
161     /// - `parent` - 属性组的父文件夹
162     /// - `kobj` - 属性组所属的kobject
163     /// - `group` - 属性组
164     /// - `update` - 当前是否正在更新属性
165     ///
166     /// https://code.dragonos.org.cn/xref/linux-6.1.9/fs/sysfs/group.c#34
group_create_files( &self, parent: Arc<KernFSInode>, kobj: &Arc<dyn KObject>, group: &'static dyn AttributeGroup, update: bool, ) -> Result<(), SystemError>167     fn group_create_files(
168         &self,
169         parent: Arc<KernFSInode>,
170         kobj: &Arc<dyn KObject>,
171         group: &'static dyn AttributeGroup,
172         update: bool,
173     ) -> Result<(), SystemError> {
174         let mut e = Ok(());
175         for attr in group.attrs() {
176             let mut mode = attr.mode();
177 
178             // 由于我们在更新的时候,可能会更改visibility和permissions,所以需要先删除再创建
179             if update {
180                 parent.remove(attr.name()).ok();
181             }
182             if let Some(mt) = group.is_visible(kobj.clone(), *attr) {
183                 mode = mt;
184                 // 当前属性不可见,跳过
185                 if mode.is_empty() {
186                     continue;
187                 }
188             }
189 
190             if unlikely((mode.bits() & (!0o644)) != 0) {
191                 warn!(
192                     "Attribute '{name}' has invalid mode 0{mode:o}",
193                     name = attr.name(),
194                     mode = mode
195                 );
196             }
197 
198             mode = ModeType::from_bits_truncate(mode.bits() & 0o644);
199             e = sysfs_instance().add_file_with_mode(&parent, *attr, mode);
200             if e.is_err() {
201                 break;
202             }
203         }
204 
205         if let Err(e) = e {
206             error!(
207                 "Failed to create sysfs files for group '{}', err={e:?}",
208                 group.name().unwrap_or("")
209             );
210             self.group_remove_files(&parent, group);
211             return Err(e);
212         }
213 
214         return Ok(());
215     }
216 
group_remove_files(&self, _parent: &Arc<KernFSInode>, _group: &'static dyn AttributeGroup)217     fn group_remove_files(&self, _parent: &Arc<KernFSInode>, _group: &'static dyn AttributeGroup) {
218         todo!("group_remove_files")
219     }
220 }
221