From 6e6b33f6fcf23043077b682b4564ecdc90443e5e Mon Sep 17 00:00:00 2001 From: WangRunji Date: Wed, 20 Feb 2019 17:03:24 +0800 Subject: [PATCH] rename FileInfo to Metadata. complete FsInfo --- Cargo.toml | 7 ++++++ rcore-fs-fuse/src/lib.rs | 29 ++++++++++++++-------- rcore-fs-sefs/src/lib.rs | 43 +++++++++++++++++++------------- rcore-fs-sfs/src/bin/mksfs.rs | 9 ++++--- rcore-fs-sfs/src/lib.rs | 43 +++++++++++++++++++------------- rcore-fs/src/file.rs | 6 ++--- rcore-fs/src/tests.rs | 2 +- rcore-fs/src/vfs.rs | 46 ++++++++++++++++++++++++++++------- 8 files changed, 125 insertions(+), 60 deletions(-) create mode 100644 Cargo.toml diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..f71ba8b --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[workspace] +members = [ + "rcore-fs", + "rcore-fs-sfs", + "rcore-fs-sefs", + "rcore-fs-fuse" +] \ No newline at end of file diff --git a/rcore-fs-fuse/src/lib.rs b/rcore-fs-fuse/src/lib.rs index d3267f9..b7f1a0f 100644 --- a/rcore-fs-fuse/src/lib.rs +++ b/rcore-fs-fuse/src/lib.rs @@ -1,4 +1,4 @@ -use fuse::{FileAttr, Filesystem, FileType, ReplyAttr, ReplyData, ReplyDirectory, ReplyEmpty, ReplyEntry, ReplyWrite, Request}; +use fuse::{FileAttr, Filesystem, FileType, ReplyAttr, ReplyData, ReplyDirectory, ReplyEmpty, ReplyEntry, ReplyWrite, ReplyStatfs, Request}; use rcore_fs::vfs; use std::collections::btree_map::BTreeMap; use std::ffi::OsStr; @@ -25,7 +25,7 @@ impl VfsFuse { nsec: time.nsec, } } - fn trans_attr(info: vfs::FileInfo) -> FileAttr { + fn trans_attr(info: vfs::Metadata) -> FileAttr { FileAttr { ino: info.inode as u64, size: info.size as u64, @@ -50,6 +50,8 @@ impl VfsFuse { vfs::FileType::SymLink => FileType::Symlink, vfs::FileType::CharDevice => FileType::CharDevice, vfs::FileType::BlockDevice => FileType::BlockDevice, + vfs::FileType::NamedPipe => FileType::NamedPipe, + vfs::FileType::Socket => FileType::Socket, } } fn trans_error(err: vfs::FsError) -> i32 { @@ -96,7 +98,7 @@ impl Filesystem for VfsFuse { fn lookup(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEntry) { let inode = try_vfs!(reply, self.get_inode(parent)); let target = try_vfs!(reply, inode.lookup(name.to_str().unwrap())); - let info = try_vfs!(reply, target.info()); + let info = try_vfs!(reply, target.metadata()); self.inodes.insert(info.inode, target); let attr = Self::trans_attr(info); reply.entry(&TTL, &attr, 0); @@ -104,7 +106,7 @@ impl Filesystem for VfsFuse { fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) { let inode = try_vfs!(reply, self.get_inode(ino)); - let info = try_vfs!(reply, inode.info()); + let info = try_vfs!(reply, inode.metadata()); let attr = Self::trans_attr(info); reply.attr(&TTL, &attr); } @@ -113,7 +115,7 @@ impl Filesystem for VfsFuse { let name = name.to_str().unwrap(); let inode = try_vfs!(reply, self.get_inode(parent)); let target = try_vfs!(reply, inode.create(name, vfs::FileType::File, mode)); - let info = try_vfs!(reply, target.info()); + let info = try_vfs!(reply, target.metadata()); self.inodes.insert(info.inode, target); let attr = Self::trans_attr(info); reply.entry(&TTL, &attr, 0); @@ -123,7 +125,7 @@ impl Filesystem for VfsFuse { let name = name.to_str().unwrap(); let inode = try_vfs!(reply, self.get_inode(parent)); let target = try_vfs!(reply, inode.create(name, vfs::FileType::Dir, mode)); - let info = try_vfs!(reply, target.info()); + let info = try_vfs!(reply, target.metadata()); let attr = Self::trans_attr(info); reply.entry(&TTL, &attr, 0); } @@ -158,7 +160,7 @@ impl Filesystem for VfsFuse { let inode = try_vfs!(reply, self.get_inode(ino)); let newparent = try_vfs!(reply, self.get_inode(newparent)); try_vfs!(reply, newparent.link(newname, inode)); - let info = try_vfs!(reply, inode.info()); + let info = try_vfs!(reply, inode.metadata()); let attr = Self::trans_attr(info); reply.entry(&TTL, &attr, 0); } @@ -173,7 +175,7 @@ impl Filesystem for VfsFuse { fn write(&mut self, _req: &Request, ino: u64, _fh: u64, offset: i64, data: &[u8], _flags: u32, reply: ReplyWrite) { let inode = try_vfs!(reply, self.get_inode(ino)); - let info = try_vfs!(reply, inode.info()); + let info = try_vfs!(reply, inode.metadata()); let end = offset as usize + data.len(); if end > info.size { try_vfs!(reply, inode.resize(end)); @@ -196,12 +198,12 @@ impl Filesystem for VfsFuse { fn readdir(&mut self, _req: &Request, ino: u64, _fh: u64, offset: i64, mut reply: ReplyDirectory) { let inode = try_vfs!(reply, self.get_inode(ino)); - let info = try_vfs!(reply, inode.info()); + let info = try_vfs!(reply, inode.metadata()); let count = info.size; for i in offset as usize..count { let name = inode.get_entry(i).unwrap(); let inode = try_vfs!(reply, inode.find(name.as_str())); - let info = try_vfs!(reply, inode.info()); + let info = try_vfs!(reply, inode.metadata()); let kind = Self::trans_type(info.type_); let full = reply.add(info.inode as u64, i as i64 + 1, kind, name); if full { @@ -210,4 +212,11 @@ impl Filesystem for VfsFuse { } reply.ok(); } + + fn statfs(&mut self, _req: &Request, _ino: u64, reply: ReplyStatfs) { + let info = self.fs.info(); + reply.statfs(info.blocks as u64, info.bfree as u64, info.bavail as u64, + info.files as u64, info.ffree as u64, info.bsize as u32, + info.namemax as u32, info.frsize as u32); + } } diff --git a/rcore-fs-sefs/src/lib.rs b/rcore-fs-sefs/src/lib.rs index 6004d54..2e30ee6 100644 --- a/rcore-fs-sefs/src/lib.rs +++ b/rcore-fs-sefs/src/lib.rs @@ -143,9 +143,10 @@ impl vfs::INode for INodeImpl { Ok(len) } /// the size returned here is logical size(entry num for directory), not the disk space used. - fn info(&self) -> vfs::Result { + fn metadata(&self) -> vfs::Result { let disk_inode = self.disk_inode.read(); - Ok(vfs::FileInfo { + Ok(vfs::Metadata { + dev: 0, inode: self.id, size: match disk_inode.type_ { FileType::File => disk_inode.size as usize, @@ -161,6 +162,7 @@ impl vfs::INode for INodeImpl { nlinks: disk_inode.nlinks as usize, uid: disk_inode.uid as usize, gid: disk_inode.gid as usize, + blk_size: 0x1000, }) } fn sync(&self) -> vfs::Result<()> { @@ -185,7 +187,7 @@ impl vfs::INode for INodeImpl { vfs::FileType::Dir => FileType::Dir, _ => return Err(vfs::FsError::InvalidParam), }; - let info = self.info()?; + let info = self.metadata()?; if info.type_ != vfs::FileType::Dir { return Err(FsError::NotDir); } @@ -219,7 +221,7 @@ impl vfs::INode for INodeImpl { Ok(inode) } fn unlink(&self, name: &str) -> vfs::Result<()> { - let info = self.info()?; + let info = self.metadata()?; if info.type_ != vfs::FileType::Dir { return Err(FsError::NotDir) } @@ -254,7 +256,7 @@ impl vfs::INode for INodeImpl { Ok(()) } fn link(&self, name: &str, other: &Arc) -> vfs::Result<()> { - let info = self.info()?; + let info = self.metadata()?; if info.type_ != vfs::FileType::Dir { return Err(FsError::NotDir) } @@ -268,7 +270,7 @@ impl vfs::INode for INodeImpl { if !Arc::ptr_eq(&self.fs, &child.fs) { return Err(FsError::NotSameFs); } - if child.info()?.type_ == vfs::FileType::Dir { + if child.metadata()?.type_ == vfs::FileType::Dir { return Err(FsError::IsDir); } let entry = DiskEntry { @@ -280,7 +282,7 @@ impl vfs::INode for INodeImpl { Ok(()) } fn rename(&self, old_name: &str, new_name: &str) -> vfs::Result<()> { - let info = self.info()?; + let info = self.metadata()?; if info.type_ != vfs::FileType::Dir { return Err(FsError::NotDir) } @@ -311,7 +313,7 @@ impl vfs::INode for INodeImpl { Ok(()) } fn move_(&self, old_name: &str, target: &Arc, new_name: &str) -> vfs::Result<()> { - let info = self.info()?; + let info = self.metadata()?; if info.type_ != vfs::FileType::Dir { return Err(FsError::NotDir) } @@ -329,10 +331,10 @@ impl vfs::INode for INodeImpl { if !Arc::ptr_eq(&self.fs, &dest.fs) { return Err(FsError::NotSameFs); } - if dest.info()?.type_ != vfs::FileType::Dir { + if dest.metadata()?.type_ != vfs::FileType::Dir { return Err(FsError::NotDir) } - if dest.info()?.nlinks <= 0 { + if dest.metadata()?.nlinks <= 0 { return Err(FsError::DirRemoved) } @@ -350,7 +352,7 @@ impl vfs::INode for INodeImpl { dest.dirent_append(&entry)?; self.dirent_remove(entry_id)?; - if inode.info()?.type_ == vfs::FileType::Dir { + if inode.metadata()?.type_ == vfs::FileType::Dir { self.nlinks_dec(); dest.nlinks_inc(); } @@ -358,7 +360,7 @@ impl vfs::INode for INodeImpl { Ok(()) } fn find(&self, name: &str) -> vfs::Result> { - let info = self.info()?; + let info = self.metadata()?; if info.type_ != vfs::FileType::Dir { return Err(FsError::NotDir) } @@ -593,11 +595,18 @@ impl vfs::FileSystem for SEFS { self.get_inode(BLKN_ROOT) } - fn info(&self) -> &'static vfs::FsInfo { - static INFO: vfs::FsInfo = vfs::FsInfo { - max_file_size: MAX_FILE_SIZE, - }; - &INFO + fn info(&self) -> vfs::FsInfo { + let sb = self.super_block.read(); + vfs::FsInfo { + bsize: BLKSIZE, + frsize: BLKSIZE, + blocks: sb.blocks as usize, + bfree: sb.unused_blocks as usize, + bavail: sb.unused_blocks as usize, + files: sb.blocks as usize, // inaccurate + ffree: sb.unused_blocks as usize, // inaccurate + namemax: MAX_FNAME_LEN, + } } } diff --git a/rcore-fs-sfs/src/bin/mksfs.rs b/rcore-fs-sfs/src/bin/mksfs.rs index 60f7bd5..3ad633e 100644 --- a/rcore-fs-sfs/src/bin/mksfs.rs +++ b/rcore-fs-sfs/src/bin/mksfs.rs @@ -8,6 +8,8 @@ use std::sync::{Arc, Mutex}; use rcore_fs::vfs::*; use rcore_fs_sfs::SimpleFileSystem; +const DEFAULT_MODE: u32 = 0o664; + fn main() -> Result<()> { let args: Vec<_> = env::args().collect(); let cmd = &args[1]; @@ -41,7 +43,7 @@ fn zip_dir(path: &Path, inode: Arc) -> Result<()> { let name = name_.to_str().unwrap(); let type_ = entry.file_type()?; if type_.is_file() { - let inode = inode.create(name, FileType::File).expect("Failed to create INode"); + let inode = inode.create(name, FileType::File, DEFAULT_MODE).expect("Failed to create INode"); let mut file = fs::File::open(entry.path())?; inode.resize(file.metadata().unwrap().len() as usize).expect("Failed to resize INode"); let mut buf: [u8; 4096] = unsafe { uninitialized() }; @@ -53,7 +55,7 @@ fn zip_dir(path: &Path, inode: Arc) -> Result<()> { offset += len; } } else if type_.is_dir() { - let inode = inode.create(name, FileType::Dir).expect("Failed to create INode"); + let inode = inode.create(name, FileType::Dir, DEFAULT_MODE).expect("Failed to create INode"); zip_dir(entry.path().as_path(), inode)?; } } @@ -75,7 +77,7 @@ fn unzip_dir(path: &Path, inode: Arc) -> Result<()> { let inode = inode.lookup(name.as_str()).expect("Failed to lookup"); let mut path = path.to_path_buf(); path.push(name); - let info = inode.info().expect("Failed to get file info"); + let info = inode.metadata().expect("Failed to get file info"); match info.type_ { FileType::File => { let mut file = fs::File::create(&path)?; @@ -92,6 +94,7 @@ fn unzip_dir(path: &Path, inode: Arc) -> Result<()> { fs::create_dir(&path)?; unzip_dir(path.as_path(), inode)?; } + _ => panic!("unsupported file type"), } } Ok(()) diff --git a/rcore-fs-sfs/src/lib.rs b/rcore-fs-sfs/src/lib.rs index 7880884..dcfe424 100644 --- a/rcore-fs-sfs/src/lib.rs +++ b/rcore-fs-sfs/src/lib.rs @@ -276,9 +276,10 @@ impl vfs::INode for INodeImpl { self._write_at(offset, buf) } /// the size returned here is logical size(entry num for directory), not the disk space used. - fn info(&self) -> vfs::Result { + fn metadata(&self) -> vfs::Result { let disk_inode = self.disk_inode.read(); - Ok(vfs::FileInfo { + Ok(vfs::Metadata { + dev: 0, inode: self.id, size: match disk_inode.type_ { FileType::File => disk_inode.size as usize, @@ -294,6 +295,7 @@ impl vfs::INode for INodeImpl { nlinks: disk_inode.nlinks as usize, uid: 0, gid: 0, + blk_size: BLKSIZE, }) } fn sync(&self) -> vfs::Result<()> { @@ -311,7 +313,7 @@ impl vfs::INode for INodeImpl { self._resize(len) } fn create(&self, name: &str, type_: vfs::FileType, _mode: u32) -> vfs::Result> { - let info = self.info()?; + let info = self.metadata()?; if info.type_!=vfs::FileType::Dir { return Err(FsError::NotDir); } @@ -348,7 +350,7 @@ impl vfs::INode for INodeImpl { Ok(inode) } fn unlink(&self, name: &str) -> vfs::Result<()> { - let info = self.info()?; + let info = self.metadata()?; if info.type_!=vfs::FileType::Dir { return Err(FsError::NotDir) } @@ -383,7 +385,7 @@ impl vfs::INode for INodeImpl { Ok(()) } fn link(&self, name: &str, other: &Arc) -> vfs::Result<()> { - let info = self.info()?; + let info = self.metadata()?; if info.type_!=vfs::FileType::Dir { return Err(FsError::NotDir) } @@ -397,7 +399,7 @@ impl vfs::INode for INodeImpl { if !Arc::ptr_eq(&self.fs, &child.fs) { return Err(FsError::NotSameFs); } - if child.info()?.type_ == vfs::FileType::Dir { + if child.metadata()?.type_ == vfs::FileType::Dir { return Err(FsError::IsDir); } let entry = DiskEntry { @@ -411,7 +413,7 @@ impl vfs::INode for INodeImpl { Ok(()) } fn rename(&self, old_name: &str, new_name: &str) -> vfs::Result<()> { - let info = self.info()?; + let info = self.metadata()?; if info.type_!=vfs::FileType::Dir { return Err(FsError::NotDir) } @@ -441,7 +443,7 @@ impl vfs::INode for INodeImpl { Ok(()) } fn move_(&self, old_name: &str, target: &Arc, new_name: &str) -> vfs::Result<()> { - let info = self.info()?; + let info = self.metadata()?; if info.type_!=vfs::FileType::Dir { return Err(FsError::NotDir) } @@ -459,10 +461,10 @@ impl vfs::INode for INodeImpl { if !Arc::ptr_eq(&self.fs, &dest.fs) { return Err(FsError::NotSameFs); } - if dest.info()?.type_ != vfs::FileType::Dir { + if dest.metadata()?.type_ != vfs::FileType::Dir { return Err(FsError::NotDir) } - if dest.info()?.nlinks <= 0 { + if dest.metadata()?.nlinks <= 0 { return Err(FsError::DirRemoved) } @@ -483,7 +485,7 @@ impl vfs::INode for INodeImpl { self.remove_dirent_page(entry_id)?; - if inode.info()?.type_ == vfs::FileType::Dir { + if inode.metadata()?.type_ == vfs::FileType::Dir { self.nlinks_dec(); dest.nlinks_inc(); } @@ -491,7 +493,7 @@ impl vfs::INode for INodeImpl { Ok(()) } fn find(&self, name: &str) -> vfs::Result> { - let info = self.info()?; + let info = self.metadata()?; if info.type_!=vfs::FileType::Dir { return Err(FsError::NotDir) } @@ -716,11 +718,18 @@ impl vfs::FileSystem for SimpleFileSystem { self.get_inode(BLKN_ROOT) } - fn info(&self) -> &'static vfs::FsInfo { - static INFO: vfs::FsInfo = vfs::FsInfo { - max_file_size: MAX_FILE_SIZE, - }; - &INFO + fn info(&self) -> vfs::FsInfo { + let sb = self.super_block.read(); + vfs::FsInfo { + bsize: BLKSIZE, + frsize: BLKSIZE, + blocks: sb.blocks as usize, + bfree: sb.unused_blocks as usize, + bavail: sb.unused_blocks as usize, + files: sb.blocks as usize, // inaccurate + ffree: sb.unused_blocks as usize, // inaccurate + namemax: MAX_FNAME_LEN, + } } } diff --git a/rcore-fs/src/file.rs b/rcore-fs/src/file.rs index 6cc6684..671e773 100644 --- a/rcore-fs/src/file.rs +++ b/rcore-fs/src/file.rs @@ -1,4 +1,4 @@ -use crate::vfs::{INode, Result, FileInfo}; +use crate::vfs::{INode, Result, Metadata}; use alloc::{sync::Arc, string::String}; pub struct File { @@ -27,8 +27,8 @@ impl File { Ok(len) } - pub fn info(&self) -> Result { - self.inode.info() + pub fn info(&self) -> Result { + self.inode.metadata() } pub fn get_entry(&self, id: usize) -> Result { diff --git a/rcore-fs/src/tests.rs b/rcore-fs/src/tests.rs index 45787e9..ffd75d8 100644 --- a/rcore-fs/src/tests.rs +++ b/rcore-fs/src/tests.rs @@ -38,7 +38,7 @@ fn create_file() -> Result<()> { let root = sfs.root_inode(); let file1 = root.create("file1", FileType::File)?; - assert_eq!(file1.info()?, FileInfo { + assert_eq!(file1.info()?, Metadata { inode: 5, size: 0, type_: FileType::File, diff --git a/rcore-fs/src/vfs.rs b/rcore-fs/src/vfs.rs index 5310b0b..2482c4a 100644 --- a/rcore-fs/src/vfs.rs +++ b/rcore-fs/src/vfs.rs @@ -6,7 +6,7 @@ use core::result; pub trait INode: Any + Sync + Send { fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result; fn write_at(&self, offset: usize, buf: &[u8]) -> Result; - fn info(&self) -> Result; + fn metadata(&self) -> Result; fn sync(&self) -> Result<()>; fn resize(&self, len: usize) -> Result<()>; fn create(&self, name: &str, type_: FileType, mode: u32) -> Result>; @@ -33,7 +33,7 @@ impl INode { self.as_any_ref().downcast_ref::() } pub fn list(&self) -> Result> { - let info = self.info()?; + let info = self.metadata()?; if info.type_ != FileType::Dir { return Err(FsError::NotDir); } @@ -42,13 +42,13 @@ impl INode { }).collect() } pub fn lookup(&self, path: &str) -> Result> { - if self.info()?.type_ != FileType::Dir { + if self.metadata()?.type_ != FileType::Dir { return Err(FsError::NotDir); } let mut result = self.find(".")?; let mut rest_path = path; while rest_path != "" { - if result.info()?.type_!= FileType::Dir { + if result.metadata()?.type_!= FileType::Dir { return Err(FsError::NotDir); } let name; @@ -71,8 +71,13 @@ impl INode { } } +/// Metadata of INode +/// +/// Ref: [http://pubs.opengroup.org/onlinepubs/009604499/basedefs/sys/stat.h.html] #[derive(Debug, Eq, PartialEq)] -pub struct FileInfo { +pub struct Metadata { + /// Device ID + pub dev: usize, /// Inode number pub inode: usize, /// Size in bytes @@ -80,6 +85,9 @@ pub struct FileInfo { /// SFS Note: for normal file size is the actuate file size /// for directory this is count of dirent. pub size: usize, + /// A file system-specific preferred I/O block size for this object. + /// In some file system types, this may vary from file to file. + pub blk_size: usize, /// Size in blocks pub blocks: usize, /// Time of last access @@ -97,9 +105,9 @@ pub struct FileInfo { /// SFS Note: different from linux, "." and ".." count in nlinks /// this is same as original ucore. pub nlinks: usize, - /// User id + /// User ID pub uid: usize, - /// Group id + /// Group ID pub gid: usize, } @@ -116,11 +124,31 @@ pub enum FileType { SymLink, CharDevice, BlockDevice, + NamedPipe, + Socket, } +/// Metadata of FileSystem +/// +/// Ref: [http://pubs.opengroup.org/onlinepubs/9699919799/] #[derive(Debug)] pub struct FsInfo { - pub max_file_size: usize, + /// File system block size + pub bsize: usize, + /// Fundamental file system block size + pub frsize: usize, + /// Total number of blocks on file system in units of `frsize` + pub blocks: usize, + /// Total number of free blocks + pub bfree: usize, + /// Number of free blocks available to non-privileged process + pub bavail: usize, + /// Total number of file serial numbers + pub files: usize, + /// Total number of free file serial numbers + pub ffree: usize, + /// Maximum filename length + pub namemax: usize, } // Note: IOError/NoMemory always lead to a panic since it's hard to recover from it. @@ -148,5 +176,5 @@ pub type Result = result::Result; pub trait FileSystem: Sync { fn sync(&self) -> Result<()>; fn root_inode(&self) -> Arc; - fn info(&self) -> &'static FsInfo; + fn info(&self) -> FsInfo; }