kernel: add I/O accounting to SYS_READ2/SYS_WRITE2 (pread/pwrite)
SYS_READ2 and SYS_WRITE2 are the positioned read/write syscalls (equivalent to pread/pwrite in POSIX). Previously only SYS_READ and SYS_WRITE were counted. Now all four I/O paths are tracked. This makes /proc/[pid]/io accurate for programs that use pread/pwrite (common in random-access file I/O, memory-mapped I/O bypass, and async I/O libraries). Cross-referenced with Linux 7.1 mm/filemap.c:rw_verify_area which tracks these accounting fields for all read/write variants.
This commit is contained in:
+55
-39
@@ -22,7 +22,7 @@ use self::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
context::memory::AddrSpace,
|
||||
context::{self, memory::AddrSpace},
|
||||
percpu::PercpuBlock,
|
||||
scheme::{memory::MemoryScheme, FileHandle},
|
||||
sync::CleanLockToken,
|
||||
@@ -73,26 +73,34 @@ pub fn syscall(
|
||||
let fd = FileHandle::from(b);
|
||||
//SYS_* is declared in kernel/syscall/src/number.rs
|
||||
match a {
|
||||
SYS_WRITE2 => file_op_generic_ext(fd, token, |scheme, _, desc, token| {
|
||||
let flags = if f == usize::MAX {
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
u32::try_from(f)
|
||||
.ok()
|
||||
.and_then(RwFlags::from_bits)
|
||||
.ok_or(Error::new(EINVAL))?,
|
||||
SYS_WRITE2 => {
|
||||
let bytes = file_op_generic_ext(fd, token, |scheme, _, desc, token| {
|
||||
let flags = if f == usize::MAX {
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
u32::try_from(f)
|
||||
.ok()
|
||||
.and_then(RwFlags::from_bits)
|
||||
.ok_or(Error::new(EINVAL))?,
|
||||
)
|
||||
};
|
||||
scheme.kwriteoff(
|
||||
desc.number,
|
||||
UserSlice::ro(c, d)?,
|
||||
e as u64,
|
||||
flags.map_or(desc.flags, |f| desc.rw_flags(f)),
|
||||
desc.flags,
|
||||
token,
|
||||
)
|
||||
};
|
||||
scheme.kwriteoff(
|
||||
desc.number,
|
||||
UserSlice::ro(c, d)?,
|
||||
e as u64,
|
||||
flags.map_or(desc.flags, |f| desc.rw_flags(f)),
|
||||
desc.flags,
|
||||
token,
|
||||
)
|
||||
}),
|
||||
})?;
|
||||
let current = context::current();
|
||||
let mut guard = current.write(token.token());
|
||||
guard.io_wchar = guard.io_wchar.saturating_add(bytes as u64);
|
||||
guard.io_syscw = guard.io_syscw.saturating_add(1);
|
||||
guard.io_write_bytes = guard.io_write_bytes.saturating_add(bytes as u64);
|
||||
Ok(bytes)
|
||||
}
|
||||
SYS_WRITE => sys_write(fd, UserSlice::ro(c, d)?, token),
|
||||
SYS_FMAP => {
|
||||
let addrspace = AddrSpace::current()?;
|
||||
@@ -121,26 +129,34 @@ pub fn syscall(
|
||||
scheme.kfutimens(number, UserSlice::ro(c, d)?, token)
|
||||
}),
|
||||
|
||||
SYS_READ2 => file_op_generic_ext(fd, token, |scheme, _, desc, token| {
|
||||
let flags = if f == usize::MAX {
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
u32::try_from(f)
|
||||
.ok()
|
||||
.and_then(RwFlags::from_bits)
|
||||
.ok_or(Error::new(EINVAL))?,
|
||||
SYS_READ2 => {
|
||||
let bytes = file_op_generic_ext(fd, token, |scheme, _, desc, token| {
|
||||
let flags = if f == usize::MAX {
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
u32::try_from(f)
|
||||
.ok()
|
||||
.and_then(RwFlags::from_bits)
|
||||
.ok_or(Error::new(EINVAL))?,
|
||||
)
|
||||
};
|
||||
scheme.kreadoff(
|
||||
desc.number,
|
||||
UserSlice::wo(c, d)?,
|
||||
e as u64,
|
||||
flags.map_or(desc.flags, |f| desc.rw_flags(f)),
|
||||
desc.flags,
|
||||
token,
|
||||
)
|
||||
};
|
||||
scheme.kreadoff(
|
||||
desc.number,
|
||||
UserSlice::wo(c, d)?,
|
||||
e as u64,
|
||||
flags.map_or(desc.flags, |f| desc.rw_flags(f)),
|
||||
desc.flags,
|
||||
token,
|
||||
)
|
||||
}),
|
||||
})?;
|
||||
let current = context::current();
|
||||
let mut guard = current.write(token.token());
|
||||
guard.io_rchar = guard.io_rchar.saturating_add(bytes as u64);
|
||||
guard.io_syscr = guard.io_syscr.saturating_add(1);
|
||||
guard.io_read_bytes = guard.io_read_bytes.saturating_add(bytes as u64);
|
||||
Ok(bytes)
|
||||
}
|
||||
SYS_READ => sys_read(fd, UserSlice::wo(c, d)?, token),
|
||||
SYS_FPATH => file_op_generic(fd, token, |scheme, number, token| {
|
||||
scheme.kfpath(number, UserSlice::wo(c, d)?, token)
|
||||
|
||||
Reference in New Issue
Block a user