feat: 支持 sysfs下 block, char, Net, rtc, tty 等类型设备的 uevent 文件读操作 (#973)

* 新增CommonAttrGroup,基本支持sysfs下各种类型设备的uevent属性文件的读测试

* 修改net设备的uevent内容,使之与Linux语义一致

* 删除无用注释
This commit is contained in:
Val213 2024-10-14 13:07:37 +08:00 committed by GitHub
parent 4e4ce68e03
commit 38d161ccfe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 126 additions and 58 deletions

View File

@ -133,7 +133,7 @@ pub extern "sysv64" fn syscall_handler(frame: &mut TrapFrame) {
show &= false;
}
}
show = false;
if show {
debug!("[SYS] [Pid: {:?}] [Call: {:?}]", pid, to_print);
}

View File

@ -1,9 +1,8 @@
/// 引入Module
use crate::driver::{
use crate::{driver::{
base::{
device::{
device_number::{DeviceNumber, Major},
Device, DeviceError, IdTable, BLOCKDEVS,
device_number::{DeviceNumber, Major}, Device, DeviceError, IdTable, BLOCKDEVS
},
map::{
DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START,
@ -11,7 +10,7 @@ use crate::driver::{
},
},
block::cache::{cached_block_device::BlockCache, BlockCacheError, BLOCK_SIZE},
};
}, filesystem::sysfs::AttributeGroup};
use alloc::{string::String, sync::Arc, vec::Vec};
use core::{any::Any, fmt::Display, ops::Deref};

View File

@ -43,6 +43,7 @@ use super::{
},
kset::KSet,
swnode::software_node_notify,
uevent::UeventAttr,
};
pub mod bus;
@ -1025,6 +1026,25 @@ impl Eq for DeviceId {}
impl IrqHandlerData for DeviceId {}
/// sysfs下设备的通用属性组
#[derive(Debug)]
pub struct CommonAttrGroup;
impl AttributeGroup for CommonAttrGroup {
fn name(&self) -> Option<&str> {
None
}
fn attrs(&self) -> &[&'static dyn Attribute] {
&[&UeventAttr]
}
fn is_visible(
&self,
_kobj: alloc::sync::Arc<dyn KObject>,
attr: &'static dyn Attribute,
) -> Option<crate::filesystem::vfs::syscall::ModeType> {
Some(attr.mode())
}
}
lazy_static! {
/// class_dir列表通过parent kobject的name和class_dir的name来索引class_dir实例
static ref CLASS_DIR_KSET_INSTANCE: RwLock<BTreeMap<String, Arc<ClassDir>>> = RwLock::new(BTreeMap::new());

View File

@ -22,7 +22,7 @@ use crate::{
use system_error::SystemError;
use super::{kset::KSet, uevent::kobject_uevent};
use super::{device::CommonAttrGroup, kset::KSet, uevent::kobject_uevent};
pub trait KObject: Any + Send + Sync + Debug + CastFromSync {
fn as_any_ref(&self) -> &dyn core::any::Any;

View File

@ -11,12 +11,12 @@ use crate::{
bus::{Bus, BusState},
device_manager,
driver::Driver,
Device, DeviceCommonData, DevicePrivateData, DeviceType, IdTable,
CommonAttrGroup, Device, DeviceCommonData, DevicePrivateData, DeviceType, IdTable,
},
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet,
},
filesystem::kernfs::KernFSInode,
filesystem::{kernfs::KernFSInode, sysfs::AttributeGroup},
libs::{
rwlock::{RwLockReadGuard, RwLockWriteGuard},
spinlock::{SpinLock, SpinLockGuard},
@ -329,4 +329,8 @@ impl Device for PlatformBusDevice {
fn set_dev_parent(&self, dev_parent: Option<Weak<dyn Device>>) {
self.inner().device_common.parent = dev_parent;
}
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
Some(&[&CommonAttrGroup])
}
}

View File

@ -19,6 +19,7 @@ use alloc::string::{String, ToString};
use alloc::sync::Arc;
use alloc::vec::Vec;
use intertrait::cast::CastArc;
use log::warn;
use system_error::SystemError;
use super::block::block_device::{BlockDevice, BlockDeviceOps};
@ -128,46 +129,60 @@ impl Attribute for UeventAttr {
/// 用户空间读取 uevent 文件,返回 uevent 信息
fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
let device: Arc<dyn KObject> = _kobj
.parent()
.and_then(|x| x.upgrade())
.ok_or(SystemError::ENODEV)?;
let device = kobj2device(device).ok_or(SystemError::EINVAL)?;
let device = _kobj.cast::<dyn Device>().map_err(|e: Arc<dyn KObject>| {
warn!("device:{:?} is not a device!", e);
SystemError::EINVAL
})?;
log::info!("show uevent");
let device_type = device.dev_type();
let mut uevent_content = String::new();
log::info!("device_type: {:?}", device_type);
match device_type {
DeviceType::Block => {
let block_device = device
.cast::<dyn BlockDevice>()
.ok()
.ok_or(SystemError::EINVAL)?;
let major = block_device.id_table().device_number().major().data();
let minor = block_device.id_table().device_number().minor();
let device_name = block_device.id_table().name();
let major = device.id_table().device_number().major().data();
let minor = device.id_table().device_number().minor();
let device_name = device.id_table().name();
writeln!(&mut uevent_content, "MAJOR={:?}", major).unwrap();
writeln!(&mut uevent_content, "MINOR={:?}", minor).unwrap();
writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
writeln!(&mut uevent_content, "DEVTYPE=disk").unwrap();
}
DeviceType::Char => {
let char_device = device
.cast::<dyn CharDevice>()
.ok()
.ok_or(SystemError::EINVAL)?;
let major = char_device.id_table().device_number().major().data();
let minor = char_device.id_table().device_number().minor();
let device_name = char_device.id_table().name();
let major = device.id_table().device_number().major().data();
let minor = device.id_table().device_number().minor();
let device_name = device.id_table().name();
writeln!(&mut uevent_content, "MAJOR={}", major).unwrap();
writeln!(&mut uevent_content, "MINOR={}", minor).unwrap();
writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
writeln!(&mut uevent_content, "DEVTYPE=char").unwrap();
}
DeviceType::Net => {
let net_device = device.cast::<dyn Iface>().ok().ok_or(SystemError::EINVAL)?;
// let ifindex = net_device.ifindex().expect("Find ifindex error.\n");
let device_name = net_device.iface_name();
let net_device = device.clone().cast::<dyn Iface>().map_err(|e: Arc<dyn Device>| {
warn!("device:{:?} is not a net device!", e);
SystemError::EINVAL
})?;
let iface_id = net_device.nic_id();
let device_name = device.name();
writeln!(&mut uevent_content, "INTERFACE={}", device_name).unwrap();
// writeln!(&mut uevent_content, "IFINDEX={}", ifindex).unwrap();
writeln!(&mut uevent_content, "IFINDEX={}", iface_id).unwrap();
}
DeviceType::Bus => {
// 处理总线设备类型
let device_name = device.name();
writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
writeln!(&mut uevent_content, "DEVTYPE=bus").unwrap();
}
DeviceType::Rtc => {
// 处理RTC设备类型
let device_name = device.name();
writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
writeln!(&mut uevent_content, "DEVTYPE=rtc").unwrap();
}
DeviceType::Pci => {
// 处理PCI设备类型
let device_name = device.name();
writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap();
writeln!(&mut uevent_content, "DEVTYPE=pci").unwrap();
}
_ => {
// 处理其他设备类型
@ -180,17 +195,15 @@ impl Attribute for UeventAttr {
}
/// 捕获来自用户空间对 uevent 文件的写操作触发uevent事件
fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
log::info!("store uevent");
return kobject_synth_uevent(_buf, _kobj);
}
}
/// 将 kobject 转换为 device
fn kobj2device(kobj: Arc<dyn KObject>) -> Option<Arc<dyn Device>> {
kobj.cast::<dyn Device>().ok()
}
/// 将设备的基本信息写入 uevent 文件
fn sysfs_emit_str(buf: &mut [u8], content: &str) -> Result<usize, SystemError> {
log::info!("sysfs_emit_str");
let bytes = content.as_bytes();
if buf.len() < bytes.len() {
return Err(SystemError::ENOMEM);
@ -211,7 +224,10 @@ fn kobject_synth_uevent(buf: &[u8], kobj: Arc<dyn KObject>) -> Result<usize, Sys
};
if let Err(e) = result {
let device = kobj2device(kobj).ok_or(SystemError::EINVAL)?;
let device = kobj.cast::<dyn Device>().map_err(|e: Arc<dyn KObject>| {
warn!("device:{:?} is not a device!", e);
SystemError::EINVAL
})?;
let devname = device.name();
log::error!("synth uevent: {}: {:?}", devname, e);
return Err(SystemError::EINVAL);

View File

@ -24,7 +24,7 @@ use crate::{
device::{
bus::Bus,
driver::{Driver, DriverCommonData},
Device, DeviceCommonData, DeviceId, DeviceType, IdTable,
CommonAttrGroup, Device, DeviceCommonData, DeviceId, DeviceType, IdTable,
},
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet,
@ -38,7 +38,7 @@ use crate::{
},
},
exception::{irqdesc::IrqReturn, IrqNumber},
filesystem::{kernfs::KernFSInode, mbr::MbrDiskPartionTable},
filesystem::{kernfs::KernFSInode, mbr::MbrDiskPartionTable, sysfs::AttributeGroup},
init::initcall::INITCALL_POSTCORE,
libs::{
rwlock::{RwLockReadGuard, RwLockWriteGuard},
@ -342,7 +342,7 @@ impl VirtIODevice for VirtIOBlkDevice {
impl Device for VirtIOBlkDevice {
fn dev_type(&self) -> DeviceType {
DeviceType::Net
DeviceType::Block
}
fn id_table(&self) -> IdTable {
@ -407,6 +407,10 @@ impl Device for VirtIOBlkDevice {
fn set_dev_parent(&self, parent: Option<Weak<dyn Device>>) {
self.inner().device_common.parent = parent;
}
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
Some(&[&CommonAttrGroup])
}
}
impl KObject for VirtIOBlkDevice {
@ -472,7 +476,7 @@ fn virtio_blk_driver_init() -> Result<(), SystemError> {
let driver = VirtIOBlkDriver::new();
virtio_driver_manager()
.register(driver.clone() as Arc<dyn VirtIODriver>)
.expect("Add virtio net driver failed");
.expect("Add virtio block driver failed");
unsafe {
VIRTIO_BLK_DRIVER = Some(driver);
}

View File

@ -1,7 +1,7 @@
use crate::{
driver::base::{
class::{class_manager, Class},
device::sys_dev_char_kset,
device::{sys_dev_char_kset, CommonAttrGroup},
kobject::KObject,
subsys::SubSysPrivate,
},
@ -78,6 +78,6 @@ impl Class for NetClass {
}
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
return &[&NetAttrGroup];
return &[&NetAttrGroup, &CommonAttrGroup];
}
}

View File

@ -25,7 +25,7 @@ use crate::{
device::{
bus::Bus,
driver::{Driver, DriverCommonData},
Device, DeviceCommonData, DeviceId, DeviceType, IdTable,
CommonAttrGroup, Device, DeviceCommonData, DeviceId, DeviceType, IdTable,
},
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet,
@ -41,7 +41,7 @@ use crate::{
},
},
exception::{irqdesc::IrqReturn, IrqNumber},
filesystem::kernfs::KernFSInode,
filesystem::{kernfs::KernFSInode, sysfs::AttributeGroup},
init::initcall::INITCALL_POSTCORE,
libs::{
rwlock::{RwLockReadGuard, RwLockWriteGuard},
@ -249,6 +249,10 @@ impl Device for VirtIONetDevice {
fn set_dev_parent(&self, parent: Option<Weak<dyn Device>>) {
self.inner().device_common.parent = parent;
}
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
Some(&[&CommonAttrGroup])
}
}
impl VirtIODevice for VirtIONetDevice {

View File

@ -8,7 +8,10 @@ use alloc::{
use crate::{
driver::base::{
class::Class,
device::{bus::Bus, driver::Driver, Device, DeviceCommonData, DeviceType, IdTable},
device::{
bus::Bus, driver::Driver, CommonAttrGroup, Device, DeviceCommonData, DeviceType,
IdTable,
},
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet,
},
@ -84,7 +87,7 @@ impl PciDevice for PciGeneralDevice {
impl Device for PciGeneralDevice {
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
Some(&[&BasicPciReadOnlyAttrs])
Some(&[&BasicPciReadOnlyAttrs, &CommonAttrGroup])
}
fn bus(&self) -> Option<Weak<dyn Bus>> {

View File

@ -10,7 +10,10 @@ use crate::{
driver::{
base::{
class::Class,
device::{bus::Bus, driver::Driver, Device, DeviceCommonData, DeviceType, IdTable},
device::{
bus::Bus, driver::Driver, CommonAttrGroup, Device, DeviceCommonData, DeviceType,
IdTable,
},
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet,
},
@ -74,7 +77,7 @@ impl PciDevice for TestDevice {
impl Device for TestDevice {
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
Some(&[&HelloAttr])
Some(&[&HelloAttr, &CommonAttrGroup])
}
fn bus(&self) -> Option<Weak<dyn Bus>> {

View File

@ -9,10 +9,11 @@ use unified_init::macros::unified_init;
use crate::{
driver::base::{
class::{class_manager, Class},
device::{device_manager, sys_dev_char_kset},
device::{device_manager, sys_dev_char_kset, CommonAttrGroup},
kobject::KObject,
subsys::SubSysPrivate,
},
filesystem::sysfs::AttributeGroup,
init::initcall::INITCALL_SUBSYS,
time::{timekeeping::do_settimeofday64, PosixTimeSpec},
};
@ -78,6 +79,9 @@ impl Class for RtcClass {
fn subsystem(&self) -> &SubSysPrivate {
return &self.subsystem;
}
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
return &[&CommonAttrGroup];
}
}
/// 注册rtc通用设备

View File

@ -9,7 +9,8 @@ use crate::{
driver::base::{
class::Class,
device::{
bus::Bus, device_manager, driver::Driver, Device, DeviceCommonData, DeviceType, IdTable,
bus::Bus, device_manager, driver::Driver, CommonAttrGroup, Device, DeviceCommonData,
DeviceType, IdTable,
},
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet,
@ -172,7 +173,7 @@ impl Device for RtcGeneralDevice {
true
}
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
Some(&[&RtcAttrGroup])
Some(&[&RtcAttrGroup, &CommonAttrGroup])
}
fn dev_parent(&self) -> Option<Weak<dyn Device>> {

View File

@ -8,10 +8,11 @@ use unified_init::macros::unified_init;
use crate::{
driver::base::{
class::{class_manager, Class},
device::sys_dev_char_kset,
device::{sys_dev_char_kset, CommonAttrGroup},
kobject::KObject,
subsys::SubSysPrivate,
},
filesystem::sysfs::AttributeGroup,
init::initcall::INITCALL_SUBSYS,
};
@ -61,6 +62,10 @@ impl Class for TtyClass {
fn subsystem(&self) -> &SubSysPrivate {
return &self.subsystem;
}
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
return &[&CommonAttrGroup];
}
}
/// 初始化帧缓冲区子系统

View File

@ -11,8 +11,8 @@ use crate::{
base::{
class::Class,
device::{
bus::Bus, device_manager, driver::Driver, Device, DeviceCommonData, DeviceType,
IdTable,
bus::Bus, device_manager, driver::Driver, CommonAttrGroup, Device,
DeviceCommonData, DeviceType, IdTable,
},
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet,
@ -235,7 +235,7 @@ impl Device for FbConsoleDevice {
}
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
return Some(&[&AnonymousAttributeGroup]);
return Some(&[&AnonymousAttributeGroup, &CommonAttrGroup]);
}
fn dev_parent(&self) -> Option<Weak<dyn Device>> {

View File

@ -18,7 +18,7 @@ use crate::{
device_manager,
device_number::{DeviceNumber, Major},
driver::Driver,
sys_dev_char_kset, Device, DeviceCommonData, DeviceType, IdTable,
sys_dev_char_kset, CommonAttrGroup, Device, DeviceCommonData, DeviceType, IdTable,
},
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet,
@ -112,6 +112,10 @@ impl Class for GraphicsClass {
fn subsystem(&self) -> &SubSysPrivate {
return &self.subsystem;
}
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
return &[&CommonAttrGroup];
}
}
/// 帧缓冲区管理器
@ -373,7 +377,7 @@ impl Device for FbDevice {
}
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
Some(&[&FbDeviceAttrGroup])
Some(&[&FbDeviceAttrGroup, &CommonAttrGroup])
}
fn dev_parent(&self) -> Option<Weak<dyn Device>> {

View File

@ -5,6 +5,7 @@ use unified_init::macros::unified_init;
use crate::{
driver::base::{
device::CommonAttrGroup,
kobject::{KObjType, KObject, KObjectManager, KObjectSysFSOps},
kset::KSet,
},
@ -45,7 +46,7 @@ impl KObjType for IrqKObjType {
}
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
Some(&[&IrqAttrGroup])
Some(&[&IrqAttrGroup, &CommonAttrGroup])
}
fn release(&self, _kobj: Arc<dyn KObject>) {