Remove `inode_handle/static_cap.rs`
This commit is contained in:
parent
277b5b5c24
commit
722efc62ca
|
|
@ -1,12 +1,31 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use aster_rights::TRights;
|
||||
use core::sync::atomic::AtomicU32;
|
||||
|
||||
use aster_rights::Rights;
|
||||
use inherit_methods_macro::inherit_methods;
|
||||
|
||||
use super::*;
|
||||
use crate::{fs::file_handle::Mappable, prelude::*, process::signal::Pollable};
|
||||
use super::HandleInner;
|
||||
use crate::{
|
||||
events::IoEvents,
|
||||
fs::{
|
||||
file_handle::{FileLike, Mappable},
|
||||
path::Path,
|
||||
utils::{
|
||||
AccessMode, DirentVisitor, FallocMode, FlockItem, InodeMode, InodeType, IoctlCmd,
|
||||
Metadata, RangeLockItem, RangeLockType, SeekFrom, StatusFlags,
|
||||
},
|
||||
},
|
||||
prelude::*,
|
||||
process::{
|
||||
signal::{PollHandle, Pollable},
|
||||
Gid, Uid,
|
||||
},
|
||||
};
|
||||
|
||||
impl InodeHandle<Rights> {
|
||||
pub struct InodeHandle(HandleInner, Rights);
|
||||
|
||||
impl InodeHandle {
|
||||
pub fn new(path: Path, access_mode: AccessMode, status_flags: StatusFlags) -> Result<Self> {
|
||||
let inode = path.inode();
|
||||
if !status_flags.contains(StatusFlags::O_PATH) {
|
||||
|
|
@ -37,26 +56,16 @@ impl InodeHandle<Rights> {
|
|||
(file_io, rights)
|
||||
};
|
||||
|
||||
let inner = Arc::new(InodeHandle_ {
|
||||
let inner = HandleInner {
|
||||
path,
|
||||
file_io,
|
||||
offset: Mutex::new(0),
|
||||
access_mode,
|
||||
status_flags: AtomicU32::new(status_flags.bits()),
|
||||
});
|
||||
};
|
||||
Ok(Self(inner, rights))
|
||||
}
|
||||
|
||||
#[expect(dead_code)]
|
||||
#[expect(clippy::wrong_self_convention)]
|
||||
pub fn to_static<R1: TRights>(self) -> Result<InodeHandle<R1>> {
|
||||
let rights = Rights::from_bits(R1::BITS).ok_or(Error::new(Errno::EBADF))?;
|
||||
if !self.1.contains(rights) {
|
||||
return_errno_with_message!(Errno::EBADF, "check rights failed");
|
||||
}
|
||||
Ok(InodeHandle(self.0.clone(), R1::new()))
|
||||
}
|
||||
|
||||
pub fn readdir(&self, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
||||
if !self.1.contains(Rights::READ) {
|
||||
return_errno_with_message!(Errno::EBADF, "the file is not opened readable");
|
||||
|
|
@ -106,21 +115,23 @@ impl InodeHandle<Rights> {
|
|||
self.0.unlock_flock(self);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for InodeHandle<Rights> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone(), self.1)
|
||||
pub fn path(&self) -> &Path {
|
||||
&self.0.path
|
||||
}
|
||||
|
||||
pub fn offset(&self) -> usize {
|
||||
self.0.offset()
|
||||
}
|
||||
}
|
||||
|
||||
#[inherit_methods(from = "self.0")]
|
||||
impl Pollable for InodeHandle<Rights> {
|
||||
impl Pollable for InodeHandle {
|
||||
fn poll(&self, mask: IoEvents, poller: Option<&mut PollHandle>) -> IoEvents;
|
||||
}
|
||||
|
||||
#[inherit_methods(from = "self.0")]
|
||||
impl FileLike for InodeHandle<Rights> {
|
||||
impl FileLike for InodeHandle {
|
||||
fn status_flags(&self) -> StatusFlags;
|
||||
fn access_mode(&self) -> AccessMode;
|
||||
fn metadata(&self) -> Metadata;
|
||||
|
|
@ -202,3 +213,10 @@ impl FileLike for InodeHandle<Rights> {
|
|||
self.0.fallocate(mode, offset, len)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for InodeHandle {
|
||||
fn drop(&mut self) {
|
||||
self.0.release_range_locks();
|
||||
self.0.unlock_flock(self);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,18 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#![expect(unused_variables)]
|
||||
|
||||
//! Opened Inode-backed File Handle
|
||||
|
||||
mod dyn_cap;
|
||||
mod static_cap;
|
||||
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
|
||||
use aster_rights::Rights;
|
||||
pub use dyn_cap::InodeHandle;
|
||||
use inherit_methods_macro::inherit_methods;
|
||||
|
||||
use crate::{
|
||||
events::IoEvents,
|
||||
fs::{
|
||||
file_handle::{FileLike, Mappable},
|
||||
file_handle::Mappable,
|
||||
path::Path,
|
||||
utils::{
|
||||
AccessMode, DirentVisitor, FallocMode, FileRange, FlockItem, FlockList, Inode,
|
||||
|
|
@ -30,10 +27,7 @@ use crate::{
|
|||
},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InodeHandle<R = Rights>(Arc<InodeHandle_>, R);
|
||||
|
||||
struct InodeHandle_ {
|
||||
struct HandleInner {
|
||||
path: Path,
|
||||
/// `file_io` is Similar to `file_private` field in `file` structure in linux. If
|
||||
/// `file_io` is Some, typical file operations including `read`, `write`, `poll`,
|
||||
|
|
@ -44,8 +38,8 @@ struct InodeHandle_ {
|
|||
status_flags: AtomicU32,
|
||||
}
|
||||
|
||||
impl InodeHandle_ {
|
||||
pub fn read(&self, writer: &mut VmWriter) -> Result<usize> {
|
||||
impl HandleInner {
|
||||
pub(self) fn read(&self, writer: &mut VmWriter) -> Result<usize> {
|
||||
if let Some(ref file_io) = self.file_io {
|
||||
return file_io.read(writer, self.status_flags());
|
||||
}
|
||||
|
|
@ -62,7 +56,7 @@ impl InodeHandle_ {
|
|||
Ok(len)
|
||||
}
|
||||
|
||||
pub fn write(&self, reader: &mut VmReader) -> Result<usize> {
|
||||
pub(self) fn write(&self, reader: &mut VmReader) -> Result<usize> {
|
||||
if let Some(ref file_io) = self.file_io {
|
||||
return file_io.write(reader, self.status_flags());
|
||||
}
|
||||
|
|
@ -83,8 +77,8 @@ impl InodeHandle_ {
|
|||
Ok(len)
|
||||
}
|
||||
|
||||
pub fn read_at(&self, offset: usize, writer: &mut VmWriter) -> Result<usize> {
|
||||
if let Some(ref file_io) = self.file_io {
|
||||
pub(self) fn read_at(&self, offset: usize, writer: &mut VmWriter) -> Result<usize> {
|
||||
if let Some(ref _file_io) = self.file_io {
|
||||
todo!("support read_at for FileIo");
|
||||
}
|
||||
|
||||
|
|
@ -95,8 +89,8 @@ impl InodeHandle_ {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn write_at(&self, mut offset: usize, reader: &mut VmReader) -> Result<usize> {
|
||||
if let Some(ref file_io) = self.file_io {
|
||||
pub(self) fn write_at(&self, mut offset: usize, reader: &mut VmReader) -> Result<usize> {
|
||||
if let Some(ref _file_io) = self.file_io {
|
||||
todo!("support write_at for FileIo");
|
||||
}
|
||||
|
||||
|
|
@ -113,41 +107,41 @@ impl InodeHandle_ {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn seek(&self, pos: SeekFrom) -> Result<usize> {
|
||||
pub(self) fn seek(&self, pos: SeekFrom) -> Result<usize> {
|
||||
do_seek_util(self.path.inode().as_ref(), &self.offset, pos)
|
||||
}
|
||||
|
||||
pub fn offset(&self) -> usize {
|
||||
pub(self) fn offset(&self) -> usize {
|
||||
let offset = self.offset.lock();
|
||||
*offset
|
||||
}
|
||||
|
||||
pub fn resize(&self, new_size: usize) -> Result<()> {
|
||||
pub(self) fn resize(&self, new_size: usize) -> Result<()> {
|
||||
do_resize_util(self.path.inode().as_ref(), self.status_flags(), new_size)
|
||||
}
|
||||
|
||||
pub fn access_mode(&self) -> AccessMode {
|
||||
pub(self) fn access_mode(&self) -> AccessMode {
|
||||
self.access_mode
|
||||
}
|
||||
|
||||
pub fn status_flags(&self) -> StatusFlags {
|
||||
pub(self) fn status_flags(&self) -> StatusFlags {
|
||||
let bits = self.status_flags.load(Ordering::Relaxed);
|
||||
StatusFlags::from_bits(bits).unwrap()
|
||||
}
|
||||
|
||||
pub fn set_status_flags(&self, new_status_flags: StatusFlags) {
|
||||
pub(self) fn set_status_flags(&self, new_status_flags: StatusFlags) {
|
||||
self.status_flags
|
||||
.store(new_status_flags.bits(), Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub fn readdir(&self, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
||||
pub(self) fn readdir(&self, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
||||
let mut offset = self.offset.lock();
|
||||
let read_cnt = self.path.inode().readdir_at(*offset, visitor)?;
|
||||
*offset += read_cnt;
|
||||
Ok(read_cnt)
|
||||
}
|
||||
|
||||
fn poll(&self, mask: IoEvents, poller: Option<&mut PollHandle>) -> IoEvents {
|
||||
pub(self) fn poll(&self, mask: IoEvents, poller: Option<&mut PollHandle>) -> IoEvents {
|
||||
if let Some(ref file_io) = self.file_io {
|
||||
return file_io.poll(mask, poller);
|
||||
}
|
||||
|
|
@ -155,7 +149,7 @@ impl InodeHandle_ {
|
|||
self.path.inode().poll(mask, poller)
|
||||
}
|
||||
|
||||
fn fallocate(&self, mode: FallocMode, offset: usize, len: usize) -> Result<()> {
|
||||
pub(self) fn fallocate(&self, mode: FallocMode, offset: usize, len: usize) -> Result<()> {
|
||||
do_fallocate_util(
|
||||
self.path.inode().as_ref(),
|
||||
self.status_flags(),
|
||||
|
|
@ -165,7 +159,7 @@ impl InodeHandle_ {
|
|||
)
|
||||
}
|
||||
|
||||
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
||||
pub(self) fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
||||
if let Some(ref file_io) = self.file_io {
|
||||
return file_io.ioctl(cmd, arg);
|
||||
}
|
||||
|
|
@ -173,7 +167,7 @@ impl InodeHandle_ {
|
|||
self.path.inode().ioctl(cmd, arg)
|
||||
}
|
||||
|
||||
fn mappable(&self) -> Result<Mappable> {
|
||||
pub(self) fn mappable(&self) -> Result<Mappable> {
|
||||
let inode = self.path.inode();
|
||||
if inode.page_cache().is_some() {
|
||||
// If the inode has a page cache, it is a file-backed mapping and
|
||||
|
|
@ -188,7 +182,7 @@ impl InodeHandle_ {
|
|||
}
|
||||
}
|
||||
|
||||
fn test_range_lock(&self, mut lock: RangeLockItem) -> Result<RangeLockItem> {
|
||||
pub(self) fn test_range_lock(&self, mut lock: RangeLockItem) -> Result<RangeLockItem> {
|
||||
let Some(extension) = self.path.inode().extension() else {
|
||||
// Range locks are not supported. So nothing is locked.
|
||||
lock.set_type(RangeLockType::Unlock);
|
||||
|
|
@ -205,7 +199,7 @@ impl InodeHandle_ {
|
|||
Ok(req_lock)
|
||||
}
|
||||
|
||||
fn set_range_lock(&self, lock: &RangeLockItem, is_nonblocking: bool) -> Result<()> {
|
||||
pub(self) fn set_range_lock(&self, lock: &RangeLockItem, is_nonblocking: bool) -> Result<()> {
|
||||
if RangeLockType::Unlock == lock.type_() {
|
||||
self.unlock_range_lock(lock);
|
||||
return Ok(());
|
||||
|
|
@ -224,7 +218,7 @@ impl InodeHandle_ {
|
|||
range_lock_list.set_lock(lock, is_nonblocking)
|
||||
}
|
||||
|
||||
fn release_range_locks(&self) {
|
||||
pub(self) fn release_range_locks(&self) {
|
||||
if self.path.inode().extension().is_none() {
|
||||
return;
|
||||
}
|
||||
|
|
@ -236,7 +230,7 @@ impl InodeHandle_ {
|
|||
self.unlock_range_lock(&range_lock);
|
||||
}
|
||||
|
||||
fn unlock_range_lock(&self, lock: &RangeLockItem) {
|
||||
pub(self) fn unlock_range_lock(&self, lock: &RangeLockItem) {
|
||||
if let Some(extension) = self.path.inode().extension()
|
||||
&& let Some(range_lock_list) = extension.get::<RangeLockList>()
|
||||
{
|
||||
|
|
@ -244,7 +238,7 @@ impl InodeHandle_ {
|
|||
}
|
||||
}
|
||||
|
||||
fn set_flock(&self, lock: FlockItem, is_nonblocking: bool) -> Result<()> {
|
||||
pub(self) fn set_flock(&self, lock: FlockItem, is_nonblocking: bool) -> Result<()> {
|
||||
let Some(extension) = self.path.inode().extension() else {
|
||||
// TODO: Figure out whether flocks are supported on all inodes.
|
||||
warn!("the inode does not have support for flocks; this operation will fail");
|
||||
|
|
@ -258,7 +252,7 @@ impl InodeHandle_ {
|
|||
flock_list.set_lock(lock, is_nonblocking)
|
||||
}
|
||||
|
||||
fn unlock_flock<R>(&self, req_owner: &InodeHandle<R>) {
|
||||
pub(self) fn unlock_flock(&self, req_owner: &InodeHandle) {
|
||||
if let Some(extension) = self.path.inode().extension()
|
||||
&& let Some(flock_list) = extension.get::<FlockList>()
|
||||
{
|
||||
|
|
@ -268,20 +262,20 @@ impl InodeHandle_ {
|
|||
}
|
||||
|
||||
#[inherit_methods(from = "self.path")]
|
||||
impl InodeHandle_ {
|
||||
pub fn size(&self) -> usize;
|
||||
pub fn metadata(&self) -> Metadata;
|
||||
pub fn mode(&self) -> Result<InodeMode>;
|
||||
pub fn set_mode(&self, mode: InodeMode) -> Result<()>;
|
||||
pub fn owner(&self) -> Result<Uid>;
|
||||
pub fn set_owner(&self, uid: Uid) -> Result<()>;
|
||||
pub fn group(&self) -> Result<Gid>;
|
||||
pub fn set_group(&self, gid: Gid) -> Result<()>;
|
||||
impl HandleInner {
|
||||
pub(self) fn size(&self) -> usize;
|
||||
pub(self) fn metadata(&self) -> Metadata;
|
||||
pub(self) fn mode(&self) -> Result<InodeMode>;
|
||||
pub(self) fn set_mode(&self, mode: InodeMode) -> Result<()>;
|
||||
pub(self) fn owner(&self) -> Result<Uid>;
|
||||
pub(self) fn set_owner(&self, uid: Uid) -> Result<()>;
|
||||
pub(self) fn group(&self) -> Result<Gid>;
|
||||
pub(self) fn set_group(&self, gid: Gid) -> Result<()>;
|
||||
}
|
||||
|
||||
impl Debug for InodeHandle_ {
|
||||
impl Debug for HandleInner {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
f.debug_struct("InodeHandle_")
|
||||
f.debug_struct("HandleInner")
|
||||
.field("path", &self.path)
|
||||
.field("offset", &self.offset())
|
||||
.field("access_mode", &self.access_mode())
|
||||
|
|
@ -290,24 +284,6 @@ impl Debug for InodeHandle_ {
|
|||
}
|
||||
}
|
||||
|
||||
/// Methods for both dyn and static
|
||||
impl<R> InodeHandle<R> {
|
||||
pub fn path(&self) -> &Path {
|
||||
&self.0.path
|
||||
}
|
||||
|
||||
pub fn offset(&self) -> usize {
|
||||
self.0.offset()
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> Drop for InodeHandle<R> {
|
||||
fn drop(&mut self) {
|
||||
self.0.release_range_locks();
|
||||
self.0.unlock_flock(self);
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for file-like objects that provide custom I/O operations.
|
||||
///
|
||||
/// This trait is typically implemented for special files like devices or
|
||||
|
|
@ -315,7 +291,7 @@ impl<R> Drop for InodeHandle<R> {
|
|||
//
|
||||
// TODO: The `status_flags` parameter in `read` and `write` may need to be stored directly
|
||||
// in the `FileIo`. We need further refactoring to find an appropriate way to enable `FileIo`
|
||||
// to utilize the information in the `InodeHandle_`.
|
||||
// to utilize the information in the `HandleInner`.
|
||||
pub trait FileIo: Pollable + Send + Sync + 'static {
|
||||
/// Reads data from the file into the given `VmWriter`.
|
||||
fn read(&self, writer: &mut VmWriter, status_flags: StatusFlags) -> Result<usize>;
|
||||
|
|
@ -323,12 +299,12 @@ pub trait FileIo: Pollable + Send + Sync + 'static {
|
|||
/// Writes data from the given `VmReader` into the file.
|
||||
fn write(&self, reader: &mut VmReader, status_flags: StatusFlags) -> Result<usize>;
|
||||
|
||||
/// See [`FileLike::mappable`].
|
||||
// See `FileLike::mappable`.
|
||||
fn mappable(&self) -> Result<Mappable> {
|
||||
return_errno_with_message!(Errno::EINVAL, "the file is not mappable");
|
||||
}
|
||||
|
||||
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
||||
fn ioctl(&self, _cmd: IoctlCmd, _arg: usize) -> Result<i32> {
|
||||
return_errno_with_message!(Errno::ENOTTY, "ioctl is not supported");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use aster_rights::{Read, TRightSet, TRights, Write};
|
||||
use aster_rights_proc::require;
|
||||
|
||||
use super::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
impl<R: TRights> InodeHandle<TRightSet<R>> {
|
||||
#[expect(dead_code)]
|
||||
#[require(R > Read)]
|
||||
pub fn read(&self, writer: &mut VmWriter) -> Result<usize> {
|
||||
self.0.read(writer)
|
||||
}
|
||||
|
||||
#[expect(dead_code)]
|
||||
#[require(R > Write)]
|
||||
pub fn write(&self, reader: &mut VmReader) -> Result<usize> {
|
||||
self.0.write(reader)
|
||||
}
|
||||
|
||||
#[expect(dead_code)]
|
||||
#[require(R > Read)]
|
||||
pub fn readdir(&self, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
||||
self.0.readdir(visitor)
|
||||
}
|
||||
}
|
||||
|
|
@ -163,17 +163,14 @@ impl FlockList {
|
|||
/// If the owner is valid, the lock is removed from the list and all threads waiting for the lock are woken.
|
||||
/// The function does nothing if the owner is not found in the list.
|
||||
/// The function is called when the file is closed or the lock is released.
|
||||
pub fn unlock<R>(&self, req_owner: &InodeHandle<R>) {
|
||||
debug!(
|
||||
"unlock with owner: {:?}",
|
||||
req_owner as *const InodeHandle<R>
|
||||
);
|
||||
pub fn unlock(&self, req_owner: &InodeHandle) {
|
||||
debug!("unlock with owner: {:?}", req_owner as *const InodeHandle);
|
||||
let mut list = self.inner.lock();
|
||||
list.retain(|lock| {
|
||||
if let Some(owner) = lock.owner() {
|
||||
if ptr::eq(
|
||||
Arc::as_ptr(&owner) as *const InodeHandle<R>,
|
||||
req_owner as *const InodeHandle<R>,
|
||||
Arc::as_ptr(&owner) as *const InodeHandle,
|
||||
req_owner as *const InodeHandle,
|
||||
) {
|
||||
lock.wake_all(); // Wake all threads waiting for this lock.
|
||||
false // Remove lock from the list.
|
||||
|
|
|
|||
Loading…
Reference in New Issue