106d5e247SLoGin use core::intrinsics::unlikely; 206d5e247SLoGin 306d5e247SLoGin use alloc::{string::ToString, sync::Arc}; 406d5e247SLoGin 506d5e247SLoGin use crate::{ 606d5e247SLoGin driver::base::kobject::KObject, 706d5e247SLoGin filesystem::{ 806d5e247SLoGin kernfs::{callback::KernInodePrivateData, KernFSInode}, 906d5e247SLoGin sysfs::{dir::SysKernDirPriv, sysfs_instance, SysFSKernPrivateData}, 1006d5e247SLoGin vfs::{syscall::ModeType, IndexNode}, 1106d5e247SLoGin }, 1206d5e247SLoGin kwarn, 1306d5e247SLoGin libs::casting::DowncastArc, 1406d5e247SLoGin syscall::SystemError, 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]; 37*a03c4f9dSLoGin if group.attrs().is_empty() { 38*a03c4f9dSLoGin continue; 39*a03c4f9dSLoGin } 4006d5e247SLoGin if let Err(e) = self.do_create_group(kobj, group, update) { 41*a03c4f9dSLoGin kerror!( 42*a03c4f9dSLoGin "Failed to create group '{}', err={e:?}", 43*a03c4f9dSLoGin group.name().unwrap_or("") 44*a03c4f9dSLoGin ); 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 108*a03c4f9dSLoGin pub fn remove_groups( 109*a03c4f9dSLoGin &self, 110*a03c4f9dSLoGin kobj: &Arc<dyn KObject>, 111*a03c4f9dSLoGin groups: &'static [&'static dyn AttributeGroup], 112*a03c4f9dSLoGin ) { 113*a03c4f9dSLoGin for group in groups.iter() { 114*a03c4f9dSLoGin self.remove_group(kobj, *group).ok(); 115*a03c4f9dSLoGin } 116*a03c4f9dSLoGin } 117*a03c4f9dSLoGin 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| { 14006d5e247SLoGin kwarn!("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 /// 16706d5e247SLoGin /// https://opengrok.ringotek.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) { 19206d5e247SLoGin kwarn!( 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*a03c4f9dSLoGin kerror!( 208*a03c4f9dSLoGin "Failed to create sysfs files for group '{}', err={e:?}", 209*a03c4f9dSLoGin group.name().unwrap_or("") 210*a03c4f9dSLoGin ); 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