xref: /DragonOS/kernel/src/filesystem/sysfs/file.rs (revision 06d5e247267cb65b84a80f219853ccd0f384b16e)
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