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