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