YJwu2023 73c607aadd
VirtIO网卡能够正常发送、接收数据 (#204)
* virtio-net小修改

* 移动volatile.rs到libs文件夹

* 使用virtio-drivers 0.3.0

* bugfix: 初始化BAR之后,未正确设置command register的问题


---------

Co-authored-by: longjin <longjin@dragonos.org>
2023-03-18 20:43:37 +08:00

515 lines
16 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/// 导出devfs的模块
pub mod null_dev;
pub mod zero_dev;
use super::vfs::{
core::{generate_inode_id, ROOT_INODE},
file::FileMode,
FileSystem, FileType, FsInfo, IndexNode, Metadata, PollStatus,
};
use crate::{
include::bindings::bindings::{EEXIST, EISDIR, ENOENT, ENOTDIR, ENOTSUP},
kerror,
libs::spinlock::{SpinLock, SpinLockGuard},
time::TimeSpec,
};
use alloc::{
collections::BTreeMap,
string::{String, ToString},
sync::{Arc, Weak},
vec::Vec,
};
const DEVFS_MAX_NAMELEN: usize = 64;
/// @brief dev文件系统
#[derive(Debug)]
pub struct DevFS {
// 文件系统根节点
root_inode: Arc<LockedDevFSInode>,
}
impl FileSystem for DevFS {
fn as_any_ref(&self) -> &dyn core::any::Any {
self
}
fn root_inode(&self) -> Arc<dyn super::vfs::IndexNode> {
return self.root_inode.clone();
}
fn info(&self) -> super::vfs::FsInfo {
return FsInfo {
blk_dev_id: 0,
max_name_len: DEVFS_MAX_NAMELEN,
};
}
}
impl DevFS {
pub fn new() -> Arc<Self> {
// 初始化root inode
let root: Arc<LockedDevFSInode> = Arc::new(LockedDevFSInode(SpinLock::new(
// /dev 的权限设置为 读+执行root 可以读写
// root 的 parent 是空指针
DevFSInode::new(FileType::Dir, 0o755 as u32, 0),
)));
let devfs: Arc<DevFS> = Arc::new(DevFS { root_inode: root });
// 对root inode加锁并继续完成初始化工作
let mut root_guard: SpinLockGuard<DevFSInode> = devfs.root_inode.0.lock();
root_guard.parent = Arc::downgrade(&devfs.root_inode);
root_guard.self_ref = Arc::downgrade(&devfs.root_inode);
root_guard.fs = Arc::downgrade(&devfs);
// 释放锁
drop(root_guard);
// 创建文件夹
let root: &Arc<LockedDevFSInode> = &devfs.root_inode;
root.add_dir("char")
.expect("DevFS: Failed to create /dev/char");
root.add_dir("block")
.expect("DevFS: Failed to create /dev/block");
devfs.register_bultinin_device();
// kdebug!("ls /dev: {:?}", root.list());
return devfs;
}
/// @brief 注册系统内部自带的设备
fn register_bultinin_device(&self) {
use null_dev::LockedNullInode;
use zero_dev::LockedZeroInode;
let dev_root: Arc<LockedDevFSInode> = self.root_inode.clone();
dev_root
.add_dev("null", LockedNullInode::new())
.expect("DevFS: Failed to register /dev/null");
dev_root
.add_dev("zero", LockedZeroInode::new())
.expect("DevFS: Failed to register /dev/zero");
}
/// @brief 在devfs内注册设备
///
/// @param name 设备名称
/// @param device 设备节点的结构体
pub fn register_device<T: DeviceINode>(&self, name: &str, device: Arc<T>) -> Result<(), i32> {
let dev_root_inode: Arc<LockedDevFSInode> = self.root_inode.clone();
match device.metadata().unwrap().file_type {
// 字节设备挂载在 /dev/char
FileType::CharDevice => {
if let Err(_) = dev_root_inode.find("char") {
dev_root_inode.create("char", FileType::Dir, 0o755)?;
}
let any_char_inode = dev_root_inode.find("char")?;
let dev_char_inode: &LockedDevFSInode = any_char_inode
.as_any_ref()
.downcast_ref::<LockedDevFSInode>()
.unwrap();
dev_char_inode.add_dev(name, device.clone())?;
device.set_fs(dev_char_inode.0.lock().fs.clone());
}
FileType::BlockDevice => {
if let Err(_) = dev_root_inode.find("block") {
dev_root_inode.create("block", FileType::Dir, 0o755)?;
}
let any_block_inode = dev_root_inode.find("block")?;
let dev_block_inode: &LockedDevFSInode = any_block_inode
.as_any_ref()
.downcast_ref::<LockedDevFSInode>()
.unwrap();
dev_block_inode.add_dev(name, device.clone())?;
device.set_fs(dev_block_inode.0.lock().fs.clone());
}
_ => {
return Err(-(ENOTSUP as i32));
}
}
return Ok(());
}
/// @brief 卸载设备
pub fn unregister_device<T: DeviceINode>(&self, name: &str, device: Arc<T>) -> Result<(), i32> {
let dev_root_inode: Arc<LockedDevFSInode> = self.root_inode.clone();
match device.metadata().unwrap().file_type {
// 字节设备挂载在 /dev/char
FileType::CharDevice => {
if let Err(_) = dev_root_inode.find("char") {
return Err(-(ENOENT as i32));
}
let any_char_inode = dev_root_inode.find("char")?;
let dev_char_inode = any_char_inode
.as_any_ref()
.downcast_ref::<LockedDevFSInode>()
.unwrap();
// TODO 调用设备的卸载接口(当引入卸载接口之后)
dev_char_inode.remove(name)?;
}
FileType::BlockDevice => {
if let Err(_) = dev_root_inode.find("block") {
return Err(-(ENOENT as i32));
}
let any_block_inode = dev_root_inode.find("block")?;
let dev_block_inode = any_block_inode
.as_any_ref()
.downcast_ref::<LockedDevFSInode>()
.unwrap();
dev_block_inode.remove(name)?;
}
_ => {
return Err(-(ENOTSUP as i32));
}
}
return Ok(());
}
}
/// @brief dev文件i节点(锁)
#[derive(Debug)]
pub struct LockedDevFSInode(SpinLock<DevFSInode>);
/// @brief dev文件i节点(无锁)
#[derive(Debug)]
pub struct DevFSInode {
/// 指向父Inode的弱引用
parent: Weak<LockedDevFSInode>,
/// 指向自身的弱引用
self_ref: Weak<LockedDevFSInode>,
/// 子Inode的B树
children: BTreeMap<String, Arc<dyn IndexNode>>,
/// 指向inode所在的文件系统对象的指针
fs: Weak<DevFS>,
/// INode 元数据
metadata: Metadata,
}
impl DevFSInode {
pub fn new(dev_type_: FileType, mode_: u32, data_: usize) -> Self {
return Self::new_with_parent(Weak::default(), dev_type_, mode_, data_);
}
pub fn new_with_parent(
parent: Weak<LockedDevFSInode>,
dev_type_: FileType,
mode_: u32,
data_: usize,
) -> Self {
return DevFSInode {
parent: parent,
self_ref: Weak::default(),
children: BTreeMap::new(),
metadata: Metadata {
dev_id: 1,
inode_id: generate_inode_id(),
size: 0,
blk_size: 0,
blocks: 0,
atime: TimeSpec::default(),
mtime: TimeSpec::default(),
ctime: TimeSpec::default(),
file_type: dev_type_, // 文件夹
mode: mode_,
nlinks: 1,
uid: 0,
gid: 0,
raw_dev: data_,
},
fs: Weak::default(),
};
}
}
impl LockedDevFSInode {
pub fn add_dir(&self, name: &str) -> Result<(), i32> {
let guard: SpinLockGuard<DevFSInode> = self.0.lock();
if guard.children.contains_key(name) {
return Err(-(EEXIST as i32));
}
match self.do_create_with_data(guard, name, FileType::Dir, 0o755 as u32, 0) {
Ok(inode) => inode,
Err(err) => {
return Err(err);
}
};
return Ok(());
}
pub fn add_dev(&self, name: &str, dev: Arc<dyn IndexNode>) -> Result<(), i32> {
let mut this = self.0.lock();
if this.children.contains_key(name) {
return Err(-(EEXIST as i32));
}
this.children.insert(name.to_string(), dev);
return Ok(());
}
pub fn remove(&self, name: &str) -> Result<(), i32> {
let x = self
.0
.lock()
.children
.remove(name)
.ok_or(-(ENOENT as i32))?;
drop(x);
return Ok(());
}
fn do_create_with_data(
&self,
mut guard: SpinLockGuard<DevFSInode>,
_name: &str,
_file_type: FileType,
_mode: u32,
_data: usize,
) -> Result<Arc<dyn IndexNode>, i32> {
if guard.metadata.file_type != FileType::Dir {
return Err(-(ENOTDIR as i32));
}
// 如果有重名的,则返回
if guard.children.contains_key(_name) {
return Err(-(EEXIST as i32));
}
// 创建inode
let result: Arc<LockedDevFSInode> = Arc::new(LockedDevFSInode(SpinLock::new(DevFSInode {
parent: guard.self_ref.clone(),
self_ref: Weak::default(),
children: BTreeMap::new(),
metadata: Metadata {
dev_id: 0,
inode_id: generate_inode_id(),
size: 0,
blk_size: 0,
blocks: 0,
atime: TimeSpec::default(),
mtime: TimeSpec::default(),
ctime: TimeSpec::default(),
file_type: _file_type,
mode: _mode,
nlinks: 1,
uid: 0,
gid: 0,
raw_dev: _data,
},
fs: guard.fs.clone(),
})));
// 初始化inode的自引用的weak指针
result.0.lock().self_ref = Arc::downgrade(&result);
// 将子inode插入父inode的B树中
guard.children.insert(String::from(_name), result.clone());
return Ok(result);
}
}
impl IndexNode for LockedDevFSInode {
fn as_any_ref(&self) -> &dyn core::any::Any {
self
}
fn open(&self, _data: &mut super::vfs::FilePrivateData, _mode: &FileMode) -> Result<(), i32> {
return Ok(());
}
fn close(&self, _data: &mut super::vfs::FilePrivateData) -> Result<(), i32> {
return Ok(());
}
fn create_with_data(
&self,
name: &str,
file_type: FileType,
mode: u32,
data: usize,
) -> Result<Arc<dyn IndexNode>, i32> {
// 获取当前inode
let guard: SpinLockGuard<DevFSInode> = self.0.lock();
// 如果当前inode不是文件夹则返回
return self.do_create_with_data(guard, name, file_type, mode, data);
}
fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, i32> {
let inode = self.0.lock();
if inode.metadata.file_type != FileType::Dir {
return Err(-(ENOTDIR as i32));
}
match name {
"" | "." => {
return Ok(inode.self_ref.upgrade().ok_or(-(ENOENT as i32))?);
}
".." => {
return Ok(inode.parent.upgrade().ok_or(-(ENOENT as i32))?);
}
name => {
// 在子目录项中查找
return Ok(inode.children.get(name).ok_or(-(ENOENT as i32))?.clone());
}
}
}
fn fs(&self) -> Arc<dyn FileSystem> {
return self.0.lock().fs.upgrade().unwrap();
}
fn get_entry_name(&self, ino: super::vfs::InodeId) -> Result<String, i32> {
let inode: SpinLockGuard<DevFSInode> = self.0.lock();
if inode.metadata.file_type != FileType::Dir {
return Err(-(ENOTDIR as i32));
}
match ino {
0 => {
return Ok(String::from("."));
}
1 => {
return Ok(String::from(".."));
}
ino => {
// 暴力遍历所有的children判断inode id是否相同
// TODO: 优化这里,这个地方性能很差!
let mut key: Vec<String> = inode
.children
.keys()
.filter(|k| inode.children.get(*k).unwrap().metadata().unwrap().inode_id == ino)
.cloned()
.collect();
match key.len() {
0=>{return Err(-(ENOENT as i32));}
1=>{return Ok(key.remove(0));}
_ => panic!("Devfs get_entry_name: key.len()={key_len}>1, current inode_id={inode_id}, to find={to_find}", key_len=key.len(), inode_id = inode.metadata.inode_id, to_find=ino)
}
}
}
}
fn ioctl(&self, _cmd: u32, _data: usize) -> Result<usize, i32> {
Err(-(ENOTSUP as i32))
}
fn list(&self) -> Result<Vec<String>, i32> {
let info = self.metadata()?;
if info.file_type != FileType::Dir {
return Err(-(ENOTDIR as i32));
}
let mut keys: Vec<String> = Vec::new();
keys.push(String::from("."));
keys.push(String::from(".."));
keys.append(&mut self.0.lock().children.keys().cloned().collect());
return Ok(keys);
}
fn metadata(&self) -> Result<Metadata, i32> {
return Ok(self.0.lock().metadata.clone());
}
fn set_metadata(&self, metadata: &Metadata) -> Result<(), i32> {
let mut inode = self.0.lock();
inode.metadata.atime = metadata.atime;
inode.metadata.mtime = metadata.mtime;
inode.metadata.ctime = metadata.ctime;
inode.metadata.mode = metadata.mode;
inode.metadata.uid = metadata.uid;
inode.metadata.gid = metadata.gid;
return Ok(());
}
fn poll(&self) -> Result<super::vfs::PollStatus, i32> {
// 加锁
let inode: SpinLockGuard<DevFSInode> = self.0.lock();
// 检查当前inode是否为一个文件夹如果是的话就返回错误
if inode.metadata.file_type == FileType::Dir {
return Err(-(EISDIR as i32));
}
return Ok(PollStatus {
flags: PollStatus::READ_MASK | PollStatus::WRITE_MASK,
});
}
/// 读设备 - 应该调用设备的函数读写,而不是通过文件系统读写
fn read_at(
&self,
_offset: usize,
_len: usize,
_buf: &mut [u8],
_data: &mut super::vfs::file::FilePrivateData,
) -> Result<usize, i32> {
Err(-(ENOTSUP as i32))
}
/// 写设备 - 应该调用设备的函数读写,而不是通过文件系统读写
fn write_at(
&self,
_offset: usize,
_len: usize,
_buf: &[u8],
_data: &mut super::vfs::file::FilePrivateData,
) -> Result<usize, i32> {
Err(-(ENOTSUP as i32))
}
}
/// @brief 所有的设备INode都需要额外实现这个trait
pub trait DeviceINode: IndexNode {
fn set_fs(&self, fs: Weak<DevFS>);
// TODO: 增加 unregister 方法
}
/// @brief 获取devfs实例的强类型不可变引用
macro_rules! devfs_exact_ref {
() => {{
let devfs_inode: Result<Arc<dyn IndexNode>, i32> = ROOT_INODE().find("dev");
if let Err(e) = devfs_inode {
kerror!("failed to get DevFS ref. errcode = {e}");
return Err(-(ENOENT as i32));
}
let binding = devfs_inode.unwrap();
let devfs_inode: &LockedDevFSInode = binding
.as_any_ref()
.downcast_ref::<LockedDevFSInode>()
.unwrap();
let binding = devfs_inode.fs();
binding
}
.as_any_ref()
.downcast_ref::<DevFS>()
.unwrap()};
}
/// @brief devfs的设备注册函数
pub fn devfs_register<T: DeviceINode>(name: &str, device: Arc<T>) -> Result<(), i32> {
return devfs_exact_ref!().register_device(name, device);
}
/// @brief devfs的设备卸载函数
#[allow(dead_code)]
pub fn devfs_unregister<T: DeviceINode>(name: &str, device: Arc<T>) -> Result<(), i32> {
return devfs_exact_ref!().unregister_device(name, device);
}