1 use core::{intrinsics::unlikely, ops::BitAnd}; 2 3 use alloc::{ 4 string::ToString, 5 sync::{Arc, Weak}, 6 }; 7 8 use crate::{ 9 driver::base::kobject::KObject, 10 filesystem::{ 11 kernfs::{ 12 callback::{KernCallbackData, KernFSCallback, KernInodePrivateData}, 13 KernFSInode, 14 }, 15 sysfs::{SysFSOps, SysFSOpsSupport}, 16 vfs::{syscall::ModeType, PollStatus}, 17 }, 18 kwarn, 19 syscall::SystemError, 20 }; 21 22 use super::{Attribute, SysFS, SysFSKernPrivateData}; 23 24 #[derive(Debug)] 25 pub struct SysKernFilePriv { 26 attribute: Option<&'static dyn Attribute>, 27 /// 当前文件对应的kobject 28 kobj: Weak<dyn KObject>, 29 // todo: 增加bin attribute,它和attribute二选一,只能有一个为Some 30 } 31 32 impl SysKernFilePriv { 33 pub fn new(kobj: &Arc<dyn KObject>, attribute: Option<&'static dyn Attribute>) -> Self { 34 if attribute.is_none() { 35 panic!("attribute can't be None"); 36 } 37 let kobj = Arc::downgrade(kobj); 38 return Self { kobj, attribute }; 39 } 40 41 #[allow(dead_code)] 42 #[inline] 43 pub fn attribute(&self) -> Option<&'static dyn Attribute> { 44 self.attribute 45 } 46 47 pub fn callback_read(&self, buf: &mut [u8]) -> Result<usize, SystemError> { 48 let attribute = self.attribute.ok_or(SystemError::EINVAL)?; 49 // 当前文件所指向的kobject已经被释放 50 let kobj = self.kobj.upgrade().expect("kobj is None"); 51 return attribute.show(kobj, buf); 52 } 53 54 pub fn callback_write(&self, buf: &[u8]) -> Result<usize, SystemError> { 55 let attribute = self.attribute.ok_or(SystemError::EINVAL)?; 56 // 当前文件所指向的kobject已经被释放 57 let kobj = self.kobj.upgrade().expect("kobj is None"); 58 return attribute.store(kobj, buf); 59 } 60 } 61 62 impl SysFS { 63 /// 为指定的kobject创建一个属性文件 64 /// 65 /// ## 参数 66 /// 67 /// - `kobj` 要创建属性文件的kobject 68 /// - `attr` 属性 69 pub fn create_file( 70 &self, 71 kobj: &Arc<dyn KObject>, 72 attr: &'static dyn Attribute, 73 ) -> Result<(), SystemError> { 74 let inode = kobj.inode().ok_or(SystemError::EINVAL)?; 75 return self.add_file_with_mode(&inode, attr, attr.mode()); 76 } 77 78 // https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/file.c?fi=sysfs_add_file_mode_ns#271 79 pub(super) fn add_file_with_mode( 80 &self, 81 parent: &Arc<KernFSInode>, 82 attr: &'static dyn Attribute, 83 mode: ModeType, 84 ) -> Result<(), SystemError> { 85 let x = parent.private_data_mut(); 86 let kobj: Arc<dyn KObject>; 87 if let Some(KernInodePrivateData::SysFS(SysFSKernPrivateData::Dir(dt))) = x.as_ref() { 88 kobj = dt.kobj().unwrap(); 89 } else { 90 drop(x); 91 let path = self.kernfs_path(parent); 92 panic!("parent '{path}' is not a dir"); 93 } 94 drop(x); 95 96 let sysfs_ops: &dyn SysFSOps = kobj.kobj_type().unwrap().sysfs_ops().ok_or_else(|| { 97 kwarn!("missing sysfs attribute operations for kobject: {kobj:?}"); 98 SystemError::EINVAL 99 })?; 100 101 // assume that all sysfs ops are preallocated. 102 103 let sys_support = sysfs_ops.support(attr); 104 105 let kern_callback: &'static dyn KernFSCallback; 106 if sys_support.contains(SysFSOpsSupport::SHOW) 107 && sys_support.contains(SysFSOpsSupport::STORE) 108 { 109 kern_callback = &PreallocKFOpsRW; 110 } else if sys_support.contains(SysFSOpsSupport::SHOW) { 111 kern_callback = &PreallocKFOpsReadOnly; 112 } else if sys_support.contains(SysFSOpsSupport::STORE) { 113 kern_callback = &PreallocKFOpsWriteOnly; 114 } else { 115 kern_callback = &PreallocKFOpsEmpty; 116 } 117 118 let sys_priv = SysFSKernPrivateData::File(SysKernFilePriv::new(&kobj, Some(attr))); 119 let r = parent.add_file( 120 attr.name().to_string(), 121 mode.bitand(ModeType::from_bits_truncate(0o777)), 122 Some(KernInodePrivateData::SysFS(sys_priv)), 123 Some(kern_callback), 124 ); 125 126 if let Err(e) = r { 127 if e == SystemError::EEXIST { 128 self.warn_duplicate(parent, attr.name()); 129 } 130 131 return Err(e); 132 } 133 return Ok(()); 134 } 135 136 /// 在sysfs中删除某个kobject的属性文件 137 /// 138 /// 如果属性文件不存在,则发出一个警告 139 /// 140 /// ## 参数 141 /// 142 /// - `kobj` 要删除属性文件的kobject 143 /// - `attr` 属性 144 pub fn remove_file(&self, kobj: &Arc<dyn KObject>, attr: &'static dyn Attribute) { 145 let parent = kobj.inode(); 146 147 if let Some(parent) = parent { 148 let r = parent.remove(attr.name()); 149 if unlikely(r.is_err()) { 150 kwarn!( 151 "failed to remove file '{}' from '{}'", 152 attr.name(), 153 kobj.name() 154 ); 155 } 156 } 157 } 158 } 159 160 #[derive(Debug)] 161 struct PreallocKFOpsRW; 162 163 impl KernFSCallback for PreallocKFOpsRW { 164 fn open(&self, _data: KernCallbackData) -> Result<(), SystemError> { 165 return Ok(()); 166 } 167 168 fn read( 169 &self, 170 data: KernCallbackData, 171 buf: &mut [u8], 172 offset: usize, 173 ) -> Result<usize, SystemError> { 174 return data.callback_read(buf, offset); 175 } 176 177 fn write( 178 &self, 179 data: KernCallbackData, 180 buf: &[u8], 181 offset: usize, 182 ) -> Result<usize, SystemError> { 183 return data.callback_write(buf, offset); 184 } 185 186 #[inline] 187 fn poll(&self, _data: KernCallbackData) -> Result<PollStatus, SystemError> { 188 return Ok(PollStatus::READ | PollStatus::WRITE); 189 } 190 } 191 192 #[derive(Debug)] 193 struct PreallocKFOpsReadOnly; 194 195 impl KernFSCallback for PreallocKFOpsReadOnly { 196 fn open(&self, _data: KernCallbackData) -> Result<(), SystemError> { 197 return Ok(()); 198 } 199 200 fn read( 201 &self, 202 data: KernCallbackData, 203 buf: &mut [u8], 204 offset: usize, 205 ) -> Result<usize, SystemError> { 206 return data.callback_read(buf, offset); 207 } 208 209 fn write( 210 &self, 211 _data: KernCallbackData, 212 _buf: &[u8], 213 _offset: usize, 214 ) -> Result<usize, SystemError> { 215 return Err(SystemError::EPERM); 216 } 217 218 #[inline] 219 fn poll(&self, _data: KernCallbackData) -> Result<PollStatus, SystemError> { 220 return Ok(PollStatus::READ); 221 } 222 } 223 224 #[derive(Debug)] 225 struct PreallocKFOpsWriteOnly; 226 227 impl KernFSCallback for PreallocKFOpsWriteOnly { 228 fn open(&self, _data: KernCallbackData) -> Result<(), SystemError> { 229 return Ok(()); 230 } 231 232 fn read( 233 &self, 234 _data: KernCallbackData, 235 _buf: &mut [u8], 236 _offset: usize, 237 ) -> Result<usize, SystemError> { 238 return Err(SystemError::EPERM); 239 } 240 241 fn write( 242 &self, 243 data: KernCallbackData, 244 buf: &[u8], 245 offset: usize, 246 ) -> Result<usize, SystemError> { 247 return data.callback_write(buf, offset); 248 } 249 250 #[inline] 251 fn poll(&self, _data: KernCallbackData) -> Result<PollStatus, SystemError> { 252 return Ok(PollStatus::WRITE); 253 } 254 } 255 256 #[derive(Debug)] 257 struct PreallocKFOpsEmpty; 258 259 impl KernFSCallback for PreallocKFOpsEmpty { 260 fn open(&self, _data: KernCallbackData) -> Result<(), SystemError> { 261 return Ok(()); 262 } 263 264 fn read( 265 &self, 266 _data: KernCallbackData, 267 _buf: &mut [u8], 268 _offset: usize, 269 ) -> Result<usize, SystemError> { 270 return Err(SystemError::EPERM); 271 } 272 273 fn write( 274 &self, 275 _data: KernCallbackData, 276 _buf: &[u8], 277 _offset: usize, 278 ) -> Result<usize, SystemError> { 279 return Err(SystemError::EPERM); 280 } 281 282 #[inline] 283 fn poll(&self, _data: KernCallbackData) -> Result<PollStatus, SystemError> { 284 return Ok(PollStatus::empty()); 285 } 286 } 287 288 pub fn sysfs_emit_str(buf: &mut [u8], s: &str) -> Result<usize, SystemError> { 289 let len; 290 if buf.len() > s.len() { 291 len = s.len(); 292 } else { 293 len = buf.len() - 1; 294 } 295 buf[..len].copy_from_slice(&s.as_bytes()[..len]); 296 buf[len] = b'\0'; 297 return Ok(len); 298 } 299