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的属性组创建文件夹 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 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 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 .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 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 217 fn group_remove_files(&self, _parent: &Arc<KernFSInode>, _group: &'static dyn AttributeGroup) { 218 todo!("group_remove_files") 219 } 220 } 221