Skip to main content

proka_kernel/fs/fs_impl/
kernfs.rs

1extern crate alloc;
2use crate::drivers::Device;
3use crate::fs::vfs::{FileSystem, Inode, Metadata, VNodeType, VfsError};
4use alloc::{
5    boxed::Box,
6    collections::BTreeMap,
7    string::{String, ToString},
8    sync::Arc,
9    vec::Vec,
10};
11use core::any::Any;
12use spin::RwLock;
13
14pub type ReadCallback = Box<dyn Fn(u64, &mut [u8]) -> Result<usize, VfsError> + Send + Sync>;
15pub type WriteCallback = Box<dyn Fn(u64, &[u8]) -> Result<usize, VfsError> + Send + Sync>;
16
17pub enum KernNodeContent {
18    /// 目录
19    Dir(RwLock<BTreeMap<String, Arc<KernInode>>>),
20    /// 读写函数
21    File {
22        read: Option<ReadCallback>,
23        write: Option<WriteCallback>,
24        size: u64,
25    },
26    /// 设备映射
27    Device { device: Arc<Device> },
28}
29
30/// 内核文件系统节点
31pub struct KernInode {
32    node_type: VNodeType,
33    content: KernNodeContent,
34}
35
36impl core::fmt::Debug for KernInode {
37    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
38        f.debug_struct("KernInode")
39            .field("node_type", &self.node_type)
40            .finish()
41    }
42}
43
44impl KernInode {
45    /// 创建目录节点
46    pub fn new_dir() -> Arc<Self> {
47        Arc::new(Self {
48            node_type: VNodeType::Dir,
49            content: KernNodeContent::Dir(RwLock::new(BTreeMap::new())),
50        })
51    }
52
53    /// 创建文件节点
54    pub fn new_file(read: Option<ReadCallback>, write: Option<WriteCallback>) -> Arc<Self> {
55        Arc::new(Self {
56            node_type: VNodeType::File,
57            content: KernNodeContent::File {
58                read,
59                write,
60                size: 0,
61            },
62        })
63    }
64    /// 创建设备节点
65    pub fn new_device(device: Arc<Device>) -> Arc<Self> {
66        Arc::new(Self {
67            node_type: VNodeType::Device,
68            content: KernNodeContent::Device { device },
69        })
70    }
71
72    /// 添加子节点(仅目录节点可用)
73    pub fn add_child(&self, name: &str, child: Arc<KernInode>) -> Result<(), VfsError> {
74        match &self.content {
75            KernNodeContent::Dir(entries) => {
76                let mut map = entries.write();
77                if map.contains_key(name) {
78                    return Err(VfsError::AlreadyExists);
79                }
80                map.insert(name.to_string(), child);
81                Ok(())
82            }
83            _ => Err(VfsError::NotADirectory),
84        }
85    }
86}
87
88impl Inode for KernInode {
89    fn metadata(&self) -> Result<Metadata, VfsError> {
90        let size = match &self.content {
91            KernNodeContent::File { size, .. } => *size,
92            _ => 0,
93        };
94        Ok(Metadata {
95            size,
96            permissions: 0o755,
97            uid: 0,
98            gid: 0,
99            ctime: 0,
100            mtime: 0,
101            blocks: 0,
102            nlinks: 1,
103        })
104    }
105
106    fn set_metadata(&self, _metadata: &Metadata) -> Result<(), VfsError> {
107        Err(VfsError::NotImplemented)
108    }
109
110    fn node_type(&self) -> VNodeType {
111        self.node_type
112    }
113
114    fn read_at(&self, offset: u64, buf: &mut [u8]) -> Result<usize, VfsError> {
115        match &self.content {
116            KernNodeContent::File { read, .. } => {
117                if let Some(cb) = read {
118                    cb(offset, buf)
119                } else {
120                    Err(VfsError::PermissionDenied)
121                }
122            }
123            KernNodeContent::Device { device } => {
124                if let Some(char_dev) = device.as_char_device() {
125                    char_dev.read(buf).map_err(VfsError::DeviceError)
126                } else {
127                    Err(VfsError::NotImplemented)
128                }
129            }
130            _ => Err(VfsError::NotAFile),
131        }
132    }
133
134    fn write_at(&self, offset: u64, buf: &[u8]) -> Result<usize, VfsError> {
135        match &self.content {
136            KernNodeContent::File { write, .. } => {
137                if let Some(cb) = write {
138                    cb(offset, buf)
139                } else {
140                    Err(VfsError::PermissionDenied)
141                }
142            }
143            KernNodeContent::Device { device } => {
144                if let Some(char_dev) = device.as_char_device() {
145                    char_dev.write(buf).map_err(VfsError::DeviceError)
146                } else {
147                    Err(VfsError::NotImplemented)
148                }
149            }
150            _ => Err(VfsError::NotAFile),
151        }
152    }
153
154    fn truncate(&self, _size: u64) -> Result<(), VfsError> {
155        Err(VfsError::NotImplemented)
156    }
157
158    fn sync(&self) -> Result<(), VfsError> {
159        Ok(())
160    }
161
162    fn lookup(&self, name: &str) -> Result<Arc<dyn Inode>, VfsError> {
163        match &self.content {
164            KernNodeContent::Dir(entries) => entries
165                .read()
166                .get(name)
167                .cloned()
168                .map(|n| n as Arc<dyn Inode>)
169                .ok_or(VfsError::NotFound),
170            _ => Err(VfsError::NotADirectory),
171        }
172    }
173
174    fn create(&self, name: &str, typ: VNodeType) -> Result<Arc<dyn Inode>, VfsError> {
175        match &self.content {
176            KernNodeContent::Dir(entries) => {
177                let mut map = entries.write();
178                if map.contains_key(name) {
179                    return Err(VfsError::AlreadyExists);
180                }
181
182                let new_inode = match typ {
183                    VNodeType::Dir => KernInode::new_dir(),
184                    VNodeType::File => KernInode::new_file(None, None),
185                    _ => return Err(VfsError::NotImplemented),
186                };
187
188                map.insert(name.to_string(), new_inode.clone());
189                Ok(new_inode)
190            }
191            _ => Err(VfsError::NotADirectory),
192        }
193    }
194
195    fn create_device(&self, name: &str, device: Arc<Device>) -> Result<Arc<dyn Inode>, VfsError> {
196        match &self.content {
197            KernNodeContent::Dir(entries) => {
198                let mut map = entries.write();
199                if map.contains_key(name) {
200                    return Err(VfsError::AlreadyExists);
201                }
202
203                let new_inode = KernInode::new_device(device);
204                map.insert(name.to_string(), new_inode.clone());
205                Ok(new_inode)
206            }
207            _ => Err(VfsError::NotADirectory),
208        }
209    }
210
211    fn unlink(&self, name: &str) -> Result<(), VfsError> {
212        match &self.content {
213            KernNodeContent::Dir(entries) => {
214                let mut map = entries.write();
215                if map.remove(name).is_some() {
216                    Ok(())
217                } else {
218                    Err(VfsError::NotFound)
219                }
220            }
221            _ => Err(VfsError::NotADirectory),
222        }
223    }
224
225    fn list(&self) -> Result<Vec<String>, VfsError> {
226        match &self.content {
227            KernNodeContent::Dir(entries) => Ok(entries.read().keys().cloned().collect()),
228            _ => Err(VfsError::NotADirectory),
229        }
230    }
231
232    fn as_any(&self) -> &dyn Any {
233        self
234    }
235}
236
237pub struct KernFs {
238    root: Arc<KernInode>,
239}
240
241impl Default for KernFs {
242    fn default() -> Self {
243        let root = KernInode::new_dir();
244
245        Self { root }
246    }
247}
248
249impl KernFs {
250    pub fn new() -> Self {
251        Self::default()
252    }
253
254    pub fn root(&self) -> Arc<KernInode> {
255        self.root.clone()
256    }
257}
258
259impl FileSystem for KernFs {
260    fn mount(
261        &self,
262        _device: Option<Arc<Device>>,
263        _args: Option<&[&str]>,
264    ) -> Result<Arc<dyn Inode>, VfsError> {
265        Ok(self.root.clone())
266    }
267
268    fn fs_type(&self) -> &'static str {
269        "kernfs"
270    }
271}
272
273#[cfg(test)]
274mod tests {
275    use super::*;
276    use alloc::vec;
277
278    #[test_case]
279    fn test_mount_creates_root() {
280        let kernfs = KernFs::new();
281        let root = kernfs.mount(None, None).unwrap();
282        assert_eq!(root.node_type(), VNodeType::Dir);
283    }
284
285    #[test_case]
286    fn test_create_file() {
287        let kernfs = KernFs::new();
288        let root = kernfs.mount(None, None).unwrap();
289        let file_inode = root.create("test_file", VNodeType::File).unwrap();
290        assert_eq!(file_inode.node_type(), VNodeType::File);
291    }
292
293    #[test_case]
294    fn test_add_child_and_lookup() {
295        let root = KernInode::new_dir();
296        let child_dir = KernInode::new_dir();
297        root.add_child("child_dir", child_dir.clone()).unwrap();
298
299        let looked_up_child = root.lookup("child_dir").unwrap();
300        assert_eq!(looked_up_child.node_type(), VNodeType::Dir);
301
302        // Test adding an existing child
303        assert_eq!(
304            root.add_child("child_dir", child_dir.clone()).unwrap_err(),
305            VfsError::AlreadyExists
306        );
307    }
308
309    #[test_case]
310    fn test_create_and_lookup_file() {
311        let root = KernInode::new_dir();
312        let file = root.create("test_file", VNodeType::File).unwrap();
313        assert_eq!(file.node_type(), VNodeType::File);
314
315        let looked_up_file = root.lookup("test_file").unwrap();
316        assert_eq!(looked_up_file.node_type(), VNodeType::File);
317    }
318
319    #[test_case]
320    fn test_unlink() {
321        let root = KernInode::new_dir();
322        root.create("file_to_unlink", VNodeType::File).unwrap();
323        root.unlink("file_to_unlink").unwrap();
324        assert_eq!(
325            root.lookup("file_to_unlink").unwrap_err(),
326            VfsError::NotFound
327        );
328    }
329
330    #[test_case]
331    fn test_list_directory() {
332        let root = KernInode::new_dir();
333        root.create("file1", VNodeType::File).unwrap();
334        root.create("dir1", VNodeType::Dir).unwrap();
335
336        let mut entries = root.list().unwrap();
337        entries.sort(); // Sort to ensure consistent order
338        assert_eq!(entries, vec!["dir1".to_string(), "file1".to_string()]);
339    }
340
341    #[test_case]
342    fn test_file_read_write() {
343        let file_content = Arc::new(RwLock::new(Vec::<u8>::new()));
344        let content_for_read = file_content.clone();
345        let read_callback: ReadCallback = Box::new(move |offset, buf| {
346            let data = content_for_read.read();
347            let end = (offset + buf.len() as u64).min(data.len() as u64);
348            let start = offset.min(data.len() as u64);
349            let bytes_to_read = (end - start) as usize;
350            buf[..bytes_to_read].copy_from_slice(&data[start as usize..end as usize]);
351            Ok(bytes_to_read)
352        });
353
354        let content_for_write = file_content.clone();
355        let write_callback: WriteCallback = Box::new(move |offset, buf| {
356            let mut data = content_for_write.write();
357            if offset + buf.len() as u64 > data.len() as u64 {
358                data.resize((offset + buf.len() as u64) as usize, 0);
359            }
360            data[offset as usize..(offset + buf.len() as u64) as usize].copy_from_slice(buf);
361            Ok(buf.len())
362        });
363
364        let file_inode = KernInode::new_file(Some(read_callback), Some(write_callback));
365
366        // Write some data
367        let write_data = b"hello world";
368        file_inode.write_at(0, write_data).unwrap();
369
370        // Read the data back
371        let mut read_buffer = vec![0; write_data.len()];
372        file_inode.read_at(0, &mut read_buffer).unwrap();
373        assert_eq!(read_buffer, write_data);
374
375        // Test partial read
376        let mut partial_read_buffer = vec![0; 5];
377        file_inode.read_at(0, &mut partial_read_buffer).unwrap();
378        assert_eq!(partial_read_buffer, b"hello");
379
380        file_inode.read_at(6, &mut partial_read_buffer).unwrap();
381        assert_eq!(partial_read_buffer, b"world");
382
383        // Test writing with offset
384        file_inode.write_at(6, b"rust").unwrap();
385        let mut full_read_buffer = vec![0; 10];
386        file_inode.read_at(0, &mut full_read_buffer).unwrap();
387        assert_eq!(full_read_buffer, b"hello rust");
388
389        // Test no read/write permissions
390        let no_perm_file = KernInode::new_file(None, None);
391        assert_eq!(
392            no_perm_file.read_at(0, &mut [0]).unwrap_err(),
393            VfsError::PermissionDenied
394        );
395        assert_eq!(
396            no_perm_file.write_at(0, &[0]).unwrap_err(),
397            VfsError::PermissionDenied
398        );
399    }
400
401    #[test_case]
402    fn test_error_scenarios() {
403        let root = KernInode::new_dir();
404        let file_inode = KernInode::new_file(None, None);
405
406        // NotADirectory errors
407        assert_eq!(
408            file_inode
409                .add_child("child", KernInode::new_dir())
410                .unwrap_err(),
411            VfsError::NotADirectory
412        );
413        assert_eq!(
414            file_inode.lookup("child").unwrap_err(),
415            VfsError::NotADirectory
416        );
417        assert_eq!(
418            file_inode.create("child", VNodeType::File).unwrap_err(),
419            VfsError::NotADirectory
420        );
421        assert_eq!(
422            file_inode
423                .create_device("child", Arc::new(Device::null()))
424                .unwrap_err(),
425            VfsError::NotADirectory
426        );
427        assert_eq!(
428            file_inode.unlink("child").unwrap_err(),
429            VfsError::NotADirectory
430        );
431        assert_eq!(file_inode.list().unwrap_err(), VfsError::NotADirectory);
432
433        // NotAFile errors
434        assert_eq!(root.read_at(0, &mut [0]).unwrap_err(), VfsError::NotAFile);
435        assert_eq!(root.write_at(0, &[0]).unwrap_err(), VfsError::NotAFile);
436
437        // NotFound errors (already covered by test_unlink and test_lookup for non-existent entry)
438        // AlreadyExists errors (already covered by test_add_child_and_lookup and create/create_device for existing entry)
439        // PermissionDenied errors (already covered by test_file_read_write for file without callbacks)
440
441        // Test create with unsupported VNodeType
442        assert_eq!(
443            root.create("symlink", VNodeType::SymLink).unwrap_err(),
444            VfsError::NotImplemented
445        );
446
447        // Test set_metadata (always NotImplemented)
448        assert_eq!(
449            root.set_metadata(&Metadata::default()).unwrap_err(),
450            VfsError::NotImplemented
451        );
452        // Test truncate (always NotImplemented)
453        assert_eq!(
454            file_inode.truncate(0).unwrap_err(),
455            VfsError::NotImplemented
456        );
457    }
458
459    // Mock Device and CharDevice for testing
460    struct MockCharDevice {
461        data: RwLock<Vec<u8>>,
462        name: String,
463    }
464
465    impl crate::drivers::SharedDeviceOps for MockCharDevice {
466        fn name(&self) -> &str {
467            &self.name
468        }
469        fn device_type(&self) -> crate::drivers::DeviceType {
470            crate::drivers::DeviceType::Char
471        }
472        fn open(&self) -> Result<(), crate::drivers::DeviceError> {
473            Ok(())
474        }
475        fn close(&self) -> Result<(), crate::drivers::DeviceError> {
476            Ok(())
477        }
478        fn ioctl(&self, _cmd: u64, _arg: u64) -> Result<u64, crate::drivers::DeviceError> {
479            Err(crate::drivers::DeviceError::NotSupported)
480        }
481    }
482
483    impl crate::drivers::CharDevice for MockCharDevice {
484        fn read(&self, buf: &mut [u8]) -> Result<usize, crate::drivers::DeviceError> {
485            let mut data = self.data.write();
486            let bytes_to_read = buf.len().min(data.len());
487            buf[..bytes_to_read].copy_from_slice(&data[..bytes_to_read]);
488            data.drain(..bytes_to_read);
489            Ok(bytes_to_read)
490        }
491
492        fn write(&self, buf: &[u8]) -> Result<usize, crate::drivers::DeviceError> {
493            self.data.write().extend_from_slice(buf);
494            Ok(buf.len())
495        }
496    }
497
498    impl MockCharDevice {
499        fn new(name: &str, initial_data: &[u8]) -> Arc<Self> {
500            Arc::new(Self {
501                data: RwLock::new(initial_data.to_vec()),
502                name: name.to_string(),
503            })
504        }
505    }
506
507    // Mock BlockDevice for testing
508    struct MockBlockDevice {
509        name: String,
510        block_size: usize,
511        num_blocks: usize,
512        data: RwLock<Vec<u8>>,
513    }
514
515    impl crate::drivers::SharedDeviceOps for MockBlockDevice {
516        fn name(&self) -> &str {
517            &self.name
518        }
519        fn device_type(&self) -> crate::drivers::DeviceType {
520            crate::drivers::DeviceType::Block
521        }
522        fn open(&self) -> Result<(), crate::drivers::DeviceError> {
523            Ok(())
524        }
525        fn close(&self) -> Result<(), crate::drivers::DeviceError> {
526            Ok(())
527        }
528        fn ioctl(&self, _cmd: u64, _arg: u64) -> Result<u64, crate::drivers::DeviceError> {
529            Err(crate::drivers::DeviceError::NotSupported)
530        }
531    }
532
533    impl crate::drivers::BlockDevice for MockBlockDevice {
534        fn block_size(&self) -> usize {
535            self.block_size
536        }
537        fn num_blocks(&self) -> usize {
538            self.num_blocks
539        }
540
541        fn read_blocks(
542            &self,
543            block_idx: usize,
544            num_blocks: usize,
545            buf: &mut [u8],
546        ) -> Result<usize, crate::drivers::DeviceError> {
547            let start_byte = block_idx * self.block_size;
548            let end_byte = (block_idx + num_blocks) * self.block_size;
549            let data = self.data.read();
550
551            if start_byte >= data.len() {
552                return Ok(0);
553            }
554            let bytes_to_read = buf
555                .len()
556                .min(data.len() - start_byte)
557                .min(end_byte - start_byte);
558            buf[..bytes_to_read].copy_from_slice(&data[start_byte..(start_byte + bytes_to_read)]);
559            Ok(bytes_to_read)
560        }
561
562        fn write_blocks(
563            &self,
564            block_idx: usize,
565            num_blocks: usize,
566            buf: &[u8],
567        ) -> Result<usize, crate::drivers::DeviceError> {
568            let start_byte = block_idx * self.block_size;
569            let end_byte = (block_idx + num_blocks) * self.block_size;
570            let mut data = self.data.write();
571
572            if end_byte > data.len() {
573                data.resize(end_byte, 0);
574            }
575            let bytes_to_write = buf.len().min(end_byte - start_byte);
576            data[start_byte..(start_byte + bytes_to_write)]
577                .copy_from_slice(buf[..bytes_to_write].as_ref());
578            Ok(bytes_to_write)
579        }
580    }
581
582    impl MockBlockDevice {
583        fn new(name: &str, block_size: usize, num_blocks: usize, initial_data: &[u8]) -> Arc<Self> {
584            let mut data = initial_data.to_vec();
585            data.resize(block_size * num_blocks, 0);
586            Arc::new(Self {
587                name: name.to_string(),
588                block_size,
589                num_blocks,
590                data: RwLock::new(data),
591            })
592        }
593    }
594
595    #[test_case]
596    fn test_device_node_read_write() {
597        let root = KernInode::new_dir();
598        let mock_char_device = MockCharDevice::new("test_char_dev", b"device_data");
599        let char_device_arc = Arc::new(crate::drivers::Device::new_auto_assign(
600            "test_char_dev".to_string(),
601            crate::drivers::DeviceInner::Char(mock_char_device.clone()),
602        ));
603
604        let device_inode = root
605            .create_device("test_device", char_device_arc.clone())
606            .unwrap();
607        assert_eq!(device_inode.node_type(), VNodeType::Device);
608
609        // Read from char device
610        let mut read_buffer = vec![0; 5];
611        device_inode.read_at(0, &mut read_buffer).unwrap();
612        assert_eq!(read_buffer, b"devic"); // Wait, original was "device_data", first 5 bytes are "devic"
613
614        // Write to char device
615        let write_mock_device = MockCharDevice::new("write_char_dev", b"");
616        let write_device_arc = Arc::new(crate::drivers::Device::new_auto_assign(
617            "write_char_dev".to_string(),
618            crate::drivers::DeviceInner::Char(write_mock_device.clone()),
619        ));
620        let write_device_inode = root
621            .create_device("write_test_device", write_device_arc)
622            .unwrap();
623
624        write_device_inode.write_at(0, b"write_test").unwrap();
625        let mut fresh_read_buffer = vec![0; 10];
626        write_device_inode
627            .read_at(0, &mut fresh_read_buffer)
628            .unwrap();
629        assert_eq!(fresh_read_buffer, b"write_test");
630
631        // Test error when not a char device
632        let mock_block_device =
633            MockBlockDevice::new("test_block_dev", 512, 10, b"initial_block_data");
634        let block_device_arc = Arc::new(crate::drivers::Device::new_auto_assign(
635            "test_block_dev".to_string(),
636            crate::drivers::DeviceInner::Block(mock_block_device.clone()),
637        ));
638        let block_device_inode = root.create_device("block_dev", block_device_arc).unwrap();
639        assert_eq!(
640            block_device_inode.read_at(0, &mut [0]).unwrap_err(),
641            VfsError::NotImplemented
642        );
643
644        // Test null device
645        let null_device_arc = Arc::new(crate::drivers::Device::null());
646        let null_inode = root
647            .create_device("null_device_node", null_device_arc)
648            .unwrap();
649        let mut null_read_buf = [0; 10];
650        assert_eq!(null_inode.read_at(0, &mut null_read_buf).unwrap(), 0);
651        assert_eq!(null_inode.write_at(0, b"data").unwrap(), 4);
652    }
653}