xref: /DragonOS/kernel/src/filesystem/sysfs/group.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
106d5e247SLoGin use core::intrinsics::unlikely;
206d5e247SLoGin 
306d5e247SLoGin use alloc::{string::ToString, sync::Arc};
4*2eab6dd7S曾俊 use log::{error, warn};
591e9d4abSLoGin use system_error::SystemError;
606d5e247SLoGin 
706d5e247SLoGin use crate::{
806d5e247SLoGin     driver::base::kobject::KObject,
906d5e247SLoGin     filesystem::{
1006d5e247SLoGin         kernfs::{callback::KernInodePrivateData, KernFSInode},
1106d5e247SLoGin         sysfs::{dir::SysKernDirPriv, sysfs_instance, SysFSKernPrivateData},
1206d5e247SLoGin         vfs::{syscall::ModeType, IndexNode},
1306d5e247SLoGin     },
1406d5e247SLoGin     libs::casting::DowncastArc,
1506d5e247SLoGin };
1606d5e247SLoGin 
1706d5e247SLoGin use super::{AttributeGroup, SysFS};
1806d5e247SLoGin 
1906d5e247SLoGin impl SysFS {
2006d5e247SLoGin     /// 在sysfs中,为指定的kobject的属性组创建文件夹
2106d5e247SLoGin     pub fn create_groups(
2206d5e247SLoGin         &self,
2306d5e247SLoGin         kobj: &Arc<dyn KObject>,
2406d5e247SLoGin         groups: &[&'static dyn AttributeGroup],
2506d5e247SLoGin     ) -> Result<(), SystemError> {
2606d5e247SLoGin         return self.do_create_groups(kobj, groups, false);
2706d5e247SLoGin     }
2806d5e247SLoGin 
2906d5e247SLoGin     fn do_create_groups(
3006d5e247SLoGin         &self,
3106d5e247SLoGin         kobj: &Arc<dyn KObject>,
3206d5e247SLoGin         groups: &[&'static dyn AttributeGroup],
3306d5e247SLoGin         update: bool,
3406d5e247SLoGin     ) -> Result<(), SystemError> {
3506d5e247SLoGin         for i in 0..groups.len() {
3606d5e247SLoGin             let group = groups[i];
37a03c4f9dSLoGin             if group.attrs().is_empty() {
38a03c4f9dSLoGin                 continue;
39a03c4f9dSLoGin             }
4006d5e247SLoGin             if let Err(e) = self.do_create_group(kobj, group, update) {
41*2eab6dd7S曾俊                 error!(
42a03c4f9dSLoGin                     "Failed to create group '{}', err={e:?}",
43a03c4f9dSLoGin                     group.name().unwrap_or("")
44a03c4f9dSLoGin                 );
4506d5e247SLoGin                 for j in (0..=i).rev() {
4606d5e247SLoGin                     self.remove_group(kobj, groups[j]).ok();
4706d5e247SLoGin                 }
4806d5e247SLoGin                 return Err(e);
4906d5e247SLoGin             }
5006d5e247SLoGin         }
5106d5e247SLoGin         return Ok(());
5206d5e247SLoGin     }
5306d5e247SLoGin 
5406d5e247SLoGin     fn do_create_group(
5506d5e247SLoGin         &self,
5606d5e247SLoGin         kobj: &Arc<dyn KObject>,
5706d5e247SLoGin         group: &'static dyn AttributeGroup,
5806d5e247SLoGin         update: bool,
5906d5e247SLoGin     ) -> Result<(), SystemError> {
6006d5e247SLoGin         // kobj的inode必须存在
6106d5e247SLoGin         let kobj_inode = kobj.inode().ok_or(SystemError::EINVAL)?;
6206d5e247SLoGin 
6306d5e247SLoGin         if group.attrs().is_empty() {
6406d5e247SLoGin             return Err(SystemError::EINVAL);
6506d5e247SLoGin         }
6606d5e247SLoGin 
6706d5e247SLoGin         let parent_inode: Arc<KernFSInode>;
6806d5e247SLoGin         if group.name().is_some() {
6906d5e247SLoGin             if update {
7006d5e247SLoGin                 // 如果是更新,那么group的name必须存在
7106d5e247SLoGin                 parent_inode = kobj_inode
7206d5e247SLoGin                     .find(group.name().unwrap())
7306d5e247SLoGin                     .map_err(|_| SystemError::EINVAL)?
7406d5e247SLoGin                     .downcast_arc()
7506d5e247SLoGin                     .unwrap();
7606d5e247SLoGin             } else {
7706d5e247SLoGin                 let private_data = KernInodePrivateData::SysFS(SysFSKernPrivateData::Dir(
7806d5e247SLoGin                     SysKernDirPriv::new(kobj.clone()),
7906d5e247SLoGin                 ));
8006d5e247SLoGin                 parent_inode = kobj_inode
8106d5e247SLoGin                     .add_dir(
8206d5e247SLoGin                         group.name().unwrap().to_string(),
8306d5e247SLoGin                         ModeType::S_IRWXU | ModeType::S_IRUGO | ModeType::S_IXUGO,
8406d5e247SLoGin                         Some(private_data),
8506d5e247SLoGin                         None,
8606d5e247SLoGin                     )
8706d5e247SLoGin                     .map_err(|e| {
8806d5e247SLoGin                         if e == SystemError::EEXIST {
8906d5e247SLoGin                             self.warn_duplicate(&kobj_inode, group.name().unwrap());
9006d5e247SLoGin                         }
9106d5e247SLoGin                         e
9206d5e247SLoGin                     })?;
9306d5e247SLoGin             }
9406d5e247SLoGin         } else {
9506d5e247SLoGin             parent_inode = kobj_inode.clone();
9606d5e247SLoGin         }
9706d5e247SLoGin 
9806d5e247SLoGin         if let Err(e) = self.group_create_files(parent_inode.clone(), kobj, group, update) {
9906d5e247SLoGin             if group.name().is_some() {
10006d5e247SLoGin                 parent_inode.remove_recursive();
10106d5e247SLoGin             }
10206d5e247SLoGin             return Err(e);
10306d5e247SLoGin         }
10406d5e247SLoGin 
10506d5e247SLoGin         return Ok(());
10606d5e247SLoGin     }
10706d5e247SLoGin 
108a03c4f9dSLoGin     pub fn remove_groups(
109a03c4f9dSLoGin         &self,
110a03c4f9dSLoGin         kobj: &Arc<dyn KObject>,
111a03c4f9dSLoGin         groups: &'static [&'static dyn AttributeGroup],
112a03c4f9dSLoGin     ) {
113a03c4f9dSLoGin         for group in groups.iter() {
114a03c4f9dSLoGin             self.remove_group(kobj, *group).ok();
115a03c4f9dSLoGin         }
116a03c4f9dSLoGin     }
117a03c4f9dSLoGin 
11806d5e247SLoGin     /// 从一个kobject中移除一个group
11906d5e247SLoGin     ///
12006d5e247SLoGin     /// This function removes a group of attributes from a kobject.  The attributes
12106d5e247SLoGin     /// previously have to have been created for this group, otherwise it will fail.
12206d5e247SLoGin     ///
12306d5e247SLoGin     /// ## 参数
12406d5e247SLoGin     ///
12506d5e247SLoGin     /// - `kobj` - 要移除group的kobject
12606d5e247SLoGin     /// - `group` - 要移除的group
12706d5e247SLoGin     ///
12806d5e247SLoGin     ///
12906d5e247SLoGin     pub fn remove_group(
13006d5e247SLoGin         &self,
13106d5e247SLoGin         kobj: &Arc<dyn KObject>,
13206d5e247SLoGin         group: &'static dyn AttributeGroup,
13306d5e247SLoGin     ) -> Result<(), SystemError> {
13406d5e247SLoGin         let inode = kobj.inode().unwrap();
13506d5e247SLoGin         let parent_inode: Arc<KernFSInode>;
13606d5e247SLoGin         if let Some(name) = group.name() {
13706d5e247SLoGin             parent_inode = inode
13806d5e247SLoGin                 .find(name)
13906d5e247SLoGin                 .map_err(|e| {
140*2eab6dd7S曾俊                     warn!("sysfs group '{name}' not found for kobject {kobj:?}");
14106d5e247SLoGin                     e
14206d5e247SLoGin                 })?
14306d5e247SLoGin                 .downcast_arc()
14406d5e247SLoGin                 .unwrap();
14506d5e247SLoGin         } else {
14606d5e247SLoGin             parent_inode = inode;
14706d5e247SLoGin         }
14806d5e247SLoGin 
14906d5e247SLoGin         self.group_remove_files(&parent_inode, group);
15006d5e247SLoGin 
15106d5e247SLoGin         if group.name().is_some() {
15206d5e247SLoGin             parent_inode.remove_recursive();
15306d5e247SLoGin         }
15406d5e247SLoGin 
15506d5e247SLoGin         return Ok(());
15606d5e247SLoGin     }
15706d5e247SLoGin 
15806d5e247SLoGin     /// 创建属性组的文件
15906d5e247SLoGin     ///
16006d5e247SLoGin     /// ## 参数
16106d5e247SLoGin     ///
16206d5e247SLoGin     /// - `parent` - 属性组的父文件夹
16306d5e247SLoGin     /// - `kobj` - 属性组所属的kobject
16406d5e247SLoGin     /// - `group` - 属性组
16506d5e247SLoGin     /// - `update` - 当前是否正在更新属性
16606d5e247SLoGin     ///
167e7071df6SLoGin     /// https://code.dragonos.org.cn/xref/linux-6.1.9/fs/sysfs/group.c#34
16806d5e247SLoGin     fn group_create_files(
16906d5e247SLoGin         &self,
17006d5e247SLoGin         parent: Arc<KernFSInode>,
17106d5e247SLoGin         kobj: &Arc<dyn KObject>,
17206d5e247SLoGin         group: &'static dyn AttributeGroup,
17306d5e247SLoGin         update: bool,
17406d5e247SLoGin     ) -> Result<(), SystemError> {
17506d5e247SLoGin         let mut e = Ok(());
17606d5e247SLoGin         for attr in group.attrs() {
17706d5e247SLoGin             let mut mode = attr.mode();
17806d5e247SLoGin 
17906d5e247SLoGin             // 由于我们在更新的时候,可能会更改visibility和permissions,所以需要先删除再创建
18006d5e247SLoGin             if update {
18106d5e247SLoGin                 parent.remove(attr.name()).ok();
18206d5e247SLoGin             }
18306d5e247SLoGin             if let Some(mt) = group.is_visible(kobj.clone(), *attr) {
18406d5e247SLoGin                 mode = mt;
18506d5e247SLoGin                 // 当前属性不可见,跳过
18606d5e247SLoGin                 if mode.is_empty() {
18706d5e247SLoGin                     continue;
18806d5e247SLoGin                 }
18906d5e247SLoGin             }
19006d5e247SLoGin 
19106d5e247SLoGin             if unlikely((mode.bits() & (!0o644)) != 0) {
192*2eab6dd7S曾俊                 warn!(
19306d5e247SLoGin                     "Attribute '{name}' has invalid mode 0{mode:o}",
19406d5e247SLoGin                     name = attr.name(),
19506d5e247SLoGin                     mode = mode
19606d5e247SLoGin                 );
19706d5e247SLoGin             }
19806d5e247SLoGin 
19906d5e247SLoGin             mode = ModeType::from_bits_truncate(mode.bits() & 0o644);
20006d5e247SLoGin             e = sysfs_instance().add_file_with_mode(&parent, *attr, mode);
20106d5e247SLoGin             if e.is_err() {
20206d5e247SLoGin                 break;
20306d5e247SLoGin             }
20406d5e247SLoGin         }
20506d5e247SLoGin 
20606d5e247SLoGin         if let Err(e) = e {
207*2eab6dd7S曾俊             error!(
208a03c4f9dSLoGin                 "Failed to create sysfs files for group '{}', err={e:?}",
209a03c4f9dSLoGin                 group.name().unwrap_or("")
210a03c4f9dSLoGin             );
21106d5e247SLoGin             self.group_remove_files(&parent, group);
21206d5e247SLoGin             return Err(e);
21306d5e247SLoGin         }
21406d5e247SLoGin 
21506d5e247SLoGin         return Ok(());
21606d5e247SLoGin     }
21706d5e247SLoGin 
21806d5e247SLoGin     fn group_remove_files(&self, _parent: &Arc<KernFSInode>, _group: &'static dyn AttributeGroup) {
21906d5e247SLoGin         todo!("group_remove_files")
22006d5e247SLoGin     }
22106d5e247SLoGin }
222