1 use core::{intrinsics::unlikely, ops::BitAnd}; 2 3 use alloc::{ 4 string::ToString, 5 sync::{Arc, Weak}, 6 }; 7 use system_error::SystemError; 8 9 use crate::{ 10 driver::base::kobject::KObject, 11 filesystem::{ 12 kernfs::{ 13 callback::{KernCallbackData, KernFSCallback, KernInodePrivateData}, 14 KernFSInode, 15 }, 16 sysfs::{SysFSOps, SysFSOpsSupport}, 17 vfs::{syscall::ModeType, PollStatus}, 18 }, 19 kwarn, 20 }; 21 22 use super::{Attribute, BinAttribute, SysFS, SysFSKernPrivateData}; 23 24 #[derive(Debug)] 25 pub struct SysKernFilePriv { 26 attribute: Option<&'static dyn Attribute>, 27 /// bin attribute和attribute二选一,只能有一个为Some 28 bin_attribute: Option<Arc<dyn BinAttribute>>, 29 /// 当前文件对应的kobject 30 kobj: Weak<dyn KObject>, 31 } 32 33 impl SysKernFilePriv { 34 pub fn new( 35 kobj: &Arc<dyn KObject>, 36 attribute: Option<&'static dyn Attribute>, 37 bin_attribute: Option<Arc<dyn BinAttribute>>, 38 ) -> Self { 39 if attribute.is_none() && bin_attribute.is_none() { 40 panic!("attribute and bin_attribute can't be both None"); 41 } 42 if attribute.is_some() && bin_attribute.is_some() { 43 panic!("attribute and bin_attribute can't be both Some"); 44 } 45 46 let kobj = Arc::downgrade(kobj); 47 return Self { 48 kobj, 49 attribute, 50 bin_attribute, 51 }; 52 } 53 54 #[allow(dead_code)] 55 #[inline] 56 pub fn attribute(&self) -> Option<&'static dyn Attribute> { 57 self.attribute 58 } 59 60 pub fn callback_read(&self, buf: &mut [u8], offset: usize) -> Result<usize, SystemError> { 61 if let Some(attribute) = self.attribute { 62 // 当前文件所指向的kobject已经被释放 63 let kobj = self.kobj.upgrade().expect("kobj is None"); 64 let len = attribute.show(kobj, buf)?; 65 if offset > 0 { 66 if len <= offset { 67 return Ok(0); 68 } 69 let len = len - offset; 70 buf.copy_within(offset..offset + len, 0); 71 buf[len] = 0; 72 } 73 return Ok(len); 74 } else if let Some(bin_attribute) = self.bin_attribute.as_ref() { 75 // 当前文件所指向的kobject已经被释放 76 let kobj = self.kobj.upgrade().expect("kobj is None"); 77 return bin_attribute.read(kobj, buf, offset); 78 } else { 79 panic!("attribute and bin_attribute can't be both None"); 80 } 81 } 82 83 pub fn callback_write(&self, buf: &[u8], offset: usize) -> Result<usize, SystemError> { 84 if let Some(attribute) = self.attribute { 85 // 当前文件所指向的kobject已经被释放 86 let kobj = self.kobj.upgrade().expect("kobj is None"); 87 return attribute.store(kobj, buf); 88 } else if let Some(bin_attribute) = self.bin_attribute.as_ref() { 89 // 当前文件所指向的kobject已经被释放 90 let kobj = self.kobj.upgrade().expect("kobj is None"); 91 return bin_attribute.write(kobj, buf, offset); 92 } else { 93 panic!("attribute and bin_attribute can't be both None"); 94 } 95 } 96 } 97 98 impl SysFS { 99 /// 为指定的kobject创建一个属性文件 100 /// 101 /// ## 参数 102 /// 103 /// - `kobj` 要创建属性文件的kobject 104 /// - `attr` 属性 105 pub fn create_file( 106 &self, 107 kobj: &Arc<dyn KObject>, 108 attr: &'static dyn Attribute, 109 ) -> Result<(), SystemError> { 110 let inode = kobj.inode().ok_or(SystemError::EINVAL)?; 111 return self.add_file_with_mode(&inode, attr, attr.mode()); 112 } 113 114 // https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/file.c?fi=sysfs_add_file_mode_ns#271 115 pub(super) fn add_file_with_mode( 116 &self, 117 parent: &Arc<KernFSInode>, 118 attr: &'static dyn Attribute, 119 mode: ModeType, 120 ) -> Result<(), SystemError> { 121 let x = parent.private_data_mut(); 122 let kobj: Arc<dyn KObject>; 123 if let Some(KernInodePrivateData::SysFS(SysFSKernPrivateData::Dir(dt))) = x.as_ref() { 124 kobj = dt.kobj().unwrap(); 125 } else { 126 drop(x); 127 let path = self.kernfs_path(parent); 128 panic!("parent '{path}' is not a dir"); 129 } 130 drop(x); 131 132 let sysfs_ops: &dyn SysFSOps = kobj.kobj_type().unwrap().sysfs_ops().ok_or_else(|| { 133 kwarn!("missing sysfs attribute operations for kobject: {kobj:?}"); 134 SystemError::EINVAL 135 })?; 136 137 // assume that all sysfs ops are preallocated. 138 139 let sys_support = sysfs_ops.support(attr); 140 141 let kern_callback: &'static dyn KernFSCallback; 142 if sys_support.contains(SysFSOpsSupport::SHOW) 143 && sys_support.contains(SysFSOpsSupport::STORE) 144 { 145 kern_callback = &PreallocKFOpsRW; 146 } else if sys_support.contains(SysFSOpsSupport::SHOW) { 147 kern_callback = &PreallocKFOpsReadOnly; 148 } else if sys_support.contains(SysFSOpsSupport::STORE) { 149 kern_callback = &PreallocKFOpsWriteOnly; 150 } else { 151 kern_callback = &PreallocKFOpsEmpty; 152 } 153 154 let sys_priv = SysFSKernPrivateData::File(SysKernFilePriv::new(&kobj, Some(attr), None)); 155 let r = parent.add_file( 156 attr.name().to_string(), 157 mode.bitand(ModeType::from_bits_truncate(0o777)), 158 Some(4096), 159 Some(KernInodePrivateData::SysFS(sys_priv)), 160 Some(kern_callback), 161 ); 162 163 if let Err(e) = r { 164 if e == SystemError::EEXIST { 165 self.warn_duplicate(parent, attr.name()); 166 } 167 168 return Err(e); 169 } 170 return Ok(()); 171 } 172 173 /// 在sysfs中删除某个kobject的属性文件 174 /// 175 /// 如果属性文件不存在,则发出一个警告 176 /// 177 /// ## 参数 178 /// 179 /// - `kobj` 要删除属性文件的kobject 180 /// - `attr` 属性 181 pub fn remove_file(&self, kobj: &Arc<dyn KObject>, attr: &'static dyn Attribute) { 182 let parent = kobj.inode(); 183 184 if let Some(parent) = parent { 185 let r = parent.remove(attr.name()); 186 if unlikely(r.is_err()) { 187 kwarn!( 188 "failed to remove file '{}' from '{}'", 189 attr.name(), 190 kobj.name() 191 ); 192 } 193 } 194 } 195 196 /// 在sysfs中,为指定的kobject创建一个动态申请的bin属性文件 197 /// 198 /// ## 参数 199 /// 200 /// - `kobj` 要创建属性文件的kobject 201 /// - `attr` 属性 202 /// 203 /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/file.c#558 204 pub fn create_bin_file( 205 &self, 206 kobj: &Arc<dyn KObject>, 207 attr: &Arc<dyn BinAttribute>, 208 ) -> Result<(), SystemError> { 209 let inode = kobj.inode().ok_or(SystemError::EINVAL)?; 210 return self.add_bin_file_with_mode(&inode, attr, attr.mode()); 211 } 212 213 /// 在sysfs中删除某个kobject的bin属性文件 214 /// 215 /// 如果属性文件不存在,则发出一个警告 216 #[allow(dead_code)] 217 pub fn remove_bin_file(&self, kobj: &Arc<dyn KObject>, attr: &Arc<dyn BinAttribute>) { 218 let parent = kobj.inode(); 219 220 if let Some(parent) = parent { 221 let r = parent.remove(attr.name()); 222 if unlikely(r.is_err()) { 223 kwarn!( 224 "failed to remove file '{}' from '{}'", 225 attr.name(), 226 kobj.name() 227 ); 228 } 229 } 230 } 231 232 /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/file.c#304 233 pub(super) fn add_bin_file_with_mode( 234 &self, 235 parent: &Arc<KernFSInode>, 236 attr: &Arc<dyn BinAttribute>, 237 mode: ModeType, 238 ) -> Result<(), SystemError> { 239 let x = parent.private_data_mut(); 240 let kobj: Arc<dyn KObject>; 241 if let Some(KernInodePrivateData::SysFS(SysFSKernPrivateData::Dir(dt))) = x.as_ref() { 242 kobj = dt.kobj().unwrap(); 243 } else { 244 drop(x); 245 let path = self.kernfs_path(parent); 246 panic!("parent '{path}' is not a dir"); 247 } 248 drop(x); 249 250 let kern_callback: &'static dyn KernFSCallback; 251 let bin_support = attr.support_battr(); 252 253 if bin_support.contains(SysFSOpsSupport::READ) 254 && bin_support.contains(SysFSOpsSupport::WRITE) 255 { 256 kern_callback = &PreallocKFOpsRW; 257 } else if bin_support.contains(SysFSOpsSupport::READ) { 258 kern_callback = &PreallocKFOpsReadOnly; 259 } else if bin_support.contains(SysFSOpsSupport::WRITE) { 260 kern_callback = &PreallocKFOpsWriteOnly; 261 } else { 262 kern_callback = &PreallocKFOpsEmpty; 263 } 264 265 let sys_priv = 266 SysFSKernPrivateData::File(SysKernFilePriv::new(&kobj, None, Some(attr.clone()))); 267 let r = parent.add_file( 268 attr.name().to_string(), 269 mode.bitand(ModeType::from_bits_truncate(0o777)), 270 Some(attr.size()), 271 Some(KernInodePrivateData::SysFS(sys_priv)), 272 Some(kern_callback), 273 ); 274 275 if let Err(e) = r { 276 if e == SystemError::EEXIST { 277 self.warn_duplicate(parent, attr.name()); 278 } 279 280 return Err(e); 281 } 282 return Ok(()); 283 } 284 } 285 286 #[derive(Debug)] 287 struct PreallocKFOpsRW; 288 289 impl KernFSCallback for PreallocKFOpsRW { 290 fn open(&self, _data: KernCallbackData) -> Result<(), SystemError> { 291 return Ok(()); 292 } 293 294 fn read( 295 &self, 296 data: KernCallbackData, 297 buf: &mut [u8], 298 offset: usize, 299 ) -> Result<usize, SystemError> { 300 return data.callback_read(buf, offset); 301 } 302 303 fn write( 304 &self, 305 data: KernCallbackData, 306 buf: &[u8], 307 offset: usize, 308 ) -> Result<usize, SystemError> { 309 return data.callback_write(buf, offset); 310 } 311 312 #[inline] 313 fn poll(&self, _data: KernCallbackData) -> Result<PollStatus, SystemError> { 314 return Ok(PollStatus::READ | PollStatus::WRITE); 315 } 316 } 317 318 #[derive(Debug)] 319 struct PreallocKFOpsReadOnly; 320 321 impl KernFSCallback for PreallocKFOpsReadOnly { 322 fn open(&self, _data: KernCallbackData) -> Result<(), SystemError> { 323 return Ok(()); 324 } 325 326 fn read( 327 &self, 328 data: KernCallbackData, 329 buf: &mut [u8], 330 offset: usize, 331 ) -> Result<usize, SystemError> { 332 return data.callback_read(buf, offset); 333 } 334 335 fn write( 336 &self, 337 _data: KernCallbackData, 338 _buf: &[u8], 339 _offset: usize, 340 ) -> Result<usize, SystemError> { 341 return Err(SystemError::EPERM); 342 } 343 344 #[inline] 345 fn poll(&self, _data: KernCallbackData) -> Result<PollStatus, SystemError> { 346 return Ok(PollStatus::READ); 347 } 348 } 349 350 #[derive(Debug)] 351 struct PreallocKFOpsWriteOnly; 352 353 impl KernFSCallback for PreallocKFOpsWriteOnly { 354 fn open(&self, _data: KernCallbackData) -> Result<(), SystemError> { 355 return Ok(()); 356 } 357 358 fn read( 359 &self, 360 _data: KernCallbackData, 361 _buf: &mut [u8], 362 _offset: usize, 363 ) -> Result<usize, SystemError> { 364 return Err(SystemError::EPERM); 365 } 366 367 fn write( 368 &self, 369 data: KernCallbackData, 370 buf: &[u8], 371 offset: usize, 372 ) -> Result<usize, SystemError> { 373 return data.callback_write(buf, offset); 374 } 375 376 #[inline] 377 fn poll(&self, _data: KernCallbackData) -> Result<PollStatus, SystemError> { 378 return Ok(PollStatus::WRITE); 379 } 380 } 381 382 #[derive(Debug)] 383 struct PreallocKFOpsEmpty; 384 385 impl KernFSCallback for PreallocKFOpsEmpty { 386 fn open(&self, _data: KernCallbackData) -> Result<(), SystemError> { 387 return Ok(()); 388 } 389 390 fn read( 391 &self, 392 _data: KernCallbackData, 393 _buf: &mut [u8], 394 _offset: usize, 395 ) -> Result<usize, SystemError> { 396 return Err(SystemError::EPERM); 397 } 398 399 fn write( 400 &self, 401 _data: KernCallbackData, 402 _buf: &[u8], 403 _offset: usize, 404 ) -> Result<usize, SystemError> { 405 return Err(SystemError::EPERM); 406 } 407 408 #[inline] 409 fn poll(&self, _data: KernCallbackData) -> Result<PollStatus, SystemError> { 410 return Ok(PollStatus::empty()); 411 } 412 } 413 414 pub fn sysfs_emit_str(buf: &mut [u8], s: &str) -> Result<usize, SystemError> { 415 let len; 416 if buf.len() > s.len() { 417 len = s.len(); 418 } else { 419 len = buf.len() - 1; 420 } 421 buf[..len].copy_from_slice(&s.as_bytes()[..len]); 422 buf[len] = b'\0'; 423 return Ok(len); 424 } 425