Files
DragonOS/kernel/src/mm/page_cache_stats.rs
T
LoGin 72ebe13f64 perf(virtiofs): batch non-DAX writeback (#2122)
* perf(virtiofs): batch non-DAX writeback

Buffer writes in the generic page cache only after FUSE_WRITEBACK_CACHE is negotiated, then claim and submit bounded contiguous batches according to the negotiated write and page limits.

Preserve Linux-compatible fsync, close, truncate, mmap, invalidation, stable EOF, redirty, short-write, and errseq behavior. Separate terminal writeback completion from generic page-cache workers so host invalidation cannot strand published Writeback pages behind its own waiters.

Harden kernel-thread creation and wakeup ordering required by the new worker pools. Add exact FUSE/page-cache counters, benchmark phase reporting, focused FUSE regressions, and root-only kthread and completion-domain selftests.

Validated with make kernel -j2, kernel formatting and diff checks, the completion-domain selftest, targeted close/flush coverage, and FuseExtended 69/69 in a DragonOS guest.

Signed-off-by: longjin <longjin@dragonos.org>

* refactor(fuse): group negotiated io limits

Pass negotiated read, write, page, capability, and effective payload limits through a dedicated stats value object.

This keeps the INIT statistics update cohesive and satisfies the project-wide Clippy argument-count lint enforced by make fmt without changing the negotiated values or publication ordering.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-07-15 19:59:02 +08:00

124 lines
3.3 KiB
Rust

use core::sync::atomic::{AtomicU64, Ordering};
#[derive(Debug, Default, Clone, Copy)]
pub struct PageCacheStatsSnapshot {
pub file_pages: u64,
pub file_mapped: u64,
pub file_dirty: u64,
pub file_writeback: u64,
pub shmem_pages: u64,
pub unevictable: u64,
pub drop_pagecache: u64,
pub read_dma_reservations: u64,
pub invalidation_launder_batches: u64,
pub invalidation_launder_pages: u64,
}
static FILE_PAGES: AtomicU64 = AtomicU64::new(0);
static FILE_MAPPED: AtomicU64 = AtomicU64::new(0);
static FILE_DIRTY: AtomicU64 = AtomicU64::new(0);
static FILE_WRITEBACK: AtomicU64 = AtomicU64::new(0);
static SHMEM_PAGES: AtomicU64 = AtomicU64::new(0);
static UNEVICTABLE: AtomicU64 = AtomicU64::new(0);
static DROP_PAGECACHE: AtomicU64 = AtomicU64::new(0);
static READ_DMA_RESERVATIONS: AtomicU64 = AtomicU64::new(0);
static INVALIDATION_LAUNDER_BATCHES: AtomicU64 = AtomicU64::new(0);
static INVALIDATION_LAUNDER_PAGES: AtomicU64 = AtomicU64::new(0);
#[inline]
pub fn inc_file_pages() {
FILE_PAGES.fetch_add(1, Ordering::Relaxed);
}
#[inline]
pub fn dec_file_pages() {
FILE_PAGES.fetch_sub(1, Ordering::Relaxed);
}
#[inline]
pub fn inc_file_mapped() {
FILE_MAPPED.fetch_add(1, Ordering::Relaxed);
}
#[inline]
pub fn dec_file_mapped() {
FILE_MAPPED.fetch_sub(1, Ordering::Relaxed);
}
#[inline]
pub fn inc_file_dirty() {
FILE_DIRTY.fetch_add(1, Ordering::Relaxed);
}
#[inline]
pub fn dec_file_dirty() {
FILE_DIRTY.fetch_sub(1, Ordering::Relaxed);
}
#[inline]
pub fn inc_file_writeback() {
FILE_WRITEBACK.fetch_add(1, Ordering::Relaxed);
}
#[inline]
pub fn dec_file_writeback() {
FILE_WRITEBACK.fetch_sub(1, Ordering::Relaxed);
}
#[inline]
pub fn inc_shmem_pages() {
SHMEM_PAGES.fetch_add(1, Ordering::Relaxed);
}
#[inline]
pub fn dec_shmem_pages() {
SHMEM_PAGES.fetch_sub(1, Ordering::Relaxed);
}
#[inline]
pub fn inc_unevictable() {
UNEVICTABLE.fetch_add(1, Ordering::Relaxed);
}
#[inline]
pub fn dec_unevictable() {
UNEVICTABLE.fetch_sub(1, Ordering::Relaxed);
}
#[inline]
pub fn inc_drop_pagecache() {
DROP_PAGECACHE.fetch_add(1, Ordering::Relaxed);
}
#[inline]
pub fn begin_read_dma_reservation() {
READ_DMA_RESERVATIONS.fetch_add(1, Ordering::AcqRel);
}
#[inline]
pub fn end_read_dma_reservation() {
READ_DMA_RESERVATIONS.fetch_sub(1, Ordering::AcqRel);
}
#[inline]
pub fn record_invalidation_launder_batch(pages: usize) {
INVALIDATION_LAUNDER_BATCHES.fetch_add(1, Ordering::Relaxed);
INVALIDATION_LAUNDER_PAGES.fetch_add(pages as u64, Ordering::Relaxed);
}
#[inline]
pub fn snapshot() -> PageCacheStatsSnapshot {
PageCacheStatsSnapshot {
file_pages: FILE_PAGES.load(Ordering::Relaxed),
file_mapped: FILE_MAPPED.load(Ordering::Relaxed),
file_dirty: FILE_DIRTY.load(Ordering::Relaxed),
file_writeback: FILE_WRITEBACK.load(Ordering::Relaxed),
shmem_pages: SHMEM_PAGES.load(Ordering::Relaxed),
unevictable: UNEVICTABLE.load(Ordering::Relaxed),
drop_pagecache: DROP_PAGECACHE.load(Ordering::Relaxed),
read_dma_reservations: READ_DMA_RESERVATIONS.load(Ordering::Acquire),
invalidation_launder_batches: INVALIDATION_LAUNDER_BATCHES.load(Ordering::Relaxed),
invalidation_launder_pages: INVALIDATION_LAUNDER_PAGES.load(Ordering::Relaxed),
}
}