From f8e8637d067e2775db004f0d01d9c5423d20f354 Mon Sep 17 00:00:00 2001 From: lsig Date: Tue, 21 Oct 2025 18:51:49 -0400 Subject: [PATCH 001/131] [Setup] Load and unload LFS Rust kernel module --- fs/Kconfig | 1 + fs/Makefile | 1 + fs/rustlfs/Kconfig | 12 ++++++++++++ fs/rustlfs/Makefile | 4 ++++ fs/rustlfs/lib.rs | 28 ++++++++++++++++++++++++++++ 5 files changed, 46 insertions(+) create mode 100644 fs/rustlfs/Kconfig create mode 100644 fs/rustlfs/Makefile create mode 100644 fs/rustlfs/lib.rs diff --git a/fs/Kconfig b/fs/Kconfig index 0bfdaecaa87751..27dcbb93359505 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -418,6 +418,7 @@ endif # NETWORK_FILESYSTEMS source "fs/nls/Kconfig" source "fs/dlm/Kconfig" source "fs/unicode/Kconfig" +source "fs/rustlfs/Kconfig" config IO_WQ bool diff --git a/fs/Makefile b/fs/Makefile index e3523ab2e58713..1637fc9ae0c499 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -129,3 +129,4 @@ obj-$(CONFIG_VBOXSF_FS) += vboxsf/ obj-$(CONFIG_ZONEFS_FS) += zonefs/ obj-$(CONFIG_BPF_LSM) += bpf_fs_kfuncs.o obj-$(CONFIG_RESCTRL_FS) += resctrl/ +obj-$(CONFIG_RUSTLFS) += rustlfs/ diff --git a/fs/rustlfs/Kconfig b/fs/rustlfs/Kconfig new file mode 100644 index 00000000000000..b2f857b01b45a6 --- /dev/null +++ b/fs/rustlfs/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 + +config RUSTLFS + tristate "RustLFS filesystem support" + depends on RUST + help + This is a log-structured filesystem written in Rust. + + To compile this as a module, choose M here: the module + will be called rustlfs. + + If unsure, say N. diff --git a/fs/rustlfs/Makefile b/fs/rustlfs/Makefile new file mode 100644 index 00000000000000..e4c5af7477b8d9 --- /dev/null +++ b/fs/rustlfs/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_RUSTLFS) += rustlfs.o +rustlfs-y := lib.o diff --git a/fs/rustlfs/lib.rs b/fs/rustlfs/lib.rs new file mode 100644 index 00000000000000..d768174c4e47f6 --- /dev/null +++ b/fs/rustlfs/lib.rs @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Log-based filesystem written in Rust + +use kernel::prelude::*; + +module! { + type: RustLFS, + name: "rustlfs", + authors: ["ls4121@columbia.edu", "kfb2117@columbia.edu"], + description: "Log-based file system in Rust", + license: "GPL", +} + +struct RustLFS; + +impl kernel::Module for RustLFS { + fn init(_module: &'static ThisModule) -> Result { + pr_info!("RustLFS loaded\n"); + Ok(RustLFS) + } +} + +impl Drop for RustLFS { + fn drop(&mut self) { + pr_info!("RustLFS unloaded\n") + } +} From 0074ac700ec03dbb6f8dcb7513a1e69bc3e256a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Tue, 28 Oct 2025 23:11:45 -0400 Subject: [PATCH 002/131] add gitignore --- fs/rustlfs/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 fs/rustlfs/.gitignore diff --git a/fs/rustlfs/.gitignore b/fs/rustlfs/.gitignore new file mode 100644 index 00000000000000..0b7adf84867679 --- /dev/null +++ b/fs/rustlfs/.gitignore @@ -0,0 +1 @@ +rust-project.json From 21818fd952201cc98f35bb826c82e33895c430e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Tue, 28 Oct 2025 23:13:07 -0400 Subject: [PATCH 003/131] setup fs modules --- fs/rustlfs/lib.rs | 17 ++----- rust/kernel/fs.rs | 114 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 13 deletions(-) diff --git a/fs/rustlfs/lib.rs b/fs/rustlfs/lib.rs index d768174c4e47f6..8f5c454531201f 100644 --- a/fs/rustlfs/lib.rs +++ b/fs/rustlfs/lib.rs @@ -2,9 +2,9 @@ //! Log-based filesystem written in Rust -use kernel::prelude::*; +use kernel::{c_str, fs, module_fs, prelude::*}; -module! { +module_fs! { type: RustLFS, name: "rustlfs", authors: ["ls4121@columbia.edu", "kfb2117@columbia.edu"], @@ -14,15 +14,6 @@ module! { struct RustLFS; -impl kernel::Module for RustLFS { - fn init(_module: &'static ThisModule) -> Result { - pr_info!("RustLFS loaded\n"); - Ok(RustLFS) - } -} - -impl Drop for RustLFS { - fn drop(&mut self) { - pr_info!("RustLFS unloaded\n") - } +impl fs::Type for RustLFS { + const NAME: &'static CStr = c_str!("rustlfs"); } diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs index 6ba6bdf143cb99..1afe68b99d130f 100644 --- a/rust/kernel/fs.rs +++ b/rust/kernel/fs.rs @@ -4,8 +4,122 @@ //! //! C headers: [`include/linux/fs.h`](srctree/include/linux/fs.h) +use crate::{ + alloc::{flags, Allocator, KBox}, + bindings, + error::code::EINVAL, + error::{to_result, Error, Result}, + pr_info, + prelude::Box, + str::CStr, + ThisModule, +}; +use core::{ + cell::UnsafeCell, + marker::{PhantomData, PhantomPinned, Send, Sync}, + pin::Pin, +}; + pub mod file; pub use self::file::{File, LocalFile}; mod kiocb; pub use self::kiocb::Kiocb; + +/// A file system type. +pub trait Type { + /// The name of the file system type. + const NAME: &'static CStr; +} + +/// A file system registration. +#[derive(Default)] +pub struct Registration { + is_registered: bool, + fs: UnsafeCell, + _pin: PhantomPinned, +} + +impl Registration { + /// Creates a new file system registration. + /// + /// It is not visible or accessible yet. A successful call to [`Registration::register`] needs + /// to be made before users can mount it. + pub fn new() -> Self { + Self { + is_registered: false, + fs: UnsafeCell::new(bindings::file_system_type::default()), + _pin: PhantomPinned, + } + } + + pub fn register(self: Pin<&mut Self>, module: &'static ThisModule) -> Result { + // SAFETY: We never move out of `this`. + let this = unsafe { self.get_unchecked_mut() }; + + if this.is_registered { + return Err(EINVAL); + } + + this.is_registered = true; + Ok(()) + } +} + +// SAFETY: `Registration` doesn't really provide any `&self` methods, so it is safe to pass +// references to it around. +unsafe impl Sync for Registration {} + +// SAFETY: Both registration and unregistration are implemented in C and safe to be performed from +// any thread, so `Registration` is `Send`. +unsafe impl Send for Registration {} + +impl Drop for Registration { + fn drop(&mut self) { + if self.is_registered { + pr_info!("Unloading FS module\n"); + + // SAFETY: When `is_registered` is `true`, a previous call to `register_filesystem` has + // succeeded, so it is safe to unregister here. + // unsafe { bindings::unregister_filesystem(self.fs.get()) }; + } + } +} + +/// Kernel module that exposes a single file system implemented by `T`. +pub struct Module { + _fs: Pin>, + _p: PhantomData, +} + +impl crate::Module for Module { + fn init(module: &'static ThisModule) -> Result { + pr_info!("Loading FS module\n"); + let reg = Registration::new(); + let kbox = KBox::::new(reg, flags::GFP_KERNEL)?; + let mut reg = Pin::from(kbox); + + reg.as_mut().register::(module)?; + + Ok(Self { + _fs: reg, + _p: PhantomData, + }) + } +} + +#[macro_export] +macro_rules! module_fs { + (type: $ty:ty, $($rest:tt)*) => { + struct __FsModuleWrapper($crate::fs::Module<$ty>); + impl $crate::Module for __FsModuleWrapper { + fn init(module: &'static $crate::ThisModule) + -> $crate::error::Result + { + let inner = < $crate::fs::Module<$ty> as $crate::Module >::init(module)?; + Ok(Self(inner)) + } + } + $crate::macros::module! { type: __FsModuleWrapper, $($rest)* } + }; +} From 4642fd5cb17c48a3939f1d779f2d645fcfffb36a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Wed, 29 Oct 2025 16:12:47 -0400 Subject: [PATCH 004/131] register+unregister nop FS --- rust/kernel/fs.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs index 1afe68b99d130f..fdb893d15a7511 100644 --- a/rust/kernel/fs.rs +++ b/rust/kernel/fs.rs @@ -61,6 +61,16 @@ impl Registration { return Err(EINVAL); } + let mut fs = this.fs.get_mut(); + fs.owner = module.0; + fs.name = T::NAME.as_char_ptr(); + + let ptr = this.fs.get(); + + // SAFETY: Pointers stored in `fs` are either static so will live for as long as the + // registration is active (it is undone in `drop`). + to_result(unsafe { bindings::register_filesystem(ptr) })?; + this.is_registered = true; Ok(()) } @@ -81,7 +91,7 @@ impl Drop for Registration { // SAFETY: When `is_registered` is `true`, a previous call to `register_filesystem` has // succeeded, so it is safe to unregister here. - // unsafe { bindings::unregister_filesystem(self.fs.get()) }; + unsafe { bindings::unregister_filesystem(self.fs.get()) }; } } } From d60f0c966e74b3d755bde8548841700c25609e84 Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 29 Oct 2025 18:15:19 -0400 Subject: [PATCH 005/131] [RustLFS] file system specific inode --- fs/rustlfs/inode.rs | 15 +++++++++++++++ fs/rustlfs/lib.rs | 1 + 2 files changed, 16 insertions(+) create mode 100644 fs/rustlfs/inode.rs diff --git a/fs/rustlfs/inode.rs b/fs/rustlfs/inode.rs new file mode 100644 index 00000000000000..855533d6b55573 --- /dev/null +++ b/fs/rustlfs/inode.rs @@ -0,0 +1,15 @@ +use kernel::uapi::{gid_t, mode_t, uid_t}; + +#[repr(C)] +pub(crate) struct EzfsInode { + mode: mode_t, + uid: uid_t, + gid: gid_t, + i_attime: i64, /* access time */ + i_mtime: i64, /* modified time */ + i_ctime: i64, /* change time */ + nlink: u32, + data_blk_num: u64, + file_size: u64, + nblocks: u64, +} diff --git a/fs/rustlfs/lib.rs b/fs/rustlfs/lib.rs index 8f5c454531201f..09974bb1e180dc 100644 --- a/fs/rustlfs/lib.rs +++ b/fs/rustlfs/lib.rs @@ -2,6 +2,7 @@ //! Log-based filesystem written in Rust +mod inode; use kernel::{c_str, fs, module_fs, prelude::*}; module_fs! { From e3566e69f6bdcfcf577b937c2fb13e9e8251496f Mon Sep 17 00:00:00 2001 From: lsig Date: Tue, 11 Nov 2025 16:54:19 -0500 Subject: [PATCH 006/131] [ezFS] add critical structure for ezFS --- fs/rustlfs/defs.rs | 17 +++++++++++++++++ fs/rustlfs/dir.rs | 8 ++++++++ fs/rustlfs/lib.rs | 5 ++++- fs/rustlfs/sb.rs | 25 +++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 fs/rustlfs/defs.rs create mode 100644 fs/rustlfs/dir.rs create mode 100644 fs/rustlfs/sb.rs diff --git a/fs/rustlfs/defs.rs b/fs/rustlfs/defs.rs new file mode 100644 index 00000000000000..1bf3dd21ad726d --- /dev/null +++ b/fs/rustlfs/defs.rs @@ -0,0 +1,17 @@ +use crate::dir::EzfsDirEntry; +use crate::inode::EzfsInode; +use core::mem::size_of; + +pub(crate) const EZFS_FILENAME_BUF_SIZE: usize = 128 - 8 - 1; +pub(crate) const EZFS_FILENAME_LENGTH: usize = EZFS_FILENAME_BUF_SIZE - 1; + +pub(crate) const EZFS_MAGIC_NUMBER: usize = 0x00004118; +pub(crate) const EZFS_BLOCK_SIZE: usize = 4096; +pub(crate) const EZFS_ROOT_INODE_NUMBER: usize = 1; +pub(crate) const EZFS_SUPERBLOCK_DATABLOCK_NUMBER: usize = 0; +pub(crate) const EZFS_INODE_STORE_DATABLOCK_NUMBER: usize = 1; +pub(crate) const EZFS_ROOT_DATABLOCK_NUMBER: usize = 2; + +pub(crate) const EZFS_MAX_INODES: usize = EZFS_BLOCK_SIZE / size_of::(); +pub(crate) const EZFS_MAX_DATA_BLKS: usize = EZFS_MAX_INODES * 256; +pub(crate) const EZFS_MAX_CHILDREN: usize = EZFS_BLOCK_SIZE / size_of::; diff --git a/fs/rustlfs/dir.rs b/fs/rustlfs/dir.rs new file mode 100644 index 00000000000000..82f057ea26d29f --- /dev/null +++ b/fs/rustlfs/dir.rs @@ -0,0 +1,8 @@ +use crate::defs::EZFS_FILENAME_BUF_SIZE; + +#[repr(C)] +pub(crate) struct EzfsDirEntry { + inode_no: u64, + active: u8, + filename: [char; EZFS_FILENAME_BUF_SIZE], +} diff --git a/fs/rustlfs/lib.rs b/fs/rustlfs/lib.rs index 09974bb1e180dc..50854d4d1537ed 100644 --- a/fs/rustlfs/lib.rs +++ b/fs/rustlfs/lib.rs @@ -2,8 +2,11 @@ //! Log-based filesystem written in Rust +mod defs; +mod dir; mod inode; -use kernel::{c_str, fs, module_fs, prelude::*}; +mod sb; +use kernel::{c_str, fs, module_fs, prelude::*, str::CStr}; module_fs! { type: RustLFS, diff --git a/fs/rustlfs/sb.rs b/fs/rustlfs/sb.rs new file mode 100644 index 00000000000000..0121c01a790fb2 --- /dev/null +++ b/fs/rustlfs/sb.rs @@ -0,0 +1,25 @@ +use crate::defs::{EZFS_BLOCK_SIZE, EZFS_MAX_DATA_BLKS, EZFS_MAX_INODES}; +use core::mem::size_of; +use kernel::sync::Mutex; + +// TODO: assert size is equal to 4096 bytes +#[repr(C)] +pub(crate) struct EzfsSuperblockDisk { + magic: u64, + disk_blocks: u64, + free_inodes: [u8; EZFS_MAX_INODES], + free_data_blocks: [u8; EZFS_MAX_DATA_BLKS], + zero_data_blocks: [u8; EZFS_MAX_DATA_BLKS], + padding: + [u8; EZFS_BLOCK_SIZE - EZFS_MAX_INODES - EZFS_MAX_DATA_BLKS * 2 - size_of::() * 2], +} + +// TODO: pin data because of mutexes +// in-memory representation of sb +pub(crate) struct EzfsSuperblock { + magic: u64, + disk_blocks: u64, + free_inodes: Mutex<[u8; EZFS_MAX_INODES]>, + free_data_blocks: Mutex<[u8; EZFS_MAX_DATA_BLKS]>, + zero_data_blocks: Mutex<[u8; EZFS_MAX_DATA_BLKS]>, +} From 422b2ef9bb29ca8fd5d7c5866fa5c272bbbe9208 Mon Sep 17 00:00:00 2001 From: lsig Date: Tue, 11 Nov 2025 17:34:21 -0500 Subject: [PATCH 007/131] [ezFS] fix compiler errors --- fs/rustlfs/defs.rs | 2 +- fs/rustlfs/sb.rs | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/fs/rustlfs/defs.rs b/fs/rustlfs/defs.rs index 1bf3dd21ad726d..a293a541bbb95d 100644 --- a/fs/rustlfs/defs.rs +++ b/fs/rustlfs/defs.rs @@ -14,4 +14,4 @@ pub(crate) const EZFS_ROOT_DATABLOCK_NUMBER: usize = 2; pub(crate) const EZFS_MAX_INODES: usize = EZFS_BLOCK_SIZE / size_of::(); pub(crate) const EZFS_MAX_DATA_BLKS: usize = EZFS_MAX_INODES * 256; -pub(crate) const EZFS_MAX_CHILDREN: usize = EZFS_BLOCK_SIZE / size_of::; +pub(crate) const EZFS_MAX_CHILDREN: usize = EZFS_BLOCK_SIZE / size_of::(); diff --git a/fs/rustlfs/sb.rs b/fs/rustlfs/sb.rs index 0121c01a790fb2..3b7e90d9ffbee7 100644 --- a/fs/rustlfs/sb.rs +++ b/fs/rustlfs/sb.rs @@ -2,16 +2,19 @@ use crate::defs::{EZFS_BLOCK_SIZE, EZFS_MAX_DATA_BLKS, EZFS_MAX_INODES}; use core::mem::size_of; use kernel::sync::Mutex; +pub(crate) struct EzfsSuperblockDiskRaw { + magic: u64, + disk_blocks: u64, + free_inodes: [u32; (EZFS_MAX_INODES / 32) + 1], + free_data_blocks: [u32; (EZFS_MAX_DATA_BLKS / 32) + 1], + zero_data_blocks: [u8; (EZFS_MAX_DATA_BLKS / 32) + 1], +} + // TODO: assert size is equal to 4096 bytes #[repr(C)] pub(crate) struct EzfsSuperblockDisk { - magic: u64, - disk_blocks: u64, - free_inodes: [u8; EZFS_MAX_INODES], - free_data_blocks: [u8; EZFS_MAX_DATA_BLKS], - zero_data_blocks: [u8; EZFS_MAX_DATA_BLKS], - padding: - [u8; EZFS_BLOCK_SIZE - EZFS_MAX_INODES - EZFS_MAX_DATA_BLKS * 2 - size_of::() * 2], + data: EzfsSuperblockDiskRaw, + _padding: [u8; EZFS_BLOCK_SIZE - size_of::()], } // TODO: pin data because of mutexes @@ -19,7 +22,7 @@ pub(crate) struct EzfsSuperblockDisk { pub(crate) struct EzfsSuperblock { magic: u64, disk_blocks: u64, - free_inodes: Mutex<[u8; EZFS_MAX_INODES]>, - free_data_blocks: Mutex<[u8; EZFS_MAX_DATA_BLKS]>, - zero_data_blocks: Mutex<[u8; EZFS_MAX_DATA_BLKS]>, + free_inodes: Mutex<[u32; (EZFS_MAX_INODES / 32) + 1]>, + free_data_blocks: Mutex<[u32; (EZFS_MAX_DATA_BLKS / 32) + 1]>, + zero_data_blocks: Mutex<[u8; (EZFS_MAX_DATA_BLKS / 32) + 1]>, } From ad869093fd9b69e4aa2c980cd91531085b893728 Mon Sep 17 00:00:00 2001 From: lsig Date: Tue, 11 Nov 2025 17:35:20 -0500 Subject: [PATCH 008/131] [ezFS] fix comment --- fs/rustlfs/sb.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/rustlfs/sb.rs b/fs/rustlfs/sb.rs index 3b7e90d9ffbee7..afda1fab75b77e 100644 --- a/fs/rustlfs/sb.rs +++ b/fs/rustlfs/sb.rs @@ -11,6 +11,7 @@ pub(crate) struct EzfsSuperblockDiskRaw { } // TODO: assert size is equal to 4096 bytes +// in-memory representation of sb #[repr(C)] pub(crate) struct EzfsSuperblockDisk { data: EzfsSuperblockDiskRaw, @@ -18,7 +19,6 @@ pub(crate) struct EzfsSuperblockDisk { } // TODO: pin data because of mutexes -// in-memory representation of sb pub(crate) struct EzfsSuperblock { magic: u64, disk_blocks: u64, From c7a6e883305b8079922b2c3883087640c7273078 Mon Sep 17 00:00:00 2001 From: lsig Date: Tue, 11 Nov 2025 17:36:01 -0500 Subject: [PATCH 009/131] [ezFS] fix comment again burhh --- fs/rustlfs/sb.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/rustlfs/sb.rs b/fs/rustlfs/sb.rs index afda1fab75b77e..3b7e90d9ffbee7 100644 --- a/fs/rustlfs/sb.rs +++ b/fs/rustlfs/sb.rs @@ -11,7 +11,6 @@ pub(crate) struct EzfsSuperblockDiskRaw { } // TODO: assert size is equal to 4096 bytes -// in-memory representation of sb #[repr(C)] pub(crate) struct EzfsSuperblockDisk { data: EzfsSuperblockDiskRaw, @@ -19,6 +18,7 @@ pub(crate) struct EzfsSuperblockDisk { } // TODO: pin data because of mutexes +// in-memory representation of sb pub(crate) struct EzfsSuperblock { magic: u64, disk_blocks: u64, From 3f9937fffad84e0f416703344b7b939dba9513a5 Mon Sep 17 00:00:00 2001 From: lsig Date: Mon, 17 Nov 2025 19:15:50 -0500 Subject: [PATCH 010/131] [ezFS] register + unregister nop FS v2 --- fs/Kconfig | 2 +- fs/Makefile | 2 +- fs/{rustlfs => rustezfs}/.gitignore | 0 fs/{rustlfs => rustezfs}/Kconfig | 0 fs/rustezfs/Makefile | 4 + fs/{rustlfs => rustezfs}/defs.rs | 0 fs/{rustlfs => rustezfs}/dir.rs | 0 fs/rustezfs/ezfs.rs | 46 +++++++++++ fs/{rustlfs => rustezfs}/inode.rs | 0 fs/{rustlfs => rustezfs}/sb.rs | 6 ++ fs/rustlfs/Makefile | 4 - fs/rustlfs/lib.rs | 23 ------ rust/kernel/fs.rs | 119 ++++++++-------------------- 13 files changed, 90 insertions(+), 116 deletions(-) rename fs/{rustlfs => rustezfs}/.gitignore (100%) rename fs/{rustlfs => rustezfs}/Kconfig (100%) create mode 100644 fs/rustezfs/Makefile rename fs/{rustlfs => rustezfs}/defs.rs (100%) rename fs/{rustlfs => rustezfs}/dir.rs (100%) create mode 100644 fs/rustezfs/ezfs.rs rename fs/{rustlfs => rustezfs}/inode.rs (100%) rename fs/{rustlfs => rustezfs}/sb.rs (92%) delete mode 100644 fs/rustlfs/Makefile delete mode 100644 fs/rustlfs/lib.rs diff --git a/fs/Kconfig b/fs/Kconfig index 27dcbb93359505..7e5c014a41bc72 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -418,7 +418,7 @@ endif # NETWORK_FILESYSTEMS source "fs/nls/Kconfig" source "fs/dlm/Kconfig" source "fs/unicode/Kconfig" -source "fs/rustlfs/Kconfig" +source "fs/rustezfs/Kconfig" config IO_WQ bool diff --git a/fs/Makefile b/fs/Makefile index 1637fc9ae0c499..7d3288024179cf 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -129,4 +129,4 @@ obj-$(CONFIG_VBOXSF_FS) += vboxsf/ obj-$(CONFIG_ZONEFS_FS) += zonefs/ obj-$(CONFIG_BPF_LSM) += bpf_fs_kfuncs.o obj-$(CONFIG_RESCTRL_FS) += resctrl/ -obj-$(CONFIG_RUSTLFS) += rustlfs/ +obj-$(CONFIG_RUSTLFS) += rustezfs/ diff --git a/fs/rustlfs/.gitignore b/fs/rustezfs/.gitignore similarity index 100% rename from fs/rustlfs/.gitignore rename to fs/rustezfs/.gitignore diff --git a/fs/rustlfs/Kconfig b/fs/rustezfs/Kconfig similarity index 100% rename from fs/rustlfs/Kconfig rename to fs/rustezfs/Kconfig diff --git a/fs/rustezfs/Makefile b/fs/rustezfs/Makefile new file mode 100644 index 00000000000000..66728a35a78669 --- /dev/null +++ b/fs/rustezfs/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_RUSTLFS) += rustezfs.o +rustezfs-y := ezfs.o diff --git a/fs/rustlfs/defs.rs b/fs/rustezfs/defs.rs similarity index 100% rename from fs/rustlfs/defs.rs rename to fs/rustezfs/defs.rs diff --git a/fs/rustlfs/dir.rs b/fs/rustezfs/dir.rs similarity index 100% rename from fs/rustlfs/dir.rs rename to fs/rustezfs/dir.rs diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs new file mode 100644 index 00000000000000..49e02ac0aeb7ac --- /dev/null +++ b/fs/rustezfs/ezfs.rs @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Log-based filesystem written in Rust + +mod defs; +mod dir; +mod inode; +mod sb; +use kernel::fs::{FileSystem, Registration}; +use kernel::prelude::*; +use kernel::{c_str, fs, str::CStr}; + +use core::marker::{PhantomData, Send, Sync}; +use pin_init::{pin_data, PinInit, PinnedDrop}; + +struct RustEzFs; + +#[pin_data] +struct RustEzFsModule { + #[pin] + fs_reg: Registration, + _p: PhantomData, +} + +impl kernel::InPlaceModule for RustEzFsModule { + fn init(module: &'static ThisModule) -> impl PinInit { + try_pin_init!(Self { + fs_reg <- Registration::new::(module), + _p: PhantomData, + }) + } +} + +impl FileSystem for RustEzFs { + const NAME: &'static CStr = c_str!("rustezfs"); +} + +type FsModule = RustEzFsModule; + +module! { + type: FsModule, + name: "rustezfs", + authors: ["ls4121@columbia.edu", "kfb2117@columbia.edu"], + description: "Easy file system in Rust", + license: "GPL", +} diff --git a/fs/rustlfs/inode.rs b/fs/rustezfs/inode.rs similarity index 100% rename from fs/rustlfs/inode.rs rename to fs/rustezfs/inode.rs diff --git a/fs/rustlfs/sb.rs b/fs/rustezfs/sb.rs similarity index 92% rename from fs/rustlfs/sb.rs rename to fs/rustezfs/sb.rs index 3b7e90d9ffbee7..3292fd970457e5 100644 --- a/fs/rustlfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -26,3 +26,9 @@ pub(crate) struct EzfsSuperblock { free_data_blocks: Mutex<[u32; (EZFS_MAX_DATA_BLKS / 32) + 1]>, zero_data_blocks: Mutex<[u8; (EZFS_MAX_DATA_BLKS / 32) + 1]>, } + +impl EzfsSuperblock { + // fn fill_super() {} + + // fn init_root() {} +} diff --git a/fs/rustlfs/Makefile b/fs/rustlfs/Makefile deleted file mode 100644 index e4c5af7477b8d9..00000000000000 --- a/fs/rustlfs/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -obj-$(CONFIG_RUSTLFS) += rustlfs.o -rustlfs-y := lib.o diff --git a/fs/rustlfs/lib.rs b/fs/rustlfs/lib.rs deleted file mode 100644 index 50854d4d1537ed..00000000000000 --- a/fs/rustlfs/lib.rs +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -//! Log-based filesystem written in Rust - -mod defs; -mod dir; -mod inode; -mod sb; -use kernel::{c_str, fs, module_fs, prelude::*, str::CStr}; - -module_fs! { - type: RustLFS, - name: "rustlfs", - authors: ["ls4121@columbia.edu", "kfb2117@columbia.edu"], - description: "Log-based file system in Rust", - license: "GPL", -} - -struct RustLFS; - -impl fs::Type for RustLFS { - const NAME: &'static CStr = c_str!("rustlfs"); -} diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs index fdb893d15a7511..15a8139a828a5f 100644 --- a/rust/kernel/fs.rs +++ b/rust/kernel/fs.rs @@ -4,19 +4,18 @@ //! //! C headers: [`include/linux/fs.h`](srctree/include/linux/fs.h) +use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop}; + use crate::{ - alloc::{flags, Allocator, KBox}, bindings, - error::code::EINVAL, - error::{to_result, Error, Result}, - pr_info, - prelude::Box, + error::{to_result, Error}, str::CStr, + try_pin_init, + types::Opaque, ThisModule, }; use core::{ - cell::UnsafeCell, - marker::{PhantomData, PhantomPinned, Send, Sync}, + marker::{Send, Sync}, pin::Pin, }; @@ -27,17 +26,16 @@ mod kiocb; pub use self::kiocb::Kiocb; /// A file system type. -pub trait Type { +pub trait FileSystem { /// The name of the file system type. const NAME: &'static CStr; } /// A file system registration. -#[derive(Default)] +#[pin_data(PinnedDrop)] pub struct Registration { - is_registered: bool, - fs: UnsafeCell, - _pin: PhantomPinned, + #[pin] + fs: Opaque, } impl Registration { @@ -45,34 +43,21 @@ impl Registration { /// /// It is not visible or accessible yet. A successful call to [`Registration::register`] needs /// to be made before users can mount it. - pub fn new() -> Self { - Self { - is_registered: false, - fs: UnsafeCell::new(bindings::file_system_type::default()), - _pin: PhantomPinned, - } - } - - pub fn register(self: Pin<&mut Self>, module: &'static ThisModule) -> Result { - // SAFETY: We never move out of `this`. - let this = unsafe { self.get_unchecked_mut() }; - - if this.is_registered { - return Err(EINVAL); - } - - let mut fs = this.fs.get_mut(); - fs.owner = module.0; - fs.name = T::NAME.as_char_ptr(); - - let ptr = this.fs.get(); - - // SAFETY: Pointers stored in `fs` are either static so will live for as long as the - // registration is active (it is undone in `drop`). - to_result(unsafe { bindings::register_filesystem(ptr) })?; - - this.is_registered = true; - Ok(()) + pub fn new(module: &'static ThisModule) -> impl PinInit { + try_pin_init!(Self { + fs <- Opaque::try_ffi_init(|fs_ptr: *mut bindings::file_system_type| { + // SAFETY: `try_ffi_init` guarantees that `fs_ptr` is valid for write. + unsafe { fs_ptr.write(bindings::file_system_type::default()) }; + + let fs = unsafe { &mut *fs_ptr }; + fs.owner = module.0; + fs.name = T::NAME.as_char_ptr(); + + // SAFETY: Pointers stored in `fs` are static so will live for as long as the + // registration is active (it is undone in `drop`). + to_result(unsafe { bindings::register_filesystem(fs_ptr) }) + }), + }) } } @@ -84,52 +69,12 @@ unsafe impl Sync for Registration {} // any thread, so `Registration` is `Send`. unsafe impl Send for Registration {} -impl Drop for Registration { - fn drop(&mut self) { - if self.is_registered { - pr_info!("Unloading FS module\n"); - - // SAFETY: When `is_registered` is `true`, a previous call to `register_filesystem` has - // succeeded, so it is safe to unregister here. - unsafe { bindings::unregister_filesystem(self.fs.get()) }; - } +#[pinned_drop] +impl PinnedDrop for Registration { + fn drop(self: Pin<&mut Self>) { + // SAFETY: If an instance of `Self` has been successfully created, a call to + // `register_filesystem` has necessarily succeeded. So it's ok to call + // `unregister_filesystem` on the previously registered fs. + unsafe { bindings::unregister_filesystem(self.fs.get()) }; } } - -/// Kernel module that exposes a single file system implemented by `T`. -pub struct Module { - _fs: Pin>, - _p: PhantomData, -} - -impl crate::Module for Module { - fn init(module: &'static ThisModule) -> Result { - pr_info!("Loading FS module\n"); - let reg = Registration::new(); - let kbox = KBox::::new(reg, flags::GFP_KERNEL)?; - let mut reg = Pin::from(kbox); - - reg.as_mut().register::(module)?; - - Ok(Self { - _fs: reg, - _p: PhantomData, - }) - } -} - -#[macro_export] -macro_rules! module_fs { - (type: $ty:ty, $($rest:tt)*) => { - struct __FsModuleWrapper($crate::fs::Module<$ty>); - impl $crate::Module for __FsModuleWrapper { - fn init(module: &'static $crate::ThisModule) - -> $crate::error::Result - { - let inner = < $crate::fs::Module<$ty> as $crate::Module >::init(module)?; - Ok(Self(inner)) - } - } - $crate::macros::module! { type: __FsModuleWrapper, $($rest)* } - }; -} From a8dd3ef0c7c9bde9fe2db4d4719c77a98a2dcd8e Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 19 Nov 2025 21:50:16 -0500 Subject: [PATCH 011/131] [VFS] mount checkpoint --- fs/rustezfs/ezfs.rs | 24 +++ rust/bindings/bindings_helper.h | 1 + rust/helpers/dcache.c | 8 + rust/helpers/fs.c | 10 ++ rust/helpers/helpers.c | 3 + rust/helpers/kdev.c | 8 + rust/helpers/pagemap.c | 8 + rust/kernel/block.rs | 46 ++++++ rust/kernel/dentry.rs | 72 ++++++++ rust/kernel/fs.rs | 180 +++++++++++++++++++- rust/kernel/inode.rs | 282 ++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 3 + rust/kernel/sb.rs | 126 ++++++++++++++ rust/kernel/time.rs | 51 ++++++ 14 files changed, 818 insertions(+), 4 deletions(-) create mode 100644 rust/helpers/dcache.c create mode 100644 rust/helpers/kdev.c create mode 100644 rust/helpers/pagemap.c create mode 100644 rust/kernel/dentry.rs create mode 100644 rust/kernel/inode.rs create mode 100644 rust/kernel/sb.rs diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 49e02ac0aeb7ac..9bc44f0707163f 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -6,8 +6,12 @@ mod defs; mod dir; mod inode; mod sb; +use kernel::dentry::Root; use kernel::fs::{FileSystem, Registration}; +use kernel::inode::{INode, INodeState, Mapper}; use kernel::prelude::*; +use kernel::sb::{New, SuperBlock}; +use kernel::types::ARef; use kernel::{c_str, fs, str::CStr}; use core::marker::{PhantomData, Send, Sync}; @@ -31,8 +35,28 @@ impl kernel::InPlaceModule for RustEzFsModule { } } +impl RustEzFs { + fn iget(sb: &SuperBlock, ino: usize) -> Result>> { + let mut new = match sb.get_or_create_inode(ino)? { + INodeState::Existing(inode) => return Ok(inode), + INodeState::Uninitilized(new_inode) => new_inode, + }; + todo!() + } +} + impl FileSystem for RustEzFs { + type Data = KBox; + type INodeData = (); const NAME: &'static CStr = c_str!("rustezfs"); + + fn fill_super(sb: &mut SuperBlock, _: Option>) -> Result { + todo!() + } + + fn init_root(_: &SuperBlock) -> Result> { + todo!() + } } type FsModule = RustEzFsModule; diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 2e43c66635a2c9..8f10a4e24906d3 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/helpers/dcache.c b/rust/helpers/dcache.c new file mode 100644 index 00000000000000..a1036599c80472 --- /dev/null +++ b/rust/helpers/dcache.c @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +struct dentry *rust_helper_dget(struct dentry *dentry) +{ + return dget(dentry); +} diff --git a/rust/helpers/fs.c b/rust/helpers/fs.c index a75c9676337246..1dec5a12959e32 100644 --- a/rust/helpers/fs.c +++ b/rust/helpers/fs.c @@ -10,3 +10,13 @@ struct file *rust_helper_get_file(struct file *f) { return get_file(f); } + +void rust_helper_i_uid_write(struct inode *inode, uid_t uid) +{ + i_uid_write(inode, uid); +} + +void rust_helper_i_gid_write(struct inode *inode, gid_t gid) +{ + i_gid_write(inode, gid); +} diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index 551da6c9b5064c..c529904b10bf81 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -24,6 +24,7 @@ #include "cpumask.c" #include "cred.c" #include "device.c" +#include "dcache.c" #include "dma.c" #include "drm.c" #include "err.c" @@ -31,12 +32,14 @@ #include "fs.c" #include "io.c" #include "jump_label.c" +#include "kdev.c" #include "kunit.c" #include "maple_tree.c" #include "mm.c" #include "mutex.c" #include "of.c" #include "page.c" +#include "pagemap.c" #include "pci.c" #include "pid_namespace.c" #include "platform.c" diff --git a/rust/helpers/kdev.c b/rust/helpers/kdev.c new file mode 100644 index 00000000000000..364fdfe43f5a12 --- /dev/null +++ b/rust/helpers/kdev.c @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +unsigned int rust_helper_MKDEV(unsigned int major, unsigned int minor) +{ + return MKDEV(major, minor); +} diff --git a/rust/helpers/pagemap.c b/rust/helpers/pagemap.c new file mode 100644 index 00000000000000..e940b753879d3c --- /dev/null +++ b/rust/helpers/pagemap.c @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +void rust_helper_mapping_set_large_folios(struct address_space *mapping) +{ + mapping_set_large_folios(mapping); +} diff --git a/rust/kernel/block.rs b/rust/kernel/block.rs index 32c8d865afb629..1aef16bbca393c 100644 --- a/rust/kernel/block.rs +++ b/rust/kernel/block.rs @@ -2,6 +2,11 @@ //! Types for working with the block layer. +use crate::bindings; +use crate::fs::FileSystem; +use crate::inode::INode; +use crate::types::Opaque; + pub mod mq; /// Bit mask for masking out [`SECTOR_SIZE`]. @@ -16,3 +21,44 @@ pub const SECTOR_SIZE: u32 = bindings::SECTOR_SIZE; /// The difference between the size of a page and the size of a sector, /// expressed as a power of two. pub const PAGE_SECTORS_SHIFT: u32 = bindings::PAGE_SECTORS_SHIFT; + +/// The type used for indexing onto a disc or disc partition. +/// +/// This is C's `sector_t`. +pub type Sector = u64; + +/// The type of the inode's block count. +/// +/// This is C's `blkcnt_t`. +pub type Count = u64; + +/// A block device. +/// +/// Wraps the kernel's `struct block_device`. +#[repr(transparent)] +pub struct Device(pub(crate) Opaque); + +impl Device { + /// Creates a new block device reference from the given raw pointer. + /// + /// # Safety + /// + /// Callers must ensure that `ptr` is valid and remains so for the lifetime of the returned + /// object. + pub(crate) unsafe fn from_raw<'a>(ptr: *mut bindings::block_device) -> &'a Self { + // SAFETY: The safety requirements guarantee that the cast below is ok. + unsafe { &*ptr.cast::() } + } + + /// Returns the inode associated with this block device. + // TODO: Maybe this should be dealt with in the Address space struct instead of here + // Also should be default type instead of generic + pub fn inode(&self) -> &INode { + // SAFETY: `bd_inode` is never reassigned. + let mapping = unsafe { (*self.0.get()).bd_mapping }; + // TODO: Why is this safe + let inode_ptr = unsafe { (*mapping).host }; + // SAFET: `ptr` is valid as long as the block device remains valid as well. + unsafe { INode::from_raw(inode_ptr) } + } +} diff --git a/rust/kernel/dentry.rs b/rust/kernel/dentry.rs new file mode 100644 index 00000000000000..14941f56b5e97f --- /dev/null +++ b/rust/kernel/dentry.rs @@ -0,0 +1,72 @@ +use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr}; + +use crate::{ + bindings, + error::Result, + fs::FileSystem, + inode::INode, + prelude::*, + sb::SuperBlock, + types::{ARef, AlwaysRefCounted, Opaque}, +}; + +#[repr(transparent)] +pub struct DEntry(pub(crate) Opaque, PhantomData); + +// SAFETY: The type invariants guarantee that `DEntry` is always ref-counted. +unsafe impl AlwaysRefCounted for DEntry { + fn inc_ref(&self) { + // SAFETY: The existence of a shared reference means that the refcount is nonzero. + unsafe { bindings::dget(self.0.get()) }; + } + + unsafe fn dec_ref(obj: ptr::NonNull) { + // SAFETY: The safety requirements guarantee that the refcount is nonzero. + unsafe { bindings::dput(obj.as_ref().0.get()) } + } +} + +impl DEntry { + /// Creates a new [`DEntry`] from a raw C pointer. + /// + /// # Safety + /// + /// * `ptr` must be valid for at least the lifetime of the returned reference. + /// * `ptr` has the correct file system type, or `T` is [`super::UnspecifiedFS`]. + pub(crate) unsafe fn from_raw<'a>(ptr: *mut bindings::dentry) -> &'a Self { + // SAFETY: The safety requirements guarantee that the reference is and remains valid. + unsafe { &*ptr.cast::() } + } + + /// Returns the superblock of the dentry. + pub fn super_block(&self) -> &SuperBlock { + // `d_sb` is immutable, so it's safe to read it. + unsafe { SuperBlock::from_raw((*self.0.get()).d_sb) } + } +} + +pub struct Root(ARef>); + +impl Root { + /// Creates a root dentry. + pub fn try_new(inode: ARef>) -> Result> { + // SAFETY: `d_make_root` requires that `inode` be valid and referenced, which is the + // case for this call. + // + // It takes over the inode, even on failure, so we don't need to clean it up. + let dentry_ptr = unsafe { bindings::d_make_root(ManuallyDrop::new(inode).0.get()) }; + let dentry = ptr::NonNull::new(dentry_ptr).ok_or(ENOMEM)?; + + // SAFETY: `dentry` is valid and referenced. It reference ownership is transferred to + // `ARef`. + Ok(Root(unsafe { ARef::from_raw(dentry.cast::>()) })) + } +} + +impl Deref for Root { + type Target = DEntry; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs index 15a8139a828a5f..c6540be649867d 100644 --- a/rust/kernel/fs.rs +++ b/rust/kernel/fs.rs @@ -7,16 +7,21 @@ use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop}; use crate::{ - bindings, - error::{to_result, Error}, + bindings, dentry, + error::{from_result, to_result, Error, Result}, + inode, + prelude::*, + sb::{self, SuperBlock}, str::CStr, try_pin_init, - types::Opaque, + types::{ForeignOwnable, Opaque}, ThisModule, }; use core::{ marker::{Send, Sync}, + mem::ManuallyDrop, pin::Pin, + ptr, }; pub mod file; @@ -25,10 +30,40 @@ pub use self::file::{File, LocalFile}; mod kiocb; pub use self::kiocb::Kiocb; +/// The offset of a file in a file system. +/// +/// This is C's `loff_t`. +pub type Offset = i64; + +/// An index into the page cache. +/// +/// This is C's `pgoff_t`. +pub type PageOffset = usize; + /// A file system type. pub trait FileSystem { + /// Data associated with each file system instance (super-block). + type Data: ForeignOwnable + Send + Sync; + + /// Type of data associated with each inode. + type INodeData: Send + Sync; + /// The name of the file system type. const NAME: &'static CStr; + + /// Determines how superblocks for this file system type are keyed. + const SUPER_TYPE: sb::Type = sb::Type::Independent; + + fn fill_super( + sb: &mut SuperBlock, + mapper: Option>, //TODO: Default type parameter should be UnspecifiedFS + ) -> Result; + + /// Initialises and returns the root inode of the given superblock. + /// + /// This is called during initialisation of a superblock after [`FileSystem::fill_super`] has + /// completed successfully. + fn init_root(sb: &SuperBlock) -> Result>; } /// A file system registration. @@ -41,7 +76,7 @@ pub struct Registration { impl Registration { /// Creates a new file system registration. /// - /// It is not visible or accessible yet. A successful call to [`Registration::register`] needs + /// It is not visible or accessible yet. A successful call to [`Registration::new`] needs /// to be made before users can mount it. pub fn new(module: &'static ThisModule) -> impl PinInit { try_pin_init!(Self { @@ -59,6 +94,34 @@ impl Registration { }), }) } + + unsafe extern "C" fn kill_sb_callback( + sb_ptr: *mut bindings::super_block, + ) { + match T::SUPER_TYPE { + // SAFETY: In `get_tree_callback` we always call `get_tree_bdev` for + // `sb::Type::BlockDev`, so `kill_block_super` is the appropriate function to call + // for cleanup. + sb::Type::BlockDev => unsafe { + bindings::kill_block_super(sb_ptr); + }, + // SAFETY: In `get_tree_callback` we always call `get_tree_nodev` for + // `sb::Type::Independent`, so `kill_anon_super` is the appropriate function to call + // for cleanup. + sb::Type::Independent => unsafe { + bindings::kill_anon_super(sb_ptr); + }, + } + + let ptr = unsafe { (*sb_ptr).s_fs_info }; + if !ptr.is_null() { + // SAFETY: The only place where `s_fs_info` is assigned is `NewSuperBlock::init`, where + // it's initialised with the result of an `into_foreign` call. We checked above that + // `ptr` is non-null because it would be null if we never reached the point where we + // init the field. + unsafe { T::Data::from_foreign(ptr) }; + } + } } // SAFETY: `Registration` doesn't really provide any `&self` methods, so it is safe to pass @@ -78,3 +141,112 @@ impl PinnedDrop for Registration { unsafe { bindings::unregister_filesystem(self.fs.get()) }; } } + +struct Tables(T); +impl Tables { + const CONTEXT: bindings::fs_context_operations = bindings::fs_context_operations { + free: None, + parse_param: None, + get_tree: Some(Self::get_tree_callback), + reconfigure: None, + parse_monolithic: None, + dup: None, + }; + + unsafe extern "C" fn get_tree_callback(fc: *mut bindings::fs_context) -> ffi::c_int { + match T::SUPER_TYPE { + sb::Type::BlockDev => unsafe { + bindings::get_tree_bdev(fc, Some(Self::fill_super_callback)) + }, + sb::Type::Independent => unsafe { + bindings::get_tree_nodev(fc, Some(Self::fill_super_callback)) + }, + } + } + + unsafe extern "C" fn fill_super_callback( + sb_ptr: *mut bindings::super_block, + _fc: *mut bindings::fs_context, + ) -> ffi::c_int { + from_result(|| { + // SAFETY: The callback contract guarantees that `sb_ptr` is a unique pointer to a + // newly-created superblock. + let new_sb = unsafe { SuperBlock::from_raw_mut(sb_ptr) }; + + // SAFETY: The callback contract guarantees that `sb_ptr`, from which `new_sb` is + // derived, is valid for write. + let sb = unsafe { &mut *new_sb.0.get() }; + sb.s_op = &Tables::::SUPER_BLOCK; + + let mapper = if matches!(T::SUPER_TYPE, sb::Type::BlockDev) { + // SAFETY: This is the only mapper created for this inode, so it is unique. + Some(unsafe { new_sb.bdev().inode().mapper() }) + } else { + None + }; + + let data = T::fill_super(new_sb, mapper)?; + + // N.B.: Even on failure, `kill_sb` is called and frees the data. + sb.s_fs_info = data.into_foreign(); + + // SAFETY: The callback contract guarantees that `sb_ptr` is a unique pointer to a + // newly-created (and initialised above) superblock. And we have just initialised + // `s_fs_info`. + let sb = unsafe { SuperBlock::from_raw(sb_ptr) }; + let root = T::init_root(sb)?; + + // Reject root inode if it belongs to a different superblock. + if !ptr::eq(root.super_block(), sb) { + return Err(EINVAL); + } + + let dentry = ManuallyDrop::new(root).0.get(); + + // SAFETY: The callback contract guarantees that `sb_ptr` is a unique pointer to a + // newly-created (and initialised above) superblock. + unsafe { (*sb_ptr).s_root = dentry }; + + Ok(0) + }) + } + + const SUPER_BLOCK: bindings::super_operations = bindings::super_operations { + alloc_inode: None, + // alloc_inode: if size_of::() != 0 { + // Some(INode::::alloc_inode_callback) + // } else { + // None + // }, + // destroy_inode: Some(INode::::destroy_inode_callback), + destroy_inode: None, + free_inode: None, + dirty_inode: None, + write_inode: None, + drop_inode: None, + evict_inode: None, + put_super: None, + sync_fs: None, + freeze_super: None, + freeze_fs: None, + thaw_super: None, + unfreeze_fs: None, + statfs: None, + remount_fs: None, + remove_bdev: None, // TODO: New field, research + umount_begin: None, + show_options: None, + show_devname: None, + show_path: None, + show_stats: None, + #[cfg(CONFIG_QUOTA)] + quota_read: None, + #[cfg(CONFIG_QUOTA)] + quota_write: None, + #[cfg(CONFIG_QUOTA)] + get_dquots: None, + nr_cached_objects: None, + free_cached_objects: None, + shutdown: None, + }; +} diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs new file mode 100644 index 00000000000000..c587649dd1b85f --- /dev/null +++ b/rust/kernel/inode.rs @@ -0,0 +1,282 @@ +use core::marker::PhantomData; +use core::mem::{ManuallyDrop, MaybeUninit}; + +use crate::error::Result; +use crate::str::CString; +use crate::time::Timespec; +use crate::types::AlwaysRefCounted; +use crate::{block, container_of}; +use crate::{ + fs::{FileSystem, Offset}, + time, + types::{ARef, Opaque}, +}; +use core::ptr; + +pub type Ino = usize; + +pub enum INodeState { + Existing(ARef>), + Uninitilized(New), +} + +/// A node (inode) in the file index. +/// +/// Wraps the kernel's `struct inode`. +/// +/// # Invariants +/// +/// Instances of this type are always ref-counted, that is, a call to `ihold` ensures that the +/// allocation remains valid at least until the matching call to `iput`. +// TODO: should be default UnspecifiedFS +#[repr(transparent)] +pub struct INode(pub(crate) Opaque, PhantomData); + +impl INode { + /// Creates a new inode reference from the given raw pointer. + /// + /// # Safety + /// + /// Callers must ensure that: + /// + /// * `ptr` is valid and remains so for the lifetime of the returned object. + /// * `ptr` has the correct file system type, or `T` is [`super::UnspecifiedFS`]. + pub(crate) unsafe fn from_raw<'a>(ptr: *mut bindings::inode) -> &'a Self { + // SAFETY: The safety requirements guarantee that the cast below is ok. + unsafe { &*ptr.cast::() } + } + + /// Returns a mapper for this inode. + /// + /// # Safety + /// + /// Callers must ensure that mappers are unique for a given inode and range. For inodes that + /// back a block device, a mapper is always created when the filesystem is mounted; so callers + /// in such situations must ensure that that mapper is never used. + pub unsafe fn mapper(&self) -> Mapper { + Mapper { + inode: self.into(), + begin: 0, + end: Offset::MAX, + } + } +} + +// SAFETY: The type invariants guarantee that `INode` is always ref-counted. +unsafe impl AlwaysRefCounted for INode { + fn inc_ref(&self) { + // SAFETY: The existence of a shared reference means that the refcount is nonzero. + unsafe { bindings::ihold(self.0.get()) }; + } + + unsafe fn dec_ref(obj: ptr::NonNull) { + // SAFETY: The safety requirements guarantee that the refcount is nonzero. + unsafe { bindings::iput(obj.as_ref().0.get()) } + } +} + +/// Allows mapping the contents of the inode. +/// +/// # Invariants +/// +/// Mappers are unique per range per inode. +// TODO: should be default UnspecifiedFS +pub struct Mapper { + inode: ARef>, + begin: Offset, + end: Offset, +} + +// SAFETY: All inode and folio operations are safe from any thread. +unsafe impl Send for Mapper {} + +// SAFETY: All inode and folio operations are safe from any thread. +unsafe impl Sync for Mapper {} + +struct WithData { + data: MaybeUninit, + inode: bindings::inode, +} + +/// An inode that is locked and hasn't been initialised yet. +/// +/// # Invariants +/// +/// The inode is a new one, locked, and valid for write. +pub struct New( + pub(crate) ptr::NonNull, + pub(crate) PhantomData, +); + +impl New { + /// Initialises the new inode with the given parameters. + pub fn init(self, params: Params) -> Result>> { + let outerp = unsafe { container_of!(self.0.as_ptr(), WithData, inode) }; + + // SAFETY: This is a newly-created inode. No other references to it exist, so it is + // safe to mutably dereference it. + let outer = unsafe { &mut *outerp }; + + // N.B. We must always write this to a newly allocated inode because the free callback + // expects the data to be initialised and drops it. + outer.data.write(params.value); + + let inode = &mut outer.inode; + let mode = match params.typ { + Type::Dir => bindings::S_IFDIR, + Type::Reg => { + // SAFETY: The `i_mapping` pointer doesn't change and is valid. + unsafe { bindings::mapping_set_large_folios(inode.i_mapping) }; + bindings::S_IFREG + } + Type::Lnk(str) => { + // If we are using `page_get_link`, we need to prevent the use of high mem. + if !inode.i_op.is_null() { + // SAFETY: We just checked that `i_op` is non-null, and we always just set it + // to valid values. + if unsafe { + (*inode.i_op).get_link == bindings::page_symlink_inode_operations.get_link + } { + // SAFETY: `inode` is valid for write as it's a new inode. + unsafe { bindings::inode_nohighmem(inode) }; + } + } + // if let Some(s) = str { + // inode.__bindgen_anon_5.i_link = s.into_foreign().cast::().cast_mut(); + // } + bindings::S_IFLNK + } + Type::Fifo => { + // SAFETY: `inode` is valid for write as it's a new inode. + unsafe { bindings::init_special_inode(inode, bindings::S_IFIFO as _, 0) }; + bindings::S_IFIFO + } + Type::Sock => { + // SAFETY: `inode` is valid for write as it's a new inode. + unsafe { bindings::init_special_inode(inode, bindings::S_IFSOCK as _, 0) }; + bindings::S_IFSOCK + } + Type::Chr(major, minor) => { + // SAFETY: `inode` is valid for write as it's a new inode. + unsafe { + bindings::init_special_inode( + inode, + bindings::S_IFCHR as _, + bindings::MKDEV(major, minor & bindings::MINORMASK), + ) + }; + bindings::S_IFCHR + } + Type::Blk(major, minor) => { + // SAFETY: `inode` is valid for write as it's a new inode. + unsafe { + bindings::init_special_inode( + inode, + bindings::S_IFBLK as _, + bindings::MKDEV(major, minor & bindings::MINORMASK), + ) + }; + bindings::S_IFBLK + } + }; + + inode.i_mode = (params.mode & 0o777) | u16::try_from(mode)?; + inode.i_size = params.size; + inode.i_blocks = params.blocks; + + inode.i_ctime_sec = params.ctime.tv_sec(); + inode.i_ctime_nsec = params.ctime.tv_nsec()?; + inode.i_mtime_sec = params.mtime.tv_sec(); + inode.i_mtime_nsec = params.mtime.tv_nsec()?; + inode.i_atime_sec = params.atime.tv_sec(); + inode.i_atime_nsec = params.atime.tv_nsec()?; + + // SAFETY: inode is a new inode, so it is valid for write. + unsafe { + bindings::set_nlink(inode, params.nlink); + bindings::i_uid_write(inode, params.uid); + bindings::i_gid_write(inode, params.gid); + bindings::unlock_new_inode(inode); + } + + let manual = ManuallyDrop::new(self); + // SAFETY: We transferred ownership of the refcount to `ARef` by preventing `drop` from + // being called with the `ManuallyDrop` instance created above. + Ok(unsafe { ARef::from_raw(manual.0.cast::>()) }) + } +} + +impl Drop for New { + fn drop(&mut self) { + // SAFETY: The new inode failed to be turned into an initialised inode, so it's safe (and + // in fact required) to call `iget_failed` on it. + unsafe { bindings::iget_failed(self.0.as_ptr()) }; + } +} + +/// The type of an inode. +pub enum Type { + /// Named pipe (first-in, first-out) type. + Fifo, + + /// Character device type. + Chr(u32, u32), + + /// Directory type. + Dir, + + /// Block device type. + Blk(u32, u32), + + /// Regular file type. + Reg, + + /// Symbolic link type. + Lnk(Option), + + /// Named unix-domain socket type. + Sock, +} + +/// Required inode parameters. +/// +/// This is used when creating new inodes. +pub struct Params { + /// The access mode. It's a mask that grants execute (1), write (2) and read (4) access to + /// everyone, the owner group, and the owner. + pub mode: u16, + + /// Type of inode. + /// + /// Also carries additional per-type data. + pub typ: Type, + + /// Size of the contents of the inode. + /// + /// Its maximum value is [`super::MAX_LFS_FILESIZE`]. + pub size: Offset, + + /// Number of blocks. + pub blocks: block::Count, + + /// Number of links to the inode. + pub nlink: u32, + + /// User id. + pub uid: u32, + + /// Group id. + pub gid: u32, + + /// Creation time. + pub ctime: Timespec, + + /// Last modification time. + pub mtime: Timespec, + + /// Last access time. + pub atime: Timespec, + + /// Value to attach to this node. + pub value: T, +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 3dd7bebe78882a..c39163ad5a24c9 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -81,6 +81,7 @@ pub mod cpufreq; pub mod cpumask; pub mod cred; pub mod debugfs; +pub mod dentry; pub mod device; pub mod device_id; pub mod devres; @@ -96,6 +97,7 @@ pub mod fmt; pub mod fs; pub mod id_pool; pub mod init; +pub mod inode; pub mod io; pub mod ioctl; pub mod iov; @@ -124,6 +126,7 @@ pub mod ptr; pub mod rbtree; pub mod regulator; pub mod revocable; +pub mod sb; pub mod scatterlist; pub mod security; pub mod seq_file; diff --git a/rust/kernel/sb.rs b/rust/kernel/sb.rs new file mode 100644 index 00000000000000..cd87f1cb7d96f5 --- /dev/null +++ b/rust/kernel/sb.rs @@ -0,0 +1,126 @@ +use core::{marker::PhantomData, ptr}; + +use crate::error::{code::*, Result}; +use crate::types::ARef; +use crate::{block, inode}; +use crate::{ + build_error, + fs::FileSystem, + inode::{INodeState, Ino}, + types::Opaque, +}; + +pub enum Type { + /// Multiple independent superblocks may exist. + Independent, + /// Uses a block device. + BlockDev, +} + +/// Indicates that a superblock in this typestate has data initialized. +/// +/// # Safety +/// +/// Implementers must ensure that `s_fs_info` is properly initialised in this state. +#[doc(hidden)] +pub unsafe trait DataInited {} + +/// A typestate for [`SuperBlock`] that indicates that it's a new one, so not fully initialized +/// yet. +pub enum New {} + +/// A typestate for [`SuperBlock`] that indicates that it's ready to be used. +pub enum Ready {} + +// SAFETY: Instances of `SuperBlock` are only created after initialising the data. +unsafe impl DataInited for Ready {} + +/// A file system superblock +/// +/// Wraps the kernel's `struct super_block`. +#[repr(transparent)] +pub struct SuperBlock( + pub(crate) Opaque, + PhantomData<(S, T)>, +); + +impl SuperBlock { + /// Creates a new superblock reference from the given raw pointer. + /// + /// # Safety + /// + /// Callers must ensure that: + /// + /// * `ptr` is valid and remains so for the lifetime of the returned object. + /// * `ptr` has the correct file system type, or `T` is [`super::UnspecifiedFS`]. + /// * `ptr` in the right typestate. + pub(crate) unsafe fn from_raw<'a>(ptr: *mut bindings::super_block) -> &'a Self { + // SAFETY: The safety requirements guarantee that the cast below is ok. + unsafe { &*ptr.cast::() } + } + + /// Creates a new superblock mutable reference from the given raw pointer. + /// + /// # Safety + /// + /// Callers must ensure that: + /// + /// * `ptr` is valid and remains so for the lifetime of the returned object. + /// * `ptr` has the correct file system type, or `T` is [`super::UnspecifiedFS`]. + /// * `ptr` in the right typestate. + /// * `ptr` is the only active pointer to the superblock. + pub(crate) unsafe fn from_raw_mut<'a>(ptr: *mut bindings::super_block) -> &'a mut Self { + // SAFETY: The safety requirements guarantee that the cast below is ok. + unsafe { &mut *ptr.cast::() } + } + + pub fn bdev(&self) -> &block::Device { + if !matches!(T::SUPER_TYPE, Type::BlockDev) { + build_error!("bdev is only available in blockdev superblocks"); + } + + // SAFETY: The superblock is valid and given that it's a blockdev superblock it must have a + // valid `s_bdev` that remains valid while the superblock (`self`) is valid. + unsafe { block::Device::from_raw((*self.0.get()).s_bdev) } + } +} + +impl SuperBlock { + /// Tries to get an existing inode or create a new one if it doesn't exist yet. + /// + /// This method is not callable from a superblock where data isn't inited yet because it would + /// allow one to get access to the uninited data via `inode::New::init()` -> + /// `INode::super_block()` -> `SuperBlock::data()`. + pub fn get_or_create_inode(&self, ino: Ino) -> Result> { + // SAFETY: All superblock-related state needed by `iget_locked` is initialised by C code + // before calling `fill_super_callback`, or by `fill_super_callback` itself before calling + // `super_params`, which is the first function to see a new superblock. + let inode = + ptr::NonNull::new(unsafe { bindings::iget_locked(self.0.get(), ino) }).ok_or(ENOMEM)?; + + // SAFETY: `inode` is a valid pointer returned by `iget_locked`. + unsafe { bindings::spin_lock(ptr::addr_of_mut!((*inode.as_ptr()).i_lock)) }; + + // SAFETY: `inode` is valid and was locked by the previous lock. + let state = unsafe { *ptr::addr_of!((*inode.as_ptr()).i_state) }; + + // SAFETY: `inode` is a valid pointer returned by `iget_locked`. + unsafe { bindings::spin_unlock(ptr::addr_of_mut!((*inode.as_ptr()).i_lock)) }; + + // TODO: investigate if size of state is variable + // if state & u64::from(bindings::I_NEW) == 0 was old code + if state & bindings::inode_state_flags_t_I_NEW == 0 { + // The inode is cached. Just return it. + // + // SAFETY: `inode` had its refcount incremented by `iget_locked`; this increment is now + // owned by `ARef`. + Ok(INodeState::Existing(unsafe { + ARef::from_raw(inode.cast()) + })) + } else { + // SAFETY: The new inode is valid but not fully initialised yet, so it's ok to create a + // `inode::New`. + Ok(INodeState::Uninitilized(inode::New(inode, PhantomData))) + } + } +} diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs index 6ea98dfcd02787..011551e9c81ab5 100644 --- a/rust/kernel/time.rs +++ b/rust/kernel/time.rs @@ -24,6 +24,9 @@ //! C header: [`include/linux/jiffies.h`](srctree/include/linux/jiffies.h). //! C header: [`include/linux/ktime.h`](srctree/include/linux/ktime.h). +use crate::{bindings, error::code::*, error::Result}; + +/// TODO: Add docs about Timespec use core::marker::PhantomData; use core::ops; @@ -53,6 +56,54 @@ pub fn msecs_to_jiffies(msecs: Msecs) -> Jiffies { unsafe { bindings::__msecs_to_jiffies(msecs) } } +/// A [`Timespec`] instance at the Unix epoch. +pub const UNIX_EPOCH: Timespec = Timespec { + t: bindings::timespec64 { + tv_sec: 0, + tv_nsec: 0, + }, +}; + +/// A timestamp. +#[derive(Copy, Clone)] +#[repr(transparent)] +pub struct Timespec { + t: bindings::timespec64, +} + +impl Timespec { + /// Creates a new timestamp. + /// + /// `sec` is the number of seconds since the Unix epoch. `nsec` is the number of nanoseconds + /// within that second. + pub fn new(sec: u64, nsec: u32) -> Result { + if nsec >= 1000000000 { + return Err(EDOM); + } + + Ok(Self { + t: bindings::timespec64 { + tv_sec: sec.try_into()?, + tv_nsec: nsec.try_into()?, + }, + }) + } + + pub fn tv_sec(self) -> i64 { + self.t.tv_sec + } + + pub fn tv_nsec(self) -> Result { + self.t.tv_nsec.try_into().map_err(|_| EINVAL) + } +} + +impl From for bindings::timespec64 { + fn from(v: Timespec) -> Self { + v.t + } +} + /// Trait for clock sources. /// /// Selection of the clock source depends on the use case. In some cases the usage of a From e9460cc00eee9c200edf7d404fbd36706bb06618 Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 19 Nov 2025 22:10:31 -0500 Subject: [PATCH 012/131] [VFS] sb set magic number --- rust/kernel/sb.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/rust/kernel/sb.rs b/rust/kernel/sb.rs index cd87f1cb7d96f5..764acd66acfbfa 100644 --- a/rust/kernel/sb.rs +++ b/rust/kernel/sb.rs @@ -85,6 +85,16 @@ impl SuperBlock { } } +impl SuperBlock { + /// Sets the magic number of the superblock. + pub fn set_magic(&mut self, magic: usize) -> &mut Self { + // SAFETY: This is a new superblock that is being initialised, so it's ok to write to its + // fields. + unsafe { (*self.0.get()).s_magic = magic }; + self + } +} + impl SuperBlock { /// Tries to get an existing inode or create a new one if it doesn't exist yet. /// From 4e8057f5f535ee7b83c3d7ce836a878f5dd8b5a4 Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 19 Nov 2025 22:10:41 -0500 Subject: [PATCH 013/131] [ezFS] minimal for mount?? --- fs/rustezfs/ezfs.rs | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 9bc44f0707163f..fc77cac0f8b555 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -6,11 +6,13 @@ mod defs; mod dir; mod inode; mod sb; -use kernel::dentry::Root; +use defs::*; +use kernel::dentry; use kernel::fs::{FileSystem, Registration}; -use kernel::inode::{INode, INodeState, Mapper}; +use kernel::inode::{INode, INodeState, Mapper, Params, Type}; use kernel::prelude::*; use kernel::sb::{New, SuperBlock}; +use kernel::time::UNIX_EPOCH; use kernel::types::ARef; use kernel::{c_str, fs, str::CStr}; @@ -37,25 +39,41 @@ impl kernel::InPlaceModule for RustEzFsModule { impl RustEzFs { fn iget(sb: &SuperBlock, ino: usize) -> Result>> { - let mut new = match sb.get_or_create_inode(ino)? { + let mut inode = match sb.get_or_create_inode(ino)? { INodeState::Existing(inode) => return Ok(inode), INodeState::Uninitilized(new_inode) => new_inode, }; - todo!() + + inode.init(Params { + typ: Type::Dir, + mode: 0o755, + size: 0, + blocks: 0, + nlink: 2, + uid: 0, + gid: 0, + ctime: UNIX_EPOCH, + mtime: UNIX_EPOCH, + atime: UNIX_EPOCH, + value: (), + }) } } impl FileSystem for RustEzFs { - type Data = KBox; + // type Data = KBox; + type Data = (); type INodeData = (); const NAME: &'static CStr = c_str!("rustezfs"); fn fill_super(sb: &mut SuperBlock, _: Option>) -> Result { - todo!() + sb.set_magic(EZFS_MAGIC_NUMBER); + Ok(()) } - fn init_root(_: &SuperBlock) -> Result> { - todo!() + fn init_root(sb: &SuperBlock) -> Result> { + let inode = Self::iget(sb, EZFS_ROOT_INODE_NUMBER)?; + dentry::Root::try_new(inode) } } From 6691b2b0d435f5e5aad3ba2f347d0355735c1143 Mon Sep 17 00:00:00 2001 From: lsig Date: Fri, 21 Nov 2025 14:02:05 -0500 Subject: [PATCH 014/131] [ezFS] mountttt --- rust/kernel/fs.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs index c6540be649867d..cbe892708e9ff5 100644 --- a/rust/kernel/fs.rs +++ b/rust/kernel/fs.rs @@ -87,6 +87,11 @@ impl Registration { let fs = unsafe { &mut *fs_ptr }; fs.owner = module.0; fs.name = T::NAME.as_char_ptr(); + fs.init_fs_context = Some(Self::init_fs_context_callback::); + fs.kill_sb = Some(Self::kill_sb_callback::); + fs.fs_flags = if let sb::Type::BlockDev = T::SUPER_TYPE { + bindings::FS_REQUIRES_DEV as i32 + } else { 0 }; // SAFETY: Pointers stored in `fs` are static so will live for as long as the // registration is active (it is undone in `drop`). @@ -95,6 +100,17 @@ impl Registration { }) } + unsafe extern "C" fn init_fs_context_callback( + fc_ptr: *mut bindings::fs_context, + ) -> ffi::c_int { + from_result(|| { + // SAFETY: The C callback API guarantees that `fc_ptr` is valid. + let fc = unsafe { &mut *fc_ptr }; + fc.ops = &Tables::::CONTEXT; + Ok(0) + }) + } + unsafe extern "C" fn kill_sb_callback( sb_ptr: *mut bindings::super_block, ) { From 164b9197c1a207e977fee62d940a1bd07f748377 Mon Sep 17 00:00:00 2001 From: lsig Date: Mon, 24 Nov 2025 14:08:42 -0500 Subject: [PATCH 015/131] [Read Sb] checkpoint --- fs/rustezfs/ezfs.rs | 23 ++++- fs/rustezfs/sb.rs | 17 ++-- rust/helpers/mm.c | 15 ++++ rust/helpers/page.c | 21 +++++ rust/helpers/pagemap.c | 5 ++ rust/kernel/folio.rs | 187 +++++++++++++++++++++++++++++++++++++++++ rust/kernel/inode.rs | 57 ++++++++++++- rust/kernel/lib.rs | 1 + 8 files changed, 316 insertions(+), 10 deletions(-) create mode 100644 rust/kernel/folio.rs diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index fc77cac0f8b555..2726319ac48a1a 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -6,13 +6,15 @@ mod defs; mod dir; mod inode; mod sb; +use crate::sb::EzfsSuperblockDisk; use defs::*; use kernel::dentry; use kernel::fs::{FileSystem, Registration}; use kernel::inode::{INode, INodeState, Mapper, Params, Type}; use kernel::prelude::*; -use kernel::sb::{New, SuperBlock}; +use kernel::sb::{New, SuperBlock, Type as SuperType}; use kernel::time::UNIX_EPOCH; +use kernel::transmute::FromBytes; use kernel::types::ARef; use kernel::{c_str, fs, str::CStr}; @@ -65,9 +67,24 @@ impl FileSystem for RustEzFs { type Data = (); type INodeData = (); const NAME: &'static CStr = c_str!("rustezfs"); + const SUPER_TYPE: SuperType = SuperType::BlockDev; - fn fill_super(sb: &mut SuperBlock, _: Option>) -> Result { - sb.set_magic(EZFS_MAGIC_NUMBER); + fn fill_super( + sb: &mut SuperBlock, + mapper: Option>, + ) -> Result { + let Some(mapper) = mapper else { + return Err(EINVAL); + }; + + let offset = 0; + let mapped_sb = mapper.mapped_folio(offset.try_into()?)?; + + let sb_disk = EzfsSuperblockDisk::from_bytes(&mapped_sb).ok_or(EIO)?; + + pr_info!("sb disk magic: {:?}", sb_disk.magic()); + + // sb.set_magic(EZFS_MAGIC_NUMBER); Ok(()) } diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index 3292fd970457e5..1b5a28d91e4b01 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -1,6 +1,7 @@ use crate::defs::{EZFS_BLOCK_SIZE, EZFS_MAX_DATA_BLKS, EZFS_MAX_INODES}; use core::mem::size_of; use kernel::sync::Mutex; +use kernel::transmute::FromBytes; pub(crate) struct EzfsSuperblockDiskRaw { magic: u64, @@ -17,6 +18,16 @@ pub(crate) struct EzfsSuperblockDisk { _padding: [u8; EZFS_BLOCK_SIZE - size_of::()], } +impl EzfsSuperblockDisk { + pub fn magic(&self) -> u64 { + self.data.magic + } +} + +// SAFETY: EzfsSuperblockDisk contains only primitive integer types (u32, u64, u8) +// which accept any bit pattern. The struct is #[repr(C)] for consistent layout. +unsafe impl FromBytes for EzfsSuperblockDisk {} + // TODO: pin data because of mutexes // in-memory representation of sb pub(crate) struct EzfsSuperblock { @@ -26,9 +37,3 @@ pub(crate) struct EzfsSuperblock { free_data_blocks: Mutex<[u32; (EZFS_MAX_DATA_BLKS / 32) + 1]>, zero_data_blocks: Mutex<[u8; (EZFS_MAX_DATA_BLKS / 32) + 1]>, } - -impl EzfsSuperblock { - // fn fill_super() {} - - // fn init_root() {} -} diff --git a/rust/helpers/mm.c b/rust/helpers/mm.c index 81b510c96fd269..8dec8e6d1c3212 100644 --- a/rust/helpers/mm.c +++ b/rust/helpers/mm.c @@ -48,3 +48,18 @@ void rust_helper_vma_end_read(struct vm_area_struct *vma) { vma_end_read(vma); } + +void rust_helper_folio_get(struct folio *folio) +{ + folio_get(folio); +} + +void rust_helper_folio_put(struct folio *folio) +{ + folio_put(folio); +} + +size_t rust_helper_folio_size(struct folio *folio) +{ + return folio_size(folio); +} diff --git a/rust/helpers/page.c b/rust/helpers/page.c index 7144de5a61dbdb..132f060e70cd3a 100644 --- a/rust/helpers/page.c +++ b/rust/helpers/page.c @@ -3,6 +3,7 @@ #include #include #include +#include struct page *rust_helper_alloc_pages(gfp_t gfp_mask, unsigned int order) { @@ -19,6 +20,26 @@ void rust_helper_kunmap_local(const void *addr) kunmap_local(addr); } +void *rust_helper_kmap(struct page *page) +{ + return kmap(page); +} + +void rust_helper_kunmap(struct page *page) +{ + kunmap(page); +} + +struct page *rust_helper_folio_page(struct folio *folio, size_t n) +{ + return folio_page(folio, n); +} + +bool rust_helper_folio_test_highmem(struct folio *folio) +{ + return folio_test_highmem(folio); +} + #ifndef NODE_NOT_IN_PAGE_FLAGS int rust_helper_page_to_nid(const struct page *page) { diff --git a/rust/helpers/pagemap.c b/rust/helpers/pagemap.c index e940b753879d3c..f0a017fc950714 100644 --- a/rust/helpers/pagemap.c +++ b/rust/helpers/pagemap.c @@ -6,3 +6,8 @@ void rust_helper_mapping_set_large_folios(struct address_space *mapping) { mapping_set_large_folios(mapping); } + +struct folio *rust_helper_read_mapping_folio(struct address_space *mapping, pgoff_t index, struct file *file) +{ + return read_mapping_folio(mapping, index, file); +} diff --git a/rust/kernel/folio.rs b/rust/kernel/folio.rs new file mode 100644 index 00000000000000..c67c0cde02c430 --- /dev/null +++ b/rust/kernel/folio.rs @@ -0,0 +1,187 @@ +use core::{marker::PhantomData, ops::Deref, ptr}; + +use crate::{ + error::Result, + fs::FileSystem, + prelude::EDOM, + types::{ARef, AlwaysRefCounted, Opaque}, +}; + +/// The type of a [`Folio`] is unspecified. +pub struct Unspecified; + +/// The [`Folio`] instance is a page-cache one. +pub struct PageCache(PhantomData); + +/// A folio. +/// +/// The `S` type parameter specifies the type of folio. +/// +/// Wraps the kernel's `struct folio`. +/// +/// # Invariants +/// +/// Instances of this type are always ref-counted, that is, a call to `folio_get` ensures that the +/// allocation remains valid at least until the matching call to `folio_put`. +#[repr(transparent)] +pub struct Folio(pub(crate) Opaque, PhantomData); + +// SAFETY: The type invariants guarantee that `Folio` is always ref-counted. +unsafe impl AlwaysRefCounted for Folio { + fn inc_ref(&self) { + // SAFETY: The existence of a shared reference means that the refcount is nonzero. + unsafe { + bindings::folio_get(self.0.get()); + } + } + + unsafe fn dec_ref(obj: ptr::NonNull) { + // SAFETY: The safety requirements guarantee that the refcount is nonzero. + unsafe { + bindings::folio_put(obj.as_ref().0.get()); + } + } +} + +impl Folio { + /// Creates a new folio reference from the given raw pointer. + /// + /// # Safety + /// + /// Callers must ensure that: + /// * `ptr` is valid and remains so for the lifetime of the returned reference. + /// * The folio has the right state. + pub(crate) unsafe fn from_raw<'a>(ptr: *mut bindings::folio) -> &'a Self { + // SAFETY: The safety requirements guarantee that the cast below is ok. + unsafe { &*ptr.cast() } + } + + /// Returns the byte size of this folio. + pub fn size(&self) -> usize { + // SAFETY: The folio is valid because the shared reference implies a non-zero refcount. + unsafe { bindings::folio_size(self.0.get()) } + } + + /// Returns true if the folio is in highmem. + pub fn test_highmem(&self) -> bool { + // SAFETY: The folio is valid because the shared reference implies a non-zero refcount. + unsafe { bindings::folio_test_highmem(self.0.get()) } + } + + /// Consumes the folio and returns an owned mapped reference. + /// + /// # Safety + /// + /// Callers must ensure that the folio is not concurrently mapped for write. + pub unsafe fn map_owned(folio: ARef, offset: usize) -> Result> { + // SAFETY: The safety requirements of this function satisfy those of `map`. + let guard = unsafe { folio.map(offset)? }; + let to_unmap = guard.page; + let data = &guard[0] as *const u8; + let data_len = guard.len(); + core::mem::forget(guard); + Ok(Mapped { + _folio: folio, + to_unmap, + data, + data_len, + _p: PhantomData, + }) + } + + /// Maps the contents of a folio page into a slice. + /// + /// # Safety + /// + /// Callers must ensure that the folio is not concurrently mapped for write. + pub unsafe fn map(&self, offset: usize) -> Result> { + if offset > self.size() { + return Err(EDOM); + } + + let page_index = offset / bindings::PAGE_SIZE; + let page_offset = offset % bindings::PAGE_SIZE; + + // SAFETY: We just checked that the index is within bounds of the folio. + let page = unsafe { bindings::folio_page(self.0.get(), page_index) }; + + // SAFETY: `page` is valid because it was returned by `folio_page` above. + let ptr = unsafe { bindings::kmap(page) }; + + let size = if self.test_highmem() { + bindings::PAGE_SIZE + } else { + self.size() + }; + + // SAFETY: We just mapped `ptr`, so it's valid for read. + let data = unsafe { + core::slice::from_raw_parts(ptr.cast::().add(page_offset), size - page_offset) + }; + Ok(MapGuard { data, page }) + } +} + +/// An owned mapped folio. +/// +/// That is, a mapped version of a folio that holds a reference to it. +/// +/// The lifetime is used to tie the mapping to other lifetime, for example, the lifetime of a lock +/// guard. This allows the mapping to exist only while a lock is held. +/// +/// # Invariants +/// +/// `to_unmap` is a mapped page of the folio. The byte range starting at `data` and extending for +/// `data_len` bytes is within the mapped page. +pub struct Mapped<'a, S = Unspecified> { + _folio: ARef>, + to_unmap: *mut bindings::page, + data: *const u8, + data_len: usize, + _p: PhantomData<&'a ()>, +} + +impl Mapped<'_, S> { + pub fn cap_len(&mut self, new_len: usize) { + if new_len < self.data_len { + self.data_len = new_len; + } + } +} + +impl Deref for Mapped<'_, S> { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + unsafe { core::slice::from_raw_parts(self.data, self.data_len) } + } +} + +impl Drop for Mapped<'_, S> { + fn drop(&mut self) { + // SAFETY: By the type invariant, we know that `to_unmap` is mapped. + unsafe { bindings::kunmap(self.to_unmap) }; + } +} + +/// A mapped [`Folio`]. +pub struct MapGuard<'a> { + data: &'a [u8], + page: *mut bindings::page, +} + +impl Deref for MapGuard<'_> { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + self.data + } +} + +impl Drop for MapGuard<'_> { + fn drop(&mut self) { + // SAFETY: A `MapGuard` instance is only created when `kmap` succeeds, so it's ok to unmap + // it when the guard is dropped. + unsafe { bindings::kunmap(self.page) }; + } +} diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index c587649dd1b85f..c5317483143728 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -1,7 +1,10 @@ use core::marker::PhantomData; use core::mem::{ManuallyDrop, MaybeUninit}; -use crate::error::Result; +use crate::error::{from_err_ptr, Result}; +use crate::folio::{self, Folio}; +use crate::fs::PageOffset; +use crate::prelude::{EIO, ERANGE}; use crate::str::CString; use crate::time::Timespec; use crate::types::AlwaysRefCounted; @@ -60,6 +63,44 @@ impl INode { end: Offset::MAX, } } + + /// Returns a mapped folio at the given offset. + /// + /// # Safety + /// + /// Callers must ensure that there are no concurrent mutable mappings of the folio. + pub unsafe fn mapped_folio( + &self, + offset: Offset, + ) -> Result>> { + let page_index = offset >> bindings::PAGE_SHIFT; + let page_offset = offset & ((bindings::PAGE_SIZE - 1) as Offset); + let folio = self.read_mapping_folio(page_index.try_into()?)?; + + // SAFETY: The safety requirements guarantee that there are no concurrent mutable mappings + // of the folio. + unsafe { Folio::map_owned(folio, page_offset.try_into()?) } + } + + /// Returns the folio at the given page index + pub fn read_mapping_folio( + &self, + index: PageOffset, + ) -> Result>>> { + let folio = from_err_ptr(unsafe { + bindings::read_mapping_folio( + (*self.0.get()).i_mapping, + index.try_into()?, + ptr::null_mut(), + ) + })?; + let ptr = ptr::NonNull::new(folio) + .ok_or(EIO)? + .cast::>>(); + + // SAFETY: The folio returned by read_mapping_folio has had its refcount incremented. + Ok(unsafe { ARef::from_raw(ptr) }) + } } // SAFETY: The type invariants guarantee that `INode` is always ref-counted. @@ -93,6 +134,20 @@ unsafe impl Send for Mapper {} // SAFETY: All inode and folio operations are safe from any thread. unsafe impl Sync for Mapper {} +impl Mapper { + /// Returns a mapped folio at the given offset. + pub fn mapped_folio(&self, offset: Offset) -> Result>> { + if offset < self.begin || offset >= self.end { + return Err(ERANGE); + } + + // SAFETY: By the type invariant, there are no other mutable mappings of the folio. + let mut map = unsafe { self.inode.mapped_folio(offset) }?; + map.cap_len((self.end - offset).try_into()?); + Ok(map) + } +} + struct WithData { data: MaybeUninit, inode: bindings::inode, diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index c39163ad5a24c9..cb49fe45e4d66b 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -94,6 +94,7 @@ pub mod faux; #[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)] pub mod firmware; pub mod fmt; +pub mod folio; pub mod fs; pub mod id_pool; pub mod init; From 9bba107357a10d7bc2b6d669bfecb41e498bbb5d Mon Sep 17 00:00:00 2001 From: lsig Date: Mon, 24 Nov 2025 14:15:52 -0500 Subject: [PATCH 016/131] [Read sb] fix super block struct --- fs/rustezfs/sb.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index 1b5a28d91e4b01..645750a51be1a5 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -4,6 +4,7 @@ use kernel::sync::Mutex; use kernel::transmute::FromBytes; pub(crate) struct EzfsSuperblockDiskRaw { + version: u64, magic: u64, disk_blocks: u64, free_inodes: [u32; (EZFS_MAX_INODES / 32) + 1], @@ -31,6 +32,7 @@ unsafe impl FromBytes for EzfsSuperblockDisk {} // TODO: pin data because of mutexes // in-memory representation of sb pub(crate) struct EzfsSuperblock { + version: u64, magic: u64, disk_blocks: u64, free_inodes: Mutex<[u32; (EZFS_MAX_INODES / 32) + 1]>, From 192df58a69c651eb899b593f06c6b31232ee76f9 Mon Sep 17 00:00:00 2001 From: lsig Date: Mon, 24 Nov 2025 16:45:46 -0500 Subject: [PATCH 017/131] [Read SB] add mutex init --- fs/rustezfs/ezfs.rs | 25 +++++++++++++++++-------- fs/rustezfs/sb.rs | 30 ++++++++++++++++++++++++++++-- rust/kernel/sb.rs | 15 ++++++++++++++- 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 2726319ac48a1a..ee7fda28fafeb0 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -6,7 +6,7 @@ mod defs; mod dir; mod inode; mod sb; -use crate::sb::EzfsSuperblockDisk; +use crate::sb::{EzfsSuperblock, EzfsSuperblockDisk}; use defs::*; use kernel::dentry; use kernel::fs::{FileSystem, Registration}; @@ -63,8 +63,7 @@ impl RustEzFs { } impl FileSystem for RustEzFs { - // type Data = KBox; - type Data = (); + type Data = Pin>; type INodeData = (); const NAME: &'static CStr = c_str!("rustezfs"); const SUPER_TYPE: SuperType = SuperType::BlockDev; @@ -78,14 +77,24 @@ impl FileSystem for RustEzFs { }; let offset = 0; - let mapped_sb = mapper.mapped_folio(offset.try_into()?)?; + let disk_sb = { + let mapped_sb = mapper.mapped_folio(offset.try_into()?)?; + EzfsSuperblockDisk::from_bytes_copy(&mapped_sb).ok_or(EIO)? + }; + + if disk_sb.magic() != EZFS_MAGIC_NUMBER.try_into()? { + return Err(EINVAL); + } + + pr_info!("sb disk magic: {:?}", disk_sb.magic()); + + let ezfs_sb = KBox::pin_init(EzfsSuperblock::new(disk_sb, mapper), GFP_KERNEL)?; - let sb_disk = EzfsSuperblockDisk::from_bytes(&mapped_sb).ok_or(EIO)?; + pr_info!("sb in-memory magic: {:?}", ezfs_sb.magic()); - pr_info!("sb disk magic: {:?}", sb_disk.magic()); + sb.set_magic(EZFS_MAGIC_NUMBER); - // sb.set_magic(EZFS_MAGIC_NUMBER); - Ok(()) + Ok(ezfs_sb) } fn init_root(sb: &SuperBlock) -> Result> { diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index 645750a51be1a5..58f749e25a0c50 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -1,5 +1,10 @@ use crate::defs::{EZFS_BLOCK_SIZE, EZFS_MAX_DATA_BLKS, EZFS_MAX_INODES}; +use crate::RustEzFs; use core::mem::size_of; +use kernel::fs::FileSystem; +use kernel::inode; +use kernel::new_mutex; +use kernel::prelude::*; use kernel::sync::Mutex; use kernel::transmute::FromBytes; @@ -29,13 +34,34 @@ impl EzfsSuperblockDisk { // which accept any bit pattern. The struct is #[repr(C)] for consistent layout. unsafe impl FromBytes for EzfsSuperblockDisk {} -// TODO: pin data because of mutexes -// in-memory representation of sb +#[pin_data] pub(crate) struct EzfsSuperblock { version: u64, magic: u64, disk_blocks: u64, + #[pin] free_inodes: Mutex<[u32; (EZFS_MAX_INODES / 32) + 1]>, + #[pin] free_data_blocks: Mutex<[u32; (EZFS_MAX_DATA_BLKS / 32) + 1]>, + #[pin] zero_data_blocks: Mutex<[u8; (EZFS_MAX_DATA_BLKS / 32) + 1]>, + mapper: inode::Mapper, +} + +impl EzfsSuperblock { + pub fn new(disk_sb: EzfsSuperblockDisk, mapper: inode::Mapper) -> impl PinInit { + pin_init!(Self { + version: disk_sb.data.version, + magic: disk_sb.data.magic, + disk_blocks: disk_sb.data.disk_blocks, + free_inodes <- new_mutex!(disk_sb.data.free_inodes), + free_data_blocks <- new_mutex!(disk_sb.data.free_data_blocks), + zero_data_blocks <- new_mutex!(disk_sb.data.zero_data_blocks), + mapper, + }) + } + + pub fn magic(&self) -> u64 { + self.magic + } } diff --git a/rust/kernel/sb.rs b/rust/kernel/sb.rs index 764acd66acfbfa..4594e134b15572 100644 --- a/rust/kernel/sb.rs +++ b/rust/kernel/sb.rs @@ -1,7 +1,7 @@ use core::{marker::PhantomData, ptr}; use crate::error::{code::*, Result}; -use crate::types::ARef; +use crate::types::{ARef, ForeignOwnable}; use crate::{block, inode}; use crate::{ build_error, @@ -96,6 +96,19 @@ impl SuperBlock { } impl SuperBlock { + /// Returns the data associated with the superblock. + pub fn data(&self) -> ::Borrowed<'_> { + // TODO: Add UnspecifiedFS + // if T::IS_UNSPECIFIED { + // crate::build_error!("super block data type is unspecified"); + // } + + // SAFETY: This method is only available if the typestate implements `DataInited`, whose + // safety requirements include `s_fs_info` being properly initialised. + let ptr = unsafe { (*self.0.get()).s_fs_info }; + unsafe { T::Data::borrow(ptr) } + } + /// Tries to get an existing inode or create a new one if it doesn't exist yet. /// /// This method is not callable from a superblock where data isn't inited yet because it would From 1328f6e5351290143b0e85df0906be5b83b48b23 Mon Sep 17 00:00:00 2001 From: lsig Date: Mon, 24 Nov 2025 17:23:33 -0500 Subject: [PATCH 018/131] [Read Inode store] checkpoint --- fs/rustezfs/ezfs.rs | 17 +++++++++++------ fs/rustezfs/inode.rs | 19 +++++++++++++++++++ fs/rustezfs/sb.rs | 10 +++++++++- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index ee7fda28fafeb0..52b58c0ed52eaa 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -6,6 +6,7 @@ mod defs; mod dir; mod inode; mod sb; +use crate::inode::InodeStore; use crate::sb::{EzfsSuperblock, EzfsSuperblockDisk}; use defs::*; use kernel::dentry; @@ -76,8 +77,8 @@ impl FileSystem for RustEzFs { return Err(EINVAL); }; - let offset = 0; let disk_sb = { + let offset = EZFS_SUPERBLOCK_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE; let mapped_sb = mapper.mapped_folio(offset.try_into()?)?; EzfsSuperblockDisk::from_bytes_copy(&mapped_sb).ok_or(EIO)? }; @@ -86,12 +87,16 @@ impl FileSystem for RustEzFs { return Err(EINVAL); } - pr_info!("sb disk magic: {:?}", disk_sb.magic()); - - let ezfs_sb = KBox::pin_init(EzfsSuperblock::new(disk_sb, mapper), GFP_KERNEL)?; - - pr_info!("sb in-memory magic: {:?}", ezfs_sb.magic()); + let inode_store = { + let offset = EZFS_INODE_STORE_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE; + let mapped_inode_store = mapper.mapped_folio(offset.try_into()?)?; + InodeStore::from_bytes_copy(&mapped_inode_store).ok_or(EIO)? + }; + let ezfs_sb = KBox::pin_init( + EzfsSuperblock::new(disk_sb, inode_store, mapper), + GFP_KERNEL, + )?; sb.set_magic(EZFS_MAGIC_NUMBER); Ok(ezfs_sb) diff --git a/fs/rustezfs/inode.rs b/fs/rustezfs/inode.rs index 855533d6b55573..598a161f1978d3 100644 --- a/fs/rustezfs/inode.rs +++ b/fs/rustezfs/inode.rs @@ -1,3 +1,6 @@ +use crate::defs::*; +use core::ops::Deref; +use kernel::transmute::FromBytes; use kernel::uapi::{gid_t, mode_t, uid_t}; #[repr(C)] @@ -13,3 +16,19 @@ pub(crate) struct EzfsInode { file_size: u64, nblocks: u64, } + +#[repr(C)] +pub(crate) struct InodeStore { + inodes: [EzfsInode; EZFS_MAX_INODES], +} + +impl Deref for InodeStore { + type Target = [EzfsInode]; + + fn deref(&self) -> &Self::Target { + &self.inodes + } +} + +// SAFETY: EzfsInode is FromBytes, so array of them is too +unsafe impl FromBytes for InodeStore {} diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index 58f749e25a0c50..b52702d9a72d42 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -1,4 +1,5 @@ use crate::defs::{EZFS_BLOCK_SIZE, EZFS_MAX_DATA_BLKS, EZFS_MAX_INODES}; +use crate::inode::InodeStore; use crate::RustEzFs; use core::mem::size_of; use kernel::fs::FileSystem; @@ -8,6 +9,7 @@ use kernel::prelude::*; use kernel::sync::Mutex; use kernel::transmute::FromBytes; +#[repr(C)] pub(crate) struct EzfsSuperblockDiskRaw { version: u64, magic: u64, @@ -46,10 +48,15 @@ pub(crate) struct EzfsSuperblock { #[pin] zero_data_blocks: Mutex<[u8; (EZFS_MAX_DATA_BLKS / 32) + 1]>, mapper: inode::Mapper, + inode_store: InodeStore, } impl EzfsSuperblock { - pub fn new(disk_sb: EzfsSuperblockDisk, mapper: inode::Mapper) -> impl PinInit { + pub fn new( + disk_sb: EzfsSuperblockDisk, + inode_store: InodeStore, + mapper: inode::Mapper, + ) -> impl PinInit { pin_init!(Self { version: disk_sb.data.version, magic: disk_sb.data.magic, @@ -58,6 +65,7 @@ impl EzfsSuperblock { free_data_blocks <- new_mutex!(disk_sb.data.free_data_blocks), zero_data_blocks <- new_mutex!(disk_sb.data.zero_data_blocks), mapper, + inode_store, }) } From fc2579fb074a514a8ec803f39691e07298b4444f Mon Sep 17 00:00:00 2001 From: lsig Date: Mon, 24 Nov 2025 17:36:20 -0500 Subject: [PATCH 019/131] [Read Inode store] lets go --- fs/rustezfs/ezfs.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 52b58c0ed52eaa..bafa1d21ccd925 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -20,6 +20,7 @@ use kernel::types::ARef; use kernel::{c_str, fs, str::CStr}; use core::marker::{PhantomData, Send, Sync}; +use core::mem::size_of; use pin_init::{pin_data, PinInit, PinnedDrop}; struct RustEzFs; @@ -90,13 +91,15 @@ impl FileSystem for RustEzFs { let inode_store = { let offset = EZFS_INODE_STORE_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE; let mapped_inode_store = mapper.mapped_folio(offset.try_into()?)?; - InodeStore::from_bytes_copy(&mapped_inode_store).ok_or(EIO)? + InodeStore::from_bytes_copy(&mapped_inode_store[..size_of::()]) + .ok_or(EIO)? }; let ezfs_sb = KBox::pin_init( EzfsSuperblock::new(disk_sb, inode_store, mapper), GFP_KERNEL, )?; + sb.set_magic(EZFS_MAGIC_NUMBER); Ok(ezfs_sb) From b1bfee08e6e45ee55fdf3747d187a066ce966d3c Mon Sep 17 00:00:00 2001 From: lsig Date: Mon, 24 Nov 2025 17:39:25 -0500 Subject: [PATCH 020/131] [Read Inode Store] Add comment --- fs/rustezfs/sb.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index b52702d9a72d42..8ad7b841a507cc 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -48,6 +48,7 @@ pub(crate) struct EzfsSuperblock { #[pin] zero_data_blocks: Mutex<[u8; (EZFS_MAX_DATA_BLKS / 32) + 1]>, mapper: inode::Mapper, + // TODO: Add mutex around inode store inode_store: InodeStore, } From 927cb6a9f71155225477a648b78169e1e6e4bccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Tue, 25 Nov 2025 17:39:49 -0500 Subject: [PATCH 021/131] add ezfs formatter --- fs/rustezfs/big_files/big_img.jpeg | Bin 0 -> 29296 bytes fs/rustezfs/big_files/big_txt.txt | 214 +++++++++++++++++++++++++++++ fs/rustezfs/format_disk_as_ezfs | Bin 0 -> 67568 bytes 3 files changed, 214 insertions(+) create mode 100644 fs/rustezfs/big_files/big_img.jpeg create mode 100644 fs/rustezfs/big_files/big_txt.txt create mode 100755 fs/rustezfs/format_disk_as_ezfs diff --git a/fs/rustezfs/big_files/big_img.jpeg b/fs/rustezfs/big_files/big_img.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..56cf421ff93b844e19f0eeecadea9ef755e3e050 GIT binary patch literal 29296 zcma%ibzED|@@UYar8oiFVuj)ooFb*TySrP0dx4_Gi@O!KK#L`~JA~qpK#LS85?W}H zLQ7wI@B4l4{k^~5=94{VC$oFb&g{(2&P@KS{n-LMP*YM>0$^bS01lWB;LizwT*2So zJs5xmzy$yRLKx5~;Qn(5Pdi6|!vF??^#=ur0TAH-Etr~sgy0?l$$cUM0;2m5NJ;OL zl0G0O!PNIj$jK-usVFJP=;-L_>F8KlSXfv&{wY|51O$Xcgv5k|#P^9wiSLu&#}snP ze+@uMM^1(*64yI2UH-ig>szWnNB{{A29+F#93Tt$xrq)bq|D!?1;3m_NO?=o z9@(9yD=cU?=l>jSqP=~CkoLBN(O9U`I%Dp6POdSvn3tl3n$XGI)#D;yAf`<|CZJ$X zQSKfA|Mhw055W5;0yu%!-oFv<^B1(|5QmNYbSf($@)y$b0t@Vk=~(a=V#@rg1BMwu z^Dm?^ZNS|8_xJ((Ux<;44KMU=_j~4F2shjR*8orsSCV`F|2)=J>ILBRpV9Y7vR(!L zGrUin8r^?TKQA~7=lyrnVZny-A6!j#O##Ax-i1AXlO1dJpBZd|x|pc{HRs8{C^_@& z@p%7vg*Mf4EX)7F1@V`uR%88Zs(&XB;x7->z<=?tzWJNl7y@(@sMb{C8~kT9A*8~# z1ry_c02vu=ul^T}cphRN3i=lZzCy#s1xF^uOU-T)m>w&_`}Qvc15JL`oTy zd`EOuqaZ!>dy1}%E$6O5>J&*ip+ULqqF5H4_!LtPS2o*8PN^p(*ligB0a#{Q3jrD1 z!2?fmPvhlU2AQJ>*iPfUAtvUHK|tOzpG;+y4=@f0pd&TI<&Yjdi8>%5$(~;bR90Dq zXnj(7CuFQpAgR1>T_&oXYMimu@ukIq`B3SZCRmy9Cw_KAPb0@4o9FwVF z4_naM5Fq}N`8?UBcphM`tSbCSx0oVeix|_S!*GoxcV4Po5S0ld!Mc&?HpzrTX(ESDRmU~q?RMwebk8%i)5lvCQ0yMrg@o9;X!&dmrN~k8c0m@i-&(NBo ziml3)fuEtuhPkHWW~eezsIt8>m1)1AQ294Gb^nr6faLwSweS6E(hNsR6-mV=wt0sn zix*r^3cV#2ASm$!s6R^}bUI52!ki>I%aF6vl!2gR1AlCze2O1hl;EIyC8lkPd#e|4qa3Q7Rh)+{-IrMm|JlA^ zfJ~0hispPQT2`<`lCG+xvdc!vW>difG+AV$karVN)B4Yt;|eBUr}BS-IlVV_;HXRwK;ZpXO8$It-y&7ldN#)p)_2zn9!$0Tkk&67M|uG-=h-2x ze=?l6B9vhOHDcow?Sr5c`2z$2wu#c(ZSxXOG;4xCv8X&&Mdjp-=8FgF{6Hj=)5 z*w$mONwM5h(SaUZS3y@MW~@NR(8vs=GA~=9rb25Dc}(j9%_e*ZmF_xWVZvB>Vw)9Y z)>zz1qm3)Yngc41e2k`?@~g$p8UxZf2PpaFXf{}Yx!O6h){)oKs8@_BqCd}4K5ckB zlWul<-Mv_3*_<%@Fx>M&+^4glBR*>|D?0TLVEz|4`${rOVj&oM@R?zDbg045Z0YG# zx_O@xdN4_canBF6U;S0~xcOI`*d>p-9r(fVj6x3bUG4Sg!fAcl$9FlWmurlx$+)-i zV6A{Ir6ukZ_4u?#Qz50L1J4-0$~qX$b5;-Uw6Z-0v~Lmm1)HIPz3EsRm%U{tVm(e9 zuiMU7F8Q)X*cmJ8<{qao!JNl}Z-<7EfVEtvBCd0r1G+?q4zpWf^x-q-(4YaEI#v1T zEHC6P{>qFHL6@AQR{=>HnP*m=YQbTV+0Lw(3Us8hPPOQW<@Eh+!Wgf&qnzRj&yIw* z9Rif)$Y>9+=M#KoOA!sqY)upXw=#@p%TNV;J}k<>V#`p8`p+r=+HietBv?d)nMMCMF$XyL9E_O*7z761G}?TYM^Nf zKH^fUNHym7Zl9(KD2aC~b z!yMR1t!HGT2!y+lVfdcTr(8}%x<&}U*RYeF#njW20Wy|jayu3?IHotKLK*nFLF%+ zd1bmG$-1ULaVckoyGIWA z>g#r;K|%y&ix`>z>q@aSWMPasTMT=Q#&-n$Y!Cw23=dmD?n1%q`q6%Q#vf!3V2xQr zuN!}8!sKe)^~;=a4KI^inhI#~%NX~L9loWs!=~pvMcpBXAxl_F_hPhtJ$S2V2J!CR zE_izKir#un2jr}6^`x-N+@MTtRvF#o4CM;led7YH+4xx+k^&eG&6YG8k|)i6%dNDk zdc=l*k<5eo#TWnR>d@T1O(-wgV@v4rW-AI(i&9~;xvw|tA7v9&0m7=AI-XE_^5Gp` zgZ>oA-us0{vKpc)cP?;yyFZ455+$b-oHytcnwosojuxH-5qjmrjI-2^ zc7-90T3>c~_M9!qoyk#ATsvvHPIOar%2d&Uj6SMtkr-xykEz*6h@Jt?3XfrNM$h&>1Z>67HQ0nG z@WVIUI=Fygi#BFmtB}GNJUY7QHBkn&+x!-3k` zUUez%Z7(Y$a;p{+yHp+7PXNsgPog6p_DnrGjM^Y`p`b2pQDt@`Lby>D|2-6W zHNJ{sqR7xu0p;Kj4M?bR^5CKcUy;P$Gnsr$z)n6?c}lXAOCxh!q_;E6VtR$E^<`j| zp`nCaD$#Ms$?^pS97L&ho|iIOSMlHVCQ<#CJIkjtBn?sxhuo4 zL}`$wRE3Pb%yofV!E}$Hw3FkRNOO~ulQms_BT4tr6Cc@^3J`*2VxT_XLY$_7moury zF2Fao!xm50VNckDvDz{dQ&+LHcN}om*vu4nj%cdmbLCV;#}|k?Ibv!fjl^J=^%>*J z8|5fRDPiIX?E)n0wzTo?NAq{bFu0ejDyS62C$zfQhTxxGv%tqJI^O5|tYy$;5<&9N zvVC!lhdi6Jx$dNuy6~Cur`RM7^4d6JfyPm0D@rW(f+QbLsNW0iZ8bW2HU>oW))K$k zDtD0CUODQkIISH|DC{0pZ%Qt28)_As@PKx6HMlrj>CF1wwjy651V%T|5F}O;r>x#-KB%L{Y{S`POOIA~i)^w{fY9o43JT(S(XGnsAg@ufq{lmK&i ztTwF(9cY|{7dn4&^#2MyW8T#bM4fH)?HYD_$dq0bTF2ipdk&)*{s5R7d_%qTpHHnl zyJzKVJy8)QzeD$caGPWOWNx>%;Mb=g=Y=q_uM}Q5L_Ue_T?R$fLnrDx<IU!#3HLbS*GGk0(0GAH8D>WMs9p3F;FgzllP=kydF|5jH*} zr;KUeIa%0baENOmawd!kMoC!;H4f|T?Ch*VRE&%i*K%p#Z7$Ru(~9NKAlFRXPN+Wi zH4MS$Dm=11&{>W#KR+dPLgq=vLPAU2rp%w$m)SU3A%dcF%f3SWRxHF>B|c})R;~DN zajUFMPqm{42?y*!U0c$cgceVrNDgsgsYstl?g1$#<+Q~JgPt1hl0 zKLVhu1%7973en#H&!N zaoa%I)%sV^8W)}v`n#IME+gDFEm&xCW8grTg4WI~aa1~YIVh$`k8cO#J}Xi*z{>EO z8o}&1+<**KQamGobPfC_55rnGW!oN84l4mQ z>1&nVK_Cm(NNt8OuKYE^)smcHCmSP&lYOB4?nsg5ghDu_iAK^eUF@K6bA0SPr&l4# z)(q%5P(&?1^yL$h7WrVRy$WF-V6n^i2{|Wq157-j!Dfe3NOV7|po3X&`JEP}+9Wk4 z-{6$1>6VjU0Zl4Zs(Eb%=Ua>NfMlNyM3Z!G)cO9!d#CNIWD=C8*F~ue(n`wx*xzSI zQro{}qk3ndt6*EAx8S0)l&{%nvzkBe;jPHlJ&df5%SmM zR8YDG7@-4w=wRc_N3*Y8B7^yF3$J(!-NNUyRMAkB!&9EQAE_d_Tpq#W>rnIo*Z}?q zaI83zQ!;n!s4BA9or=`0o;ok8~f%{BixrJd4u9}$R2s5X*}ux~eS$`!Sp@_j4z zgEIVpywe3vABQ_Dwf&rWH_O=D*Rut=vFXW2Yy_@z3Ye73JeMKxGex)wLb&lUH0Gm{Pf0iY4%wyoB@ zKQTtm6f9tcE)87TaGP(`llAiD>(?G*9F%_m+^1K8d>iho^o?H4&jqg-GRD;$x#64b z!&P1;)Moir{qpJ5{&pXx%3D^ThHb-_e!DA~Qm{=E0-Ae7+met@Dz*~c)DKv1RJa2! zI)PY(TI0N%PqoD9DMdOM>L02{LIe%gk6HuvIN!R3dv)^`k15#Pm)Qw1qNS!jzC>+9 zkX%I&Ed6nf4diK7GmIzJIpM7Lb`@gbeL|&JJD{!GVwU_Rd*BbibQ-;)YFGu`T2@O%Vb0jar5A?${ME>SzNzR z`q-aG;G0IL{_U8{1y9y=^cnm4!7zj1-nf;wGx-?q=qaH$E+5HGppna_g)~bb?gF*b zrb+DQf?VSwrK9P{eE*;kNaI3Rf2G=&ET7g>g4XzpS>(9;}jycf2B9ibt-k=g>aqmgD3 zl6g3baU7)zMnYS~yx7|>@^eQP@HNjsO$l``HI9dLhiC<&1g;dY66=N~I}yNT#Dl{^ z-P?Pdr7pXVTD&PT%{uNYxvfcPBr&pACC6}a8(}1KT|xueIpw-G)xs&oolUtZ-{@YK_q7Py>wb1{ zy3@V|$q%BTt)&_qfmZ6(rbX90M5qJ2=^3CfoPV^c3&LM^8ovCQBS1>f=OB0tuzlxi zm#4P!vL>vLnw5Y>P+c90!l?qRf!Us+_b!u(V0v)HrZ0|Pb_Jz-9fsbJF4ow4k?J&}T$ zOXPm)OV#*7=nh~swIXZ0J78~R94ni3+&LUQU_#O8y5J6uc*L8>@3eJU!u*=x^76R3 zz*n<5{`;=W&&U{fdlgP{LggjROI}`TIF2-afo=T2Izi8c8;$lNm5)wgFR=Bm#wAcmP48c>#nkB-Y zggG(N^BOKbC54{v0{S~POsUCSV?z!f&%f;uiAO*fZnf`io^?liU?UO%&s0Iq?$<}A zC;{#a=sV?GMeQS}KY)aFQ)^&{n(k=XmFfuj;)0tA5@gzur}Gr9y8rn@gz16jSCkm- zUeASgZvG>h<&+k1$~%}qXr;G(7U=qPftxEu8JRTTUy>ATBTfszPNvR_XwxJ1xy-uv zX#0mb&V`UHWZAk&ITze*u%u%Y4P`P*T(i{zSslG5g|j66C{LbcH@txwPT<-Xt&=l{%xF62oKGQ6ihLJUkUm?r*5-Z9y%bl-+k(qCpboH78x1kr1l+Dv)pcr zPM_B=Y9LBfZ{TIKHC<-BI?>uWpzP|LB~B{RJ38QEZ-q2J&E6|8HhSXklqU3*N9jmY zeeywLxjNLu3IhuG-O-Q@TiQu#@A( zz-;Jo(QHq9Gq9=7{*%Q%c)Mt|51ya<(wgb_!cu$SUGjRwQ*(vJWH)ONyXNU~hbWNW>?Ui)xo5_;YV=kn*5UF4 z7LZI=@TGM+tgEf^aUi*fRGlXch!>3DwyX{=O3^86Wn|~bK9@4Yg_uyiz55s;UQ_%l zK{TiIIc|MsHJtFApZ_Q1=ICQb6ED&`UnERfHfBX5Yjy7sbLjasH4h6JElfHYl>a^f z6%U!q3VzJ83S7%nW;?dm$HSO;J}Lf50`$*kK4>JR1bVrrh!a+h^=UU5^agE$IrYTp zR^~<@E^?8ddNf4lta+HC_`SBA-+${S4&*Z@iM4(`WPf^>+Opl>FduOKHQ|@tQ9bkr zX&i1coe#+UE)mSEZvTS!eug0TV9XDcbSoGg%MGP{_(E29#q7ZD481XkUWRV4z#ktz zgZ5W|JNCO}jk*x5!>5;;9bFA&E2mF;=IH%P0w?ceZlSB^lvqImwOd=>k2>dStWl^9 z{jz!u)hiRhoj5YgV3d?7II7m6Rj)Ce8LZ^u=91 zryK}>u(EJ=pQgMKYbdJZ$91y8&DU7HH@BnJ-OaBOG zM{9=~cR6qQhWTc~kFuBzPu?|>S2Rzt4}lqYLi@IX#t_oUcI^=ScFzX9fnV%2S3zJX zDmiO|>}|t1o{>!ET+YeyNSgD85V{n8)AWAfLD)FWV*)%jvt_Tv=d3aumD3xi@wM$I zG=|{1ebu=-4myV04o%U>>LQEPH#eH>*%B#Mry26ev?C@6~zGVs|QGGf~QH9uY++iv<@s zCoe8{aLYP%#$`QmTvudqv4ZEFlX;wEPq%R$c_(g|mK~3bLU;vp$xU?A>0+uIq_H>TXj=Nmc z9Nu<;2D7v##mhq$ijLM6`;Hd~4~%NC+V(AQ%aPgk%{Pw}4Pf?vB~;-N4rx#hsPQsPq^Ys5v8hacV0F;#1HaOjSUm z@S#m8!GuovB-Mm4+d#}kDUF~Pe$i&h^N@>q2AZ-PWV;&5s1SA7%>TwF;qERrkzX1N+3)jig@d+dqbNw5>BQ zi;9K|m3O&+E1(H@nu?!De_kXrcldp}U;AK8oPYb5xfBs+#d0WoK=qpR8yTghdWk>HD7u=;^oQK?AfI&+of1@gc=qtiX z(Tl;1SNpycXjqw~u|EI6f-|=iY&kt(%2b}{$k6TxUuLl&dVw{3GSKLqKlCY8*o)c& zEB%1|&3LY16^~Tq#YXwd#a6#gvxQhX3Igef%EsS|xo^(H^NnqD-EbV!wcW-a3~HtI6KlUUt7FTn}E-f5abH+;^)i>+du%2C#z zSjb$sd+gM;@sZD>f4Qpl4apzCP_s$T1Wc3fErI)OMumDvlm1DldO+i;(T)HK{%elJ z3heTi)@Qv{zpD_NgH`;8e$Na?iAv=`rRM8Mmc=XXs`#$Tf)dHs2;<9$ulX-qe?%Nl z+-Y5mY^;g)POZ|vnIKOE%>{GNHrd>)*C_yPTx5JbCwkl68N4dr)n{6?7jygp#C&I- zt#qGx&SUxEzFA`Qw{3|wPiMfUO|l5RxJ{VF-Pahsqm12zo5IEBM#nFzc5Xh8&-5SX z=s36n?bh@A+Ordz=)7W2^&jDI4%A?2y>~w`1_>8jD#F!M%_(Wz_p~Jzj@B|kSA`93 z!Z~kqo8r6MdA>fsTm{xRv=8P`j-6b&@g=(_Uz$H0%BBlZI~J*Ef45nNMg4}|L?J(N zgvdzHv7Y_rJL9dEv9}3ykij;_Yztwb$m(bNpa+Dp4_Je2`3+Vaw?SX|eD%JJIe!Gs zGAmhbk1_jcN|iJFsT(+NkUP_j^AS`eaJ>Rf+H+H6_^7fFVuF`!8LAKd6T)X9>%%&g zsRk-MxOvkkq-97HMa5GtpRDkFNFbUuMlkxBqkL77BHt^l)D5acOFH%V#_3&&d^m76 zbSIPB3)Hx1up+Z%<79XyDn?v1wL#cOo*Cp!>75+%4Z-$v+z=ZSXEHTuV96Swr7JAh zpd?ggjIvXJ)XBc$*pjS_P8yondsLdicD zte~##)t76b53Je~!!=XXMdJX!drrWbH<(qMOC~gL&@9o}m2sKY+$5hi(hPcGO1KE{?Qw^4T@EG1kcF zFXtp~CAT?6SWCPdTP-6;@$W|``^puE7ykLxjVMDbCBM{lZn@gz``)E&M z?uFCs<)*ulIgk6`v9b~4dkaTd<`*8&Ei8Df%ASS8`o}g8JPQcdyBboC$9bR{@aclt zRLEx-5d?DF4K8^LH4Tg~f|5yK-}w{@G3W07*ixAFL`z>RIOIF* zN?=dgXkkGT58#u#dCeV~)y z47i5$$VY&g#uWcn0ScId!hdD)U{t`H+M8h>f}1yWajH{qSE!yhKAmEH!KKjimVD&H zBTheC#!l+)^ju2Q)iGa?7pMRh_xDn{Y9M%pBaw+w2E_yUQjtX~1QR`=1Pi)Z;vHsR z@nyiS#F)vCY$3OF-()0$2b64{N{tCjYJxH1{`c}0H$erO@_s-wtd=cNqqhpGpckV3 z@cq(Ig$yO{WrmO0Ay~Ez)%u~f@yACocQ2hqKFU7+aXdreCjCXUs7o2WUhv)5@SuR3 z-zNLejuzo4xP6X!D0%}8d@wv6k~$FDcd?7g6_Q(=(PZ9`4x zqVooK9|9JOE5A;wmi5GIr-QLi-2qja!I}?WNB30d6Zw^3+`-Gky3VXMQouF z&ERT|`*Yegsk&0^(Tqzuh|_hQ_rNjn;8j-EbPEA zEGz2b#h*^dUD@2Y>toy%kE3ab=r;d*gdj8`#qkpfxb$v=s0@&esQSt51{C1 zQR6tSNW*s)`|bpzbS!XwqvTM}QX>sLe=kbFh&#R78|XoqgH(Eb?Qgz<%~3(nm2Elo z6n~@nk(Ipx;UC!L!4a(f0iosHp^?xfRvBd^r)pDQBZ3ax#~*!L%z7wJR$X-O=iI}e zT6Y~|vw|Zc!;4uzUI(N&v=njbS|2`>%{`SK>sqTQAbkDjpR(sg6pv?xJ7ftt|Gl=f_xsG+9gob0tbK$CJJMt2nypxY;g@monsAqU8evwr@(0 zwjzbx$}?2ilrZ1t|8KU;m%qA4g9+oXc&$2ZAT-QFG!&oWYLuHTF;4mXWqGcmg7?iR zgh)NX`6H#!HNx#9a0a#GTF=eu1k+dljhKm|K97J{mhMnwG4&LtCQVHs5V4EWzy7t*iCHts10) z2O_-Sykr5!nYm_;z7yV$AE+c1*#m|K8Kx5Hy-G4eVdVwFh&6WP%9$^(wfDBk#m@J0 z%T{Q}!>Vkqt~eIjK(|^sgoqoG8qce^E6-JYw(BhS$*0_r2%&H0s7JQXRuHR!Z7(*o zsI9-3aGzV#m#FaF+O<2^^*Y#01f^2`z-UU|>4NX~M8rqPc4Y8oZ*v1^PAxWwXha6S zn>k9!mfo^wxc9)CDIY7zY=R1*=hv@y`rK#2=_8Ip!L3$z@<~!{As@;_%!}$J=DO}A z4$#4y#n4GS%kfTvDv}oicX;hc%Wlt*VgL7C!o}}v%l6DxGW{bSuLpU_9*TCW$lfGT za85x@W!G*`e!qHsh@!1tonZ*nLSYAa(IskwI&@*5%ARH-QtDJrFDoI$Bw`PI+mUSlT(AWWQ|L&UOTMPn;#^Xe!S+`G-(S| z5i#%FfXEuxJb3c!4L zCK*yKUKmT9l}=v%I2ZLamqC^N8XU83K>f7eZbG6vI#H=6-R`uyuizuAml2IC5s%w9 zOwoy^+QW5^_l<6+}bno)}^>5(HrBTPJVhq83znQTd z#Cv&AoDSVEiimKR!_#SX%Ku`b`jZFm?v3*Ngaw{Py#di-f09pqzaZAu*RB-zj2e$dm23H#@c%=NVDozL73 zS%^B$Q*?m}XpO~F29w=liWE`FZd(YRVY>QqOw=O76%%7*!<=3IS2D{lnTjJ@Bit}0 zAP3jDiDRUSVLZS1P{0djTvxDlEp3`ds?@K6ZkB$AQwJ!yo)28(3mnX=6I^G zx(()r{LR~=_H7#jqym};}U#CuGw(|*3Uw#?$81K7Ti*m)L_BIaU%BNKg%m_YEo>DVs=%eQw^R6)ypRDV+7#{iDNv_|dY)H_7Yk*cAVkx&Hj%Mdc z8OZMJU4>V`wJ-v(Z?S1 zTSJagfWt9*Ut1u&=Xb$eYs=7EMc>A0Z3efwG|SQ0f%JxKZSse0g#)F!Hkv9SWN{SJ z-fL7i&n*Zn!u2b_!o3i_{wLL_8N~V=w&khRJWZFtIF@N~|2r^xJ)zcZd#F{x((BcI z>|(p_ElAM0@6)v#M)p-pNVgSuOkHETc~MA4PNp4`6st1QjYC+w049C7vprYt*4+a*<1u^#MeFEafvxQ!C0|e80 z4Ui!xFS&PLNg_Bcqp=P0Uaw6&zmjvZffhhj5b7SI(c41nfx8Uz*tWp^a^d*8n-rHh zCM6mA_IXxkp~MNl54WGvhGG+;u5j%9dHg1&(zp0c;B-PGYRWtRYLvZrJ9)0>K1c954KnznMbce)n4M%*ohPb^HYO#uPgj(D%vX?>e-=~H*XBk*m^B0dz45XRjNWwI@ zjC>mX<1}ojhB@P7DPMEq9!}v>DmIN3@cI~NvIaKJ^^du10%vY_C1?E=9ZuP;FiwLG z%-8WOW(8k#O9M45fe9g^hO%?Kl1Lmix)aqFxZqply;V4gc?#c%}qv)n~21<`ua57Z>32=`yKj7chd{f*p@^rpf>+aSZQ`fcdz7~1T?I;mxxvC zGYLya6M)%2TKsf+T*6?(g}w86GWXIRMW2OlK623%uqpK6!<=mYCWFcnE3m2yj#PPD z;u{*CeV?qd-#RD9Yo;4=`MH4JI5~7Y2(_|lwtK`F(=j#J<4MrPv9nj zak@?syXh}jSQmoRp=NvyalK5bd*Bq-N0}AA-iMXCAqa5);Iv_{O{M|WgB-}^m-aEk zrqYe2C}9tSn|vBapR;MbMQ%H^RTQ1&%61S5?rf_cFBN?%`?DNq>8U|fDZ<9FO3(X045^2Z&jb9?-&;dEb{C;CRf``b~se|bNN~T z{`7LDJ-xHsKSp68g}P1HoRBl4+U@*50M)s$9PkgYw9nCn(P`}SJTqq@&#$D-EZ8_z znUpgt=B_?_%g~jwt!VKt$O^r+cclGC2vruMV_lx_p;ibt%R)wd6s zx;}iTew*0dU~}6GJr?Ok?se7jRx3O%+BH>MR?4#g6BVQ{8Sw{(IkRI)j?VH(K4&6Y z+#3pFg#pSEeZ&Gk@WF(Jw_2F>C|D2S~vv&9XiCH_ow7poq%E*q*iTRUyp@L%| zD*gkqPKOj!5O8h8fl=nl=#{*L<;D>ow6CHm$(JGtr9{d^#U_I3zY%)2rsN%C+T`#r z*9uL^dn2vQgrz|^rZqtd{3Lq=Gd=jSmGa;Agq!&Ui7N=5=HM(%pj3<{9rZ+hOpm-Z zOVCgmv%~#OCI2rEJ=WFWUom^eq>RbgG}x6ek{srYG;xTJ0~)=^+A0>ng3$u!fQxz}c1l1Bhz58{&}d_i+2P+~oc#=wUgk zqi;iQR~oXZC_sq_Y6$du`rEkyX~v8Nnz%F%2()4uTW8YIf_6EDlc(UpRo5%$pxQQ! z4`gbKFWvOTzn76a%de9q7uL70r*|?XD}lsMjJ+<(q)9fr9dJ$`i@$@tJt|Kt5=IY% zdJ?92T3{+N8|DI!{VoC5I+rFt_f%Rma-iUm`ED3oaU0-#=C?4A7N`=q<%k0@3@`z zz>+g5s!r)0#nXCO?TaFQH9&@B=J{gyBo(J9*)*sQ4iyZ8gegCZ*&Cxa1Qu2MZ*CS6 z%mugA(LF`@y7qh(@TvmGQrYLTKSNzU2`3+`C^b+i9bzuCsm2 z)RAgXMAP>*PJE)T=j+|FXsd2O$10?Lse%0D-Y@(36V<@6qL6cPKjxxtCu5`pp_5mA z50@K_zw0&PnZ)J(_s<7GHtpl|qhhooI4{)pzK!Xc1R4mI5t|g>7Jr7vjDeK^gNCtND&y`M>HkZw-f?YebPPtIySzgE7=9piP4`~&b5L^xWz2S)7kNf>CQ zh&Z;JEnkRKh#YIaJy##7i-*OxXA0^s-e=Y7cF$9KWhcK39aZ*ggJo344 zhVj3E*-S|&=Vawei2<;L=W98|vge#xwJ0TOwcJufxt1!ews!B&#^B`ZievVFB@mtS|rOS-+Eo-wf3iB|Wswz|s)P!@^`fR~aNA<0-1K_jN`_ zPetyj>Iy^GQnq#MVFd9XcU42GTRqQ?LHr~n%l-NJuyJ6c`eV!yH*gGO?A9T!&5cowX+fL!Fouf0!Fnk$7P|QmC zoM6fvgnKy(`Z>|=)jOm*OfF8%ARrLe(JnzmVBGG(r{~r9i^{8>n(8D*V5>$h$RoqNJM{^^v9X5A!ek<(_8&mSF%9pIqH0osG-~@abr;_!Y}SG* ztfEo;+^Cjje$i>YqH|xu7liOYL#}euHlkX3c1TSFe!sGZ?Vj16@TEezO zMzzEbRAU1tpyRf__*8DI@rjU^g=iQyI*t_S<63M?j&Y<7^@ds^jszF9KZF!DJnHL{ zurfDq=DLEmH?)ztvp>_18R+lqbWI|84otOR7L#mCitHUG`U7a&!Af}NWbxEBZSTX6 zLf1yE39+WnuW?qgqC;aDZnGKRkQKF{I+QZe+g0#Kud{YpS35`*`pAO=+n}dVgS*Vc z$gr~L#bk?iboac^Z)V1-QCeE$t{^AX(7Yz|^J*5JH-;6zNSHdGSB_5F33mi8y}KvT z^kyZvfjyZWu~}bU?OEk}D^N|(J}5wM}R*W(!Q&=iJixZ<(_qYbsFIPn2lGMQ?8 za5sGAuIp&RQSGbYf;!|zCb8oE$e&V@@(FmG{z@kl^H0J1Ilqrzld}m4+y*pb5_OD{ zj4_!y1_;HisWzd!mW~JYc054+6|;9-j>jY=j4s4+RC(;Xj8#!EmO$^ufGq^4zgI37 zr15x{UgP#y1k$L6?)3HhVQ&pH`<4%b`W3>!EANRrk~=$RP2RwGS->=Xhh>*@SiH_o zSLSK4o4)#wI6Psr_-|z@ws=mK4XTUv4{rG>6H8Y@o3UEqRbEqhh{uOW)6swsk@4Tw z&(AJ1UM0X>u!NrZXVjCj*RNzo1zTOEGbZX0SV;%}UyNhb;qAkTDcJu(h4)`Jl=`bwr^oUZ|y?010hOQI7a=j_qlA(wr zT?^G`8ungDpR0{YJlD{Jo$#p5v9K zkM1s~9!MwM$Qqw*312q?Om5=B>D?OBX1}XHE2E)~ZC!umbnE81jM~aqhT@8oVWc=I zx0o0qYz>N9ExcVdSom<06808Q4BTNssCh_%J-xf&Dy8IhbK*GZ9Os!Bg4b(tvNDW49G7km9eSJ(`${_GAJq$~X zJ_#&I87cEF=StiAL}r)R(<@2z?gN*|Be<#!x##s(cX_w$-b6x6F(jTeIL;M)-ty+=w8@o0B{I0j?QFi+<+oFDoaB-=gRz13oCZP=q6a2zGe#wu^t6Vw!&cbC}S)&u2H2KJ4n zDXNeA4+av~Ma8q;rmJdw{Ka`nZtj${tbkpz)WD2Uy?9EK=$n3}nT1;2!AjI)!mu`X z1sg%gVMB=cOI7a;Yf@K%%nq_Gkl2Bxxo|T6)fxI5bX(T7tqn8h7Z!nEZgAUmp*%U# zSfRGWf$TDT00p)|LzE(02P2#?P{LGO8vUk{wep?33u@8TLzL383cy;j)Tz&mZrYk< zE?hISFi>Y})>IFi?GO3N?2d>`6PQYTr5Q|pheFSv^?-32WiU*fqwG2ob*xp=XtlFg z2epPqIk@P}xo)v%wbE)eqs9g7pIG~k*2sG>4`-O04`Knf{UQ4g^|7AB6Ih!Kx9J9U z=ahf2bYq(bgsHL8YaPEyQ@80K>>U|hiO#_@RPFjse;=ejVCc+C9`(bBl4-8r-lm*H zknUX{M+9m^U_a9RVhGA&Il{iBw!Yrm4Oje&$3T5j8rWIuNKB)%Khped_A=vsC zVVqskI?8?!4w22r>u20b#co>TG~V7dqyyTo2>$?K{wH+2FXxctv)=(lv!9F_zv_RV7%HA#gg%7vU~c;lomKofMTW zgENfaCC|1T8s!zb$wH&p06gW^-3R#2GBLno3okvYaz!8j=Qabv<)vu9S7ZsUIDA4rpBs?7OkUVCI4X{zfS z_*C+lTk9-Vr9-jG()}Ry=Qj6CZBCJw*q9UR7wz0p+*KOL_Jfke8cmr3?avXnO0fP( ztDHWS;3>jo?X2IueY}S4n(f=Z+jS;@R;GjeOw``nvuGRJw(hz5P;o!jA#wLgn%H*r z5Vq}{fIsIq)0FLr$-UO}+OSvv`>Vg(u$j=(fr9W+6WulM<8Ahug9{AzuNC{S8hvY= z4&L>_xMka+ySlwqQrRf!{bVQ>&fe9Q)voJYy7}wSf5Nj)yff{~NF5gRSwBN3a08t^ z%%|rZzi|HmJICA5biMm|8Wm8cpQ~dtd^(Gr-ry^%UHY8JQUwt@nLIr2Bxpuof&f$P<4gju1 zqT~9^N835re;kT;YRg}}jb&-D`cI>qWnH&vg>>%j(0XwH0OcKJJ}=6#7OZEx60W8G2x)F1kBl`&DX%5GEm7dK3crqaHq zPC<{oX~^ay8%@GpTf1{X-$J%e`>FjzCy_0?+1uS91+UrBcoF;U`%lbFU6V2m40MIY z+woQzSESd>`=gnD&KtM3t~HHTt^;oRo_QDm&$hU2Fbt#Cla`+<0@aVVwTWRyNG?Qg%4f^UfIypB8qY5BwDpW#2mUp3I)*l9E^09 z0IBXKe0qpfVB9b6;jP_Q8XF$4ouJT_HW}Km zpb^Srgi6J-rh^HiZA}3%yF;3*r=*mI(t!1?;e-?I`b~3aa+EeiKVkm1Gi~6TZH6;x ztPU_n&q)6OVEt@kwdn?S(`eX(HX-{5MmgJblskTtVXX9nHe>FdjFY$NC~S0^&1MYR ztaEa@GX~y{zM@H@EqjNkl2>x*+ON3!m{emH)mA>H6--xT^){^vtrbJo8CpfzQ$tE& z6{70Uie&aVp!Jee8DST7ba076fWpesF8=^^O#oyNM$oQNvILhoMkPF(1`Zl$RuI$lXq0t3v4djwSZaab}e@C1gRNk5!r2$ zpwN70rP*0U0+f?^M)wBx=|upDW=t@bRiKr8j4{KXJeOc=K@;5FHpl~vY2QUjnRl;? zw@q>ok$R4psAHMVHDr^P1DsmX4k!i@%XkV>Ds)xDnU^|`3B(6FOA{}x!#sq@&48>Q zWRpXH8ICc6?%vhHTiI+-3bzv{uP2%VR4$ZS4l!Gb&cxR)F_$jKNW!_w=+X(UFtaBv z3Nj(6xa5uqxL4Lv;()poX-~0nC)CFKMEjfSISx|mX;4(*%<+m(g=LWTn;?{Lv}5xy zf5s$g#oQbR3e9)Zl>n|>;BFvQCEBiXRmccn`!H^JBAaER|Yqk&1mydgHw(pBT_xB6gRv)x6 zp(EiLv$nOeL#?WIc109(a!1Z-Zfp&)(2HBG?$ydAxU$ymwSKFN9sUCWFTO`u2aa3J zn`XMKz5eOB{{Z<`iX(5dEK8@fuAsh%GZCOWSM1vZ=>r~`YDdmEmX_~+_chRism@N< zCo>t_s~UDTHs=?*4M(W@r7qeRM%K#HKp{!$DHz_+ZxQlaHuPKSX^b7C+u94Xs7tC% ze$x@psXenBUR=}Z()#%jD~IVhSMxlpUDo3@2RODkTWlGgeLCs(^8*QQT;TBI0qNANPp&3?o z>X3LEW@k!_>5n)ga8{9d7*t?ulz(jOaLy(e9Py0ps2d1e78>>x5F?5OFpF)?MI%%^ zCL3N|8tX9aB&YhxUb15+HGNW(w34z2W{#;z%1h2ev2}{+l`9K5)*XfdD=1bQ3BnKDr%|ssRDlQFeM~AvXpnU<%1Dc>GRU=aQwm{KpcWNGn^iR!G$1AkVHd2M zRW)2x&VkNwO9?%dHFA@>Wq=akWfn#Q(I;#i;fD@$p0Q;5xTpsRWL8oPqMmT7L^6F& z?Y9i91!tx4`+z{kc@%0Hv$5QT0xy<(>%-Np%7H8@W^UT~Y7%}EK^m(yo*bJ@Qrpp{ z(-Azn3+=fe1E-wzJM&9MWbD&j%|uX2*W~r^(b;W^pe8=HfEdbJ$Ov)LRSE!6c8nrVQr7i+Hxv=walE%>sm`yr@6S37$b?x zgbS{!lYkLkA<9DNE06AMpv{n~*IS1^aq(;q?lwF`TXs)qCo)*Xxqc%K<)GV+mynO7D^u4AV1xMgP~y6f z4_sj^4&vNl{{Yu7PD06 zHHokUT-4x3P^i}3blenS#ta&w-W`<4JmH&=@Sl^k z_a9hPl?rtqSX5aRQFZ4If>9O~SDcEdy7PuvL|9c>HBn`R947+wmkWfIL==}2D#8WE zDsfReQ!S&6?t>Bk0G9-k+Dw{aHD^Ok=)yp!lmg1rLuAx7CT9gP&5`%eM zazw4PBnf6(O?B|f`B9pJkW4CY`NGg~lw(ssB<=S&iZG`haNq?{VC{iiW!Qtq2&aKu zt~C>c{^RhHwKN$C#`h2gT%xqqT#4r{qY7}9D_Q}N&RAnWApmSETKpiim!Qdb!(6~& zDi5)}B-zQpmb*2B~g?4~$oEFsJDwW$Wdac}TKcj9rKZAoyHfN_fp1 z)u<mATwGtxN^K`NL8AhJ9m|R($;y z+irU;yAOb6E%G$}v2<-e-6o>gU{|9GiA~L;RW+unqZw4VMY7G4E`}XOQ%O^GBJQgC ziKu20yQ&*?&q=6mh7R&+Z37{fq@~M+Q%S`e1M4&vGxrOt+ghB#h?F22%?AT6P)?eG z!d$7rC0dI7p%&e7A1Txsso@H#q}CRm9PNTJ%thYW20uZVg1DfHkCZzW2-1@32{f0| zYm6HV-MoVC4*qkSb+LnDMdFP}n@7k&-M7p#(?& z0FPNix9J{BBnUEvOwelwDoPt2C1w^`QR}AHet{*u<;+SVRj4}OYcWLA5tUAVmf^|(z2M992lS7oS!6+~-CS2T}7p-f+ zNDU4UVAX=~5QN}J$Ym=d0lCB|$DHH)RE~H~FWh)z2YJ9`9OV7ZM*yI>PFcWiMj%rm zSj`AiUOXT-C+Qqme}q@UwerrmzScD95V{T{pBbfkfmMDcBXnb{fSK0X)@8wi4mnC2 zfAZUuYW2FBh&CR@96^IpWQ(hE(HM+D>LO)_N{6Nr?NU0y0aMBeqJ`CrEt_8IPFh1Ww)=8OFi!WkJS+386;QQaLR z?evQyu@h=k*^lZMskDv8Aq$RyQD zil!Y>aTXayQB%u-Wr9nE=kS*c6$%9s;b8(xi(}&vN*3JAq!`rJn@-c~JK zAehox4&jS^sYn~#iQl+uggaw|3)`-9pMCbT4Rw+RZV;Vi8tJ!Wk%>HD?>Jhh&Mx;( zkfKNI!)dNfTDheGV~NHZ-QM9i(q|VmspW+2tH38($FH-&-5M&zn1Er60J?YypKkF~ zCn9*xoyGthxXmW=Mt4hTqT^0<2M7l}%gQ(mpf?vq1u~1B)}1{LFuTtRp1bBAJB)Ob zjdGIjxr1^TPd&Wfx^7cX7RG4pH*0-KuhIT6n`Yrx*JQ|-#T)|`bp(3L?{^Be!{%ue zP0Czl6@^x^;m5T`p~#3UmcdX*INkP9iO5XG-J+IS)EJkpYnOe1s|-dU#jZ85Do?0^ z-fziTaRy|*?W#uu9E+NrzjoRYNR9i8pE#}S?D2QJ#05Mh!V>Mk4MtL}bQP=vwMIN3 zi{UClv}U@lDa1;J6vK=_y9dHCYU#ij@SKXuYb=&a7;9F|*{ihJmZlPJ#Y%0q#GFLi z+HG(cMy%`=Xh51acHwdoF2oJ16s8fCw+^ol%AdIkr zXyF%S5GI%HO)~V7oMQ@s4P~^LI%7I8jumTd@9?aBUZP=IxK@)w z&Faugm*Ix`pVfp5wM?4oAZ{@cZ)s~2PzM=Hw-hW3-8F!BtitbF%>cPqxJ@vWC@Wr2 z_yJP`akHe#&z95Z1>2MaMXcU6BdqQA&H~XYYZSb+n()&t?Si=H0azuvSagE9bX19X zOoKhr*jE7&yLpw3P7|woq>AGf-DMojT$l@V#Jb!V(g$t5xn$h{{Zox{qKDxVb4J2x ztX?IUtry=j*$U<=o2FZWhMi*7Bxe9$OIBH8P8$2Y`8H@8reWOQHnCHPox6IV%)5_A zl_7X(+;ZZvOMr}PI+tj)IYC^y4sxU`RMo?Tp`paem&ej@)a8u4Ce<#q5UIe%mu~kB zX;{_29LE|%w1mrB1e(${Z)QmtO`AS50fc{V<7jabHr%k!*zCw45j_^uY!nKJOB*F# z5$jf|gwE_$E!q_Hhg9i=vLO=SM3*#*QcWUSl0+0M#&b-uoQ6Z1M70MA%JMU!Ae7-H zCuD$flashkRsq5#NS!8Bn8TS$G_f#jV+xUk3yMN9gJT>ZS_RB2K)k3yJOe{C14@NL zV*>Ea0@9*rN9rE3P9Lax$uHoQA5ry&K?VjV)W#8H(}Ey|Q7D2LM4F|PLnxe8g;kMN z7EubKRYW3*CL%(plu-zxAh4GhP65VT2!o)RZW0BoumC_hJtc&IPJsaBCuuu7NW!v9 zQgDcafRP%o^v)}ky0tKsDt4J`TX00}!BG*jdYQ*k;9)f4#x_|>Ttis72D44AgO|!H zcGv=Cx2dMPl6E2qjYVOuQYUiYS)J9syn}dF1xFZWaNKi(EuCua$qCQy?eLd1wNXGxVN86{Z3v6eE1Q3lWt3}Bi#0B9D6 zVF2=_O#zGxoFSer@}g*UqYqgp4rA0wEQSNzePak9K=&V5bP-VoK@Oq`1Yso8T|_F0 zRS>Eq)0NO6R2fwqVN^(}%E}>>bd^{|5gVX#mjj%DOND@N3}VCwNB^lY~}UoMemyM6D0P6p2zIIaLfnjM%+G1YVP>2raJw(hO~J$~=t5Fxl6Hy6j2eH&pqF#NA{D@ zP5%I*{xKGFUWEk|OVqyv@sPRU8yK-H|1q)tUclZHykj1LY; zNhe}AB$7yiP8r!C6_Rw$K$V=N?BoekDrL-}l>&{%QKihGjDs*u3TZ0BR4Q4;U>rtX zF7l#FxXuCN4@kSpgaP`8tdbw7ddVx{CRge{u;~H^xcbAUaHR)9$}oZjBMBy$sv(p? zsD@D{o>x%_qESJHQ6)<#g;6N5f*`mO(xO~M9i*_Ntn32PQgBYdB<$f6m547St!HZt zhfL)JhZ)aU1j0@;l0eq2GL2ZdS`INYER0owj%|utOq|>xbTh>H>u+wPPjzmNvm4EL z{`ICHV>%?8a(tl?M; zgu~k~{I#uC+IkX|6q#O1)~jqYm9Ld)d3?ijY+K%g%+Gb;f90g|9#Yng*kOh<*8V zvzi21R#nPOCv?bGF_mj2WTrEeh~221l9CYs;hZwmoTLd;D=tK#5G72hmNKSLP|7sB zL72%y2F6{ofpaPq4b5|lxe%^t7IRrpgLaFvLOFqXP^e|S!`4Yt^$%Gk{3i_nJ;&A^ z1PC~vSadL`9U}=ALL&-f(}ofmV(P*bOoK2X6u_%O28hR5a9~uz116|ZEDR87aAE=j zC3(tLO27$GJ5iLSMCD*>*15@9TFRD^1l7h$m>ox)=x81Vtd*42)^M1{7u7kg2${;n zFg~$4t_HHe!0^)AU8tdrUA8VI2*PCT-%DpT?KYu0eH&+r=k`ooyq}oy`d_%Boaa1s z+Ivj&oBg1>Y=bsfwcONV=PTL&O^s5mYl2|WCxsM z0!cUxXJ8UZ*~1xSCo3V9sDZ3ze)kkUk^Ct$_oM}A=abjVzu>LAI1H`Gcs@faAGGSDXYgKPYZV-&$|uuSoGzB$1*;d#d)V8c8Uw-RE_ zxLyVcw*#EGSRL4Ni#tKK;eId=d`c_`?EuXL*T*;qzB$T?z~#Ne)<~JX?jE8^SPk|1 zkE}99!S^3nbTF*pgojwV7*y zI!lOvwUCi1JDf0X>ZF?GbCQrZbs05IQc6S+nJYL!6Oc8lI9gUi5%7eQC1)joFg&0$ zxYl-(QVGh+)HRyBOSlP>NY>TpahiIrHjMp~F|_0|R(TINg)a+$QhLjN^qBr@W-eMS z#c>nA*{$0~96+!fY#40wKmTP2|rw`clk#X5NAOr4IFZ&n|qC%Cd*Z9&!G$PRPMpCCsVGrwb8 zW1hNQqtrJ2dBGnbInOkA$DFV881awwQ|}&-`2o&Q`2o&(!@E4?4(*I{)LrAzw)}H~ zZTj=|o_y|_4YyCuSLz+x&A%MrUw>XR3AZiI4DJs(Q`BFvw%h)&CwxyCira?bWjp3v z^(VVz?@Srq9&;q#Jmn4e{{UHC+O4`IX9U}xvoPN|N*m@>^``988;Y>Uh>~Rs$5Q%< zC3G&&q7SJ0!=wd$$JP;B8HGu-BM5YgD?_76re#bjm<4LXDUx{=NrqSzA{BT=gUEnO z4CE5Paf<3P=muCwB#Ohz*hx_aT2S0EDi5m(%~4}^bGl+whV_XHh_7~cTre;(X*E_0 zTY4 z)ki2j{+6`Eq#n%s0j#HxyQb3_>P!Cs%b%ly&;E~}@An65y(?M*aGSdg*t=|Fobo@C z-W}aaeannr#d*-Xd=3zx9_dG)XhIe{!!mtoYyPd6DjlMHG6|e{nFphfm`U{V%b9cK`Q&T*jk@7&f6^MBs$aT~se5ae-c{aG! zCU2*zuU&X=T;1!gHJE-xmZ=cCTm8X_hTQFoA!=4{B$bD<*PLC`?e2#Lgil%Ge z)01!H!)fn&*Yc$C{a_o(G2<{-b_mW`U#}b_{)`{)YQFvXz`pgq=z($Zm91m_Ut#+W z9orl$C-O~mh??`2sT^f~vhL73l6cM=_2V;*;w5|WezDo5{EErm>odjaVRxK;1*c8k zvZm>Z_c@u)=!a3*-*!&vrg2{A%2eHlQpvM+SGyJN$=vH7QIjU+M5%so9m&G*>N^Tt zN|vkGQP zZb*RY)$fVhH-WeW$NovAF4p@s&?A$WTWiI8J+;xGO#c8eyH&K<@RH5lHpOR}{EvQ8 z(@@UKwdpl+`u%;qk2|^3zul2sD;-b8lJaU_n4Vu{@vFk6aF2`Ufi{mlxbn^hF&FbjxSXN< z&xYUF3{f=!$WIx%ea)6DaT$IP>7NaB_DlA9SMvp{j7IkRRY)_=o#PHNt-NEEW11@6 zeC4utDorZ_><<}_-?&U7-hQ(Bl=fr8(|D%^!jr~(8+#v0@A~n&2V_UNnPJX^EZF#!m+_D7a<2kTm5hQx*)z zaL8^Nz*NbMFbD2V7cf|lS>BK(^~-CZgQV?xKrh@ghT)}P$(+s@2yU@7oYqenG|mwo z1Et%X=Wy0Qq|Ox}z_Raf%A1Fr;gqR3M~D_T45_;+Xk`r}k`)ne66@+Dl}c-0Q6zj9 z`+KnGQT2sZq*#4N))h?Sv9zWG9&n2m29U_|Y*t4S>cnw^4kv3T3Y5aPS#>qz77if= z!3-Wu2I~l{GmD23!G&bt@?u|KBFeJN|GY|!z-wmuz54A3Bzzj=y}di@iAcXW4JlahY?~hl82mKMojl7 z3&4D5X%3?z>W}#4tLr&%h*-DWdT^ReaW=N=kP`IM{@)QE&G_p))~(&j+P9qXKag)0 z;3Bv}`5!ld0MdAWFXf9d0j9G%-UqAI(sr#68)n|L{FO7UnCn-F(cM$THNjs z4MfbZvQHI1{{TI{UqM~%rWuKT?WPxAFtzYkY;Yqr0GC^gPz zZhsi@TcQ2SDr?LMm^|^f^%EJf`4y(1CRF!ppQ3N0*(cSJ|0Z(2^;$?zH;i)Yqar-^CQRh+&C1Z_J5CECWuY~XC1m6GmLD>+OcIA z85h}=UtGrzTe-3t$u!|UP5DBqZb%f)eJJ@L`(P{Xr1`&@*=~1xr*#B^O(wp*=3Mtp zxtMwMA~S7k8nxkf6&jXk+VKnkG@9+czf#vr^kuEF${8(Im`yX|^o(VDDQ`I)^pX@;0uTox1@CBP7x1#*N`TE%IC0Gwb1 zXjlwo#?TnML65NjIMP~zl%#y@#Hre-;|}n3C8j{JlVhx}Xb5%~1T30NWLQ!$GlJ5N zF?JX(SA^jNMzkryb3%;c>|IM~Glg212+;~<8ALk{rM<(36O4aY#*lM^bQ~k>FkPUH zc}BZ(r2)=4O9cxVJz?1tLA3@#vZaZkREAn}5=*I2>Q6BwtnuMEdtGBu^_CX|Q&H4? zWr3{av8=G-+y)Rh;9_fD5P^(cRoK{hVR9%giGJloT}NYm&U2ySec_boy(a3cv{vR2 zfyB%gjIg@Vbv(4Ypi2v&%);-Si+P4-9Y$Jx&^XR_y3EtK>p9=+3=Fip-DK|bnd0F* zW&5-l#e>PSazSz>{D3nur*g2xJfH3katnY&hT%-Hy0p$L44v-@&gd}%dmxm9=XS3%kL%vjfb|ZZ?;h!z)J^W9>75u;VK< zVtMdS`1e4eF{@Uv0p;mhRirs!a*LIASla+$lpk*2+fzEXMoeXcuLBHHwNq&b`XvR8 zRTRPy-0Mj@ng%>_F_uAXfMbsy5I1~np@~|?`{42UPWNm3Nrq{Ek}0vZOcNR3;HTS2 z=W$0v%2lrMkF^*qHuU!B_`$x*8tIMy03l5^mS#}dB=wplMtPos zQo6Vr4nW7)u+It1P)lg83mrYbwAbS)q#BSb^N%NjX5JXVl*f%Z%?6-a75@Mj8SHlyQb2 zj+$fan+PqVt!kV{2_u%zxO+}xgp#{b!Na(HMv8MX>3#Vhl#)rfC@|cx{iaxMU+pqU zCxb(Lk&*dMrs2WBAC!_s!HO>y%}>e^E`gXbNe%+$=mMY_!MbW-56Vd*;Q4d;R}bw! zDN}jK$jKx)Hx}b@2jwr^uLJUuNUjZabHcNZ@5sp{Tn4k z86<}V$Yq%DFl<`5R!Jk_Q!WO6Mp#^7kTOXQ50%C1oQ$_}<6uGgNhDkjR@UH9DV6Ws zAGG|Wk{l zl0FZWP0_>=@RPbL`@T|155#gZ-x&~oQX8ZSrG8RL4heMJwJAogp`3fyITAf2k{ksF z;Dhc{@-v5W7|^Rzog|V0HEQ~GQ=FBfP!~1fNhE~8P`eDl`ACRZQ z`bj+mqr2&;M>NW#2_%nN?Jl||!$kZ(d7GwL7knIwAp|xBAf`4NVpuJziqyhVtTBpya~k{&KfeX4y(q@lc(qT4KZ z@RCUQCk?_40uT=xRzrB@rHS;CNN^SIY7`dOo-`AH^F~_yq>>zb2M;il0SsM|Jh0%89x93 literal 0 HcmV?d00001 diff --git a/fs/rustezfs/big_files/big_txt.txt b/fs/rustezfs/big_files/big_txt.txt new file mode 100644 index 00000000000000..8d4453a29fef94 --- /dev/null +++ b/fs/rustezfs/big_files/big_txt.txt @@ -0,0 +1,214 @@ +#ifndef __EZFS_H__ +#define __EZFS_H__ + +/* An inode contains metadata about the file it represents. This includes + * permissions, access times, size, etc. All the stuff you can see with the ls + * command is taken right from the inode. + * + * Note that the inode does not contain the file data itself. But it must + * contain information to find the file data. In our case, we store the block + * number where the data is. + */ +struct ezfs_inode { + /* What kind of file this is (i.e. directory, plain old file, etc). */ + mode_t mode; + + uid_t uid; + gid_t gid; + + long i_atime; /* Access time */ + long i_mtime; /* Modified time */ + long i_ctime; /* Change time */ + unsigned int nlink; + + /* The device block where the data starts for this file. */ + uint64_t data_blk_num; + + /* A file can be a directory or a plain file. In the latter case + * we store the file size. Each directory's size is 4096. + */ + uint64_t file_size; + + uint64_t nblocks; /* number of blocks */ +}; + +/* Directories store a mapping from filename -> inode number. Each of these + * mappings is a single "directory entry" and is represented by the struct + * below. + */ +#define EZFS_FILENAME_BUF_SIZE (128 - 8 - 1) +#define EZFS_MAX_FILENAME_LENGTH (EZFS_FILENAME_BUF_SIZE - 1) +struct ezfs_dir_entry { + uint64_t inode_no; + uint8_t active; /* 0 or 1 */ + char filename[EZFS_FILENAME_BUF_SIZE]; +}; + +/* Macros to set, test, and clear a bit array of integers. */ +#define SETBIT(A, k) (A[((k) / 32)] |= (1 << ((k) % 32))) +#define CLEARBIT(A, k) (A[((k) / 32)] &= ~(1 << ((k) % 32))) +#define IS_SET(A, k) (A[((k) / 32)] & (1 << ((k) % 32))) + +/* This macro will declare a bit vector. I use it to declare an array of the + * right size inside the ezfs_sb. + */ +#define DECLARE_BIT_VECTOR(name, size) uint32_t name[(size / 32) + 1]; + +#define EZFS_MAGIC_NUMBER 0x00004118 +#define EZFS_BLOCK_SIZE 4096 + + +/* Inode numbers start from 1. It's because if a function is supposed to + * return an inode number and there's an error, the function returns 0! + */ +#define EZFS_ROOT_INODE_NUMBER 1 + +/* Data block # | Contents + * ------------------------------- + * 0 | Superblock + * 1 | Inode Store + * 2 | Root Data Block + */ +#define EZFS_SUPERBLOCK_DATABLOCK_NUMBER 0 +#define EZFS_INODE_STORE_DATABLOCK_NUMBER 1 +#define EZFS_ROOT_DATABLOCK_NUMBER 2 + +/* The inode store is one 4096 byte-block. The following macro calculates + * how many ezfs_inodes we can shove in the inode store. + */ +#define EZFS_MAX_INODES (EZFS_BLOCK_SIZE / sizeof(struct ezfs_inode)) +#define EZFS_MAX_DATA_BLKS EZFS_MAX_INODES * 256 +#define EZFS_MAX_CHILDREN ((loff_t) (EZFS_BLOCK_SIZE / sizeof(struct ezfs_dir_entry))) + +#define EZFS_SB_MEMBERS uint64_t version;\ + uint64_t magic;\ + uint64_t disk_blks;\ + DECLARE_BIT_VECTOR(free_inodes, EZFS_MAX_INODES);\ + DECLARE_BIT_VECTOR(free_data_blocks, EZFS_MAX_DATA_BLKS);\ + DECLARE_BIT_VECTOR(zero_blocks, EZFS_MAX_DATA_BLKS);\ + struct mutex *ezfs_lock; + +/* This is the superblock, as it will be serialized onto the disk. */ +struct ezfs_super_block { + EZFS_SB_MEMBERS + + /* Padding, so that this structure takes up the entire block. */ + char __padding__[EZFS_BLOCK_SIZE - sizeof(struct {EZFS_SB_MEMBERS})]; +}; + +/* In the VFS superblock, we store pointers to the pages for the inode + * store and superblock so that we can easily read from them and mark them + * as dirty when they're modified. + */ +struct ezfs_sb_pages { + struct page *sb_page; /* Points to the superblock page */ + struct page *istore_page; /* Points to the istore page */ +}; +#endif /* ifndef __EZFS_H__ */ +#ifndef __EZFS_H__ +#define __EZFS_H__ + +/* An inode contains metadata about the file it represents. This includes + * permissions, access times, size, etc. All the stuff you can see with the ls + * command is taken right from the inode. + * + * Note that the inode does not contain the file data itself. But it must + * contain information to find the file data. In our case, we store the block + * number where the data is. + */ +struct ezfs_inode { + /* What kind of file this is (i.e. directory, plain old file, etc). */ + mode_t mode; + + uid_t uid; + gid_t gid; + + long i_atime; /* Access time */ + long i_mtime; /* Modified time */ + long i_ctime; /* Change time */ + unsigned int nlink; + + /* The device block where the data starts for this file. */ + uint64_t data_blk_num; + + /* A file can be a directory or a plain file. In the latter case + * we store the file size. Each directory's size is 4096. + */ + uint64_t file_size; + + uint64_t nblocks; /* number of blocks */ +}; + +/* Directories store a mapping from filename -> inode number. Each of these + * mappings is a single "directory entry" and is represented by the struct + * below. + */ +#define EZFS_FILENAME_BUF_SIZE (128 - 8 - 1) +#define EZFS_MAX_FILENAME_LENGTH (EZFS_FILENAME_BUF_SIZE - 1) +struct ezfs_dir_entry { + uint64_t inode_no; + uint8_t active; /* 0 or 1 */ + char filename[EZFS_FILENAME_BUF_SIZE]; +}; + +/* Macros to set, test, and clear a bit array of integers. */ +#define SETBIT(A, k) (A[((k) / 32)] |= (1 << ((k) % 32))) +#define CLEARBIT(A, k) (A[((k) / 32)] &= ~(1 << ((k) % 32))) +#define IS_SET(A, k) (A[((k) / 32)] & (1 << ((k) % 32))) + +/* This macro will declare a bit vector. I use it to declare an array of the + * right size inside the ezfs_sb. + */ +#define DECLARE_BIT_VECTOR(name, size) uint32_t name[(size / 32) + 1]; + +#define EZFS_MAGIC_NUMBER 0x00004118 +#define EZFS_BLOCK_SIZE 4096 + + +/* Inode numbers start from 1. It's because if a function is supposed to + * return an inode number and there's an error, the function returns 0! + */ +#define EZFS_ROOT_INODE_NUMBER 1 + +/* Data block # | Contents + * ------------------------------- + * 0 | Superblock + * 1 | Inode Store + * 2 | Root Data Block + */ +#define EZFS_SUPERBLOCK_DATABLOCK_NUMBER 0 +#define EZFS_INODE_STORE_DATABLOCK_NUMBER 1 +#define EZFS_ROOT_DATABLOCK_NUMBER 2 + +/* The inode store is one 4096 byte-block. The following macro calculates + * how many ezfs_inodes we can shove in the inode store. + */ +#define EZFS_MAX_INODES (EZFS_BLOCK_SIZE / sizeof(struct ezfs_inode)) +#define EZFS_MAX_DATA_BLKS EZFS_MAX_INODES * 256 +#define EZFS_MAX_CHILDREN ((loff_t) (EZFS_BLOCK_SIZE / sizeof(struct ezfs_dir_entry))) + +#define EZFS_SB_MEMBERS uint64_t version;\ + uint64_t magic;\ + uint64_t disk_blks;\ + DECLARE_BIT_VECTOR(free_inodes, EZFS_MAX_INODES);\ + DECLARE_BIT_VECTOR(free_data_blocks, EZFS_MAX_DATA_BLKS);\ + DECLARE_BIT_VECTOR(zero_blocks, EZFS_MAX_DATA_BLKS);\ + struct mutex *ezfs_lock; + +/* This is the superblock, as it will be serialized onto the disk. */ +struct ezfs_super_block { + EZFS_SB_MEMBERS + + /* Padding, so that this structure takes up the entire block. */ + char __padding__[EZFS_BLOCK_SIZE - sizeof(struct {EZFS_SB_MEMBERS})]; +}; + +/* In the VFS superblock, we store pointers to the pages for the inode + * store and superblock so that we can easily read from them and mark them + * as dirty when they're modified. + */ +struct ezfs_sb_pages { + struct page *sb_page; /* Points to the superblock page */ + struct page *istore_page; /* Points to the istore page */ +}; +#endif /* ifndef __EZFS_H__ */ \ No newline at end of file diff --git a/fs/rustezfs/format_disk_as_ezfs b/fs/rustezfs/format_disk_as_ezfs new file mode 100755 index 0000000000000000000000000000000000000000..14f0c8605fc7df0cdb14c771f9bf21ec01cfe196 GIT binary patch literal 67568 zcmeI1e{fXSb;r-{iXa;qgu#&w1RjDUn4sl{6%2M-uOzS_1{-6XbX<3KSK23O&1zTP zU12bGvcaB?CrPK;LTo4FxEiL@!A!?PGHweQk1c2>b)3|pa_w;wgI99gp>-0g6Fc>` zi0${>ckgnw>>{RrblREon78MhbI*@^Kli@-9#3E0yzO?s&qwA6(BBekp;?|Kq#M>) zJ|WsbS5t@<(gOMf+Usx{ze>5rk479u)_W=iAUW=kZm*OJwV#ouhb(94wrb)T$Fmwq zYBb(2_mw8ScAC@~wQS@L;kaH)6UW`-xJDhZphb3ofG<#M#~VI=$V z!IIAg2R}F}<&bA4BTd|n_p&j*etNOzP$_rmI3rEm-H20Mbo+FoQ9JC^^=k1{6U@Gv zrp3iEzxMY zyKjAKFp~DFqnSvreIvxRm%37G4f|a+?98@Wo?pW5 z;H*5NFf>;hp>k)h-HBB9?r^W0&Bps( z3Wqb
{W-Qk{SJVEZ>c$R$=Zj#b&G)AcbTt%~~IDE18yE!184fjXmNm#n~M#DYv zWHb?f*rlG#zGOG`yZsqA%XKm?4W#4AY!5w@j%QtpcBRr;N@QGj_mslDgVA)1I62=) z>#6$f)wykJdq;R(aP7@xE^lh3@YY@1!!bAQ_Qo?=H@$0nM%`ta{KB=0*8&ZqKE;+CqT*Ko}T=XoB|>`O1G z_5l5}wt4>kvcK8)19}6DG;kK8dcB_;dxN%5lz3%f8`J(T^1{JUkGgyqyU|Z;e;@p3 zDi81HEz5465!_O+?Dlm}A7U-(ZZ8w=E02F}eTc z=OzP`AHZwVED5V%F>^OK5prUq5FSN8C3BB3Uk3w&^^yi^>S^D>(AF%YlfqvN1e*pcIrN0Dy z+|o}$_y7LI`ago+Z0WB;Z@2WMo(h-;`na|=W`>F`=j^7u-|yL?ti$emG`AD`_lfd#J+9&B z^(VKp1Ab$3LPgcyh&mk8sPzV|H)y?{irh!jm+>a}qCf5Ad!PFg!dN72-Cxw(2tRwgW> zt;utoXJM#_etfSm^UoL1BD!`wKr6Y9&smi(1pF(vV=U#`xm7BE)!Kzs`D3~^IzAsP z6=Od=UarmKL#(R(V|87lcBnJ{%GM(F@MXR7%dz`Y*X$;;VCMX=Ftf}Gv*iO zg--Y$p}Bm2ImdDf=#d%o-o+RqkAx25MJZ1oe&zMC$LjJrZs8zksY9+pw;M`>gohW!Fs zxM!Io`7n=F=IuYZFJ_HYo41@->r1*;f3;ei8*2o6hN>0f+Er@3GhHoOqsDbBYVdvM zd-ZFhy!U<2iYo-1qlD+Swf_wHB3@hz_p#fb-=k$U{)1 zDuBsnsW|pou-4BeelD55|FOoia3 zs%6{x`G9%ZeI>PWUacR&m!F~BCkO9d<$6`daPO7mrJK|kj-XUG*OtpGWtE%^TtKM*pdW)v37vWs~m3wualhx`Kym~iS z^+sycqv`57pI7znhaa83{2Kf9c`(PGaoIIC?B(0Sb+P9i;h1V`3~m34wpwd!^h#s8-dQ0q$9*o#+^ci79@guG+CkLq_M`+hrW=Ydbv`z>^{>fa32zaie!ro9Ia*?DW- z$0J_e58yk-d#`?vvioi-jbgTE8-|0%rx+j-v)>~9DB{frOit~(r-x3_KG z#_|t8o%ti@)0wOJnvX4RB9U?)N~IIArEJ{X-ye1EjJtieI`_pNh)0voeSOhn@2$?3 zXnJsW-04guqj5Oin~CZJoJ*jkmG#ie^GrPmlOxS(6C*y3|{H3iOo5OduZQtx{ z+Ir6&;r4BJ+!IvwwkG%BgJ-PLOq=;btHU2mxzGUHUlr}WIrW1FTTtIn&OM=t`y%NoSgG&FTQmY?Q* zdtxxt=RCx#KEo5t_dPdlQg^GPwijU~7#Ay+^y|DaUb0?9|CC&>5k zPO96x*tf7@iLzY}dn@X+a(mm%#q75VXAZVCY{S8}5YA^{`vN2%%W-l)e+b(SHng?0 z&33+9_iUj3p#RRZXI`HT3(WIzK7w-se)jkCMX>Q$3b4l@Nk@PA>>2f0o7-Q&xg2AA z#cL0>eb@i2FLmZDJ8=6y;ruDuS9tBJ`W79}{rix8(7vhx7j3f}IlN=`vBQDDjKJ*1 zHtp&C-I>S8sQ7QQeDL2A%-=Ei?*|c_Us-VB)!R4SMf;nx`v%)Mv}p5NNwI<)a0c(G2pvx8|4iKhG4w>I-1 z66FvALO=)z0U;m+gn$qb0zyCt2mv7=1cZPP5CTF#2nYcoAOwVf5D)@FKnMr{As_^V zfDjM@LO=)z0U;m+gn$qb0zyCt2mv7=1cZPP5CTF#2nYcoAOwVf5D)@FKnMr{As_^V zfDjM@LO=)z0U;m+gn$qb0zyCt2mv7=1cZPP5CTF#2nYcoAOwVf5D)@FKnMr{As_^V zfDjM@LO=)z0U;m+gn$qb0zyCt2mv7=1cZPP5CTF#2nYcoAOwVf5D)@FKnMr{As_^V zfDjM@LO=)z0U;m+gn$qb0zyCt2mv7=1cZPP5CTF#2nYcoAOwVf5D)@FKnMr{As_^V zfDjM@LO=)z0U;m+gn$qb0zyCt2mv7=1cZPP5CTF#2nYcoAOwVf5D)@FKnMr{As_^V zfDjM@LO=)z0U;m+gn$qb0zyCt2mv7=1cZPP5CTF#2nYcoAOwVf5D)_Y&j>^sybd>L z>C^pxUQ44N*SdD2BUgEbYqb5`4c>(oM3Y|RLfu}k z9?}<|(E4fJezn$b)E%9r_3O2~PD>*K`l7Mq1?V(X(DCzi`%EpHw0uPyjD13P#Ek1L z?WeJjslQm;jo*Kjyz!x&GF{O6u+CS~y6M-1)*sOAMXlHAy#HI`v>w?1RoST5({wyu zGz+%Ev7S8QogE#wI4kb$8cb#fowcpOb-^_)Yc~!mecg@PLKMvOWwPmPw2OktRMrjl zCI^FEgYiVHB_5+-JehUV1Ej2d(M%r&WBZbsef^%yroEOuZaNcBC8sE1w58odlmqnD zKqAW-w4M3 z(R4bx&&y`6Q8d~g??#VOsN?1D%48_mo$Bv*li3Pp{}Yw(PrirD`X101MlP>NTDi{o ze&Soz#2?ZZMwYDr3Bv^wB9)pQLtuKrm&^m8d zyw{j`vmb2Gb`x**H6zVF1~+w7_CEwG?-3^6>|v2q}c~eeG_lS-=pK(bwabR8fo@nj{hXi%J>1;n2FvF%g-V6 zJTmhK7j>9^7=1S`?D)$4EK&iy(FAI_ry@S2A2>!HnLRZiG*zWXD&oy^(@4X~gjM$c zfQ~o($vjZC{8mMP;b-!Fy(0c;{eUuZmvPjxA{{+l5kH~hja*d0ud@DO#M}3OgX0x4 zQmdX3zm@fm!Dh#=(g8;D`mm46_?OVgQ)J!)%zFw=dQp}AHM)_n!flQfU$37#^;a1G zCSrN*n)>Fs)u`jmjb+|@OkJ}M-$5)RF30Qln8p%}I3_$%{x$JN{t_*A{KY%jn>bU) zBrtJC|2JH)tz2JsxKU-jc)uF|ise8bpn+{`jDwaYp7&?_F!8oDwQaxky8g$u5!WWp GnExB*%t~Sa literal 0 HcmV?d00001 From 1670ed83385f79c2d21abde9c1499ed61d2b597c Mon Sep 17 00:00:00 2001 From: lsig Date: Tue, 25 Nov 2025 18:49:58 -0500 Subject: [PATCH 022/131] [ezfs] add lookup --- fs/rustezfs/dir.rs | 42 +++++++- fs/rustezfs/ezfs.rs | 102 ++++++++++++++----- fs/rustezfs/inode.rs | 51 +++++++++- fs/rustezfs/sb.rs | 22 ++-- rust/helpers/fs.c | 11 ++ rust/kernel/dentry.rs | 54 +++++++++- rust/kernel/fs.rs | 27 +++++ rust/kernel/fs/file.rs | 8 +- rust/kernel/inode.rs | 164 +++++++++++++++++++++++++++++- rust/kernel/types.rs | 95 +++++++++++++++++ scripts/generate_rust_analyzer.py | 2 +- 11 files changed, 528 insertions(+), 50 deletions(-) diff --git a/fs/rustezfs/dir.rs b/fs/rustezfs/dir.rs index 82f057ea26d29f..ae31a23a624e04 100644 --- a/fs/rustezfs/dir.rs +++ b/fs/rustezfs/dir.rs @@ -1,8 +1,46 @@ -use crate::defs::EZFS_FILENAME_BUF_SIZE; +use crate::defs::{EZFS_FILENAME_BUF_SIZE, EZFS_MAX_CHILDREN}; +use core::ops::Deref; +use kernel::transmute::FromBytes; #[repr(C)] pub(crate) struct EzfsDirEntry { inode_no: u64, active: u8, - filename: [char; EZFS_FILENAME_BUF_SIZE], + filename: [u8; EZFS_FILENAME_BUF_SIZE], } + +impl EzfsDirEntry { + pub(crate) fn inode_no(&self) -> u64 { + self.inode_no + } + + pub(crate) fn is_active(&self) -> bool { + self.active != 0 + } + + pub(crate) fn filename(&self) -> &[u8] { + let len = self + .filename + .iter() + .position(|&b| b == 0) + .unwrap_or(self.filename.len()); + + &self.filename[..len] + } +} + +#[repr(C)] +pub(crate) struct DirEntryStore { + dir_entries: [EzfsDirEntry; EZFS_MAX_CHILDREN], +} + +impl Deref for DirEntryStore { + type Target = [EzfsDirEntry]; + + fn deref(&self) -> &Self::Target { + &self.dir_entries + } +} + +// TODO: Add Safety +unsafe impl FromBytes for DirEntryStore {} diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index bafa1d21ccd925..390198e3f12f24 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -6,7 +6,8 @@ mod defs; mod dir; mod inode; mod sb; -use crate::inode::InodeStore; +use crate::dir::DirEntryStore; +use crate::inode::{EzfsInode, InodeStore}; use crate::sb::{EzfsSuperblock, EzfsSuperblockDisk}; use defs::*; use kernel::dentry; @@ -16,7 +17,7 @@ use kernel::prelude::*; use kernel::sb::{New, SuperBlock, Type as SuperType}; use kernel::time::UNIX_EPOCH; use kernel::transmute::FromBytes; -use kernel::types::ARef; +use kernel::types::{ARef, Locked}; use kernel::{c_str, fs, str::CStr}; use core::marker::{PhantomData, Send, Sync}; @@ -48,25 +49,53 @@ impl RustEzFs { INodeState::Uninitilized(new_inode) => new_inode, }; + let h = &*sb.data(); + let inode_store = { + let offset = EZFS_INODE_STORE_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE; + let mapped_inode_store = h.mapper.mapped_folio(offset.try_into()?)?; + InodeStore::from_bytes_copy(&mapped_inode_store[..size_of::()]) + .ok_or(EIO)? + }; + + let ezfs_inode = inode_store[ino]; + let mode = ezfs_inode.mode(); + + const DIR_IOPS: kernel::inode::Ops = kernel::inode::Ops::new::(); + + let typ = match mode & fs::mode::S_IFMT { + fs::mode::S_IFREG => { + // inode + // .set_fops(file::Ops::generic_ro_file()) + // .set_aops(FILE_AOPS); + Type::Reg + } + fs::mode::S_IFDIR => { + inode.set_iops(DIR_IOPS); + // inode.set_iops(DIR_IOPS).set_fops(DIR_FOPS); + Type::Dir + } + _ => return Err(ENOENT), + }; + inode.init(Params { - typ: Type::Dir, - mode: 0o755, - size: 0, - blocks: 0, - nlink: 2, - uid: 0, - gid: 0, - ctime: UNIX_EPOCH, - mtime: UNIX_EPOCH, - atime: UNIX_EPOCH, - value: (), + typ, + mode: ezfs_inode.mode().try_into()?, + size: ezfs_inode.file_size().try_into()?, + blocks: ezfs_inode.nblocks(), + nlink: ezfs_inode.nlink(), + uid: ezfs_inode.uid(), + gid: ezfs_inode.gid(), + ctime: ezfs_inode.ctime()?, + mtime: ezfs_inode.mtime()?, + atime: ezfs_inode.atime()?, + value: ezfs_inode, }) } } impl FileSystem for RustEzFs { type Data = Pin>; - type INodeData = (); + type INodeData = EzfsInode; const NAME: &'static CStr = c_str!("rustezfs"); const SUPER_TYPE: SuperType = SuperType::BlockDev; @@ -88,17 +117,7 @@ impl FileSystem for RustEzFs { return Err(EINVAL); } - let inode_store = { - let offset = EZFS_INODE_STORE_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE; - let mapped_inode_store = mapper.mapped_folio(offset.try_into()?)?; - InodeStore::from_bytes_copy(&mapped_inode_store[..size_of::()]) - .ok_or(EIO)? - }; - - let ezfs_sb = KBox::pin_init( - EzfsSuperblock::new(disk_sb, inode_store, mapper), - GFP_KERNEL, - )?; + let ezfs_sb = KBox::pin_init(EzfsSuperblock::new(disk_sb, mapper), GFP_KERNEL)?; sb.set_magic(EZFS_MAGIC_NUMBER); @@ -111,6 +130,39 @@ impl FileSystem for RustEzFs { } } +#[vtable] +impl kernel::inode::Operations for RustEzFs { + type FileSystem = Self; + + fn lookup( + parent: &Locked<&INode, kernel::inode::ReadSem>, + dentry: dentry::Unhashed<'_, Self::FileSystem>, + ) -> Result>>> { + let sb = &*parent.super_block(); + let h = sb.data(); + let name = dentry.name(); + let ezfs_dir_inode = parent.data(); + + let dir_entries = { + let offset = ezfs_dir_inode.data_blk_num() * EZFS_BLOCK_SIZE as u64; + let mapped = h.mapper.mapped_folio(offset.try_into()?)?; + DirEntryStore::from_bytes_copy(&mapped[..size_of::()]).ok_or(EIO)? + }; + + let dir_entry = dir_entries + .iter() + .find(|x| x.filename() == name && x.is_active()); + + let inode = if let Some(entry) = dir_entry { + Some(Self::iget(sb, entry.inode_no().try_into()?)?) + } else { + None + }; + + dentry.splice_alias(inode) + } +} + type FsModule = RustEzFsModule; module! { diff --git a/fs/rustezfs/inode.rs b/fs/rustezfs/inode.rs index 598a161f1978d3..642448e1a72922 100644 --- a/fs/rustezfs/inode.rs +++ b/fs/rustezfs/inode.rs @@ -1,22 +1,67 @@ use crate::defs::*; use core::ops::Deref; +use kernel::error::Result; +use kernel::time::Timespec; use kernel::transmute::FromBytes; use kernel::uapi::{gid_t, mode_t, uid_t}; #[repr(C)] +#[derive(Copy, Clone)] pub(crate) struct EzfsInode { mode: mode_t, uid: uid_t, gid: gid_t, - i_attime: i64, /* access time */ - i_mtime: i64, /* modified time */ - i_ctime: i64, /* change time */ + i_atime: i64, /* access time */ + i_mtime: i64, /* modified time */ + i_ctime: i64, /* change time */ nlink: u32, data_blk_num: u64, file_size: u64, nblocks: u64, } +impl EzfsInode { + pub(crate) fn mode(&self) -> mode_t { + self.mode + } + + pub(crate) fn uid(&self) -> uid_t { + self.uid + } + + pub(crate) fn gid(&self) -> gid_t { + self.gid + } + + pub(crate) fn atime(&self) -> Result { + Timespec::new(self.i_atime.try_into()?, 0) + } + + pub(crate) fn mtime(&self) -> Result { + Timespec::new(self.i_mtime.try_into()?, 0) + } + + pub(crate) fn ctime(&self) -> Result { + Timespec::new(self.i_ctime.try_into()?, 0) + } + + pub(crate) fn nlink(&self) -> u32 { + self.nlink + } + + pub(crate) fn data_blk_num(&self) -> u64 { + self.data_blk_num + } + + pub(crate) fn file_size(&self) -> u64 { + self.file_size + } + + pub(crate) fn nblocks(&self) -> u64 { + self.nblocks + } +} + #[repr(C)] pub(crate) struct InodeStore { inodes: [EzfsInode; EZFS_MAX_INODES], diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index 8ad7b841a507cc..8eea85de484ea3 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -38,24 +38,21 @@ unsafe impl FromBytes for EzfsSuperblockDisk {} #[pin_data] pub(crate) struct EzfsSuperblock { - version: u64, - magic: u64, - disk_blocks: u64, + pub(crate) version: u64, + pub(crate) magic: u64, + pub(crate) disk_blocks: u64, #[pin] - free_inodes: Mutex<[u32; (EZFS_MAX_INODES / 32) + 1]>, + pub(crate) free_inodes: Mutex<[u32; (EZFS_MAX_INODES / 32) + 1]>, #[pin] - free_data_blocks: Mutex<[u32; (EZFS_MAX_DATA_BLKS / 32) + 1]>, + pub(crate) free_data_blocks: Mutex<[u32; (EZFS_MAX_DATA_BLKS / 32) + 1]>, #[pin] - zero_data_blocks: Mutex<[u8; (EZFS_MAX_DATA_BLKS / 32) + 1]>, - mapper: inode::Mapper, - // TODO: Add mutex around inode store - inode_store: InodeStore, + pub(crate) zero_data_blocks: Mutex<[u8; (EZFS_MAX_DATA_BLKS / 32) + 1]>, + pub(crate) mapper: inode::Mapper, } impl EzfsSuperblock { - pub fn new( + pub(crate) fn new( disk_sb: EzfsSuperblockDisk, - inode_store: InodeStore, mapper: inode::Mapper, ) -> impl PinInit { pin_init!(Self { @@ -66,11 +63,10 @@ impl EzfsSuperblock { free_data_blocks <- new_mutex!(disk_sb.data.free_data_blocks), zero_data_blocks <- new_mutex!(disk_sb.data.zero_data_blocks), mapper, - inode_store, }) } - pub fn magic(&self) -> u64 { + pub(crate) fn magic(&self) -> u64 { self.magic } } diff --git a/rust/helpers/fs.c b/rust/helpers/fs.c index 1dec5a12959e32..0b8776aad1e616 100644 --- a/rust/helpers/fs.c +++ b/rust/helpers/fs.c @@ -20,3 +20,14 @@ void rust_helper_i_gid_write(struct inode *inode, gid_t gid) { i_gid_write(inode, gid); } + + +void rust_helper_inode_lock_shared(struct inode *inode) +{ + inode_lock_shared(inode); +} + +void rust_helper_inode_unlock_shared(struct inode *inode) +{ + inode_unlock_shared(inode); +} diff --git a/rust/kernel/dentry.rs b/rust/kernel/dentry.rs index 14941f56b5e97f..4ac78913e3f16a 100644 --- a/rust/kernel/dentry.rs +++ b/rust/kernel/dentry.rs @@ -2,7 +2,7 @@ use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr}; use crate::{ bindings, - error::Result, + error::{from_err_ptr, Result}, fs::FileSystem, inode::INode, prelude::*, @@ -45,6 +45,58 @@ impl DEntry { } } +pub struct Unhashed<'a, T: FileSystem + ?Sized>(pub(crate) &'a DEntry); + +impl Unhashed<'_, T> { + /// Splices a disconnected dentry into the tree if one exists. + pub fn splice_alias(self, inode: Option>>) -> Result>>> { + let inode_ptr = if let Some(i) = inode { + // Reject inode if it belongs to a different superblock. + if !ptr::eq(i.super_block(), self.0.super_block()) { + return Err(EINVAL); + } + + ManuallyDrop::new(i).0.get() + } else { + ptr::null_mut() + }; + + // SAFETY: Both inode and dentry are known to be valid. + let ptr = from_err_ptr(unsafe { bindings::d_splice_alias(inode_ptr, self.0 .0.get()) })?; + + // SAFETY: The C API guarantees that if a dentry is returned, the refcount has been + // incremented. + Ok(ptr::NonNull::new(ptr).map(|v| unsafe { ARef::from_raw(v.cast::>()) })) + } + + /// Returns the name of the dentry. + /// + /// Being unhashed guarantees that the name won't change. + pub fn name(&self) -> &[u8] { + // SAFETY: The name is immutable, so it is ok to read it. + let name = unsafe { &*ptr::addr_of!((*self.0 .0.get()).__bindgen_anon_1.d_name) }; + + // This ensures that a `u32` is representable in `usize`. If it isn't, we'll get a build + // break. + const _: usize = 0xffffffff; + + // SAFETY: The union is just allow an easy way to get the `hash` and `len` at once. `len` + // is always valid. + let len = unsafe { name.__bindgen_anon_1.__bindgen_anon_1.len } as usize; + + // SAFETY: The name is immutable, so it is ok to read it. + unsafe { core::slice::from_raw_parts(name.name, len) } + } +} + +impl Deref for Unhashed<'_, T> { + type Target = DEntry; + + fn deref(&self) -> &Self::Target { + self.0 + } +} + pub struct Root(ARef>); impl Root { diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs index cbe892708e9ff5..100683adcd2cf7 100644 --- a/rust/kernel/fs.rs +++ b/rust/kernel/fs.rs @@ -40,6 +40,33 @@ pub type Offset = i64; /// This is C's `pgoff_t`. pub type PageOffset = usize; +/// Contains constants related to Linux file modes. +pub mod mode { + /// A bitmask used to the file type from a mode value. + pub const S_IFMT: u32 = bindings::S_IFMT; + + /// File type constant for block devices. + pub const S_IFBLK: u32 = bindings::S_IFBLK; + + /// File type constant for char devices. + pub const S_IFCHR: u32 = bindings::S_IFCHR; + + /// File type constant for directories. + pub const S_IFDIR: u32 = bindings::S_IFDIR; + + /// File type constant for pipes. + pub const S_IFIFO: u32 = bindings::S_IFIFO; + + /// File type constant for symbolic links. + pub const S_IFLNK: u32 = bindings::S_IFLNK; + + /// File type constant for regular files. + pub const S_IFREG: u32 = bindings::S_IFREG; + + /// File type constant for sockets. + pub const S_IFSOCK: u32 = bindings::S_IFSOCK; +} + /// A file system type. pub trait FileSystem { /// Data associated with each file system instance (super-block). diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index cf06e73a6da041..a3864cbd66c881 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -10,12 +10,14 @@ use crate::{ bindings, cred::Credential, - error::{code::*, to_result, Error, Result}, + error::{code::*, from_result, to_result, Error, Result}, fmt, + fs::{FileSystem, Offset}, + inode::{self, INode}, sync::aref::{ARef, AlwaysRefCounted}, - types::{NotThreadSafe, Opaque}, + types::{Locked, NotThreadSafe, Opaque}, }; -use core::ptr; +use core::{marker::PhantomData, mem::ManuallyDrop, ptr}; /// Flags associated with a [`File`]. pub mod flags { diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index c5317483143728..0abecb44f6e386 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -1,13 +1,17 @@ use core::marker::PhantomData; use core::mem::{ManuallyDrop, MaybeUninit}; +use macros::vtable; + +use crate::dentry::{self, DEntry}; use crate::error::{from_err_ptr, Result}; use crate::folio::{self, Folio}; use crate::fs::PageOffset; -use crate::prelude::{EIO, ERANGE}; +use crate::prelude::{EIO, ENOTSUPP, ERANGE}; +use crate::sb::SuperBlock; use crate::str::CString; use crate::time::Timespec; -use crate::types::AlwaysRefCounted; +use crate::types::{AlwaysRefCounted, Lockable, Locked}; use crate::{block, container_of}; use crate::{ fs::{FileSystem, Offset}, @@ -23,6 +27,21 @@ pub enum INodeState { Uninitilized(New), } +/// Operations implemented by inodes. +#[vtable] +pub trait Operations { + /// File system that these operations are compatible with. + type FileSystem: FileSystem + ?Sized; + + /// Returns the inode corresponding to the directory entry with the given name + fn lookup( + _parent: &Locked<&INode, ReadSem>, + _dentry: dentry::Unhashed<'_, Self::FileSystem>, + ) -> Result>>> { + Err(ENOTSUPP) + } +} + /// A node (inode) in the file index. /// /// Wraps the kernel's `struct inode`. @@ -49,6 +68,34 @@ impl INode { unsafe { &*ptr.cast::() } } + /// Returns the number of the inode. + pub fn ino(&self) -> Ino { + // SAFETY: `i_ino` is immutable, and `self` is guaranteed to be valid by the existence of a + // shared reference (&self) to it. + unsafe { (*self.0.get()).i_ino } + } + + /// Returns the super-block that owns the inode. + pub fn super_block(&self) -> &SuperBlock { + // SAFETY: `i_sb` is immutable, and `self` is guaranteed to be valid by the existence of a + // shared reference (&self) to it. + unsafe { SuperBlock::from_raw((*self.0.get()).i_sb) } + } + + /// Returns the data associated with the inode. + pub fn data(&self) -> &T::INodeData { + // TODO: add UnspecifiedFS + // if T::IS_UNSPECIFIED { + // crate::build_error!("inode data type is unspecified"); + // } + // TODO: Add safety + let outerp = unsafe { container_of!(self.0.get(), WithData, inode) }; + // SAFETY: `self` is guaranteed to be valid by the existence of a shared reference + // (`&self`) to it. Additionally, we know `T::INodeData` is always initialised in an + // `INode`. + unsafe { &*(*outerp).data.as_ptr() } + } + /// Returns a mapper for this inode. /// /// # Safety @@ -116,6 +163,22 @@ unsafe impl AlwaysRefCounted for INode { } } +/// Indicates that the an inode's rw semapahore is locked in read (shared) mode. +pub struct ReadSem; + +unsafe impl Lockable for INode { + fn raw_lock(&self) { + // SAFETY: Since there's a reference to the inode, it must be valid. + unsafe { bindings::inode_lock_shared(self.0.get()) } + } + + unsafe fn unlock(&self) { + // SAFETY: Since there's a reference to the inode, it must be valid. Additionally, the + // safety requirements of this functino require that the inode be locked in read mode. + unsafe { bindings::inode_unlock_shared(self.0.get()) } + } +} + /// Allows mapping the contents of the inode. /// /// # Invariants @@ -259,6 +322,13 @@ impl New { // being called with the `ManuallyDrop` instance created above. Ok(unsafe { ARef::from_raw(manual.0.cast::>()) }) } + + pub fn set_iops(&mut self, iops: Ops) -> &mut Self { + let inode = unsafe { self.0.as_mut() }; + inode.i_op = iops.0; + + self + } } impl Drop for New { @@ -335,3 +405,93 @@ pub struct Params { /// Value to attach to this node. pub value: T, } + +/// Represents inode operations. +pub struct Ops(*const bindings::inode_operations, PhantomData); + +impl Ops { + /// Returns inode operations for symbolic links that are stored in a single page. + pub fn page_symlink_inode() -> Self { + // SAFETY: This is a constant in C, it never changes. + Self( + unsafe { &bindings::page_symlink_inode_operations }, + PhantomData, + ) + } + + /// Returns inode operations for symbolic links that are stored in the `i_lnk` field. + pub fn simple_symlink_inode() -> Self { + // SAFETY: This is a constant in C, it never changes. + Self( + unsafe { &bindings::simple_symlink_inode_operations }, + PhantomData, + ) + } + + /// Creates the inode operations from a type that implements the [`Operations`] trait. + pub const fn new + ?Sized>() -> Self { + struct Table(PhantomData); + impl Table { + const TABLE: bindings::inode_operations = bindings::inode_operations { + lookup: if T::HAS_LOOKUP { + Some(Self::lookup_callback) + } else { + None + }, + get_link: None, + // get_link: if T::HAS_GET_LINK { + // Some(Self::get_link_callback) + // } else { + // None + // }, + permission: None, + get_inode_acl: None, + readlink: None, + create: None, + link: None, + unlink: None, + symlink: None, + mkdir: None, + rmdir: None, + mknod: None, + rename: None, + setattr: None, + getattr: None, + listxattr: None, + fiemap: None, + update_time: None, + atomic_open: None, + tmpfile: None, + get_acl: None, + set_acl: None, + fileattr_set: None, + fileattr_get: None, + get_offset_ctx: None, + }; + + extern "C" fn lookup_callback( + parent_ptr: *mut bindings::inode, + dentry_ptr: *mut bindings::dentry, + _flags: u32, + ) -> *mut bindings::dentry { + // SAFETY: The C API guarantees that `parent_ptr` is a valid inode. + let parent = unsafe { INode::from_raw(parent_ptr) }; + + // SAFETY: The C API guarantees that `dentry_ptr` is a valid dentry. + let dentry = unsafe { DEntry::from_raw(dentry_ptr) }; + + // SAFETY: The C API guarantees that the inode's rw semaphore is locked at least in + // read mode. It does not expect callees to unlock it, so we make the locked object + // manually dropped to avoid unlocking it. + let locked = ManuallyDrop::new(unsafe { Locked::new(parent) }); + + match T::lookup(&locked, dentry::Unhashed(dentry)) { + Err(e) => e.to_ptr(), + Ok(None) => ptr::null_mut(), + Ok(Some(ret)) => ManuallyDrop::new(ret).0.get(), + } + } + } + Self(&Table::::TABLE, PhantomData) + } +} diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index dc0a02f5c3cfc5..85845eb7d92ab0 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -443,3 +443,98 @@ pub type NotThreadSafe = PhantomData<*mut ()>; /// [`NotThreadSafe`]: type@NotThreadSafe #[allow(non_upper_case_globals)] pub const NotThreadSafe: NotThreadSafe = PhantomData; + +/// A lockable object +/// +/// Implementers must implement [`Lockable::raw_lock`] and [`Lockable::unlock`], and they'll get a +/// `lock` method that returns a guard that can be used to access the locked object and unlocks it +/// automatically when it goes out of scope. +/// +/// `M` is tag that may be used to specify which mode to lock/unlock when an object may be locked +/// may be locked in multiple ways. For example, inodes have `i_lock` and `i_rwsem` so they can be +/// locked in 3 different modes. If an implementer can be locked in only one way, the default unit +/// type can be omitted for brevity. +/// +/// # Safety +/// +/// The [`Lockable::raw_lock`] function must lock the object, otherwise we run into UB if multiple +/// instances believe they have serialised access. +pub unsafe trait Lockable { + /// Locks the object + /// + /// The returned guard will automatically unlock when it goes out of scope. + fn lock(&self) -> Locked<&Self, M> { + self.raw_lock(); + + // SAFETY: the object was locked above, so responsibility to unlock is transferred to the + // `Locked` instance. + unsafe { Locked::new(self) } + } + + /// Locks the object + fn raw_lock(&self); + + /// Unlocks the object + /// + /// # Safety + /// + /// This object must be locked and it must not be used as a `Locked` object before another call + /// to [`Self::raw_lock`]. + unsafe fn unlock(&self); +} + +/// A locked version of an existing type +/// +/// # Invariants +/// +/// The object is locked and the responsibility to unlock belongs to the [`Locked`] instance. +#[repr(transparent)] +pub struct Locked(T, PhantomData) +where + T::Target: Lockable; + +impl Locked +where + T::Target: Lockable, +{ + /// Creates a new instance of [`Locked`]. + /// + /// # Safety + /// + /// The instance `T` must be locked and the responsibility to unlock is transferred to the + /// returned instance of [`Locked`]. + pub unsafe fn new(v: T) -> Self { + Self(v, PhantomData) + } +} + +impl Deref for Locked +where + T::Target: Lockable, +{ + type Target = T::Target; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Drop for Locked +where + T::Target: Lockable, +{ + fn drop(&mut self) { + // SAFETY: The type invariants guarantee that the object is locked + unsafe { self.0.unlock() } + } +} + +impl + AlwaysRefCounted, M> From> for Locked, M> { + fn from(value: Locked<&T, M>) -> Self { + let aref = ARef::::from(value.deref()); + core::mem::forget(value); + + // SAFETY: We forgot the locked value above, so responsibility is transferred to the new + // instance of [`Locked`]. + unsafe { Locked::new(aref) } + } +} diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py index fc27f0cca752d3..3ccf27e8180115 100755 --- a/scripts/generate_rust_analyzer.py +++ b/scripts/generate_rust_analyzer.py @@ -152,7 +152,7 @@ def is_root_crate(build_file, target): # Then, the rest outside of `rust/`. # # We explicitly mention the top-level folders we want to cover. - extra_dirs = map(lambda dir: srctree / dir, ("samples", "drivers")) + extra_dirs = map(lambda dir: srctree / dir, ("samples", "drivers", "fs")) if external_src is not None: extra_dirs = [external_src] for folder in extra_dirs: From 43048acf77bf0ba24f4acc563ea8ee113aba2f87 Mon Sep 17 00:00:00 2001 From: lsig Date: Tue, 25 Nov 2025 19:38:21 -0500 Subject: [PATCH 023/131] [ezfs] add lookup for ezfs --- fs/rustezfs/ezfs.rs | 47 +++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 390198e3f12f24..cc1d83a07c78f1 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -50,14 +50,13 @@ impl RustEzFs { }; let h = &*sb.data(); - let inode_store = { - let offset = EZFS_INODE_STORE_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE; - let mapped_inode_store = h.mapper.mapped_folio(offset.try_into()?)?; - InodeStore::from_bytes_copy(&mapped_inode_store[..size_of::()]) - .ok_or(EIO)? - }; - let ezfs_inode = inode_store[ino]; + let offset = EZFS_INODE_STORE_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE; + let mapped_inode_store = h.mapper.mapped_folio(offset.try_into()?)?; + let inode_store = + InodeStore::from_bytes(&mapped_inode_store[..size_of::()]).ok_or(EIO)?; + + let ezfs_inode = inode_store[ino - 1]; let mode = ezfs_inode.mode(); const DIR_IOPS: kernel::inode::Ops = kernel::inode::Ops::new::(); @@ -142,16 +141,30 @@ impl kernel::inode::Operations for RustEzFs { let h = sb.data(); let name = dentry.name(); let ezfs_dir_inode = parent.data(); - - let dir_entries = { - let offset = ezfs_dir_inode.data_blk_num() * EZFS_BLOCK_SIZE as u64; - let mapped = h.mapper.mapped_folio(offset.try_into()?)?; - DirEntryStore::from_bytes_copy(&mapped[..size_of::()]).ok_or(EIO)? - }; - - let dir_entry = dir_entries - .iter() - .find(|x| x.filename() == name && x.is_active()); + pr_info!("data_blk_num: {:?}", ezfs_dir_inode.data_blk_num()); + + let offset = ezfs_dir_inode + .data_blk_num() + .checked_mul(EZFS_BLOCK_SIZE as u64) + .ok_or(EIO)?; + let mapped = h.mapper.mapped_folio(offset.try_into()?)?; + let dir_entries = + DirEntryStore::from_bytes(&mapped[..size_of::()]).ok_or(EIO)?; + + let dir_entry = dir_entries.iter().find(|x| { + pr_info!( + "filename: {:?} = {}\n", + x.filename(), + core::str::from_utf8(x.filename()).unwrap_or("") + ); + + pr_info!( + "dname: {:?} = {}\n", + name, + core::str::from_utf8(name).unwrap_or("") + ); + x.filename() == name && x.is_active() + }); let inode = if let Some(entry) = dir_entry { Some(Self::iget(sb, entry.inode_no().try_into()?)?) From 58e06411ae6f635db3806c6e758b82726230d90d Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 26 Nov 2025 14:43:38 -0500 Subject: [PATCH 024/131] [ezfs] ls works??? (checkpoint) --- fs/rustezfs/ezfs.rs | 72 +++++++- rust/kernel/fs.rs | 25 +++ rust/kernel/fs/file.rs | 393 +++++++++++++++++++++++++++++++++++++++-- rust/kernel/inode.rs | 13 +- rust/kernel/lib.rs | 1 + rust/kernel/user.rs | 40 +++++ 6 files changed, 515 insertions(+), 29 deletions(-) create mode 100644 rust/kernel/user.rs diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index cc1d83a07c78f1..8e78e723fa0c7b 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -6,12 +6,12 @@ mod defs; mod dir; mod inode; mod sb; -use crate::dir::DirEntryStore; +use crate::dir::{DirEntryStore, EzfsDirEntry}; use crate::inode::{EzfsInode, InodeStore}; use crate::sb::{EzfsSuperblock, EzfsSuperblockDisk}; use defs::*; use kernel::dentry; -use kernel::fs::{FileSystem, Registration}; +use kernel::fs::{file, File, FileSystem, Registration}; use kernel::inode::{INode, INodeState, Mapper, Params, Type}; use kernel::prelude::*; use kernel::sb::{New, SuperBlock, Type as SuperType}; @@ -59,18 +59,17 @@ impl RustEzFs { let ezfs_inode = inode_store[ino - 1]; let mode = ezfs_inode.mode(); + const DIR_FOPS: file::Ops = file::Ops::new::(); const DIR_IOPS: kernel::inode::Ops = kernel::inode::Ops::new::(); let typ = match mode & fs::mode::S_IFMT { fs::mode::S_IFREG => { - // inode - // .set_fops(file::Ops::generic_ro_file()) - // .set_aops(FILE_AOPS); + inode.set_fops(file::Ops::generic_ro_file()); + // .set_aops(FILE_AOPS); Type::Reg } fs::mode::S_IFDIR => { - inode.set_iops(DIR_IOPS); - // inode.set_iops(DIR_IOPS).set_fops(DIR_FOPS); + inode.set_iops(DIR_IOPS).set_fops(DIR_FOPS); Type::Dir } _ => return Err(ENOENT), @@ -176,6 +175,65 @@ impl kernel::inode::Operations for RustEzFs { } } +#[vtable] +impl file::Operations for RustEzFs { + type FileSystem = Self; + + fn read_dir( + _file: &File, + inode: &Locked<&INode, kernel::inode::ReadSem>, + emitter: &mut file::DirEmitter, + ) -> Result { + let sb = &*inode.super_block(); + let h = sb.data(); + + let index = { + let pos: usize = emitter.pos().try_into().map_err(|_| ENOENT)?; + pr_info!("emitter position: {:?}", pos); + + if pos % size_of::() != 0 { + return Err(ENOENT); + } + + pos / size_of::() + }; + + pr_info!("emitter index: {:?}", index); + + if index >= EZFS_MAX_CHILDREN { + return Ok(()); + } + + let ezfs_dir_inode = inode.data(); + let offset = ezfs_dir_inode + .data_blk_num() + .checked_mul(EZFS_BLOCK_SIZE as u64) + .ok_or(EIO)?; + + let mapped = h.mapper.mapped_folio(offset.try_into()?)?; + let dir_entries = + DirEntryStore::from_bytes(&mapped[..size_of::()]).ok_or(EIO)?; + + let active_entries = dir_entries + .iter() + .skip(index) + .filter(|&entry| entry.is_active()); + + for entry in active_entries { + if !emitter.emit( + size_of::() as i64, + entry.filename(), + entry.inode_no(), + file::DirEntryType::Unknown, + ) { + return Ok(()); + } + } + + Ok(()) + } +} + type FsModule = RustEzFsModule; module! { diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs index 100683adcd2cf7..7e23179196268a 100644 --- a/rust/kernel/fs.rs +++ b/rust/kernel/fs.rs @@ -81,6 +81,12 @@ pub trait FileSystem { /// Determines how superblocks for this file system type are keyed. const SUPER_TYPE: sb::Type = sb::Type::Independent; + /// Determines if an implementation doesn't specify the required types. + /// + /// This is meant for internal use only. + #[doc(hidden)] + const IS_UNSPECIFIED: bool = false; + fn fill_super( sb: &mut SuperBlock, mapper: Option>, //TODO: Default type parameter should be UnspecifiedFS @@ -93,6 +99,25 @@ pub trait FileSystem { fn init_root(sb: &SuperBlock) -> Result>; } +/// A file system that is unspecified. +/// +/// Attempting to get super-block or inode data from it will result in a build error. +pub struct UnspecifiedFS; + +impl FileSystem for UnspecifiedFS { + type Data = (); + type INodeData = (); + const NAME: &'static CStr = crate::c_str!("unspecified"); + const IS_UNSPECIFIED: bool = true; + fn fill_super(_: &mut SuperBlock, _: Option) -> Result { + Err(ENOTSUPP) + } + + fn init_root(_: &SuperBlock) -> Result> { + Err(ENOTSUPP) + } +} + /// A file system registration. #[pin_data(PinnedDrop)] pub struct Registration { diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index a3864cbd66c881..fbdd468b238b10 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -7,15 +7,18 @@ //! C headers: [`include/linux/fs.h`](srctree/include/linux/fs.h) and //! [`include/linux/file.h`](srctree/include/linux/file.h) +use macros::vtable; + use crate::{ bindings, cred::Credential, error::{code::*, from_result, to_result, Error, Result}, fmt, - fs::{FileSystem, Offset}, - inode::{self, INode}, + fs::{FileSystem, Offset, UnspecifiedFS}, + inode::{self, INode, Ino}, sync::aref::{ARef, AlwaysRefCounted}, types::{Locked, NotThreadSafe, Opaque}, + user, }; use core::{marker::PhantomData, mem::ManuallyDrop, ptr}; @@ -180,21 +183,22 @@ pub mod flags { /// * There must not be any active calls to `fdget_pos` on this file that did not take the /// `f_pos_lock` mutex. #[repr(transparent)] -pub struct File { +pub struct File { inner: Opaque, + _p: PhantomData, } // SAFETY: This file is known to not have any active `fdget_pos` calls that did not take the // `f_pos_lock` mutex, so it is safe to transfer it between threads. -unsafe impl Send for File {} +unsafe impl Send for File {} // SAFETY: This file is known to not have any active `fdget_pos` calls that did not take the // `f_pos_lock` mutex, so it is safe to access its methods from several threads in parallel. -unsafe impl Sync for File {} +unsafe impl Sync for File {} // SAFETY: The type invariants guarantee that `File` is always ref-counted. This implementation // makes `ARef` own a normal refcount. -unsafe impl AlwaysRefCounted for File { +unsafe impl AlwaysRefCounted for File { #[inline] fn inc_ref(&self) { // SAFETY: The existence of a shared reference means that the refcount is nonzero. @@ -202,7 +206,7 @@ unsafe impl AlwaysRefCounted for File { } #[inline] - unsafe fn dec_ref(obj: ptr::NonNull) { + unsafe fn dec_ref(obj: ptr::NonNull>) { // SAFETY: To call this method, the caller passes us ownership of a normal refcount, so we // may drop it. The cast is okay since `File` has the same representation as `struct file`. unsafe { bindings::fput(obj.cast().as_ptr()) } @@ -224,13 +228,14 @@ unsafe impl AlwaysRefCounted for File { /// /// [`assume_no_fdget_pos`]: LocalFile::assume_no_fdget_pos #[repr(transparent)] -pub struct LocalFile { +pub struct LocalFile { inner: Opaque, + _p: PhantomData, } // SAFETY: The type invariants guarantee that `LocalFile` is always ref-counted. This implementation // makes `ARef` own a normal refcount. -unsafe impl AlwaysRefCounted for LocalFile { +unsafe impl AlwaysRefCounted for LocalFile { #[inline] fn inc_ref(&self) { // SAFETY: The existence of a shared reference means that the refcount is nonzero. @@ -238,7 +243,7 @@ unsafe impl AlwaysRefCounted for LocalFile { } #[inline] - unsafe fn dec_ref(obj: ptr::NonNull) { + unsafe fn dec_ref(obj: ptr::NonNull>) { // SAFETY: To call this method, the caller passes us ownership of a normal refcount, so we // may drop it. The cast is okay since `LocalFile` has the same representation as // `struct file`. @@ -246,7 +251,7 @@ unsafe impl AlwaysRefCounted for LocalFile { } } -impl LocalFile { +impl LocalFile { /// Constructs a new `struct file` wrapper from a file descriptor. /// /// The file descriptor belongs to the current process, and there might be active local calls @@ -256,7 +261,7 @@ impl LocalFile { /// /// [`assume_no_fdget_pos`]: LocalFile::assume_no_fdget_pos #[inline] - pub fn fget(fd: u32) -> Result, BadFdError> { + pub fn fget(fd: u32) -> Result>, BadFdError> { // SAFETY: FFI call, there are no requirements on `fd`. let ptr = ptr::NonNull::new(unsafe { bindings::fget(fd) }).ok_or(BadFdError)?; @@ -277,7 +282,7 @@ impl LocalFile { /// * The caller must ensure that if there is an active call to `fdget_pos` that did not take /// the `f_pos_lock` mutex, then that call is on the current thread. #[inline] - pub unsafe fn from_raw_file<'a>(ptr: *const bindings::file) -> &'a LocalFile { + pub unsafe fn from_raw_file<'a>(ptr: *const bindings::file) -> &'a LocalFile { // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the // duration of `'a`. The cast is okay because `LocalFile` is `repr(transparent)`. // @@ -300,7 +305,7 @@ impl LocalFile { /// /// There must not be any active `fdget_pos` calls on the current thread. #[inline] - pub unsafe fn assume_no_fdget_pos(me: ARef) -> ARef { + pub unsafe fn assume_no_fdget_pos(me: ARef>) -> ARef> { // INVARIANT: There are no `fdget_pos` calls on the current thread, and by the type // invariants, if there is a `fdget_pos` call on another thread, then it took the // `f_pos_lock` mutex. @@ -339,9 +344,15 @@ impl LocalFile { // FIXME(read_once): Replace with `read_once` when available on the Rust side. unsafe { core::ptr::addr_of!((*self.as_ptr()).f_flags).read_volatile() } } + + /// Returns the inode associated with the file. + pub fn inode(&self) -> &INode { + // SAFETY: `f_inode` is an immutable field, so it's safe to read it. + unsafe { INode::from_raw((*self.inner.get()).f_inode) } + } } -impl File { +impl File { /// Creates a reference to a [`File`] from a valid pointer. /// /// # Safety @@ -351,7 +362,7 @@ impl File { /// * The caller must ensure that if there are active `fdget_pos` calls on this file, then they /// took the `f_pos_lock` mutex. #[inline] - pub unsafe fn from_raw_file<'a>(ptr: *const bindings::file) -> &'a File { + pub unsafe fn from_raw_file<'a>(ptr: *const bindings::file) -> &'a File { // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the // duration of `'a`. The cast is okay because `File` is `repr(transparent)`. // @@ -361,10 +372,10 @@ impl File { } // Make LocalFile methods available on File. -impl core::ops::Deref for File { - type Target = LocalFile; +impl core::ops::Deref for File { + type Target = LocalFile; #[inline] - fn deref(&self) -> &LocalFile { + fn deref(&self) -> &LocalFile { // SAFETY: The caller provides a `&File`, and since it is a reference, it must point at a // valid file for the desired duration. // @@ -468,3 +479,347 @@ impl fmt::Debug for BadFdError { f.pad("EBADF") } } + +/// Indicates how to interpret the `offset` argument in [`Operations::seek`]. +#[repr(u32)] +pub enum Whence { + /// `offset` bytes from the start of the file. + Set = bindings::SEEK_SET, + + /// `offset` bytes from the end of the file. + End = bindings::SEEK_END, + + /// `offset` bytes from the current location. + Cur = bindings::SEEK_CUR, + + /// The next location greater than or equal to `offset` that contains data. + Data = bindings::SEEK_DATA, + + /// The next location greater than or equal to `offset` that contains a hole. + Hole = bindings::SEEK_HOLE, +} + +impl TryFrom for Whence { + type Error = crate::error::Error; + + fn try_from(v: i32) -> Result { + match v { + v if v == Self::Set as i32 => Ok(Self::Set), + v if v == Self::End as i32 => Ok(Self::End), + v if v == Self::Cur as i32 => Ok(Self::Cur), + v if v == Self::Data as i32 => Ok(Self::Data), + v if v == Self::Hole as i32 => Ok(Self::Hole), + _ => Err(EDOM), + } + } +} + +/// Generic implementation of [`Operations::seek`]. +pub fn generic_seek( + file: &File, + offset: Offset, + whence: Whence, +) -> Result { + let n = unsafe { bindings::generic_file_llseek(file.inner.get(), offset, whence as i32) }; + if n < 0 { + Err(Error::from_errno(n.try_into()?)) + } else { + Ok(n) + } +} + +/// Operations implemented by files +#[vtable] +pub trait Operations { + /// File system that these operations are compatible with. + type FileSystem: FileSystem + ?Sized; + + /// Reads data from this file into caller's buffer. + fn read( + _file: &File, + _buffer: &mut user::Writer, + _offset: &mut Offset, + ) -> Result { + Err(EINVAL) + } + + /// Seeks the file to the given offset. + fn seek(_file: &File, _offset: Offset, _whence: Whence) -> Result { + Err(EINVAL) + } + + /// Reads directory entries from directory files. + /// + /// [`DirEmitter::pos`] holds the current position of the directory reader. + fn read_dir( + _file: &File, + _inode: &Locked<&INode, inode::ReadSem>, + _emitter: &mut DirEmitter, + ) -> Result { + Err(EINVAL) + } +} + +/// Represents file operations +pub struct Ops { + pub(crate) inner: *const bindings::file_operations, + _p: PhantomData, +} + +impl Ops { + /// Returns file operations for page-cache-based ro files. + pub fn generic_ro_file() -> Self { + // SAFETY: This is a constant in C, it never changes. + Self { + inner: unsafe { &bindings::generic_ro_fops }, + _p: PhantomData, + } + } + /// Creates file operations from a type that implements the [`Operations`] trait. + pub const fn new + ?Sized>() -> Self { + struct Table(PhantomData); + impl Table { + const TABLE: bindings::file_operations = bindings::file_operations { + owner: ptr::null_mut(), + llseek: if T::HAS_SEEK { + Some(Self::seek_callback) + } else { + None + }, + read: if T::HAS_READ { + Some(Self::read_callback) + } else { + None + }, + write: None, + read_iter: None, + write_iter: None, + iopoll: None, + iterate_shared: if T::HAS_READ_DIR { + Some(Self::read_dir_callback) + } else { + None + }, + poll: None, + unlocked_ioctl: None, + fop_flags: 0, + compat_ioctl: None, + mmap: None, + mmap_prepare: None, + open: None, + flush: None, + release: None, + fsync: None, + fasync: None, + lock: None, + get_unmapped_area: None, + check_flags: None, + flock: None, + splice_write: None, + splice_read: None, + splice_eof: None, + setlease: None, + fallocate: None, + show_fdinfo: None, + copy_file_range: None, + remap_file_range: None, + fadvise: None, + uring_cmd: None, + uring_cmd_iopoll: None, + }; + + unsafe extern "C" fn seek_callback( + file_ptr: *mut bindings::file, + offset: bindings::loff_t, + whence: i32, + ) -> bindings::loff_t { + from_result(|| { + // SAFETY: The C API guarantees that `file` is valid for the duration of the + // callback. Since this callback is specifically for filesystem T, we know `T` + // is the right filesystem. + let file = unsafe { File::from_raw_file(file_ptr) }; + T::seek(file, offset, whence.try_into()?) + }) + } + + unsafe extern "C" fn read_callback( + file_ptr: *mut bindings::file, + ptr: *mut core::ffi::c_char, + len: usize, + offset: *mut bindings::loff_t, + ) -> isize { + from_result(|| { + // SAFETY: The C API guarantees that `file` is valid for the duration of the + // callback. Since this callback is specifically for filesystem T, we know `T` + // is the right filesystem. + let file = unsafe { File::from_raw_file(file_ptr) }; + let mut writer = user::Writer::new(ptr, len); + + // SAFETY: The C API guarantees that `offset` is valid for read and write. + let read = T::read(file, &mut writer, unsafe { &mut *offset })?; + Ok(isize::try_from(read)?) + }) + } + + unsafe extern "C" fn read_dir_callback( + file_ptr: *mut bindings::file, + ctx_ptr: *mut bindings::dir_context, + ) -> core::ffi::c_int { + from_result(|| { + // SAFETY: The C API guarantees that `file` is valid for the duration of the + // callback. Since this callback is specifically for filesystem T, we know `T` + // is the right filesystem. + let file = unsafe { File::from_raw_file(file_ptr) }; + + // SAFETY: The C API guarantees that this is the only reference to the + // `dir_context` instance. + let emitter = unsafe { &mut *ctx_ptr.cast::() }; + let orig_pos = emitter.pos(); + + // SAFETY: The C API guarantees that the inode's rw semaphore is locked in read + // mode. It does not expect callees to unlock it, so we make the locked object + // manually dropped to avoid unlocking it. + let locked = ManuallyDrop::new(unsafe { Locked::new(file.inode()) }); + + // Call the module implementation. We ignore errors if directory entries have + // been succesfully emitted: this is because we want users to see them before + // the error. + match T::read_dir(file, &locked, emitter) { + Ok(_) => Ok(0), + Err(e) => { + if emitter.pos() == orig_pos { + Err(e) + } else { + Ok(0) + } + } + } + }) + } + } + Self { + inner: &Table::::TABLE, + _p: PhantomData, + } + } +} + +/// The types of directory entries reported by [`Operations::read_dir`]. +#[repr(u32)] +#[derive(Copy, Clone)] +pub enum DirEntryType { + /// Unknown type. + Unknown = bindings::DT_UNKNOWN, + + /// Named pipe (first-in, first-out) type. + Fifo = bindings::DT_FIFO, + + /// Character device type. + Chr = bindings::DT_CHR, + + /// Directory type. + Dir = bindings::DT_DIR, + + /// Block device type. + Blk = bindings::DT_BLK, + + /// Regular file type. + Reg = bindings::DT_REG, + + /// Symbolic link type. + Lnk = bindings::DT_LNK, + + /// Named unix-domain socket type. + Sock = bindings::DT_SOCK, + + /// White-out type. + Wht = bindings::DT_WHT, +} + +impl From<&inode::Type> for DirEntryType { + fn from(value: &inode::Type) -> Self { + match value { + inode::Type::Fifo => DirEntryType::Fifo, + inode::Type::Chr(_, _) => DirEntryType::Chr, + inode::Type::Dir => DirEntryType::Dir, + inode::Type::Blk(_, _) => DirEntryType::Blk, + inode::Type::Reg => DirEntryType::Reg, + inode::Type::Lnk(_) => DirEntryType::Lnk, + inode::Type::Sock => DirEntryType::Sock, + } + } +} + +impl TryFrom for DirEntryType { + type Error = crate::error::Error; + + fn try_from(v: u32) -> Result { + match v { + v if v == Self::Unknown as u32 => Ok(Self::Unknown), + v if v == Self::Fifo as u32 => Ok(Self::Fifo), + v if v == Self::Chr as u32 => Ok(Self::Chr), + v if v == Self::Dir as u32 => Ok(Self::Dir), + v if v == Self::Blk as u32 => Ok(Self::Blk), + v if v == Self::Reg as u32 => Ok(Self::Reg), + v if v == Self::Lnk as u32 => Ok(Self::Lnk), + v if v == Self::Sock as u32 => Ok(Self::Sock), + v if v == Self::Wht as u32 => Ok(Self::Wht), + _ => Err(EDOM), + } + } +} + +/// Directory entry emitter. +/// +/// This is used in [`Operations::read_dir`] implementations to report the directory entry. +#[repr(transparent)] +pub struct DirEmitter(bindings::dir_context); + +impl DirEmitter { + /// Returns the current position of the emitter. + pub fn pos(&self) -> Offset { + self.0.pos + } + + /// Emits a directory entry. + /// + /// `pos_inc` is the number with which to increment the current position on success. + /// + /// `name` is the name of the entry. + /// + /// `ino` is the inode number of the entry. + /// + /// `etype` is the type of the entry. + /// + /// Returns `false` when the entry could not be emitted, possibly because the user-provided + /// buffer is full. + pub fn emit(&mut self, pos_inc: Offset, name: &[u8], ino: u64, etype: DirEntryType) -> bool { + let Ok(name_len) = i32::try_from(name.len()) else { + return false; + }; + + let Some(actor) = self.0.actor else { + return false; + }; + + let Some(new_pos) = self.0.pos.checked_add(pos_inc) else { + return false; + }; + + // SAFETY: `name` is valid at least for the duration of the `actor` call. + let ret = unsafe { + actor( + &mut self.0, + name.as_ptr(), + name_len, + self.0.pos, + ino, + etype as _, + ) + }; + if ret { + self.0.pos = new_pos; + } + ret + } +} diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index 0abecb44f6e386..f199aa25055753 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -6,7 +6,7 @@ use macros::vtable; use crate::dentry::{self, DEntry}; use crate::error::{from_err_ptr, Result}; use crate::folio::{self, Folio}; -use crate::fs::PageOffset; +use crate::fs::{file, PageOffset, UnspecifiedFS}; use crate::prelude::{EIO, ENOTSUPP, ERANGE}; use crate::sb::SuperBlock; use crate::str::CString; @@ -184,8 +184,7 @@ unsafe impl Lockable for INode { /// # Invariants /// /// Mappers are unique per range per inode. -// TODO: should be default UnspecifiedFS -pub struct Mapper { +pub struct Mapper { inode: ARef>, begin: Offset, end: Offset, @@ -329,6 +328,14 @@ impl New { self } + + /// Sets the file operations on this new inode. + pub fn set_fops(&mut self, fops: file::Ops) -> &mut Self { + // SAFETY: By the type invariants, it's ok to modify the inode. + let inode = unsafe { self.0.as_mut() }; + inode.__bindgen_anon_3.i_fop = fops.inner; + self + } } impl Drop for New { diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index cb49fe45e4d66b..3e839d3dd85b9e 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -143,6 +143,7 @@ pub mod tracepoint; pub mod transmute; pub mod types; pub mod uaccess; +pub mod user; pub mod workqueue; pub mod xarray; diff --git a/rust/kernel/user.rs b/rust/kernel/user.rs new file mode 100644 index 00000000000000..38326d2fa7aed0 --- /dev/null +++ b/rust/kernel/user.rs @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! User-space related functions. +use crate::error::{code::*, Result}; + +/// A writer to userspace memory. +pub struct Writer { + ptr: *mut u8, + len: usize, +} + +impl Writer { + pub(crate) fn new(ptr: *mut u8, len: usize) -> Self { + Self { ptr, len } + } + + /// Writes all of `data` into user memory. + pub fn write_all(&mut self, data: &[u8]) -> Result { + let len = data.len(); + if len > self.len { + return Err(EFAULT); + } + + let pending = unsafe { + bindings::copy_to_user( + self.ptr.cast::(), + data.as_ptr().cast::(), + data.len().try_into()?, + ) + }; + if pending != 0 { + return Err(EFAULT); + } + + self.ptr = self.ptr.wrapping_add(len); + self.len -= len; + + Ok(()) + } +} From debd5c923ccb15d195f139c5022bdc1d2f7cb75a Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 26 Nov 2025 15:24:33 -0500 Subject: [PATCH 025/131] [ezfs] move ops def into static fs scope --- fs/rustezfs/ezfs.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 8e78e723fa0c7b..861900acceb728 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -43,6 +43,9 @@ impl kernel::InPlaceModule for RustEzFsModule { } impl RustEzFs { + const DIR_FOPS: file::Ops = file::Ops::new::(); + const DIR_IOPS: kernel::inode::Ops = kernel::inode::Ops::new::(); + fn iget(sb: &SuperBlock, ino: usize) -> Result>> { let mut inode = match sb.get_or_create_inode(ino)? { INodeState::Existing(inode) => return Ok(inode), @@ -59,9 +62,6 @@ impl RustEzFs { let ezfs_inode = inode_store[ino - 1]; let mode = ezfs_inode.mode(); - const DIR_FOPS: file::Ops = file::Ops::new::(); - const DIR_IOPS: kernel::inode::Ops = kernel::inode::Ops::new::(); - let typ = match mode & fs::mode::S_IFMT { fs::mode::S_IFREG => { inode.set_fops(file::Ops::generic_ro_file()); @@ -69,7 +69,7 @@ impl RustEzFs { Type::Reg } fs::mode::S_IFDIR => { - inode.set_iops(DIR_IOPS).set_fops(DIR_FOPS); + inode.set_iops(Self::DIR_IOPS).set_fops(Self::DIR_FOPS); Type::Dir } _ => return Err(ENOENT), From 857e65466598918c416dc7b54b355168e69e6d1d Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 26 Nov 2025 16:35:19 -0500 Subject: [PATCH 026/131] [ezfs] fix kernel crash? --- fs/rustezfs/ezfs.rs | 4 +++- rust/kernel/inode.rs | 2 +- rust/kernel/sb.rs | 7 +++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 861900acceb728..6a56992f559763 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -64,7 +64,9 @@ impl RustEzFs { let typ = match mode & fs::mode::S_IFMT { fs::mode::S_IFREG => { - inode.set_fops(file::Ops::generic_ro_file()); + inode + .set_iops(Self::DIR_IOPS) + .set_fops(file::Ops::generic_ro_file()); // .set_aops(FILE_AOPS); Type::Reg } diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index f199aa25055753..31920abfaf6ded 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -258,6 +258,7 @@ impl New { unsafe { bindings::inode_nohighmem(inode) }; } } + // TODO: Look into this // if let Some(s) = str { // inode.__bindgen_anon_5.i_link = s.into_foreign().cast::().cast_mut(); // } @@ -325,7 +326,6 @@ impl New { pub fn set_iops(&mut self, iops: Ops) -> &mut Self { let inode = unsafe { self.0.as_mut() }; inode.i_op = iops.0; - self } diff --git a/rust/kernel/sb.rs b/rust/kernel/sb.rs index 4594e134b15572..51eb3fc33a3996 100644 --- a/rust/kernel/sb.rs +++ b/rust/kernel/sb.rs @@ -98,10 +98,9 @@ impl SuperBlock { impl SuperBlock { /// Returns the data associated with the superblock. pub fn data(&self) -> ::Borrowed<'_> { - // TODO: Add UnspecifiedFS - // if T::IS_UNSPECIFIED { - // crate::build_error!("super block data type is unspecified"); - // } + if T::IS_UNSPECIFIED { + crate::build_error!("super block data type is unspecified"); + } // SAFETY: This method is only available if the typestate implements `DataInited`, whose // safety requirements include `s_fs_info` being properly initialised. From 6985208934a36485236bc536cb2c5121bc457f89 Mon Sep 17 00:00:00 2001 From: lsig Date: Fri, 28 Nov 2025 01:49:52 -0500 Subject: [PATCH 027/131] [ezfs] add get_link to prevent kernel crash --- rust/kernel/inode.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index 31920abfaf6ded..521e98e8f12e86 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -33,6 +33,18 @@ pub trait Operations { /// File system that these operations are compatible with. type FileSystem: FileSystem + ?Sized; + /// Returns the string that represents the name of the file a symbolic link inode points to. + /// + /// When `dentry` is `None`, `get_link` is called with the RCU read-side lock held, so it may + /// not sleep. Implementations must return `Err(ECHILD)` for it to be called again without + /// holding the RCU lock. + fn get_link<'a>( + _dentry: Option<&DEntry>, + _inode: &'a INode, + ) -> Result { + Err(ENOTSUPP) + } + /// Returns the inode corresponding to the directory entry with the given name fn lookup( _parent: &Locked<&INode, ReadSem>, From e77246d1da7ca78685b10179ce094e7c79ea0ddd Mon Sep 17 00:00:00 2001 From: lsig Date: Fri, 28 Nov 2025 16:28:01 -0500 Subject: [PATCH 028/131] mem_cache: checkpoint --- fs/rustezfs/ezfs.rs | 23 ++++++- rust/bindings/bindings_helper.h | 2 + rust/helpers/fs.c | 6 ++ rust/helpers/slab.c | 11 ++++ rust/kernel/error.rs | 1 + rust/kernel/fs.rs | 7 ++- rust/kernel/inode.rs | 108 ++++++++++++++++++++++++++++++-- rust/kernel/lib.rs | 1 + rust/kernel/mem_cache.rs | 62 ++++++++++++++++++ 9 files changed, 212 insertions(+), 9 deletions(-) create mode 100644 rust/kernel/mem_cache.rs diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 6a56992f559763..126f938692971e 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -11,13 +11,14 @@ use crate::inode::{EzfsInode, InodeStore}; use crate::sb::{EzfsSuperblock, EzfsSuperblockDisk}; use defs::*; use kernel::dentry; -use kernel::fs::{file, File, FileSystem, Registration}; +use kernel::fs::{file, File, FileSystem, Offset, Registration}; use kernel::inode::{INode, INodeState, Mapper, Params, Type}; use kernel::prelude::*; use kernel::sb::{New, SuperBlock, Type as SuperType}; use kernel::time::UNIX_EPOCH; use kernel::transmute::FromBytes; use kernel::types::{ARef, Locked}; +use kernel::uapi::ENAMETOOLONG; use kernel::{c_str, fs, str::CStr}; use core::marker::{PhantomData, Send, Sync}; @@ -140,14 +141,25 @@ impl kernel::inode::Operations for RustEzFs { ) -> Result>>> { let sb = &*parent.super_block(); let h = sb.data(); + let name = dentry.name(); + pr_info!("looking for file: {:?}", core::str::from_utf8(name)); + + if name.len() > EZFS_FILENAME_BUF_SIZE { + pr_info!("dentry name to long: {:?}", core::str::from_utf8(name)); + // return Err(ENAMETOOLONG); + } + let ezfs_dir_inode = parent.data(); + pr_info!("ezfs_dir inode number: {:?}", parent.ino()); + pr_info!("ezfs dir inode links: {:?}", ezfs_dir_inode.nlink()); pr_info!("data_blk_num: {:?}", ezfs_dir_inode.data_blk_num()); let offset = ezfs_dir_inode .data_blk_num() .checked_mul(EZFS_BLOCK_SIZE as u64) .ok_or(EIO)?; + let mapped = h.mapper.mapped_folio(offset.try_into()?)?; let dir_entries = DirEntryStore::from_bytes(&mapped[..size_of::()]).ok_or(EIO)?; @@ -168,6 +180,7 @@ impl kernel::inode::Operations for RustEzFs { }); let inode = if let Some(entry) = dir_entry { + pr_info!("Inode found: {:?}", entry.inode_no()); Some(Self::iget(sb, entry.inode_no().try_into()?)?) } else { None @@ -181,6 +194,14 @@ impl kernel::inode::Operations for RustEzFs { impl file::Operations for RustEzFs { type FileSystem = Self; + fn seek(file: &File, offset: Offset, whence: file::Whence) -> Result { + file::generic_seek(file, offset, whence) + } + + fn read(_: &File, _: &mut kernel::user::Writer, _: &mut Offset) -> Result { + Err(EISDIR) + } + fn read_dir( _file: &File, inode: &Locked<&INode, kernel::inode::ReadSem>, diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 8f10a4e24906d3..9d832ea432ac44 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -110,6 +110,8 @@ const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT; const gfp_t RUST_CONST_HELPER_XA_FLAGS_ALLOC = XA_FLAGS_ALLOC; const gfp_t RUST_CONST_HELPER_XA_FLAGS_ALLOC1 = XA_FLAGS_ALLOC1; const vm_flags_t RUST_CONST_HELPER_VM_MERGEABLE = VM_MERGEABLE; +const slab_flags_t RUST_CONST_HELPER_SLAB_RECLAIM_ACCOUNT = SLAB_RECLAIM_ACCOUNT; +const slab_flags_t RUST_CONST_HELPER_SLAB_ACCOUNT = SLAB_ACCOUNT; #if IS_ENABLED(CONFIG_ANDROID_BINDER_IPC_RUST) #include "../../drivers/android/binder/rust_binder.h" diff --git a/rust/helpers/fs.c b/rust/helpers/fs.c index 0b8776aad1e616..d13ffd2407cb0c 100644 --- a/rust/helpers/fs.c +++ b/rust/helpers/fs.c @@ -31,3 +31,9 @@ void rust_helper_inode_unlock_shared(struct inode *inode) { inode_unlock_shared(inode); } + +void *rust_helper_alloc_inode_sb(struct super_block *sb, + struct kmem_cache *cache, gfp_t gfp) +{ + return alloc_inode_sb(sb, cache, gfp); +} diff --git a/rust/helpers/slab.c b/rust/helpers/slab.c index 7fac958907b0a7..18d53b8c5e02af 100644 --- a/rust/helpers/slab.c +++ b/rust/helpers/slab.c @@ -15,3 +15,14 @@ rust_helper_kvrealloc_node_align(const void *p, size_t size, unsigned long align { return kvrealloc_node_align(p, size, align, flags, node); } + +// TODO: update to new API +struct kmem_cache *rust_helper_kmem_cache_create( + const char *name, + unsigned int size, + unsigned int align, + slab_flags_t flags, + void (*ctor)(void *)) +{ + return kmem_cache_create(name, size, align, flags, ctor); +} diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index 1c0e0e241daa91..ae66a481556bd9 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -87,6 +87,7 @@ pub mod code { declare_err!(EIOCBQUEUED, "iocb queued, will get completion event."); declare_err!(ERECALLCONFLICT, "Conflict with recalled state."); declare_err!(ENOGRACE, "NFS file lock reclaim refused."); + declare_err!(ENAMETOOLONG, "File name too long"); } /// Generic integer kernel error. diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs index 7e23179196268a..75b9e25a82ff54 100644 --- a/rust/kernel/fs.rs +++ b/rust/kernel/fs.rs @@ -9,7 +9,8 @@ use pin_init::{pin_data, pinned_drop, PinInit, PinnedDrop}; use crate::{ bindings, dentry, error::{from_result, to_result, Error, Result}, - inode, + inode::{self, INode}, + mem_cache::MemCache, prelude::*, sb::{self, SuperBlock}, str::CStr, @@ -122,7 +123,8 @@ impl FileSystem for UnspecifiedFS { #[pin_data(PinnedDrop)] pub struct Registration { #[pin] - fs: Opaque, + pub(crate) fs: Opaque, + pub(crate) inode_cache: Option, } impl Registration { @@ -132,6 +134,7 @@ impl Registration { /// to be made before users can mount it. pub fn new(module: &'static ThisModule) -> impl PinInit { try_pin_init!(Self { + inode_cache: INode::::new_cache()?, fs <- Opaque::try_ffi_init(|fs_ptr: *mut bindings::file_system_type| { // SAFETY: `try_ffi_init` guarantees that `fs_ptr` is valid for write. unsafe { fs_ptr.write(bindings::file_system_type::default()) }; diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index 521e98e8f12e86..e8602ec9a18ee0 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -6,13 +6,15 @@ use macros::vtable; use crate::dentry::{self, DEntry}; use crate::error::{from_err_ptr, Result}; use crate::folio::{self, Folio}; +use crate::fs::{self, mode, Registration}; use crate::fs::{file, PageOffset, UnspecifiedFS}; -use crate::prelude::{EIO, ENOTSUPP, ERANGE}; +use crate::mem_cache::MemCache; +use crate::prelude::{EIO, ENOTSUPP, ERANGE, GFP_KERNEL}; use crate::sb::SuperBlock; use crate::str::CString; use crate::time::Timespec; use crate::types::{AlwaysRefCounted, Lockable, Locked}; -use crate::{block, container_of}; +use crate::{block, container_of, inode}; use crate::{ fs::{FileSystem, Offset}, time, @@ -96,10 +98,9 @@ impl INode { /// Returns the data associated with the inode. pub fn data(&self) -> &T::INodeData { - // TODO: add UnspecifiedFS - // if T::IS_UNSPECIFIED { - // crate::build_error!("inode data type is unspecified"); - // } + if T::IS_UNSPECIFIED { + crate::build_error!("inode data type is unspecified"); + } // TODO: Add safety let outerp = unsafe { container_of!(self.0.get(), WithData, inode) }; // SAFETY: `self` is guaranteed to be valid by the existence of a shared reference @@ -160,6 +161,101 @@ impl INode { // SAFETY: The folio returned by read_mapping_folio has had its refcount incremented. Ok(unsafe { ARef::from_raw(ptr) }) } + + pub(crate) fn new_cache() -> Result> { + Ok(if size_of::() == 0 { + None + } else { + Some(MemCache::try_new::>( + T::NAME, + Some(Self::inode_init_once_callback), + )?) + }) + } + + unsafe extern "C" fn inode_init_once_callback(outer_inode: *mut core::ffi::c_void) { + let ptr = outer_inode.cast::>(); + + // SAFETY: This is only used in `new`, so we know that we have a valid `inode::WithData` + // instance whose inode part can be initialised. + unsafe { bindings::inode_init_once(ptr::addr_of_mut!((*ptr).inode)) }; + } + + pub(crate) unsafe extern "C" fn alloc_inode_callback( + sb: *mut bindings::super_block, + ) -> *mut bindings::inode { + // SAFETY: The callback contract guarantees that `sb` is valid for read. + let raw_super_type = unsafe { (*sb).s_type }; + let super_type = raw_super_type.cast::>(); + + // SAFETY: This callback is only used in `Registration`, so `super_type` is necessarily + // embedded in a `Registration`, which is guaranteed to be valid because it has a + // superblock associated to it. + let reg = unsafe { &*container_of!(super_type, Registration, fs) }; + + // SAFETY: `sb` and `cache` are guaranteed to be valid by the callback contract and by + // the existence of a superblock respectively. + let ptr = unsafe { + bindings::alloc_inode_sb(sb, MemCache::ptr(®.inode_cache), bindings::GFP_KERNEL) + } + .cast::>(); + if ptr.is_null() { + return ptr::null_mut(); + } + + // SAFETY: `ptr` was just allocated, so it is valid for dereferencing. + unsafe { ptr::addr_of_mut!((*ptr).inode) } + } + + pub(crate) unsafe extern "C" fn destroy_inode_callback(inode: *mut bindings::inode) { + // SAFETY: By the C contract, `inode` is a valid pointer. + let is_bad = unsafe { bindings::is_bad_inode(inode) }; + + // SAFETY: The inode is guaranteed to be valid by the callback contract. Additionally, the + // superblock is also guaranteed to still be valid by the inode existence. + let raw_super_type = unsafe { (*(*inode).i_sb).s_type }; + let super_type = raw_super_type.cast::>(); + + // SAFETY: This callback is only used in `Registration`, so `super_type` is necessarily + // embedded in a `Registration`, which is guaranteed to be valid because it has a + // superblock associated to it. + let reg = unsafe { &*container_of!(super_type, Registration, fs) }; + let ptr = unsafe { container_of!(inode, WithData, inode) }; + + if !is_bad { + // SAFETY: The API contract guarantees that `inode` is valid. + // TODO: Add Link support + // if unsafe { (*inode).i_mode & mode::S_IFMT == mode::S_IFLNK } { + // // SAFETY: We just checked that the inode is a link. + // let lnk = unsafe { (*inode).__bindgen_anon_5.i_link }; + // if !lnk.is_null() { + // // SAFETY: This value is on link inode are only populated from with the result + // // of `CString::into_foreign`. + // unsafe { CString::from_foreign(lnk.cast::()) }; + // } + // } + + // SAFETY: The code either initialises the data or marks the inode as bad. Since the + // inode is not bad, the data is initialised, and thus safe to drop. + unsafe { ptr::drop_in_place((*ptr).data.as_mut_ptr()) }; + } + + if size_of::() == 0 { + // SAFETY: When the size of `INodeData` is zero, we don't use a separate mem_cache, so + // it is allocated from the regular mem_cache, which is what `free_inode_nonrcu` uses + // to free the inode. + unsafe { bindings::free_inode_nonrcu(inode) }; + } else { + // The callback contract guarantees that the inode was previously allocated via the + // `alloc_inode_callback` callback, so it is safe to free it back to the cache. + unsafe { + bindings::kmem_cache_free( + MemCache::ptr(®.inode_cache), + ptr.cast::(), + ) + }; + } + } } // SAFETY: The type invariants guarantee that `INode` is always ref-counted. diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 3e839d3dd85b9e..fd660fd7dd911d 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -108,6 +108,7 @@ pub mod jump_label; pub mod kunit; pub mod list; pub mod maple_tree; +pub mod mem_cache; pub mod miscdevice; pub mod mm; #[cfg(CONFIG_NET)] diff --git a/rust/kernel/mem_cache.rs b/rust/kernel/mem_cache.rs new file mode 100644 index 00000000000000..cbf1b7e7533400 --- /dev/null +++ b/rust/kernel/mem_cache.rs @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Kernel memory caches (kmem_cache). +//! +//! C headers: [`include/linux/slab.h`](../../include/linux/slab.h) + +use crate::error::{code::*, Result}; +use crate::{bindings, str::CStr}; +use core::ptr; + +/// A kernel memory cache. +/// +/// This isn't ready to be made public yet because it only provides functionality useful for the +/// allocation of inodes in file systems. +pub(crate) struct MemCache { + ptr: ptr::NonNull, +} + +impl MemCache { + /// Allocates a new `kmem_cache` for type `T`. + /// + /// `init` is called by the C code when entries are allocated. + pub(crate) fn try_new( + name: &'static CStr, + init: Option, + ) -> Result { + // SAFETY: `name` is static, so always valid. + let ptr = ptr::NonNull::new(unsafe { + bindings::kmem_cache_create( + name.as_char_ptr(), + core::mem::size_of::().try_into()?, + core::mem::align_of::().try_into()?, + bindings::SLAB_RECLAIM_ACCOUNT | bindings::SLAB_ACCOUNT, + init, + ) + }) + .ok_or(ENOMEM)?; + + Ok(Self { ptr }) + } + + /// Returns the pointer to the `kmem_cache` instance, or null if it's `None`. + /// + /// This is a helper for functions like `alloc_inode_sb` where the cache is optional. + pub(crate) fn ptr(c: &Option) -> *mut bindings::kmem_cache { + match c { + Some(m) => m.ptr.as_ptr(), + None => ptr::null_mut(), + } + } +} + +impl Drop for MemCache { + fn drop(&mut self) { + // SAFETY: Just an FFI call with no additional safety requirements. + unsafe { bindings::rcu_barrier() }; + + // SAFETY: `ptr` was previously returned by successful call to `kmem_cache_create`, so it's + // ok to destroy it here. + unsafe { bindings::kmem_cache_destroy(self.ptr.as_ptr()) }; + } +} From 48bb30d86fa590d7a5f5760d9b4fa089f39c6543 Mon Sep 17 00:00:00 2001 From: lsig Date: Fri, 28 Nov 2025 17:57:02 -0500 Subject: [PATCH 029/131] iterated_shared: emit dots checkpoint --- fs/rustezfs/ezfs.rs | 16 ++++++++++++---- rust/kernel/fs/file.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 126f938692971e..ae9368647ceb78 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -203,22 +203,30 @@ impl file::Operations for RustEzFs { } fn read_dir( - _file: &File, + file: &File, inode: &Locked<&INode, kernel::inode::ReadSem>, emitter: &mut file::DirEmitter, ) -> Result { + let pos: usize = emitter.pos().try_into().map_err(|_| ENOENT)?; + + if pos <= 2 { + if !emitter.emit_dots(file) { + return Ok(()); + } + } + let sb = &*inode.super_block(); let h = sb.data(); let index = { - let pos: usize = emitter.pos().try_into().map_err(|_| ENOENT)?; + let disk_pos = pos - 2; pr_info!("emitter position: {:?}", pos); - if pos % size_of::() != 0 { + if disk_pos % size_of::() != 0 { return Err(ENOENT); } - pos / size_of::() + disk_pos / size_of::() }; pr_info!("emitter index: {:?}", index); diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index fbdd468b238b10..096d6f0f4669d4 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -16,6 +16,7 @@ use crate::{ fmt, fs::{FileSystem, Offset, UnspecifiedFS}, inode::{self, INode, Ino}, + kernel::dentry::DEntry, sync::aref::{ARef, AlwaysRefCounted}, types::{Locked, NotThreadSafe, Opaque}, user, @@ -350,6 +351,19 @@ impl LocalFile { // SAFETY: `f_inode` is an immutable field, so it's safe to read it. unsafe { INode::from_raw((*self.inner.get()).f_inode) } } + + /// Returns the dentry associated with the file. + pub fn dentry(&self) -> &DEntry { + // SAFETY: `f_path` is an immutable field, so it's safe to read it. And will remain safe to + // read while the `&self` is valid. + unsafe { DEntry::from_raw((*self.inner.get()).__bindgen_anon_1.f_path.dentry) } + } + + pub fn parent_ino(&self) -> usize { + let dentry = self.dentry().0.get(); + + unsafe { bindings::d_parent_ino(dentry) } + } } impl File { @@ -822,4 +836,20 @@ impl DirEmitter { } ret } + + pub fn emit_dots(&mut self, file: &File) -> bool { + if self.0.pos == 0 { + if !self.emit(1, b".", file.inode().ino() as u64, DirEntryType::Dir) { + return false; + } + } + + if self.0.pos == 0 { + if !self.emit(1, b"..", file.parent_ino() as u64, DirEntryType::Dir) { + return false; + } + } + + true + } } From 8f2d48959169eae5317853a1587e79b957db737e Mon Sep 17 00:00:00 2001 From: lsig Date: Sat, 29 Nov 2025 00:38:00 -0500 Subject: [PATCH 030/131] [iterate_shared] checkpoint 2 --- fs/rustezfs/ezfs.rs | 18 +++++++++++++----- rust/kernel/fs.rs | 13 ++++++------- rust/kernel/fs/file.rs | 2 +- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index ae9368647ceb78..e310143e59386b 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -18,7 +18,6 @@ use kernel::sb::{New, SuperBlock, Type as SuperType}; use kernel::time::UNIX_EPOCH; use kernel::transmute::FromBytes; use kernel::types::{ARef, Locked}; -use kernel::uapi::ENAMETOOLONG; use kernel::{c_str, fs, str::CStr}; use core::marker::{PhantomData, Send, Sync}; @@ -147,7 +146,7 @@ impl kernel::inode::Operations for RustEzFs { if name.len() > EZFS_FILENAME_BUF_SIZE { pr_info!("dentry name to long: {:?}", core::str::from_utf8(name)); - // return Err(ENAMETOOLONG); + return Err(ENAMETOOLONG); } let ezfs_dir_inode = parent.data(); @@ -208,8 +207,11 @@ impl file::Operations for RustEzFs { emitter: &mut file::DirEmitter, ) -> Result { let pos: usize = emitter.pos().try_into().map_err(|_| ENOENT)?; + pr_info!("emitter position: {:?}", pos); - if pos <= 2 { + if pos < 2 { + pr_info!("pos < 2: trying to emit dots"); + pr_info!("file inode: {:?}", file.inode().ino()); if !emitter.emit_dots(file) { return Ok(()); } @@ -219,8 +221,8 @@ impl file::Operations for RustEzFs { let h = sb.data(); let index = { - let disk_pos = pos - 2; - pr_info!("emitter position: {:?}", pos); + let disk_pos = pos.checked_sub(2).ok_or(ENOENT)?; + pr_info!("disk position: {:?}", disk_pos); if disk_pos % size_of::() != 0 { return Err(ENOENT); @@ -232,18 +234,24 @@ impl file::Operations for RustEzFs { pr_info!("emitter index: {:?}", index); if index >= EZFS_MAX_CHILDREN { + pr_info!("index higher than max children: {:?}", index); return Ok(()); } let ezfs_dir_inode = inode.data(); + pr_info!("inode data_blk_num: {:?}", ezfs_dir_inode.data_blk_num()); + let offset = ezfs_dir_inode .data_blk_num() .checked_mul(EZFS_BLOCK_SIZE as u64) .ok_or(EIO)?; + pr_info!("valid offset: {:?}", offset); + let mapped = h.mapper.mapped_folio(offset.try_into()?)?; let dir_entries = DirEntryStore::from_bytes(&mapped[..size_of::()]).ok_or(EIO)?; + pr_info!("found dir_entries"); let active_entries = dir_entries .iter() diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs index 75b9e25a82ff54..cca588eb996887 100644 --- a/rust/kernel/fs.rs +++ b/rust/kernel/fs.rs @@ -283,13 +283,12 @@ impl Tables { } const SUPER_BLOCK: bindings::super_operations = bindings::super_operations { - alloc_inode: None, - // alloc_inode: if size_of::() != 0 { - // Some(INode::::alloc_inode_callback) - // } else { - // None - // }, - // destroy_inode: Some(INode::::destroy_inode_callback), + alloc_inode: if size_of::() != 0 { + Some(INode::::alloc_inode_callback) + } else { + None + }, + destroy_inode: Some(INode::::destroy_inode_callback), destroy_inode: None, free_inode: None, dirty_inode: None, diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index 096d6f0f4669d4..90a61d96350904 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -844,7 +844,7 @@ impl DirEmitter { } } - if self.0.pos == 0 { + if self.0.pos == 1 { if !self.emit(1, b"..", file.parent_ino() as u64, DirEntryType::Dir) { return false; } From b93412372e5853a02bf8042e353de1a8dafc7164 Mon Sep 17 00:00:00 2001 From: lsig Date: Sat, 29 Nov 2025 00:49:37 -0500 Subject: [PATCH 031/131] [vfs] fix small bug --- rust/kernel/fs.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs index cca588eb996887..85466d502f67e4 100644 --- a/rust/kernel/fs.rs +++ b/rust/kernel/fs.rs @@ -289,7 +289,6 @@ impl Tables { None }, destroy_inode: Some(INode::::destroy_inode_callback), - destroy_inode: None, free_inode: None, dirty_inode: None, write_inode: None, From 4b611cba481e964067074d3d1eb55c574b1d3624 Mon Sep 17 00:00:00 2001 From: lsig Date: Sat, 29 Nov 2025 14:10:46 -0500 Subject: [PATCH 032/131] [ezfs] file mode conversion checkpoint --- fs/rustezfs/ezfs.rs | 12 +++++++++++- rust/kernel/fs/file.rs | 7 +++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index e310143e59386b..6dc55a2236eb54 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -253,17 +253,27 @@ impl file::Operations for RustEzFs { DirEntryStore::from_bytes(&mapped[..size_of::()]).ok_or(EIO)?; pr_info!("found dir_entries"); + let inode_store = { + let offset = EZFS_INODE_STORE_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE; + let mapped_inode_store = h.mapper.mapped_folio(offset.try_into()?)?; + InodeStore::from_bytes(&mapped_inode_store[..size_of::()]).ok_or(EIO)? + }; + let active_entries = dir_entries .iter() .skip(index) .filter(|&entry| entry.is_active()); for entry in active_entries { + let ino: usize = entry.inode_no().try_into()?; + let entry_inode = inode_store[ino - EZFS_ROOT_INODE_NUMBER]; + let etype = file::DirEntryType::from_mode(entry_inode.mode()); + if !emitter.emit( size_of::() as i64, entry.filename(), entry.inode_no(), - file::DirEntryType::Unknown, + etype, ) { return Ok(()); } diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index 90a61d96350904..6a91f796f4b454 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -750,6 +750,13 @@ pub enum DirEntryType { Wht = bindings::DT_WHT, } +impl DirEntryType { + pub fn from_mode(mode: u32) -> Self { + let dt_value = (mode & bindings::S_IFMT) >> bindings::S_DT_SHIFT; + Self::try_from(dt_value).unwrap_or(Self::Unknown) + } +} + impl From<&inode::Type> for DirEntryType { fn from(value: &inode::Type) -> Self { match value { From caa99ea85e2912a0d69cf5764cd482009634dec4 Mon Sep 17 00:00:00 2001 From: lsig Date: Sat, 29 Nov 2025 14:33:34 -0500 Subject: [PATCH 033/131] [ezfs] file type, fix lifetime issue --- fs/rustezfs/ezfs.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 6dc55a2236eb54..6f67056f992b19 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -253,11 +253,10 @@ impl file::Operations for RustEzFs { DirEntryStore::from_bytes(&mapped[..size_of::()]).ok_or(EIO)?; pr_info!("found dir_entries"); - let inode_store = { - let offset = EZFS_INODE_STORE_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE; - let mapped_inode_store = h.mapper.mapped_folio(offset.try_into()?)?; - InodeStore::from_bytes(&mapped_inode_store[..size_of::()]).ok_or(EIO)? - }; + let inode_store_offset = EZFS_INODE_STORE_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE; + let mapped_inode_store = h.mapper.mapped_folio(inode_store_offset.try_into()?)?; + let inode_store = + InodeStore::from_bytes(&mapped_inode_store[..size_of::()]).ok_or(EIO)?; let active_entries = dir_entries .iter() From d2881f7fe9576df41ebb0098545d0c18659f57d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Sat, 29 Nov 2025 14:55:01 -0500 Subject: [PATCH 034/131] add address_space_operations to inodes --- rust/kernel/address_space.rs | 65 ++++++++++++++++++++++++++++++++++++ rust/kernel/inode.rs | 9 +++++ rust/kernel/lib.rs | 1 + 3 files changed, 75 insertions(+) create mode 100644 rust/kernel/address_space.rs diff --git a/rust/kernel/address_space.rs b/rust/kernel/address_space.rs new file mode 100644 index 00000000000000..2772cffbf66528 --- /dev/null +++ b/rust/kernel/address_space.rs @@ -0,0 +1,65 @@ +use crate::{error::{from_result, Result}, fs::file::File, fs::FileSystem, folio::Folio, folio::PageCache, types::Locked}; +use core::marker::PhantomData; +use crate::prelude::EIO; +use macros::vtable; + +/// Operations implemented by address space +#[vtable] +pub trait Operations { + /// File system that these operations are compatible with. + type FileSystem: FileSystem + ?Sized; + + fn read_folio( + file: Option<&File>, + // folio: Locked<&Folio>>, + folio: &Folio>, + ) -> Result; +} + +/// Represents address space operations. +pub struct Ops( + pub(crate) *const bindings::address_space_operations, + pub(crate) PhantomData, +); + + +impl Ops { + + pub const fn new + ?Sized>() -> Self { + struct Table(PhantomData); + impl Table { + + const TABLE: bindings::address_space_operations = bindings::address_space_operations { + read_folio: Some(Self::read_folio_callback), + writepages: None, + dirty_folio: None, + readahead: None, + write_begin: None, + write_end: None, + bmap: None, + invalidate_folio: None, + release_folio: None, + free_folio: None, + direct_IO: None, + migrate_folio: None, + launder_folio: None, + is_partially_uptodate: None, + is_dirty_writeback: None, + error_remove_folio: None, + swap_activate: None, + swap_deactivate: None, + swap_rw: None, + }; + + extern "C" fn read_folio_callback( + file_ptr: *mut bindings::file, + folio_ptr: *mut bindings::folio, + ) -> i32 { + from_result(|| { + Err(EIO) + }) + } + } + Self(&Table::::TABLE, PhantomData) + } +} diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index e8602ec9a18ee0..10448fe0e1542c 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -6,6 +6,7 @@ use macros::vtable; use crate::dentry::{self, DEntry}; use crate::error::{from_err_ptr, Result}; use crate::folio::{self, Folio}; +use crate::address_space; use crate::fs::{self, mode, Registration}; use crate::fs::{file, PageOffset, UnspecifiedFS}; use crate::mem_cache::MemCache; @@ -444,6 +445,14 @@ impl New { inode.__bindgen_anon_3.i_fop = fops.inner; self } + + /// Sets the address space operations on this new inode. + pub fn set_aops(&mut self, aops: address_space::Ops) -> &mut Self { + // SAFETY: By the type invariants, it's ok to modify the inode. + let inode = unsafe { self.0.as_mut() }; + inode.i_data.a_ops = aops.0; + self + } } impl Drop for New { diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index fd660fd7dd911d..90cb4f61b25b6d 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -99,6 +99,7 @@ pub mod fs; pub mod id_pool; pub mod init; pub mod inode; +pub mod address_space; pub mod io; pub mod ioctl; pub mod iov; From 78e9c2ea24d2efee60e0287e31a26cd8a4288070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Sun, 30 Nov 2025 16:02:48 -0500 Subject: [PATCH 035/131] (temporarily) suppress some warnings --- rust/kernel/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 90cb4f61b25b6d..e277fca0a2aedb 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -12,6 +12,8 @@ //! do so first instead of bypassing this crate. #![no_std] +#![allow(missing_docs)] +#![allow(unused)] // // Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on // the unstable features in use. From f03ec8711f53b9a7dea4e86f3f8c02eb197b632b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Sun, 30 Nov 2025 16:04:00 -0500 Subject: [PATCH 036/131] add folio and iomap bindings --- rust/bindings/bindings_helper.h | 1 + rust/helpers/page.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 9d832ea432ac44..30f0b50c0743c7 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/helpers/page.c b/rust/helpers/page.c index 132f060e70cd3a..f126c5f66a2fa3 100644 --- a/rust/helpers/page.c +++ b/rust/helpers/page.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 +#include "linux/pagemap.h" #include #include #include @@ -40,6 +41,16 @@ bool rust_helper_folio_test_highmem(struct folio *folio) return folio_test_highmem(folio); } +void rust_helper_folio_lock(struct folio *folio) +{ + return folio_lock(folio); +} + +void rust_helper_folio_unlock(struct folio *folio) +{ + return folio_unlock(folio); +} + #ifndef NODE_NOT_IN_PAGE_FLAGS int rust_helper_page_to_nid(const struct page *page) { From 3f3ddb827fb6d9d11f8fb467a40d41ecb3b4e288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Sun, 30 Nov 2025 16:06:32 -0500 Subject: [PATCH 037/131] let address_space::Ops call FS specific read_iter --- rust/kernel/address_space.rs | 48 ++++++++++++++++++++++++++++-------- rust/kernel/folio.rs | 15 ++++++++++- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/rust/kernel/address_space.rs b/rust/kernel/address_space.rs index 2772cffbf66528..f87264657fd190 100644 --- a/rust/kernel/address_space.rs +++ b/rust/kernel/address_space.rs @@ -1,6 +1,19 @@ -use crate::{error::{from_result, Result}, fs::file::File, fs::FileSystem, folio::Folio, folio::PageCache, types::Locked}; +//! File system address spaces. +//! +//! This module allows Rust code implement address space operations. +//! +//! C headers: [`include/linux/fs.h`](srctree/include/linux/fs.h) + +use crate::pr_info; +use crate::{ + error::{from_result, Result}, + folio::Folio, + folio::PageCache, + fs::file::File, + fs::FileSystem, + types::Locked, +}; use core::marker::PhantomData; -use crate::prelude::EIO; use macros::vtable; /// Operations implemented by address space @@ -11,8 +24,7 @@ pub trait Operations { fn read_folio( file: Option<&File>, - // folio: Locked<&Folio>>, - folio: &Folio>, + folio: Locked<&Folio>>, ) -> Result; } @@ -22,15 +34,16 @@ pub struct Ops( pub(crate) PhantomData, ); - -impl Ops { - +impl Ops { pub const fn new + ?Sized>() -> Self { struct Table(PhantomData); impl Table { - const TABLE: bindings::address_space_operations = bindings::address_space_operations { - read_folio: Some(Self::read_folio_callback), + read_folio: if T::HAS_READ_FOLIO { + Some(Self::read_folio_callback) + } else { + None + }, writepages: None, dirty_folio: None, readahead: None, @@ -56,7 +69,22 @@ impl Ops { folio_ptr: *mut bindings::folio, ) -> i32 { from_result(|| { - Err(EIO) + pr_info!("RUSTEZFS: in read_folio_callback\n"); + + let file = if file_ptr.is_null() { + None + } else { + // SAFETY: The C API guarantees that `file_ptr` is a valid file if non-null. + Some(unsafe { File::from_raw_file(file_ptr) }) + }; + + // SAFETY: The C API guarantees that `folio_ptr` is a valid folio. + let folio = unsafe { Folio::from_raw(folio_ptr) }; + + // SAFETY: The C contract guarantees that the folio is valid and locked, with + // ownership of the lock transferred to the callee (this function). + T::read_folio(file, unsafe { Locked::new(folio) })?; + Ok(0) }) } } diff --git a/rust/kernel/folio.rs b/rust/kernel/folio.rs index c67c0cde02c430..d4dbf4973ecf95 100644 --- a/rust/kernel/folio.rs +++ b/rust/kernel/folio.rs @@ -4,7 +4,7 @@ use crate::{ error::Result, fs::FileSystem, prelude::EDOM, - types::{ARef, AlwaysRefCounted, Opaque}, + types::{Lockable, Locked, ARef, AlwaysRefCounted, Opaque}, }; /// The type of a [`Folio`] is unspecified. @@ -185,3 +185,16 @@ impl Drop for MapGuard<'_> { unsafe { bindings::kunmap(self.page) }; } } + +// SAFETY: `raw_lock` calls folio_lock, which actually locks the folio. +unsafe impl Lockable for Folio { + fn raw_lock(&self) { + // SAFETY: The folio is valid because the shared reference implies a non-zero refcount. + unsafe { bindings::folio_lock(self.0.get()) } + } + + unsafe fn unlock(&self) { + // SAFETY: The safety requirements guarantee that the folio is locked. + unsafe { bindings::folio_unlock(self.0.get()) } + } +} From babf6d28898efd280e5b077cf2deefc1f5521c2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Sun, 30 Nov 2025 16:11:21 -0500 Subject: [PATCH 038/131] add generic_file_read_iter to file::Ops --- rust/kernel/fs/file.rs | 49 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index 90a61d96350904..64155870926e45 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -12,15 +12,18 @@ use macros::vtable; use crate::{ bindings, cred::Credential, - error::{code::*, from_result, to_result, Error, Result}, + error::{Error, Result, code::*, from_result, to_result}, fmt, - fs::{FileSystem, Offset, UnspecifiedFS}, + fs::{FileSystem, Kiocb, Offset, UnspecifiedFS}, inode::{self, INode, Ino}, + iov::IovIterDest, kernel::dentry::DEntry, sync::aref::{ARef, AlwaysRefCounted}, - types::{Locked, NotThreadSafe, Opaque}, + types::{ForeignOwnable, Locked, NotThreadSafe, Opaque}, user, }; + +use crate::pr_info; use core::{marker::PhantomData, mem::ManuallyDrop, ptr}; /// Flags associated with a [`File`]. @@ -557,6 +560,11 @@ pub trait Operations { Err(EINVAL) } + + fn read_iter(_kiocb: Kiocb<'_, ::Data>, _iov: &mut IovIterDest<'_>) -> Result { + Err(EINVAL) + } + /// Seeks the file to the given offset. fn seek(_file: &File, _offset: Offset, _whence: Whence) -> Result { Err(EINVAL) @@ -606,7 +614,8 @@ impl Ops { None }, write: None, - read_iter: None, + read_iter: Some(Self::read_iter_callback), + // read_iter: Some(unsafe {bindings::generic_file_read_iter}), write_iter: None, iopoll: None, iterate_shared: if T::HAS_READ_DIR { @@ -675,6 +684,38 @@ impl Ops { }) } + // /// # Safety + // /// + // /// `kiocb` must be correspond to a valid file that is associated with a + // /// `T`. `iter` must be a valid `struct iov_iter` for writing. + // unsafe extern "C" fn read_iter_callback( + // kiocb: *mut bindings::kiocb, + // iter: *mut bindings::iov_iter, + // ) -> isize { + // // SAFETY: The caller provides a valid `struct kiocb` associated with a + // // `MiscDeviceRegistration` file. + // let kiocb = unsafe { Kiocb::from_raw(kiocb) }; + // // SAFETY: This is a valid `struct iov_iter` for writing. + // let iov = unsafe { IovIterDest::from_raw(iter) }; + // + // match T::read_iter(kiocb, iov) { + // Ok(res) => res as isize, + // Err(err) => err.to_errno() as isize, + // } + // } + + /// # Safety + /// + /// `kiocb` must be correspond to a valid file that is associated with a + /// `T`. `iter` must be a valid `struct iov_iter` for writing. + unsafe extern "C" fn read_iter_callback( + kiocb: *mut bindings::kiocb, + iter: *mut bindings::iov_iter, + ) -> isize { + pr_info!("read_iter_callback\n"); + return unsafe {bindings::generic_file_read_iter(kiocb, iter)}; + } + unsafe extern "C" fn read_dir_callback( file_ptr: *mut bindings::file, ctx_ptr: *mut bindings::dir_context, From f144a0b15ca67361e7baba2eeee537eba95476f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Sun, 30 Nov 2025 16:12:43 -0500 Subject: [PATCH 039/131] add iomap::Ops that implement own aops --- rust/kernel/iomap.rs | 225 +++++++++++++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + 2 files changed, 226 insertions(+) create mode 100644 rust/kernel/iomap.rs diff --git a/rust/kernel/iomap.rs b/rust/kernel/iomap.rs new file mode 100644 index 00000000000000..9029a0b3df83f0 --- /dev/null +++ b/rust/kernel/iomap.rs @@ -0,0 +1,225 @@ +//! File system io maps. +//! +//! This module allows Rust code to use iomaps to implement filesystems. +//! +//! C headers: [`include/linux/iomap.h`](srctree/include/linux/iomap.h) + +use super::address_space; +use crate::pr_info; +use crate::prelude::EIO; +use crate::{ + error::{from_result, Result}, + folio::Folio, + folio::PageCache, + fs::file::File, + fs::Offset, + fs::FileSystem, + types::Locked, +}; + +use crate::inode::INode; +use core::marker::PhantomData; +use core::mem; +use macros::vtable; +use uapi::writeback_control; + + +/// A map from address space to block device. +#[repr(transparent)] +pub struct Map<'a>(pub bindings::iomap, PhantomData<&'a ()>); + +impl<'a> Map<'a> { + // /// Sets the map type. + // pub fn set_type(&mut self, t: Type) -> &mut Self { + // self.0.type_ = t as u16; + // self + // } + // + // /// Sets the file offset, in bytes. + // pub fn set_offset(&mut self, v: Offset) -> &mut Self { + // self.0.offset = v; + // self + // } + // + // /// Sets the length of the mapping, in bytes. + // pub fn set_length(&mut self, len: u64) -> &mut Self { + // self.0.length = len; + // self + // } + // + // /// Sets the mapping flags. + // /// + // /// Values come from the [`map_flags`] module. + // pub fn set_flags(&mut self, flags: u16) -> &mut Self { + // self.0.flags = flags; + // self + // } + // + // /// Sets the disk offset of the mapping, in bytes. + // pub fn set_addr(&mut self, addr: u64) -> &mut Self { + // self.0.addr = addr; + // self + // } + // + // /// Sets the block device of the mapping. + // pub fn set_bdev(&mut self, bdev: Option<&'a block::Device>) -> &mut Self { + // self.0.bdev = if let Some(b) = bdev { + // b.0.get() + // } else { + // core::ptr::null_mut() + // }; + // self + // } +} + +/// Operations implemented by iomap users. +pub trait Operations { + /// File system that these operations are compatible with. + type FileSystem: FileSystem + ?Sized; + + /// Returns the existing mapping at `pos`, or reserves space starting at `pos` for up to + /// `length`, as long as it can be done as a single mapping. The actual length is returned in + /// `iomap`. + /// + /// The values of `flags` come from the [`flags`] module. + fn begin<'a>( + inode: &'a INode, + pos: Offset, + length: Offset, + flags: u32, + map: &mut Map<'a>, + srcmap: &mut Map<'a>, + ) -> Result; + + /// Commits and/or unreserves space previously allocated using [`Operations::begin`]. `writte`n + /// indicates the length of the successful write operation which needs to be commited, while + /// the rest needs to be unreserved. `written` might be zero if no data was written. + /// + /// The values of `flags` come from the [`flags`] module. + fn end<'a>( + _inode: &'a INode, + _pos: Offset, + _length: Offset, + _written: isize, + _flags: u32, + _map: &Map<'a>, + ) -> Result { + Ok(()) + } +} + + +/// Returns address space oprerations backed by iomaps. +pub const fn aops() -> address_space::Ops { + struct Table(PhantomData); + impl Table { + const MAP_TABLE: bindings::iomap_ops = bindings::iomap_ops { + iomap_begin: Some(Self::iomap_begin_callback), + iomap_end: Some(Self::iomap_end_callback), + }; + + const WRITEBACK_TABLE: bindings::iomap_writeback_ops = bindings::iomap_writeback_ops { + writeback_range: None, + writeback_submit: None, + }; + + extern "C" fn iomap_begin_callback( + inode_ptr: *mut bindings::inode, + pos: Offset, + length: Offset, + flags: u32, + map: *mut bindings::iomap, + srcmap: *mut bindings::iomap, + ) -> i32 { + from_result(|| { + // SAFETY: The C API guarantees that `inode_ptr` is a valid inode. + let inode = unsafe { INode::from_raw(inode_ptr) }; + T::begin( + inode, + pos, + length, + flags, + // SAFETY: The C API guarantees that `map` is valid for write. + unsafe { &mut *map.cast::>() }, + // SAFETY: The C API guarantees that `srcmap` is valid for write. + unsafe { &mut *srcmap.cast::>() }, + )?; + Ok(0) + }) + } + + extern "C" fn iomap_end_callback( + inode_ptr: *mut bindings::inode, + pos: Offset, + length: Offset, + written: isize, + flags: u32, + map: *mut bindings::iomap, + ) -> i32 { + from_result(|| { + // SAFETY: The C API guarantees that `inode_ptr` is a valid inode. + let inode = unsafe { INode::from_raw(inode_ptr) }; + // SAFETY: The C API guarantees that `map` is valid for read. + T::end(inode, pos, length, written, flags, unsafe { + &*map.cast::>() + })?; + Ok(0) + }) + } + + const TABLE: bindings::address_space_operations = bindings::address_space_operations { + read_folio: Some(Self::read_folio_callback), + writepages: Some(Self::writepages_callback), + dirty_folio: Some(bindings::iomap_dirty_folio), + // readahead: Some(Self::readahead_callback), + readahead: None, + write_begin: None, + write_end: None, + // bmap: Some(Self::bmap_callback), + bmap: None, + invalidate_folio: Some(bindings::iomap_invalidate_folio), + release_folio: Some(bindings::iomap_release_folio), + free_folio: None, + // direct_IO: Some(bindings::noop_direct_IO), + direct_IO: None, + migrate_folio: None, + launder_folio: None, + is_partially_uptodate: None, + is_dirty_writeback: None, + error_remove_folio: None, + swap_activate: None, + swap_deactivate: None, + swap_rw: None, + }; + + extern "C" fn read_folio_callback( + _file: *mut bindings::file, + folio: *mut bindings::folio, + ) -> i32 { + // SAFETY: `folio` is just forwarded from C and `Self::MAP_TABLE` is always valid. + unsafe { bindings::iomap_read_folio(folio, &Self::MAP_TABLE) } + } + + + extern "C" fn writepages_callback(_mapping: *mut bindings::address_space, _wbc: *mut bindings::writeback_control) -> i32 { + // Safety: iomap docs say wpc must be zero-initialized. + let mut wpc: bindings::iomap_writepage_ctx = unsafe {mem::zeroed()}; + wpc.inode = unsafe { (*_mapping).host }; // struct inode *host + wpc.wbc = _wbc; + wpc.ops = &Self::WRITEBACK_TABLE; + + unsafe {bindings::iomap_writepages(&mut wpc)} + } + + extern "C" fn readahead_callback(rac: *mut bindings::readahead_control) { + // SAFETY: `rac` is just forwarded from C and `Self::MAP_TABLE` is always valid. + unsafe { bindings::iomap_readahead(rac, &Self::MAP_TABLE) } + } + + extern "C" fn bmap_callback(mapping: *mut bindings::address_space, block: u64) -> u64 { + // SAFETY: `mapping` is just forwarded from C and `Self::MAP_TABLE` is always valid. + unsafe { bindings::iomap_bmap(mapping, block, &Self::MAP_TABLE) } + } + } + address_space::Ops(&Table::::TABLE, PhantomData) +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index e277fca0a2aedb..b843bda0d39afd 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -101,6 +101,7 @@ pub mod fs; pub mod id_pool; pub mod init; pub mod inode; +pub mod iomap; pub mod address_space; pub mod io; pub mod ioctl; From dbd7ad2e14f4ef6f8fc36e8c782e8c5c4c3edabf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Sun, 30 Nov 2025 22:00:50 -0500 Subject: [PATCH 040/131] use generic_mmap and .._splice_read --- rust/kernel/fs/file.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index 64155870926e45..38b84cf6b624c9 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -627,7 +627,7 @@ impl Ops { unlocked_ioctl: None, fop_flags: 0, compat_ioctl: None, - mmap: None, + mmap: Some(bindings::generic_file_mmap), mmap_prepare: None, open: None, flush: None, @@ -639,7 +639,7 @@ impl Ops { check_flags: None, flock: None, splice_write: None, - splice_read: None, + splice_read: Some(bindings::filemap_splice_read), splice_eof: None, setlease: None, fallocate: None, From 783d244467ce1fdec8e1abffada4dd3eac60e7bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Sun, 30 Nov 2025 22:01:48 -0500 Subject: [PATCH 041/131] add sb and inode getters --- fs/rustezfs/sb.rs | 2 +- rust/kernel/inode.rs | 7 ++++++- rust/kernel/sb.rs | 5 +++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index 8eea85de484ea3..3637cdfa3ad8c8 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -27,7 +27,7 @@ pub(crate) struct EzfsSuperblockDisk { } impl EzfsSuperblockDisk { - pub fn magic(&self) -> u64 { + pub(crate) fn magic(&self) -> u64 { self.data.magic } } diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index 10448fe0e1542c..ca0374b127edf2 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -3,10 +3,10 @@ use core::mem::{ManuallyDrop, MaybeUninit}; use macros::vtable; +use crate::address_space; use crate::dentry::{self, DEntry}; use crate::error::{from_err_ptr, Result}; use crate::folio::{self, Folio}; -use crate::address_space; use crate::fs::{self, mode, Registration}; use crate::fs::{file, PageOffset, UnspecifiedFS}; use crate::mem_cache::MemCache; @@ -97,6 +97,11 @@ impl INode { unsafe { SuperBlock::from_raw((*self.0.get()).i_sb) } } + pub fn blocks(&self) -> u64 { + // SAFETY: this is ok + unsafe { (*self.0.get()).i_blocks } + } + /// Returns the data associated with the inode. pub fn data(&self) -> &T::INodeData { if T::IS_UNSPECIFIED { diff --git a/rust/kernel/sb.rs b/rust/kernel/sb.rs index 51eb3fc33a3996..332ba404dc22f3 100644 --- a/rust/kernel/sb.rs +++ b/rust/kernel/sb.rs @@ -83,6 +83,11 @@ impl SuperBlock { // valid `s_bdev` that remains valid while the superblock (`self`) is valid. unsafe { block::Device::from_raw((*self.0.get()).s_bdev) } } + + pub fn blocksize_bits(&self) -> u8 { + // SAFETY: This should be fine?? + unsafe {(*self.0.get()).s_blocksize_bits} + } } impl SuperBlock { From c6f74bbf80290dddee7cdb84722b576572667b3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Sun, 30 Nov 2025 22:01:59 -0500 Subject: [PATCH 042/131] add iomap Types, flags and setters --- rust/kernel/iomap.rs | 171 ++++++++++++++++++++++++++++++++----------- 1 file changed, 130 insertions(+), 41 deletions(-) diff --git a/rust/kernel/iomap.rs b/rust/kernel/iomap.rs index 9029a0b3df83f0..ceb2077759010b 100644 --- a/rust/kernel/iomap.rs +++ b/rust/kernel/iomap.rs @@ -15,6 +15,7 @@ use crate::{ fs::Offset, fs::FileSystem, types::Locked, + block, }; use crate::inode::INode; @@ -23,54 +24,142 @@ use core::mem; use macros::vtable; use uapi::writeback_control; +/// The type of mapping. +/// +/// This is used in [`Map`]. +#[repr(u16)] +pub enum Type { + /// No blocks allocated, need allocation. + Hole = bindings::IOMAP_HOLE as u16, + + /// Delayed allocation blocks. + DelAlloc = bindings::IOMAP_DELALLOC as u16, + + /// Blocks allocated at the given address. + Mapped = bindings::IOMAP_MAPPED as u16, + + /// Blocks allocated at the given address in unwritten state. + Unwritten = bindings::IOMAP_UNWRITTEN as u16, + + /// Data inline in the inode. + Inline = bindings::IOMAP_INLINE as u16, +} + + +/// Flags usable in [`Map`], in [`Map::set_flags`] in particular. +pub mod map_flags { + /// Indicates that the blocks have been newly allocated and need zeroing for areas that no data + /// is copied to. + pub const NEW: u16 = bindings::IOMAP_F_NEW as u16; + + /// Indicates that the inode has uncommitted metadata needed to access written data and + /// requires fdatasync to commit them to persistent storage. This needs to take into account + /// metadata changes that *may* be made at IO completion, such as file size updates from direct + /// IO. + pub const DIRTY: u16 = bindings::IOMAP_F_DIRTY as u16; + + /// Indicates that the blocks are shared, and will need to be unshared as part a write. + pub const SHARED: u16 = bindings::IOMAP_F_SHARED as u16; + + /// Indicates that the iomap contains the merge of multiple block mappings. + pub const MERGED: u16 = bindings::IOMAP_F_MERGED as u16; + + /// Indicates that the file system requires the use of buffer heads for this mapping. + pub const BUFFER_HEAD: u16 = bindings::IOMAP_F_BUFFER_HEAD as u16; + + /// Indicates that the iomap is for an extended attribute extent rather than a file data + /// extent. + pub const XATTR: u16 = bindings::IOMAP_F_XATTR as u16; + + /// Indicates to the iomap_end method that the file size has changed as the result of this + /// write operation. + pub const SIZE_CHANGED: u16 = bindings::IOMAP_F_SIZE_CHANGED as u16; + + /// Indicates that the iomap is not valid any longer and the file range it covers needs to be + /// remapped by the high level before the operation can proceed. + pub const STALE: u16 = bindings::IOMAP_F_STALE as u16; + + /// Flags from 0x1000 up are for file system specific usage. + pub const PRIVATE: u16 = bindings::IOMAP_F_PRIVATE as u16; +} /// A map from address space to block device. #[repr(transparent)] pub struct Map<'a>(pub bindings::iomap, PhantomData<&'a ()>); impl<'a> Map<'a> { - // /// Sets the map type. - // pub fn set_type(&mut self, t: Type) -> &mut Self { - // self.0.type_ = t as u16; - // self - // } - // - // /// Sets the file offset, in bytes. - // pub fn set_offset(&mut self, v: Offset) -> &mut Self { - // self.0.offset = v; - // self - // } - // - // /// Sets the length of the mapping, in bytes. - // pub fn set_length(&mut self, len: u64) -> &mut Self { - // self.0.length = len; - // self - // } - // - // /// Sets the mapping flags. - // /// - // /// Values come from the [`map_flags`] module. - // pub fn set_flags(&mut self, flags: u16) -> &mut Self { - // self.0.flags = flags; - // self - // } - // - // /// Sets the disk offset of the mapping, in bytes. - // pub fn set_addr(&mut self, addr: u64) -> &mut Self { - // self.0.addr = addr; - // self - // } - // - // /// Sets the block device of the mapping. - // pub fn set_bdev(&mut self, bdev: Option<&'a block::Device>) -> &mut Self { - // self.0.bdev = if let Some(b) = bdev { - // b.0.get() - // } else { - // core::ptr::null_mut() - // }; - // self - // } + /// Sets the map type. + pub fn set_type(&mut self, t: Type) -> &mut Self { + self.0.type_ = t as u16; + self + } + + /// Sets the file offset, in bytes. + pub fn set_offset(&mut self, v: Offset) -> &mut Self { + self.0.offset = v; + self + } + + /// Sets the length of the mapping, in bytes. + pub fn set_length(&mut self, len: u64) -> &mut Self { + self.0.length = len; + self + } + + /// Sets the mapping flags. + /// + /// Values come from the [`map_flags`] module. + pub fn set_flags(&mut self, flags: u16) -> &mut Self { + self.0.flags = flags; + self + } + + /// Sets the disk offset of the mapping, in bytes. + pub fn set_addr(&mut self, addr: u64) -> &mut Self { + self.0.addr = addr; + self + } + + /// Sets the block device of the mapping. + pub fn set_bdev(&mut self, bdev: Option<&'a block::Device>) -> &mut Self { + self.0.bdev = if let Some(b) = bdev { + b.0.get() + } else { + core::ptr::null_mut() + }; + self + } } +/// Flags passed to [`Operations::begin`] and [`Operations::end`]. +pub mod flags { + /// Writing, must allocate block. + pub const WRITE: u32 = bindings::IOMAP_WRITE; + + /// Zeroing operation, may skip holes. + pub const ZERO: u32 = bindings::IOMAP_ZERO; + + /// Report extent status, e.g. FIEMAP. + pub const REPORT: u32 = bindings::IOMAP_REPORT; + + /// Mapping for page fault. + pub const FAULT: u32 = bindings::IOMAP_FAULT; + + /// Direct I/O. + pub const DIRECT: u32 = bindings::IOMAP_DIRECT; + + /// Do not block. + pub const NOWAIT: u32 = bindings::IOMAP_NOWAIT; + + /// Only pure overwrites allowed. + pub const OVERWRITE_ONLY: u32 = bindings::IOMAP_OVERWRITE_ONLY; + + /// `unshare_file_range`. + pub const UNSHARE: u32 = bindings::IOMAP_UNSHARE; + + /// DAX mapping. + pub const DAX: u32 = bindings::IOMAP_DAX; +} + /// Operations implemented by iomap users. pub trait Operations { From a72889c6ba6ff3bc295b3fbabe89545966045052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Sun, 30 Nov 2025 22:12:10 -0500 Subject: [PATCH 043/131] ezfs: add iomap_begin and iomap_end --- fs/rustezfs/ezfs.rs | 118 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 110 insertions(+), 8 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index e310143e59386b..5c8ab5ab853ed4 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 //! Log-based filesystem written in Rust +#![allow(unused)] mod defs; mod dir; @@ -10,14 +11,19 @@ use crate::dir::{DirEntryStore, EzfsDirEntry}; use crate::inode::{EzfsInode, InodeStore}; use crate::sb::{EzfsSuperblock, EzfsSuperblockDisk}; use defs::*; +use kernel::bindings; use kernel::dentry; +use kernel::folio::{Folio, PageCache}; +use kernel::fs::Kiocb; use kernel::fs::{file, File, FileSystem, Offset, Registration}; use kernel::inode::{INode, INodeState, Mapper, Params, Type}; +use kernel::iov::IovIterDest; use kernel::prelude::*; use kernel::sb::{New, SuperBlock, Type as SuperType}; use kernel::time::UNIX_EPOCH; use kernel::transmute::FromBytes; -use kernel::types::{ARef, Locked}; +use kernel::types::{ARef, Lockable, Locked}; +use kernel::{address_space, iomap}; use kernel::{c_str, fs, str::CStr}; use core::marker::{PhantomData, Send, Sync}; @@ -45,8 +51,10 @@ impl kernel::InPlaceModule for RustEzFsModule { impl RustEzFs { const DIR_FOPS: file::Ops = file::Ops::new::(); const DIR_IOPS: kernel::inode::Ops = kernel::inode::Ops::new::(); + const AOPS: kernel::address_space::Ops = kernel::iomap::aops::(); fn iget(sb: &SuperBlock, ino: usize) -> Result>> { + pr_info!("iget(ino={ino})\n"); let mut inode = match sb.get_or_create_inode(ino)? { INodeState::Existing(inode) => return Ok(inode), INodeState::Uninitilized(new_inode) => new_inode, @@ -66,12 +74,16 @@ impl RustEzFs { fs::mode::S_IFREG => { inode .set_iops(Self::DIR_IOPS) - .set_fops(file::Ops::generic_ro_file()); - // .set_aops(FILE_AOPS); + // .set_fops(file::Ops::generic_ro_file()) + .set_fops(Self::DIR_FOPS) + .set_aops(Self::AOPS); Type::Reg } fs::mode::S_IFDIR => { - inode.set_iops(Self::DIR_IOPS).set_fops(Self::DIR_FOPS); + inode + .set_iops(Self::DIR_IOPS) + .set_fops(Self::DIR_FOPS) + .set_aops(Self::AOPS); Type::Dir } _ => return Err(ENOENT), @@ -81,7 +93,7 @@ impl RustEzFs { typ, mode: ezfs_inode.mode().try_into()?, size: ezfs_inode.file_size().try_into()?, - blocks: ezfs_inode.nblocks(), + blocks: ezfs_inode.nblocks() * 8, nlink: ezfs_inode.nlink(), uid: ezfs_inode.uid(), gid: ezfs_inode.gid(), @@ -103,6 +115,7 @@ impl FileSystem for RustEzFs { sb: &mut SuperBlock, mapper: Option>, ) -> Result { + pr_info!("fill_super()\n"); let Some(mapper) = mapper else { return Err(EINVAL); }; @@ -117,7 +130,7 @@ impl FileSystem for RustEzFs { return Err(EINVAL); } - let ezfs_sb = KBox::pin_init(EzfsSuperblock::new(disk_sb, mapper), GFP_KERNEL)?; + let ezfs_sb: Self::Data = KBox::pin_init(EzfsSuperblock::new(disk_sb, mapper), GFP_KERNEL)?; sb.set_magic(EZFS_MAGIC_NUMBER); @@ -125,6 +138,7 @@ impl FileSystem for RustEzFs { } fn init_root(sb: &SuperBlock) -> Result> { + pr_info!("init_root()\n"); let inode = Self::iget(sb, EZFS_ROOT_INODE_NUMBER)?; dentry::Root::try_new(inode) } @@ -194,11 +208,21 @@ impl file::Operations for RustEzFs { type FileSystem = Self; fn seek(file: &File, offset: Offset, whence: file::Whence) -> Result { + pr_info!("seek()\n"); file::generic_seek(file, offset, whence) } - fn read(_: &File, _: &mut kernel::user::Writer, _: &mut Offset) -> Result { - Err(EISDIR) + fn read_iter( + _kiocb: Kiocb<'_, ::Data>, + _iov: &mut IovIterDest<'_>, + ) -> Result { + pr_info!("read_iter()\n"); + + // from_result(|| { + // let res = unsafe { bindings::generic_file_read_iter() }; + // }) + + Err(EINVAL) } fn read_dir( @@ -273,6 +297,84 @@ impl file::Operations for RustEzFs { } } +impl iomap::Operations for RustEzFs { + type FileSystem = Self; + + fn begin<'a>( + inode: &'a INode, + pos: Offset, + length: Offset, + flags: u32, + map: &mut iomap::Map<'a>, + srcmap: &mut iomap::Map<'a>, + ) -> Result { + pr_info!("iomap_begin()\n"); + + let sb = inode.super_block(); + let ezfs_sb: Pin<&EzfsSuperblock> = sb.data(); + let ezfs_inode = inode.data(); + + let start_block = (pos >> sb.blocksize_bits()) as u64; + let end_block = ((pos + length - 1) >> sb.blocksize_bits()) as u64; + + let ez_blk_num = ezfs_inode.data_blk_num(); + let ez_blk_count = inode.blocks() / 8; + + let phys = if ez_blk_num > 0 { + ez_blk_num + start_block + } else { + 0 + }; + + let phys_sidx: i64 = if ez_blk_num > 0 { + // SAFETY: phys should always be >= root datablock number + (phys - EZFS_ROOT_DATABLOCK_NUMBER as u64) + .try_into() + .unwrap() + } else { + -1i64 + }; + + // pr_info!("pos={pos}, length={length}\n"); + // pr_info!("block: {start_block}-{end_block}\n"); + // pr_info!("ez_blk_num={ez_blk_num}, start_block={start_block}, ez_blk_count={ez_blk_count}"); + // pr_info!("phys={phys}, (sidx={phys_sidx})\n"); + + map.set_bdev(Some(sb.bdev())) + .set_offset(pos) + .set_length(length as u64); + + if (flags & iomap::flags::WRITE == 0) { + pr_info!("READING\n"); + + if ez_blk_num == 0 || start_block >= ez_blk_count { + map.set_type(iomap::Type::Hole) + .set_addr(bindings::IOMAP_NULL_ADDR as u64); + return Ok(()); + } + map.set_type(iomap::Type::Mapped) + .set_addr(phys << sb.blocksize_bits()); + return Ok(()); + }; + + pr_info!("WRITING\n"); + + Err(EIO) + } + + fn end<'a>( + _inode: &'a INode, + _pos: Offset, + _length: Offset, + _written: isize, + _flags: u32, + _map: &iomap::Map<'a>, + ) -> Result { + pr_info!("iomap_end()\n"); + Ok(()) + } +} + type FsModule = RustEzFsModule; module! { From dcf435c027f4814e05a5ccd7aca63b51a2622f07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Sun, 30 Nov 2025 22:35:02 -0500 Subject: [PATCH 044/131] cleanup fops --- fs/rustezfs/ezfs.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 5c8ab5ab853ed4..3994cc36f479cf 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -49,7 +49,7 @@ impl kernel::InPlaceModule for RustEzFsModule { } impl RustEzFs { - const DIR_FOPS: file::Ops = file::Ops::new::(); + const FILE_FOPS: file::Ops = file::Ops::new::(); const DIR_IOPS: kernel::inode::Ops = kernel::inode::Ops::new::(); const AOPS: kernel::address_space::Ops = kernel::iomap::aops::(); @@ -74,15 +74,14 @@ impl RustEzFs { fs::mode::S_IFREG => { inode .set_iops(Self::DIR_IOPS) - // .set_fops(file::Ops::generic_ro_file()) - .set_fops(Self::DIR_FOPS) + .set_fops(Self::FILE_FOPS) .set_aops(Self::AOPS); Type::Reg } fs::mode::S_IFDIR => { inode .set_iops(Self::DIR_IOPS) - .set_fops(Self::DIR_FOPS) + .set_fops(Self::FILE_FOPS) // TODO: Change this .set_aops(Self::AOPS); Type::Dir } From 58f1820ee12fb201b393449749625b313cb93d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Mon, 1 Dec 2025 11:34:04 -0500 Subject: [PATCH 045/131] have separate dir and file fops --- fs/rustezfs/ezfs.rs | 72 +++++++++++++++++++++--------------------- rust/kernel/fs/file.rs | 69 ++++++++++++++++++++++++++++++++++------ 2 files changed, 95 insertions(+), 46 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 3994cc36f479cf..0f89dc2ca6b9a2 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -49,8 +49,9 @@ impl kernel::InPlaceModule for RustEzFsModule { } impl RustEzFs { - const FILE_FOPS: file::Ops = file::Ops::new::(); - const DIR_IOPS: kernel::inode::Ops = kernel::inode::Ops::new::(); + const FILE_FOPS: file::Ops = file::Ops::new_file::(); + const DIR_FOPS: file::Ops = file::Ops::new_dir::(); + const IOPS: kernel::inode::Ops = kernel::inode::Ops::new::(); const AOPS: kernel::address_space::Ops = kernel::iomap::aops::(); fn iget(sb: &SuperBlock, ino: usize) -> Result>> { @@ -72,22 +73,18 @@ impl RustEzFs { let typ = match mode & fs::mode::S_IFMT { fs::mode::S_IFREG => { - inode - .set_iops(Self::DIR_IOPS) - .set_fops(Self::FILE_FOPS) - .set_aops(Self::AOPS); + inode.set_fops(Self::FILE_FOPS); Type::Reg } fs::mode::S_IFDIR => { - inode - .set_iops(Self::DIR_IOPS) - .set_fops(Self::FILE_FOPS) // TODO: Change this - .set_aops(Self::AOPS); + inode.set_fops(Self::DIR_FOPS); Type::Dir } _ => return Err(ENOENT), }; + inode.set_iops(Self::IOPS).set_aops(Self::AOPS); + inode.init(Params { typ, mode: ezfs_inode.mode().try_into()?, @@ -155,17 +152,19 @@ impl kernel::inode::Operations for RustEzFs { let h = sb.data(); let name = dentry.name(); - pr_info!("looking for file: {:?}", core::str::from_utf8(name)); + pr_info!("lookup(name={:?})\n", core::str::from_utf8(name)); + + // pr_info!("looking for file: {:?}", core::str::from_utf8(name)); if name.len() > EZFS_FILENAME_BUF_SIZE { - pr_info!("dentry name to long: {:?}", core::str::from_utf8(name)); + // pr_info!("dentry name to long: {:?}", core::str::from_utf8(name)); return Err(ENAMETOOLONG); } let ezfs_dir_inode = parent.data(); - pr_info!("ezfs_dir inode number: {:?}", parent.ino()); - pr_info!("ezfs dir inode links: {:?}", ezfs_dir_inode.nlink()); - pr_info!("data_blk_num: {:?}", ezfs_dir_inode.data_blk_num()); + // pr_info!("ezfs_dir inode number: {:?}", parent.ino()); + // pr_info!("ezfs dir inode links: {:?}", ezfs_dir_inode.nlink()); + // pr_info!("data_blk_num: {:?}", ezfs_dir_inode.data_blk_num()); let offset = ezfs_dir_inode .data_blk_num() @@ -177,22 +176,22 @@ impl kernel::inode::Operations for RustEzFs { DirEntryStore::from_bytes(&mapped[..size_of::()]).ok_or(EIO)?; let dir_entry = dir_entries.iter().find(|x| { - pr_info!( - "filename: {:?} = {}\n", - x.filename(), - core::str::from_utf8(x.filename()).unwrap_or("") - ); - - pr_info!( - "dname: {:?} = {}\n", - name, - core::str::from_utf8(name).unwrap_or("") - ); + // pr_info!( + // "filename: {:?} = {}\n", + // x.filename(), + // core::str::from_utf8(x.filename()).unwrap_or("") + // ); + // + // pr_info!( + // "dname: {:?} = {}\n", + // name, + // core::str::from_utf8(name).unwrap_or("") + // ); x.filename() == name && x.is_active() }); let inode = if let Some(entry) = dir_entry { - pr_info!("Inode found: {:?}", entry.inode_no()); + pr_info!("Inode found: {:?}\n", entry.inode_no()); Some(Self::iget(sb, entry.inode_no().try_into()?)?) } else { None @@ -229,12 +228,13 @@ impl file::Operations for RustEzFs { inode: &Locked<&INode, kernel::inode::ReadSem>, emitter: &mut file::DirEmitter, ) -> Result { + pr_info!("read_dir()\n"); let pos: usize = emitter.pos().try_into().map_err(|_| ENOENT)?; - pr_info!("emitter position: {:?}", pos); + // pr_info!("emitter position: {:?}", pos); if pos < 2 { - pr_info!("pos < 2: trying to emit dots"); - pr_info!("file inode: {:?}", file.inode().ino()); + // pr_info!("pos < 2: trying to emit dots"); + // pr_info!("file inode: {:?}", file.inode().ino()); if !emitter.emit_dots(file) { return Ok(()); } @@ -245,7 +245,7 @@ impl file::Operations for RustEzFs { let index = { let disk_pos = pos.checked_sub(2).ok_or(ENOENT)?; - pr_info!("disk position: {:?}", disk_pos); + // pr_info!("disk position: {:?}", disk_pos); if disk_pos % size_of::() != 0 { return Err(ENOENT); @@ -254,27 +254,27 @@ impl file::Operations for RustEzFs { disk_pos / size_of::() }; - pr_info!("emitter index: {:?}", index); + // pr_info!("emitter index: {:?}", index); if index >= EZFS_MAX_CHILDREN { - pr_info!("index higher than max children: {:?}", index); + // pr_info!("index higher than max children: {:?}", index); return Ok(()); } let ezfs_dir_inode = inode.data(); - pr_info!("inode data_blk_num: {:?}", ezfs_dir_inode.data_blk_num()); + // pr_info!("inode data_blk_num: {:?}", ezfs_dir_inode.data_blk_num()); let offset = ezfs_dir_inode .data_blk_num() .checked_mul(EZFS_BLOCK_SIZE as u64) .ok_or(EIO)?; - pr_info!("valid offset: {:?}", offset); + // pr_info!("valid offset: {:?}", offset); let mapped = h.mapper.mapped_folio(offset.try_into()?)?; let dir_entries = DirEntryStore::from_bytes(&mapped[..size_of::()]).ok_or(EIO)?; - pr_info!("found dir_entries"); + // pr_info!("found dir_entries"); let active_entries = dir_entries .iter() diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index 38b84cf6b624c9..e5741e3f8408ac 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -12,7 +12,7 @@ use macros::vtable; use crate::{ bindings, cred::Credential, - error::{Error, Result, code::*, from_result, to_result}, + error::{code::*, from_result, to_result, Error, Result}, fmt, fs::{FileSystem, Kiocb, Offset, UnspecifiedFS}, inode::{self, INode, Ino}, @@ -560,8 +560,10 @@ pub trait Operations { Err(EINVAL) } - - fn read_iter(_kiocb: Kiocb<'_, ::Data>, _iov: &mut IovIterDest<'_>) -> Result { + fn read_iter( + _kiocb: Kiocb<'_, ::Data>, + _iov: &mut IovIterDest<'_>, + ) -> Result { Err(EINVAL) } @@ -598,7 +600,7 @@ impl Ops { } } /// Creates file operations from a type that implements the [`Operations`] trait. - pub const fn new + ?Sized>() -> Self { + pub const fn new_file + ?Sized>() -> Self { struct Table(PhantomData); impl Table { const TABLE: bindings::file_operations = bindings::file_operations { @@ -618,11 +620,7 @@ impl Ops { // read_iter: Some(unsafe {bindings::generic_file_read_iter}), write_iter: None, iopoll: None, - iterate_shared: if T::HAS_READ_DIR { - Some(Self::read_dir_callback) - } else { - None - }, + iterate_shared: None, poll: None, unlocked_ioctl: None, fop_flags: 0, @@ -713,8 +711,59 @@ impl Ops { iter: *mut bindings::iov_iter, ) -> isize { pr_info!("read_iter_callback\n"); - return unsafe {bindings::generic_file_read_iter(kiocb, iter)}; + return unsafe { bindings::generic_file_read_iter(kiocb, iter) }; } + } + Self { + inner: &Table::::TABLE, + _p: PhantomData, + } + } + + /// Creates file operations from a type that implements the [`Operations`] trait. + pub const fn new_dir + ?Sized>() -> Self { + struct Table(PhantomData); + impl Table { + const TABLE: bindings::file_operations = bindings::file_operations { + owner: ptr::null_mut(), + llseek: None, + read: None, + write: None, + read_iter: None, + write_iter: None, + iopoll: None, + iterate_shared: if T::HAS_READ_DIR { + Some(Self::read_dir_callback) + } else { + None + }, + poll: None, + unlocked_ioctl: None, + fop_flags: 0, + compat_ioctl: None, + mmap: None, + mmap_prepare: None, + open: None, + flush: None, + release: None, + fsync: None, + fasync: None, + lock: None, + get_unmapped_area: None, + check_flags: None, + flock: None, + splice_write: None, + splice_read: None, + splice_eof: None, + setlease: None, + fallocate: None, + show_fdinfo: None, + copy_file_range: None, + remap_file_range: None, + fadvise: None, + uring_cmd: None, + uring_cmd_iopoll: None, + }; unsafe extern "C" fn read_dir_callback( file_ptr: *mut bindings::file, From a066ed06144fd038e8ef81d555b8a84833189d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Mon, 1 Dec 2025 12:21:13 -0500 Subject: [PATCH 046/131] ezfs: cleanup --- fs/rustezfs/ezfs.rs | 43 +++++++------------------------------------ 1 file changed, 7 insertions(+), 36 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 0f89dc2ca6b9a2..a8a9dd4f81954f 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 -//! Log-based filesystem written in Rust +//! Easy filesystem written in Rust #![allow(unused)] mod defs; @@ -154,10 +154,7 @@ impl kernel::inode::Operations for RustEzFs { let name = dentry.name(); pr_info!("lookup(name={:?})\n", core::str::from_utf8(name)); - // pr_info!("looking for file: {:?}", core::str::from_utf8(name)); - if name.len() > EZFS_FILENAME_BUF_SIZE { - // pr_info!("dentry name to long: {:?}", core::str::from_utf8(name)); return Err(ENAMETOOLONG); } @@ -175,20 +172,9 @@ impl kernel::inode::Operations for RustEzFs { let dir_entries = DirEntryStore::from_bytes(&mapped[..size_of::()]).ok_or(EIO)?; - let dir_entry = dir_entries.iter().find(|x| { - // pr_info!( - // "filename: {:?} = {}\n", - // x.filename(), - // core::str::from_utf8(x.filename()).unwrap_or("") - // ); - // - // pr_info!( - // "dname: {:?} = {}\n", - // name, - // core::str::from_utf8(name).unwrap_or("") - // ); - x.filename() == name && x.is_active() - }); + let dir_entry = dir_entries + .iter() + .find(|x| x.is_active() && x.filename() == name); let inode = if let Some(entry) = dir_entry { pr_info!("Inode found: {:?}\n", entry.inode_no()); @@ -230,11 +216,8 @@ impl file::Operations for RustEzFs { ) -> Result { pr_info!("read_dir()\n"); let pos: usize = emitter.pos().try_into().map_err(|_| ENOENT)?; - // pr_info!("emitter position: {:?}", pos); if pos < 2 { - // pr_info!("pos < 2: trying to emit dots"); - // pr_info!("file inode: {:?}", file.inode().ino()); if !emitter.emit_dots(file) { return Ok(()); } @@ -245,7 +228,6 @@ impl file::Operations for RustEzFs { let index = { let disk_pos = pos.checked_sub(2).ok_or(ENOENT)?; - // pr_info!("disk position: {:?}", disk_pos); if disk_pos % size_of::() != 0 { return Err(ENOENT); @@ -257,7 +239,6 @@ impl file::Operations for RustEzFs { // pr_info!("emitter index: {:?}", index); if index >= EZFS_MAX_CHILDREN { - // pr_info!("index higher than max children: {:?}", index); return Ok(()); } @@ -266,15 +247,12 @@ impl file::Operations for RustEzFs { let offset = ezfs_dir_inode .data_blk_num() - .checked_mul(EZFS_BLOCK_SIZE as u64) + .checked_mul(EZFS_BLOCK_SIZE as u64) // TODO: better check? .ok_or(EIO)?; - // pr_info!("valid offset: {:?}", offset); - let mapped = h.mapper.mapped_folio(offset.try_into()?)?; let dir_entries = DirEntryStore::from_bytes(&mapped[..size_of::()]).ok_or(EIO)?; - // pr_info!("found dir_entries"); let active_entries = dir_entries .iter() @@ -326,19 +304,12 @@ impl iomap::Operations for RustEzFs { }; let phys_sidx: i64 = if ez_blk_num > 0 { - // SAFETY: phys should always be >= root datablock number - (phys - EZFS_ROOT_DATABLOCK_NUMBER as u64) - .try_into() - .unwrap() + // phys should always be >= root datablock number + (phys - EZFS_ROOT_DATABLOCK_NUMBER as u64).try_into()?; } else { -1i64 }; - // pr_info!("pos={pos}, length={length}\n"); - // pr_info!("block: {start_block}-{end_block}\n"); - // pr_info!("ez_blk_num={ez_blk_num}, start_block={start_block}, ez_blk_count={ez_blk_count}"); - // pr_info!("phys={phys}, (sidx={phys_sidx})\n"); - map.set_bdev(Some(sb.bdev())) .set_offset(pos) .set_length(length as u64); From 3ec59b478694d9c6c37aa722c1c980beec9185a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Mon, 1 Dec 2025 12:34:24 -0500 Subject: [PATCH 047/131] remove `;` so that kernel compiles --- fs/rustezfs/ezfs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index a8a9dd4f81954f..30ae75b762a23d 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -305,7 +305,7 @@ impl iomap::Operations for RustEzFs { let phys_sidx: i64 = if ez_blk_num > 0 { // phys should always be >= root datablock number - (phys - EZFS_ROOT_DATABLOCK_NUMBER as u64).try_into()?; + (phys - EZFS_ROOT_DATABLOCK_NUMBER as u64).try_into()? } else { -1i64 }; From fc7a1ea4e6a8790c3177cb92cdc969ef14a4c9c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Mon, 1 Dec 2025 12:34:37 -0500 Subject: [PATCH 048/131] comment out redundant read_iter --- fs/rustezfs/ezfs.rs | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 30ae75b762a23d..b47def21dc6b1a 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -196,18 +196,21 @@ impl file::Operations for RustEzFs { file::generic_seek(file, offset, whence) } - fn read_iter( - _kiocb: Kiocb<'_, ::Data>, - _iov: &mut IovIterDest<'_>, - ) -> Result { - pr_info!("read_iter()\n"); - - // from_result(|| { - // let res = unsafe { bindings::generic_file_read_iter() }; - // }) - - Err(EINVAL) - } + // TODO: file::Operations currently just calls generic_file_read_iter directly + // we might want to move it here but that requires us being able to have both + // Kiocb and IovIterDest implement ::to_ptr(); Let's do that later + // fn read_iter( + // _kiocb: Kiocb<'_, ::Data>, + // _iov: &mut IovIterDest<'_>, + // ) -> Result { + // pr_info!("read_iter()\n"); + // + // // from_result(|| { + // // let res = unsafe { bindings::generic_file_read_iter() }; + // // }) + // + // Err(EINVAL) + // } fn read_dir( file: &File, From c99126e90d9acb843586ff070ac19dd546edfe4a Mon Sep 17 00:00:00 2001 From: lsig Date: Mon, 1 Dec 2025 16:22:58 -0500 Subject: [PATCH 049/131] [chore] add rust config --- RUSTFS_CONFIG | 9325 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 9325 insertions(+) create mode 100644 RUSTFS_CONFIG diff --git a/RUSTFS_CONFIG b/RUSTFS_CONFIG new file mode 100644 index 00000000000000..8158eb1767e8e6 --- /dev/null +++ b/RUSTFS_CONFIG @@ -0,0 +1,9325 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm64 6.18.0-rc1 Kernel Configuration +# +CONFIG_CC_VERSION_TEXT="Ubuntu clang version 20.1.2 (0ubuntu1)" +CONFIG_GCC_VERSION=0 +CONFIG_CC_IS_CLANG=y +CONFIG_CLANG_VERSION=200102 +CONFIG_AS_IS_LLVM=y +CONFIG_AS_VERSION=200102 +CONFIG_LD_VERSION=0 +CONFIG_LD_IS_LLD=y +CONFIG_LLD_VERSION=200102 +CONFIG_RUSTC_VERSION=109000 +CONFIG_RUST_IS_AVAILABLE=y +CONFIG_RUSTC_LLVM_VERSION=200108 +CONFIG_CC_CAN_LINK=y +CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y +CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y +CONFIG_TOOLS_SUPPORT_RELR=y +CONFIG_CC_HAS_ASM_INLINE=y +CONFIG_CC_HAS_ASSUME=y +CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y +CONFIG_CC_HAS_COUNTED_BY=y +CONFIG_RUSTC_HAS_COERCE_POINTEE=y +CONFIG_RUSTC_HAS_SPAN_FILE=y +CONFIG_RUSTC_HAS_UNNECESSARY_TRANSMUTES=y +CONFIG_RUSTC_HAS_FILE_WITH_NUL=y +CONFIG_PAHOLE_VERSION=129 +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_TABLE_SORT=y +CONFIG_THREAD_INFO_IN_TASK=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +# CONFIG_COMPILE_TEST is not set +# CONFIG_WERROR is not set +CONFIG_LOCALVERSION="-RUSTLFS" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_BUILD_SALT="" +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_ZSTD=y +# CONFIG_KERNEL_GZIP is not set +CONFIG_KERNEL_ZSTD=y +CONFIG_DEFAULT_INIT="" +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_WATCH_QUEUE=y +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_AUDIT=y +CONFIG_HAVE_ARCH_AUDITSYSCALL=y +CONFIG_AUDITSYSCALL=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS=y +CONFIG_GENERIC_IRQ_IPI=y +CONFIG_GENERIC_IRQ_IPI_MUX=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_IRQ_MSI_IOMMU=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +# CONFIG_GENERIC_IRQ_DEBUGFS is not set +CONFIG_GENERIC_IRQ_KEXEC_CLEAR_VM_FORWARD=y +# end of IRQ subsystem + +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_HAVE_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +# CONFIG_NO_HZ_IDLE is not set +CONFIG_NO_HZ_FULL=y +CONFIG_CONTEXT_TRACKING_USER=y +# CONFIG_CONTEXT_TRACKING_USER_FORCE is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +# CONFIG_POSIX_AUX_CLOCKS is not set +# end of Timers subsystem + +CONFIG_BPF=y +CONFIG_HAVE_EBPF_JIT=y +CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y + +# +# BPF subsystem +# +CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT=y +CONFIG_BPF_JIT_ALWAYS_ON=y +CONFIG_BPF_JIT_DEFAULT_ON=y +CONFIG_BPF_UNPRIV_DEFAULT_OFF=y +# CONFIG_BPF_PRELOAD is not set +CONFIG_BPF_LSM=y +# end of BPF subsystem + +CONFIG_PREEMPT_BUILD=y +CONFIG_ARCH_HAS_PREEMPT_LAZY=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +# CONFIG_PREEMPT_LAZY is not set +# CONFIG_PREEMPT_RT is not set +CONFIG_PREEMPT_COUNT=y +CONFIG_PREEMPTION=y +CONFIG_PREEMPT_DYNAMIC=y +CONFIG_SCHED_CORE=y +CONFIG_SCHED_CLASS_EXT=y + +# +# CPU/Task time and stats accounting +# +CONFIG_VIRT_CPU_ACCOUNTING=y +CONFIG_VIRT_CPU_ACCOUNTING_GEN=y +# CONFIG_IRQ_TIME_ACCOUNTING is not set +CONFIG_SCHED_HW_PRESSURE=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_PSI=y +# CONFIG_PSI_DEFAULT_DISABLED is not set +# end of CPU/Task time and stats accounting + +CONFIG_CPU_ISOLATION=y + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +CONFIG_PREEMPT_RCU=y +# CONFIG_RCU_EXPERT is not set +CONFIG_TREE_SRCU=y +CONFIG_TASKS_RCU_GENERIC=y +CONFIG_NEED_TASKS_RCU=y +CONFIG_TASKS_RCU=y +CONFIG_TASKS_RUDE_RCU=y +CONFIG_TASKS_TRACE_RCU=y +CONFIG_RCU_STALL_COMMON=y +CONFIG_RCU_NEED_SEGCBLIST=y +CONFIG_RCU_NOCB_CPU=y +# CONFIG_RCU_NOCB_CPU_DEFAULT_ALL is not set +CONFIG_RCU_LAZY=y +CONFIG_RCU_LAZY_DEFAULT_OFF=y +# end of RCU Subsystem + +CONFIG_IKCONFIG=m +# CONFIG_IKCONFIG_PROC is not set +# CONFIG_IKHEADERS is not set +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +# CONFIG_PRINTK_INDEX is not set +CONFIG_GENERIC_SCHED_CLOCK=y + +# +# Scheduler features +# +CONFIG_UCLAMP_TASK=y +CONFIG_UCLAMP_BUCKETS_COUNT=5 +# end of Scheduler features + +CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y +CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y +CONFIG_CC_HAS_INT128=y +CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough" +CONFIG_GCC10_NO_ARRAY_BOUNDS=y +CONFIG_GCC_NO_STRINGOP_OVERFLOW=y +CONFIG_ARCH_SUPPORTS_INT128=y +CONFIG_NUMA_BALANCING=y +CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y +CONFIG_SLAB_OBJ_EXT=y +CONFIG_CGROUPS=y +CONFIG_PAGE_COUNTER=y +# CONFIG_CGROUP_FAVOR_DYNMODS is not set +CONFIG_MEMCG=y +# CONFIG_MEMCG_V1 is not set +CONFIG_BLK_CGROUP=y +CONFIG_CGROUP_WRITEBACK=y +CONFIG_CGROUP_SCHED=y +CONFIG_GROUP_SCHED_WEIGHT=y +CONFIG_GROUP_SCHED_BANDWIDTH=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_EXT_GROUP_SCHED=y +CONFIG_SCHED_MM_CID=y +CONFIG_UCLAMP_TASK_GROUP=y +CONFIG_CGROUP_PIDS=y +CONFIG_CGROUP_RDMA=y +CONFIG_CGROUP_DMEM=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_HUGETLB=y +CONFIG_CPUSETS=y +# CONFIG_CPUSETS_V1 is not set +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_PERF=y +CONFIG_CGROUP_BPF=y +CONFIG_CGROUP_MISC=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_SOCK_CGROUP_DATA=y +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_TIME_NS=y +CONFIG_IPC_NS=y +CONFIG_USER_NS=y +CONFIG_PID_NS=y +CONFIG_NET_NS=y +CONFIG_CHECKPOINT_RESTORE=y +CONFIG_SCHED_AUTOGROUP=y +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_RD_LZ4=y +CONFIG_RD_ZSTD=y +CONFIG_BOOT_CONFIG=y +# CONFIG_BOOT_CONFIG_FORCE is not set +# CONFIG_BOOT_CONFIG_EMBED is not set +CONFIG_INITRAMFS_PRESERVE_MTIME=y +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_LD_ORPHAN_WARN=y +CONFIG_LD_ORPHAN_WARN_LEVEL="warn" +CONFIG_SYSCTL=y +CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_SYSFS_SYSCALL=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_MULTIUSER=y +CONFIG_SGETMASK_SYSCALL=y +CONFIG_FHANDLE=y +CONFIG_POSIX_TIMERS=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +# CONFIG_BASE_SMALL is not set +CONFIG_FUTEX=y +CONFIG_FUTEX_PI=y +CONFIG_FUTEX_PRIVATE_HASH=y +CONFIG_FUTEX_MPOL=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_IO_URING=y +# CONFIG_IO_URING_MOCK_FILE is not set +CONFIG_ADVISE_SYSCALLS=y +CONFIG_MEMBARRIER=y +CONFIG_KCMP=y +CONFIG_RSEQ=y +# CONFIG_DEBUG_RSEQ is not set +CONFIG_CACHESTAT_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_SELFTEST is not set +CONFIG_KALLSYMS_ALL=y +CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y +CONFIG_ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_GUEST_PERF_EVENTS=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +# end of Kernel Performance Events And Counters + +CONFIG_SYSTEM_DATA_VERIFICATION=y +CONFIG_PROFILING=y +CONFIG_RUST=y +CONFIG_RUSTC_VERSION_TEXT="rustc 1.90.0 (1159e78c4 2025-09-14)" +CONFIG_BINDGEN_VERSION_TEXT="bindgen 0.72.1" +CONFIG_TRACEPOINTS=y + +# +# Kexec and crash features +# +CONFIG_CRASH_RESERVE=y +CONFIG_VMCORE_INFO=y +CONFIG_KEXEC_CORE=y +CONFIG_HAVE_IMA_KEXEC=y +CONFIG_KEXEC=y +CONFIG_KEXEC_FILE=y +CONFIG_KEXEC_SIG=y +CONFIG_KEXEC_IMAGE_VERIFY_SIG=y +# CONFIG_KEXEC_HANDOVER is not set +CONFIG_CRASH_DUMP=y +# end of Kexec and crash features +# end of General setup + +CONFIG_ARM64=y +CONFIG_RUSTC_SUPPORTS_ARM64=y +CONFIG_CLANG_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_64BIT=y +CONFIG_MMU=y +CONFIG_ARM64_CONT_PTE_SHIFT=4 +CONFIG_ARM64_CONT_PMD_SHIFT=4 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=33 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_SMP=y +CONFIG_KERNEL_MODE_NEON=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_PGTABLE_LEVELS=4 +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y + +# +# Platform selection +# +CONFIG_ARCH_ACTIONS=y +CONFIG_ARCH_AIROHA=y +CONFIG_ARCH_SUNXI=y +# CONFIG_ARCH_ALPINE is not set +CONFIG_ARCH_APPLE=y +# CONFIG_ARCH_AXIADO is not set +# CONFIG_ARCH_BCM is not set +CONFIG_ARCH_BERLIN=y +CONFIG_ARCH_BITMAIN=y +CONFIG_ARCH_BLAIZE=y +# CONFIG_ARCH_CIX is not set +# CONFIG_ARCH_EXYNOS is not set +CONFIG_ARCH_K3=y +CONFIG_ARCH_LG1K=y +CONFIG_ARCH_HISI=y +CONFIG_ARCH_KEEMBAY=y +CONFIG_ARCH_MEDIATEK=y +CONFIG_ARCH_MESON=y + +# +# Microchip SoC support +# +CONFIG_ARCH_MICROCHIP=y +# CONFIG_ARCH_LAN969X is not set +CONFIG_ARCH_SPARX5=y +# end of Microchip SoC support + +# CONFIG_ARCH_MMP is not set +CONFIG_ARCH_MVEBU=y +CONFIG_ARCH_NXP=y +CONFIG_ARCH_LAYERSCAPE=y +CONFIG_ARCH_MXC=y +CONFIG_ARCH_S32=y +CONFIG_ARCH_MA35=y +CONFIG_ARCH_NPCM=y +CONFIG_ARCH_PENSANDO=y +CONFIG_ARCH_QCOM=y +CONFIG_ARCH_REALTEK=y +CONFIG_ARCH_RENESAS=y +CONFIG_ARCH_ROCKCHIP=y +CONFIG_ARCH_SEATTLE=y +CONFIG_ARCH_INTEL_SOCFPGA=y +# CONFIG_ARCH_SOPHGO is not set +CONFIG_ARCH_STM32=y +CONFIG_ARCH_SYNQUACER=y +CONFIG_ARCH_TEGRA=y +CONFIG_ARCH_SPRD=y +CONFIG_ARCH_THUNDER=y +CONFIG_ARCH_THUNDER2=y +# CONFIG_ARCH_UNIPHIER is not set +CONFIG_ARCH_VEXPRESS=y +CONFIG_ARCH_VISCONTI=y +CONFIG_ARCH_XGENE=y +CONFIG_ARCH_ZYNQMP=y +# end of Platform selection + +# +# Kernel Features +# + +# +# ARM errata workarounds via the alternatives framework +# +CONFIG_AMPERE_ERRATUM_AC03_CPU_38=y +CONFIG_AMPERE_ERRATUM_AC04_CPU_23=y +CONFIG_ARM64_WORKAROUND_CLEAN_CACHE=y +CONFIG_ARM64_ERRATUM_826319=y +CONFIG_ARM64_ERRATUM_827319=y +CONFIG_ARM64_ERRATUM_824069=y +CONFIG_ARM64_ERRATUM_819472=y +CONFIG_ARM64_ERRATUM_832075=y +CONFIG_ARM64_ERRATUM_834220=y +CONFIG_ARM64_ERRATUM_1742098=y +CONFIG_ARM64_ERRATUM_845719=y +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_ERRATUM_1024718=y +CONFIG_ARM64_ERRATUM_1418040=y +CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT=y +CONFIG_ARM64_ERRATUM_1165522=y +CONFIG_ARM64_ERRATUM_1319367=y +CONFIG_ARM64_ERRATUM_1530923=y +CONFIG_ARM64_WORKAROUND_REPEAT_TLBI=y +CONFIG_ARM64_ERRATUM_2441007=y +CONFIG_ARM64_ERRATUM_1286807=y +CONFIG_ARM64_ERRATUM_1463225=y +CONFIG_ARM64_ERRATUM_1542419=y +CONFIG_ARM64_ERRATUM_1508412=y +CONFIG_ARM64_ERRATUM_2051678=y +CONFIG_ARM64_ERRATUM_2077057=y +CONFIG_ARM64_ERRATUM_2658417=y +CONFIG_ARM64_WORKAROUND_TSB_FLUSH_FAILURE=y +CONFIG_ARM64_ERRATUM_2054223=y +CONFIG_ARM64_ERRATUM_2067961=y +CONFIG_ARM64_ERRATUM_2441009=y +CONFIG_ARM64_ERRATUM_2457168=y +CONFIG_ARM64_ERRATUM_2645198=y +CONFIG_ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD=y +CONFIG_ARM64_ERRATUM_2966298=y +CONFIG_ARM64_ERRATUM_3117295=y +CONFIG_ARM64_ERRATUM_3194386=y +CONFIG_CAVIUM_ERRATUM_22375=y +CONFIG_CAVIUM_ERRATUM_23144=y +CONFIG_CAVIUM_ERRATUM_23154=y +CONFIG_CAVIUM_ERRATUM_27456=y +CONFIG_CAVIUM_ERRATUM_30115=y +CONFIG_CAVIUM_TX2_ERRATUM_219=y +CONFIG_FUJITSU_ERRATUM_010001=y +CONFIG_HISILICON_ERRATUM_161600802=y +CONFIG_HISILICON_ERRATUM_162100801=y +CONFIG_QCOM_FALKOR_ERRATUM_1003=y +CONFIG_QCOM_FALKOR_ERRATUM_1009=y +CONFIG_QCOM_QDF2400_ERRATUM_0065=y +CONFIG_QCOM_FALKOR_ERRATUM_E1041=y +CONFIG_NVIDIA_CARMEL_CNP_ERRATUM=y +CONFIG_ROCKCHIP_ERRATUM_3568002=y +CONFIG_ROCKCHIP_ERRATUM_3588001=y +CONFIG_SOCIONEXT_SYNQUACER_PREITS=y +# end of ARM errata workarounds via the alternatives framework + +CONFIG_ARM64_4K_PAGES=y +# CONFIG_ARM64_16K_PAGES is not set +# CONFIG_ARM64_64K_PAGES is not set +# CONFIG_ARM64_VA_BITS_39 is not set +CONFIG_ARM64_VA_BITS_48=y +# CONFIG_ARM64_VA_BITS_52 is not set +CONFIG_ARM64_VA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_PA_BITS=48 +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_NR_CPUS=512 +CONFIG_HOTPLUG_CPU=y +CONFIG_NUMA=y +CONFIG_NODES_SHIFT=6 +# CONFIG_HZ_100 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +CONFIG_HZ_1000=y +CONFIG_HZ=1000 +CONFIG_SCHED_HRTICK=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_HW_PERF_EVENTS=y +CONFIG_CC_HAVE_SHADOW_CALL_STACK=y +CONFIG_PARAVIRT=y +# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set +CONFIG_ARCH_SUPPORTS_KEXEC=y +CONFIG_ARCH_SUPPORTS_KEXEC_FILE=y +CONFIG_ARCH_SELECTS_KEXEC_FILE=y +CONFIG_ARCH_SUPPORTS_KEXEC_SIG=y +CONFIG_ARCH_SUPPORTS_KEXEC_IMAGE_VERIFY_SIG=y +CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y +CONFIG_ARCH_SUPPORTS_KEXEC_HANDOVER=y +CONFIG_ARCH_SUPPORTS_CRASH_DUMP=y +CONFIG_ARCH_DEFAULT_CRASH_DUMP=y +CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION=y +CONFIG_TRANS_TABLE=y +CONFIG_XEN_DOM0=y +CONFIG_XEN=y +CONFIG_ARCH_FORCE_MAX_ORDER=10 +CONFIG_UNMAP_KERNEL_AT_EL0=y +CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY=y +CONFIG_ARM64_SW_TTBR0_PAN=y +CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_COMPAT=y +CONFIG_KUSER_HELPERS=y +CONFIG_COMPAT_VDSO=y +CONFIG_THUMB2_COMPAT_VDSO=y +# CONFIG_COMPAT_ALIGNMENT_FIXUPS is not set +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y + +# +# ARMv8.1 architectural features +# +CONFIG_ARM64_HW_AFDBM=y +CONFIG_ARM64_PAN=y +CONFIG_ARM64_LSE_ATOMICS=y +CONFIG_ARM64_USE_LSE_ATOMICS=y +# end of ARMv8.1 architectural features + +# +# ARMv8.2 architectural features +# +CONFIG_ARM64_PMEM=y +CONFIG_ARM64_RAS_EXTN=y +CONFIG_ARM64_CNP=y +# end of ARMv8.2 architectural features + +# +# ARMv8.3 architectural features +# +CONFIG_ARM64_PTR_AUTH=y +CONFIG_ARM64_PTR_AUTH_KERNEL=y +CONFIG_CC_HAS_BRANCH_PROT_PAC_RET=y +CONFIG_AS_HAS_CFI_NEGATE_RA_STATE=y +# end of ARMv8.3 architectural features + +# +# ARMv8.4 architectural features +# +CONFIG_ARM64_AMU_EXTN=y +CONFIG_ARM64_TLB_RANGE=y +# end of ARMv8.4 architectural features + +# +# ARMv8.5 architectural features +# +CONFIG_AS_HAS_ARMV8_5=y +CONFIG_ARM64_BTI=y +CONFIG_ARM64_BTI_KERNEL=y +CONFIG_CC_HAS_BRANCH_PROT_PAC_RET_BTI=y +CONFIG_ARM64_E0PD=y +CONFIG_ARM64_AS_HAS_MTE=y +CONFIG_ARM64_MTE=y +# end of ARMv8.5 architectural features + +# +# ARMv8.7 architectural features +# +CONFIG_ARM64_EPAN=y +# end of ARMv8.7 architectural features + +CONFIG_AS_HAS_MOPS=y + +# +# ARMv8.9 architectural features +# +CONFIG_ARM64_POE=y +CONFIG_ARCH_PKEY_BITS=3 +CONFIG_ARM64_HAFT=y +# end of ARMv8.9 architectural features + +# +# ARMv9.4 architectural features +# +CONFIG_ARM64_GCS=y +# end of ARMv9.4 architectural features + +CONFIG_ARM64_SVE=y +CONFIG_ARM64_SME=y +CONFIG_ARM64_PSEUDO_NMI=y +# CONFIG_ARM64_DEBUG_PRIORITY_MASKING is not set +CONFIG_RELOCATABLE=y +CONFIG_RANDOMIZE_BASE=y +CONFIG_RANDOMIZE_MODULE_REGION_FULL=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_STACKPROTECTOR_PER_TASK=y +# CONFIG_UNWIND_PATCH_PAC_INTO_SCS is not set +CONFIG_ARM64_CONTPTE=y +# end of Kernel Features + +# +# Boot options +# +CONFIG_ARM64_ACPI_PARKING_PROTOCOL=y +CONFIG_CMDLINE="console=ttyAMA0" +CONFIG_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_CMDLINE_FORCE is not set +CONFIG_EFI_STUB=y +CONFIG_EFI=y +# CONFIG_COMPRESSED_INSTALL is not set +CONFIG_DMI=y +# end of Boot options + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_SUSPEND_SKIP_SYNC is not set +# CONFIG_HIBERNATION is not set +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_USERSPACE_AUTOSLEEP is not set +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=100 +CONFIG_PM_WAKELOCKS_GC=y +CONFIG_PM=y +CONFIG_PM_DEBUG=y +CONFIG_PM_ADVANCED_DEBUG=y +# CONFIG_PM_TEST_SUSPEND is not set +CONFIG_PM_SLEEP_DEBUG=y +# CONFIG_DPM_WATCHDOG is not set +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y +CONFIG_PM_GENERIC_DOMAINS_SLEEP=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_CPU_PM=y +CONFIG_ENERGY_MODEL=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# end of Power management options + +# +# CPU Power Management +# + +# +# CPU Idle +# +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_IDLE_GOV_TEO=y +CONFIG_DT_IDLE_STATES=y +CONFIG_DT_IDLE_GENPD=y + +# +# ARM CPU Idle Drivers +# +CONFIG_ARM_PSCI_CPUIDLE=y +CONFIG_ARM_PSCI_CPUIDLE_DOMAIN=y +# end of ARM CPU Idle Drivers +# end of CPU Idle + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y + +# +# CPU frequency scaling drivers +# +CONFIG_CPUFREQ_DT=y +# CONFIG_CPUFREQ_DT_RUST is not set +# CONFIG_CPUFREQ_VIRT is not set +CONFIG_CPUFREQ_DT_PLATDEV=y +# CONFIG_ARM_AIROHA_SOC_CPUFREQ is not set +# CONFIG_ARM_APPLE_SOC_CPUFREQ is not set +# CONFIG_ARM_ARMADA_37XX_CPUFREQ is not set +# CONFIG_ARM_ARMADA_8K_CPUFREQ is not set +# CONFIG_ARM_IMX_CPUFREQ_DT is not set +# CONFIG_ARM_MEDIATEK_CPUFREQ is not set +# CONFIG_ARM_MEDIATEK_CPUFREQ_HW is not set +# CONFIG_ARM_QCOM_CPUFREQ_HW is not set +# CONFIG_ARM_SCMI_CPUFREQ is not set +CONFIG_ARM_TEGRA20_CPUFREQ=y +CONFIG_ARM_TEGRA124_CPUFREQ=y +# CONFIG_ARM_TEGRA186_CPUFREQ is not set +# CONFIG_ARM_TEGRA194_CPUFREQ is not set +CONFIG_ARM_TI_CPUFREQ=y +# CONFIG_QORIQ_CPUFREQ is not set +# CONFIG_ACPI_CPPC_CPUFREQ is not set +# end of CPU Frequency scaling +# end of CPU Power Management + +CONFIG_ARCH_SUPPORTS_ACPI=y +CONFIG_ACPI=y +CONFIG_ACPI_GENERIC_GSI=y +CONFIG_ACPI_CCA_REQUIRED=y +CONFIG_ACPI_THERMAL_LIB=y +# CONFIG_ACPI_DEBUGGER is not set +CONFIG_ACPI_SPCR_TABLE=y +CONFIG_ACPI_FPDT=y +CONFIG_ACPI_EC=y +# CONFIG_ACPI_EC_DEBUGFS is not set +CONFIG_ACPI_AC=y +CONFIG_ACPI_BATTERY=y +CONFIG_ACPI_BUTTON=y +# CONFIG_ACPI_VIDEO is not set +CONFIG_ACPI_FAN=y +# CONFIG_ACPI_TAD is not set +CONFIG_ACPI_DOCK=y +CONFIG_ACPI_PROCESSOR_IDLE=y +CONFIG_ACPI_MCFG=y +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_HOTPLUG_CPU=y +CONFIG_ACPI_THERMAL=y +CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y +CONFIG_ACPI_TABLE_UPGRADE=y +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_PCI_SLOT=y +CONFIG_ACPI_CONTAINER=y +CONFIG_ACPI_HOTPLUG_MEMORY=y +CONFIG_ACPI_HED=y +CONFIG_ACPI_BGRT=y +CONFIG_ACPI_REDUCED_HARDWARE_ONLY=y +CONFIG_ACPI_NHLT=y +# CONFIG_ACPI_NFIT is not set +CONFIG_ACPI_NUMA=y +CONFIG_ACPI_HMAT=y +CONFIG_HAVE_ACPI_APEI=y +CONFIG_ACPI_APEI=y +CONFIG_ACPI_APEI_GHES=y +CONFIG_ACPI_APEI_PCIEAER=y +CONFIG_ACPI_APEI_SEA=y +CONFIG_ACPI_APEI_MEMORY_FAILURE=y +# CONFIG_ACPI_APEI_EINJ is not set +# CONFIG_ACPI_APEI_ERST_DEBUG is not set +# CONFIG_ACPI_CONFIGFS is not set +# CONFIG_ACPI_PFRUT is not set +CONFIG_ACPI_IORT=y +CONFIG_ACPI_GTDT=y +CONFIG_ACPI_AGDI=y +CONFIG_ACPI_APMT=y +CONFIG_ACPI_PPTT=y +CONFIG_ACPI_PCC=y +CONFIG_ACPI_FFH=y +# CONFIG_PMIC_OPREGION is not set +CONFIG_ACPI_VIOT=y +CONFIG_ACPI_PRMT=y +CONFIG_KVM_COMMON=y +CONFIG_HAVE_KVM_IRQCHIP=y +CONFIG_HAVE_KVM_IRQ_ROUTING=y +CONFIG_HAVE_KVM_DIRTY_RING=y +CONFIG_HAVE_KVM_DIRTY_RING_ACQ_REL=y +CONFIG_NEED_KVM_DIRTY_RING_WITH_BITMAP=y +CONFIG_KVM_MMIO=y +CONFIG_HAVE_KVM_MSI=y +CONFIG_HAVE_KVM_READONLY_MEM=y +CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y +CONFIG_KVM_VFIO=y +CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y +CONFIG_HAVE_KVM_IRQ_BYPASS=y +CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE=y +CONFIG_VIRT_XFER_TO_GUEST_WORK=y +CONFIG_KVM_GENERIC_HARDWARE_ENABLING=y +CONFIG_KVM_GENERIC_MMU_NOTIFIER=y +CONFIG_KVM_GUEST_MEMFD=y +CONFIG_VIRTUALIZATION=y +CONFIG_KVM=y +# CONFIG_NVHE_EL2_DEBUG is not set +# CONFIG_PTDUMP_STAGE2_DEBUGFS is not set +CONFIG_HAVE_LIVEPATCH=y +# CONFIG_LIVEPATCH is not set +CONFIG_CPU_MITIGATIONS=y +CONFIG_ARCH_HAS_DMA_OPS=y + +# +# General architecture-dependent options +# +CONFIG_ARCH_HAS_SUBPAGE_FAULTS=y +CONFIG_HOTPLUG_SMT=y +CONFIG_ARCH_SUPPORTS_SCHED_SMT=y +CONFIG_ARCH_SUPPORTS_SCHED_CLUSTER=y +CONFIG_ARCH_SUPPORTS_SCHED_MC=y +CONFIG_SCHED_SMT=y +CONFIG_SCHED_CLUSTER=y +CONFIG_SCHED_MC=y +CONFIG_HOTPLUG_CORE_SYNC=y +CONFIG_HOTPLUG_CORE_SYNC_DEAD=y +CONFIG_GENERIC_IRQ_ENTRY=y +CONFIG_KPROBES=y +CONFIG_JUMP_LABEL=y +# CONFIG_STATIC_KEYS_SELFTEST is not set +CONFIG_UPROBES=y +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_KRETPROBES=y +CONFIG_HAVE_IOREMAP_PROT=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y +CONFIG_HAVE_NMI=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_ARCH_HAS_FORTIFY_SOURCE=y +CONFIG_ARCH_HAS_KEEPINITRD=y +CONFIG_ARCH_HAS_SET_MEMORY=y +CONFIG_ARCH_HAS_SET_DIRECT_MAP=y +CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_HAVE_ASM_MODVERSIONS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_RSEQ=y +CONFIG_HAVE_RUST=y +CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_PERF_EVENTS_NMI=y +CONFIG_HAVE_HARDLOCKUP_DETECTOR_PERF=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y +CONFIG_MMU_GATHER_TABLE_FREE=y +CONFIG_MMU_GATHER_RCU_TABLE_FREE=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y +CONFIG_ARCH_HAS_NMI_SAFE_THIS_CPU_OPS=y +CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y +CONFIG_HAVE_CMPXCHG_LOCAL=y +CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_SECCOMP=y +CONFIG_SECCOMP_FILTER=y +# CONFIG_SECCOMP_CACHE_DEBUG is not set +CONFIG_HAVE_ARCH_KSTACK_ERASE=y +CONFIG_HAVE_STACKPROTECTOR=y +CONFIG_STACKPROTECTOR=y +CONFIG_STACKPROTECTOR_STRONG=y +CONFIG_ARCH_SUPPORTS_SHADOW_CALL_STACK=y +CONFIG_SHADOW_CALL_STACK=y +CONFIG_ARCH_SUPPORTS_LTO_CLANG=y +CONFIG_ARCH_SUPPORTS_LTO_CLANG_THIN=y +CONFIG_HAS_LTO_CLANG=y +CONFIG_LTO_NONE=y +# CONFIG_LTO_CLANG_FULL is not set +# CONFIG_LTO_CLANG_THIN is not set +CONFIG_ARCH_SUPPORTS_CFI=y +# CONFIG_CFI is not set +CONFIG_HAVE_CFI_ICALL_NORMALIZE_INTEGERS=y +CONFIG_HAVE_CFI_ICALL_NORMALIZE_INTEGERS_RUSTC=y +CONFIG_HAVE_CONTEXT_TRACKING_USER=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MOVE_PUD=y +CONFIG_HAVE_MOVE_PMD=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_HAVE_ARCH_HUGE_VMAP=y +CONFIG_HAVE_ARCH_HUGE_VMALLOC=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_ARCH_WANT_PMD_MKWRITE=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_ARCH_WANTS_EXECMEM_LATE=y +CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SOFTIRQ_ON_OWN_STACK=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_HAVE_ARCH_MMAP_RND_BITS=y +CONFIG_ARCH_MMAP_RND_BITS=33 +CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16 +CONFIG_HAVE_PAGE_SIZE_4KB=y +CONFIG_PAGE_SIZE_4KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SHIFT=12 +CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT=y +CONFIG_HAVE_RELIABLE_STACKTRACE=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_COMPAT_OLD_SIGACTION=y +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_ARCH_SUPPORTS_RT=y +CONFIG_HAVE_ARCH_VMAP_STACK=y +CONFIG_VMAP_STACK=y +CONFIG_HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET=y +CONFIG_RANDOMIZE_KSTACK_OFFSET=y +CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT=y +CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y +CONFIG_STRICT_KERNEL_RWX=y +CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y +CONFIG_STRICT_MODULE_RWX=y +CONFIG_HAVE_ARCH_COMPILER_H=y +CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y +CONFIG_ARCH_USE_MEMREMAP_PROT=y +# CONFIG_LOCK_EVENT_COUNTS is not set +CONFIG_ARCH_HAS_RELR=y +# CONFIG_RELR is not set +CONFIG_ARCH_HAS_MEM_ENCRYPT=y +CONFIG_ARCH_HAS_CC_PLATFORM=y +CONFIG_HAVE_PREEMPT_DYNAMIC=y +CONFIG_HAVE_PREEMPT_DYNAMIC_KEY=y +CONFIG_ARCH_WANT_LD_ORPHAN_WARN=y +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_ARCH_SUPPORTS_PAGE_TABLE_CHECK=y +CONFIG_ARCH_HAVE_TRACE_MMIO_ACCESS=y +CONFIG_ARCH_HAS_HW_PTE_YOUNG=y +CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG=y +CONFIG_ARCH_HAS_KERNEL_FPU_SUPPORT=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +# end of GCOV-based kernel profiling + +CONFIG_HAVE_GCC_PLUGINS=y +CONFIG_FUNCTION_ALIGNMENT_4B=y +CONFIG_FUNCTION_ALIGNMENT_8B=y +CONFIG_FUNCTION_ALIGNMENT=8 +CONFIG_CC_HAS_SANE_FUNCTION_ALIGNMENT=y +# end of General architecture-dependent options + +CONFIG_RT_MUTEXES=y +CONFIG_MODULE_SIG_FORMAT=y +CONFIG_MODULES=y +# CONFIG_MODULE_DEBUG is not set +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODULE_UNLOAD_TAINT_TRACKING is not set +CONFIG_MODVERSIONS=y +# CONFIG_GENKSYMS is not set +CONFIG_GENDWARFKSYMS=y +CONFIG_ASM_MODVERSIONS=y +CONFIG_EXTENDED_MODVERSIONS=y +CONFIG_BASIC_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_MODULE_SIG_ALL=y +# CONFIG_MODULE_SIG_SHA1 is not set +# CONFIG_MODULE_SIG_SHA256 is not set +# CONFIG_MODULE_SIG_SHA384 is not set +CONFIG_MODULE_SIG_SHA512=y +# CONFIG_MODULE_SIG_SHA3_256 is not set +# CONFIG_MODULE_SIG_SHA3_384 is not set +# CONFIG_MODULE_SIG_SHA3_512 is not set +CONFIG_MODULE_SIG_HASH="sha512" +CONFIG_MODULE_COMPRESS=y +# CONFIG_MODULE_COMPRESS_GZIP is not set +# CONFIG_MODULE_COMPRESS_XZ is not set +CONFIG_MODULE_COMPRESS_ZSTD=y +# CONFIG_MODULE_COMPRESS_ALL is not set +CONFIG_MODULE_DECOMPRESS=y +# CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set +CONFIG_MODPROBE_PATH="/sbin/modprobe" +# CONFIG_TRIM_UNUSED_KSYMS is not set +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_BLOCK=y +CONFIG_BLOCK_LEGACY_AUTOLOAD=y +CONFIG_BLK_RQ_ALLOC_TIME=y +CONFIG_BLK_CGROUP_RWSTAT=y +CONFIG_BLK_DEV_BSG_COMMON=y +CONFIG_BLK_DEV_BSGLIB=y +CONFIG_BLK_DEV_INTEGRITY=y +CONFIG_BLK_DEV_WRITE_MOUNTED=y +CONFIG_BLK_DEV_ZONED=y +CONFIG_BLK_DEV_THROTTLING=y +CONFIG_BLK_WBT=y +CONFIG_BLK_WBT_MQ=y +# CONFIG_BLK_CGROUP_IOLATENCY is not set +CONFIG_BLK_CGROUP_IOCOST=y +CONFIG_BLK_CGROUP_IOPRIO=y +CONFIG_BLK_DEBUG_FS=y +CONFIG_BLK_SED_OPAL=y +CONFIG_BLK_INLINE_ENCRYPTION=y +CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_AIX_PARTITION=y +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +CONFIG_ATARI_PARTITION=y +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_LDM_PARTITION=y +# CONFIG_LDM_DEBUG is not set +CONFIG_SGI_PARTITION=y +CONFIG_ULTRIX_PARTITION=y +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y +CONFIG_SYSV68_PARTITION=y +CONFIG_CMDLINE_PARTITION=y +CONFIG_OF_PARTITION=y +# end of Partition Types + +CONFIG_BLK_PM=y +CONFIG_BLOCK_HOLDER_DEPRECATED=y +CONFIG_BLK_MQ_STACKING=y + +# +# IO Schedulers +# +CONFIG_MQ_IOSCHED_DEADLINE=y +# CONFIG_MQ_IOSCHED_KYBER is not set +# CONFIG_IOSCHED_BFQ is not set +# end of IO Schedulers + +CONFIG_PREEMPT_NOTIFIERS=y +CONFIG_PADATA=y +CONFIG_ASN1=y +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_ARCH_USE_QUEUED_RWLOCKS=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE=y +CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y +CONFIG_FREEZER=y + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y +CONFIG_ARCH_BINFMT_ELF_STATE=y +CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y +CONFIG_ARCH_HAVE_ELF_PROT=y +CONFIG_ARCH_USE_GNU_PROPERTY=y +CONFIG_ELFCORE=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_BINFMT_SCRIPT=y +CONFIG_BINFMT_MISC=m +CONFIG_COREDUMP=y +# end of Executable file formats + +# +# Memory Management options +# +CONFIG_SWAP=y +CONFIG_ZSWAP=y +# CONFIG_ZSWAP_DEFAULT_ON is not set +CONFIG_ZSWAP_SHRINKER_DEFAULT_ON=y +# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_DEFLATE is not set +CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZO=y +# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_842 is not set +# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZ4 is not set +# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZ4HC is not set +# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_ZSTD is not set +CONFIG_ZSWAP_COMPRESSOR_DEFAULT="lzo" +CONFIG_ZSMALLOC=y + +# +# Zsmalloc allocator options +# + +# +# Zsmalloc is a common backend allocator for zswap & zram +# +# CONFIG_ZSMALLOC_STAT is not set +CONFIG_ZSMALLOC_CHAIN_SIZE=8 +# end of Zsmalloc allocator options + +# +# Slab allocator options +# +CONFIG_SLUB=y +CONFIG_KVFREE_RCU_BATCHED=y +# CONFIG_SLUB_TINY is not set +CONFIG_SLAB_MERGE_DEFAULT=y +CONFIG_SLAB_FREELIST_RANDOM=y +CONFIG_SLAB_FREELIST_HARDENED=y +CONFIG_SLAB_BUCKETS=y +# CONFIG_SLUB_STATS is not set +CONFIG_SLUB_CPU_PARTIAL=y +CONFIG_RANDOM_KMALLOC_CACHES=y +# end of Slab allocator options + +CONFIG_SHUFFLE_PAGE_ALLOCATOR=y +# CONFIG_COMPAT_BRK is not set +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_HAVE_GUP_FAST=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_NUMA_KEEP_MEMINFO=y +CONFIG_MEMORY_ISOLATION=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_MEMORY_HOTPLUG=y +# CONFIG_MHP_DEFAULT_ONLINE_TYPE_OFFLINE is not set +CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_AUTO=y +# CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_KERNEL is not set +# CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_MOVABLE is not set +CONFIG_MEMORY_HOTREMOVE=y +CONFIG_MHP_MEMMAP_ON_MEMORY=y +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_SPLIT_PTE_PTLOCKS=y +CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y +CONFIG_SPLIT_PMD_PTLOCKS=y +CONFIG_MEMORY_BALLOON=y +CONFIG_BALLOON_COMPACTION=y +CONFIG_COMPACTION=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +CONFIG_PAGE_REPORTING=y +CONFIG_MIGRATION=y +CONFIG_DEVICE_MIGRATION=y +CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION=y +CONFIG_ARCH_ENABLE_THP_MIGRATION=y +CONFIG_CONTIG_ALLOC=y +CONFIG_PCP_BATCH_SCALE_MAX=5 +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_MMU_NOTIFIER=y +CONFIG_KSM=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y +CONFIG_MEMORY_FAILURE=y +# CONFIG_HWPOISON_INJECT is not set +CONFIG_ARCH_WANTS_THP_SWAP=y +# CONFIG_PERSISTENT_HUGE_ZERO_FOLIO is not set +CONFIG_MM_ID=y +CONFIG_TRANSPARENT_HUGEPAGE=y +# CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS is not set +CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y +# CONFIG_TRANSPARENT_HUGEPAGE_NEVER is not set +CONFIG_THP_SWAP=y +# CONFIG_READ_ONLY_THP_FOR_FS is not set +# CONFIG_NO_PAGE_MAPCOUNT is not set +CONFIG_PAGE_MAPCOUNT=y +CONFIG_PGTABLE_HAS_HUGE_LEAVES=y +CONFIG_ARCH_SUPPORTS_HUGE_PFNMAP=y +CONFIG_ARCH_SUPPORTS_PMD_PFNMAP=y +CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y +CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y +CONFIG_USE_PERCPU_NUMA_NODE_ID=y +CONFIG_HAVE_SETUP_PER_CPU_AREA=y +CONFIG_CMA=y +# CONFIG_CMA_DEBUGFS is not set +CONFIG_CMA_SYSFS=y +CONFIG_CMA_AREAS=7 +CONFIG_PAGE_BLOCK_MAX_ORDER=10 +CONFIG_GENERIC_EARLY_IOREMAP=y +# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set +CONFIG_PAGE_IDLE_FLAG=y +CONFIG_IDLE_PAGE_TRACKING=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_ARCH_HAS_CURRENT_STACK_POINTER=y +CONFIG_ARCH_HAS_ZONE_DMA_SET=y +CONFIG_ZONE_DMA=y +CONFIG_ZONE_DMA32=y +CONFIG_ZONE_DEVICE=y +CONFIG_GET_FREE_REGION=y +CONFIG_DEVICE_PRIVATE=y +CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y +CONFIG_ARCH_HAS_PKEYS=y +CONFIG_ARCH_USES_PG_ARCH_2=y +CONFIG_ARCH_USES_PG_ARCH_3=y +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_PERCPU_STATS is not set +# CONFIG_GUP_TEST is not set +# CONFIG_DMAPOOL_TEST is not set +CONFIG_ARCH_HAS_PTE_SPECIAL=y +CONFIG_MAPPING_DIRTY_HELPERS=y +CONFIG_MEMFD_CREATE=y +CONFIG_SECRETMEM=y +CONFIG_ANON_VMA_NAME=y +CONFIG_HAVE_ARCH_USERFAULTFD_WP=y +CONFIG_HAVE_ARCH_USERFAULTFD_MINOR=y +CONFIG_USERFAULTFD=y +CONFIG_PTE_MARKER_UFFD_WP=y +CONFIG_LRU_GEN=y +CONFIG_LRU_GEN_ENABLED=y +# CONFIG_LRU_GEN_STATS is not set +CONFIG_LRU_GEN_WALKS_MMU=y +CONFIG_ARCH_SUPPORTS_PER_VMA_LOCK=y +CONFIG_PER_VMA_LOCK=y +CONFIG_LOCK_MM_AND_FIND_VMA=y +CONFIG_IOMMU_MM_DATA=y +CONFIG_EXECMEM=y +CONFIG_NUMA_MEMBLKS=y +# CONFIG_NUMA_EMU is not set +CONFIG_ARCH_HAS_USER_SHADOW_STACK=y + +# +# Data Access Monitoring +# +# CONFIG_DAMON is not set +# end of Data Access Monitoring +# end of Memory Management options + +CONFIG_NET=y +CONFIG_NET_INGRESS=y +CONFIG_NET_EGRESS=y +CONFIG_NET_XGRESS=y +CONFIG_SKB_EXTENSIONS=y +CONFIG_NET_DEVMEM=y +CONFIG_NET_CRC32C=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set +# CONFIG_INET_PSP is not set +CONFIG_UNIX=y +CONFIG_AF_UNIX_OOB=y +# CONFIG_UNIX_DIAG is not set +# CONFIG_TLS is not set +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +# CONFIG_DIBS is not set +CONFIG_XDP_SOCKETS=y +# CONFIG_XDP_SOCKETS_DIAG is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_FIB_TRIE_STATS=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_IP_MROUTE_COMMON=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +# CONFIG_NET_IPVTI is not set +# CONFIG_NET_FOU is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +CONFIG_INET_TABLE_PERTURB_ORDER=16 +# CONFIG_INET_DIAG is not set +CONFIG_TCP_CONG_ADVANCED=y +# CONFIG_TCP_CONG_BIC is not set +CONFIG_TCP_CONG_CUBIC=y +# CONFIG_TCP_CONG_WESTWOOD is not set +# CONFIG_TCP_CONG_HTCP is not set +# CONFIG_TCP_CONG_HSTCP is not set +# CONFIG_TCP_CONG_HYBLA is not set +# CONFIG_TCP_CONG_VEGAS is not set +# CONFIG_TCP_CONG_NV is not set +# CONFIG_TCP_CONG_SCALABLE is not set +# CONFIG_TCP_CONG_LP is not set +# CONFIG_TCP_CONG_VENO is not set +# CONFIG_TCP_CONG_YEAH is not set +# CONFIG_TCP_CONG_ILLINOIS is not set +# CONFIG_TCP_CONG_DCTCP is not set +# CONFIG_TCP_CONG_CDG is not set +# CONFIG_TCP_CONG_BBR is not set +CONFIG_DEFAULT_CUBIC=y +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +CONFIG_TCP_SIGPOOL=y +CONFIG_TCP_AO=y +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_IPV6_ILA is not set +# CONFIG_IPV6_VTI is not set +# CONFIG_IPV6_SIT is not set +# CONFIG_IPV6_TUNNEL is not set +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_IPV6_SEG6_LWTUNNEL=y +CONFIG_IPV6_SEG6_HMAC=y +CONFIG_IPV6_SEG6_BPF=y +# CONFIG_IPV6_RPL_LWTUNNEL is not set +CONFIG_IPV6_IOAM6_LWTUNNEL=y +CONFIG_NETLABEL=y +CONFIG_MPTCP=y +CONFIG_MPTCP_IPV6=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NET_PTP_CLASSIFY=y +CONFIG_NETWORK_PHY_TIMESTAMPING=y +CONFIG_NETFILTER=y +CONFIG_NETFILTER_ADVANCED=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_INGRESS=y +CONFIG_NETFILTER_EGRESS=y +CONFIG_NETFILTER_SKIP_EGRESS=y +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_FAMILY_ARP=y +CONFIG_NETFILTER_BPF_LINK=y +CONFIG_NETFILTER_NETLINK_HOOK=m +# CONFIG_NETFILTER_NETLINK_ACCT is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +# CONFIG_NETFILTER_NETLINK_OSF is not set +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NF_LOG_SYSLOG is not set +CONFIG_NF_TABLES=m +CONFIG_NF_TABLES_INET=y +CONFIG_NF_TABLES_NETDEV=y +# CONFIG_NFT_NUMGEN is not set +# CONFIG_NFT_EXTHDR_DCCP is not set +# CONFIG_NFT_LOG is not set +# CONFIG_NFT_LIMIT is not set +# CONFIG_NFT_TUNNEL is not set +# CONFIG_NFT_QUOTA is not set +# CONFIG_NFT_REJECT is not set +# CONFIG_NFT_COMPAT is not set +# CONFIG_NFT_HASH is not set +# CONFIG_NFT_SOCKET is not set +# CONFIG_NFT_OSF is not set +# CONFIG_NFT_TPROXY is not set +# CONFIG_NF_DUP_NETDEV is not set +# CONFIG_NFT_DUP_NETDEV is not set +# CONFIG_NFT_FWD_NETDEV is not set +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XTABLES_COMPAT=y +# CONFIG_NETFILTER_XTABLES_LEGACY is not set + +# +# Xtables combined modules +# +# CONFIG_NETFILTER_XT_MARK is not set + +# +# Xtables targets +# +# CONFIG_NETFILTER_XT_TARGET_AUDIT is not set +# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set +# CONFIG_NETFILTER_XT_TARGET_HMARK is not set +# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set +# CONFIG_NETFILTER_XT_TARGET_LED is not set +# CONFIG_NETFILTER_XT_TARGET_LOG is not set +# CONFIG_NETFILTER_XT_TARGET_MARK is not set +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +# CONFIG_NETFILTER_XT_TARGET_TEE is not set +# CONFIG_NETFILTER_XT_TARGET_SECMARK is not set +# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set + +# +# Xtables matches +# +# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_BPF is not set +# CONFIG_NETFILTER_XT_MATCH_CGROUP is not set +# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set +# CONFIG_NETFILTER_XT_MATCH_CPU is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set +# CONFIG_NETFILTER_XT_MATCH_DSCP is not set +# CONFIG_NETFILTER_XT_MATCH_ECN is not set +# CONFIG_NETFILTER_XT_MATCH_ESP is not set +# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_HL is not set +# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set +# CONFIG_NETFILTER_XT_MATCH_L2TP is not set +# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set +# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_MAC is not set +# CONFIG_NETFILTER_XT_MATCH_MARK is not set +# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set +# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set +# CONFIG_NETFILTER_XT_MATCH_OSF is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set +# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set +# CONFIG_NETFILTER_XT_MATCH_STRING is not set +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set +# CONFIG_NETFILTER_XT_MATCH_TIME is not set +# CONFIG_NETFILTER_XT_MATCH_U32 is not set +# end of Core Netfilter Configuration + +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_NF_SOCKET_IPV4 is not set +# CONFIG_NF_TPROXY_IPV4 is not set +CONFIG_NF_TABLES_IPV4=y +# CONFIG_NFT_DUP_IPV4 is not set +# CONFIG_NFT_FIB_IPV4 is not set +CONFIG_NF_TABLES_ARP=y +# CONFIG_NF_DUP_IPV4 is not set +# CONFIG_NF_LOG_ARP is not set +# CONFIG_NF_LOG_IPV4 is not set +# CONFIG_NF_REJECT_IPV4 is not set +# CONFIG_IP_NF_IPTABLES is not set +# end of IP: Netfilter Configuration + +# +# IPv6: Netfilter Configuration +# +# CONFIG_NF_SOCKET_IPV6 is not set +# CONFIG_NF_TPROXY_IPV6 is not set +CONFIG_NF_TABLES_IPV6=y +# CONFIG_NFT_DUP_IPV6 is not set +# CONFIG_NFT_FIB_IPV6 is not set +# CONFIG_NF_DUP_IPV6 is not set +# CONFIG_NF_REJECT_IPV6 is not set +# CONFIG_NF_LOG_IPV6 is not set +# CONFIG_IP6_NF_IPTABLES is not set +# end of IPv6: Netfilter Configuration + +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +# CONFIG_6LOWPAN is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +# CONFIG_NET_SCH_HTB is not set +# CONFIG_NET_SCH_HFSC is not set +# CONFIG_NET_SCH_PRIO is not set +# CONFIG_NET_SCH_MULTIQ is not set +# CONFIG_NET_SCH_RED is not set +# CONFIG_NET_SCH_SFB is not set +# CONFIG_NET_SCH_SFQ is not set +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_CBS is not set +# CONFIG_NET_SCH_ETF is not set +# CONFIG_NET_SCH_TAPRIO is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_NETEM is not set +# CONFIG_NET_SCH_DRR is not set +# CONFIG_NET_SCH_MQPRIO is not set +# CONFIG_NET_SCH_SKBPRIO is not set +# CONFIG_NET_SCH_CHOKE is not set +# CONFIG_NET_SCH_QFQ is not set +# CONFIG_NET_SCH_CODEL is not set +CONFIG_NET_SCH_FQ_CODEL=m +# CONFIG_NET_SCH_CAKE is not set +# CONFIG_NET_SCH_FQ is not set +# CONFIG_NET_SCH_HHF is not set +# CONFIG_NET_SCH_PIE is not set +# CONFIG_NET_SCH_INGRESS is not set +# CONFIG_NET_SCH_PLUG is not set +# CONFIG_NET_SCH_ETS is not set +# CONFIG_NET_SCH_BPF is not set +# CONFIG_NET_SCH_DUALPI2 is not set +# CONFIG_NET_SCH_DEFAULT is not set + +# +# Classification +# +CONFIG_NET_CLS=y +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_ROUTE4 is not set +# CONFIG_NET_CLS_FW is not set +# CONFIG_NET_CLS_U32 is not set +# CONFIG_NET_CLS_FLOW is not set +# CONFIG_NET_CLS_CGROUP is not set +# CONFIG_NET_CLS_BPF is not set +# CONFIG_NET_CLS_FLOWER is not set +# CONFIG_NET_CLS_MATCHALL is not set +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +# CONFIG_NET_EMATCH_CMP is not set +# CONFIG_NET_EMATCH_NBYTE is not set +# CONFIG_NET_EMATCH_U32 is not set +# CONFIG_NET_EMATCH_META is not set +# CONFIG_NET_EMATCH_TEXT is not set +# CONFIG_NET_EMATCH_IPT is not set +CONFIG_NET_CLS_ACT=y +# CONFIG_NET_ACT_POLICE is not set +# CONFIG_NET_ACT_GACT is not set +# CONFIG_NET_ACT_MIRRED is not set +# CONFIG_NET_ACT_SAMPLE is not set +# CONFIG_NET_ACT_NAT is not set +# CONFIG_NET_ACT_PEDIT is not set +# CONFIG_NET_ACT_SIMP is not set +# CONFIG_NET_ACT_SKBEDIT is not set +# CONFIG_NET_ACT_CSUM is not set +# CONFIG_NET_ACT_MPLS is not set +# CONFIG_NET_ACT_VLAN is not set +# CONFIG_NET_ACT_BPF is not set +# CONFIG_NET_ACT_SKBMOD is not set +# CONFIG_NET_ACT_IFE is not set +# CONFIG_NET_ACT_TUNNEL_KEY is not set +# CONFIG_NET_ACT_GATE is not set +CONFIG_NET_TC_SKB_EXT=y +CONFIG_NET_SCH_FIFO=y +CONFIG_DCB=y +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +CONFIG_VSOCKETS=m +# CONFIG_VSOCKETS_DIAG is not set +CONFIG_VSOCKETS_LOOPBACK=m +CONFIG_VMWARE_VMCI_VSOCKETS=m +# CONFIG_VIRTIO_VSOCKETS is not set +CONFIG_VIRTIO_VSOCKETS_COMMON=m +# CONFIG_NETLINK_DIAG is not set +CONFIG_MPLS=y +# CONFIG_NET_MPLS_GSO is not set +# CONFIG_MPLS_ROUTING is not set +# CONFIG_NET_NSH is not set +# CONFIG_HSR is not set +CONFIG_NET_SWITCHDEV=y +CONFIG_NET_L3_MASTER_DEV=y +CONFIG_QRTR=m +# CONFIG_QRTR_TUN is not set +CONFIG_NET_NCSI=y +CONFIG_NCSI_OEM_CMD_GET_MAC=y +# CONFIG_NCSI_OEM_CMD_KEEP_PHY is not set +CONFIG_PCPU_DEV_REFCNT=y +CONFIG_MAX_SKB_FRAGS=17 +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_XPS=y +CONFIG_CGROUP_NET_PRIO=y +CONFIG_CGROUP_NET_CLASSID=y +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +CONFIG_BPF_STREAM_PARSER=y +CONFIG_NET_FLOW_LIMIT=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NET_DROP_MONITOR=y +# end of Network testing +# end of Networking options + +CONFIG_HAMRADIO=y + +# +# Packet Radio protocols +# +# CONFIG_AX25 is not set +# CONFIG_CAN is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_AF_KCM is not set +CONFIG_STREAM_PARSER=y +CONFIG_MCTP=y +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 +CONFIG_RFKILL=y +CONFIG_RFKILL_LEDS=y +CONFIG_RFKILL_INPUT=y +# CONFIG_RFKILL_GPIO is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set +# CONFIG_PSAMPLE is not set +# CONFIG_NET_IFE is not set +CONFIG_LWTUNNEL=y +CONFIG_LWTUNNEL_BPF=y +CONFIG_DST_CACHE=y +CONFIG_NET_SELFTESTS=y +CONFIG_NET_SOCK_MSG=y +CONFIG_PAGE_POOL=y +CONFIG_PAGE_POOL_STATS=y +CONFIG_FAILOVER=y +CONFIG_ETHTOOL_NETLINK=y + +# +# Device Drivers +# +CONFIG_ARM_AMBA=y +CONFIG_TEGRA_AHB=y +CONFIG_HAVE_PCI=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_SYSCALL=y +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=y +CONFIG_PCIEAER=y +# CONFIG_PCIEAER_INJECT is not set +# CONFIG_PCIE_ECRC is not set +CONFIG_PCIEASPM=y +CONFIG_PCIEASPM_DEFAULT=y +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +# CONFIG_PCIEASPM_PERFORMANCE is not set +CONFIG_PCIE_PME=y +CONFIG_PCIE_DPC=y +CONFIG_PCIE_PTM=y +CONFIG_PCIE_EDR=y +CONFIG_PCI_MSI=y +CONFIG_PCI_QUIRKS=y +# CONFIG_PCI_DEBUG is not set +CONFIG_PCI_REALLOC_ENABLE_AUTO=y +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_PF_STUB is not set +CONFIG_PCI_ATS=y +# CONFIG_PCI_DOE is not set +CONFIG_PCI_ECAM=y +CONFIG_PCI_BRIDGE_EMUL=y +CONFIG_PCI_IOV=y +CONFIG_PCI_NPEM=y +CONFIG_PCI_PRI=y +CONFIG_PCI_PASID=y +CONFIG_PCIE_TPH=y +CONFIG_PCI_P2PDMA=y +CONFIG_PCI_LABEL=y +# CONFIG_PCI_DYNAMIC_OF_NODES is not set +# CONFIG_PCIE_BUS_TUNE_OFF is not set +CONFIG_PCIE_BUS_DEFAULT=y +# CONFIG_PCIE_BUS_SAFE is not set +# CONFIG_PCIE_BUS_PERFORMANCE is not set +# CONFIG_PCIE_BUS_PEER2PEER is not set +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_ACPI=y +# CONFIG_HOTPLUG_PCI_ACPI_AMPERE_ALTRA is not set +# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set +CONFIG_HOTPLUG_PCI_CPCI=y +CONFIG_HOTPLUG_PCI_OCTEONEP=y +CONFIG_HOTPLUG_PCI_SHPC=y + +# +# PCI controller drivers +# +CONFIG_PCI_HOST_COMMON=y +CONFIG_PCI_AARDVARK=y +CONFIG_PCIE_ALTERA=y +CONFIG_PCIE_ALTERA_MSI=y +# CONFIG_PCIE_APPLE is not set +CONFIG_PCI_HOST_THUNDER_PEM=y +CONFIG_PCI_HOST_THUNDER_ECAM=y +CONFIG_PCI_FTPCI100=y +CONFIG_PCI_HOST_GENERIC=y +CONFIG_PCIE_HISI_ERR=y +CONFIG_PCIE_MEDIATEK=y +# CONFIG_PCIE_MEDIATEK_GEN3 is not set +CONFIG_PCI_TEGRA=y +CONFIG_PCIE_RCAR_HOST=y +CONFIG_PCIE_RCAR_EP=y +CONFIG_PCIE_ROCKCHIP=y +# CONFIG_PCIE_ROCKCHIP_HOST is not set +CONFIG_PCIE_ROCKCHIP_EP=y +CONFIG_PCI_XGENE=y +CONFIG_PCI_XGENE_MSI=y +CONFIG_PCIE_XILINX=y +CONFIG_PCIE_XILINX_DMA_PL=y +CONFIG_PCIE_XILINX_NWL=y +CONFIG_PCIE_XILINX_CPM=y + +# +# Cadence-based PCIe controllers +# +CONFIG_PCIE_CADENCE=y +CONFIG_PCIE_CADENCE_HOST=y +CONFIG_PCIE_CADENCE_EP=y +CONFIG_PCIE_CADENCE_PLAT=y +CONFIG_PCIE_CADENCE_PLAT_HOST=y +CONFIG_PCIE_CADENCE_PLAT_EP=y +CONFIG_PCI_J721E=y +CONFIG_PCI_J721E_HOST=y +CONFIG_PCI_J721E_EP=y +# end of Cadence-based PCIe controllers + +# +# DesignWare-based PCIe controllers +# +CONFIG_PCIE_DW=y +# CONFIG_PCIE_DW_DEBUGFS is not set +CONFIG_PCIE_DW_HOST=y +CONFIG_PCIE_DW_EP=y +CONFIG_PCIE_AL=y +# CONFIG_PCIE_AMD_MDB is not set +# CONFIG_PCI_MESON is not set +CONFIG_PCI_IMX6=y +CONFIG_PCI_IMX6_HOST=y +CONFIG_PCI_IMX6_EP=y +CONFIG_PCI_LAYERSCAPE=y +CONFIG_PCI_LAYERSCAPE_EP=y +CONFIG_PCI_HISI=y +CONFIG_PCIE_KIRIN=y +CONFIG_PCIE_HISI_STB=y +CONFIG_PCIE_KEEMBAY=y +CONFIG_PCIE_KEEMBAY_HOST=y +CONFIG_PCIE_KEEMBAY_EP=y +CONFIG_PCIE_ARMADA_8K=y +# CONFIG_PCIE_TEGRA194_HOST is not set +# CONFIG_PCIE_TEGRA194_EP is not set +CONFIG_PCIE_DW_PLAT=y +CONFIG_PCIE_DW_PLAT_HOST=y +CONFIG_PCIE_DW_PLAT_EP=y +CONFIG_PCIE_QCOM_COMMON=y +CONFIG_PCIE_QCOM=y +# CONFIG_PCIE_QCOM_EP is not set +# CONFIG_PCIE_RCAR_GEN4_HOST is not set +# CONFIG_PCIE_RCAR_GEN4_EP is not set +CONFIG_PCIE_ROCKCHIP_DW=y +CONFIG_PCIE_ROCKCHIP_DW_HOST=y +CONFIG_PCIE_ROCKCHIP_DW_EP=y +# CONFIG_PCIE_STM32_HOST is not set +# CONFIG_PCIE_STM32_EP is not set +CONFIG_PCI_KEYSTONE=y +CONFIG_PCI_KEYSTONE_HOST=y +CONFIG_PCI_KEYSTONE_EP=y +CONFIG_PCIE_VISCONTI_HOST=y +# end of DesignWare-based PCIe controllers + +# +# Mobiveil-based PCIe controllers +# +# CONFIG_PCIE_LAYERSCAPE_GEN4 is not set +# CONFIG_PCIE_MOBIVEIL_PLAT is not set +# end of Mobiveil-based PCIe controllers + +# +# PLDA-based PCIe controllers +# +CONFIG_PCIE_PLDA_HOST=y +CONFIG_PCIE_MICROCHIP_HOST=y +# end of PLDA-based PCIe controllers +# end of PCI controller drivers + +# +# PCI Endpoint +# +CONFIG_PCI_ENDPOINT=y +CONFIG_PCI_ENDPOINT_CONFIGFS=y +# CONFIG_PCI_ENDPOINT_MSI_DOORBELL is not set +# CONFIG_PCI_EPF_TEST is not set +# CONFIG_PCI_EPF_NTB is not set +# end of PCI Endpoint + +# +# PCI switch controller drivers +# +# CONFIG_PCI_SW_SWITCHTEC is not set +# end of PCI switch controller drivers + +CONFIG_HAVE_PWRCTRL=y +CONFIG_PCI_PWRCTRL=y +CONFIG_PCI_PWRCTRL_SLOT=y +# CONFIG_CXL_BUS is not set +# CONFIG_PCCARD is not set +CONFIG_RAPIDIO=y +# CONFIG_RAPIDIO_TSI721 is not set +CONFIG_RAPIDIO_DISC_TIMEOUT=30 +# CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS is not set +CONFIG_RAPIDIO_DMA_ENGINE=y +# CONFIG_RAPIDIO_DEBUG is not set +# CONFIG_RAPIDIO_ENUM_BASIC is not set +# CONFIG_RAPIDIO_CHMAN is not set +# CONFIG_RAPIDIO_MPORT_CDEV is not set + +# +# RapidIO Switch drivers +# +# CONFIG_RAPIDIO_CPS_XX is not set +# CONFIG_RAPIDIO_CPS_GEN2 is not set +# CONFIG_RAPIDIO_RXS_GEN3 is not set +# end of RapidIO Switch drivers + +CONFIG_PC104=y + +# +# Generic Driver Options +# +CONFIG_AUXILIARY_BUS=y +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_DEVTMPFS_SAFE=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y + +# +# Firmware loader +# +CONFIG_FW_LOADER=y +CONFIG_FW_LOADER_DEBUG=y +CONFIG_RUST_FW_LOADER_ABSTRACTIONS=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +CONFIG_EXTRA_FIRMWARE="" +CONFIG_FW_LOADER_USER_HELPER=y +# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set +CONFIG_FW_LOADER_COMPRESS=y +CONFIG_FW_LOADER_COMPRESS_XZ=y +CONFIG_FW_LOADER_COMPRESS_ZSTD=y +CONFIG_FW_CACHE=y +CONFIG_FW_UPLOAD=y +# end of Firmware loader + +CONFIG_WANT_DEV_COREDUMP=y +CONFIG_ALLOW_DEV_COREDUMP=y +CONFIG_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set +CONFIG_HMEM_REPORTING=y +# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set +CONFIG_SYS_HYPERVISOR=y +CONFIG_GENERIC_CPU_DEVICES=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_SOC_BUS=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_IRQ=y +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_DMA_FENCE_TRACE is not set +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_ARCH_NUMA=y +# CONFIG_FW_DEVLINK_SYNC_STATE_TIMEOUT is not set +# end of Generic Driver Options + +# +# Bus devices +# +CONFIG_ARM_CCI=y +CONFIG_ARM_CCI400_COMMON=y +# CONFIG_MOXTET is not set +CONFIG_HISILICON_LPC=y +# CONFIG_IMX_AIPSTZ is not set +CONFIG_IMX_WEIM=y +CONFIG_QCOM_EBI2=y +CONFIG_QCOM_SSC_BLOCK_BUS=y +CONFIG_STM32_FIREWALL=y +CONFIG_SUN50I_DE2_BUS=y +# CONFIG_SUNXI_RSB is not set +# CONFIG_TEGRA_ACONNECT is not set +# CONFIG_TEGRA_GMI is not set +CONFIG_TI_SYSC=y +CONFIG_VEXPRESS_CONFIG=y +CONFIG_FSL_MC_BUS=y +CONFIG_FSL_MC_UAPI_SUPPORT=y +# CONFIG_MHI_BUS is not set +# CONFIG_MHI_BUS_EP is not set +# end of Bus devices + +# +# Cache Drivers +# +# end of Cache Drivers + +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Firmware Drivers +# + +# +# ARM System Control and Management Interface Protocol +# +CONFIG_ARM_SCMI_PROTOCOL=y +CONFIG_ARM_SCMI_NEED_DEBUGFS=y +CONFIG_ARM_SCMI_RAW_MODE_SUPPORT=y +CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX=y +# CONFIG_ARM_SCMI_DEBUG_COUNTERS is not set +CONFIG_ARM_SCMI_QUIRKS=y + +# +# SCMI Transport Drivers +# +CONFIG_ARM_SCMI_HAVE_TRANSPORT=y +CONFIG_ARM_SCMI_HAVE_SHMEM=y +CONFIG_ARM_SCMI_HAVE_MSG=y +CONFIG_ARM_SCMI_TRANSPORT_MAILBOX=y +CONFIG_ARM_SCMI_TRANSPORT_SMC=y +CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE=y +CONFIG_ARM_SCMI_TRANSPORT_VIRTIO=y +CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y +CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_ATOMIC_ENABLE=y +# end of SCMI Transport Drivers + +# +# ARM SCMI NXP i.MX Vendor Protocols +# +CONFIG_IMX_SCMI_BBM_EXT=y +CONFIG_IMX_SCMI_CPU_EXT=y +CONFIG_IMX_SCMI_LMM_EXT=y +# end of ARM SCMI NXP i.MX Vendor Protocols + +# CONFIG_ARM_SCMI_POWER_CONTROL is not set +# end of ARM System Control and Management Interface Protocol + +# CONFIG_ARM_SCPI_PROTOCOL is not set +CONFIG_ARM_SDE_INTERFACE=y +CONFIG_FIRMWARE_MEMMAP=y +CONFIG_DMIID=y +CONFIG_DMI_SYSFS=m +# CONFIG_ISCSI_IBFT is not set +# CONFIG_FW_CFG_SYSFS is not set +# CONFIG_INTEL_STRATIX10_SERVICE is not set +CONFIG_SYSFB=y +CONFIG_SYSFB_SIMPLEFB=y +CONFIG_TI_SCI_PROTOCOL=y +# CONFIG_TURRIS_MOX_RWTM is not set +# CONFIG_ARM_FFA_TRANSPORT is not set +# CONFIG_GOOGLE_FIRMWARE is not set + +# +# EFI (Extensible Firmware Interface) Support +# +CONFIG_EFI_ESRT=y +CONFIG_EFI_VARS_PSTORE=m +# CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE is not set +CONFIG_EFI_SOFT_RESERVE=y +CONFIG_EFI_PARAMS_FROM_FDT=y +CONFIG_EFI_RUNTIME_WRAPPERS=y +CONFIG_EFI_GENERIC_STUB=y +CONFIG_EFI_ZBOOT=y +# CONFIG_EFI_ARMSTUB_DTB_LOADER is not set +# CONFIG_EFI_BOOTLOADER_CONTROL is not set +# CONFIG_EFI_CAPSULE_LOADER is not set +# CONFIG_EFI_TEST is not set +CONFIG_RESET_ATTACK_MITIGATION=y +# CONFIG_EFI_DISABLE_PCI_DMA is not set +CONFIG_EFI_EARLYCON=y +CONFIG_EFI_CUSTOM_SSDT_OVERLAYS=y +# CONFIG_EFI_DISABLE_RUNTIME is not set +CONFIG_EFI_COCO_SECRET=y +# CONFIG_OVMF_DEBUG_LOG is not set +CONFIG_EFI_SBAT_FILE="" +# end of EFI (Extensible Firmware Interface) Support + +CONFIG_UEFI_CPER=y +CONFIG_UEFI_CPER_ARM=y +CONFIG_IMX_SCMI_CPU_DRV=y +CONFIG_IMX_SCMI_LMM_DRV=y +# CONFIG_IMX_SCMI_MISC_DRV is not set +CONFIG_MESON_SM=y +CONFIG_ARM_PSCI_FW=y +# CONFIG_ARM_PSCI_CHECKER is not set + +# +# Qualcomm firmware drivers +# +CONFIG_QCOM_SCM=y +CONFIG_QCOM_TZMEM=y +# CONFIG_QCOM_TZMEM_MODE_GENERIC is not set +CONFIG_QCOM_TZMEM_MODE_SHMBRIDGE=y +CONFIG_QCOM_QSEECOM=y +CONFIG_QCOM_QSEECOM_UEFISECAPP=y +# end of Qualcomm firmware drivers + +CONFIG_HAVE_ARM_SMCCC=y +CONFIG_HAVE_ARM_SMCCC_DISCOVERY=y +CONFIG_ARM_SMCCC_SOC_ID=y + +# +# Tegra firmware driver +# +CONFIG_TEGRA_IVC=y +CONFIG_TEGRA_BPMP=y +# end of Tegra firmware driver + +# +# Zynq MPSoC Firmware Drivers +# +CONFIG_ZYNQMP_FIRMWARE=y +# CONFIG_ZYNQMP_FIRMWARE_DEBUG is not set +# end of Zynq MPSoC Firmware Drivers +# end of Firmware Drivers + +# CONFIG_FWCTL is not set +# CONFIG_GNSS is not set +# CONFIG_MTD is not set +CONFIG_DTC=y +CONFIG_OF=y +# CONFIG_OF_UNITTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_KOBJ=y +CONFIG_OF_DYNAMIC=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_RESERVED_MEM=y +CONFIG_OF_RESOLVE=y +CONFIG_OF_OVERLAY=y +CONFIG_OF_NUMA=y +# CONFIG_PARPORT is not set +CONFIG_PNP=y +# CONFIG_PNP_DEBUG_MESSAGES is not set + +# +# Protocols +# +CONFIG_PNPACPI=y +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +CONFIG_BLK_DEV_RUST_NULL=y +CONFIG_CDROM=y +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +# CONFIG_ZRAM is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_XEN_BLKDEV_FRONTEND=y +# CONFIG_XEN_BLKDEV_BACKEND is not set +CONFIG_VIRTIO_BLK=y +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_BLK_DEV_UBLK is not set +# CONFIG_BLK_DEV_ZONED_LOOP is not set + +# +# NVME Support +# +CONFIG_NVME_KEYRING=m +CONFIG_NVME_AUTH=m +CONFIG_NVME_CORE=m +CONFIG_BLK_DEV_NVME=m +CONFIG_NVME_MULTIPATH=y +# CONFIG_NVME_VERBOSE_ERRORS is not set +CONFIG_NVME_HWMON=y +# CONFIG_NVME_FC is not set +# CONFIG_NVME_TCP is not set +CONFIG_NVME_HOST_AUTH=y +# CONFIG_NVME_TARGET is not set +# end of NVME Support + +# +# Misc devices +# +# CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_PHANTOM is not set +# CONFIG_RPMB is not set +# CONFIG_TI_FPC202 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +CONFIG_SRAM=y +# CONFIG_DW_XDATA_PCIE is not set +# CONFIG_PCI_ENDPOINT_TEST is not set +# CONFIG_XILINX_SDFEC is not set +# CONFIG_HISI_HIKEY_USB is not set +# CONFIG_OPEN_DICE is not set +# CONFIG_NTSYNC is not set +# CONFIG_VCPU_STALL_DETECTOR is not set +# CONFIG_NSM is not set +# CONFIG_MARVELL_CN10K_DPI is not set +# CONFIG_MCHP_LAN966X_PCI is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_EEPROM_IDT_89HPESX is not set +# CONFIG_EEPROM_EE1004 is not set +# CONFIG_EEPROM_M24LR is not set +# end of EEPROM support + +# CONFIG_CB710_CORE is not set +# CONFIG_SENSORS_LIS3_I2C is not set +# CONFIG_ALTERA_STAPL is not set +CONFIG_VMWARE_VMCI=m +# CONFIG_GENWQE is not set +# CONFIG_BCM_VK is not set +# CONFIG_MISC_ALCOR_PCI is not set +# CONFIG_MISC_RTSX_PCI is not set +# CONFIG_MISC_RTSX_USB is not set +# CONFIG_UACCE is not set +CONFIG_PVPANIC=y +# CONFIG_PVPANIC_MMIO is not set +# CONFIG_PVPANIC_PCI is not set +# CONFIG_GP_PCI1XXXX is not set +# CONFIG_KEBA_CP500 is not set +# CONFIG_AMD_SBRMI_I2C is not set +# CONFIG_MISC_RP1 is not set +# end of Misc devices + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI_COMMON=y +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +CONFIG_BLK_DEV_SR=y +CONFIG_CHR_DEV_SG=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# end of SCSI Transports + +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set +# CONFIG_SCSI_CXGB4_ISCSI is not set +# CONFIG_SCSI_BNX2_ISCSI is not set +# CONFIG_BE2ISCSI is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_HPSA is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_3W_SAS is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_HISI_SAS is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_MVUMI is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_SCSI_ESAS2R is not set +CONFIG_MEGARAID_NEWGEN=y +# CONFIG_MEGARAID_MM is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_MPT3SAS is not set +# CONFIG_SCSI_MPT2SAS is not set +# CONFIG_SCSI_MPI3MR is not set +# CONFIG_SCSI_SMARTPQI is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_MYRB is not set +# CONFIG_SCSI_MYRS is not set +# CONFIG_XEN_SCSI_FRONTEND is not set +# CONFIG_SCSI_SNIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FDOMAIN_PCI is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_WD719X is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_PMCRAID is not set +# CONFIG_SCSI_PM8001 is not set +CONFIG_SCSI_VIRTIO=y +CONFIG_SCSI_DH=y +# CONFIG_SCSI_DH_RDAC is not set +# CONFIG_SCSI_DH_HP_SW is not set +# CONFIG_SCSI_DH_EMC is not set +# CONFIG_SCSI_DH_ALUA is not set +# end of SCSI device support + +CONFIG_ATA=y +CONFIG_SATA_HOST=y +CONFIG_PATA_TIMINGS=y +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_ATA_FORCE=y +CONFIG_ATA_ACPI=y +CONFIG_SATA_ZPODD=y +CONFIG_SATA_PMP=y + +# +# Controllers with non-SFF native interface +# +CONFIG_SATA_AHCI=m +CONFIG_SATA_MOBILE_LPM_POLICY=3 +# CONFIG_SATA_AHCI_PLATFORM is not set +# CONFIG_AHCI_DWC is not set +CONFIG_AHCI_IMX=y +# CONFIG_AHCI_CEVA is not set +# CONFIG_AHCI_MTK is not set +# CONFIG_AHCI_MVEBU is not set +# CONFIG_AHCI_SUNXI is not set +# CONFIG_AHCI_TEGRA is not set +# CONFIG_AHCI_XGENE is not set +# CONFIG_AHCI_QORIQ is not set +# CONFIG_SATA_AHCI_SEATTLE is not set +# CONFIG_SATA_INIC162X is not set +# CONFIG_SATA_ACARD_AHCI is not set +# CONFIG_SATA_SIL24 is not set +CONFIG_ATA_SFF=y + +# +# SFF controllers with custom DMA interface +# +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_SX4 is not set +CONFIG_ATA_BMDMA=y + +# +# SATA SFF controllers with BMDMA +# +# CONFIG_ATA_PIIX is not set +# CONFIG_SATA_DWC is not set +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_RCAR is not set +# CONFIG_SATA_SIL is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_SVW is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set + +# +# PATA SFF controllers with BMDMA +# +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_ATP867X is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IMX is not set +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set +# CONFIG_PATA_NS87415 is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RDC is not set +# CONFIG_PATA_SCH is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_TOSHIBA is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set + +# +# PIO-only SFF controllers +# +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OF_PLATFORM is not set +# CONFIG_PATA_RZ1000 is not set + +# +# Generic fallback / legacy drivers +# +# CONFIG_PATA_ACPI is not set +# CONFIG_ATA_GENERIC is not set +# CONFIG_PATA_LEGACY is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_BITMAP=y +# CONFIG_MD_LLBITMAP is not set +CONFIG_MD_AUTODETECT=y +CONFIG_MD_BITMAP_FILE=y +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID10 is not set +# CONFIG_MD_RAID456 is not set +# CONFIG_BCACHE is not set +CONFIG_BLK_DEV_DM_BUILTIN=y +CONFIG_BLK_DEV_DM=y +# CONFIG_DM_DEBUG is not set +# CONFIG_DM_UNSTRIPED is not set +# CONFIG_DM_CRYPT is not set +# CONFIG_DM_SNAPSHOT is not set +# CONFIG_DM_THIN_PROVISIONING is not set +# CONFIG_DM_CACHE is not set +# CONFIG_DM_WRITECACHE is not set +# CONFIG_DM_EBS is not set +# CONFIG_DM_ERA is not set +# CONFIG_DM_CLONE is not set +# CONFIG_DM_MIRROR is not set +# CONFIG_DM_RAID is not set +# CONFIG_DM_ZERO is not set +# CONFIG_DM_MULTIPATH is not set +# CONFIG_DM_DELAY is not set +# CONFIG_DM_DUST is not set +CONFIG_DM_INIT=y +CONFIG_DM_UEVENT=y +# CONFIG_DM_FLAKEY is not set +# CONFIG_DM_VERITY is not set +# CONFIG_DM_SWITCH is not set +# CONFIG_DM_LOG_WRITES is not set +# CONFIG_DM_INTEGRITY is not set +# CONFIG_DM_ZONED is not set +CONFIG_DM_AUDIT=y +# CONFIG_DM_VDO is not set +# CONFIG_TARGET_CORE is not set +CONFIG_FUSION=y +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_SAS is not set +CONFIG_FUSION_MAX_SGE=128 +CONFIG_FUSION_LOGGING=y + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +# end of IEEE 1394 (FireWire) support + +CONFIG_NETDEVICES=y +CONFIG_MII=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_WIREGUARD is not set +# CONFIG_OVPN is not set +# CONFIG_EQUALIZER is not set +CONFIG_NET_FC=y +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_IPVLAN is not set +# CONFIG_VXLAN is not set +# CONFIG_GENEVE is not set +# CONFIG_BAREUDP is not set +# CONFIG_GTP is not set +# CONFIG_PFCP is not set +# CONFIG_AMT is not set +# CONFIG_MACSEC is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_RIONET is not set +CONFIG_TUN=y +# CONFIG_TUN_VNET_CROSS_LE is not set +# CONFIG_VETH is not set +CONFIG_VIRTIO_NET=y +# CONFIG_NLMON is not set +CONFIG_NETKIT=y +# CONFIG_NET_VRF is not set +# CONFIG_ARCNET is not set +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_3COM=y +# CONFIG_VORTEX is not set +# CONFIG_TYPHOON is not set +CONFIG_NET_VENDOR_ACTIONS=y +# CONFIG_OWL_EMAC is not set +CONFIG_NET_VENDOR_ADAPTEC=y +# CONFIG_ADAPTEC_STARFIRE is not set +CONFIG_NET_VENDOR_AGERE=y +# CONFIG_ET131X is not set +# CONFIG_NET_VENDOR_AIROHA is not set +CONFIG_NET_VENDOR_ALACRITECH=y +# CONFIG_SLICOSS is not set +CONFIG_NET_VENDOR_ALLWINNER=y +# CONFIG_SUN4I_EMAC is not set +CONFIG_NET_VENDOR_ALTEON=y +# CONFIG_ACENIC is not set +# CONFIG_ALTERA_TSE is not set +CONFIG_NET_VENDOR_AMAZON=y +# CONFIG_ENA_ETHERNET is not set +CONFIG_NET_VENDOR_AMD=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_PCNET32 is not set +# CONFIG_AMD_XGBE is not set +# CONFIG_PDS_CORE is not set +# CONFIG_NET_XGENE is not set +# CONFIG_NET_XGENE_V2 is not set +CONFIG_NET_VENDOR_AQUANTIA=y +# CONFIG_AQTION is not set +CONFIG_NET_VENDOR_ARC=y +# CONFIG_EMAC_ROCKCHIP is not set +CONFIG_NET_VENDOR_ASIX=y +# CONFIG_SPI_AX88796C is not set +CONFIG_NET_VENDOR_ATHEROS=y +# CONFIG_ATL2 is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_ALX is not set +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_BCMGENET is not set +# CONFIG_BNX2 is not set +# CONFIG_CNIC is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2X is not set +# CONFIG_SYSTEMPORT is not set +# CONFIG_BNXT is not set +# CONFIG_BNGE is not set +CONFIG_NET_VENDOR_CADENCE=y +# CONFIG_MACB is not set +CONFIG_NET_VENDOR_CAVIUM=y +# CONFIG_THUNDER_NIC_PF is not set +# CONFIG_THUNDER_NIC_VF is not set +# CONFIG_THUNDER_NIC_BGX is not set +# CONFIG_THUNDER_NIC_RGX is not set +# CONFIG_CAVIUM_PTP is not set +# CONFIG_LIQUIDIO is not set +# CONFIG_LIQUIDIO_VF is not set +CONFIG_NET_VENDOR_CHELSIO=y +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_CHELSIO_T4 is not set +# CONFIG_CHELSIO_T4VF is not set +CONFIG_NET_VENDOR_CISCO=y +# CONFIG_ENIC is not set +CONFIG_NET_VENDOR_CORTINA=y +# CONFIG_GEMINI_ETHERNET is not set +CONFIG_NET_VENDOR_DAVICOM=y +# CONFIG_DM9051 is not set +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_DEC=y +CONFIG_NET_TULIP=y +# CONFIG_DE2104X is not set +# CONFIG_TULIP is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_DM9102 is not set +# CONFIG_ULI526X is not set +CONFIG_NET_VENDOR_DLINK=y +# CONFIG_DL2K is not set +# CONFIG_SUNDANCE is not set +CONFIG_NET_VENDOR_EMULEX=y +# CONFIG_BE2NET is not set +CONFIG_NET_VENDOR_ENGLEDER=y +# CONFIG_TSNEP is not set +CONFIG_NET_VENDOR_EZCHIP=y +# CONFIG_EZCHIP_NPS_MANAGEMENT_ENET is not set +CONFIG_NET_VENDOR_FREESCALE=y +CONFIG_FEC=y +CONFIG_FSL_FMAN=y +CONFIG_DPAA_ERRATUM_A050385=y +# CONFIG_FSL_PQ_MDIO is not set +CONFIG_FSL_XGMAC_MDIO=y +# CONFIG_GIANFAR is not set +# CONFIG_FSL_DPAA_ETH is not set +# CONFIG_FSL_DPAA2_SWITCH is not set +# CONFIG_FSL_ENETC is not set +# CONFIG_NXP_ENETC4 is not set +# CONFIG_FSL_ENETC_VF is not set +# CONFIG_FSL_ENETC_IERB is not set +# CONFIG_FSL_ENETC_MDIO is not set +# CONFIG_NXP_NETC_BLK_CTRL is not set +CONFIG_NET_VENDOR_FUNGIBLE=y +# CONFIG_FUN_ETH is not set +CONFIG_NET_VENDOR_GOOGLE=y +# CONFIG_GVE is not set +CONFIG_NET_VENDOR_HISILICON=y +# CONFIG_HIX5HD2_GMAC is not set +# CONFIG_HISI_FEMAC is not set +# CONFIG_HIP04_ETH is not set +# CONFIG_HNS_DSAF is not set +# CONFIG_HNS_ENET is not set +# CONFIG_HNS3 is not set +# CONFIG_HIBMCGE is not set +CONFIG_NET_VENDOR_HUAWEI=y +# CONFIG_HINIC is not set +# CONFIG_HINIC3 is not set +CONFIG_NET_VENDOR_I825XX=y +CONFIG_NET_VENDOR_INTEL=y +# CONFIG_E100 is not set +# CONFIG_E1000 is not set +CONFIG_E1000E=m +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_IXGBE is not set +# CONFIG_IXGBEVF is not set +# CONFIG_I40E is not set +# CONFIG_I40EVF is not set +# CONFIG_ICE is not set +# CONFIG_FM10K is not set +# CONFIG_IGC is not set +# CONFIG_IDPF is not set +# CONFIG_JME is not set +CONFIG_NET_VENDOR_ADI=y +# CONFIG_ADIN1110 is not set +CONFIG_NET_VENDOR_LITEX=y +# CONFIG_LITEX_LITEETH is not set +CONFIG_NET_VENDOR_MARVELL=y +# CONFIG_MVMDIO is not set +# CONFIG_MVNETA is not set +# CONFIG_MVPP2 is not set +# CONFIG_PXA168_ETH is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_OCTEONTX2_AF is not set +# CONFIG_OCTEONTX2_PF is not set +# CONFIG_OCTEON_EP is not set +# CONFIG_OCTEON_EP_VF is not set +# CONFIG_NET_VENDOR_MEDIATEK is not set +CONFIG_NET_VENDOR_MELLANOX=y +# CONFIG_MLX4_EN is not set +# CONFIG_MLX5_CORE is not set +# CONFIG_MLXSW_CORE is not set +# CONFIG_MLXFW is not set +# CONFIG_MLXBF_GIGE is not set +CONFIG_NET_VENDOR_META=y +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_KSZ884X_PCI is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set +# CONFIG_ENCX24J600 is not set +# CONFIG_LAN743X is not set +# CONFIG_LAN865X is not set +# CONFIG_LAN966X_SWITCH is not set +# CONFIG_SPARX5_SWITCH is not set +CONFIG_VCAP=y +CONFIG_NET_VENDOR_MICROSEMI=y +# CONFIG_MSCC_OCELOT_SWITCH is not set +CONFIG_NET_VENDOR_MICROSOFT=y +CONFIG_NET_VENDOR_MYRI=y +# CONFIG_MYRI10GE is not set +# CONFIG_FEALNX is not set +CONFIG_NET_VENDOR_NI=y +# CONFIG_NI_XGE_MANAGEMENT_ENET is not set +CONFIG_NET_VENDOR_NATSEMI=y +# CONFIG_NATSEMI is not set +# CONFIG_NS83820 is not set +CONFIG_NET_VENDOR_NETERION=y +# CONFIG_S2IO is not set +CONFIG_NET_VENDOR_NETRONOME=y +# CONFIG_NFP is not set +CONFIG_NET_VENDOR_8390=y +# CONFIG_NE2K_PCI is not set +CONFIG_NET_VENDOR_NVIDIA=y +# CONFIG_FORCEDETH is not set +CONFIG_NET_VENDOR_OKI=y +# CONFIG_ETHOC is not set +CONFIG_NET_VENDOR_PACKET_ENGINES=y +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +CONFIG_NET_VENDOR_PENSANDO=y +# CONFIG_IONIC is not set +CONFIG_NET_VENDOR_QLOGIC=y +# CONFIG_QLA3XXX is not set +# CONFIG_QLCNIC is not set +# CONFIG_NETXEN_NIC is not set +# CONFIG_QED is not set +CONFIG_NET_VENDOR_BROCADE=y +# CONFIG_BNA is not set +CONFIG_NET_VENDOR_QUALCOMM=y +# CONFIG_QCA7000_SPI is not set +# CONFIG_QCA7000_UART is not set +# CONFIG_QCOM_EMAC is not set +# CONFIG_QCOM_PPE is not set +# CONFIG_RMNET is not set +CONFIG_NET_VENDOR_RDC=y +# CONFIG_R6040 is not set +CONFIG_NET_VENDOR_REALTEK=y +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_R8169 is not set +# CONFIG_RTASE is not set +CONFIG_NET_VENDOR_RENESAS=y +# CONFIG_SH_ETH is not set +# CONFIG_RAVB is not set +# CONFIG_RENESAS_ETHER_SWITCH is not set +# CONFIG_RTSN is not set +CONFIG_NET_VENDOR_ROCKER=y +CONFIG_NET_VENDOR_SAMSUNG=y +# CONFIG_SXGBE_ETH is not set +CONFIG_NET_VENDOR_SEEQ=y +CONFIG_NET_VENDOR_SILAN=y +# CONFIG_SC92031 is not set +CONFIG_NET_VENDOR_SIS=y +# CONFIG_SIS900 is not set +# CONFIG_SIS190 is not set +CONFIG_NET_VENDOR_SOLARFLARE=y +# CONFIG_SFC is not set +# CONFIG_SFC_FALCON is not set +# CONFIG_SFC_SIENA is not set +CONFIG_NET_VENDOR_SMSC=y +CONFIG_SMC91X=y +# CONFIG_EPIC100 is not set +# CONFIG_SMSC911X is not set +# CONFIG_SMSC9420 is not set +CONFIG_NET_VENDOR_SOCIONEXT=y +# CONFIG_SNI_NETSEC is not set +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_SUN=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NIU is not set +CONFIG_NET_VENDOR_SYNOPSYS=y +# CONFIG_DWC_XLGMAC is not set +CONFIG_NET_VENDOR_TEHUTI=y +# CONFIG_TEHUTI is not set +# CONFIG_TEHUTI_TN40 is not set +CONFIG_NET_VENDOR_TI=y +CONFIG_TI_DAVINCI_MDIO=y +# CONFIG_TI_CPSW_PHY_SEL is not set +# CONFIG_TI_K3_AM65_CPSW_NUSS is not set +# CONFIG_TI_K3_AM65_CPTS is not set +# CONFIG_TLAN is not set +CONFIG_NET_VENDOR_VERTEXCOM=y +# CONFIG_MSE102X is not set +CONFIG_NET_VENDOR_VIA=y +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +CONFIG_NET_VENDOR_WANGXUN=y +# CONFIG_NGBE is not set +# CONFIG_TXGBE is not set +# CONFIG_TXGBEVF is not set +# CONFIG_NGBEVF is not set +CONFIG_NET_VENDOR_WIZNET=y +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set +CONFIG_NET_VENDOR_XILINX=y +# CONFIG_XILINX_EMACLITE is not set +# CONFIG_XILINX_LL_TEMAC is not set +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +# CONFIG_SKFP is not set +# CONFIG_HIPPI is not set +CONFIG_MDIO_BUS=y +CONFIG_PHYLINK=y +CONFIG_PHYLIB=y +CONFIG_SWPHY=y +CONFIG_LED_TRIGGER_PHY=y +CONFIG_PHYLIB_LEDS=y +CONFIG_FIXED_PHY=y +CONFIG_RUST_PHYLIB_ABSTRACTIONS=y +# CONFIG_SFP is not set + +# +# MII PHY device drivers +# +# CONFIG_AS21XXX_PHY is not set +# CONFIG_AIR_EN8811H_PHY is not set +# CONFIG_AMD_PHY is not set +# CONFIG_MESON_GXL_PHY is not set +# CONFIG_ADIN_PHY is not set +# CONFIG_ADIN1100_PHY is not set +# CONFIG_AMCC_QT2025_PHY is not set +# CONFIG_AQUANTIA_PHY is not set +# CONFIG_AX88796B_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM54140_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +CONFIG_BCM84881_PHY=y +# CONFIG_BCM87XX_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_CORTINA_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_INTEL_XWAY_PHY is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_MARVELL_10G_PHY is not set +# CONFIG_MARVELL_88Q2XXX_PHY is not set +# CONFIG_MARVELL_88X2222_PHY is not set +# CONFIG_MAXLINEAR_GPHY is not set +# CONFIG_MAXLINEAR_86110_PHY is not set +# CONFIG_MEDIATEK_2P5GE_PHY is not set +# CONFIG_MEDIATEK_GE_PHY is not set +# CONFIG_MEDIATEK_GE_SOC_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_MICROCHIP_T1S_PHY is not set +# CONFIG_MICROCHIP_PHY is not set +# CONFIG_MICROCHIP_T1_PHY is not set +# CONFIG_MICROSEMI_PHY is not set +# CONFIG_MOTORCOMM_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_NXP_CBTX_PHY is not set +# CONFIG_NXP_C45_TJA11XX_PHY is not set +# CONFIG_NXP_TJA11XX_PHY is not set +# CONFIG_NCN26000_PHY is not set +# CONFIG_AT803X_PHY is not set +# CONFIG_QCA83XX_PHY is not set +# CONFIG_QCA808X_PHY is not set +# CONFIG_QCA807X_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_RENESAS_PHY is not set +# CONFIG_ROCKCHIP_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_TERANETICS_PHY is not set +# CONFIG_DP83822_PHY is not set +# CONFIG_DP83TC811_PHY is not set +# CONFIG_DP83848_PHY is not set +# CONFIG_DP83867_PHY is not set +# CONFIG_DP83869_PHY is not set +# CONFIG_DP83TD510_PHY is not set +# CONFIG_DP83TG720_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_XILINX_GMII2RGMII is not set +CONFIG_PSE_CONTROLLER=y +# CONFIG_PSE_REGULATOR is not set +# CONFIG_PSE_PD692X0 is not set +# CONFIG_PSE_SI3474 is not set +# CONFIG_PSE_TPS23881 is not set + +# +# MCTP Device Drivers +# +# CONFIG_MCTP_SERIAL is not set +# CONFIG_MCTP_TRANSPORT_I2C is not set +# CONFIG_MCTP_TRANSPORT_USB is not set +# end of MCTP Device Drivers + +CONFIG_FWNODE_MDIO=y +CONFIG_OF_MDIO=y +CONFIG_ACPI_MDIO=y +# CONFIG_MDIO_AIROHA is not set +# CONFIG_MDIO_SUN4I is not set +# CONFIG_MDIO_XGENE is not set +CONFIG_MDIO_BITBANG=y +# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_MDIO_GPIO is not set +# CONFIG_MDIO_HISI_FEMAC is not set +# CONFIG_MDIO_MVUSB is not set +# CONFIG_MDIO_MSCC_MIIM is not set +# CONFIG_MDIO_OCTEON is not set +# CONFIG_MDIO_IPQ4019 is not set +# CONFIG_MDIO_IPQ8064 is not set +# CONFIG_MDIO_THUNDER is not set + +# +# MDIO Multiplexers +# +# CONFIG_MDIO_BUS_MUX_MESON_G12A is not set +# CONFIG_MDIO_BUS_MUX_MESON_GXL is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MULTIPLEXER is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set + +# +# PCS device drivers +# +# CONFIG_PCS_XPCS is not set +CONFIG_PCS_LYNX=y +# CONFIG_PCS_RZN1_MIIC is not set +# end of PCS device drivers + +CONFIG_PPP=y +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPP_DEFLATE is not set +CONFIG_PPP_FILTER=y +# CONFIG_PPP_MPPE is not set +CONFIG_PPP_MULTILINK=y +# CONFIG_PPPOE is not set +CONFIG_PPPOE_HASH_BITS=4 +# CONFIG_PPP_ASYNC is not set +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_SLIP is not set +CONFIG_SLHC=y +# CONFIG_USB_NET_DRIVERS is not set +CONFIG_WLAN=y +CONFIG_WLAN_VENDOR_ADMTEK=y +CONFIG_WLAN_VENDOR_ATH=y +# CONFIG_ATH_DEBUG is not set +CONFIG_ATH5K_PCI=y +CONFIG_WLAN_VENDOR_ATMEL=y +CONFIG_WLAN_VENDOR_BROADCOM=y +CONFIG_WLAN_VENDOR_INTEL=y +CONFIG_WLAN_VENDOR_INTERSIL=y +CONFIG_WLAN_VENDOR_MARVELL=y +CONFIG_WLAN_VENDOR_MEDIATEK=y +CONFIG_WLAN_VENDOR_MICROCHIP=y +CONFIG_WLAN_VENDOR_PURELIFI=y +CONFIG_WLAN_VENDOR_RALINK=y +CONFIG_WLAN_VENDOR_REALTEK=y +CONFIG_WLAN_VENDOR_RSI=y +CONFIG_WLAN_VENDOR_SILABS=y +CONFIG_WLAN_VENDOR_ST=y +CONFIG_WLAN_VENDOR_TI=y +CONFIG_WLAN_VENDOR_ZYDAS=y +CONFIG_WLAN_VENDOR_QUANTENNA=y +CONFIG_WAN=y +# CONFIG_HDLC is not set +# CONFIG_FRAMER is not set +# CONFIG_SLIC_DS26522 is not set + +# +# Wireless WAN +# +# CONFIG_WWAN is not set +# end of Wireless WAN + +CONFIG_XEN_NETDEV_FRONTEND=y +# CONFIG_XEN_NETDEV_BACKEND is not set +# CONFIG_VMXNET3 is not set +# CONFIG_FUJITSU_ES is not set +# CONFIG_NETDEVSIM is not set +CONFIG_NET_FAILOVER=y +CONFIG_ISDN=y +# CONFIG_MISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_LEDS=m +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_SPARSEKMAP is not set +# CONFIG_INPUT_MATRIXKMAP is not set +CONFIG_INPUT_VIVALDIFMAP=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=y + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5520 is not set +# CONFIG_KEYBOARD_ADP5588 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1050 is not set +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_DLINK_DIR685 is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_SNVS_PWRKEY is not set +# CONFIG_KEYBOARD_IMX is not set +CONFIG_KEYBOARD_IMX_BBM_SCMI=y +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_TEGRA is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_PINEPHONE is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_STMPE is not set +# CONFIG_KEYBOARD_SUN4I_LRADC is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_TC3589X is not set +# CONFIG_KEYBOARD_TM2_TOUCHKEY is not set +# CONFIG_KEYBOARD_TWL4030 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_BCM is not set +# CONFIG_KEYBOARD_MT6779 is not set +# CONFIG_KEYBOARD_CYPRESS_SF is not set +CONFIG_INPUT_MOUSE=y +# CONFIG_MOUSE_PS2 is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set +CONFIG_INPUT_JOYSTICK=y +# CONFIG_JOYSTICK_ANALOG is not set +# CONFIG_JOYSTICK_A3D is not set +# CONFIG_JOYSTICK_ADI is not set +# CONFIG_JOYSTICK_COBRA is not set +# CONFIG_JOYSTICK_GF2K is not set +# CONFIG_JOYSTICK_GRIP is not set +# CONFIG_JOYSTICK_GRIP_MP is not set +# CONFIG_JOYSTICK_GUILLEMOT is not set +# CONFIG_JOYSTICK_INTERACT is not set +# CONFIG_JOYSTICK_SIDEWINDER is not set +# CONFIG_JOYSTICK_TMDC is not set +# CONFIG_JOYSTICK_IFORCE is not set +# CONFIG_JOYSTICK_WARRIOR is not set +# CONFIG_JOYSTICK_MAGELLAN is not set +# CONFIG_JOYSTICK_SPACEORB is not set +# CONFIG_JOYSTICK_SPACEBALL is not set +# CONFIG_JOYSTICK_STINGER is not set +# CONFIG_JOYSTICK_TWIDJOY is not set +# CONFIG_JOYSTICK_ZHENHUA is not set +# CONFIG_JOYSTICK_AS5011 is not set +# CONFIG_JOYSTICK_JOYDUMP is not set +# CONFIG_JOYSTICK_XPAD is not set +# CONFIG_JOYSTICK_PSXPAD_SPI is not set +# CONFIG_JOYSTICK_PXRC is not set +# CONFIG_JOYSTICK_QWIIC is not set +# CONFIG_JOYSTICK_FSIA6B is not set +# CONFIG_JOYSTICK_SENSEHAT is not set +# CONFIG_JOYSTICK_SEESAW is not set +CONFIG_INPUT_TABLET=y +# CONFIG_TABLET_USB_ACECAD is not set +# CONFIG_TABLET_USB_AIPTEK is not set +# CONFIG_TABLET_USB_HANWANG is not set +# CONFIG_TABLET_USB_KBTAB is not set +# CONFIG_TABLET_USB_PEGASUS is not set +# CONFIG_TABLET_SERIAL_WACOM4 is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_88PM860X is not set +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_APPLE_Z2 is not set +# CONFIG_TOUCHSCREEN_AR1021_I2C is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_BU21029 is not set +# CONFIG_TOUCHSCREEN_CHIPONE_ICN8318 is not set +# CONFIG_TOUCHSCREEN_CHIPONE_ICN8505 is not set +# CONFIG_TOUCHSCREEN_CY8CTMA140 is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP5 is not set +# CONFIG_TOUCHSCREEN_DA9034 is not set +# CONFIG_TOUCHSCREEN_DA9052 is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set +# CONFIG_TOUCHSCREEN_EXC3000 is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GOODIX is not set +# CONFIG_TOUCHSCREEN_GOODIX_BERLIN_I2C is not set +# CONFIG_TOUCHSCREEN_GOODIX_BERLIN_SPI is not set +# CONFIG_TOUCHSCREEN_HIDEEP is not set +# CONFIG_TOUCHSCREEN_HIMAX_HX852X is not set +# CONFIG_TOUCHSCREEN_HYCON_HY46XX is not set +# CONFIG_TOUCHSCREEN_HYNITRON_CSTXXX is not set +# CONFIG_TOUCHSCREEN_HYNITRON_CST816X is not set +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_ILITEK is not set +# CONFIG_TOUCHSCREEN_S6SY761 is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_EKTF2127 is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MELFAS_MIP4 is not set +# CONFIG_TOUCHSCREEN_MSG2638 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_NOVATEK_NVT_TS is not set +# CONFIG_TOUCHSCREEN_IMAGIS is not set +# CONFIG_TOUCHSCREEN_IMX6UL_TSC is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +# CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set +# CONFIG_TOUCHSCREEN_WM831X is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_TSC2004 is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_PCAP is not set +# CONFIG_TOUCHSCREEN_RM_TS is not set +# CONFIG_TOUCHSCREEN_SILEAD is not set +# CONFIG_TOUCHSCREEN_SIS_I2C is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +# CONFIG_TOUCHSCREEN_STMFTS is not set +# CONFIG_TOUCHSCREEN_STMPE is not set +# CONFIG_TOUCHSCREEN_SUN4I is not set +# CONFIG_TOUCHSCREEN_SUR40 is not set +# CONFIG_TOUCHSCREEN_SURFACE3_SPI is not set +# CONFIG_TOUCHSCREEN_SX8654 is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_ZET6223 is not set +# CONFIG_TOUCHSCREEN_ZFORCE is not set +# CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set +# CONFIG_TOUCHSCREEN_IQS5XX is not set +# CONFIG_TOUCHSCREEN_IQS7211 is not set +# CONFIG_TOUCHSCREEN_ZINITIX is not set +# CONFIG_TOUCHSCREEN_HIMAX_HX83112B is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_88PM860X_ONKEY is not set +# CONFIG_INPUT_88PM886_ONKEY is not set +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_ATMEL_CAPTOUCH is not set +# CONFIG_INPUT_AW86927 is not set +# CONFIG_INPUT_BBNSM_PWRKEY is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_E3X0_BUTTON is not set +# CONFIG_INPUT_MAX77693_HAPTIC is not set +# CONFIG_INPUT_MAX8925_ONKEY is not set +# CONFIG_INPUT_MAX8997_HAPTIC is not set +# CONFIG_INPUT_MMA8450 is not set +# CONFIG_INPUT_GPIO_BEEPER is not set +# CONFIG_INPUT_GPIO_DECODER is not set +# CONFIG_INPUT_GPIO_VIBRA is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +# CONFIG_INPUT_REGULATOR_HAPTIC is not set +# CONFIG_INPUT_TWL4030_PWRBUTTON is not set +# CONFIG_INPUT_TWL4030_VIBRA is not set +# CONFIG_INPUT_TWL6040_VIBRA is not set +CONFIG_INPUT_UINPUT=y +# CONFIG_INPUT_PALMAS_PWRBUTTON is not set +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_PWM_BEEPER is not set +# CONFIG_INPUT_PWM_VIBRA is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_DA7280_HAPTICS is not set +# CONFIG_INPUT_DA9052_ONKEY is not set +# CONFIG_INPUT_DA9055_ONKEY is not set +# CONFIG_INPUT_DA9063_ONKEY is not set +# CONFIG_INPUT_WM831X_ON is not set +# CONFIG_INPUT_PCAP is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IBM_PANEL is not set +# CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_IQS269A is not set +# CONFIG_INPUT_IQS626A is not set +# CONFIG_INPUT_IQS7222 is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_XEN_KBDDEV_FRONTEND is not set +# CONFIG_INPUT_DRV260X_HAPTICS is not set +# CONFIG_INPUT_DRV2665_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set +# CONFIG_INPUT_HISI_POWERKEY is not set +# CONFIG_RMI4_CORE is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_SERIO_SUN4I_PS2 is not set +# CONFIG_SERIO_GPIO_PS2 is not set +# CONFIG_USERIO is not set +# CONFIG_GAMEPORT is not set +# end of Hardware I/O ports +# end of Input device support + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=0 +# CONFIG_LEGACY_TIOCSTI is not set +CONFIG_LDISC_AUTOLOAD=y + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_16550A_VARIANTS=y +CONFIG_SERIAL_8250_FINTEK=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_DMA=y +CONFIG_SERIAL_8250_PCILIB=y +CONFIG_SERIAL_8250_PCI=y +# CONFIG_SERIAL_8250_EXAR is not set +CONFIG_SERIAL_8250_NR_UARTS=48 +CONFIG_SERIAL_8250_RUNTIME_UARTS=32 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +# CONFIG_SERIAL_8250_PCI1XXXX is not set +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +CONFIG_SERIAL_8250_RSA=y +CONFIG_SERIAL_8250_DWLIB=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_DW=y +# CONFIG_SERIAL_8250_EM is not set +CONFIG_SERIAL_8250_RT288X=y +CONFIG_SERIAL_8250_OMAP=y +CONFIG_SERIAL_8250_OMAP_TTYO_FIXUP=y +CONFIG_SERIAL_8250_MT6577=y +# CONFIG_SERIAL_8250_PERICOM is not set +CONFIG_SERIAL_8250_TEGRA=y +CONFIG_SERIAL_OF_PLATFORM=y + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_EARLYCON_SEMIHOST=y +# CONFIG_SERIAL_ATMEL is not set +CONFIG_SERIAL_MESON=y +CONFIG_SERIAL_MESON_CONSOLE=y +# CONFIG_SERIAL_SAMSUNG is not set +# CONFIG_SERIAL_TEGRA is not set +CONFIG_SERIAL_TEGRA_TCU=y +CONFIG_SERIAL_TEGRA_TCU_CONSOLE=y +# CONFIG_SERIAL_TEGRA_UTC is not set +# CONFIG_SERIAL_MAX3100 is not set +CONFIG_SERIAL_MAX310X=y +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +# CONFIG_SERIAL_IMX_EARLYCON is not set +# CONFIG_SERIAL_UARTLITE is not set +CONFIG_SERIAL_SH_SCI=y +CONFIG_SERIAL_SH_SCI_NR_UARTS=2 +CONFIG_SERIAL_SH_SCI_CONSOLE=y +CONFIG_SERIAL_SH_SCI_EARLYCON=y +CONFIG_SERIAL_SH_SCI_DMA=y +# CONFIG_SERIAL_RSCI is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_CONSOLE_POLL=y +# CONFIG_SERIAL_JSM is not set +CONFIG_SERIAL_MSM=y +CONFIG_SERIAL_MSM_CONSOLE=y +CONFIG_SERIAL_QCOM_GENI=y +CONFIG_SERIAL_QCOM_GENI_CONSOLE=y +CONFIG_SERIAL_QCOM_GENI_UART_PORTS=8 +# CONFIG_SERIAL_SIFIVE is not set +# CONFIG_SERIAL_QE is not set +CONFIG_SERIAL_SCCNXP=y +CONFIG_SERIAL_SCCNXP_CONSOLE=y +# CONFIG_SERIAL_SC16IS7XX is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_RP2 is not set +# CONFIG_SERIAL_FSL_LPUART is not set +# CONFIG_SERIAL_FSL_LINFLEXUART is not set +# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set +# CONFIG_SERIAL_SPRD is not set +# CONFIG_SERIAL_STM32 is not set +CONFIG_SERIAL_MVEBU_UART=y +CONFIG_SERIAL_MVEBU_CONSOLE=y +CONFIG_SERIAL_OWL=y +CONFIG_SERIAL_OWL_CONSOLE=y +# CONFIG_SERIAL_NUVOTON_MA35D1 is not set +# end of Serial drivers + +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_N_HDLC is not set +# CONFIG_N_GSM is not set +# CONFIG_NOZOMI is not set +# CONFIG_NULL_TTY is not set +CONFIG_HVC_DRIVER=y +CONFIG_HVC_IRQ=y +CONFIG_HVC_XEN=y +CONFIG_HVC_XEN_FRONTEND=y +# CONFIG_HVC_DCC is not set +CONFIG_SERIAL_DEV_BUS=y +CONFIG_SERIAL_DEV_CTRL_TTYPORT=y +CONFIG_TTY_PRINTK=y +CONFIG_TTY_PRINTK_LEVEL=6 +CONFIG_VIRTIO_CONSOLE=y +# CONFIG_IPMI_HANDLER is not set +# CONFIG_NPCM7XX_KCS_IPMI_BMC is not set +# CONFIG_SSIF_IPMI_BMC is not set +# CONFIG_IPMB_DEVICE_INTERFACE is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_HW_RANDOM_AIROHA is not set +CONFIG_HW_RANDOM_ATMEL=y +# CONFIG_HW_RANDOM_BA431 is not set +# CONFIG_HW_RANDOM_OMAP is not set +# CONFIG_HW_RANDOM_VIRTIO is not set +# CONFIG_HW_RANDOM_HISI is not set +# CONFIG_HW_RANDOM_HISTB is not set +# CONFIG_HW_RANDOM_XGENE is not set +# CONFIG_HW_RANDOM_STM32 is not set +# CONFIG_HW_RANDOM_MESON is not set +# CONFIG_HW_RANDOM_CAVIUM is not set +# CONFIG_HW_RANDOM_MTK is not set +# CONFIG_HW_RANDOM_NPCM is not set +# CONFIG_HW_RANDOM_CCTRNG is not set +# CONFIG_HW_RANDOM_XIPHERA is not set +# CONFIG_HW_RANDOM_ARM_SMCCC_TRNG is not set +# CONFIG_HW_RANDOM_CN10K is not set +CONFIG_HW_RANDOM_ROCKCHIP=y +# CONFIG_APPLICOM is not set +CONFIG_DEVMEM=y +CONFIG_DEVPORT=y +CONFIG_TCG_TPM=y +# CONFIG_TCG_TPM2_HMAC is not set +CONFIG_HW_RANDOM_TPM=y +CONFIG_TCG_TIS_CORE=y +CONFIG_TCG_TIS=y +CONFIG_TCG_TIS_SPI=y +CONFIG_TCG_TIS_SPI_CR50=y +# CONFIG_TCG_TIS_I2C is not set +# CONFIG_TCG_TIS_SYNQUACER is not set +# CONFIG_TCG_TIS_I2C_CR50 is not set +# CONFIG_TCG_TIS_I2C_ATMEL is not set +# CONFIG_TCG_TIS_I2C_INFINEON is not set +# CONFIG_TCG_TIS_I2C_NUVOTON is not set +# CONFIG_TCG_ATMEL is not set +# CONFIG_TCG_INFINEON is not set +# CONFIG_TCG_XEN is not set +CONFIG_TCG_CRB=y +# CONFIG_TCG_VTPM_PROXY is not set +# CONFIG_TCG_TIS_ST33ZP24_I2C is not set +# CONFIG_TCG_TIS_ST33ZP24_SPI is not set +# CONFIG_XILLYBUS is not set +# CONFIG_XILLYUSB is not set +# end of Character devices + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_ACPI_I2C_OPREGION=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=m + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_GPMUX is not set +# CONFIG_I2C_MUX_LTC4306 is not set +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL is not set +# CONFIG_I2C_MUX_REG is not set +# CONFIG_I2C_DEMUX_PINCTRL is not set +# CONFIG_I2C_MUX_MLXCPLD is not set +# end of Multiplexer I2C Chip support + +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_AMD_MP2 is not set +# CONFIG_I2C_HIX5HD2 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_NVIDIA_GPU is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_ZHAOXIN is not set + +# +# ACPI drivers +# +# CONFIG_I2C_SCMI is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_ALTERA is not set +# CONFIG_I2C_AT91 is not set +# CONFIG_I2C_CADENCE is not set +# CONFIG_I2C_CBUS_GPIO is not set +CONFIG_I2C_DESIGNWARE_CORE=y +# CONFIG_I2C_DESIGNWARE_SLAVE is not set +CONFIG_I2C_DESIGNWARE_PLATFORM=y +# CONFIG_I2C_DESIGNWARE_PCI is not set +# CONFIG_I2C_EMEV2 is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_HISI is not set +# CONFIG_I2C_IMX is not set +# CONFIG_I2C_IMX_LPI2C is not set +# CONFIG_I2C_MLXBF is not set +# CONFIG_I2C_MESON is not set +# CONFIG_I2C_MT65XX is not set +# CONFIG_I2C_MT7621 is not set +# CONFIG_I2C_MV64XXX is not set +# CONFIG_I2C_NOMADIK is not set +# CONFIG_I2C_NPCM is not set +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_OMAP=y +# CONFIG_I2C_OWL is not set +# CONFIG_I2C_APPLE is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA is not set +# CONFIG_I2C_QCOM_CCI is not set +# CONFIG_I2C_QCOM_GENI is not set +# CONFIG_I2C_QUP is not set +# CONFIG_I2C_RIIC is not set +# CONFIG_I2C_RK3X is not set +# CONFIG_I2C_RZV2M is not set +# CONFIG_I2C_SH_MOBILE is not set +# CONFIG_I2C_SIMTEC is not set +CONFIG_I2C_SPRD=y +# CONFIG_I2C_STM32F4 is not set +# CONFIG_I2C_STM32F7 is not set +# CONFIG_I2C_SYNQUACER is not set +# CONFIG_I2C_TEGRA is not set +# CONFIG_I2C_TEGRA_BPMP is not set +# CONFIG_I2C_VERSATILE is not set +# CONFIG_I2C_THUNDERX is not set +# CONFIG_I2C_XILINX is not set +# CONFIG_I2C_XLP9XX is not set +# CONFIG_I2C_RCAR is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_CP2615 is not set +# CONFIG_I2C_PCI1XXXX is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_MLXCPLD is not set +# CONFIG_I2C_XGENE_SLIMPRO is not set +# CONFIG_I2C_VIRTIO is not set +# end of I2C Hardware Bus support + +# CONFIG_I2C_STUB is not set +CONFIG_I2C_SLAVE=y +# CONFIG_I2C_SLAVE_EEPROM is not set +# CONFIG_I2C_SLAVE_TESTUNIT is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# end of I2C support + +# CONFIG_I3C is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_AIROHA_SNFI is not set +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_AMLOGIC_SPIFC_A1 is not set +# CONFIG_SPI_AMLOGIC_SPIFC_A4 is not set +# CONFIG_SPI_AMLOGIC_SPISG is not set +# CONFIG_SPI_APPLE is not set +# CONFIG_SPI_ARMADA_3700 is not set +# CONFIG_SPI_ATMEL is not set +# CONFIG_SPI_AXI_SPI_ENGINE is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_CADENCE_QUADSPI is not set +# CONFIG_SPI_CADENCE_XSPI is not set +# CONFIG_SPI_CH341 is not set +# CONFIG_SPI_DESIGNWARE is not set +# CONFIG_SPI_FSL_LPSPI is not set +# CONFIG_SPI_FSL_QUADSPI is not set +# CONFIG_SPI_HISI_KUNPENG is not set +# CONFIG_SPI_HISI_SFC_V3XX is not set +# CONFIG_SPI_NXP_FLEXSPI is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_IMX is not set +CONFIG_SPI_FSL_LIB=y +CONFIG_SPI_FSL_SPI=y +# CONFIG_SPI_FSL_DSPI is not set +# CONFIG_SPI_MESON_SPICC is not set +# CONFIG_SPI_MESON_SPIFC is not set +# CONFIG_SPI_MICROCHIP_CORE is not set +# CONFIG_SPI_MICROCHIP_CORE_QSPI is not set +# CONFIG_SPI_MT65XX is not set +# CONFIG_SPI_MTK_NOR is not set +# CONFIG_SPI_WPCM_FIU is not set +# CONFIG_SPI_NPCM_FIU is not set +# CONFIG_SPI_NPCM_PSPI is not set +# CONFIG_SPI_OC_TINY is not set +CONFIG_SPI_OMAP24XX=y +# CONFIG_SPI_ORION is not set +# CONFIG_SPI_PCI1XXXX is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_ROCKCHIP is not set +# CONFIG_SPI_ROCKCHIP_SFC is not set +# CONFIG_SPI_RSPI is not set +# CONFIG_SPI_RZV2H_RSPI is not set +# CONFIG_SPI_RZV2M_CSI is not set +# CONFIG_SPI_QCOM_QSPI is not set +# CONFIG_SPI_QUP is not set +# CONFIG_SPI_QCOM_GENI is not set +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_SH_MSIOF is not set +# CONFIG_SPI_SH_HSPI is not set +# CONFIG_SPI_SIFIVE is not set +# CONFIG_SPI_SLAVE_MT27XX is not set +# CONFIG_SPI_SN_F_OSPI is not set +# CONFIG_SPI_SPRD is not set +# CONFIG_SPI_SPRD_ADI is not set +# CONFIG_SPI_STM32 is not set +# CONFIG_SPI_STM32_OSPI is not set +# CONFIG_SPI_STM32_QSPI is not set +# CONFIG_SPI_SUN4I is not set +# CONFIG_SPI_SUN6I is not set +# CONFIG_SPI_SYNQUACER is not set +# CONFIG_SPI_MXIC is not set +CONFIG_SPI_TEGRA210_QUAD=y +# CONFIG_SPI_TEGRA114 is not set +# CONFIG_SPI_TEGRA20_SFLASH is not set +# CONFIG_SPI_TEGRA20_SLINK is not set +# CONFIG_SPI_THUNDERX is not set +# CONFIG_SPI_VIRTIO is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_XLP is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set +# CONFIG_SPI_AMD is not set + +# +# SPI Multiplexer support +# +# CONFIG_SPI_MUX is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_LOOPBACK_TEST is not set +# CONFIG_SPI_TLE62X0 is not set +CONFIG_SPI_SLAVE=y +# CONFIG_SPI_SLAVE_TIME is not set +# CONFIG_SPI_SLAVE_SYSTEM_CONTROL is not set +CONFIG_SPI_DYNAMIC=y +# CONFIG_SPMI is not set +# CONFIG_HSI is not set +CONFIG_PPS=y +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_GPIO is not set +# CONFIG_PPS_GENERATOR is not set + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +# CONFIG_DP83640_PHY is not set +# CONFIG_PTP_1588_CLOCK_INES is not set +# CONFIG_PTP_1588_CLOCK_KVM is not set +# CONFIG_PTP_1588_CLOCK_VMCLOCK is not set +# CONFIG_PTP_1588_CLOCK_IDT82P33 is not set +# CONFIG_PTP_1588_CLOCK_IDTCM is not set +# CONFIG_PTP_1588_CLOCK_FC3W is not set +# CONFIG_PTP_1588_CLOCK_MOCK is not set +# CONFIG_PTP_NETC_V4_TIMER is not set +# end of PTP clock support + +# +# DPLL device support +# +# CONFIG_ZL3073X_I2C is not set +# CONFIG_ZL3073X_SPI is not set +# end of DPLL device support + +CONFIG_PINCTRL=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_PINMUX=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_PINCONF=y +CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +CONFIG_PINCTRL_AMD=y +# CONFIG_PINCTRL_APPLE_GPIO is not set +CONFIG_PINCTRL_AS3722=y +# CONFIG_PINCTRL_AW9523 is not set +CONFIG_PINCTRL_BM1880=y +# CONFIG_PINCTRL_CY8C95X0 is not set +# CONFIG_PINCTRL_KEEMBAY is not set +# CONFIG_PINCTRL_MAX77620 is not set +# CONFIG_PINCTRL_MCP23S08 is not set +CONFIG_PINCTRL_MICROCHIP_SGPIO=y +CONFIG_PINCTRL_OCELOT=y +CONFIG_PINCTRL_PALMAS=y +CONFIG_PINCTRL_ROCKCHIP=y +# CONFIG_PINCTRL_SCMI is not set +CONFIG_PINCTRL_SINGLE=y +# CONFIG_PINCTRL_STMFX is not set +CONFIG_PINCTRL_SX150X=y +# CONFIG_PINCTRL_ZYNQMP is not set +# CONFIG_PINCTRL_MLXBF3 is not set +CONFIG_PINCTRL_OWL=y +CONFIG_PINCTRL_S700=y +CONFIG_PINCTRL_S900=y +CONFIG_PINCTRL_BERLIN=y +CONFIG_PINCTRL_AS370=y +CONFIG_PINCTRL_BERLIN_BG4CT=y +# CONFIG_PINCTRL_LOCHNAGAR is not set +CONFIG_PINCTRL_IMX=y +# CONFIG_PINCTRL_IMX_SCMI is not set +CONFIG_PINCTRL_IMX8MM=y +CONFIG_PINCTRL_IMX8MN=y +CONFIG_PINCTRL_IMX8MP=y +CONFIG_PINCTRL_IMX8MQ=y +# CONFIG_PINCTRL_IMX8ULP is not set +# CONFIG_PINCTRL_IMX91 is not set +# CONFIG_PINCTRL_IMX93 is not set + +# +# MediaTek pinctrl drivers +# +CONFIG_EINT_MTK=y +CONFIG_PINCTRL_MTK=y +CONFIG_PINCTRL_MTK_V2=y +CONFIG_PINCTRL_MTK_MOORE=y +CONFIG_PINCTRL_MTK_PARIS=y +# CONFIG_PINCTRL_AIROHA is not set +CONFIG_PINCTRL_MT2712=y +CONFIG_PINCTRL_MT6765=y +# CONFIG_PINCTRL_MT6779 is not set +CONFIG_PINCTRL_MT6795=y +CONFIG_PINCTRL_MT6797=y +CONFIG_PINCTRL_MT6893=y +CONFIG_PINCTRL_MT7622=y +CONFIG_PINCTRL_MT7981=y +CONFIG_PINCTRL_MT7986=y +CONFIG_PINCTRL_MT7988=y +CONFIG_PINCTRL_MT8167=y +CONFIG_PINCTRL_MT8173=y +CONFIG_PINCTRL_MT8183=y +CONFIG_PINCTRL_MT8186=y +CONFIG_PINCTRL_MT8188=y +CONFIG_PINCTRL_MT8189=y +CONFIG_PINCTRL_MT8192=y +CONFIG_PINCTRL_MT8195=y +CONFIG_PINCTRL_MT8196=y +CONFIG_PINCTRL_MT8365=y +CONFIG_PINCTRL_MT8516=y +# end of MediaTek pinctrl drivers + +CONFIG_PINCTRL_MESON=y +CONFIG_PINCTRL_MESON_GXBB=y +CONFIG_PINCTRL_MESON_GXL=y +CONFIG_PINCTRL_MESON8_PMX=y +CONFIG_PINCTRL_MESON_AXG=y +CONFIG_PINCTRL_MESON_AXG_PMX=y +CONFIG_PINCTRL_MESON_G12A=y +CONFIG_PINCTRL_MESON_A1=y +# CONFIG_PINCTRL_MESON_S4 is not set +CONFIG_PINCTRL_AMLOGIC_A4=y +# CONFIG_PINCTRL_AMLOGIC_C3 is not set +# CONFIG_PINCTRL_AMLOGIC_T7 is not set +CONFIG_PINCTRL_MVEBU=y +CONFIG_PINCTRL_ARMADA_AP806=y +CONFIG_PINCTRL_ARMADA_CP110=y +CONFIG_PINCTRL_AC5=y +CONFIG_PINCTRL_ARMADA_37XX=y +# CONFIG_PINCTRL_NPCM8XX is not set +CONFIG_PINCTRL_MA35=y +CONFIG_PINCTRL_MA35D1=y +CONFIG_PINCTRL_S32CC=y +CONFIG_PINCTRL_S32G2=y +CONFIG_PINCTRL_MSM=y +# CONFIG_PINCTRL_GLYMUR is not set +# CONFIG_PINCTRL_IPQ5018 is not set +# CONFIG_PINCTRL_IPQ5332 is not set +# CONFIG_PINCTRL_IPQ5424 is not set +# CONFIG_PINCTRL_IPQ8074 is not set +# CONFIG_PINCTRL_IPQ6018 is not set +# CONFIG_PINCTRL_IPQ9574 is not set +# CONFIG_PINCTRL_MDM9607 is not set +# CONFIG_PINCTRL_MSM8916 is not set +# CONFIG_PINCTRL_MSM8917 is not set +# CONFIG_PINCTRL_MSM8953 is not set +# CONFIG_PINCTRL_MSM8976 is not set +# CONFIG_PINCTRL_MSM8994 is not set +# CONFIG_PINCTRL_MSM8996 is not set +# CONFIG_PINCTRL_MSM8998 is not set +# CONFIG_PINCTRL_QCM2290 is not set +# CONFIG_PINCTRL_QCS404 is not set +# CONFIG_PINCTRL_QCS615 is not set +# CONFIG_PINCTRL_QCS8300 is not set +# CONFIG_PINCTRL_QDF2XXX is not set +# CONFIG_PINCTRL_QDU1000 is not set +# CONFIG_PINCTRL_SA8775P is not set +# CONFIG_PINCTRL_SAR2130P is not set +# CONFIG_PINCTRL_SC7180 is not set +# CONFIG_PINCTRL_SC7280 is not set +# CONFIG_PINCTRL_SC8180X is not set +# CONFIG_PINCTRL_SC8280XP is not set +# CONFIG_PINCTRL_SDM660 is not set +# CONFIG_PINCTRL_SDM670 is not set +# CONFIG_PINCTRL_SDM845 is not set +# CONFIG_PINCTRL_SDX75 is not set +# CONFIG_PINCTRL_SM4450 is not set +# CONFIG_PINCTRL_SM6115 is not set +# CONFIG_PINCTRL_SM6125 is not set +# CONFIG_PINCTRL_SM6350 is not set +# CONFIG_PINCTRL_SM6375 is not set +# CONFIG_PINCTRL_SM7150 is not set +# CONFIG_PINCTRL_MILOS is not set +# CONFIG_PINCTRL_SM8150 is not set +# CONFIG_PINCTRL_SM8250 is not set +# CONFIG_PINCTRL_SM8350 is not set +# CONFIG_PINCTRL_SM8450 is not set +# CONFIG_PINCTRL_SM8550 is not set +# CONFIG_PINCTRL_SM8650 is not set +# CONFIG_PINCTRL_SM8750 is not set +# CONFIG_PINCTRL_X1E80100 is not set +# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set +# CONFIG_PINCTRL_LPASS_LPI is not set +# CONFIG_PINCTRL_RTD is not set + +# +# Renesas pinctrl drivers +# +CONFIG_PINCTRL_RENESAS=y +CONFIG_PINCTRL_SH_PFC=y +CONFIG_PINCTRL_PFC_R8A774A1=y +CONFIG_PINCTRL_PFC_R8A774B1=y +CONFIG_PINCTRL_PFC_R8A774C0=y +CONFIG_PINCTRL_PFC_R8A774E1=y +CONFIG_PINCTRL_PFC_R8A77951=y +CONFIG_PINCTRL_PFC_R8A77960=y +CONFIG_PINCTRL_PFC_R8A77961=y +CONFIG_PINCTRL_PFC_R8A77965=y +CONFIG_PINCTRL_PFC_R8A77970=y +CONFIG_PINCTRL_PFC_R8A77980=y +CONFIG_PINCTRL_PFC_R8A77990=y +CONFIG_PINCTRL_PFC_R8A77995=y +CONFIG_PINCTRL_PFC_R8A779A0=y +CONFIG_PINCTRL_PFC_R8A779F0=y +CONFIG_PINCTRL_PFC_R8A779G0=y +CONFIG_PINCTRL_PFC_R8A779H0=y +CONFIG_PINCTRL_RZG2L=y +CONFIG_PINCTRL_RZT2H=y +CONFIG_PINCTRL_RZV2M=y +# end of Renesas pinctrl drivers + +CONFIG_PINCTRL_SPRD=y +CONFIG_PINCTRL_SPRD_SC9860=y +CONFIG_PINCTRL_STM32=y +CONFIG_PINCTRL_STM32MP257=y +CONFIG_PINCTRL_STM32_HDP=y +CONFIG_PINCTRL_SUNXI=y +CONFIG_PINCTRL_SUN4I_A10=y +CONFIG_PINCTRL_SUN5I=y +CONFIG_PINCTRL_SUN6I_A31=y +CONFIG_PINCTRL_SUN6I_A31_R=y +CONFIG_PINCTRL_SUN8I_A23=y +CONFIG_PINCTRL_SUN8I_A33=y +CONFIG_PINCTRL_SUN8I_A83T=y +CONFIG_PINCTRL_SUN8I_A83T_R=y +CONFIG_PINCTRL_SUN8I_A23_R=y +CONFIG_PINCTRL_SUN8I_H3=y +CONFIG_PINCTRL_SUN8I_H3_R=y +CONFIG_PINCTRL_SUN8I_V3S=y +CONFIG_PINCTRL_SUN9I_A80=y +CONFIG_PINCTRL_SUN9I_A80_R=y +CONFIG_PINCTRL_SUN20I_D1=y +CONFIG_PINCTRL_SUN50I_A64=y +CONFIG_PINCTRL_SUN50I_A64_R=y +CONFIG_PINCTRL_SUN50I_A100=y +CONFIG_PINCTRL_SUN50I_A100_R=y +CONFIG_PINCTRL_SUN50I_H5=y +CONFIG_PINCTRL_SUN50I_H6=y +CONFIG_PINCTRL_SUN50I_H6_R=y +CONFIG_PINCTRL_SUN50I_H616=y +CONFIG_PINCTRL_SUN50I_H616_R=y +CONFIG_PINCTRL_SUN55I_A523=y +CONFIG_PINCTRL_SUN55I_A523_R=y +CONFIG_PINCTRL_TEGRA=y +CONFIG_PINCTRL_TEGRA124=y +CONFIG_PINCTRL_TEGRA210=y +CONFIG_PINCTRL_TEGRA186=y +CONFIG_PINCTRL_TEGRA194=y +CONFIG_PINCTRL_TEGRA234=y +CONFIG_PINCTRL_TEGRA_XUSB=y +CONFIG_PINCTRL_VISCONTI=y +CONFIG_PINCTRL_TMPV7700=y +CONFIG_GPIOLIB_LEGACY=y +CONFIG_GPIOLIB=y +CONFIG_GPIOLIB_FASTPATH_LIMIT=512 +CONFIG_OF_GPIO=y +CONFIG_GPIO_ACPI=y +CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_SYSFS_LEGACY=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_CDEV_V1=y +CONFIG_GPIO_GENERIC=y + +# +# Memory mapped GPIO drivers +# +# CONFIG_GPIO_74XX_MMIO is not set +# CONFIG_GPIO_ALTERA is not set +# CONFIG_GPIO_AMDPT is not set +CONFIG_GPIO_BLZP1600=y +# CONFIG_GPIO_CADENCE is not set +CONFIG_GPIO_DAVINCI=y +# CONFIG_GPIO_DWAPB is not set +# CONFIG_GPIO_EIC_SPRD is not set +# CONFIG_GPIO_EN7523 is not set +CONFIG_GPIO_FTGPIO010=y +CONFIG_GPIO_GENERIC_PLATFORM=y +# CONFIG_GPIO_GRGPIO is not set +# CONFIG_GPIO_HISI is not set +# CONFIG_GPIO_HLWD is not set +# CONFIG_GPIO_LOGICVC is not set +# CONFIG_GPIO_MB86S7X is not set +CONFIG_GPIO_MPC8XXX=y +CONFIG_GPIO_MVEBU=y +CONFIG_GPIO_MXC=y +CONFIG_GPIO_NPCM_SGPIO=y +CONFIG_GPIO_PL061=y +CONFIG_GPIO_POLARFIRE_SOC=y +# CONFIG_GPIO_RCAR is not set +# CONFIG_GPIO_ROCKCHIP is not set +# CONFIG_GPIO_RTD is not set +CONFIG_GPIO_SIFIVE=y +# CONFIG_GPIO_SPRD is not set +# CONFIG_GPIO_SYSCON is not set +CONFIG_GPIO_TEGRA=y +CONFIG_GPIO_TEGRA186=y +# CONFIG_GPIO_THUNDERX is not set +CONFIG_GPIO_VF610=y +# CONFIG_GPIO_VISCONTI is not set +CONFIG_GPIO_XGENE=y +# CONFIG_GPIO_XGENE_SB is not set +CONFIG_GPIO_XILINX=y +# CONFIG_GPIO_XLP is not set +# CONFIG_GPIO_ZYNQ is not set +# CONFIG_GPIO_ZYNQMP_MODEPIN is not set +# CONFIG_GPIO_AMD_FCH is not set +# end of Memory mapped GPIO drivers + +# +# I2C GPIO expanders +# +# CONFIG_GPIO_ADNP is not set +# CONFIG_GPIO_FXL6408 is not set +# CONFIG_GPIO_DS4520 is not set +# CONFIG_GPIO_GW_PLD is not set +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCA9570 is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_TPIC2810 is not set +# end of I2C GPIO expanders + +# +# MFD GPIO expanders +# +# CONFIG_GPIO_ADP5520 is not set +# CONFIG_GPIO_ALTERA_A10SR is not set +# CONFIG_GPIO_DA9052 is not set +# CONFIG_GPIO_DA9055 is not set +# CONFIG_GPIO_MAX77620 is not set +CONFIG_GPIO_PALMAS=y +CONFIG_GPIO_RC5T583=y +CONFIG_GPIO_STMPE=y +CONFIG_GPIO_TC3589X=y +CONFIG_GPIO_TPS6586X=y +CONFIG_GPIO_TPS65910=y +# CONFIG_GPIO_TPS65912 is not set +# CONFIG_GPIO_TWL4030 is not set +# CONFIG_GPIO_TWL6040 is not set +# CONFIG_GPIO_WM831X is not set +# CONFIG_GPIO_WM8350 is not set +# end of MFD GPIO expanders + +# +# PCI GPIO expanders +# +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_MLXBF is not set +# CONFIG_GPIO_MLXBF2 is not set +# CONFIG_GPIO_MLXBF3 is not set +# CONFIG_GPIO_PCI_IDIO_16 is not set +# CONFIG_GPIO_PCIE_IDIO_24 is not set +# CONFIG_GPIO_RDC321X is not set +# end of PCI GPIO expanders + +# +# SPI GPIO expanders +# +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX3191X is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_PISOSR is not set +# CONFIG_GPIO_XRA1403 is not set +# end of SPI GPIO expanders + +# +# USB GPIO expanders +# +# CONFIG_GPIO_MPSSE is not set +# end of USB GPIO expanders + +# +# Virtual GPIO drivers +# +# CONFIG_GPIO_AGGREGATOR is not set +# CONFIG_GPIO_LATCH is not set +# CONFIG_GPIO_MOCKUP is not set +# CONFIG_GPIO_VIRTIO is not set +# CONFIG_GPIO_SIM is not set +# end of Virtual GPIO drivers + +# +# GPIO Debugging utilities +# +# CONFIG_GPIO_SLOPPY_LOGIC_ANALYZER is not set +# CONFIG_GPIO_VIRTUSER is not set +# end of GPIO Debugging utilities + +# CONFIG_W1 is not set +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_AS3722=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_POWER_RESET_GPIO_RESTART=y +CONFIG_POWER_RESET_HISI=y +# CONFIG_POWER_RESET_LINKSTATION is not set +CONFIG_POWER_RESET_MSM=y +CONFIG_POWER_RESET_OCELOT_RESET=y +CONFIG_POWER_RESET_ODROID_GO_ULTRA_POWEROFF=y +CONFIG_POWER_RESET_LTC2952=y +CONFIG_POWER_RESET_REGULATOR=y +CONFIG_POWER_RESET_RESTART=y +# CONFIG_POWER_RESET_TORADEX_EC is not set +CONFIG_POWER_RESET_VEXPRESS=y +# CONFIG_POWER_RESET_XGENE is not set +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_RESET_SYSCON_POWEROFF=y +# CONFIG_SYSCON_REBOOT_MODE is not set +# CONFIG_NVMEM_REBOOT_MODE is not set +# CONFIG_POWER_SEQUENCING is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +CONFIG_POWER_SUPPLY_HWMON=y +# CONFIG_IP5XXX_POWER is not set +# CONFIG_MAX8925_POWER is not set +# CONFIG_WM831X_BACKUP is not set +# CONFIG_WM831X_POWER is not set +# CONFIG_WM8350_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_88PM860X is not set +# CONFIG_CHARGER_ADP5061 is not set +# CONFIG_BATTERY_CHAGALL is not set +# CONFIG_BATTERY_CW2015 is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +CONFIG_BATTERY_SAMSUNG_SDI=y +# CONFIG_BATTERY_SBS is not set +# CONFIG_CHARGER_SBS is not set +# CONFIG_MANAGER_SBS is not set +# CONFIG_BATTERY_BQ27XXX is not set +# CONFIG_BATTERY_DA9030 is not set +# CONFIG_BATTERY_DA9052 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_BATTERY_MAX1720X is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +CONFIG_CHARGER_MANAGER=y +# CONFIG_CHARGER_LT3651 is not set +# CONFIG_CHARGER_LTC4162L is not set +# CONFIG_CHARGER_MAX14577 is not set +# CONFIG_CHARGER_DETECTOR_MAX14656 is not set +# CONFIG_CHARGER_MAX77693 is not set +# CONFIG_CHARGER_MAX77976 is not set +# CONFIG_CHARGER_MAX8971 is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24257 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_BQ2515X is not set +# CONFIG_CHARGER_BQ25890 is not set +# CONFIG_CHARGER_BQ25980 is not set +# CONFIG_CHARGER_BQ256XX is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_CHARGER_TPS65090 is not set +# CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_BATTERY_GOLDFISH is not set +# CONFIG_BATTERY_RT5033 is not set +# CONFIG_CHARGER_RT9455 is not set +# CONFIG_CHARGER_RT9467 is not set +# CONFIG_CHARGER_RT9471 is not set +# CONFIG_FUEL_GAUGE_STC3117 is not set +# CONFIG_CHARGER_UCS1002 is not set +# CONFIG_CHARGER_BD99954 is not set +# CONFIG_BATTERY_UG3105 is not set +# CONFIG_FUEL_GAUGE_MM8013 is not set +CONFIG_HWMON=y +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM1177 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7310 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_AHT10 is not set +# CONFIG_SENSORS_AQUACOMPUTER_D5NEXT is not set +# CONFIG_SENSORS_AS370 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ASUS_ROG_RYUJIN is not set +# CONFIG_SENSORS_AXI_FAN_CONTROL is not set +# CONFIG_SENSORS_ARM_SCMI is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_CHIPCAP2 is not set +# CONFIG_SENSORS_CORSAIR_CPRO is not set +# CONFIG_SENSORS_CORSAIR_PSU is not set +# CONFIG_SENSORS_DRIVETEMP is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_DA9052_ADC is not set +# CONFIG_SENSORS_DA9055 is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_SPARX5 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_FTSTEUTATES is not set +# CONFIG_SENSORS_GIGABYTE_WATERFORCE is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_HS3001 is not set +# CONFIG_SENSORS_HTU31 is not set +# CONFIG_SENSORS_ISL28022 is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWERZ is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LOCHNAGAR is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC2947_I2C is not set +# CONFIG_SENSORS_LTC2947_SPI is not set +# CONFIG_SENSORS_LTC2990 is not set +# CONFIG_SENSORS_LTC2991 is not set +# CONFIG_SENSORS_LTC2992 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4222 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4260 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LTC4282 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX127 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX31722 is not set +# CONFIG_SENSORS_MAX31730 is not set +# CONFIG_SENSORS_MAX31760 is not set +# CONFIG_MAX31827 is not set +# CONFIG_SENSORS_MAX6620 is not set +# CONFIG_SENSORS_MAX6621 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_MAX31790 is not set +# CONFIG_SENSORS_MC34VR500 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_MLXREG_FAN is not set +# CONFIG_SENSORS_TC654 is not set +# CONFIG_SENSORS_TPS23861 is not set +# CONFIG_SENSORS_MR75203 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_NCT6775_I2C is not set +# CONFIG_SENSORS_NCT7363 is not set +# CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NCT7904 is not set +# CONFIG_SENSORS_NPCM7XX is not set +# CONFIG_SENSORS_NZXT_KRAKEN2 is not set +# CONFIG_SENSORS_NZXT_KRAKEN3 is not set +# CONFIG_SENSORS_NZXT_SMART2 is not set +# CONFIG_SENSORS_OCC_P8_I2C is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_PT5161L is not set +# CONFIG_SENSORS_PWM_FAN is not set +# CONFIG_SENSORS_SBTSI is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHT3x is not set +# CONFIG_SENSORS_SHT4x is not set +# CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC2305 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH5627 is not set +# CONFIG_SENSORS_SCH5636 is not set +# CONFIG_SENSORS_STTS751 is not set +# CONFIG_SENSORS_ADC128D818 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_INA238 is not set +# CONFIG_SENSORS_INA3221 is not set +# CONFIG_SENSORS_SPD5118 is not set +# CONFIG_SENSORS_TC74 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP108 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_TMP464 is not set +# CONFIG_SENSORS_TMP513 is not set +# CONFIG_SENSORS_VEXPRESS is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83773G is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_WM831X is not set +# CONFIG_SENSORS_WM8350 is not set +# CONFIG_SENSORS_XGENE is not set + +# +# ACPI drivers +# +# CONFIG_SENSORS_ACPI_POWER is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_NETLINK=y +CONFIG_THERMAL_STATISTICS=y +# CONFIG_THERMAL_DEBUGFS is not set +# CONFIG_THERMAL_CORE_TESTING is not set +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set +# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set +CONFIG_THERMAL_GOV_FAIR_SHARE=y +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_GOV_BANG_BANG=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y +CONFIG_CPU_THERMAL=y +CONFIG_CPU_FREQ_THERMAL=y +CONFIG_CPU_IDLE_THERMAL=y +CONFIG_DEVFREQ_THERMAL=y +CONFIG_PCIE_THERMAL=y +CONFIG_THERMAL_EMULATION=y +# CONFIG_THERMAL_MMIO is not set +# CONFIG_HISI_THERMAL is not set +# CONFIG_IMX_THERMAL is not set +# CONFIG_IMX8MM_THERMAL is not set +# CONFIG_K3_THERMAL is not set +# CONFIG_MAX77620_THERMAL is not set +# CONFIG_QORIQ_THERMAL is not set +# CONFIG_AIROHA_THERMAL is not set +# CONFIG_SUN8I_THERMAL is not set +# CONFIG_ROCKCHIP_THERMAL is not set +CONFIG_ARMADA_THERMAL=y + +# +# Mediatek thermal drivers +# +# CONFIG_MTK_THERMAL is not set +# end of Mediatek thermal drivers + +# CONFIG_AMLOGIC_THERMAL is not set + +# +# STMicroelectronics thermal drivers +# +# CONFIG_ST_THERMAL is not set +# CONFIG_ST_THERMAL_MEMMAP is not set +# end of STMicroelectronics thermal drivers + +# CONFIG_RCAR_THERMAL is not set +# CONFIG_RCAR_GEN3_THERMAL is not set +# CONFIG_RZG2L_THERMAL is not set +# CONFIG_RZG3E_THERMAL is not set + +# +# NVIDIA Tegra thermal drivers +# +# CONFIG_TEGRA_SOCTHERM is not set +# CONFIG_TEGRA_BPMP_THERMAL is not set +# end of NVIDIA Tegra thermal drivers + +# +# Qualcomm thermal drivers +# +# CONFIG_QCOM_LMH is not set +# end of Qualcomm thermal drivers + +# CONFIG_SPRD_THERMAL is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_CORE=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y +CONFIG_WATCHDOG_OPEN_TIMEOUT=0 +CONFIG_WATCHDOG_SYSFS=y +# CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT is not set + +# +# Watchdog Pretimeout Governors +# +CONFIG_WATCHDOG_PRETIMEOUT_GOV=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m +CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP=y +# CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC is not set +CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_DA9052_WATCHDOG is not set +# CONFIG_DA9055_WATCHDOG is not set +# CONFIG_DA9063_WATCHDOG is not set +# CONFIG_GPIO_WATCHDOG is not set +# CONFIG_WDAT_WDT is not set +# CONFIG_WM831X_WATCHDOG is not set +# CONFIG_WM8350_WATCHDOG is not set +# CONFIG_XILINX_WATCHDOG is not set +# CONFIG_XILINX_WINDOW_WATCHDOG is not set +# CONFIG_ZIIRAVE_WATCHDOG is not set +# CONFIG_MLX_WDT is not set +# CONFIG_AIROHA_WATCHDOG is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +# CONFIG_ARM_SBSA_WATCHDOG is not set +# CONFIG_ARMADA_37XX_WATCHDOG is not set +# CONFIG_CADENCE_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_K3_RTI_WATCHDOG is not set +# CONFIG_SUNXI_WATCHDOG is not set +CONFIG_NPCM7XX_WATCHDOG=y +# CONFIG_TWL4030_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set +# CONFIG_MAX77620_WATCHDOG is not set +# CONFIG_IMX2_WDT is not set +# CONFIG_IMX7ULP_WDT is not set +# CONFIG_S32G_WDT is not set +# CONFIG_TEGRA_WATCHDOG is not set +# CONFIG_QCOM_WDT is not set +# CONFIG_MESON_GXBB_WATCHDOG is not set +# CONFIG_MESON_WATCHDOG is not set +# CONFIG_MEDIATEK_WATCHDOG is not set +# CONFIG_ARM_SMC_WATCHDOG is not set +# CONFIG_RENESAS_WDT is not set +# CONFIG_RENESAS_RZAWDT is not set +# CONFIG_RENESAS_RZN1WDT is not set +# CONFIG_RENESAS_RZG2LWDT is not set +# CONFIG_RENESAS_RZV2HWDT is not set +# CONFIG_STM32_WATCHDOG is not set +CONFIG_RTD119X_WATCHDOG=y +# CONFIG_SPRD_WATCHDOG is not set +# CONFIG_VISCONTI_WATCHDOG is not set +# CONFIG_APPLE_WATCHDOG is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_I6300ESB_WDT is not set +# CONFIG_HP_WATCHDOG is not set +# CONFIG_NIC7018_WDT is not set +# CONFIG_MARVELL_GTI_WDT is not set +# CONFIG_MEN_A21_WDT is not set +# CONFIG_XEN_WDT is not set + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +# CONFIG_KEEMBAY_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_ADP5585 is not set +CONFIG_MFD_ALTERA_A10SR=y +CONFIG_MFD_ALTERA_SYSMGR=y +# CONFIG_MFD_ACT8945A is not set +# CONFIG_MFD_SUN4I_GPADC is not set +CONFIG_MFD_AS3711=y +# CONFIG_MFD_SMPRO is not set +CONFIG_MFD_AS3722=y +CONFIG_PMIC_ADP5520=y +CONFIG_MFD_AAT2870_CORE=y +# CONFIG_MFD_AT91_USART is not set +# CONFIG_MFD_ATMEL_FLEXCOM is not set +# CONFIG_MFD_ATMEL_HLCDC is not set +# CONFIG_MFD_BCM590XX is not set +# CONFIG_MFD_BD9571MWV is not set +# CONFIG_MFD_AXP20X_I2C is not set +# CONFIG_MFD_CS40L50_I2C is not set +# CONFIG_MFD_CS40L50_SPI is not set +# CONFIG_MFD_CS42L43_I2C is not set +CONFIG_MFD_LOCHNAGAR=y +# CONFIG_MFD_MADERA is not set +CONFIG_PMIC_DA903X=y +CONFIG_PMIC_DA9052=y +CONFIG_MFD_DA9052_SPI=y +CONFIG_MFD_DA9052_I2C=y +CONFIG_MFD_DA9055=y +# CONFIG_MFD_DA9062 is not set +CONFIG_MFD_DA9063=y +# CONFIG_MFD_DA9150 is not set +# CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_GATEWORKS_GSC is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_MP2629 is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_MFD_HI655X_PMIC is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set +# CONFIG_MFD_IQS62X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +CONFIG_MFD_88PM860X=y +CONFIG_MFD_88PM886_PMIC=y +# CONFIG_MFD_MAX5970 is not set +CONFIG_MFD_MAX14577=y +# CONFIG_MFD_MAX77541 is not set +CONFIG_MFD_MAX77620=y +# CONFIG_MFD_MAX77650 is not set +CONFIG_MFD_MAX77686=y +CONFIG_MFD_MAX77693=y +# CONFIG_MFD_MAX77705 is not set +# CONFIG_MFD_MAX77714 is not set +# CONFIG_MFD_MAX77759 is not set +CONFIG_MFD_MAX77843=y +# CONFIG_MFD_MAX8907 is not set +CONFIG_MFD_MAX8925=y +CONFIG_MFD_MAX8997=y +CONFIG_MFD_MAX8998=y +# CONFIG_MFD_MT6360 is not set +# CONFIG_MFD_MT6370 is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_MENF21BMC is not set +# CONFIG_MFD_NCT6694 is not set +# CONFIG_MFD_OCELOT is not set +CONFIG_EZX_PCAP=y +# CONFIG_MFD_CPCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_NTXEC is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_QCOM_RPM is not set +# CONFIG_MFD_SY7636A is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_RT4831 is not set +# CONFIG_MFD_RT5033 is not set +# CONFIG_MFD_RT5120 is not set +CONFIG_MFD_RC5T583=y +# CONFIG_MFD_RK8XX_I2C is not set +# CONFIG_MFD_RK8XX_SPI is not set +# CONFIG_MFD_RN5T618 is not set +# CONFIG_MFD_SEC_I2C is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SL28CPLD is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set +# CONFIG_MFD_SC27XX_PMIC is not set +CONFIG_RZ_MTU3=y +CONFIG_MFD_STMPE=y + +# +# STMicroelectronics STMPE Interface Drivers +# +CONFIG_STMPE_I2C=y +CONFIG_STMPE_SPI=y +# end of STMicroelectronics STMPE Interface Drivers + +CONFIG_MFD_SUN6I_PRCM=y +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP3943 is not set +CONFIG_MFD_LP8788=y +# CONFIG_MFD_TI_LMU is not set +# CONFIG_MFD_BQ257XX is not set +CONFIG_MFD_PALMAS=y +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65086 is not set +CONFIG_MFD_TPS65090=y +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TI_LP873X is not set +# CONFIG_MFD_TI_LP87565 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS65219 is not set +CONFIG_MFD_TPS6586X=y +CONFIG_MFD_TPS65910=y +CONFIG_MFD_TPS65912=y +CONFIG_MFD_TPS65912_I2C=y +CONFIG_MFD_TPS65912_SPI=y +# CONFIG_MFD_TPS6594_I2C is not set +# CONFIG_MFD_TPS6594_SPI is not set +CONFIG_TWL4030_CORE=y +CONFIG_MFD_TWL4030_AUDIO=y +CONFIG_TWL6040_CORE=y +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +CONFIG_MFD_TC3589X=y +# CONFIG_MFD_TQMX86 is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +CONFIG_MFD_WM8400=y +CONFIG_MFD_WM831X=y +CONFIG_MFD_WM831X_I2C=y +CONFIG_MFD_WM831X_SPI=y +CONFIG_MFD_WM8350=y +CONFIG_MFD_WM8350_I2C=y +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_ROHM_BD718XX is not set +# CONFIG_MFD_ROHM_BD71828 is not set +# CONFIG_MFD_ROHM_BD957XMUF is not set +# CONFIG_MFD_ROHM_BD96801 is not set +# CONFIG_MFD_STM32_LPTIMER is not set +# CONFIG_MFD_STM32_TIMERS is not set +# CONFIG_MFD_STPMIC1 is not set +# CONFIG_MFD_STMFX is not set +# CONFIG_MFD_ATC260X_I2C is not set +# CONFIG_MFD_KHADAS_MCU is not set +# CONFIG_MFD_QCOM_PM8008 is not set +CONFIG_MFD_VEXPRESS_SYSREG=y +# CONFIG_RAVE_SP_CORE is not set +# CONFIG_MFD_INTEL_M10_BMC_SPI is not set +# CONFIG_MFD_LS2K_BMC_CORE is not set +# CONFIG_MFD_QNAP_MCU is not set +# CONFIG_MFD_RSMU_I2C is not set +# CONFIG_MFD_RSMU_SPI is not set +# CONFIG_MFD_MAX7360 is not set +# end of Multifunction device drivers + +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +CONFIG_REGULATOR_NETLINK_EVENTS=y +# CONFIG_REGULATOR_88PG86X is not set +# CONFIG_REGULATOR_88PM8607 is not set +# CONFIG_REGULATOR_88PM886 is not set +# CONFIG_REGULATOR_ACT8865 is not set +# CONFIG_REGULATOR_AD5398 is not set +# CONFIG_REGULATOR_ADP5055 is not set +# CONFIG_REGULATOR_ANATOP is not set +# CONFIG_REGULATOR_AAT2870 is not set +CONFIG_REGULATOR_ARM_SCMI=y +# CONFIG_REGULATOR_AS3711 is not set +# CONFIG_REGULATOR_AS3722 is not set +# CONFIG_REGULATOR_AW37503 is not set +# CONFIG_REGULATOR_DA9052 is not set +# CONFIG_REGULATOR_DA9055 is not set +# CONFIG_REGULATOR_DA9063 is not set +# CONFIG_REGULATOR_DA9121 is not set +# CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_DA9211 is not set +# CONFIG_REGULATOR_FAN53555 is not set +# CONFIG_REGULATOR_FAN53880 is not set +# CONFIG_REGULATOR_GPIO is not set +# CONFIG_REGULATOR_ISL9305 is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_LOCHNAGAR is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_LP8755 is not set +# CONFIG_REGULATOR_LP8788 is not set +# CONFIG_REGULATOR_LTC3589 is not set +# CONFIG_REGULATOR_LTC3676 is not set +# CONFIG_REGULATOR_MAX14577 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX77503 is not set +# CONFIG_REGULATOR_MAX77620 is not set +# CONFIG_REGULATOR_MAX77857 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8893 is not set +# CONFIG_REGULATOR_MAX8925 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_MAX8973 is not set +# CONFIG_REGULATOR_MAX8997 is not set +# CONFIG_REGULATOR_MAX8998 is not set +# CONFIG_REGULATOR_MAX20086 is not set +# CONFIG_REGULATOR_MAX20411 is not set +# CONFIG_REGULATOR_MAX77686 is not set +# CONFIG_REGULATOR_MAX77693 is not set +# CONFIG_REGULATOR_MAX77802 is not set +# CONFIG_REGULATOR_MAX77826 is not set +# CONFIG_REGULATOR_MAX77838 is not set +# CONFIG_REGULATOR_MCP16502 is not set +# CONFIG_REGULATOR_MP5416 is not set +# CONFIG_REGULATOR_MP8859 is not set +# CONFIG_REGULATOR_MP886X is not set +# CONFIG_REGULATOR_MPQ7920 is not set +# CONFIG_REGULATOR_MT6311 is not set +# CONFIG_REGULATOR_PALMAS is not set +# CONFIG_REGULATOR_PCA9450 is not set +# CONFIG_REGULATOR_PF9453 is not set +# CONFIG_REGULATOR_PCAP is not set +# CONFIG_REGULATOR_PF0900 is not set +# CONFIG_REGULATOR_PF530X is not set +# CONFIG_REGULATOR_PF8X00 is not set +# CONFIG_REGULATOR_PFUZE100 is not set +# CONFIG_REGULATOR_PV88060 is not set +# CONFIG_REGULATOR_PV88080 is not set +# CONFIG_REGULATOR_PV88090 is not set +# CONFIG_REGULATOR_PWM is not set +# CONFIG_REGULATOR_QCOM_REFGEN is not set +# CONFIG_REGULATOR_QCOM_RPMH is not set +# CONFIG_REGULATOR_RAA215300 is not set +# CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY is not set +# CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_V2 is not set +# CONFIG_REGULATOR_RC5T583 is not set +# CONFIG_REGULATOR_RT4801 is not set +# CONFIG_REGULATOR_RT4803 is not set +# CONFIG_REGULATOR_RT5133 is not set +# CONFIG_REGULATOR_RT5190A is not set +# CONFIG_REGULATOR_RT5739 is not set +# CONFIG_REGULATOR_RT5759 is not set +# CONFIG_REGULATOR_RT6160 is not set +# CONFIG_REGULATOR_RT6190 is not set +# CONFIG_REGULATOR_RT6245 is not set +# CONFIG_REGULATOR_RTQ2134 is not set +# CONFIG_REGULATOR_RTMV20 is not set +# CONFIG_REGULATOR_RTQ6752 is not set +# CONFIG_REGULATOR_RTQ2208 is not set +# CONFIG_REGULATOR_SLG51000 is not set +# CONFIG_REGULATOR_STM32_BOOSTER is not set +# CONFIG_REGULATOR_STM32_VREFBUF is not set +CONFIG_REGULATOR_STM32_PWR=y +# CONFIG_REGULATOR_SUN20I is not set +# CONFIG_REGULATOR_SY8106A is not set +# CONFIG_REGULATOR_SY8824X is not set +# CONFIG_REGULATOR_SY8827N is not set +# CONFIG_REGULATOR_TPS51632 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS6286X is not set +# CONFIG_REGULATOR_TPS6287X is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS65090 is not set +# CONFIG_REGULATOR_TPS65132 is not set +# CONFIG_REGULATOR_TPS6524X is not set +# CONFIG_REGULATOR_TPS6586X is not set +# CONFIG_REGULATOR_TPS65910 is not set +# CONFIG_REGULATOR_TPS65912 is not set +# CONFIG_REGULATOR_TWL4030 is not set +CONFIG_REGULATOR_RZG2L_VBCTRL=y +# CONFIG_REGULATOR_VCTRL is not set +# CONFIG_REGULATOR_VEXPRESS is not set +# CONFIG_REGULATOR_VQMMC_IPQ4019 is not set +# CONFIG_REGULATOR_WM831X is not set +# CONFIG_REGULATOR_WM8350 is not set +# CONFIG_REGULATOR_WM8400 is not set +# CONFIG_RC_CORE is not set + +# +# CEC support +# +CONFIG_MEDIA_CEC_SUPPORT=y +# CONFIG_CEC_CH7322 is not set +# CONFIG_CEC_NXP_TDA9950 is not set +# CONFIG_CEC_MESON_AO is not set +# CONFIG_CEC_MESON_G12A_AO is not set +# CONFIG_CEC_GPIO is not set +# CONFIG_CEC_STM32 is not set +# CONFIG_CEC_TEGRA is not set +# CONFIG_USB_PULSE8_CEC is not set +# CONFIG_USB_RAINSHADOW_CEC is not set +# end of CEC support + +CONFIG_MEDIA_SUPPORT=m +CONFIG_MEDIA_SUPPORT_FILTER=y +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y + +# +# Media device types +# +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_ANALOG_TV_SUPPORT=y +CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_SDR_SUPPORT=y +CONFIG_MEDIA_PLATFORM_SUPPORT=y +CONFIG_MEDIA_TEST_SUPPORT=y +# end of Media device types + +CONFIG_VIDEO_DEV=m +CONFIG_MEDIA_CONTROLLER=y +CONFIG_DVB_CORE=m + +# +# Video4Linux options +# +CONFIG_VIDEO_V4L2_I2C=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_V4L2_FWNODE=m +CONFIG_V4L2_ASYNC=m +# end of Video4Linux options + +# +# Media controller options +# +CONFIG_MEDIA_CONTROLLER_DVB=y +# end of Media controller options + +# +# Digital TV options +# +# CONFIG_DVB_MMAP is not set +CONFIG_DVB_NET=y +CONFIG_DVB_MAX_ADAPTERS=8 +CONFIG_DVB_DYNAMIC_MINORS=y +# CONFIG_DVB_DEMUX_SECTION_LOSS_LOG is not set +# CONFIG_DVB_ULE_DEBUG is not set +# end of Digital TV options + +# +# Media drivers +# + +# +# Drivers filtered as selected at 'Filter media drivers' +# + +# +# Media drivers +# +CONFIG_MEDIA_USB_SUPPORT=y + +# +# Webcam devices +# +# CONFIG_USB_GSPCA is not set +# CONFIG_USB_PWC is not set +# CONFIG_USB_S2255 is not set +# CONFIG_VIDEO_USBTV is not set +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y + +# +# Analog TV USB devices +# +# CONFIG_VIDEO_GO7007 is not set +# CONFIG_VIDEO_HDPVR is not set +# CONFIG_VIDEO_PVRUSB2 is not set +# CONFIG_VIDEO_STK1160 is not set + +# +# Analog/digital TV USB devices +# +# CONFIG_VIDEO_AU0828 is not set +# CONFIG_VIDEO_CX231XX is not set + +# +# Digital TV USB devices +# +# CONFIG_DVB_AS102 is not set +# CONFIG_DVB_B2C2_FLEXCOP_USB is not set +# CONFIG_DVB_USB_V2 is not set +# CONFIG_SMS_USB_DRV is not set +# CONFIG_DVB_TTUSB_BUDGET is not set +# CONFIG_DVB_TTUSB_DEC is not set + +# +# Webcam, TV (analog/digital) USB devices +# +# CONFIG_VIDEO_EM28XX is not set + +# +# Software defined radio USB devices +# +# CONFIG_USB_AIRSPY is not set +# CONFIG_USB_HACKRF is not set +# CONFIG_USB_MSI2500 is not set +CONFIG_MEDIA_PCI_SUPPORT=y + +# +# Media capture support +# +# CONFIG_VIDEO_SOLO6X10 is not set +# CONFIG_VIDEO_TW5864 is not set +# CONFIG_VIDEO_TW68 is not set +# CONFIG_VIDEO_TW686X is not set + +# +# Media capture/analog TV support +# +# CONFIG_VIDEO_DT3155 is not set +# CONFIG_VIDEO_HEXIUM_GEMINI is not set +# CONFIG_VIDEO_HEXIUM_ORION is not set +# CONFIG_VIDEO_MXB is not set + +# +# Media capture/analog/hybrid TV support +# +# CONFIG_VIDEO_CX25821 is not set +# CONFIG_VIDEO_SAA7134 is not set +# CONFIG_VIDEO_SAA7164 is not set + +# +# Media digital TV PCI Adapters +# +# CONFIG_DVB_B2C2_FLEXCOP_PCI is not set +# CONFIG_DVB_DDBRIDGE is not set +# CONFIG_DVB_NETUP_UNIDVB is not set +# CONFIG_DVB_NGENE is not set +# CONFIG_DVB_PLUTO2 is not set +# CONFIG_DVB_PT1 is not set +# CONFIG_DVB_PT3 is not set +# CONFIG_DVB_BUDGET_CORE is not set +# CONFIG_VIDEO_PCI_SKELETON is not set +# CONFIG_IPU_BRIDGE is not set +# CONFIG_RADIO_ADAPTERS is not set +CONFIG_MEDIA_PLATFORM_DRIVERS=y +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_SDR_PLATFORM_DRIVERS=y +CONFIG_DVB_PLATFORM_DRIVERS=y +CONFIG_V4L_MEM2MEM_DRIVERS=y +# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set +# CONFIG_VIDEO_MUX is not set + +# +# Allegro DVT media platform drivers +# +# CONFIG_VIDEO_ALLEGRO_DVT is not set + +# +# Amlogic media platform drivers +# +# CONFIG_VIDEO_C3_ISP is not set +# CONFIG_VIDEO_C3_MIPI_ADAPTER is not set +# CONFIG_VIDEO_C3_MIPI_CSI2 is not set +# CONFIG_VIDEO_MESON_GE2D is not set + +# +# Amphion drivers +# +# CONFIG_VIDEO_AMPHION_VPU is not set + +# +# Aspeed media platform drivers +# + +# +# Atmel media platform drivers +# + +# +# Cadence media platform drivers +# +# CONFIG_VIDEO_CADENCE_CSI2RX is not set +# CONFIG_VIDEO_CADENCE_CSI2TX is not set + +# +# Chips&Media media platform drivers +# +# CONFIG_VIDEO_CODA is not set +# CONFIG_VIDEO_WAVE_VPU is not set +# CONFIG_VIDEO_E5010_JPEG_ENC is not set + +# +# Intel media platform drivers +# + +# +# Marvell media platform drivers +# +# CONFIG_VIDEO_CAFE_CCIC is not set + +# +# Mediatek media platform drivers +# +# CONFIG_VIDEO_MEDIATEK_VPU is not set + +# +# Microchip Technology, Inc. media platform drivers +# + +# +# Nuvoton media platform drivers +# +# CONFIG_VIDEO_NPCM_VCD_ECE is not set + +# +# NVidia media platform drivers +# +# CONFIG_VIDEO_TEGRA_VDE is not set + +# +# NXP media platform drivers +# +# CONFIG_VIDEO_IMX7_CSI is not set +# CONFIG_VIDEO_IMX8MQ_MIPI_CSI2 is not set +# CONFIG_VIDEO_IMX_MIPI_CSIS is not set +# CONFIG_VIDEO_IMX8_ISI is not set +# CONFIG_VIDEO_IMX_PXP is not set +# CONFIG_VIDEO_DW100 is not set +# CONFIG_VIDEO_IMX8_JPEG is not set + +# +# Qualcomm media platform drivers +# +# CONFIG_VIDEO_QCOM_CAMSS is not set +# CONFIG_VIDEO_QCOM_IRIS is not set + +# +# Raspberry Pi media platform drivers +# +# CONFIG_VIDEO_RP1_CFE is not set + +# +# Renesas media platform drivers +# +# CONFIG_VIDEO_RCAR_CSI2 is not set +# CONFIG_VIDEO_RCAR_ISP is not set +# CONFIG_VIDEO_RCAR_VIN is not set +# CONFIG_VIDEO_RZG2L_CSI2 is not set +# CONFIG_VIDEO_RZG2L_CRU is not set +# CONFIG_VIDEO_RENESAS_FCP is not set +# CONFIG_VIDEO_RENESAS_JPU is not set +# CONFIG_VIDEO_RCAR_DRIF is not set + +# +# Rockchip media platform drivers +# +# CONFIG_VIDEO_ROCKCHIP_RGA is not set +# CONFIG_VIDEO_ROCKCHIP_ISP1 is not set +# CONFIG_VIDEO_ROCKCHIP_VDEC is not set + +# +# Samsung media platform drivers +# + +# +# STMicroelectronics media platform drivers +# +# CONFIG_VIDEO_STM32_CSI is not set +# CONFIG_VIDEO_STM32_DCMI is not set +# CONFIG_VIDEO_STM32_DCMIPP is not set +# CONFIG_VIDEO_STM32_DMA2D is not set + +# +# Sunxi media platform drivers +# +# CONFIG_VIDEO_SUN4I_CSI is not set +# CONFIG_VIDEO_SUN6I_CSI is not set +# CONFIG_VIDEO_SUN8I_A83T_MIPI_CSI2 is not set +# CONFIG_VIDEO_SUN8I_DEINTERLACE is not set +# CONFIG_VIDEO_SUN8I_ROTATE is not set +# CONFIG_VIDEO_SYNOPSYS_HDMIRX is not set + +# +# Texas Instruments drivers +# +# CONFIG_VIDEO_TI_CAL is not set + +# +# Verisilicon media platform drivers +# +# CONFIG_VIDEO_HANTRO is not set + +# +# VIA media platform drivers +# + +# +# Xilinx media platform drivers +# +# CONFIG_VIDEO_XILINX is not set + +# +# MMC/SDIO DVB adapters +# +# CONFIG_SMS_SDIO_DRV is not set +CONFIG_V4L_TEST_DRIVERS=y +# CONFIG_VIDEO_VIM2M is not set +# CONFIG_VIDEO_VICODEC is not set +# CONFIG_VIDEO_VIMC is not set +# CONFIG_VIDEO_VIVID is not set +# CONFIG_VIDEO_VISL is not set +# CONFIG_DVB_TEST_DRIVERS is not set +CONFIG_UVC_COMMON=m +CONFIG_VIDEOBUF2_CORE=m +CONFIG_VIDEOBUF2_V4L2=m +CONFIG_VIDEOBUF2_MEMOPS=m +CONFIG_VIDEOBUF2_VMALLOC=m +# end of Media drivers + +# +# Media ancillary drivers +# +CONFIG_MEDIA_ATTACH=y +CONFIG_VIDEO_CAMERA_SENSOR=y +# CONFIG_VIDEO_ALVIUM_CSI2 is not set +# CONFIG_VIDEO_AR0521 is not set +# CONFIG_VIDEO_GC0308 is not set +# CONFIG_VIDEO_GC0310 is not set +# CONFIG_VIDEO_GC05A2 is not set +# CONFIG_VIDEO_GC08A3 is not set +# CONFIG_VIDEO_GC2145 is not set +# CONFIG_VIDEO_HI556 is not set +# CONFIG_VIDEO_HI846 is not set +# CONFIG_VIDEO_HI847 is not set +# CONFIG_VIDEO_IMX208 is not set +# CONFIG_VIDEO_IMX214 is not set +# CONFIG_VIDEO_IMX219 is not set +# CONFIG_VIDEO_IMX258 is not set +# CONFIG_VIDEO_IMX274 is not set +# CONFIG_VIDEO_IMX283 is not set +# CONFIG_VIDEO_IMX290 is not set +# CONFIG_VIDEO_IMX296 is not set +# CONFIG_VIDEO_IMX319 is not set +# CONFIG_VIDEO_IMX334 is not set +# CONFIG_VIDEO_IMX335 is not set +# CONFIG_VIDEO_IMX355 is not set +# CONFIG_VIDEO_IMX412 is not set +# CONFIG_VIDEO_IMX415 is not set +# CONFIG_VIDEO_MT9M001 is not set +# CONFIG_VIDEO_MT9M111 is not set +# CONFIG_VIDEO_MT9M114 is not set +# CONFIG_VIDEO_MT9P031 is not set +# CONFIG_VIDEO_MT9T112 is not set +# CONFIG_VIDEO_MT9V011 is not set +# CONFIG_VIDEO_MT9V032 is not set +# CONFIG_VIDEO_MT9V111 is not set +# CONFIG_VIDEO_OG01A1B is not set +# CONFIG_VIDEO_OG0VE1B is not set +# CONFIG_VIDEO_OV01A10 is not set +# CONFIG_VIDEO_OV02A10 is not set +# CONFIG_VIDEO_OV02E10 is not set +# CONFIG_VIDEO_OV02C10 is not set +# CONFIG_VIDEO_OV08D10 is not set +# CONFIG_VIDEO_OV08X40 is not set +# CONFIG_VIDEO_OV13858 is not set +# CONFIG_VIDEO_OV13B10 is not set +# CONFIG_VIDEO_OV2640 is not set +# CONFIG_VIDEO_OV2659 is not set +# CONFIG_VIDEO_OV2680 is not set +# CONFIG_VIDEO_OV2685 is not set +# CONFIG_VIDEO_OV2735 is not set +# CONFIG_VIDEO_OV2740 is not set +# CONFIG_VIDEO_OV4689 is not set +# CONFIG_VIDEO_OV5640 is not set +# CONFIG_VIDEO_OV5645 is not set +# CONFIG_VIDEO_OV5647 is not set +# CONFIG_VIDEO_OV5648 is not set +# CONFIG_VIDEO_OV5670 is not set +# CONFIG_VIDEO_OV5675 is not set +# CONFIG_VIDEO_OV5693 is not set +# CONFIG_VIDEO_OV5695 is not set +# CONFIG_VIDEO_OV6211 is not set +# CONFIG_VIDEO_OV64A40 is not set +# CONFIG_VIDEO_OV7251 is not set +# CONFIG_VIDEO_OV7640 is not set +# CONFIG_VIDEO_OV7670 is not set +# CONFIG_VIDEO_OV772X is not set +# CONFIG_VIDEO_OV7740 is not set +# CONFIG_VIDEO_OV8856 is not set +# CONFIG_VIDEO_OV8858 is not set +# CONFIG_VIDEO_OV8865 is not set +# CONFIG_VIDEO_OV9282 is not set +# CONFIG_VIDEO_OV9640 is not set +# CONFIG_VIDEO_OV9650 is not set +# CONFIG_VIDEO_OV9734 is not set +# CONFIG_VIDEO_RDACM20 is not set +# CONFIG_VIDEO_RDACM21 is not set +# CONFIG_VIDEO_RJ54N1 is not set +# CONFIG_VIDEO_S5C73M3 is not set +# CONFIG_VIDEO_S5K5BAF is not set +# CONFIG_VIDEO_S5K6A3 is not set +# CONFIG_VIDEO_VD55G1 is not set +# CONFIG_VIDEO_VD56G3 is not set +# CONFIG_VIDEO_VGXY61 is not set +# CONFIG_VIDEO_CCS is not set +# CONFIG_VIDEO_ET8EK8 is not set + +# +# Camera ISPs +# +# CONFIG_VIDEO_THP7312 is not set +# end of Camera ISPs + +CONFIG_VIDEO_CAMERA_LENS=y +# CONFIG_VIDEO_AD5820 is not set +# CONFIG_VIDEO_AK7375 is not set +# CONFIG_VIDEO_DW9714 is not set +# CONFIG_VIDEO_DW9719 is not set +# CONFIG_VIDEO_DW9768 is not set +# CONFIG_VIDEO_DW9807_VCM is not set + +# +# Flash devices +# +# CONFIG_VIDEO_ADP1653 is not set +# CONFIG_VIDEO_LM3560 is not set +# CONFIG_VIDEO_LM3646 is not set +# end of Flash devices + +# +# Audio decoders, processors and mixers +# +# CONFIG_VIDEO_CS3308 is not set +# CONFIG_VIDEO_CS5345 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_SONY_BTF_MPX is not set +# CONFIG_VIDEO_TDA7432 is not set +# CONFIG_VIDEO_TDA9840 is not set +# CONFIG_VIDEO_TEA6415C is not set +# CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_TVAUDIO is not set +# CONFIG_VIDEO_UDA1342 is not set +# CONFIG_VIDEO_VP27SMPX is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_WM8775 is not set +# end of Audio decoders, processors and mixers + +# +# RDS decoders +# +# CONFIG_VIDEO_SAA6588 is not set +# end of RDS decoders + +# +# Video decoders +# +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_ADV7183 is not set +# CONFIG_VIDEO_ADV748X is not set +# CONFIG_VIDEO_ADV7604 is not set +# CONFIG_VIDEO_ADV7842 is not set +# CONFIG_VIDEO_BT819 is not set +# CONFIG_VIDEO_BT856 is not set +# CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_ISL7998X is not set +# CONFIG_VIDEO_LT6911UXE is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_MAX9286 is not set +# CONFIG_VIDEO_ML86V7667 is not set +# CONFIG_VIDEO_SAA7110 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_TC358743 is not set +# CONFIG_VIDEO_TC358746 is not set +# CONFIG_VIDEO_TVP514X is not set +# CONFIG_VIDEO_TVP5150 is not set +# CONFIG_VIDEO_TVP7002 is not set +# CONFIG_VIDEO_TW2804 is not set +# CONFIG_VIDEO_TW9900 is not set +# CONFIG_VIDEO_TW9903 is not set +# CONFIG_VIDEO_TW9906 is not set +# CONFIG_VIDEO_TW9910 is not set +# CONFIG_VIDEO_VPX3220 is not set + +# +# Video and audio decoders +# +# CONFIG_VIDEO_SAA717X is not set +# CONFIG_VIDEO_CX25840 is not set +# end of Video decoders + +# +# Video encoders +# +# CONFIG_VIDEO_ADV7170 is not set +# CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_ADV7343 is not set +# CONFIG_VIDEO_ADV7393 is not set +# CONFIG_VIDEO_ADV7511 is not set +# CONFIG_VIDEO_AK881X is not set +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_THS8200 is not set +# end of Video encoders + +# +# Video improvement chips +# +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set +# end of Video improvement chips + +# +# Audio/Video compression chips +# +# CONFIG_VIDEO_SAA6752HS is not set +# end of Audio/Video compression chips + +# +# SDR tuner chips +# +# CONFIG_SDR_MAX2175 is not set +# end of SDR tuner chips + +# +# Miscellaneous helper chips +# +# CONFIG_VIDEO_I2C is not set +# CONFIG_VIDEO_M52790 is not set +# CONFIG_VIDEO_ST_MIPID02 is not set +# CONFIG_VIDEO_THS7303 is not set +# end of Miscellaneous helper chips + +# +# Video serializers and deserializers +# +# CONFIG_VIDEO_DS90UB913 is not set +# CONFIG_VIDEO_DS90UB953 is not set +# CONFIG_VIDEO_DS90UB960 is not set +# CONFIG_VIDEO_MAX96714 is not set +# CONFIG_VIDEO_MAX96717 is not set +# end of Video serializers and deserializers + +# +# Media SPI Adapters +# +# CONFIG_CXD2880_SPI_DRV is not set +# CONFIG_VIDEO_GS1662 is not set +# end of Media SPI Adapters + +CONFIG_MEDIA_TUNER=m + +# +# Customize TV tuners +# +# CONFIG_MEDIA_TUNER_E4000 is not set +# CONFIG_MEDIA_TUNER_FC0011 is not set +# CONFIG_MEDIA_TUNER_FC0012 is not set +# CONFIG_MEDIA_TUNER_FC0013 is not set +# CONFIG_MEDIA_TUNER_FC2580 is not set +# CONFIG_MEDIA_TUNER_IT913X is not set +# CONFIG_MEDIA_TUNER_M88RS6000T is not set +# CONFIG_MEDIA_TUNER_MAX2165 is not set +CONFIG_MEDIA_TUNER_MC44S803=m +# CONFIG_MEDIA_TUNER_MSI001 is not set +# CONFIG_MEDIA_TUNER_MT2060 is not set +# CONFIG_MEDIA_TUNER_MT2063 is not set +CONFIG_MEDIA_TUNER_MT20XX=m +# CONFIG_MEDIA_TUNER_MT2131 is not set +# CONFIG_MEDIA_TUNER_MT2266 is not set +# CONFIG_MEDIA_TUNER_MXL301RF is not set +# CONFIG_MEDIA_TUNER_MXL5005S is not set +# CONFIG_MEDIA_TUNER_MXL5007T is not set +# CONFIG_MEDIA_TUNER_QM1D1B0004 is not set +# CONFIG_MEDIA_TUNER_QM1D1C0042 is not set +# CONFIG_MEDIA_TUNER_QT1010 is not set +# CONFIG_MEDIA_TUNER_R820T is not set +# CONFIG_MEDIA_TUNER_SI2157 is not set +CONFIG_MEDIA_TUNER_SIMPLE=m +# CONFIG_MEDIA_TUNER_TDA18212 is not set +# CONFIG_MEDIA_TUNER_TDA18218 is not set +# CONFIG_MEDIA_TUNER_TDA18250 is not set +CONFIG_MEDIA_TUNER_TDA18271=m +CONFIG_MEDIA_TUNER_TDA827X=m +CONFIG_MEDIA_TUNER_TDA8290=m +CONFIG_MEDIA_TUNER_TDA9887=m +CONFIG_MEDIA_TUNER_TEA5761=m +CONFIG_MEDIA_TUNER_TEA5767=m +# CONFIG_MEDIA_TUNER_TUA9001 is not set +CONFIG_MEDIA_TUNER_XC2028=m +CONFIG_MEDIA_TUNER_XC4000=m +CONFIG_MEDIA_TUNER_XC5000=m +# end of Customize TV tuners + +# +# Customise DVB Frontends +# + +# +# Multistandard (satellite) frontends +# +# CONFIG_DVB_M88DS3103 is not set +# CONFIG_DVB_MXL5XX is not set +# CONFIG_DVB_STB0899 is not set +# CONFIG_DVB_STB6100 is not set +# CONFIG_DVB_STV090x is not set +# CONFIG_DVB_STV0910 is not set +# CONFIG_DVB_STV6110x is not set +# CONFIG_DVB_STV6111 is not set + +# +# Multistandard (cable + terrestrial) frontends +# +# CONFIG_DVB_DRXK is not set +# CONFIG_DVB_MN88472 is not set +# CONFIG_DVB_MN88473 is not set +# CONFIG_DVB_SI2165 is not set +# CONFIG_DVB_TDA18271C2DD is not set + +# +# DVB-S (satellite) frontends +# +# CONFIG_DVB_CX24110 is not set +# CONFIG_DVB_CX24116 is not set +# CONFIG_DVB_CX24117 is not set +# CONFIG_DVB_CX24120 is not set +# CONFIG_DVB_CX24123 is not set +# CONFIG_DVB_DS3000 is not set +# CONFIG_DVB_MB86A16 is not set +# CONFIG_DVB_MT312 is not set +# CONFIG_DVB_S5H1420 is not set +# CONFIG_DVB_SI21XX is not set +# CONFIG_DVB_STB6000 is not set +# CONFIG_DVB_STV0288 is not set +# CONFIG_DVB_STV0299 is not set +# CONFIG_DVB_STV0900 is not set +# CONFIG_DVB_STV6110 is not set +# CONFIG_DVB_TDA10071 is not set +# CONFIG_DVB_TDA10086 is not set +# CONFIG_DVB_TDA8083 is not set +# CONFIG_DVB_TDA8261 is not set +# CONFIG_DVB_TDA826X is not set +# CONFIG_DVB_TS2020 is not set +# CONFIG_DVB_TUA6100 is not set +# CONFIG_DVB_TUNER_CX24113 is not set +# CONFIG_DVB_TUNER_ITD1000 is not set +# CONFIG_DVB_VES1X93 is not set +# CONFIG_DVB_ZL10036 is not set +# CONFIG_DVB_ZL10039 is not set + +# +# DVB-T (terrestrial) frontends +# +# CONFIG_DVB_AF9013 is not set +# CONFIG_DVB_CX22700 is not set +# CONFIG_DVB_CX22702 is not set +# CONFIG_DVB_CXD2820R is not set +# CONFIG_DVB_CXD2841ER is not set +# CONFIG_DVB_DIB3000MB is not set +# CONFIG_DVB_DIB3000MC is not set +# CONFIG_DVB_DIB7000M is not set +# CONFIG_DVB_DIB7000P is not set +# CONFIG_DVB_DIB9000 is not set +# CONFIG_DVB_DRXD is not set +# CONFIG_DVB_EC100 is not set +# CONFIG_DVB_L64781 is not set +# CONFIG_DVB_MT352 is not set +# CONFIG_DVB_NXT6000 is not set +# CONFIG_DVB_RTL2830 is not set +# CONFIG_DVB_RTL2832 is not set +# CONFIG_DVB_RTL2832_SDR is not set +# CONFIG_DVB_S5H1432 is not set +# CONFIG_DVB_SI2168 is not set +# CONFIG_DVB_SP887X is not set +# CONFIG_DVB_STV0367 is not set +# CONFIG_DVB_TDA10048 is not set +# CONFIG_DVB_TDA1004X is not set +# CONFIG_DVB_ZD1301_DEMOD is not set +# CONFIG_DVB_ZL10353 is not set +# CONFIG_DVB_CXD2880 is not set + +# +# DVB-C (cable) frontends +# +# CONFIG_DVB_STV0297 is not set +# CONFIG_DVB_TDA10021 is not set +# CONFIG_DVB_TDA10023 is not set +# CONFIG_DVB_VES1820 is not set + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +# CONFIG_DVB_AU8522_DTV is not set +# CONFIG_DVB_AU8522_V4L is not set +# CONFIG_DVB_BCM3510 is not set +# CONFIG_DVB_LG2160 is not set +# CONFIG_DVB_LGDT3305 is not set +# CONFIG_DVB_LGDT3306A is not set +# CONFIG_DVB_LGDT330X is not set +# CONFIG_DVB_MXL692 is not set +# CONFIG_DVB_NXT200X is not set +# CONFIG_DVB_OR51132 is not set +# CONFIG_DVB_OR51211 is not set +# CONFIG_DVB_S5H1409 is not set +# CONFIG_DVB_S5H1411 is not set + +# +# ISDB-T (terrestrial) frontends +# +# CONFIG_DVB_DIB8000 is not set +# CONFIG_DVB_MB86A20S is not set +# CONFIG_DVB_S921 is not set + +# +# ISDB-S (satellite) & ISDB-T (terrestrial) frontends +# +# CONFIG_DVB_MN88443X is not set +# CONFIG_DVB_TC90522 is not set + +# +# Digital terrestrial only tuners/PLL +# +# CONFIG_DVB_PLL is not set +# CONFIG_DVB_TUNER_DIB0070 is not set +# CONFIG_DVB_TUNER_DIB0090 is not set + +# +# SEC control devices for DVB-S +# +# CONFIG_DVB_A8293 is not set +# CONFIG_DVB_AF9033 is not set +# CONFIG_DVB_ASCOT2E is not set +# CONFIG_DVB_ATBM8830 is not set +# CONFIG_DVB_HELENE is not set +# CONFIG_DVB_HORUS3A is not set +# CONFIG_DVB_ISL6405 is not set +# CONFIG_DVB_ISL6421 is not set +# CONFIG_DVB_ISL6423 is not set +# CONFIG_DVB_IX2505V is not set +# CONFIG_DVB_LGS8GL5 is not set +# CONFIG_DVB_LGS8GXX is not set +# CONFIG_DVB_LNBH25 is not set +# CONFIG_DVB_LNBH29 is not set +# CONFIG_DVB_LNBP21 is not set +# CONFIG_DVB_LNBP22 is not set +# CONFIG_DVB_M88RS2000 is not set +# CONFIG_DVB_TDA665x is not set +# CONFIG_DVB_DRX39XYJ is not set + +# +# Common Interface (EN50221) controller drivers +# +# CONFIG_DVB_CXD2099 is not set +# CONFIG_DVB_SP2 is not set +# end of Customise DVB Frontends + +# +# Tools to develop new frontends +# +# CONFIG_DVB_DUMMY_FE is not set +# end of Media ancillary drivers + +# +# Graphics support +# +CONFIG_APERTURE_HELPERS=y +CONFIG_SCREEN_INFO=y +CONFIG_VIDEO=y +CONFIG_AUXDISPLAY=y +# CONFIG_HD44780 is not set +# CONFIG_LCD2S is not set +# CONFIG_CHARLCD_BL_OFF is not set +# CONFIG_CHARLCD_BL_ON is not set +CONFIG_CHARLCD_BL_FLASH=y +# CONFIG_IMG_ASCII_LCD is not set +# CONFIG_HT16K33 is not set +# CONFIG_MAX6959 is not set +# CONFIG_SEG_LED_GPIO is not set +# CONFIG_TEGRA_HOST1X is not set +# CONFIG_NOVA_CORE is not set +CONFIG_DRM=y + +# +# DRM debugging options +# +# CONFIG_DRM_WERROR is not set +# CONFIG_DRM_DEBUG_MM is not set +# end of DRM debugging options + +CONFIG_DRM_KMS_HELPER=y +CONFIG_DRM_DRAW=y +CONFIG_DRM_PANIC=y +CONFIG_DRM_PANIC_FOREGROUND_COLOR=0xffffff +CONFIG_DRM_PANIC_BACKGROUND_COLOR=0x5e2750 +# CONFIG_DRM_PANIC_DEBUG is not set +CONFIG_DRM_PANIC_SCREEN="user" +# CONFIG_DRM_PANIC_SCREEN_QR_CODE is not set +# CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS is not set +# CONFIG_DRM_DEBUG_MODESET_LOCK is not set +CONFIG_DRM_CLIENT=y +CONFIG_DRM_CLIENT_LIB=y +CONFIG_DRM_CLIENT_SELECTION=y +CONFIG_DRM_CLIENT_SETUP=y + +# +# Supported DRM clients +# +CONFIG_DRM_FBDEV_EMULATION=y +CONFIG_DRM_FBDEV_OVERALLOC=100 +# CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM is not set +CONFIG_DRM_CLIENT_LOG=y +CONFIG_DRM_CLIENT_DEFAULT_FBDEV=y +# CONFIG_DRM_CLIENT_DEFAULT_LOG is not set +CONFIG_DRM_CLIENT_DEFAULT="fbdev" +# end of Supported DRM clients + +CONFIG_DRM_LOAD_EDID_FIRMWARE=y +CONFIG_DRM_TTM=m +CONFIG_DRM_TTM_HELPER=m +CONFIG_DRM_GEM_SHMEM_HELPER=y + +# +# Drivers for system framebuffers +# +CONFIG_DRM_SYSFB_HELPER=y +CONFIG_DRM_SIMPLEDRM=y +# end of Drivers for system framebuffers + +# +# ARM devices +# +# CONFIG_DRM_HDLCD is not set +# CONFIG_DRM_MALI_DISPLAY is not set +# CONFIG_DRM_KOMEDA is not set +# end of ARM devices + +# CONFIG_DRM_RADEON is not set +# CONFIG_DRM_AMDGPU is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_DRM_NOVA is not set +# CONFIG_DRM_XE is not set +# CONFIG_DRM_KMB_DISPLAY is not set +# CONFIG_DRM_VGEM is not set +# CONFIG_DRM_VKMS is not set +# CONFIG_DRM_ROCKCHIP is not set +CONFIG_DRM_VMWGFX=m +# CONFIG_DRM_UDL is not set +# CONFIG_DRM_AST is not set +# CONFIG_DRM_MGAG200 is not set +# CONFIG_DRM_RCAR_DU is not set +# CONFIG_DRM_SHMOBILE is not set +# CONFIG_DRM_SUN4I is not set +# CONFIG_DRM_QXL is not set +# CONFIG_DRM_VIRTIO_GPU is not set +# CONFIG_DRM_MSM is not set +# CONFIG_DRM_TEGRA is not set +# CONFIG_DRM_STM is not set +CONFIG_DRM_PANEL=y + +# +# Display Panels +# +# CONFIG_DRM_PANEL_ABT_Y030XX067A is not set +# CONFIG_DRM_PANEL_ARM_VERSATILE is not set +# CONFIG_DRM_PANEL_AUO_A030JTN01 is not set +# CONFIG_DRM_PANEL_LVDS is not set +# CONFIG_DRM_PANEL_ILITEK_IL9322 is not set +# CONFIG_DRM_PANEL_ILITEK_ILI9341 is not set +# CONFIG_DRM_PANEL_INNOLUX_EJ030NA is not set +# CONFIG_DRM_PANEL_LG_LB035Q02 is not set +# CONFIG_DRM_PANEL_LG_LG4573 is not set +# CONFIG_DRM_PANEL_NEC_NL8048HL11 is not set +# CONFIG_DRM_PANEL_NEWVISION_NV3052C is not set +# CONFIG_DRM_PANEL_NOVATEK_NT39016 is not set +# CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO is not set +# CONFIG_DRM_PANEL_ORISETECH_OTA5601A is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01 is not set +# CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20 is not set +# CONFIG_DRM_PANEL_SAMSUNG_DB7430 is not set +# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6D27A1 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6D7AA0 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E63M0 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set +# CONFIG_DRM_PANEL_SEIKO_43WVF1G is not set +# CONFIG_DRM_PANEL_SHARP_LS037V7DW01 is not set +# CONFIG_DRM_PANEL_SITRONIX_ST7701 is not set +# CONFIG_DRM_PANEL_SITRONIX_ST7789V is not set +# CONFIG_DRM_PANEL_SONY_ACX565AKM is not set +# CONFIG_DRM_PANEL_EDP is not set +# CONFIG_DRM_PANEL_SIMPLE is not set +# CONFIG_DRM_PANEL_TPO_TD028TTEC1 is not set +# CONFIG_DRM_PANEL_TPO_TD043MTEA1 is not set +# CONFIG_DRM_PANEL_TPO_TPG110 is not set +# CONFIG_DRM_PANEL_WIDECHIPS_WS2401 is not set +# end of Display Panels + +CONFIG_DRM_BRIDGE=y +CONFIG_DRM_PANEL_BRIDGE=y + +# +# Display Interface Bridges +# +# CONFIG_DRM_CHIPONE_ICN6211 is not set +# CONFIG_DRM_CHRONTEL_CH7033 is not set +# CONFIG_DRM_DISPLAY_CONNECTOR is not set +# CONFIG_DRM_FSL_LDB is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_ITE_IT6263 is not set +# CONFIG_DRM_ITE_IT6505 is not set +# CONFIG_DRM_LONTIUM_LT8912B is not set +# CONFIG_DRM_LONTIUM_LT9211 is not set +# CONFIG_DRM_LONTIUM_LT9611 is not set +# CONFIG_DRM_LONTIUM_LT9611UXC is not set +# CONFIG_DRM_ITE_IT66121 is not set +# CONFIG_DRM_LVDS_CODEC is not set +# CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW is not set +# CONFIG_DRM_NWL_MIPI_DSI is not set +# CONFIG_DRM_NXP_PTN3460 is not set +# CONFIG_DRM_PARADE_PS8622 is not set +# CONFIG_DRM_PARADE_PS8640 is not set +# CONFIG_DRM_SAMSUNG_DSIM is not set +# CONFIG_DRM_SIL_SII8620 is not set +# CONFIG_DRM_SII902X is not set +# CONFIG_DRM_SII9234 is not set +# CONFIG_DRM_SIMPLE_BRIDGE is not set +# CONFIG_DRM_SOLOMON_SSD2825 is not set +# CONFIG_DRM_THINE_THC63LVD1024 is not set +# CONFIG_DRM_TOSHIBA_TC358762 is not set +# CONFIG_DRM_TOSHIBA_TC358764 is not set +# CONFIG_DRM_TOSHIBA_TC358767 is not set +# CONFIG_DRM_TOSHIBA_TC358768 is not set +# CONFIG_DRM_TOSHIBA_TC358775 is not set +# CONFIG_DRM_TI_DLPC3433 is not set +# CONFIG_DRM_TI_TDP158 is not set +# CONFIG_DRM_TI_TFP410 is not set +# CONFIG_DRM_TI_SN65DSI83 is not set +# CONFIG_DRM_TI_SN65DSI86 is not set +# CONFIG_DRM_TI_TPD12S015 is not set +# CONFIG_DRM_WAVESHARE_BRIDGE is not set +# CONFIG_DRM_ANALOGIX_ANX6345 is not set +# CONFIG_DRM_ANALOGIX_ANX78XX is not set +# CONFIG_DRM_ANALOGIX_ANX7625 is not set +# CONFIG_DRM_I2C_ADV7511 is not set +# CONFIG_DRM_CDNS_DSI is not set +# CONFIG_DRM_CDNS_MHDP8546 is not set +# CONFIG_DRM_IMX8MP_DW_HDMI_BRIDGE is not set +# CONFIG_DRM_IMX8MP_HDMI_PVI is not set +# CONFIG_DRM_IMX8QM_LDB is not set +# CONFIG_DRM_IMX8QXP_LDB is not set +# CONFIG_DRM_IMX8QXP_PIXEL_COMBINER is not set +# CONFIG_DRM_IMX8QXP_PIXEL_LINK_TO_DPI is not set +# CONFIG_DRM_IMX93_MIPI_DSI is not set +# end of Display Interface Bridges + +# CONFIG_DRM_IMX8_DC is not set +# CONFIG_DRM_IMX_DCSS is not set +# CONFIG_DRM_IMX_LCDC is not set +# CONFIG_DRM_ETNAVIV is not set +# CONFIG_DRM_HISI_HIBMC is not set +# CONFIG_DRM_HISI_KIRIN is not set +# CONFIG_DRM_LOGICVC is not set +# CONFIG_DRM_MXSFB is not set +# CONFIG_DRM_IMX_LCDIF is not set +# CONFIG_DRM_MESON is not set +# CONFIG_DRM_ARCPGU is not set +# CONFIG_DRM_BOCHS is not set +# CONFIG_DRM_CIRRUS_QEMU is not set +# CONFIG_DRM_GM12U320 is not set +# CONFIG_DRM_PANEL_MIPI_DBI is not set +# CONFIG_DRM_PIXPAPER is not set +# CONFIG_TINYDRM_HX8357D is not set +# CONFIG_TINYDRM_ILI9163 is not set +# CONFIG_TINYDRM_ILI9225 is not set +# CONFIG_TINYDRM_ILI9341 is not set +# CONFIG_TINYDRM_ILI9486 is not set +# CONFIG_TINYDRM_MI0283QT is not set +# CONFIG_TINYDRM_REPAPER is not set +# CONFIG_TINYDRM_SHARP_MEMORY is not set +# CONFIG_DRM_PL111 is not set +# CONFIG_DRM_XEN_FRONTEND is not set +# CONFIG_DRM_LIMA is not set +# CONFIG_DRM_PANFROST is not set +# CONFIG_DRM_PANTHOR is not set +# CONFIG_DRM_TIDSS is not set +# CONFIG_DRM_ADP is not set +# CONFIG_DRM_GUD is not set +# CONFIG_DRM_ST7571_I2C is not set +# CONFIG_DRM_ST7586 is not set +# CONFIG_DRM_ST7735R is not set +# CONFIG_DRM_SSD130X is not set +# CONFIG_DRM_SPRD is not set +# CONFIG_DRM_POWERVR is not set +# CONFIG_DRM_TYR is not set +CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_ASILIANT=y +CONFIG_FB_IMSTT=y +# CONFIG_FB_UVESA is not set +# CONFIG_FB_EFI is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_I740 is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_CARMINE is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_IBM_GXT4500 is not set +# CONFIG_FB_XILINX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_XEN_FBDEV_FRONTEND is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_SSD1307 is not set +# CONFIG_FB_SM712 is not set +CONFIG_FB_CORE=y +CONFIG_FB_NOTIFY=y +CONFIG_FB_DEVICE=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYSMEM_FOPS=y +CONFIG_FB_DEFERRED_IO=y +CONFIG_FB_IOMEM_FOPS=y +CONFIG_FB_IOMEM_HELPERS=y +CONFIG_FB_SYSMEM_HELPERS=y +CONFIG_FB_SYSMEM_HELPERS_DEFERRED=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +# end of Frame buffer Devices + +# +# Backlight & LCD device support +# +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_KTD253 is not set +# CONFIG_BACKLIGHT_KTD2801 is not set +# CONFIG_BACKLIGHT_KTZ8866 is not set +# CONFIG_BACKLIGHT_PWM is not set +# CONFIG_BACKLIGHT_DA903X is not set +# CONFIG_BACKLIGHT_DA9052 is not set +# CONFIG_BACKLIGHT_MAX8925 is not set +# CONFIG_BACKLIGHT_APPLE_DWI is not set +# CONFIG_BACKLIGHT_QCOM_WLED is not set +# CONFIG_BACKLIGHT_WM831X is not set +# CONFIG_BACKLIGHT_ADP5520 is not set +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_88PM860X is not set +# CONFIG_BACKLIGHT_AAT2870 is not set +# CONFIG_BACKLIGHT_LM3509 is not set +# CONFIG_BACKLIGHT_LM3630A is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_LP8788 is not set +# CONFIG_BACKLIGHT_MP3309C is not set +# CONFIG_BACKLIGHT_PANDORA is not set +# CONFIG_BACKLIGHT_AS3711 is not set +# CONFIG_BACKLIGHT_GPIO is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_BD6107 is not set +# CONFIG_BACKLIGHT_ARCXCNN is not set +# CONFIG_BACKLIGHT_LED is not set +# end of Backlight & LCD device support + +CONFIG_HDMI=y + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_DUMMY_CONSOLE_COLUMNS=80 +CONFIG_DUMMY_CONSOLE_ROWS=25 +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION is not set +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y +# end of Console display driver support + +# CONFIG_LOGO is not set +# CONFIG_TRACE_GPU_MEM is not set +# end of Graphics support + +CONFIG_DRM_ACCEL=y +# CONFIG_DRM_ACCEL_ROCKET is not set +CONFIG_SOUND=m +CONFIG_SOUND_OSS_CORE=y +# CONFIG_SOUND_OSS_CORE_PRECLAIM is not set +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_SEQ_DEVICE=m +CONFIG_SND_JACK=y +CONFIG_SND_JACK_INPUT_DEV=y +CONFIG_SND_OSSEMUL=y +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +CONFIG_SND_PCM_TIMER=y +CONFIG_SND_HRTIMER=m +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_MAX_CARDS=32 +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_PROC_FS=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_CTL_FAST_LOOKUP is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_CTL_INPUT_VALIDATION is not set +CONFIG_SND_UTIMER=y +CONFIG_SND_VMASTER=y +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +# CONFIG_SND_SEQUENCER_OSS is not set +CONFIG_SND_SEQ_HRTIMER_DEFAULT=y +CONFIG_SND_SEQ_UMP=y +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_PCMTEST is not set +# CONFIG_SND_VIRMIDI is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_SERIAL_GENERIC is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_PCI=y +# CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS300 is not set +# CONFIG_SND_ALI5451 is not set +# CONFIG_SND_ATIIXP is not set +# CONFIG_SND_ATIIXP_MODEM is not set +# CONFIG_SND_AU8810 is not set +# CONFIG_SND_AU8820 is not set +# CONFIG_SND_AU8830 is not set +# CONFIG_SND_AW2 is not set +# CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BT87X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_CMIPCI is not set +# CONFIG_SND_OXYGEN is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_CTXFI is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MIA is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGODJ is not set +# CONFIG_SND_INDIGOIOX is not set +# CONFIG_SND_INDIGODJX is not set +# CONFIG_SND_EMU10K1 is not set +# CONFIG_SND_EMU10K1X is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_ES1938 is not set +# CONFIG_SND_ES1968 is not set +# CONFIG_SND_FM801 is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_ICE1712 is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_LOLA is not set +# CONFIG_SND_LX6464ES is not set +# CONFIG_SND_MAESTRO3 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_SE6X is not set +# CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_TRIDENT is not set +# CONFIG_SND_VIA82XX is not set +# CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VIRTUOSO is not set +# CONFIG_SND_VX222 is not set +# CONFIG_SND_YMFPCI is not set + +# +# HD-Audio +# +CONFIG_SND_HDA=m +CONFIG_SND_HDA_HWDEP=y +CONFIG_SND_HDA_RECONFIG=y +CONFIG_SND_HDA_INPUT_BEEP=y +CONFIG_SND_HDA_INPUT_BEEP_MODE=0 +CONFIG_SND_HDA_PATCH_LOADER=y +CONFIG_SND_HDA_POWER_SAVE_DEFAULT=1 +# CONFIG_SND_HDA_CTL_DEV_ID is not set +CONFIG_SND_HDA_PREALLOC_SIZE=64 +CONFIG_SND_HDA_INTEL=m +# CONFIG_SND_HDA_TEGRA is not set +# CONFIG_SND_HDA_ACPI is not set +# CONFIG_SND_HDA_CODEC_ANALOG is not set +# CONFIG_SND_HDA_CODEC_SIGMATEL is not set +# CONFIG_SND_HDA_CODEC_VIA is not set +# CONFIG_SND_HDA_CODEC_CONEXANT is not set +# CONFIG_SND_HDA_CODEC_SENARYTECH is not set +# CONFIG_SND_HDA_CODEC_CA0110 is not set +# CONFIG_SND_HDA_CODEC_CA0132 is not set +# CONFIG_SND_HDA_CODEC_CMEDIA is not set +# CONFIG_SND_HDA_CODEC_CM9825 is not set +# CONFIG_SND_HDA_CODEC_SI3054 is not set +CONFIG_SND_HDA_GENERIC=m +# CONFIG_SND_HDA_CODEC_REALTEK is not set +# CONFIG_SND_HDA_CODEC_CIRRUS is not set +# CONFIG_SND_HDA_CODEC_HDMI is not set +CONFIG_SND_HDA_CORE=m +CONFIG_SND_INTEL_NHLT=y +CONFIG_SND_INTEL_DSP_CONFIG=m +CONFIG_SND_INTEL_SOUNDWIRE_ACPI=m +# end of HD-Audio + +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +# CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_HIFACE is not set +# CONFIG_SND_BCD2000 is not set +# CONFIG_SND_USB_POD is not set +# CONFIG_SND_USB_PODHD is not set +# CONFIG_SND_USB_TONEPORT is not set +# CONFIG_SND_USB_VARIAX is not set +# CONFIG_SND_SOC is not set +# CONFIG_SND_XEN_FRONTEND is not set +# CONFIG_SND_VIRTIO is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=m +CONFIG_HID_BATTERY_STRENGTH=y +CONFIG_HIDRAW=y +# CONFIG_UHID is not set +CONFIG_HID_GENERIC=m +# CONFIG_HID_HAPTIC is not set + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACCUTOUCH is not set +# CONFIG_HID_ACRUX is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_ASUS is not set +# CONFIG_HID_AUREAL is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_BETOP_FF is not set +# CONFIG_HID_BIGBEN_FF is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CORSAIR is not set +# CONFIG_HID_COUGAR is not set +# CONFIG_HID_MACALLY is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_CMEDIA is not set +# CONFIG_HID_CP2112 is not set +# CONFIG_HID_CREATIVE_SB0540 is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_ELAN is not set +# CONFIG_HID_ELECOM is not set +# CONFIG_HID_ELO is not set +# CONFIG_HID_EVISION is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_FT260 is not set +# CONFIG_HID_GEMBIRD is not set +# CONFIG_HID_GFRM is not set +# CONFIG_HID_GLORIOUS is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_GOODIX_SPI is not set +# CONFIG_HID_GOOGLE_STADIA_FF is not set +# CONFIG_HID_VIVALDI is not set +# CONFIG_HID_GT683R is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_KYSONA is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_VIEWSONIC is not set +# CONFIG_HID_VRC2 is not set +# CONFIG_HID_XIAOMI is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_ITE is not set +# CONFIG_HID_JABRA is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LED is not set +# CONFIG_HID_LENOVO is not set +# CONFIG_HID_LETSKETCH is not set +# CONFIG_HID_MAGICMOUSE is not set +# CONFIG_HID_MALTRON is not set +# CONFIG_HID_MAYFLASH is not set +# CONFIG_HID_MEGAWORLD_FF is not set +# CONFIG_HID_REDRAGON is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NINTENDO is not set +# CONFIG_HID_NTI is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PENMOUNT is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PLANTRONICS is not set +# CONFIG_HID_PXRC is not set +# CONFIG_HID_RAZER is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_RETRODE is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SEMITEK is not set +# CONFIG_HID_SIGMAMICRO is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEAM is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_RMI is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_TOPRE is not set +# CONFIG_HID_THINGM is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_UDRAW_PS3 is not set +# CONFIG_HID_U2FZERO is not set +# CONFIG_HID_UNIVERSAL_PIDFF is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_WIIMOTE is not set +# CONFIG_HID_WINWING is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HID_SENSOR_HUB is not set +# CONFIG_HID_ALPS is not set +# CONFIG_HID_MCP2200 is not set +# CONFIG_HID_MCP2221 is not set +# end of Special HID drivers + +# +# HID-BPF support +# +CONFIG_HID_BPF=y +# end of HID-BPF support + +# CONFIG_I2C_HID is not set + +# +# USB HID support +# +CONFIG_USB_HID=m +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# end of USB HID Boot Protocol drivers +# end of USB HID support + +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_LED_TRIG=y +# CONFIG_USB_ULPI_BUS is not set +# CONFIG_USB_CONN_GPIO is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +CONFIG_USB_PCI=y +CONFIG_USB_PCI_AMD=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_FEW_INIT_RETRIES is not set +CONFIG_USB_DYNAMIC_MINORS=y +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_PRODUCTLIST is not set +# CONFIG_USB_OTG_DISABLE_EXTERNAL_HUB is not set +# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set +CONFIG_USB_AUTOSUSPEND_DELAY=2 +CONFIG_USB_DEFAULT_AUTHORIZATION_MODE=1 +# CONFIG_USB_MON is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_DBGCAP=y +CONFIG_USB_XHCI_PCI=y +# CONFIG_USB_XHCI_PCI_RENESAS is not set +# CONFIG_USB_XHCI_PLATFORM is not set +# CONFIG_USB_XHCI_MTK is not set +# CONFIG_USB_XHCI_MVEBU is not set +# CONFIG_USB_XHCI_SIDEBAND is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_FSL is not set +# CONFIG_USB_EHCI_HCD_NPCM7XX is not set +CONFIG_USB_EHCI_HCD_ORION=y +# CONFIG_USB_EHCI_TEGRA is not set +# CONFIG_USB_EHCI_HCD_PLATFORM is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_MAX3421_HCD is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PCI=y +# CONFIG_USB_OHCI_HCD_PLATFORM is not set +CONFIG_USB_UHCI_HCD=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HCD_TEST_MODE is not set +# CONFIG_USB_XEN_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; see USB_STORAGE Help for more info +# +# CONFIG_USB_STORAGE is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USBIP_CORE is not set + +# +# USB dual-mode controller drivers +# +# CONFIG_USB_CDNS_SUPPORT is not set +# CONFIG_USB_MTU3 is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_DWC3 is not set +CONFIG_USB_DWC2=y +CONFIG_USB_DWC2_HOST=y + +# +# Gadget/Dual-role mode requires USB Gadget support to be enabled +# +# CONFIG_USB_DWC2_PCI is not set +# CONFIG_USB_DWC2_DEBUG is not set +# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set +# CONFIG_USB_CHIPIDEA is not set +# CONFIG_USB_ISP1760 is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_QCOM_EUD is not set +# CONFIG_APPLE_MFI_FASTCHARGE is not set +# CONFIG_USB_LJCA is not set +# CONFIG_USB_USBIO is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_EHSET_TEST_FIXTURE is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_HUB_USB251XB is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_HSIC_USB4604 is not set +# CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_CHAOSKEY is not set +# CONFIG_USB_ONBOARD_DEV is not set + +# +# USB Physical Layer drivers +# +CONFIG_USB_PHY=y +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ISP1301 is not set +CONFIG_USB_MXS_PHY=y +# CONFIG_USB_TEGRA_PHY is not set +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y +# end of USB Physical Layer drivers + +# CONFIG_USB_GADGET is not set +# CONFIG_TYPEC is not set +CONFIG_USB_ROLE_SWITCH=y +CONFIG_MMC=y +# CONFIG_PWRSEQ_EMMC is not set +# CONFIG_PWRSEQ_SIMPLE is not set +# CONFIG_MMC_BLOCK is not set +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set +CONFIG_MMC_CRYPTO=y + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_ARMMMCI=y +CONFIG_MMC_STM32_SDMMC=y +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_MESON_GX is not set +# CONFIG_MMC_MESON_MX_SDIO is not set +# CONFIG_MMC_MXC is not set +# CONFIG_MMC_TIFM_SD is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MMC_SDHI is not set +# CONFIG_MMC_CB710 is not set +# CONFIG_MMC_VIA_SDMMC is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_SH_MMCIF is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_USDHI6ROL0 is not set +# CONFIG_MMC_SUNXI is not set +# CONFIG_MMC_CQHCI is not set +# CONFIG_MMC_HSQ is not set +# CONFIG_MMC_TOSHIBA_PCI is not set +# CONFIG_MMC_MTK is not set +# CONFIG_MMC_OWL is not set +# CONFIG_SCSI_UFSHCD is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +# CONFIG_LEDS_CLASS_FLASH is not set +# CONFIG_LEDS_CLASS_MULTICOLOR is not set +CONFIG_LEDS_BRIGHTNESS_HW_CHANGED=y + +# +# LED drivers +# +# CONFIG_LEDS_88PM860X is not set +# CONFIG_LEDS_AN30259A is not set +# CONFIG_LEDS_AW200XX is not set +# CONFIG_LEDS_AW2013 is not set +# CONFIG_LEDS_BCM6328 is not set +# CONFIG_LEDS_BCM6358 is not set +# CONFIG_LEDS_CR0014114 is not set +# CONFIG_LEDS_EL15203000 is not set +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3532 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_LM3692X is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP3952 is not set +# CONFIG_LEDS_LP8788 is not set +# CONFIG_LEDS_LP8860 is not set +# CONFIG_LEDS_LP8864 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_PCA995X is not set +# CONFIG_LEDS_WM831X_STATUS is not set +# CONFIG_LEDS_WM8350 is not set +# CONFIG_LEDS_DA903X is not set +# CONFIG_LEDS_DA9052 is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_PWM is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2606MVV is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_ADP5520 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_TLC591XX is not set +# CONFIG_LEDS_MAX8997 is not set +# CONFIG_LEDS_LM355x is not set +# CONFIG_LEDS_IS31FL319X is not set +# CONFIG_LEDS_IS31FL32XX is not set + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +# CONFIG_LEDS_BLINKM is not set +CONFIG_LEDS_SYSCON=y +# CONFIG_LEDS_MLXREG is not set +# CONFIG_LEDS_USER is not set +# CONFIG_LEDS_SPI_BYTE is not set +# CONFIG_LEDS_LM3697 is not set +# CONFIG_LEDS_ST1202 is not set + +# +# Flash and Torch LED drivers +# + +# +# RGB LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_TRIGGER_TIMER is not set +# CONFIG_LEDS_TRIGGER_ONESHOT is not set +CONFIG_LEDS_TRIGGER_DISK=y +# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +CONFIG_LEDS_TRIGGER_CPU=y +# CONFIG_LEDS_TRIGGER_ACTIVITY is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +CONFIG_LEDS_TRIGGER_PANIC=y +# CONFIG_LEDS_TRIGGER_NETDEV is not set +# CONFIG_LEDS_TRIGGER_PATTERN is not set +# CONFIG_LEDS_TRIGGER_TTY is not set +# CONFIG_LEDS_TRIGGER_INPUT_EVENTS is not set + +# +# Simatic LED drivers +# +CONFIG_ACCESSIBILITY=y +# CONFIG_A11Y_BRAILLE_CONSOLE is not set + +# +# Speakup console speech +# +# CONFIG_SPEAKUP is not set +# end of Speakup console speech + +# CONFIG_INFINIBAND is not set +CONFIG_EDAC_SUPPORT=y +CONFIG_EDAC=y +# CONFIG_EDAC_LEGACY_SYSFS is not set +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_GHES=y +# CONFIG_EDAC_SCRUB is not set +# CONFIG_EDAC_ECS is not set +# CONFIG_EDAC_MEM_REPAIR is not set +# CONFIG_EDAC_LAYERSCAPE is not set +# CONFIG_EDAC_THUNDERX is not set +CONFIG_EDAC_ALTERA=y +CONFIG_EDAC_ALTERA_SDRAM=y +CONFIG_EDAC_ALTERA_OCRAM=y +CONFIG_EDAC_ALTERA_ETHERNET=y +CONFIG_EDAC_ALTERA_USB=y +# CONFIG_EDAC_SYNOPSYS is not set +# CONFIG_EDAC_XGENE is not set +# CONFIG_EDAC_BLUEFIELD is not set +# CONFIG_EDAC_DMC520 is not set +# CONFIG_EDAC_ZYNQMP is not set +# CONFIG_EDAC_NPCM is not set +# CONFIG_EDAC_VERSAL is not set +# CONFIG_EDAC_CORTEX_A72 is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_SYSTOHC_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set +CONFIG_RTC_NVMEM=y + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_88PM860X is not set +# CONFIG_RTC_DRV_88PM886 is not set +# CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABEOZ9 is not set +# CONFIG_RTC_DRV_ABX80X is not set +# CONFIG_RTC_DRV_AS3722 is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_LP8788 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_MAX8925 is not set +# CONFIG_RTC_DRV_MAX8998 is not set +# CONFIG_RTC_DRV_MAX8997 is not set +# CONFIG_RTC_DRV_MAX31335 is not set +# CONFIG_RTC_DRV_MAX77686 is not set +# CONFIG_RTC_DRV_NCT3018Y is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12026 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF85363 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_TWL4030 is not set +# CONFIG_RTC_DRV_PALMAS is not set +# CONFIG_RTC_DRV_TPS6586X is not set +# CONFIG_RTC_DRV_TPS65910 is not set +# CONFIG_RTC_DRV_RC5T583 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8010 is not set +# CONFIG_RTC_DRV_RX8111 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3028 is not set +# CONFIG_RTC_DRV_RV3032 is not set +# CONFIG_RTC_DRV_RV8803 is not set +# CONFIG_RTC_DRV_SD2405AL is not set +# CONFIG_RTC_DRV_SD3078 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1302 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6916 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_MCP795 is not set +CONFIG_RTC_I2C_AND_SPI=y + +# +# SPI and I2C RTC drivers +# +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set +# CONFIG_RTC_DRV_RX6110 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1685_FAMILY is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +# CONFIG_RTC_DRV_DA9052 is not set +# CONFIG_RTC_DRV_DA9055 is not set +# CONFIG_RTC_DRV_DA9063 is not set +CONFIG_RTC_DRV_EFI=y +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_WM831X is not set +# CONFIG_RTC_DRV_WM8350 is not set +# CONFIG_RTC_DRV_ZYNQMP is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_IMXDI is not set +# CONFIG_RTC_DRV_FSL_FTM_ALARM is not set +# CONFIG_RTC_DRV_MESON_VRTC is not set +# CONFIG_RTC_DRV_SH is not set +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +CONFIG_RTC_DRV_SUN6I=y +CONFIG_RTC_DRV_MV=y +# CONFIG_RTC_DRV_ARMADA38X is not set +# CONFIG_RTC_DRV_CADENCE is not set +# CONFIG_RTC_DRV_FTRTC010 is not set +# CONFIG_RTC_DRV_PCAP is not set +# CONFIG_RTC_DRV_TEGRA is not set +# CONFIG_RTC_DRV_MXC is not set +# CONFIG_RTC_DRV_MXC_V2 is not set +# CONFIG_RTC_DRV_SNVS is not set +# CONFIG_RTC_DRV_BBNSM is not set +# CONFIG_RTC_DRV_IMX_BBM_SCMI is not set +# CONFIG_RTC_DRV_MT2712 is not set +# CONFIG_RTC_DRV_MT7622 is not set +CONFIG_RTC_DRV_XGENE=y +# CONFIG_RTC_DRV_R7301 is not set +# CONFIG_RTC_DRV_STM32 is not set +CONFIG_RTC_DRV_RTD119X=y +# CONFIG_RTC_DRV_TI_K3 is not set +# CONFIG_RTC_DRV_MA35D1 is not set +# CONFIG_RTC_DRV_RENESAS_RTCA3 is not set +# CONFIG_RTC_DRV_GOLDFISH is not set +# CONFIG_RTC_DRV_AMLOGIC_A4 is not set +# CONFIG_RTC_DRV_S32G is not set + +# +# HID Sensor RTC drivers +# +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DMA_ACPI=y +CONFIG_DMA_OF=y +# CONFIG_ALTERA_MSGDMA is not set +CONFIG_AMBA_PL08X=y +# CONFIG_APPLE_ADMAC is not set +# CONFIG_ARM_DMA350 is not set +# CONFIG_AT_XDMAC is not set +# CONFIG_AXI_DMAC is not set +# CONFIG_DMA_SUN6I is not set +# CONFIG_DW_AXI_DMAC is not set +# CONFIG_FSL_EDMA is not set +# CONFIG_FSL_QDMA is not set +# CONFIG_HISI_DMA is not set +# CONFIG_IMX_DMA is not set +# CONFIG_IMX_SDMA is not set +# CONFIG_INTEL_IDMA64 is not set +# CONFIG_K3_DMA is not set +CONFIG_MV_XOR=y +CONFIG_MV_XOR_V2=y +CONFIG_MXS_DMA=y +# CONFIG_OWL_DMA is not set +# CONFIG_PL330_DMA is not set +# CONFIG_PLX_DMA is not set +# CONFIG_SPRD_DMA is not set +# CONFIG_TEGRA186_GPC_DMA is not set +CONFIG_TEGRA20_APB_DMA=y +# CONFIG_TEGRA210_ADMA is not set +# CONFIG_XGENE_DMA is not set +# CONFIG_XILINX_DMA is not set +# CONFIG_XILINX_XDMA is not set +# CONFIG_XILINX_ZYNQMP_DMA is not set +# CONFIG_XILINX_ZYNQMP_DPDMA is not set +# CONFIG_AMD_QDMA is not set +# CONFIG_MTK_HSDMA is not set +# CONFIG_MTK_CQDMA is not set +# CONFIG_MTK_UART_APDMA is not set +# CONFIG_QCOM_BAM_DMA is not set +# CONFIG_QCOM_GPI_DMA is not set +# CONFIG_QCOM_HIDMA_MGMT is not set +# CONFIG_QCOM_HIDMA is not set +# CONFIG_DW_DMAC is not set +# CONFIG_DW_DMAC_PCI is not set +# CONFIG_DW_EDMA is not set +# CONFIG_SF_PDMA is not set +# CONFIG_RCAR_DMAC is not set +# CONFIG_RENESAS_USB_DMAC is not set +# CONFIG_RZ_DMAC is not set +CONFIG_TI_K3_UDMA=y +CONFIG_TI_K3_UDMA_GLUE_LAYER=y +CONFIG_TI_K3_PSIL=y +CONFIG_STM32_DMA=y +CONFIG_STM32_DMAMUX=y +CONFIG_STM32_MDMA=y +# CONFIG_STM32_DMA3 is not set + +# +# DMA Clients +# +CONFIG_ASYNC_TX_DMA=y +# CONFIG_DMATEST is not set +CONFIG_DMA_ENGINE_RAID=y + +# +# DMABUF options +# +CONFIG_SYNC_FILE=y +CONFIG_SW_SYNC=y +CONFIG_UDMABUF=y +CONFIG_DMABUF_MOVE_NOTIFY=y +# CONFIG_DMABUF_DEBUG is not set +# CONFIG_DMABUF_SELFTESTS is not set +CONFIG_DMABUF_HEAPS=y +# CONFIG_DMABUF_SYSFS_STATS is not set +CONFIG_DMABUF_HEAPS_SYSTEM=y +CONFIG_DMABUF_HEAPS_CMA=y +CONFIG_DMABUF_HEAPS_CMA_LEGACY=y +# end of DMABUF options + +# CONFIG_UIO is not set +# CONFIG_VFIO is not set +CONFIG_IRQ_BYPASS_MANAGER=y +CONFIG_VIRT_DRIVERS=y +# CONFIG_VMGENID is not set +# CONFIG_VBOXGUEST is not set +# CONFIG_NITRO_ENCLAVES is not set +# CONFIG_EFI_SECRET is not set +# CONFIG_ARM_PKVM_GUEST is not set +# CONFIG_ARM_CCA_GUEST is not set +CONFIG_VIRTIO_ANCHOR=y +CONFIG_VIRTIO=y +CONFIG_VIRTIO_PCI_LIB=y +CONFIG_VIRTIO_PCI_LIB_LEGACY=y +CONFIG_VIRTIO_MENU=y +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_PCI_LEGACY=y +# CONFIG_VIRTIO_PMEM is not set +CONFIG_VIRTIO_BALLOON=y +# CONFIG_VIRTIO_MEM is not set +# CONFIG_VIRTIO_INPUT is not set +CONFIG_VIRTIO_MMIO=y +CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y +# CONFIG_VIRTIO_DEBUG is not set +# CONFIG_VIRTIO_RTC is not set +# CONFIG_VDPA is not set +CONFIG_VHOST_MENU=y +# CONFIG_VHOST_NET is not set +# CONFIG_VHOST_VSOCK is not set +# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set +CONFIG_VHOST_ENABLE_FORK_OWNER_CONTROL=y + +# +# Microsoft Hyper-V guest support +# +# CONFIG_HYPERV is not set +# end of Microsoft Hyper-V guest support + +# +# Xen driver support +# +CONFIG_XEN_BALLOON=y +CONFIG_XEN_BALLOON_MEMORY_HOTPLUG=y +CONFIG_XEN_SCRUB_PAGES_DEFAULT=y +# CONFIG_XEN_DEV_EVTCHN is not set +CONFIG_XEN_BACKEND=y +# CONFIG_XENFS is not set +CONFIG_XEN_SYS_HYPERVISOR=y +CONFIG_XEN_XENBUS_FRONTEND=y +# CONFIG_XEN_GNTDEV is not set +# CONFIG_XEN_GRANT_DEV_ALLOC is not set +CONFIG_XEN_GRANT_DMA_ALLOC=y +CONFIG_SWIOTLB_XEN=y +# CONFIG_XEN_PCIDEV_STUB is not set +# CONFIG_XEN_PVCALLS_FRONTEND is not set +# CONFIG_XEN_PVCALLS_BACKEND is not set +# CONFIG_XEN_PRIVCMD is not set +CONFIG_XEN_EFI=y +CONFIG_XEN_AUTO_XLATE=y +CONFIG_XEN_UNPOPULATED_ALLOC=y +CONFIG_XEN_GRANT_DMA_IOMMU=y +CONFIG_XEN_GRANT_DMA_OPS=y +CONFIG_XEN_VIRTIO=y +# CONFIG_XEN_VIRTIO_FORCE_GRANT is not set +# end of Xen driver support + +# CONFIG_GREYBUS is not set +# CONFIG_COMEDI is not set +CONFIG_STAGING=y +# CONFIG_FB_SM750 is not set +# CONFIG_MFD_NVEC is not set +CONFIG_STAGING_MEDIA=y +# CONFIG_DVB_AV7110 is not set +# CONFIG_VIDEO_MAX96712 is not set +# CONFIG_VIDEO_MESON_VDEC is not set + +# +# StarFive media platform drivers +# +CONFIG_VIDEO_SUNXI=y +# CONFIG_VIDEO_SUNXI_CEDRUS is not set +# CONFIG_VIDEO_SUN6I_ISP is not set +# CONFIG_STAGING_MEDIA_DEPRECATED is not set +# CONFIG_FB_TFT is not set +# CONFIG_XIL_AXIS_FIFO is not set +CONFIG_VME_BUS=y + +# +# VME Bridge Drivers +# +# CONFIG_VME_TSI148 is not set +# CONFIG_VME_FAKE is not set + +# +# VME Device Drivers +# +# CONFIG_VME_USER is not set +# CONFIG_GPIB is not set +# CONFIG_GOLDFISH is not set +CONFIG_CHROME_PLATFORMS=y +# CONFIG_CHROMEOS_ACPI is not set +# CONFIG_CHROMEOS_TBMC is not set +# CONFIG_CHROMEOS_OF_HW_PROBER is not set +# CONFIG_CROS_EC is not set +# CONFIG_CROS_KBD_LED_BACKLIGHT is not set +# CONFIG_CROS_HPS_I2C is not set +# CONFIG_CHROMEOS_PRIVACY_SCREEN is not set +CONFIG_CZNIC_PLATFORMS=y +CONFIG_MELLANOX_PLATFORM=y +# CONFIG_MLX_PLATFORM is not set +# CONFIG_MLXREG_DPU is not set +# CONFIG_MLXREG_HOTPLUG is not set +# CONFIG_MLXREG_IO is not set +# CONFIG_MLXREG_LC is not set +# CONFIG_MLXBF_TMFIFO is not set +# CONFIG_MLXBF_BOOTCTL is not set +# CONFIG_MLXBF_PMC is not set +# CONFIG_NVSW_SN2201 is not set +CONFIG_SURFACE_PLATFORMS=y +# CONFIG_SURFACE_3_POWER_OPREGION is not set +# CONFIG_SURFACE_GPE is not set +# CONFIG_SURFACE_HOTPLUG is not set +# CONFIG_SURFACE_PRO3_BUTTON is not set +# CONFIG_SURFACE_AGGREGATOR is not set +CONFIG_ARM64_PLATFORM_DEVICES=y +# CONFIG_EC_ACER_ASPIRE1 is not set +# CONFIG_EC_HUAWEI_GAOKUN is not set +# CONFIG_EC_LENOVO_YOGA_C630 is not set +# CONFIG_EC_LENOVO_THINKPAD_T14S is not set +CONFIG_HAVE_CLK=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y +# CONFIG_COMMON_CLK_WM831X is not set + +# +# Clock driver for ARM Reference designs +# +CONFIG_CLK_ICST=y +CONFIG_CLK_SP810=y +CONFIG_CLK_VEXPRESS_OSC=y +# end of Clock driver for ARM Reference designs + +# CONFIG_LMK04832 is not set +# CONFIG_COMMON_CLK_APPLE_NCO is not set +# CONFIG_COMMON_CLK_MAX77686 is not set +# CONFIG_COMMON_CLK_MAX9485 is not set +CONFIG_COMMON_CLK_SCMI=y +# CONFIG_COMMON_CLK_SI5341 is not set +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_SI514 is not set +# CONFIG_COMMON_CLK_SI544 is not set +# CONFIG_COMMON_CLK_SI570 is not set +CONFIG_COMMON_CLK_BM1880=y +# CONFIG_COMMON_CLK_CDCE706 is not set +# CONFIG_COMMON_CLK_CDCE925 is not set +# CONFIG_COMMON_CLK_CS2000_CP is not set +CONFIG_COMMON_CLK_EN7523=y +# CONFIG_COMMON_CLK_FSL_FLEXSPI is not set +CONFIG_COMMON_CLK_FSL_SAI=y +# CONFIG_CLK_TWL is not set +# CONFIG_CLK_TWL6040 is not set +# CONFIG_COMMON_CLK_AXI_CLKGEN is not set +CONFIG_CLK_QORIQ=y +# CONFIG_CLK_LS1028A_PLLDIG is not set +CONFIG_COMMON_CLK_XGENE=y +# CONFIG_COMMON_CLK_LOCHNAGAR is not set +# CONFIG_COMMON_CLK_NPCM8XX is not set +# CONFIG_COMMON_CLK_PALMAS is not set +# CONFIG_COMMON_CLK_PWM is not set +# CONFIG_COMMON_CLK_RS9_PCIE is not set +# CONFIG_COMMON_CLK_SI521XX is not set +# CONFIG_COMMON_CLK_VC3 is not set +# CONFIG_COMMON_CLK_VC5 is not set +# CONFIG_COMMON_CLK_VC7 is not set +CONFIG_COMMON_CLK_FIXED_MMIO=y +CONFIG_CLK_ACTIONS=y +CONFIG_CLK_OWL_S500=y +CONFIG_CLK_OWL_S700=y +CONFIG_CLK_OWL_S900=y +# CONFIG_COMMON_CLK_HI3516CV300 is not set +# CONFIG_COMMON_CLK_HI3519 is not set +CONFIG_COMMON_CLK_HI3559A=y +CONFIG_COMMON_CLK_HI3660=y +CONFIG_COMMON_CLK_HI3670=y +# CONFIG_COMMON_CLK_HI3798CV200 is not set +CONFIG_COMMON_CLK_HI6220=y +CONFIG_RESET_HISI=y +CONFIG_STUB_CLK_HI6220=y +CONFIG_STUB_CLK_HI3660=y +CONFIG_MXC_CLK=y +CONFIG_CLK_IMX8MM=y +CONFIG_CLK_IMX8MN=y +CONFIG_CLK_IMX8MP=y +CONFIG_CLK_IMX8MQ=y +# CONFIG_CLK_IMX8ULP is not set +# CONFIG_CLK_IMX93 is not set +# CONFIG_CLK_IMX95_BLK_CTL is not set +# CONFIG_TI_SCI_CLK is not set +CONFIG_TI_SYSCON_CLK=y + +# +# Clock driver for MediaTek SoC +# +CONFIG_COMMON_CLK_MEDIATEK=y +CONFIG_COMMON_CLK_MEDIATEK_FHCTL=y +CONFIG_COMMON_CLK_MT2712=y +CONFIG_COMMON_CLK_MT2712_BDPSYS=y +CONFIG_COMMON_CLK_MT2712_IMGSYS=y +CONFIG_COMMON_CLK_MT2712_JPGDECSYS=y +CONFIG_COMMON_CLK_MT2712_MFGCFG=y +CONFIG_COMMON_CLK_MT2712_MMSYS=y +CONFIG_COMMON_CLK_MT2712_VDECSYS=y +CONFIG_COMMON_CLK_MT2712_VENCSYS=y +# CONFIG_COMMON_CLK_MT6735 is not set +CONFIG_COMMON_CLK_MT6765=y +CONFIG_COMMON_CLK_MT6765_AUDIOSYS=y +CONFIG_COMMON_CLK_MT6765_CAMSYS=y +CONFIG_COMMON_CLK_MT6765_GCESYS=y +CONFIG_COMMON_CLK_MT6765_MMSYS=y +CONFIG_COMMON_CLK_MT6765_IMGSYS=y +CONFIG_COMMON_CLK_MT6765_VCODECSYS=y +CONFIG_COMMON_CLK_MT6765_MFGSYS=y +CONFIG_COMMON_CLK_MT6765_MIPI0ASYS=y +CONFIG_COMMON_CLK_MT6765_MIPI0BSYS=y +CONFIG_COMMON_CLK_MT6765_MIPI1ASYS=y +CONFIG_COMMON_CLK_MT6765_MIPI1BSYS=y +CONFIG_COMMON_CLK_MT6765_MIPI2ASYS=y +CONFIG_COMMON_CLK_MT6765_MIPI2BSYS=y +CONFIG_COMMON_CLK_MT6779=y +CONFIG_COMMON_CLK_MT6779_MMSYS=y +CONFIG_COMMON_CLK_MT6779_IMGSYS=y +CONFIG_COMMON_CLK_MT6779_IPESYS=y +CONFIG_COMMON_CLK_MT6779_CAMSYS=y +CONFIG_COMMON_CLK_MT6779_VDECSYS=y +CONFIG_COMMON_CLK_MT6779_VENCSYS=y +CONFIG_COMMON_CLK_MT6779_MFGCFG=y +CONFIG_COMMON_CLK_MT6779_AUDSYS=y +# CONFIG_COMMON_CLK_MT6795 is not set +CONFIG_COMMON_CLK_MT6797=y +CONFIG_COMMON_CLK_MT6797_MMSYS=y +CONFIG_COMMON_CLK_MT6797_IMGSYS=y +CONFIG_COMMON_CLK_MT6797_VDECSYS=y +CONFIG_COMMON_CLK_MT6797_VENCSYS=y +CONFIG_COMMON_CLK_MT7622=y +CONFIG_COMMON_CLK_MT7622_ETHSYS=y +CONFIG_COMMON_CLK_MT7622_HIFSYS=y +CONFIG_COMMON_CLK_MT7622_AUDSYS=y +CONFIG_COMMON_CLK_MT7981=y +# CONFIG_COMMON_CLK_MT7981_ETHSYS is not set +CONFIG_COMMON_CLK_MT7986=y +CONFIG_COMMON_CLK_MT7986_ETHSYS=y +# CONFIG_COMMON_CLK_MT7988 is not set +CONFIG_COMMON_CLK_MT8167=y +CONFIG_COMMON_CLK_MT8167_AUDSYS=y +CONFIG_COMMON_CLK_MT8167_IMGSYS=y +CONFIG_COMMON_CLK_MT8167_MFGCFG=y +CONFIG_COMMON_CLK_MT8167_MMSYS=y +CONFIG_COMMON_CLK_MT8167_VDECSYS=y +CONFIG_COMMON_CLK_MT8173=y +# CONFIG_COMMON_CLK_MT8173_IMGSYS is not set +CONFIG_COMMON_CLK_MT8173_MMSYS=y +# CONFIG_COMMON_CLK_MT8173_VDECSYS is not set +# CONFIG_COMMON_CLK_MT8173_VENCSYS is not set +CONFIG_COMMON_CLK_MT8183=y +CONFIG_COMMON_CLK_MT8183_AUDIOSYS=y +CONFIG_COMMON_CLK_MT8183_CAMSYS=y +CONFIG_COMMON_CLK_MT8183_IMGSYS=y +CONFIG_COMMON_CLK_MT8183_IPU_CORE0=y +CONFIG_COMMON_CLK_MT8183_IPU_CORE1=y +CONFIG_COMMON_CLK_MT8183_IPU_ADL=y +CONFIG_COMMON_CLK_MT8183_IPU_CONN=y +CONFIG_COMMON_CLK_MT8183_MFGCFG=y +CONFIG_COMMON_CLK_MT8183_MMSYS=y +CONFIG_COMMON_CLK_MT8183_VDECSYS=y +CONFIG_COMMON_CLK_MT8183_VENCSYS=y +CONFIG_COMMON_CLK_MT8186=y +# CONFIG_COMMON_CLK_MT8186_CAMSYS is not set +# CONFIG_COMMON_CLK_MT8186_IMGSYS is not set +# CONFIG_COMMON_CLK_MT8186_IMP_IIC_WRAP is not set +# CONFIG_COMMON_CLK_MT8186_MCUSYS is not set +# CONFIG_COMMON_CLK_MT8186_MDPSYS is not set +# CONFIG_COMMON_CLK_MT8186_MFGCFG is not set +# CONFIG_COMMON_CLK_MT8186_MMSYS is not set +# CONFIG_COMMON_CLK_MT8186_VDECSYS is not set +# CONFIG_COMMON_CLK_MT8186_VENCSYS is not set +# CONFIG_COMMON_CLK_MT8188 is not set +CONFIG_COMMON_CLK_MT8192=y +CONFIG_COMMON_CLK_MT8192_AUDSYS=y +CONFIG_COMMON_CLK_MT8192_CAMSYS=y +CONFIG_COMMON_CLK_MT8192_IMGSYS=y +CONFIG_COMMON_CLK_MT8192_IMP_IIC_WRAP=y +CONFIG_COMMON_CLK_MT8192_IPESYS=y +CONFIG_COMMON_CLK_MT8192_MDPSYS=y +CONFIG_COMMON_CLK_MT8192_MFGCFG=y +CONFIG_COMMON_CLK_MT8192_MMSYS=y +CONFIG_COMMON_CLK_MT8192_MSDC=y +CONFIG_COMMON_CLK_MT8192_SCP_ADSP=y +CONFIG_COMMON_CLK_MT8192_VDECSYS=y +CONFIG_COMMON_CLK_MT8192_VENCSYS=y +CONFIG_COMMON_CLK_MT8195=y +# CONFIG_COMMON_CLK_MT8195_APUSYS is not set +# CONFIG_COMMON_CLK_MT8195_IMP_IIC_WRAP is not set +# CONFIG_COMMON_CLK_MT8195_MFGCFG is not set +# CONFIG_COMMON_CLK_MT8195_SCP_ADSP is not set +# CONFIG_COMMON_CLK_MT8195_VDOSYS is not set +# CONFIG_COMMON_CLK_MT8195_VPPSYS is not set +CONFIG_COMMON_CLK_MT8196=y +CONFIG_COMMON_CLK_MT8196_IMP_IIC_WRAP=y +CONFIG_COMMON_CLK_MT8196_MCUSYS=y +CONFIG_COMMON_CLK_MT8196_MDPSYS=y +CONFIG_COMMON_CLK_MT8196_MFGCFG=m +CONFIG_COMMON_CLK_MT8196_MMSYS=m +CONFIG_COMMON_CLK_MT8196_PEXTPSYS=y +CONFIG_COMMON_CLK_MT8196_UFSSYS=y +CONFIG_COMMON_CLK_MT8196_VDECSYS=m +CONFIG_COMMON_CLK_MT8196_VENCSYS=m +# CONFIG_COMMON_CLK_MT8365 is not set +CONFIG_COMMON_CLK_MT8516=y +CONFIG_COMMON_CLK_MT8516_AUDSYS=y +# end of Clock driver for MediaTek SoC + +# +# Clock support for Amlogic platforms +# +CONFIG_COMMON_CLK_MESON_REGMAP=y +CONFIG_COMMON_CLK_MESON_DUALDIV=y +CONFIG_COMMON_CLK_MESON_MPLL=y +CONFIG_COMMON_CLK_MESON_PLL=y +CONFIG_COMMON_CLK_MESON_VID_PLL_DIV=y +CONFIG_COMMON_CLK_MESON_VCLK=y +CONFIG_COMMON_CLK_MESON_CLKC_UTILS=y +CONFIG_COMMON_CLK_MESON_AO_CLKC=y +CONFIG_COMMON_CLK_MESON_CPU_DYNDIV=y +CONFIG_COMMON_CLK_GXBB=y +CONFIG_COMMON_CLK_AXG=y +# CONFIG_COMMON_CLK_AXG_AUDIO is not set +# CONFIG_COMMON_CLK_A1_PLL is not set +# CONFIG_COMMON_CLK_A1_PERIPHERALS is not set +CONFIG_COMMON_CLK_C3_PLL=y +# CONFIG_COMMON_CLK_C3_PERIPHERALS is not set +CONFIG_COMMON_CLK_G12A=y +# CONFIG_COMMON_CLK_S4_PLL is not set +# CONFIG_COMMON_CLK_S4_PERIPHERALS is not set +# end of Clock support for Amlogic platforms + +CONFIG_ARMADA_AP_CP_HELPER=y +CONFIG_ARMADA_37XX_CLK=y +CONFIG_ARMADA_AP806_SYSCON=y +CONFIG_ARMADA_CP110_SYSCON=y +CONFIG_COMMON_CLK_NUVOTON=y +CONFIG_CLK_MA35D1=y +CONFIG_QCOM_GDSC=y +CONFIG_COMMON_CLK_QCOM=y +# CONFIG_CLK_GLYMUR_DISPCC is not set +# CONFIG_CLK_GLYMUR_GCC is not set +# CONFIG_CLK_GLYMUR_TCSRCC is not set +# CONFIG_CLK_X1E80100_CAMCC is not set +# CONFIG_CLK_X1E80100_DISPCC is not set +# CONFIG_CLK_X1E80100_GCC is not set +# CONFIG_CLK_X1E80100_GPUCC is not set +# CONFIG_CLK_X1E80100_TCSRCC is not set +# CONFIG_CLK_X1P42100_GPUCC is not set +# CONFIG_CLK_QCM2290_GPUCC is not set +# CONFIG_QCOM_A53PLL is not set +# CONFIG_QCOM_A7PLL is not set +# CONFIG_QCOM_CLK_APCC_MSM8996 is not set +CONFIG_QCOM_CLK_RPMH=y +# CONFIG_IPQ_APSS_PLL is not set +# CONFIG_IPQ_APSS_5424 is not set +# CONFIG_IPQ_CMN_PLL is not set +# CONFIG_IPQ_GCC_4019 is not set +# CONFIG_IPQ_GCC_5018 is not set +# CONFIG_IPQ_GCC_5332 is not set +# CONFIG_IPQ_GCC_5424 is not set +# CONFIG_IPQ_GCC_6018 is not set +# CONFIG_IPQ_GCC_8074 is not set +# CONFIG_IPQ_GCC_9574 is not set +# CONFIG_IPQ_NSSCC_QCA8K is not set +# CONFIG_MSM_GCC_8916 is not set +# CONFIG_MSM_GCC_8917 is not set +# CONFIG_MSM_GCC_8939 is not set +# CONFIG_MSM_GCC_8953 is not set +# CONFIG_MSM_GCC_8976 is not set +# CONFIG_MSM_MMCC_8994 is not set +# CONFIG_MSM_GCC_8994 is not set +# CONFIG_MSM_GCC_8996 is not set +# CONFIG_MSM_MMCC_8996 is not set +# CONFIG_MSM_GCC_8998 is not set +# CONFIG_MSM_GPUCC_8998 is not set +# CONFIG_MSM_MMCC_8998 is not set +# CONFIG_QCM_GCC_2290 is not set +# CONFIG_QCM_DISPCC_2290 is not set +# CONFIG_QCS_DISPCC_615 is not set +# CONFIG_QCS_CAMCC_615 is not set +# CONFIG_QCS_GCC_404 is not set +# CONFIG_SA_CAMCC_8775P is not set +# CONFIG_QCS_GCC_8300 is not set +# CONFIG_QCS_GCC_615 is not set +# CONFIG_QCS_GPUCC_615 is not set +# CONFIG_QCS_VIDEOCC_615 is not set +# CONFIG_SC_CAMCC_7180 is not set +# CONFIG_SC_CAMCC_7280 is not set +# CONFIG_SC_CAMCC_8180X is not set +# CONFIG_SC_CAMCC_8280XP is not set +# CONFIG_SA_DISPCC_8775P is not set +# CONFIG_SC_DISPCC_7180 is not set +# CONFIG_SC_DISPCC_7280 is not set +# CONFIG_SC_DISPCC_8280XP is not set +# CONFIG_SA_GCC_8775P is not set +# CONFIG_SA_GPUCC_8775P is not set +# CONFIG_SAR_GCC_2130P is not set +# CONFIG_SAR_GPUCC_2130P is not set +# CONFIG_SC_GCC_7180 is not set +CONFIG_SC_GCC_7280=y +# CONFIG_SC_GCC_8180X is not set +# CONFIG_SC_GCC_8280XP is not set +# CONFIG_SC_GPUCC_7180 is not set +# CONFIG_SC_GPUCC_7280 is not set +# CONFIG_SC_GPUCC_8280XP is not set +# CONFIG_SC_LPASSCC_7280 is not set +# CONFIG_SC_LPASSCC_8280XP is not set +# CONFIG_SC_LPASS_CORECC_7180 is not set +# CONFIG_SC_LPASS_CORECC_7280 is not set +# CONFIG_SC_VIDEOCC_7180 is not set +# CONFIG_SC_VIDEOCC_7280 is not set +# CONFIG_SDM_CAMCC_845 is not set +# CONFIG_SDM_GCC_660 is not set +# CONFIG_SDM_MMCC_660 is not set +# CONFIG_SDM_GPUCC_660 is not set +# CONFIG_QCS_TURING_404 is not set +# CONFIG_QCS_Q6SSTOP_404 is not set +# CONFIG_QDU_GCC_1000 is not set +# CONFIG_QDU_ECPRICC_1000 is not set +# CONFIG_SDM_GCC_845 is not set +# CONFIG_SDM_GPUCC_845 is not set +# CONFIG_SDM_VIDEOCC_845 is not set +# CONFIG_SDM_DISPCC_845 is not set +# CONFIG_SDM_LPASSCC_845 is not set +# CONFIG_SDX_GCC_75 is not set +# CONFIG_SM_CAMCC_4450 is not set +# CONFIG_SM_CAMCC_6350 is not set +# CONFIG_SM_CAMCC_7150 is not set +# CONFIG_SM_CAMCC_MILOS is not set +# CONFIG_SM_CAMCC_8150 is not set +# CONFIG_SM_CAMCC_8250 is not set +# CONFIG_SM_CAMCC_8450 is not set +# CONFIG_SM_CAMCC_8550 is not set +# CONFIG_SM_CAMCC_8650 is not set +# CONFIG_SM_GCC_4450 is not set +# CONFIG_SM_GCC_6115 is not set +# CONFIG_SM_GCC_6125 is not set +# CONFIG_SM_GCC_6350 is not set +# CONFIG_SM_GCC_6375 is not set +# CONFIG_SM_GCC_7150 is not set +# CONFIG_SM_GCC_MILOS is not set +# CONFIG_SM_GCC_8150 is not set +# CONFIG_SM_GCC_8250 is not set +# CONFIG_SM_GCC_8350 is not set +# CONFIG_SM_GCC_8450 is not set +# CONFIG_SM_GCC_8550 is not set +# CONFIG_SM_GCC_8650 is not set +# CONFIG_SM_GCC_8750 is not set +# CONFIG_SM_GPUCC_4450 is not set +# CONFIG_SM_GPUCC_6115 is not set +# CONFIG_SM_GPUCC_6125 is not set +# CONFIG_SM_GPUCC_6375 is not set +# CONFIG_SM_GPUCC_6350 is not set +# CONFIG_SM_GPUCC_MILOS is not set +# CONFIG_SM_GPUCC_8150 is not set +# CONFIG_SM_GPUCC_8250 is not set +# CONFIG_SM_GPUCC_8350 is not set +# CONFIG_SM_GPUCC_8450 is not set +# CONFIG_SM_GPUCC_8550 is not set +# CONFIG_SM_GPUCC_8650 is not set +# CONFIG_SM_LPASSCC_6115 is not set +# CONFIG_SM_TCSRCC_8550 is not set +# CONFIG_SM_TCSRCC_8650 is not set +# CONFIG_SM_TCSRCC_8750 is not set +# CONFIG_SA_VIDEOCC_8775P is not set +# CONFIG_SM_VIDEOCC_6350 is not set +# CONFIG_SM_VIDEOCC_7150 is not set +# CONFIG_SM_VIDEOCC_MILOS is not set +# CONFIG_SM_VIDEOCC_8150 is not set +# CONFIG_SM_VIDEOCC_8250 is not set +# CONFIG_SM_VIDEOCC_8350 is not set +# CONFIG_SM_VIDEOCC_8550 is not set +# CONFIG_QCOM_HFPLL is not set +# CONFIG_KPSS_XCC is not set +# CONFIG_CLK_GFM_LPASS_SM8250 is not set +# CONFIG_SM_VIDEOCC_8450 is not set +CONFIG_CLK_RENESAS=y +CONFIG_CLK_R8A774A1=y +CONFIG_CLK_R8A774B1=y +CONFIG_CLK_R8A774C0=y +CONFIG_CLK_R8A774E1=y +CONFIG_CLK_R8A7795=y +CONFIG_CLK_R8A77960=y +CONFIG_CLK_R8A77961=y +CONFIG_CLK_R8A77965=y +CONFIG_CLK_R8A77970=y +CONFIG_CLK_R8A77980=y +CONFIG_CLK_R8A77990=y +CONFIG_CLK_R8A77995=y +CONFIG_CLK_R8A779A0=y +CONFIG_CLK_R8A779F0=y +CONFIG_CLK_R8A779G0=y +CONFIG_CLK_R8A779H0=y +CONFIG_CLK_R9A07G043=y +CONFIG_CLK_R9A07G044=y +CONFIG_CLK_R9A07G054=y +CONFIG_CLK_R9A08G045=y +CONFIG_CLK_R9A09G011=y +CONFIG_CLK_R9A09G047=y +CONFIG_CLK_R9A09G056=y +CONFIG_CLK_R9A09G057=y +CONFIG_CLK_R9A09G077=y +CONFIG_CLK_R9A09G087=y +CONFIG_CLK_RCAR_CPG_LIB=y +CONFIG_CLK_RCAR_GEN3_CPG=y +CONFIG_CLK_RCAR_GEN4_CPG=y +CONFIG_CLK_RCAR_USB2_CLOCK_SEL=y +CONFIG_CLK_RZG2L=y +CONFIG_CLK_RZV2H=y +# CONFIG_CLK_RENESAS_VBATTB is not set +CONFIG_CLK_RENESAS_CPG_MSSR=y +CONFIG_CLK_RENESAS_DIV6=y +CONFIG_COMMON_CLK_ROCKCHIP=y +CONFIG_CLK_PX30=y +CONFIG_CLK_RK3308=y +CONFIG_CLK_RK3328=y +CONFIG_CLK_RK3368=y +CONFIG_CLK_RK3399=y +CONFIG_CLK_RK3528=y +CONFIG_CLK_RK3562=y +CONFIG_CLK_RK3568=y +CONFIG_CLK_RK3576=y +CONFIG_CLK_RK3588=y +CONFIG_CLK_INTEL_SOCFPGA=y +CONFIG_CLK_INTEL_SOCFPGA64=y +# CONFIG_SPRD_COMMON_CLK is not set +CONFIG_SUNXI_CCU=y +CONFIG_SUN50I_A64_CCU=y +CONFIG_SUN50I_A100_CCU=y +CONFIG_SUN50I_A100_R_CCU=y +CONFIG_SUN50I_H6_CCU=y +CONFIG_SUN50I_H616_CCU=y +CONFIG_SUN50I_H6_R_CCU=y +CONFIG_SUN55I_A523_CCU=y +CONFIG_SUN55I_A523_MCU_CCU=y +CONFIG_SUN55I_A523_R_CCU=y +# CONFIG_SUN6I_RTC_CCU is not set +CONFIG_SUN8I_H3_CCU=y +CONFIG_SUN8I_DE2_CCU=y +CONFIG_SUN8I_R_CCU=y +CONFIG_CLK_TEGRA_BPMP=y +CONFIG_TEGRA_CLK_DFLL=y +CONFIG_COMMON_CLK_STM32MP=y +CONFIG_COMMON_CLK_STM32MP215=y +CONFIG_COMMON_CLK_STM32MP257=y +CONFIG_COMMON_CLK_VISCONTI=y +# CONFIG_XILINX_VCU is not set +# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set +CONFIG_COMMON_CLK_ZYNQMP=y +CONFIG_HWSPINLOCK=y +# CONFIG_HWSPINLOCK_OMAP is not set +# CONFIG_HWSPINLOCK_QCOM is not set +# CONFIG_HWSPINLOCK_SPRD is not set +# CONFIG_HWSPINLOCK_SUN6I is not set + +# +# Clock Source drivers +# +CONFIG_TIMER_OF=y +CONFIG_TIMER_ACPI=y +CONFIG_TIMER_PROBE=y +CONFIG_CLKSRC_MMIO=y +CONFIG_OMAP_DM_TIMER=y +CONFIG_DW_APB_TIMER=y +CONFIG_DW_APB_TIMER_OF=y +CONFIG_ROCKCHIP_TIMER=y +CONFIG_OWL_TIMER=y +CONFIG_SUN4I_TIMER=y +CONFIG_TEGRA_TIMER=y +CONFIG_TEGRA186_TIMER=y +CONFIG_NPCM7XX_TIMER=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y +CONFIG_FSL_ERRATUM_A008585=y +CONFIG_HISILICON_ERRATUM_161010101=y +CONFIG_ARM64_ERRATUM_858921=y +CONFIG_SUN50I_ERRATUM_UNKNOWN1=y +CONFIG_ARM_TIMER_SP804=y +CONFIG_SYS_SUPPORTS_SH_CMT=y +CONFIG_MTK_TIMER=y +CONFIG_MTK_CPUX_TIMER=y +CONFIG_SPRD_TIMER=y +CONFIG_SYS_SUPPORTS_SH_TMU=y +CONFIG_SH_TIMER_CMT=y +CONFIG_RENESAS_OSTM=y +CONFIG_SH_TIMER_TMU=y +CONFIG_TIMER_IMX_SYS_CTR=y +# CONFIG_NXP_STM_TIMER is not set +# end of Clock Source drivers + +CONFIG_MAILBOX=y +# CONFIG_ARM_MHU is not set +# CONFIG_ARM_MHU_V2 is not set +# CONFIG_ARM_MHU_V3 is not set +# CONFIG_IMX_MBOX is not set +# CONFIG_PLATFORM_MHU is not set +CONFIG_PL320_MBOX=y +# CONFIG_ARMADA_37XX_RWTM_MBOX is not set +# CONFIG_OMAP2PLUS_MBOX is not set +CONFIG_ROCKCHIP_MBOX=y +CONFIG_PCC=y +# CONFIG_ALTERA_MBOX is not set +CONFIG_TI_MESSAGE_MANAGER=y +# CONFIG_HI3660_MBOX is not set +# CONFIG_HI6220_MBOX is not set +# CONFIG_MAILBOX_TEST is not set +# CONFIG_QCOM_APCS_IPC is not set +CONFIG_TEGRA_HSP_MBOX=y +# CONFIG_XGENE_SLIMPRO_MBOX is not set +# CONFIG_MTK_ADSP_MBOX is not set +# CONFIG_MTK_CMDQ_MBOX is not set +# CONFIG_MTK_GPUEB_MBOX is not set +CONFIG_ZYNQMP_IPI_MBOX=y +CONFIG_SUN6I_MSGBOX=y +# CONFIG_SPRD_MBOX is not set +# CONFIG_QCOM_CPUCP_MBOX is not set +CONFIG_QCOM_IPCC=y +CONFIG_IOMMU_IOVA=y +CONFIG_IOMMU_API=y +CONFIG_IOMMU_SUPPORT=y + +# +# Generic IOMMU Pagetable Support +# +CONFIG_IOMMU_IO_PGTABLE=y +CONFIG_IOMMU_IO_PGTABLE_LPAE=y +# CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST is not set +CONFIG_IOMMU_IO_PGTABLE_ARMV7S=y +# CONFIG_IOMMU_IO_PGTABLE_ARMV7S_SELFTEST is not set +CONFIG_IOMMU_IO_PGTABLE_DART=y +# end of Generic IOMMU Pagetable Support + +# CONFIG_IOMMU_DEBUGFS is not set +CONFIG_IOMMU_DEFAULT_DMA_STRICT=y +# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set +# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set +CONFIG_OF_IOMMU=y +CONFIG_IOMMU_DMA=y +CONFIG_IOMMU_SVA=y +CONFIG_IOMMU_IOPF=y +CONFIG_ARM_SMMU=y +# CONFIG_ARM_SMMU_LEGACY_DT_BINDINGS is not set +# CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT is not set +CONFIG_ARM_SMMU_MMU_500_CPRE_ERRATA=y +CONFIG_ARM_SMMU_QCOM=y +CONFIG_ARM_SMMU_QCOM_DEBUG=y +CONFIG_ARM_SMMU_V3=y +CONFIG_ARM_SMMU_V3_SVA=y +CONFIG_TEGRA241_CMDQV=y +CONFIG_QCOM_IOMMU=y +# CONFIG_IOMMUFD is not set +CONFIG_ROCKCHIP_IOMMU=y +CONFIG_SUN50I_IOMMU=y +CONFIG_TEGRA_IOMMU_SMMU=y +# CONFIG_IPMMU_VMSA is not set +# CONFIG_APPLE_DART is not set +# CONFIG_MTK_IOMMU is not set +CONFIG_VIRTIO_IOMMU=y +# CONFIG_SPRD_IOMMU is not set + +# +# Remoteproc drivers +# +CONFIG_REMOTEPROC=y +CONFIG_REMOTEPROC_CDEV=y +# CONFIG_IMX_REMOTEPROC is not set +# CONFIG_IMX_DSP_REMOTEPROC is not set +# CONFIG_MTK_SCP is not set +# CONFIG_RCAR_REMOTEPROC is not set +# CONFIG_STM32_RPROC is not set +# CONFIG_XLNX_R5_REMOTEPROC is not set +# end of Remoteproc drivers + +# +# Rpmsg drivers +# +# CONFIG_RPMSG_QCOM_GLINK_RPM is not set +# CONFIG_RPMSG_VIRTIO is not set +# end of Rpmsg drivers + +# +# SOC (System On Chip) specific Drivers +# + +# +# Amlogic SoC drivers +# +# CONFIG_MESON_CANVAS is not set +CONFIG_MESON_CLK_MEASURE=y +CONFIG_MESON_GX_SOCINFO=y +# end of Amlogic SoC drivers + +# +# Apple SoC drivers +# +# CONFIG_APPLE_MAILBOX is not set +# CONFIG_APPLE_SART is not set +# end of Apple SoC drivers + +# +# Broadcom SoC drivers +# +# end of Broadcom SoC drivers + +# +# NXP/Freescale QorIQ SoC drivers +# +CONFIG_FSL_DPAA=y +CONFIG_FSL_DPAA_CHECKING=y +# CONFIG_FSL_BMAN_TEST is not set +# CONFIG_FSL_QMAN_TEST is not set +CONFIG_QUICC_ENGINE=y +# CONFIG_CPM_TSA is not set +# CONFIG_FSL_MC_DPIO is not set +# CONFIG_DPAA2_CONSOLE is not set +CONFIG_FSL_RCPM=y +# end of NXP/Freescale QorIQ SoC drivers + +# +# fujitsu SoC drivers +# +CONFIG_A64FX_DIAG=y +# end of fujitsu SoC drivers + +# +# Hisilicon SoC drivers +# +# CONFIG_KUNPENG_HCCS is not set +# end of Hisilicon SoC drivers + +# +# i.MX SoC drivers +# +CONFIG_SOC_IMX8M=y +# CONFIG_SOC_IMX9 is not set +# end of i.MX SoC drivers + +# +# Enable LiteX SoC Builder specific drivers +# +# CONFIG_LITEX_SOC_CONTROLLER is not set +# end of Enable LiteX SoC Builder specific drivers + +# +# MediaTek SoC drivers +# +# CONFIG_MTK_CMDQ is not set +# CONFIG_MTK_DEVAPC is not set +# CONFIG_MTK_DVFSRC is not set +CONFIG_MTK_INFRACFG=y +# CONFIG_MTK_PMIC_WRAP is not set +CONFIG_MTK_REGULATOR_COUPLER=y +# CONFIG_MTK_MMSYS is not set +# end of MediaTek SoC drivers + +# CONFIG_WPCM450_SOC is not set + +# +# Qualcomm SoC drivers +# +# CONFIG_QCOM_AOSS_QMP is not set +CONFIG_QCOM_COMMAND_DB=y +CONFIG_QCOM_GENI_SE=y +# CONFIG_QCOM_GSBI is not set +# CONFIG_QCOM_LLCC is not set +CONFIG_QCOM_KRYO_L2_ACCESSORS=y +# CONFIG_QCOM_OCMEM is not set +# CONFIG_QCOM_PD_MAPPER is not set +# CONFIG_QCOM_RAMP_CTRL is not set +# CONFIG_QCOM_RMTFS_MEM is not set +# CONFIG_QCOM_RPM_MASTER_STATS is not set +CONFIG_QCOM_RPMH=y +# CONFIG_QCOM_SMEM is not set +CONFIG_QCOM_SPM=y +# CONFIG_QCOM_ICC_BWMON is not set +# end of Qualcomm SoC drivers + +CONFIG_SOC_RENESAS=y +CONFIG_ARCH_RCAR_GEN3=y +CONFIG_ARCH_RCAR_GEN4=y +CONFIG_ARCH_RCAR_GEN5=y +CONFIG_ARCH_RZG2L=y +CONFIG_ARCH_R8A774A1=y +CONFIG_ARCH_R8A774B1=y +CONFIG_ARCH_R8A774C0=y +CONFIG_ARCH_R8A774E1=y +CONFIG_ARCH_R8A77951=y +CONFIG_ARCH_R8A77960=y +CONFIG_ARCH_R8A77961=y +CONFIG_ARCH_R8A77965=y +CONFIG_ARCH_R8A77970=y +CONFIG_ARCH_R8A77980=y +CONFIG_ARCH_R8A77990=y +CONFIG_ARCH_R8A77995=y +CONFIG_ARCH_R8A779A0=y +CONFIG_ARCH_R8A779F0=y +CONFIG_ARCH_R8A779G0=y +CONFIG_ARCH_R8A779H0=y +CONFIG_ARCH_R8A78000=y +CONFIG_ARCH_R9A07G043=y +CONFIG_ARCH_R9A07G044=y +CONFIG_ARCH_R9A07G054=y +CONFIG_ARCH_R9A08G045=y +CONFIG_ARCH_R9A09G011=y +CONFIG_ARCH_R9A09G047=y +CONFIG_ARCH_R9A09G056=y +CONFIG_ARCH_R9A09G057=y +CONFIG_ARCH_R9A09G077=y +CONFIG_ARCH_R9A09G087=y +CONFIG_PWC_RZV2M=y +CONFIG_RST_RCAR=y +CONFIG_SYSC_RZ=y +CONFIG_SYSC_R9A08G045=y +CONFIG_SYS_R9A09G047=y +CONFIG_SYS_R9A09G056=y +CONFIG_SYS_R9A09G057=y +CONFIG_ROCKCHIP_GRF=y +# CONFIG_ROCKCHIP_IODOMAIN is not set +# CONFIG_ROCKCHIP_DTPM is not set +CONFIG_SUNXI_MBUS=y +CONFIG_SUNXI_SRAM=y +CONFIG_ARCH_TEGRA_132_SOC=y +CONFIG_ARCH_TEGRA_210_SOC=y +CONFIG_ARCH_TEGRA_186_SOC=y +CONFIG_ARCH_TEGRA_194_SOC=y +CONFIG_ARCH_TEGRA_234_SOC=y +CONFIG_ARCH_TEGRA_241_SOC=y +# CONFIG_ARCH_TEGRA_264_SOC is not set +CONFIG_SOC_TEGRA_FUSE=y +CONFIG_SOC_TEGRA_FLOWCTRL=y +CONFIG_SOC_TEGRA_PMC=y +# CONFIG_SOC_TEGRA_CBB is not set +CONFIG_SOC_TI=y +CONFIG_TI_K3_RINGACC=y +CONFIG_TI_K3_SOCINFO=y +# CONFIG_TI_PRUSS is not set +CONFIG_TI_SCI_INTA_MSI_DOMAIN=y + +# +# Xilinx SoC drivers +# +CONFIG_ZYNQMP_POWER=y +CONFIG_XLNX_EVENT_MANAGER=y +# end of Xilinx SoC drivers +# end of SOC (System On Chip) specific Drivers + +# +# PM Domains +# +CONFIG_OWL_PM_DOMAINS_HELPER=y +CONFIG_OWL_PM_DOMAINS=y + +# +# Amlogic PM Domains +# +CONFIG_MESON_EE_PM_DOMAINS=y +CONFIG_MESON_SECURE_PM_DOMAINS=y +# end of Amlogic PM Domains + +CONFIG_APPLE_PMGR_PWRSTATE=y +# CONFIG_ARM_SCMI_PERF_DOMAIN is not set +# CONFIG_ARM_SCMI_POWER_DOMAIN is not set + +# +# Broadcom PM Domains +# +# end of Broadcom PM Domains + +# +# i.MX PM Domains +# +CONFIG_IMX_GPCV2_PM_DOMAINS=y +CONFIG_IMX8M_BLK_CTRL=y +# end of i.MX PM Domains + +# +# MediaTek PM Domains +# +CONFIG_MTK_SCPSYS=y +CONFIG_MTK_SCPSYS_PM_DOMAINS=y +# CONFIG_AIROHA_CPU_PM_DOMAIN is not set +# end of MediaTek PM Domains + +# +# Qualcomm PM Domains +# +# CONFIG_QCOM_CPR is not set +CONFIG_QCOM_RPMHPD=y +# end of Qualcomm PM Domains + +# +# Renesas PM Domains +# +CONFIG_SYSC_RCAR=y +CONFIG_SYSC_RCAR_GEN4=y +CONFIG_SYSC_R8A774A1=y +CONFIG_SYSC_R8A774B1=y +CONFIG_SYSC_R8A774C0=y +CONFIG_SYSC_R8A774E1=y +CONFIG_SYSC_R8A7795=y +CONFIG_SYSC_R8A77960=y +CONFIG_SYSC_R8A77961=y +CONFIG_SYSC_R8A77965=y +CONFIG_SYSC_R8A77970=y +CONFIG_SYSC_R8A77980=y +CONFIG_SYSC_R8A77990=y +CONFIG_SYSC_R8A77995=y +CONFIG_SYSC_R8A779A0=y +CONFIG_SYSC_R8A779F0=y +CONFIG_SYSC_R8A779G0=y +CONFIG_SYSC_R8A779H0=y +# end of Renesas PM Domains + +CONFIG_ROCKCHIP_PM_DOMAINS=y +CONFIG_SUN20I_PPU=y +# CONFIG_SUN50I_H6_PRCM_PPU is not set +CONFIG_SUN55I_PCK600=y +CONFIG_SOC_TEGRA_POWERGATE_BPMP=y +# CONFIG_TI_SCI_PM_DOMAINS is not set +CONFIG_ZYNQMP_PM_DOMAINS=y +# end of PM Domains + +CONFIG_PM_DEVFREQ=y + +# +# DEVFREQ Governors +# +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y +CONFIG_DEVFREQ_GOV_PERFORMANCE=y +CONFIG_DEVFREQ_GOV_POWERSAVE=y +CONFIG_DEVFREQ_GOV_USERSPACE=y +CONFIG_DEVFREQ_GOV_PASSIVE=y + +# +# DEVFREQ Drivers +# +# CONFIG_ARM_HISI_UNCORE_DEVFREQ is not set +# CONFIG_ARM_IMX_BUS_DEVFREQ is not set +# CONFIG_ARM_IMX8M_DDRC_DEVFREQ is not set +# CONFIG_ARM_TEGRA_DEVFREQ is not set +# CONFIG_ARM_RK3399_DMC_DEVFREQ is not set +# CONFIG_ARM_SUN8I_A33_MBUS_DEVFREQ is not set +CONFIG_PM_DEVFREQ_EVENT=y +# CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI is not set +CONFIG_EXTCON=y + +# +# Extcon Device Drivers +# +# CONFIG_EXTCON_FSA9480 is not set +# CONFIG_EXTCON_GPIO is not set +# CONFIG_EXTCON_LC824206XA is not set +# CONFIG_EXTCON_MAX14577 is not set +# CONFIG_EXTCON_MAX3355 is not set +# CONFIG_EXTCON_MAX77693 is not set +# CONFIG_EXTCON_MAX77843 is not set +# CONFIG_EXTCON_MAX8997 is not set +# CONFIG_EXTCON_MAX14526 is not set +# CONFIG_EXTCON_PALMAS is not set +# CONFIG_EXTCON_PTN5150 is not set +# CONFIG_EXTCON_QCOM_SPMI_MISC is not set +# CONFIG_EXTCON_RT8973A is not set +# CONFIG_EXTCON_SM5502 is not set +# CONFIG_EXTCON_USB_GPIO is not set +CONFIG_MEMORY=y +# CONFIG_ARM_PL172_MPMC is not set +CONFIG_OMAP_GPMC=y +# CONFIG_OMAP_GPMC_DEBUG is not set +CONFIG_FSL_IFC=y +# CONFIG_RENESAS_RPCIF is not set +# CONFIG_STM32_FMC2_EBI is not set +CONFIG_TEGRA_MC=y +# CONFIG_TEGRA210_EMC is not set +# CONFIG_IIO is not set +# CONFIG_NTB is not set +CONFIG_PWM=y +# CONFIG_PWM_DEBUG is not set +# CONFIG_PWM_PROVIDE_GPIO is not set +# CONFIG_PWM_APPLE is not set +# CONFIG_PWM_ARGON_FAN_HAT is not set +# CONFIG_PWM_ATMEL_TCB is not set +# CONFIG_PWM_AXI_PWMGEN is not set +# CONFIG_PWM_BERLIN is not set +# CONFIG_PWM_CLK is not set +# CONFIG_PWM_DWC is not set +# CONFIG_PWM_FSL_FTM is not set +# CONFIG_PWM_GPIO is not set +# CONFIG_PWM_HIBVT is not set +# CONFIG_PWM_IMX1 is not set +# CONFIG_PWM_IMX27 is not set +# CONFIG_PWM_IMX_TPM is not set +# CONFIG_PWM_KEEMBAY is not set +# CONFIG_PWM_MC33XS2410 is not set +# CONFIG_PWM_MEDIATEK is not set +# CONFIG_PWM_MESON is not set +# CONFIG_PWM_MTK_DISP is not set +# CONFIG_PWM_OMAP_DMTIMER is not set +# CONFIG_PWM_PCA9685 is not set +# CONFIG_PWM_RENESAS_RCAR is not set +# CONFIG_PWM_RENESAS_RZG2L_GPT is not set +# CONFIG_PWM_RENESAS_RZ_MTU3 is not set +# CONFIG_PWM_RENESAS_TPU is not set +# CONFIG_PWM_ROCKCHIP is not set +# CONFIG_PWM_SPRD is not set +CONFIG_PWM_STMPE=y +# CONFIG_PWM_SUN4I is not set +# CONFIG_PWM_TEGRA is not set +# CONFIG_PWM_TIECAP is not set +# CONFIG_PWM_TIEHRPWM is not set +# CONFIG_PWM_TWL is not set +# CONFIG_PWM_TWL_LED is not set +# CONFIG_PWM_VISCONTI is not set +# CONFIG_PWM_XILINX is not set + +# +# IRQ chip support +# +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_PM=y +CONFIG_ARM_GIC_MAX_NR=1 +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_ITS_PARENT=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ITS_FSL_MC=y +CONFIG_ARM_GIC_V5=y +CONFIG_IRQ_MSI_LIB=y +CONFIG_AL_FIC=y +CONFIG_DW_APB_ICTL=y +CONFIG_HISILICON_IRQ_MBIGEN=y +CONFIG_RENESAS_IRQC=y +CONFIG_RENESAS_RZG2L_IRQC=y +CONFIG_RENESAS_RZV2H_ICU=y +CONFIG_SUN6I_R_INTC=y +CONFIG_SUNXI_NMI_INTC=y +CONFIG_XILINX_INTC=y +CONFIG_IMX_GPCV2=y +CONFIG_MVEBU_GICP=y +CONFIG_MVEBU_ICU=y +CONFIG_MVEBU_ODMI=y +CONFIG_MVEBU_PIC=y +CONFIG_MVEBU_SEI=y +CONFIG_LS_EXTIRQ=y +CONFIG_LS_SCFG_MSI=y +CONFIG_PARTITION_PERCPU=y +# CONFIG_STM32MP_EXTI is not set +CONFIG_QCOM_IRQ_COMBINER=y +CONFIG_MESON_IRQ_GPIO=y +CONFIG_QCOM_PDC=y +# CONFIG_QCOM_MPM is not set +CONFIG_IMX_IRQSTEER=y +CONFIG_IMX_INTMUX=y +# CONFIG_IMX_MU_MSI is not set +CONFIG_TI_SCI_INTR_IRQCHIP=y +CONFIG_TI_SCI_INTA_IRQCHIP=y +CONFIG_MST_IRQ=y +CONFIG_APPLE_AIC=y +# end of IRQ chip support + +# CONFIG_IPACK_BUS is not set +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +CONFIG_RESET_CONTROLLER=y +# CONFIG_RESET_A10SR is not set +CONFIG_RESET_BERLIN=y +# CONFIG_RESET_GPIO is not set +CONFIG_RESET_IMX7=y +# CONFIG_RESET_IMX8MP_AUDIOMIX is not set +CONFIG_RESET_MCHP_SPARX5=y +CONFIG_RESET_NPCM=y +CONFIG_RESET_NUVOTON_MA35D1=y +CONFIG_RESET_QCOM_AOSS=y +# CONFIG_RESET_QCOM_PDC is not set +CONFIG_RESET_RZG2L_USBPHY_CTRL=y +# CONFIG_RESET_RZV2H_USB2PHY is not set +# CONFIG_RESET_SCMI is not set +CONFIG_RESET_SIMPLE=y +CONFIG_RESET_SUNXI=y +# CONFIG_RESET_TI_SCI is not set +# CONFIG_RESET_TI_SYSCON is not set +# CONFIG_RESET_TI_TPS380X is not set +CONFIG_RESET_ZYNQMP=y +CONFIG_RESET_MESON_COMMON=y +CONFIG_RESET_MESON=y +# CONFIG_RESET_MESON_AUX is not set +# CONFIG_RESET_MESON_AUDIO_ARB is not set +# CONFIG_COMMON_RESET_HI3660 is not set +# CONFIG_COMMON_RESET_HI6220 is not set +CONFIG_RESET_TEGRA_BPMP=y + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PHY_MIPI_DPHY=y +# CONFIG_PHY_SNPS_EUSB2 is not set +CONFIG_PHY_XGENE=y +# CONFIG_PHY_CAN_TRANSCEIVER is not set +# CONFIG_PHY_AIROHA_PCIE is not set +# CONFIG_PHY_NXP_PTN3222 is not set +# CONFIG_PHY_SUN4I_USB is not set +# CONFIG_PHY_SUN6I_MIPI_DPHY is not set +# CONFIG_PHY_SUN9I_USB is not set +# CONFIG_PHY_SUN50I_USB3 is not set +# CONFIG_PHY_MESON8B_USB2 is not set +# CONFIG_PHY_MESON_GXL_USB2 is not set +# CONFIG_PHY_MESON_G12A_MIPI_DPHY_ANALOG is not set +# CONFIG_PHY_MESON_G12A_USB2 is not set +# CONFIG_PHY_MESON_G12A_USB3_PCIE is not set +CONFIG_PHY_MESON_AXG_PCIE=y +CONFIG_PHY_MESON_AXG_MIPI_PCIE_ANALOG=y +# CONFIG_PHY_MESON_AXG_MIPI_DPHY is not set + +# +# PHY drivers for Broadcom platforms +# +# CONFIG_BCM_KONA_USB2_PHY is not set +# end of PHY drivers for Broadcom platforms + +# CONFIG_PHY_CADENCE_TORRENT is not set +# CONFIG_PHY_CADENCE_DPHY is not set +# CONFIG_PHY_CADENCE_DPHY_RX is not set +# CONFIG_PHY_CADENCE_SIERRA is not set +# CONFIG_PHY_CADENCE_SALVO is not set +# CONFIG_PHY_FSL_IMX8MQ_USB is not set +# CONFIG_PHY_MIXEL_LVDS_PHY is not set +# CONFIG_PHY_MIXEL_MIPI_DPHY is not set +# CONFIG_PHY_FSL_IMX8M_PCIE is not set +# CONFIG_PHY_FSL_IMX8QM_HSIO is not set +# CONFIG_PHY_FSL_SAMSUNG_HDMI_PHY is not set +# CONFIG_PHY_FSL_LYNX_28G is not set +# CONFIG_PHY_HI6220_USB is not set +# CONFIG_PHY_HI3660_USB is not set +# CONFIG_PHY_HI3670_USB is not set +# CONFIG_PHY_HI3670_PCIE is not set +# CONFIG_PHY_HISTB_COMBPHY is not set +# CONFIG_PHY_HISI_INNO_USB2 is not set +# CONFIG_PHY_BERLIN_SATA is not set +# CONFIG_PHY_BERLIN_USB is not set +# CONFIG_PHY_MVEBU_A3700_COMPHY is not set +# CONFIG_PHY_MVEBU_A3700_UTMI is not set +# CONFIG_PHY_MVEBU_A38X_COMPHY is not set +# CONFIG_PHY_MVEBU_CP110_COMPHY is not set +# CONFIG_PHY_MVEBU_CP110_UTMI is not set +# CONFIG_PHY_PXA_28NM_HSIC is not set +# CONFIG_PHY_PXA_28NM_USB2 is not set +# CONFIG_PHY_MTK_PCIE is not set +# CONFIG_PHY_MTK_XFI_TPHY is not set +# CONFIG_PHY_MTK_TPHY is not set +# CONFIG_PHY_MTK_UFS is not set +# CONFIG_PHY_MTK_XSPHY is not set +# CONFIG_PHY_MTK_HDMI is not set +# CONFIG_PHY_MTK_MIPI_CSI_0_5 is not set +# CONFIG_PHY_MTK_MIPI_DSI is not set +# CONFIG_PHY_MTK_DP is not set +# CONFIG_PHY_SPARX5_SERDES is not set +# CONFIG_PHY_MAPPHONE_MDM6600 is not set +# CONFIG_PHY_OCELOT_SERDES is not set +# CONFIG_PHY_MA35_USB is not set +# CONFIG_PHY_QCOM_APQ8064_SATA is not set +# CONFIG_PHY_QCOM_EDP is not set +# CONFIG_PHY_QCOM_IPQ4019_USB is not set +# CONFIG_PHY_QCOM_IPQ806X_SATA is not set +# CONFIG_PHY_QCOM_PCIE2 is not set +# CONFIG_PHY_QCOM_QMP is not set +# CONFIG_PHY_QCOM_QUSB2 is not set +# CONFIG_PHY_QCOM_EUSB2_REPEATER is not set +# CONFIG_PHY_QCOM_M31_USB is not set +# CONFIG_PHY_QCOM_UNIPHY_PCIE_28LP is not set +# CONFIG_PHY_QCOM_M31_EUSB is not set +# CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2 is not set +# CONFIG_PHY_QCOM_USB_HS_28NM is not set +# CONFIG_PHY_QCOM_USB_SS is not set +# CONFIG_PHY_QCOM_IPQ806X_USB is not set +# CONFIG_PHY_QCOM_SGMII_ETH is not set +# CONFIG_PHY_RTK_RTD_USB2PHY is not set +# CONFIG_PHY_RTK_RTD_USB3PHY is not set +# CONFIG_PHY_R8A779F0_ETHERNET_SERDES is not set +# CONFIG_PHY_RCAR_GEN2 is not set +# CONFIG_PHY_RCAR_GEN3_PCIE is not set +# CONFIG_PHY_RCAR_GEN3_USB2 is not set +# CONFIG_PHY_RCAR_GEN3_USB3 is not set +# CONFIG_PHY_ROCKCHIP_DP is not set +# CONFIG_PHY_ROCKCHIP_DPHY_RX0 is not set +# CONFIG_PHY_ROCKCHIP_EMMC is not set +# CONFIG_PHY_ROCKCHIP_INNO_HDMI is not set +# CONFIG_PHY_ROCKCHIP_INNO_USB2 is not set +# CONFIG_PHY_ROCKCHIP_INNO_CSIDPHY is not set +# CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY is not set +# CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY is not set +# CONFIG_PHY_ROCKCHIP_PCIE is not set +# CONFIG_PHY_ROCKCHIP_SAMSUNG_DCPHY is not set +# CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX is not set +# CONFIG_PHY_ROCKCHIP_SNPS_PCIE3 is not set +# CONFIG_PHY_ROCKCHIP_TYPEC is not set +# CONFIG_PHY_ROCKCHIP_USB is not set +# CONFIG_PHY_SAMSUNG_USB2 is not set +# CONFIG_PHY_STM32_COMBOPHY is not set +# CONFIG_PHY_STM32_USBPHYC is not set +# CONFIG_PHY_TEGRA_XUSB is not set +# CONFIG_PHY_TEGRA194_P2U is not set +# CONFIG_PHY_AM654_SERDES is not set +# CONFIG_PHY_J721E_WIZ is not set +# CONFIG_OMAP_USB2 is not set +# CONFIG_PHY_INTEL_KEEMBAY_EMMC is not set +# CONFIG_PHY_INTEL_KEEMBAY_USB is not set +# CONFIG_PHY_XILINX_ZYNQMP is not set +# end of PHY Subsystem + +CONFIG_POWERCAP=y +CONFIG_IDLE_INJECT=y +# CONFIG_ARM_SCMI_POWERCAP is not set +CONFIG_DTPM=y +CONFIG_DTPM_CPU=y +# CONFIG_DTPM_DEVFREQ is not set +# CONFIG_MCB is not set + +# +# Performance monitor support +# +CONFIG_ARM_CCI_PMU=y +CONFIG_ARM_CCI400_PMU=y +CONFIG_ARM_CCI5xx_PMU=y +CONFIG_ARM_CCN=y +# CONFIG_ARM_CMN is not set +# CONFIG_ARM_NI is not set +CONFIG_ARM_PMU=y +CONFIG_ARM_PMU_ACPI=y +# CONFIG_ARM_SMMU_V3_PMU is not set +CONFIG_ARM_PMUV3=y +# CONFIG_ARM_DSU_PMU is not set +# CONFIG_FSL_IMX8_DDR_PMU is not set +# CONFIG_FSL_IMX9_DDR_PMU is not set +# CONFIG_FUJITSU_UNCORE_PMU is not set +CONFIG_QCOM_L2_PMU=y +CONFIG_QCOM_L3_PMU=y +# CONFIG_THUNDERX2_PMU is not set +CONFIG_XGENE_PMU=y +# CONFIG_ARM_SPE_PMU is not set +CONFIG_ARM64_BRBE=y +# CONFIG_ARM_DMC620_PMU is not set +# CONFIG_MARVELL_CN10K_TAD_PMU is not set +CONFIG_APPLE_M1_CPU_PMU=y +# CONFIG_ALIBABA_UNCORE_DRW_PMU is not set +# CONFIG_HISI_PMU is not set +# CONFIG_HISI_PCIE_PMU is not set +# CONFIG_HNS3_PMU is not set +# CONFIG_MARVELL_CN10K_DDR_PMU is not set +# CONFIG_DWC_PCIE_PMU is not set +# CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU is not set +# CONFIG_MESON_DDR_PMU is not set +# CONFIG_MARVELL_PEM_PMU is not set +# end of Performance monitor support + +CONFIG_RAS=y +# CONFIG_USB4 is not set + +# +# Android +# +# CONFIG_ANDROID_BINDER_IPC is not set +# CONFIG_ANDROID_BINDER_IPC_RUST is not set +# end of Android + +CONFIG_LIBNVDIMM=y +# CONFIG_BLK_DEV_PMEM is not set +CONFIG_ND_CLAIM=y +CONFIG_BTT=y +CONFIG_NVDIMM_PFN=y +CONFIG_NVDIMM_DAX=y +# CONFIG_OF_PMEM is not set +CONFIG_NVDIMM_KEYS=y +# CONFIG_NVDIMM_SECURITY_TEST is not set +CONFIG_DAX=y +# CONFIG_DEV_DAX is not set +# CONFIG_DEV_DAX_HMEM is not set +CONFIG_NVMEM=y +CONFIG_NVMEM_SYSFS=y +CONFIG_NVMEM_LAYOUTS=y + +# +# Layout Types +# +# CONFIG_NVMEM_LAYOUT_SL28_VPD is not set +# CONFIG_NVMEM_LAYOUT_ONIE_TLV is not set +# CONFIG_NVMEM_LAYOUT_U_BOOT_ENV is not set +# end of Layout Types + +# CONFIG_NVMEM_APPLE_EFUSES is not set +# CONFIG_NVMEM_IMX_IIM is not set +# CONFIG_NVMEM_IMX_OCOTP is not set +# CONFIG_NVMEM_IMX_OCOTP_ELE is not set +# CONFIG_NVMEM_LAYERSCAPE_SFP is not set +# CONFIG_NVMEM_MESON_EFUSE is not set +# CONFIG_NVMEM_MESON_MX_EFUSE is not set +# CONFIG_NVMEM_MTK_EFUSE is not set +# CONFIG_NVMEM_S32G_OCOTP is not set +# CONFIG_NVMEM_QCOM_QFPROM is not set +# CONFIG_NVMEM_QCOM_SEC_QFPROM is not set +# CONFIG_NVMEM_RCAR_EFUSE is not set +# CONFIG_NVMEM_RMEM is not set +# CONFIG_NVMEM_ROCKCHIP_EFUSE is not set +# CONFIG_NVMEM_ROCKCHIP_OTP is not set +# CONFIG_NVMEM_SNVS_LPGPR is not set +# CONFIG_NVMEM_SPRD_EFUSE is not set +# CONFIG_NVMEM_STM32_ROMEM is not set +# CONFIG_NVMEM_SUNXI_SID is not set +CONFIG_NVMEM_ZYNQMP=y + +# +# HW tracing support +# +# CONFIG_STM is not set +# CONFIG_INTEL_TH is not set +# CONFIG_HISI_PTT is not set +# end of HW tracing support + +# CONFIG_FPGA is not set +# CONFIG_FSI is not set +# CONFIG_TEE is not set +CONFIG_MULTIPLEXER=y + +# +# Multiplexer drivers +# +# CONFIG_MUX_ADG792A is not set +# CONFIG_MUX_ADGS1408 is not set +# CONFIG_MUX_GPIO is not set +# CONFIG_MUX_MMIO is not set +# end of Multiplexer drivers + +CONFIG_PM_OPP=y +# CONFIG_SIOX is not set +# CONFIG_SLIMBUS is not set +CONFIG_INTERCONNECT=y +# CONFIG_INTERCONNECT_IMX is not set +CONFIG_INTERCONNECT_MTK=y +CONFIG_INTERCONNECT_QCOM=y +# CONFIG_INTERCONNECT_QCOM_GLYMUR is not set +# CONFIG_INTERCONNECT_QCOM_OSM_L3 is not set +# CONFIG_INTERCONNECT_QCOM_QCS615 is not set +# CONFIG_INTERCONNECT_QCOM_QCS8300 is not set +# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set +CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y +# CONFIG_INTERCONNECT_QCOM_SA8775P is not set +# CONFIG_INTERCONNECT_QCOM_SAR2130P is not set +# CONFIG_INTERCONNECT_QCOM_SC7180 is not set +# CONFIG_INTERCONNECT_QCOM_SC7280 is not set +# CONFIG_INTERCONNECT_QCOM_SC8180X is not set +# CONFIG_INTERCONNECT_QCOM_SC8280XP is not set +# CONFIG_INTERCONNECT_QCOM_SDM670 is not set +# CONFIG_INTERCONNECT_QCOM_SDM845 is not set +# CONFIG_INTERCONNECT_QCOM_SDX55 is not set +# CONFIG_INTERCONNECT_QCOM_SDX65 is not set +# CONFIG_INTERCONNECT_QCOM_SDX75 is not set +# CONFIG_INTERCONNECT_QCOM_SM6350 is not set +# CONFIG_INTERCONNECT_QCOM_SM7150 is not set +# CONFIG_INTERCONNECT_QCOM_MILOS is not set +# CONFIG_INTERCONNECT_QCOM_SM8150 is not set +# CONFIG_INTERCONNECT_QCOM_SM8250 is not set +# CONFIG_INTERCONNECT_QCOM_SM8350 is not set +# CONFIG_INTERCONNECT_QCOM_SM8450 is not set +# CONFIG_INTERCONNECT_QCOM_SM8550 is not set +# CONFIG_INTERCONNECT_QCOM_SM8650 is not set +# CONFIG_INTERCONNECT_QCOM_SM8750 is not set +# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set +CONFIG_INTERCONNECT_CLK=y +# CONFIG_COUNTER is not set +# CONFIG_MOST is not set +# CONFIG_PECI is not set +CONFIG_HTE=y +# CONFIG_HTE_TEGRA194 is not set +CONFIG_CDX_BUS=y +# CONFIG_CDX_CONTROLLER is not set +# end of Device Drivers + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_VALIDATE_FS_PARSER=y +CONFIG_FS_IOMAP=y +CONFIG_FS_STACK=y +CONFIG_BUFFER_HEAD=y +CONFIG_LEGACY_DIRECT_IO=y +# CONFIG_EXT2_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT2=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_F2FS_FS is not set +# CONFIG_ZONEFS_FS is not set +CONFIG_FS_DAX=y +CONFIG_FS_DAX_PMD=y +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y +CONFIG_EXPORTFS_BLOCK_OPS=y +CONFIG_FILE_LOCKING=y +CONFIG_FS_ENCRYPTION=y +CONFIG_FS_ENCRYPTION_ALGS=y +CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y +CONFIG_FS_VERITY=y +CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_FANOTIFY=y +CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_QUOTA_DEBUG is not set +# CONFIG_QFMT_V1 is not set +# CONFIG_QFMT_V2 is not set +CONFIG_QUOTACTL=y +CONFIG_AUTOFS_FS=m +CONFIG_FUSE_FS=y +# CONFIG_CUSE is not set +# CONFIG_VIRTIO_FS is not set +CONFIG_FUSE_PASSTHROUGH=y +CONFIG_FUSE_IO_URING=y +# CONFIG_OVERLAY_FS is not set + +# +# Caches +# +# end of Caches + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +# CONFIG_UDF_FS is not set +# end of CD-ROM/DVD Filesystems + +# +# DOS/FAT/EXFAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_FAT_DEFAULT_UTF8 is not set +# CONFIG_EXFAT_FS is not set +# CONFIG_NTFS3_FS is not set +# CONFIG_NTFS_FS is not set +# end of DOS/FAT/EXFAT/NT Filesystems + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_VMCORE=y +CONFIG_PROC_VMCORE_DEVICE_DUMP=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_PROC_CHILDREN=y +CONFIG_KERNFS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +CONFIG_TMPFS_INODE64=y +CONFIG_TMPFS_QUOTA=y +CONFIG_ARCH_SUPPORTS_HUGETLBFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING=y +CONFIG_ARCH_HAS_GIGANTIC_PAGE=y +CONFIG_CONFIGFS_FS=y +CONFIG_EFIVAR_FS=y +# end of Pseudo filesystems + +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ORANGEFS_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +CONFIG_ECRYPT_FS=y +CONFIG_ECRYPT_FS_MESSAGING=y +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +# CONFIG_SQUASHFS_FILE_CACHE is not set +CONFIG_SQUASHFS_FILE_DIRECT=y +CONFIG_SQUASHFS_DECOMP_SINGLE=y +CONFIG_SQUASHFS_DECOMP_MULTI=y +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT=y +CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS=y +CONFIG_SQUASHFS_XATTR=y +# CONFIG_SQUASHFS_COMP_CACHE_FULL is not set +CONFIG_SQUASHFS_ZLIB=y +CONFIG_SQUASHFS_LZ4=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_ZSTD=y +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_PSTORE=y +CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 +CONFIG_PSTORE_COMPRESS=y +# CONFIG_PSTORE_CONSOLE is not set +# CONFIG_PSTORE_PMSG is not set +# CONFIG_PSTORE_FTRACE is not set +# CONFIG_PSTORE_RAM is not set +# CONFIG_PSTORE_BLK is not set +# CONFIG_UFS_FS is not set +# CONFIG_EROFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_SMB_SERVER is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=m +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set +CONFIG_UNICODE=y +CONFIG_RUSTLFS=m +CONFIG_IO_WQ=y +# end of File systems + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_REQUEST_CACHE=y +CONFIG_PERSISTENT_KEYRINGS=y +# CONFIG_BIG_KEYS is not set +CONFIG_TRUSTED_KEYS=y +CONFIG_HAVE_TRUSTED_KEYS=y +CONFIG_TRUSTED_KEYS_TPM=y +CONFIG_ENCRYPTED_KEYS=y +CONFIG_USER_DECRYPTED_DATA=y +CONFIG_KEY_DH_OPERATIONS=y +CONFIG_KEY_NOTIFICATIONS=y +CONFIG_SECURITY_DMESG_RESTRICT=y +CONFIG_PROC_MEM_ALWAYS_FORCE=y +# CONFIG_PROC_MEM_FORCE_PTRACE is not set +# CONFIG_PROC_MEM_NO_FORCE is not set +CONFIG_SECURITY=y +CONFIG_HAS_SECURITY_AUDIT=y +CONFIG_SECURITYFS=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_PATH=y +CONFIG_LSM_MMAP_MIN_ADDR=0 +# CONFIG_STATIC_USERMODEHELPER is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_SIDTAB_HASH_BITS=9 +CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE=256 +# CONFIG_SECURITY_SELINUX_DEBUG is not set +CONFIG_SECURITY_SMACK=y +# CONFIG_SECURITY_SMACK_BRINGUP is not set +CONFIG_SECURITY_SMACK_NETFILTER=y +CONFIG_SECURITY_SMACK_APPEND_SIGNALS=y +CONFIG_SECURITY_TOMOYO=y +CONFIG_SECURITY_TOMOYO_MAX_ACCEPT_ENTRY=2048 +CONFIG_SECURITY_TOMOYO_MAX_AUDIT_LOG=1024 +# CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER is not set +CONFIG_SECURITY_TOMOYO_POLICY_LOADER="/sbin/tomoyo-init" +CONFIG_SECURITY_TOMOYO_ACTIVATION_TRIGGER="/sbin/init" +# CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING is not set +CONFIG_SECURITY_APPARMOR=y +# CONFIG_SECURITY_APPARMOR_DEBUG is not set +CONFIG_SECURITY_APPARMOR_INTROSPECT_POLICY=y +CONFIG_SECURITY_APPARMOR_HASH=y +CONFIG_SECURITY_APPARMOR_HASH_DEFAULT=y +CONFIG_SECURITY_APPARMOR_EXPORT_BINARY=y +CONFIG_SECURITY_APPARMOR_PARANOID_LOAD=y +# CONFIG_SECURITY_LOADPIN is not set +CONFIG_SECURITY_YAMA=y +CONFIG_SECURITY_SAFESETID=y +CONFIG_SECURITY_LOCKDOWN_LSM=y +CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y +CONFIG_LOCK_DOWN_KERNEL_FORCE_NONE=y +# CONFIG_LOCK_DOWN_KERNEL_FORCE_INTEGRITY is not set +# CONFIG_LOCK_DOWN_KERNEL_FORCE_CONFIDENTIALITY is not set +CONFIG_SECURITY_LANDLOCK=y +CONFIG_SECURITY_IPE=y +CONFIG_IPE_BOOT_POLICY="" +CONFIG_IPE_POLICY_SIG_SECONDARY_KEYRING=y +CONFIG_IPE_POLICY_SIG_PLATFORM_KEYRING=y + +# +# IPE Trust Providers +# +CONFIG_IPE_PROP_FS_VERITY=y +CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG=y +# end of IPE Trust Providers + +CONFIG_INTEGRITY=y +CONFIG_INTEGRITY_SIGNATURE=y +CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y +CONFIG_INTEGRITY_TRUSTED_KEYRING=y +CONFIG_INTEGRITY_PLATFORM_KEYRING=y +CONFIG_INTEGRITY_MACHINE_KEYRING=y +# CONFIG_INTEGRITY_CA_MACHINE_KEYRING is not set +CONFIG_LOAD_UEFI_KEYS=y +CONFIG_INTEGRITY_AUDIT=y +CONFIG_IMA=y +CONFIG_IMA_KEXEC=y +CONFIG_IMA_MEASURE_PCR_IDX=10 +CONFIG_IMA_LSM_RULES=y +CONFIG_IMA_NG_TEMPLATE=y +# CONFIG_IMA_SIG_TEMPLATE is not set +CONFIG_IMA_DEFAULT_TEMPLATE="ima-ng" +# CONFIG_IMA_DEFAULT_HASH_SHA1 is not set +CONFIG_IMA_DEFAULT_HASH_SHA256=y +# CONFIG_IMA_DEFAULT_HASH_SHA512 is not set +CONFIG_IMA_DEFAULT_HASH="sha256" +# CONFIG_IMA_WRITE_POLICY is not set +# CONFIG_IMA_READ_POLICY is not set +CONFIG_IMA_APPRAISE=y +CONFIG_IMA_ARCH_POLICY=y +# CONFIG_IMA_APPRAISE_BUILD_POLICY is not set +CONFIG_IMA_APPRAISE_BOOTPARAM=y +CONFIG_IMA_APPRAISE_MODSIG=y +# CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY is not set +# CONFIG_IMA_BLACKLIST_KEYRING is not set +# CONFIG_IMA_LOAD_X509 is not set +CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS=y +CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS=y +CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT=y +# CONFIG_IMA_DISABLE_HTABLE is not set +CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB=0 +CONFIG_EVM=y +CONFIG_EVM_ATTR_FSUUID=y +CONFIG_EVM_EXTRA_SMACK_XATTRS=y +CONFIG_EVM_ADD_XATTRS=y +# CONFIG_EVM_LOAD_X509 is not set +# CONFIG_DEFAULT_SECURITY_SELINUX is not set +# CONFIG_DEFAULT_SECURITY_SMACK is not set +# CONFIG_DEFAULT_SECURITY_TOMOYO is not set +CONFIG_DEFAULT_SECURITY_APPARMOR=y +# CONFIG_DEFAULT_SECURITY_DAC is not set +CONFIG_LSM="landlock,lockdown,yama,integrity,apparmor" + +# +# Kernel hardening options +# + +# +# Memory initialization +# +CONFIG_CC_HAS_AUTO_VAR_INIT_PATTERN=y +CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO_BARE=y +CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO=y +# CONFIG_INIT_STACK_NONE is not set +# CONFIG_INIT_STACK_ALL_PATTERN is not set +CONFIG_INIT_STACK_ALL_ZERO=y +CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y +# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set +CONFIG_CC_HAS_ZERO_CALL_USED_REGS=y +CONFIG_ZERO_CALL_USED_REGS=y +# end of Memory initialization + +# +# Bounds checking +# +CONFIG_FORTIFY_SOURCE=y +CONFIG_HARDENED_USERCOPY=y +CONFIG_HARDENED_USERCOPY_DEFAULT_ON=y +# end of Bounds checking + +# +# Hardening of kernel data structures +# +# CONFIG_LIST_HARDENED is not set +CONFIG_RUST_BITMAP_HARDENED=y +# CONFIG_BUG_ON_DATA_CORRUPTION is not set +# end of Hardening of kernel data structures + +CONFIG_CC_HAS_RANDSTRUCT=y +CONFIG_RANDSTRUCT_NONE=y +# CONFIG_RANDSTRUCT_FULL is not set +# end of Kernel hardening options +# end of Security options + +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_SIG=y +CONFIG_CRYPTO_SIG2=y +CONFIG_CRYPTO_SKCIPHER=y +CONFIG_CRYPTO_SKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_AKCIPHER2=y +CONFIG_CRYPTO_AKCIPHER=y +CONFIG_CRYPTO_KPP2=y +CONFIG_CRYPTO_KPP=y +CONFIG_CRYPTO_ACOMP2=y +CONFIG_CRYPTO_HKDF=m +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_SELFTESTS is not set +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_PCRYPT is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_KRB5ENC is not set +# CONFIG_CRYPTO_BENCHMARK is not set +# end of Crypto core or helper + +# +# Public-key cryptography +# +CONFIG_CRYPTO_RSA=y +CONFIG_CRYPTO_DH=y +CONFIG_CRYPTO_DH_RFC7919_GROUPS=y +CONFIG_CRYPTO_ECC=y +CONFIG_CRYPTO_ECDH=y +# CONFIG_CRYPTO_ECDSA is not set +# CONFIG_CRYPTO_ECRDSA is not set +# end of Public-key cryptography + +# +# Block ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_AES_TI is not set +# CONFIG_CRYPTO_ARIA is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_SM4_GENERIC is not set +# CONFIG_CRYPTO_TWOFISH is not set +# end of Block ciphers + +# +# Length-preserving ciphers and modes +# +# CONFIG_CRYPTO_ADIANTUM is not set +# CONFIG_CRYPTO_CHACHA20 is not set +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_CTS=y +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_HCTR2 is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +CONFIG_CRYPTO_XTS=y +# end of Length-preserving ciphers and modes + +# +# AEAD (authenticated encryption with associated data) ciphers +# +# CONFIG_CRYPTO_AEGIS128 is not set +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +# CONFIG_CRYPTO_CCM is not set +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_GENIV=y +CONFIG_CRYPTO_SEQIV=y +# CONFIG_CRYPTO_ECHAINIV is not set +# CONFIG_CRYPTO_ESSIV is not set +# end of AEAD (authenticated encryption with associated data) ciphers + +# +# Hashes, digests, and MACs +# +# CONFIG_CRYPTO_BLAKE2B is not set +# CONFIG_CRYPTO_CMAC is not set +CONFIG_CRYPTO_GHASH=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +CONFIG_CRYPTO_POLYVAL=m +# CONFIG_CRYPTO_RMD160 is not set +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_SHA3=y +# CONFIG_CRYPTO_SM3_GENERIC is not set +# CONFIG_CRYPTO_STREEBOG is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_XXHASH is not set +# end of Hashes, digests, and MACs + +# +# CRCs (cyclic redundancy checks) +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32 is not set +# end of CRCs (cyclic redundancy checks) + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_842 is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set +# CONFIG_CRYPTO_ZSTD is not set +# end of Compression + +# +# Random number generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_HASH=y +CONFIG_CRYPTO_DRBG_CTR=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKS=64 +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE=32 +CONFIG_CRYPTO_JITTERENTROPY_OSR=1 +CONFIG_CRYPTO_KDF800108_CTR=y +# end of Random number generation + +# +# Userspace interface +# +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_USER_API_AEAD is not set +# end of Userspace interface + +# CONFIG_CRYPTO_NHPOLY1305_NEON is not set + +# +# Accelerated Cryptographic Algorithms for CPU (arm64) +# +CONFIG_CRYPTO_GHASH_ARM64_CE=m +CONFIG_CRYPTO_SHA3_ARM64=m +# CONFIG_CRYPTO_SM3_NEON is not set +# CONFIG_CRYPTO_SM3_ARM64_CE is not set +CONFIG_CRYPTO_POLYVAL_ARM64_CE=m +# CONFIG_CRYPTO_AES_ARM64 is not set +CONFIG_CRYPTO_AES_ARM64_CE=m +CONFIG_CRYPTO_AES_ARM64_CE_BLK=m +# CONFIG_CRYPTO_AES_ARM64_NEON_BLK is not set +# CONFIG_CRYPTO_AES_ARM64_BS is not set +# CONFIG_CRYPTO_SM4_ARM64_CE is not set +# CONFIG_CRYPTO_SM4_ARM64_CE_BLK is not set +# CONFIG_CRYPTO_SM4_ARM64_NEON_BLK is not set +# CONFIG_CRYPTO_AES_ARM64_CE_CCM is not set +# CONFIG_CRYPTO_SM4_ARM64_CE_CCM is not set +# CONFIG_CRYPTO_SM4_ARM64_CE_GCM is not set +# end of Accelerated Cryptographic Algorithms for CPU (arm64) + +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_DEV_ALLWINNER=y +# CONFIG_CRYPTO_DEV_SUN4I_SS is not set +# CONFIG_CRYPTO_DEV_SUN8I_CE is not set +# CONFIG_CRYPTO_DEV_SUN8I_SS is not set +# CONFIG_CRYPTO_DEV_FSL_CAAM is not set +# CONFIG_CRYPTO_DEV_SAHARA is not set +# CONFIG_CRYPTO_DEV_ATMEL_AES is not set +# CONFIG_CRYPTO_DEV_ATMEL_ECC is not set +# CONFIG_CRYPTO_DEV_ATMEL_SHA204A is not set +CONFIG_CRYPTO_DEV_CCP=y +# CONFIG_CRYPTO_DEV_CCP_DD is not set +# CONFIG_CRYPTO_DEV_MXS_DCP is not set +# CONFIG_CAVIUM_CPT is not set +# CONFIG_CRYPTO_DEV_NITROX_CNN55XX is not set +# CONFIG_CRYPTO_DEV_MARVELL_CESA is not set +# CONFIG_CRYPTO_DEV_OCTEONTX_CPT is not set +# CONFIG_CRYPTO_DEV_OCTEONTX2_CPT is not set +# CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4 is not set +# CONFIG_CRYPTO_DEV_KEEMBAY_OCS_ECC is not set +# CONFIG_CRYPTO_DEV_KEEMBAY_OCS_HCU is not set +# CONFIG_CRYPTO_DEV_QAT_DH895xCC is not set +# CONFIG_CRYPTO_DEV_QAT_C3XXX is not set +# CONFIG_CRYPTO_DEV_QAT_C62X is not set +# CONFIG_CRYPTO_DEV_QAT_4XXX is not set +# CONFIG_CRYPTO_DEV_QAT_420XX is not set +# CONFIG_CRYPTO_DEV_QAT_DH895xCCVF is not set +# CONFIG_CRYPTO_DEV_QAT_C3XXXVF is not set +# CONFIG_CRYPTO_DEV_QAT_C62XVF is not set +# CONFIG_CRYPTO_DEV_QCE is not set +# CONFIG_CRYPTO_DEV_QCOM_RNG is not set +# CONFIG_CRYPTO_DEV_ROCKCHIP is not set +# CONFIG_CRYPTO_DEV_XILINX_TRNG is not set +# CONFIG_CRYPTO_DEV_ZYNQMP_AES is not set +# CONFIG_CRYPTO_DEV_ZYNQMP_SHA3 is not set +# CONFIG_CRYPTO_DEV_VIRTIO is not set +# CONFIG_CRYPTO_DEV_STM32_HASH is not set +# CONFIG_CRYPTO_DEV_STM32_CRYP is not set +# CONFIG_CRYPTO_DEV_SAFEXCEL is not set +# CONFIG_CRYPTO_DEV_CCREE is not set +# CONFIG_CRYPTO_DEV_HISI_SEC is not set +# CONFIG_CRYPTO_DEV_HISI_SEC2 is not set +# CONFIG_CRYPTO_DEV_HISI_ZIP is not set +# CONFIG_CRYPTO_DEV_HISI_HPRE is not set +# CONFIG_CRYPTO_DEV_HISI_TRNG is not set +# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set +# CONFIG_CRYPTO_DEV_SA2UL is not set +# CONFIG_CRYPTO_DEV_EIP93 is not set +# CONFIG_CRYPTO_DEV_TI_DTHEV2 is not set +CONFIG_ASYMMETRIC_KEY_TYPE=y +CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y +CONFIG_X509_CERTIFICATE_PARSER=y +# CONFIG_PKCS8_PRIVATE_KEY_PARSER is not set +CONFIG_PKCS7_MESSAGE_PARSER=y +# CONFIG_PKCS7_TEST_KEY is not set +CONFIG_SIGNED_PE_FILE_VERIFICATION=y +# CONFIG_FIPS_SIGNATURE_SELFTEST is not set + +# +# Certificates for signature checking +# +CONFIG_MODULE_SIG_KEY="certs/signing_key.pem" +CONFIG_MODULE_SIG_KEY_TYPE_RSA=y +# CONFIG_MODULE_SIG_KEY_TYPE_ECDSA is not set +CONFIG_SYSTEM_TRUSTED_KEYRING=y +CONFIG_SYSTEM_TRUSTED_KEYS="" +CONFIG_SYSTEM_EXTRA_CERTIFICATE=y +CONFIG_SYSTEM_EXTRA_CERTIFICATE_SIZE=4096 +CONFIG_SECONDARY_TRUSTED_KEYRING=y +# CONFIG_SECONDARY_TRUSTED_KEYRING_SIGNED_BY_BUILTIN is not set +CONFIG_SYSTEM_BLACKLIST_KEYRING=y +CONFIG_SYSTEM_BLACKLIST_HASH_LIST="" +CONFIG_SYSTEM_REVOCATION_LIST=y +CONFIG_SYSTEM_REVOCATION_KEYS="" +# CONFIG_SYSTEM_BLACKLIST_AUTH_UPDATE is not set +# end of Certificates for signature checking + +# CONFIG_CRYPTO_KRB5 is not set +CONFIG_BINARY_PRINTF=y + +# +# Library routines +# +CONFIG_LINEAR_RANGES=y +CONFIG_PACKING=y +CONFIG_BITREVERSE=y +CONFIG_HAVE_ARCH_BITREVERSE=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +# CONFIG_CORDIC is not set +# CONFIG_PRIME_NUMBERS is not set +CONFIG_RATIONAL=y +CONFIG_STMP_DEVICE=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_ARCH_HAS_FAST_MULTIPLIER=y +CONFIG_ARCH_USE_SYM_ANNOTATIONS=y +CONFIG_INDIRECT_PIO=y +CONFIG_TRACE_MMIO_ACCESS=y +CONFIG_CRC8=y +CONFIG_CRC16=y +CONFIG_CRC_CCITT=y +CONFIG_CRC_T10DIF=y +CONFIG_CRC_T10DIF_ARCH=y +CONFIG_CRC32=y +CONFIG_CRC32_ARCH=y +CONFIG_CRC64=y +CONFIG_CRC_OPTIMIZATIONS=y + +# +# Crypto library routines +# +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_MD5=y +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=9 +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_SHA1_ARCH=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LIB_SHA256_ARCH=y +CONFIG_CRYPTO_LIB_SHA512=y +CONFIG_CRYPTO_LIB_SHA512_ARCH=y +# end of Crypto library routines + +CONFIG_XXHASH=y +CONFIG_AUDIT_GENERIC=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_AUDIT_COMPAT_GENERIC=y +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_DECOMPRESS=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +CONFIG_XZ_DEC_POWERPC=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_ARM64=y +CONFIG_XZ_DEC_SPARC=y +CONFIG_XZ_DEC_RISCV=y +CONFIG_XZ_DEC_MICROLZMA=y +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_LZ4=y +CONFIG_DECOMPRESS_ZSTD=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_INTERVAL_TREE=y +CONFIG_XARRAY_MULTI=y +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAS_DMA=y +CONFIG_DMA_OPS_HELPERS=y +CONFIG_NEED_SG_DMA_FLAGS=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_DMA_DECLARE_COHERENT=y +CONFIG_ARCH_HAS_SETUP_DMA_OPS=y +CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE=y +CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU=y +CONFIG_ARCH_HAS_DMA_PREP_COHERENT=y +CONFIG_ARCH_HAS_FORCE_DMA_UNENCRYPTED=y +CONFIG_SWIOTLB=y +CONFIG_SWIOTLB_DYNAMIC=y +CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y +CONFIG_DMA_NEED_SYNC=y +CONFIG_DMA_RESTRICTED_POOL=y +CONFIG_DMA_NONCOHERENT_MMAP=y +CONFIG_DMA_COHERENT_POOL=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DMA_CMA=y +CONFIG_DMA_NUMA_CMA=y + +# +# Default contiguous memory area size: +# +CONFIG_CMA_SIZE_MBYTES=32 +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_ALIGNMENT=8 +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_DMA_MAP_BENCHMARK is not set +CONFIG_SGL_ALLOC=y +CONFIG_CPUMASK_OFFSTACK=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_GLOB=y +# CONFIG_GLOB_SELFTEST is not set +CONFIG_NLATTR=y +CONFIG_CLZ_TAB=y +CONFIG_IRQ_POLL=y +CONFIG_MPILIB=y +CONFIG_SIGNATURE=y +CONFIG_DIMLIB=y +CONFIG_LIBFDT=y +CONFIG_OID_REGISTRY=y +CONFIG_UCS2_STRING=y +CONFIG_HAVE_GENERIC_VDSO=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_VDSO_GETRANDOM=y +CONFIG_FONT_SUPPORT=y +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +CONFIG_FONT_ACORN_8x8=y +# CONFIG_FONT_MINI_4x6 is not set +CONFIG_FONT_6x10=y +# CONFIG_FONT_10x18 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +CONFIG_FONT_TER16x32=y +# CONFIG_FONT_6x8 is not set +CONFIG_SG_SPLIT=y +CONFIG_SG_POOL=y +CONFIG_ARCH_HAS_PMEM_API=y +CONFIG_MEMREGION=y +CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_STACKDEPOT=y +CONFIG_STACKDEPOT_MAX_FRAMES=64 +CONFIG_SBITMAP=y +# CONFIG_LWQ_TEST is not set +# end of Library routines + +CONFIG_GENERIC_IOREMAP=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_ASN1_ENCODER=y +CONFIG_FIRMWARE_TABLE=y +CONFIG_UNION_FIND=y + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +CONFIG_PRINTK_TIME=y +# CONFIG_PRINTK_CALLER is not set +# CONFIG_STACKTRACE_BUILD_ID is not set +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 +CONFIG_CONSOLE_LOGLEVEL_QUIET=3 +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +CONFIG_BOOT_PRINTK_DELAY=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DYNAMIC_DEBUG_CORE=y +CONFIG_SYMBOLIC_ERRNAME=y +CONFIG_DEBUG_BUGVERBOSE=y +# end of printk and dmesg options + +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_MISC=y + +# +# Compile-time checks and compiler options +# +CONFIG_DEBUG_INFO=y +CONFIG_AS_HAS_NON_CONST_ULEB128=y +# CONFIG_DEBUG_INFO_NONE is not set +# CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT is not set +# CONFIG_DEBUG_INFO_DWARF4 is not set +CONFIG_DEBUG_INFO_DWARF5=y +# CONFIG_DEBUG_INFO_REDUCED is not set +CONFIG_DEBUG_INFO_COMPRESSED_NONE=y +# CONFIG_DEBUG_INFO_COMPRESSED_ZLIB is not set +# CONFIG_DEBUG_INFO_COMPRESSED_ZSTD is not set +# CONFIG_DEBUG_INFO_SPLIT is not set +CONFIG_DEBUG_INFO_BTF=y +CONFIG_PAHOLE_HAS_SPLIT_BTF=y +CONFIG_PAHOLE_HAS_BTF_TAG=y +CONFIG_PAHOLE_HAS_LANG_EXCLUDE=y +CONFIG_DEBUG_INFO_BTF_MODULES=y +# CONFIG_MODULE_ALLOW_BTF_MISMATCH is not set +CONFIG_GDB_SCRIPTS=y +CONFIG_FRAME_WARN=1024 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_HEADERS_INSTALL is not set +CONFIG_SECTION_MISMATCH_WARN_ONLY=y +# CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B is not set +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_FRAME_POINTER=y +CONFIG_VMLINUX_MAP=y +CONFIG_BUILTIN_MODULE_RANGES=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# end of Compile-time checks and compiler options + +# +# Generic Kernel Debugging Instruments +# +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x01b6 +CONFIG_MAGIC_SYSRQ_SERIAL=y +CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE="" +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_FS_ALLOW_ALL=y +# CONFIG_DEBUG_FS_DISALLOW_MOUNT is not set +# CONFIG_DEBUG_FS_ALLOW_NONE is not set +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_KGDB=y +CONFIG_KGDB_HONOUR_BLOCKLIST=y +CONFIG_KGDB_SERIAL_CONSOLE=y +# CONFIG_KGDB_TESTS is not set +CONFIG_KGDB_KDB=y +CONFIG_KDB_DEFAULT_ENABLE=0x1 +CONFIG_KDB_KEYBOARD=y +CONFIG_KDB_CONTINUE_CATASTROPHIC=0 +CONFIG_ARCH_HAS_UBSAN=y +CONFIG_UBSAN=y +# CONFIG_UBSAN_TRAP is not set +CONFIG_CC_HAS_UBSAN_ARRAY_BOUNDS=y +CONFIG_UBSAN_BOUNDS=y +CONFIG_UBSAN_ARRAY_BOUNDS=y +CONFIG_UBSAN_SHIFT=y +# CONFIG_UBSAN_UNREACHABLE is not set +CONFIG_UBSAN_BOOL=y +CONFIG_UBSAN_ENUM=y +# CONFIG_UBSAN_ALIGNMENT is not set +# CONFIG_TEST_UBSAN is not set +# CONFIG_UBSAN_KVM_EL2 is not set +CONFIG_HAVE_ARCH_KCSAN=y +CONFIG_HAVE_KCSAN_COMPILER=y +# CONFIG_KCSAN is not set +# end of Generic Kernel Debugging Instruments + +# +# Networking Debugging +# +# CONFIG_NET_DEV_REFCNT_TRACKER is not set +# CONFIG_NET_NS_REFCNT_TRACKER is not set +# CONFIG_DEBUG_NET is not set +# CONFIG_DEBUG_NET_SMALL_RTNL is not set +# end of Networking Debugging + +# +# Memory Debugging +# +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_SLUB_DEBUG=y +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_PAGE_OWNER is not set +# CONFIG_PAGE_TABLE_CHECK is not set +CONFIG_PAGE_POISONING=y +# CONFIG_DEBUG_PAGE_REF is not set +# CONFIG_DEBUG_RODATA_TEST is not set +CONFIG_ARCH_HAS_DEBUG_WX=y +CONFIG_DEBUG_WX=y +CONFIG_ARCH_HAS_PTDUMP=y +CONFIG_PTDUMP=y +# CONFIG_PTDUMP_DEBUGFS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_PER_VMA_LOCK_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SHRINKER_DEBUG is not set +# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_SCHED_STACK_END_CHECK=y +CONFIG_ARCH_HAS_DEBUG_VM_PGTABLE=y +# CONFIG_DEBUG_VFS is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_VM_PGTABLE is not set +CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y +# CONFIG_DEBUG_VIRTUAL is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_MEM_ALLOC_PROFILING is not set +CONFIG_HAVE_ARCH_KASAN=y +CONFIG_HAVE_ARCH_KASAN_SW_TAGS=y +CONFIG_HAVE_ARCH_KASAN_HW_TAGS=y +CONFIG_HAVE_ARCH_KASAN_VMALLOC=y +CONFIG_CC_HAS_KASAN_GENERIC=y +CONFIG_CC_HAS_KASAN_SW_TAGS=y +CONFIG_CC_HAS_WORKING_NOSANITIZE_ADDRESS=y +# CONFIG_KASAN is not set +CONFIG_HAVE_ARCH_KFENCE=y +CONFIG_KFENCE=y +CONFIG_KFENCE_SAMPLE_INTERVAL=0 +CONFIG_KFENCE_NUM_OBJECTS=255 +# CONFIG_KFENCE_DEFERRABLE is not set +# CONFIG_KFENCE_STATIC_KEYS is not set +CONFIG_KFENCE_STRESS_TEST_FAULTS=0 +CONFIG_HAVE_KMSAN_COMPILER=y +# end of Memory Debugging + +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Oops, Lockups and Hangs +# +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_TIMEOUT=0 +CONFIG_LOCKUP_DETECTOR=y +CONFIG_SOFTLOCKUP_DETECTOR=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_HAVE_HARDLOCKUP_DETECTOR_BUDDY=y +CONFIG_HARDLOCKUP_DETECTOR=y +# CONFIG_HARDLOCKUP_DETECTOR_PREFER_BUDDY is not set +CONFIG_HARDLOCKUP_DETECTOR_PERF=y +# CONFIG_HARDLOCKUP_DETECTOR_BUDDY is not set +# CONFIG_HARDLOCKUP_DETECTOR_ARCH is not set +CONFIG_HARDLOCKUP_DETECTOR_COUNTS_HRTIMER=y +# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_DETECT_HUNG_TASK_BLOCKER=y +# CONFIG_WQ_WATCHDOG is not set +CONFIG_WQ_CPU_INTENSIVE_REPORT=y +# CONFIG_TEST_LOCKUP is not set +# end of Debug Oops, Lockups and Hangs + +# +# Scheduler Debugging +# +CONFIG_SCHED_INFO=y +CONFIG_SCHEDSTATS=y +# end of Scheduler Debugging + +# CONFIG_DEBUG_PREEMPT is not set + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +CONFIG_LOCK_DEBUGGING_SUPPORT=y +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +# CONFIG_WW_MUTEX_SELFTEST is not set +# CONFIG_SCF_TORTURE_TEST is not set +# CONFIG_CSD_LOCK_WAIT_DEBUG is not set +# end of Lock Debugging (spinlocks, mutexes, etc...) + +# CONFIG_DEBUG_IRQFLAGS is not set +CONFIG_STACKTRACE=y +# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set +# CONFIG_DEBUG_KOBJECT is not set + +# +# Debug kernel data structures +# +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PLIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_MAPLE_TREE is not set +# end of Debug kernel data structures + +# +# RCU Debugging +# +# CONFIG_RCU_SCALE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_REF_SCALE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_RCU_EXP_CPU_STALL_TIMEOUT=0 +CONFIG_RCU_CPU_STALL_CPUTIME=y +# CONFIG_RCU_TRACE is not set +# CONFIG_RCU_EQS_DEBUG is not set +# end of RCU Debugging + +# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set +# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set +CONFIG_LATENCYTOP=y +# CONFIG_DEBUG_CGROUP_REF is not set +CONFIG_USER_STACKTRACE_SUPPORT=y +CONFIG_NOP_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_FREGS=y +CONFIG_HAVE_FTRACE_GRAPH_FUNC=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS=y +CONFIG_HAVE_EXTRA_IPI_TRACEPOINTS=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_BUILDTIME_MCOUNT_SORT=y +CONFIG_BUILDTIME_MCOUNT_SORT=y +CONFIG_TRACER_MAX_TRACE=y +CONFIG_TRACE_CLOCK=y +CONFIG_RING_BUFFER=y +CONFIG_EVENT_TRACING=y +CONFIG_CONTEXT_SWITCH_TRACER=y +CONFIG_TRACING=y +CONFIG_GENERIC_TRACER=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +CONFIG_TRACEFS_AUTOMOUNT_DEPRECATED=y +CONFIG_BOOTTIME_TRACING=y +CONFIG_FUNCTION_TRACER=y +CONFIG_FUNCTION_GRAPH_TRACER=y +CONFIG_FUNCTION_GRAPH_RETVAL=y +CONFIG_FUNCTION_GRAPH_RETADDR=y +CONFIG_FUNCTION_TRACE_ARGS=y +CONFIG_DYNAMIC_FTRACE=y +CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y +CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS=y +CONFIG_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_FPROBE=y +CONFIG_FUNCTION_PROFILER=y +CONFIG_STACK_TRACER=y +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +CONFIG_SCHED_TRACER=y +CONFIG_HWLAT_TRACER=y +CONFIG_OSNOISE_TRACER=y +CONFIG_TIMERLAT_TRACER=y +CONFIG_FTRACE_SYSCALLS=y +CONFIG_TRACER_SNAPSHOT=y +# CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_FPROBE_EVENTS=y +CONFIG_PROBE_EVENTS_BTF_ARGS=y +CONFIG_KPROBE_EVENTS=y +# CONFIG_KPROBE_EVENTS_ON_NOTRACE is not set +CONFIG_UPROBE_EVENTS=y +CONFIG_EPROBE_EVENTS=y +CONFIG_BPF_EVENTS=y +CONFIG_DYNAMIC_EVENTS=y +CONFIG_PROBE_EVENTS=y +CONFIG_BPF_KPROBE_OVERRIDE=y +CONFIG_FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY=y +CONFIG_TRACING_MAP=y +CONFIG_SYNTH_EVENTS=y +CONFIG_USER_EVENTS=y +CONFIG_HIST_TRIGGERS=y +CONFIG_TRACE_EVENT_INJECT=y +# CONFIG_TRACEPOINT_BENCHMARK is not set +# CONFIG_RING_BUFFER_BENCHMARK is not set +# CONFIG_TRACE_EVAL_MAP_FILE is not set +# CONFIG_FTRACE_RECORD_RECURSION is not set +# CONFIG_FTRACE_VALIDATE_RCU_IS_WATCHING is not set +# CONFIG_FTRACE_STARTUP_TEST is not set +# CONFIG_FTRACE_SORT_STARTUP_TEST is not set +# CONFIG_RING_BUFFER_STARTUP_TEST is not set +# CONFIG_RING_BUFFER_VALIDATE_TIME_DELTAS is not set +# CONFIG_PREEMPTIRQ_DELAY_TEST is not set +# CONFIG_SYNTH_EVENT_GEN_TEST is not set +# CONFIG_KPROBE_EVENT_GEN_TEST is not set +# CONFIG_HIST_TRIGGERS_DEBUG is not set +CONFIG_RV_MON_EVENTS=y +CONFIG_RV_MON_MAINTENANCE_EVENTS=y +CONFIG_DA_MON_EVENTS_ID=y +CONFIG_RV=y +CONFIG_RV_PER_TASK_MONITORS=2 +CONFIG_RV_MON_WWNR=y +# CONFIG_RV_MON_RTAPP is not set +CONFIG_RV_REACTORS=y +CONFIG_RV_REACT_PRINTK=y +CONFIG_RV_REACT_PANIC=y +CONFIG_SAMPLES=y +# CONFIG_SAMPLE_AUXDISPLAY is not set +# CONFIG_SAMPLE_TRACE_EVENTS is not set +# CONFIG_SAMPLE_TRACE_CUSTOM_EVENTS is not set +# CONFIG_SAMPLE_TRACE_PRINTK is not set +# CONFIG_SAMPLE_FTRACE_DIRECT is not set +# CONFIG_SAMPLE_FTRACE_DIRECT_MULTI is not set +# CONFIG_SAMPLE_FTRACE_OPS is not set +# CONFIG_SAMPLE_TRACE_ARRAY is not set +# CONFIG_SAMPLE_KOBJECT is not set +# CONFIG_SAMPLE_KPROBES is not set +# CONFIG_SAMPLE_HW_BREAKPOINT is not set +# CONFIG_SAMPLE_FPROBE is not set +# CONFIG_SAMPLE_KFIFO is not set +# CONFIG_SAMPLE_KDB is not set +# CONFIG_SAMPLE_QMI_CLIENT is not set +# CONFIG_SAMPLE_CONFIGFS is not set +# CONFIG_SAMPLE_TSM_MR is not set +# CONFIG_SAMPLE_VFIO_MDEV_MDPY_FB is not set +# CONFIG_SAMPLE_WATCHDOG is not set +# CONFIG_SAMPLE_HUNG_TASK is not set +CONFIG_SAMPLES_RUST=y +CONFIG_SAMPLE_RUST_CONFIGFS=y +CONFIG_SAMPLE_RUST_MINIMAL=y +CONFIG_SAMPLE_RUST_MISC_DEVICE=y +CONFIG_SAMPLE_RUST_PRINT=y +CONFIG_SAMPLE_RUST_DMA=y +CONFIG_SAMPLE_RUST_DEBUGFS=y +CONFIG_SAMPLE_RUST_DEBUGFS_SCOPED=y +CONFIG_SAMPLE_RUST_DRIVER_PCI=y +CONFIG_SAMPLE_RUST_DRIVER_PLATFORM=y +CONFIG_SAMPLE_RUST_DRIVER_FAUX=y +CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY=y +CONFIG_SAMPLE_RUST_HOSTPROGS=y + +# +# DAMON Samples +# +# end of DAMON Samples + +CONFIG_HAVE_SAMPLE_FTRACE_DIRECT=y +CONFIG_HAVE_SAMPLE_FTRACE_DIRECT_MULTI=y +CONFIG_STRICT_DEVMEM=y +# CONFIG_IO_STRICT_DEVMEM is not set + +# +# arm64 Debugging +# +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_DEBUG_EFI is not set +# CONFIG_ARM64_RELOC_TEST is not set +# CONFIG_CORESIGHT is not set +# end of arm64 Debugging + +# +# Kernel Testing and Coverage +# +# CONFIG_KUNIT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +CONFIG_FUNCTION_ERROR_INJECTION=y +# CONFIG_FAULT_INJECTION is not set +CONFIG_ARCH_HAS_KCOV=y +# CONFIG_KCOV is not set +CONFIG_RUNTIME_TESTING_MENU=y +# CONFIG_TEST_DHRY is not set +# CONFIG_LKDTM is not set +# CONFIG_TEST_MIN_HEAP is not set +# CONFIG_TEST_DIV64 is not set +# CONFIG_TEST_MULDIV64 is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_TEST_REF_TRACKER is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_REED_SOLOMON_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_BITMAP is not set +# CONFIG_TEST_UUID is not set +# CONFIG_TEST_XARRAY is not set +# CONFIG_TEST_MAPLE_TREE is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_TEST_IDA is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_BITOPS is not set +# CONFIG_TEST_VMALLOC is not set +# CONFIG_TEST_BPF is not set +# CONFIG_FIND_BIT_BENCHMARK is not set +# CONFIG_FIND_BIT_BENCHMARK_RUST is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_SYSCTL is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_TEST_STATIC_KEYS is not set +# CONFIG_TEST_DYNAMIC_DEBUG is not set +# CONFIG_TEST_KMOD is not set +# CONFIG_TEST_KALLSYMS is not set +# CONFIG_TEST_MEMCAT_P is not set +# CONFIG_TEST_MEMINIT is not set +# CONFIG_TEST_HMM is not set +# CONFIG_TEST_FREE_PAGES is not set +# CONFIG_TEST_FPU is not set +# CONFIG_TEST_OBJPOOL is not set +CONFIG_ARCH_USE_MEMTEST=y +CONFIG_MEMTEST=y +# end of Kernel Testing and Coverage + +# +# Rust hacking +# +CONFIG_RUST_DEBUG_ASSERTIONS=y +CONFIG_RUST_OVERFLOW_CHECKS=y +CONFIG_RUST_BUILD_ASSERT_ALLOW=y +# end of Rust hacking +# end of Kernel hacking + +CONFIG_IO_URING_ZCRX=y From 2a54aac2de6ff15c22007e6e76cfb5c1f2593307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Mon, 1 Dec 2025 16:45:23 -0500 Subject: [PATCH 050/131] address comments --- fs/rustezfs/ezfs.rs | 7 ++++--- rust/kernel/iomap.rs | 38 +++++++++++++++++++++++++------------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index b47def21dc6b1a..c5700ef276ee6d 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -126,7 +126,7 @@ impl FileSystem for RustEzFs { return Err(EINVAL); } - let ezfs_sb: Self::Data = KBox::pin_init(EzfsSuperblock::new(disk_sb, mapper), GFP_KERNEL)?; + let ezfs_sb = KBox::pin_init(EzfsSuperblock::new(disk_sb, mapper), GFP_KERNEL)?; sb.set_magic(EZFS_MAGIC_NUMBER); @@ -280,6 +280,7 @@ impl file::Operations for RustEzFs { impl iomap::Operations for RustEzFs { type FileSystem = Self; + // Equivalent to c's iomap_begin() fn begin<'a>( inode: &'a INode, pos: Offset, @@ -294,8 +295,8 @@ impl iomap::Operations for RustEzFs { let ezfs_sb: Pin<&EzfsSuperblock> = sb.data(); let ezfs_inode = inode.data(); - let start_block = (pos >> sb.blocksize_bits()) as u64; - let end_block = ((pos + length - 1) >> sb.blocksize_bits()) as u64; + let start_block: u64 = (pos >> sb.blocksize_bits()).try_into()?; + let end_block: u64 = ((pos + length - 1) >> sb.blocksize_bits()).try_into()?; let ez_blk_num = ezfs_inode.data_blk_num(); let ez_blk_count = inode.blocks() / 8; diff --git a/rust/kernel/iomap.rs b/rust/kernel/iomap.rs index ceb2077759010b..1eb1de2a0669eb 100644 --- a/rust/kernel/iomap.rs +++ b/rust/kernel/iomap.rs @@ -8,14 +8,14 @@ use super::address_space; use crate::pr_info; use crate::prelude::EIO; use crate::{ + block, error::{from_result, Result}, folio::Folio, folio::PageCache, fs::file::File, - fs::Offset, fs::FileSystem, + fs::Offset, types::Locked, - block, }; use crate::inode::INode; @@ -45,6 +45,12 @@ pub enum Type { Inline = bindings::IOMAP_INLINE as u16, } +impl From for u16 { + fn from(t: Type) -> Self { + // This is ok as Type values are is represented as u16 + t as u16 + } +} /// Flags usable in [`Map`], in [`Map::set_flags`] in particular. pub mod map_flags { @@ -90,7 +96,7 @@ pub struct Map<'a>(pub bindings::iomap, PhantomData<&'a ()>); impl<'a> Map<'a> { /// Sets the map type. pub fn set_type(&mut self, t: Type) -> &mut Self { - self.0.type_ = t as u16; + self.0.type_ = t.into(); self } @@ -160,7 +166,6 @@ pub mod flags { pub const DAX: u32 = bindings::IOMAP_DAX; } - /// Operations implemented by iomap users. pub trait Operations { /// File system that these operations are compatible with. @@ -197,7 +202,6 @@ pub trait Operations { } } - /// Returns address space oprerations backed by iomaps. pub const fn aops() -> address_space::Ops { struct Table(PhantomData); @@ -289,15 +293,23 @@ pub const fn aops() -> address_space::Ops unsafe { bindings::iomap_read_folio(folio, &Self::MAP_TABLE) } } - - extern "C" fn writepages_callback(_mapping: *mut bindings::address_space, _wbc: *mut bindings::writeback_control) -> i32 { + extern "C" fn writepages_callback( + _mapping: *mut bindings::address_space, + _wbc: *mut bindings::writeback_control, + ) -> i32 { // Safety: iomap docs say wpc must be zero-initialized. - let mut wpc: bindings::iomap_writepage_ctx = unsafe {mem::zeroed()}; - wpc.inode = unsafe { (*_mapping).host }; // struct inode *host - wpc.wbc = _wbc; - wpc.ops = &Self::WRITEBACK_TABLE; - - unsafe {bindings::iomap_writepages(&mut wpc)} + let mut wpc: bindings::iomap_writepage_ctx = unsafe { mem::zeroed() }; + + // SAFETY: `_mapping` is guaranteed by the VFS to be a valid `struct address_space *`. + // Its `host` field is a valid `struct inode *`. + wpc.inode = unsafe { (*_mapping).host }; + wpc.wbc = _wbc; + wpc.ops = &Self::WRITEBACK_TABLE; + + // SAFETY: We just created `wpc` to be stack-allocated & zero-initialised. + // The VFS guarantees that `.inode` + `.wbc` are valid while `.ops` is static. + // We pass a unique mutable pointer to `wpc`. + unsafe { bindings::iomap_writepages(&mut wpc) } } extern "C" fn readahead_callback(rac: *mut bindings::readahead_control) { From 3efc237080364cea7f6178aff0a8f13752c80de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Mon, 1 Dec 2025 16:54:57 -0500 Subject: [PATCH 051/131] add comments to ezfs::iomap_begin impl --- fs/rustezfs/ezfs.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index c5700ef276ee6d..fa64e868705873 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -307,13 +307,7 @@ impl iomap::Operations for RustEzFs { 0 }; - let phys_sidx: i64 = if ez_blk_num > 0 { - // phys should always be >= root datablock number - (phys - EZFS_ROOT_DATABLOCK_NUMBER as u64).try_into()? - } else { - -1i64 - }; - + // For all cases, the bdev, offset and length are as such map.set_bdev(Some(sb.bdev())) .set_offset(pos) .set_length(length as u64); @@ -321,11 +315,13 @@ impl iomap::Operations for RustEzFs { if (flags & iomap::flags::WRITE == 0) { pr_info!("READING\n"); + // Invalid read, block does not belong to inode if ez_blk_num == 0 || start_block >= ez_blk_count { map.set_type(iomap::Type::Hole) .set_addr(bindings::IOMAP_NULL_ADDR as u64); return Ok(()); } + // Valid read, set target address accordingly map.set_type(iomap::Type::Mapped) .set_addr(phys << sb.blocksize_bits()); return Ok(()); @@ -333,6 +329,14 @@ impl iomap::Operations for RustEzFs { pr_info!("WRITING\n"); + // // Shifted physical index + // let phys_sidx: i64 = if ez_blk_num > 0 { + // // phys should always be >= root datablock number + // (phys - EZFS_ROOT_DATABLOCK_NUMBER as u64).try_into()? + // } else { + // -1i64 + // }; + Err(EIO) } From 551667a260beefc36d27ae81341a140e08b077e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Mon, 1 Dec 2025 18:08:03 -0500 Subject: [PATCH 052/131] add write_iter --- rust/kernel/fs/file.rs | 50 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index 20bd4accbde0dc..0877cca33a4691 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -16,7 +16,7 @@ use crate::{ fmt, fs::{FileSystem, Kiocb, Offset, UnspecifiedFS}, inode::{self, INode, Ino}, - iov::IovIterDest, + iov::{IovIterDest, IovIterSource}, kernel::dentry::DEntry, sync::aref::{ARef, AlwaysRefCounted}, types::{ForeignOwnable, Locked, NotThreadSafe, Opaque}, @@ -582,6 +582,26 @@ pub trait Operations { ) -> Result { Err(EINVAL) } + + // /// Writes data from the caller's buffer to this file. + // /// + // /// Corresponds to the `write_iter` function pointer in `struct file_operations`. + // fn write( + // _data: ::Borrowed<'_>, + // _file: &File, + // _reader: &mut impl IoBufferReader, + // _offset: u64, + // ) -> Result { + // Err(EINVAL) + // } + + /// Write to this miscdevice. + fn write_iter( + _kiocb: Kiocb<'_, ::Data>, + _iov: &mut IovIterSource<'_>, + ) -> Result { + Err(EINVAL) + } } /// Represents file operations @@ -617,8 +637,11 @@ impl Ops { }, write: None, read_iter: Some(Self::read_iter_callback), - // read_iter: Some(unsafe {bindings::generic_file_read_iter}), - write_iter: None, + write_iter: if T::HAS_WRITE_ITER { + Some(Self::write_iter_callback) + } else { + None + }, iopoll: None, iterate_shared: None, poll: None, @@ -713,6 +736,27 @@ impl Ops { pr_info!("read_iter_callback\n"); return unsafe { bindings::generic_file_read_iter(kiocb, iter) }; } + + /// # Safety + /// + /// `kiocb` must be correspond to a valid file that is associated with a + /// `MiscDeviceRegistration`. `iter` must be a valid `struct iov_iter` for writing. + unsafe extern "C" fn write_iter_callback( + kiocb: *mut bindings::kiocb, + iter: *mut bindings::iov_iter, + ) -> isize { + pr_info!("write_iter_callback\n"); + // SAFETY: The caller provides a valid `struct kiocb` associated with a + // `MiscDeviceRegistration` file. + let kiocb = unsafe { Kiocb::from_raw(kiocb) }; + // SAFETY: This is a valid `struct iov_iter` for reading. + let iov = unsafe { IovIterSource::from_raw(iter) }; + + match T::write_iter(kiocb, iov) { + Ok(res) => res as isize, + Err(err) => err.to_errno() as isize, + } + } } Self { inner: &Table::::TABLE, From 3d8954c4fdfc09f3834bb41afc8bc17d16f4c44d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Mon, 1 Dec 2025 18:11:59 -0500 Subject: [PATCH 053/131] add required `.migrate_folio` to address_space::Ops --- rust/kernel/address_space.rs | 2 +- rust/kernel/iomap.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/kernel/address_space.rs b/rust/kernel/address_space.rs index f87264657fd190..5e8842f180ffa6 100644 --- a/rust/kernel/address_space.rs +++ b/rust/kernel/address_space.rs @@ -54,7 +54,7 @@ impl Ops { release_folio: None, free_folio: None, direct_IO: None, - migrate_folio: None, + migrate_folio: Some(bindings::filemap_migrate_folio), launder_folio: None, is_partially_uptodate: None, is_dirty_writeback: None, diff --git a/rust/kernel/iomap.rs b/rust/kernel/iomap.rs index 1eb1de2a0669eb..9cee6994dbd43e 100644 --- a/rust/kernel/iomap.rs +++ b/rust/kernel/iomap.rs @@ -275,7 +275,7 @@ pub const fn aops() -> address_space::Ops free_folio: None, // direct_IO: Some(bindings::noop_direct_IO), direct_IO: None, - migrate_folio: None, + migrate_folio: Some(bindings::filemap_migrate_folio), launder_folio: None, is_partially_uptodate: None, is_dirty_writeback: None, From a2bf1ef07f8d230d12e6364c89ac489fe34047b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Tue, 2 Dec 2025 01:28:33 -0500 Subject: [PATCH 054/131] complete write_iter --- fs/rustezfs/ezfs.rs | 45 +++++++- rust/helpers/fs.c | 6 +- rust/kernel/iomap.rs | 238 ++++++++++++++++++++++--------------------- 3 files changed, 171 insertions(+), 118 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 755fae6c0ba763..45a1f025a31b8d 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -17,7 +17,7 @@ use kernel::folio::{Folio, PageCache}; use kernel::fs::Kiocb; use kernel::fs::{file, File, FileSystem, Offset, Registration}; use kernel::inode::{INode, INodeState, Mapper, Params, Type}; -use kernel::iov::IovIterDest; +use kernel::iov::{IovIterDest, IovIterSource}; use kernel::prelude::*; use kernel::sb::{New, SuperBlock, Type as SuperType}; use kernel::time::UNIX_EPOCH; @@ -28,6 +28,7 @@ use kernel::{c_str, fs, str::CStr}; use core::marker::{PhantomData, Send, Sync}; use core::mem::size_of; +use core::ptr; use pin_init::{pin_data, PinInit, PinnedDrop}; struct RustEzFs; @@ -284,6 +285,48 @@ impl file::Operations for RustEzFs { Ok(()) } + + fn write_iter( + _kiocb: Kiocb<'_, ::Data>, + _iov: &mut IovIterSource<'_>, + ) -> Result { + pr_info!("write_iter\n"); + + let kiocb = _kiocb.as_raw(); + let iter = _iov.as_raw(); + let iomap_ops = iomap::map_table::(); + + // SAFETY: VFS guarantees kiocb is never null and can be dereferenced + // Theerefore, both operations below are valid + let flags = unsafe { (*kiocb).ki_flags as u32 }; // casting a bitmask to u32 is always ok + let file_ptr = unsafe { (*kiocb).ki_filp }; + + if flags & bindings::IOCB_DIRECT != 0 { + return Err(EINVAL); // We don't support direct I/O + } + + // SAFETY: VFS will always provide a valid file pointer + let file_flags = unsafe { (*file_ptr).f_flags }; + + if (file_flags & bindings::O_APPEND) != 0 { + unsafe { (*kiocb).ki_pos = bindings::i_size_read((*(*file_ptr).f_mapping).host) }; + } + + // SAFETY: We've got a valid kiocb and iov iter from our VFS and our iomap_ops is static + // The function treats null pointers as valid inputs for the last two params + let ret: usize = unsafe { + bindings::iomap_file_buffered_write( + kiocb, + iter, + iomap_ops, + ptr::null(), + ptr::null_mut(), + ) + } + .try_into()?; + + Ok(ret) + } } impl iomap::Operations for RustEzFs { diff --git a/rust/helpers/fs.c b/rust/helpers/fs.c index d13ffd2407cb0c..02429eb371b89a 100644 --- a/rust/helpers/fs.c +++ b/rust/helpers/fs.c @@ -21,7 +21,6 @@ void rust_helper_i_gid_write(struct inode *inode, gid_t gid) i_gid_write(inode, gid); } - void rust_helper_inode_lock_shared(struct inode *inode) { inode_lock_shared(inode); @@ -37,3 +36,8 @@ void *rust_helper_alloc_inode_sb(struct super_block *sb, { return alloc_inode_sb(sb, cache, gfp); } + +loff_t rust_helper_i_size_read(const struct inode *inode) +{ + return i_size_read(inode); +} diff --git a/rust/kernel/iomap.rs b/rust/kernel/iomap.rs index 1eb1de2a0669eb..ab5bf9037359f0 100644 --- a/rust/kernel/iomap.rs +++ b/rust/kernel/iomap.rs @@ -202,125 +202,131 @@ pub trait Operations { } } -/// Returns address space oprerations backed by iomaps. -pub const fn aops() -> address_space::Ops { - struct Table(PhantomData); - impl Table { - const MAP_TABLE: bindings::iomap_ops = bindings::iomap_ops { - iomap_begin: Some(Self::iomap_begin_callback), - iomap_end: Some(Self::iomap_end_callback), - }; +struct Table(PhantomData); - const WRITEBACK_TABLE: bindings::iomap_writeback_ops = bindings::iomap_writeback_ops { - writeback_range: None, - writeback_submit: None, - }; +impl Table { + const MAP_TABLE: bindings::iomap_ops = bindings::iomap_ops { + iomap_begin: Some(Self::iomap_begin_callback), + iomap_end: Some(Self::iomap_end_callback), + }; - extern "C" fn iomap_begin_callback( - inode_ptr: *mut bindings::inode, - pos: Offset, - length: Offset, - flags: u32, - map: *mut bindings::iomap, - srcmap: *mut bindings::iomap, - ) -> i32 { - from_result(|| { - // SAFETY: The C API guarantees that `inode_ptr` is a valid inode. - let inode = unsafe { INode::from_raw(inode_ptr) }; - T::begin( - inode, - pos, - length, - flags, - // SAFETY: The C API guarantees that `map` is valid for write. - unsafe { &mut *map.cast::>() }, - // SAFETY: The C API guarantees that `srcmap` is valid for write. - unsafe { &mut *srcmap.cast::>() }, - )?; - Ok(0) - }) - } - - extern "C" fn iomap_end_callback( - inode_ptr: *mut bindings::inode, - pos: Offset, - length: Offset, - written: isize, - flags: u32, - map: *mut bindings::iomap, - ) -> i32 { - from_result(|| { - // SAFETY: The C API guarantees that `inode_ptr` is a valid inode. - let inode = unsafe { INode::from_raw(inode_ptr) }; - // SAFETY: The C API guarantees that `map` is valid for read. - T::end(inode, pos, length, written, flags, unsafe { - &*map.cast::>() - })?; - Ok(0) - }) - } - - const TABLE: bindings::address_space_operations = bindings::address_space_operations { - read_folio: Some(Self::read_folio_callback), - writepages: Some(Self::writepages_callback), - dirty_folio: Some(bindings::iomap_dirty_folio), - // readahead: Some(Self::readahead_callback), - readahead: None, - write_begin: None, - write_end: None, - // bmap: Some(Self::bmap_callback), - bmap: None, - invalidate_folio: Some(bindings::iomap_invalidate_folio), - release_folio: Some(bindings::iomap_release_folio), - free_folio: None, - // direct_IO: Some(bindings::noop_direct_IO), - direct_IO: None, - migrate_folio: None, - launder_folio: None, - is_partially_uptodate: None, - is_dirty_writeback: None, - error_remove_folio: None, - swap_activate: None, - swap_deactivate: None, - swap_rw: None, - }; + const WRITEBACK_TABLE: bindings::iomap_writeback_ops = bindings::iomap_writeback_ops { + writeback_range: None, + writeback_submit: None, + }; + + extern "C" fn iomap_begin_callback( + inode_ptr: *mut bindings::inode, + pos: Offset, + length: Offset, + flags: u32, + map: *mut bindings::iomap, + srcmap: *mut bindings::iomap, + ) -> i32 { + from_result(|| { + // SAFETY: The C API guarantees that `inode_ptr` is a valid inode. + let inode = unsafe { INode::from_raw(inode_ptr) }; + T::begin( + inode, + pos, + length, + flags, + // SAFETY: The C API guarantees that `map` is valid for write. + unsafe { &mut *map.cast::>() }, + // SAFETY: The C API guarantees that `srcmap` is valid for write. + unsafe { &mut *srcmap.cast::>() }, + )?; + Ok(0) + }) + } - extern "C" fn read_folio_callback( - _file: *mut bindings::file, - folio: *mut bindings::folio, - ) -> i32 { - // SAFETY: `folio` is just forwarded from C and `Self::MAP_TABLE` is always valid. - unsafe { bindings::iomap_read_folio(folio, &Self::MAP_TABLE) } - } - - extern "C" fn writepages_callback( - _mapping: *mut bindings::address_space, - _wbc: *mut bindings::writeback_control, - ) -> i32 { - // Safety: iomap docs say wpc must be zero-initialized. - let mut wpc: bindings::iomap_writepage_ctx = unsafe { mem::zeroed() }; - - // SAFETY: `_mapping` is guaranteed by the VFS to be a valid `struct address_space *`. - // Its `host` field is a valid `struct inode *`. - wpc.inode = unsafe { (*_mapping).host }; - wpc.wbc = _wbc; - wpc.ops = &Self::WRITEBACK_TABLE; - - // SAFETY: We just created `wpc` to be stack-allocated & zero-initialised. - // The VFS guarantees that `.inode` + `.wbc` are valid while `.ops` is static. - // We pass a unique mutable pointer to `wpc`. - unsafe { bindings::iomap_writepages(&mut wpc) } - } - - extern "C" fn readahead_callback(rac: *mut bindings::readahead_control) { - // SAFETY: `rac` is just forwarded from C and `Self::MAP_TABLE` is always valid. - unsafe { bindings::iomap_readahead(rac, &Self::MAP_TABLE) } - } - - extern "C" fn bmap_callback(mapping: *mut bindings::address_space, block: u64) -> u64 { - // SAFETY: `mapping` is just forwarded from C and `Self::MAP_TABLE` is always valid. - unsafe { bindings::iomap_bmap(mapping, block, &Self::MAP_TABLE) } - } + extern "C" fn iomap_end_callback( + inode_ptr: *mut bindings::inode, + pos: Offset, + length: Offset, + written: isize, + flags: u32, + map: *mut bindings::iomap, + ) -> i32 { + from_result(|| { + // SAFETY: The C API guarantees that `inode_ptr` is a valid inode. + let inode = unsafe { INode::from_raw(inode_ptr) }; + // SAFETY: The C API guarantees that `map` is valid for read. + T::end(inode, pos, length, written, flags, unsafe { + &*map.cast::>() + })?; + Ok(0) + }) } + + const TABLE: bindings::address_space_operations = bindings::address_space_operations { + read_folio: Some(Self::read_folio_callback), + writepages: Some(Self::writepages_callback), + dirty_folio: Some(bindings::iomap_dirty_folio), + // readahead: Some(Self::readahead_callback), + readahead: None, + write_begin: None, + write_end: None, + // bmap: Some(Self::bmap_callback), + bmap: None, + invalidate_folio: Some(bindings::iomap_invalidate_folio), + release_folio: Some(bindings::iomap_release_folio), + free_folio: None, + // direct_IO: Some(bindings::noop_direct_IO), + direct_IO: None, + migrate_folio: None, + launder_folio: None, + is_partially_uptodate: None, + is_dirty_writeback: None, + error_remove_folio: None, + swap_activate: None, + swap_deactivate: None, + swap_rw: None, + }; + + extern "C" fn read_folio_callback( + _file: *mut bindings::file, + folio: *mut bindings::folio, + ) -> i32 { + // SAFETY: `folio` is just forwarded from C and `Self::MAP_TABLE` is always valid. + unsafe { bindings::iomap_read_folio(folio, &Self::MAP_TABLE) } + } + + extern "C" fn writepages_callback( + _mapping: *mut bindings::address_space, + _wbc: *mut bindings::writeback_control, + ) -> i32 { + // Safety: iomap docs say wpc must be zero-initialized. + let mut wpc: bindings::iomap_writepage_ctx = unsafe { mem::zeroed() }; + + // SAFETY: `_mapping` is guaranteed by the VFS to be a valid `struct address_space *`. + // Its `host` field is a valid `struct inode *`. + wpc.inode = unsafe { (*_mapping).host }; + wpc.wbc = _wbc; + wpc.ops = &Self::WRITEBACK_TABLE; + + // SAFETY: We just created `wpc` to be stack-allocated & zero-initialised. + // The VFS guarantees that `.inode` + `.wbc` are valid while `.ops` is static. + // We pass a unique mutable pointer to `wpc`. + unsafe { bindings::iomap_writepages(&mut wpc) } + } + + extern "C" fn readahead_callback(rac: *mut bindings::readahead_control) { + // SAFETY: `rac` is just forwarded from C and `Self::MAP_TABLE` is always valid. + unsafe { bindings::iomap_readahead(rac, &Self::MAP_TABLE) } + } + + extern "C" fn bmap_callback(mapping: *mut bindings::address_space, block: u64) -> u64 { + // SAFETY: `mapping` is just forwarded from C and `Self::MAP_TABLE` is always valid. + unsafe { bindings::iomap_bmap(mapping, block, &Self::MAP_TABLE) } + } +} + +/// Returns address space oprerations backed by iomaps. +pub const fn aops() -> address_space::Ops { address_space::Ops(&Table::::TABLE, PhantomData) } + +pub const fn map_table() -> &'static bindings::iomap_ops { + return &Table::::MAP_TABLE; +} From 994c5046367e62146eb4092abb1bd1dd943b0393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Tue, 2 Dec 2025 14:23:57 -0500 Subject: [PATCH 055/131] add no-op iomap writeback ops to avoid kernel WHOOPSIE --- rust/kernel/iomap.rs | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/rust/kernel/iomap.rs b/rust/kernel/iomap.rs index ab5bf9037359f0..d79d6a059276d3 100644 --- a/rust/kernel/iomap.rs +++ b/rust/kernel/iomap.rs @@ -205,16 +205,36 @@ pub trait Operations { struct Table(PhantomData); impl Table { + const WRITEBACK_TABLE: bindings::iomap_writeback_ops = bindings::iomap_writeback_ops { + writeback_range: Some(Self::writeback_range_callback), + writeback_submit: Some(Self::writeback_submit), + }; + + extern "C" fn writeback_range_callback( + _wpc: *mut bindings::iomap_writepage_ctx, + _folio: *mut bindings::folio, + pos: u64, + len: u32, + end_pos: u64, + ) -> isize { + from_result(|| { + pr_info!("writeback_range()\n"); + Ok(len.try_into()?) + }) + } + + extern "C" fn writeback_submit(_wpc: *mut bindings::iomap_writepage_ctx, _error: i32) -> i32 { + from_result(|| { + pr_info!("writeback_submit()\n"); + Ok(0) + }) + } + const MAP_TABLE: bindings::iomap_ops = bindings::iomap_ops { iomap_begin: Some(Self::iomap_begin_callback), iomap_end: Some(Self::iomap_end_callback), }; - const WRITEBACK_TABLE: bindings::iomap_writeback_ops = bindings::iomap_writeback_ops { - writeback_range: None, - writeback_submit: None, - }; - extern "C" fn iomap_begin_callback( inode_ptr: *mut bindings::inode, pos: Offset, From c91902373688aa2d9c5c573e5823ce76b084f422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Tue, 2 Dec 2025 14:34:42 -0500 Subject: [PATCH 056/131] add simplest write case (WriteType::WITHIN) --- fs/rustezfs/ezfs.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 45a1f025a31b8d..8dafd99c2269f2 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -381,6 +381,9 @@ impl iomap::Operations for RustEzFs { pr_info!("WRITING\n"); + let blocks_needed = end_block + 1; + let blocks_to_add = blocks_needed - ez_blk_count; + // // Shifted physical index // let phys_sidx: i64 = if ez_blk_num > 0 { // // phys should always be >= root datablock number @@ -388,6 +391,50 @@ impl iomap::Operations for RustEzFs { // } else { // -1i64 // }; + // + pr_info!( + "blocks: needed={blocks_needed}, to_add={blocks_to_add}, ez_blk_num: {ez_blk_num}\n" + ); + pr_info!("CASE\n"); + + enum WriteCase { + NEW, // Write to an empty file without any allocated blocks + WITHIN, // File can fit written contents within allocated, unused block + EXTEND, // File has adjacent, free block to extend to + MOVE, // File has no adjacent, free block and must be moved + } + + let case_type = if ez_blk_num == 0 { + pr_info!("file has no blocks\n"); + WriteCase::NEW + } else { + let ez_blk_sidx = ez_blk_num - TryInto::::try_into(EZFS_ROOT_DATABLOCK_NUMBER)?; + + if blocks_to_add <= 0 { + pr_info!("inside: don't need additional blocks to perform write\n"); + WriteCase::WITHIN + } else { + pr_info!("extend: we need to allocate blocks\n"); + WriteCase::MOVE + } + }; + + match case_type { + WriteCase::NEW => { + pr_info!("creating a file\n"); + } + WriteCase::WITHIN => { + pr_info!("easiest write\n"); + + return Ok(()); + } + WriteCase::EXTEND => { + pr_info!("semi easy writ\n"); + } + WriteCase::MOVE => { + pr_info!("Hardest write\n"); + } + } Err(EIO) } From 1d2e17370aa5e9f5cca33906fab6cc6dbf22ee10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Tue, 2 Dec 2025 15:46:15 -0500 Subject: [PATCH 057/131] set iomap fields on successful writes --- fs/rustezfs/ezfs.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 8dafd99c2269f2..5b3eff7f4baeee 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -422,21 +422,25 @@ impl iomap::Operations for RustEzFs { match case_type { WriteCase::NEW => { pr_info!("creating a file\n"); + return Err(EIO); } WriteCase::WITHIN => { pr_info!("easiest write\n"); - - return Ok(()); } WriteCase::EXTEND => { pr_info!("semi easy writ\n"); + return Err(EIO); } WriteCase::MOVE => { pr_info!("Hardest write\n"); + return Err(EIO); } } - Err(EIO) + map.set_type(iomap::Type::Mapped) + .set_addr(phys << sb.blocksize_bits()); + + Ok(()) } fn end<'a>( From 9f5bbf5758799ce130a6a0c37e05c1e7cbdf41bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Tue, 2 Dec 2025 22:04:41 -0500 Subject: [PATCH 058/131] updated format_disk_as_ezfs --- fs/rustezfs/format_disk_as_ezfs | Bin 67568 -> 70992 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/fs/rustezfs/format_disk_as_ezfs b/fs/rustezfs/format_disk_as_ezfs index 14f0c8605fc7df0cdb14c771f9bf21ec01cfe196..4e73e5a04fee4109862d2eec65fa5934728ee919 100755 GIT binary patch literal 70992 zcmeHMeQ;dWbw9f+W7(GNwIMO#%g?eCjEUEuF&Hpj$(Cgme}EB5n~!;V+I^BXUhQsn zpTNcrY}^cGLfi2M3LTnImvmC&NiuFiQ!7J)0@Id4hH=ElkThXdf}|uQQzy_iTM*lG z?z?Ao_i5Mm^p8$wdY;CS?d;4^E*RCDmPzd;nz~2LD@p(QH*B#LX(>8Iq z7Un`6E{DtD0_<AprH+3uq(L5;@$ zpK66E?KPz%Y8j=1@VZz__M`I1FRJ~bY|s9>e$bM~M`NQqr}3a%fqitbBwM;j(*5Ex z(q_t|J`60`@8+L*Nox05zClp-YCo3jcMJL{UUdJtL{uB>)A^e5sV10gHJ_SoHMWa1 z+`Z>EIR4PrpMCYtH$MEtGWXu`BY$%0?f5+_*Q8VZYtqTp=~QOqz-q_ICx$j{j1{u6 zb^feSERIJh&i9Josy#kurga3CAjlKx_iskAc%~_AY=ZA?f)lrm;=GQyg?I3B5NHpA zsJ{>IMsXf&g6Epxzt;rsYJ%V11Yh0+|7;VSCd|UV;PoX076n1nzkqk6@zT0)gk$)I zc)STdzX`suNu7V##2#`ZUIB7$KA+7)!OLe7xr2~MXA}GFLD%zA!!Fo%!E;bg4DGiE zoKzaz11XPe({2Xxu9Jjp4qJ|wO`$EW{RBDWJ$u+mWe`amaO{Cp#!08{bYY-yFq42` zcevnsl&9cAE}zPH18_$^<+S z`wU#aVyNCB1J~3mJZIpVdW9b_@C8QvqJb|o@OurM*9vtXHE@&vKR56TjX1{)oStKR z9XD_~tNA)<;O}P;mQ5Q^BdAXr`lG0ax2Rak z{;R0B8~O>DQA7U@>Q5Q^_fVfS^ruh{-#DHBA5m{N^k-4; zH1y|D?>F>u)Q=eY%cwtU=s!mNDMNo1^+`jYL_NG!Oo7P*QLN#(NlS|MR>*<8hn^aF6$I^}QrVed;4C^n^IBHxigi1K7>&1MV z(asz%p9k~TK0IDctbVQ<30KMsk>3c`pvOM3Azlh&zV;_tD`CtB#P6|K3Fo1r+GT7n zNBep45|n3^LU3e!64w)PbUE>{5a+24J~PJiR9sV9gE&BO@%0h7sEq5K)+b<&Ib@IX z%k%Vg^qIgp1NftTxNi6VGsoy#Te?EWSj90cKSl@Uedj%lvmE0r$J{Nj4%e)|M#k2b zeu90J`!e!-Z5EF0h?>veB2K<)O!0N4Us8-KF~*g_80$*U=@|1U#u9(rVK_QY^Go(B z|CPuIwqI9q;uWmpZ_Bg)@)G>XyLd7Jt0+&%T3;$h!mE04EVbOl^(ubD+~xJ9uj$;s z3S;htocr^&+%&%O)qd`OQ0*qU;~P}&RhS$1!g%>foX_R=j+dWC-=)RT@;|BhJss-9 zz3_CnbOVfS+0rt$<;K>rEnC~hwk)&amCK;GR7M0?aaS-b=e&${q69CzR0`2AqbF2UP(y)g0Ctdcd{(0TTicdNaWcL4J$oX)e~-TeZ--Q7odCb9mBuY^i* zfct1ILu-7r9iU>-zTB^3-h!Nsmajfb%~4!mRCDA4zh<;;ShHcLYR<+-%WE)pAwD{> zCO&Eb%qwp|9oywgVRSulbt%@+3b&N6LHwGt)Ie*TYQS}?cthKUH5hiPhO@>D%tavP zL}b}2oR7J|c~fzzZki7q#{{;^8{(t1Pw%T#d(F9`_R@>sGgrNZxZZPWui*Y%L2Gmk zuDLa|PUF8RFR9xjM?=T_by_4loWqAmZoPM3c|VNy;d&|G52JBfzk6xD9vLs+it|eP z$1o<^(|OIg=9syx(9B%0QSAv==Q@lMW2qctn~ri$l?%_P%6F%*mb2vhHTCn@8s+Qr z^Y!R_eI)hRa7-$1@jS;iey&_&ey*6#)zx5Z$8;_{H!Js?V{G3(S3c__ip#}1-&GCr zjd8v!;}zl&LXGF`FV2;#=;!)RvcoxF&?pzh#x+vD+RugjHe4gcbLE0fYFs}-J36mI z&wg&4o-_LlzjDMn0r<{job^XTeZJrGWcOO6w1jv;8Ce0P$pz}UdNedfHjxuqw6SRZ zBQ2X%op)p1XiLv>Udtaf@-2mMgSC8(s`HyV-#c2?cPEz_AzW$W4MKC!1;Sv z%epz}Bb&&H-(ozT^J0@Z_>s=3&dNq}e$3DJ5uN9*M)|DkRKAyue8-yP`|i2&^--+w zst@Qq{f+XK{e0gs@{Kjg_gCl2XI-!IO`#o}KKmN`QyuH9^K;CP_Y1PcGp~naqcw(o zU%$9Ro_=t zeMiUf-SwP%;3H<-X8U-|k9(BrqqA4PvzqlSH{+m9!}|JeRQ27Z>ihgSo#W@)qw~$U z&FU-rafiqj&x_aJ!L^0&sI})dz|6C?Z>y^16WZrZ^ijWK^luP4=Kwzq!PwRkpbg+z zj@YU)z-jtD`5OMFN9Y3TWRcv_(X)%>Cq7vCl=Z>FTx!#`(@m$d)*ab=I=PI%uHj+F+LLmJuD3p( z`gF?4SRWs9GK1G!JDvQ<{*=|7%{VDEysh92y4P8;H3QlFu;bauRAImE6m0j-fr7QY z>!Ur}y6in2ySuFIJ-6Oucka6B)|krIlerx~I46TJbkT=yi#}MVGJ}>kRWr`V=~{q%L7>+$h?HtSibOg32?hmQ{t>y)q7$#MFVseBE@ zU_PF4hTTE~d*XzdFumB1`Z0^)c`JUvw{lKFXSO``wH=^Vksg4bH;HWJ4_Y|KR=}Vz zLX~nJ!%lbHjI?`M%grRM?0}_sP(~@2*k`|5P?J*Cul+MFazwLkX?AN&C@YR*;nb{V=BW89s&mSe{Y$tEG+?|48uMB<_nu!YvdAM$+knF?HsI z(3Vanmh?9TYLleDBT$nMT=)!8iW8T3w0qlPGsmGQ6U`fY6=$pyj|7p-bDA zD(qs!)0k%?^>@s^g6uww_bJ5I5{4IHalBtd>;{x{t-zb=d>65s3FuhevB3Ir%OjD_ z`@?%){pkw}5JC7Nybt5O5^Fa94ssb{G?t4IPof0v{jpbns{TAd{g31QN$h{d?~iwU zIs8Z{`_os+fcjs=y9LL*((hNu>bgcY;-J$lKZv=N52w@BqIx=9oo{L z7aAi`MSo+bi{_309!2xkhxc8Vy!Y&m?R()+yLT|>wqMttbo<*s+@399bEJPHM}Mft^_K8P^5o*=hc|6(r#}eGB@74y z!hkR!3~xd`}HStHv+U zvQ_tA#=4gO{$4dp&68mtn5FT!Zd{=C)4G4I*00iq&eQtETE0(977^WuR(%H@2Flw1 zBHce*%OzSqqXEXx=t6j0uV_0>3vm7`G|qPKRQ>T`It9I_^_gA#u zqT~K=iPL&u|5s&HucveI@dPi}fMF~6jCXI_cAd5Iw*HZfH)5^Z7+W7(yL#Q`5v8xc zN+SVZQ}vfo8^n1b>P~;YqVNODv)W@VTieGv4CbV3KJb37$LGQ+Uf{Ze?Q>1)ITomg_5;-u#4U}V4%qwSU4om1 zcZ8pKgSO{$%SQovuo1%D7uEKDea!Pkz~>Iz-=^$m;)fBZI{AELd%vCwfzLO_?^SVT z;=X+p$`)Jt(#NOkKk*l9Z)g3{mA83e2YR`fCI4!{E ze?2}6_&HIJUjTf5*5k8*&)s^w75IFw$L9b)2kP;e`-u7@(2R$f=YwxQbKm*+%>C}; zGv~#}qj1WiR{a$*&J(jI0*m48z&fG+2+Um1K0b55`1t!ExPE;6{lL##()o%2JzZx` ze8kwlY)di%wYQ5J{IA$rT+^l-l_vNcT%e8YKhy-j7IAAjY^~LTWm^sE??wA)gZlds zZ?AbzHx47-sGi4loQnhe{F%a+)Xq1K^ra?ozD{^}=DPY;llV_IiF3LMUT%V)X@ZB5 zw`c?279!q=hpU_5Hz02D;0<{b;`Gc5UPCHQ8$6(&|0}h@NR#;YP@M40=g$32?EjkV zVS1nX=Q6;zn%F4slvP!Fg}h_WWM4QQOlw*vS4Bjq`Jm`FLH&;rF29 znvY*7oUNv1Mce;CKX;zdU9<2-n)nIEUxaw0d0c_GH66Cry0MA<&4h;=oU1Diz=|Z; zw$q=oJ!cRSPC9Mh;X3>6fea+wygQgGcy8YIhV4W;n{f+ho6OpS>1@A~wv%2qU$C8# z1CYoL=hCj{CSz+GTi64sOv-lhdFP<*X1x4C7|1)ruALki9zKXJhGwIsS7&P5JN9+# z?y|e~Y`1N&xBtPOj@>=m(5rjTZFbjA-Me%9KCruY?d|N?W$)dwc2d*E8#Y4D&F8cEI`f|1-S#v+ zy}P#&IlWGQ+Qq8+3k4ksi?tI692&fnPTlF6F_6#1etXdMywq@AhwUaE&w+Hob@!VN zib5UU%_NbDfx^K|!ZdNbY|7NLx%y!byTb)HFmOudmy5BH04ypog!AvD(qurOr@TON1m($)3YHqM`3Tewm(iQGXmflYJG z8=-EdbNN)p8>q9Tr3(-%931wXew1F`mqXmjWIZ=Fm>G%nkEGJc)u|-JFo>JafkKCz z!Vtug2QwJKmtNlQx!uhdQrS$MVq;(4O*`bETe-AH5wVJx=N`cSY2RUAR;{U+JEV8o zP!fGvgP1C-qqAo<9Rj|V!f1}BjEfeb%P~; zZ{fV^BZLtkj&1r0#{Q>ugJn+Z^f?BP=-PK3{@$@ut{QbpF)57rouYE-?OCnbW#0e6C8gUF^bLp{5yapf9K)+?9b!BUHf;U zq>Fzquq^8VlmGki4*C}nBNP74#oyUj^8BHRy0{M34`IXf=igy0`vQbV*-^`T0{;BI z!E!~wAs+Dm zi1YLBD3+H6_zUL$CiMV;QSY#&$-KxGoPmJPII{|^Ol z_BSQ3J=64Bo&SLT{zlJ%>+$CLd0$aC*KYcsq#wR`eKgR?dD)hJI|WQs*9G%^%hrHH HK!yJX9KB&j delta 3444 zcma)9eQXnD7=PbuaT_0H?TTgVSa0i6W*M;Qz%78>G7||($Z$X~M4Dg>37{-7MkAqh z5JL=xoi}rkATGqjr7>i48ksRT5&{DewnF@a&)d`lm5-SKS_9PI^WI%)M+aVV`Q1Gq zzu)sd&)wVWVB9&n+u2^_tKpp4hr;UFM5Zu5D^VA#6ZgrcW1p;^KkS)o-911p&O@F( zWoFO=)JFJz@4A66LzhQe?w>DP`?vPXyVGu8Jn?*Qhjgc4MwRMd%!{OMrc|jTla%DJ zgT=*tq^kFe$z_~ZYR9GoL%Z^m5{o5-r?W~mida%y8@Tqdq%lcRS;VPLbp@kOsdG~) zow1nbqQtz0LrG#4Dq~8r0Cq(889t>iz*y@k##&6Ruv%f|oUwCcGpCWoR;2DD&yPGm z@|>*ph@ICTRt@+_>j>qocdAm9wIw)`?!ZCGLO_|N-XM|yNCIO?W~pZ^l5QgLiKVC# zYfn%!DBda{N!M42$FC$&NRN^CSqUp;o)HHNlMa`w)u`c+!ppFlw0Nvq2;>wus?}~w z9Ex6Jsx7`FElw*$t`I*VuE!BqW~Iv6s`7@&q2VHJo7-1gh?d{lc6J!niVgB1qe$svPUbd{L)QT>YyIhNswIoV zuWfec7ohQJo?3Wp%ZkcZ!9DuTWeQS81}w z;+-pumswu~6E@yseG09&i5|+fM96r7B}D^X1St}vf>>H?Lt0FG!|Pka=1|YVM=k0L zKx7Ka{`u{;grG(XlBE>)2=m~JV3muhA9dU^bubuZ(j3a&;T%yU_r3O*ea#V>NsW6s^+7I(L8G->OJ^V1U zT2ZLm5_%<1S!hslbEzmd?+&NDYEkquuPe1bL8PP->&urZ5uQOsmL1}n$g zYM>UGu^-dSIqF)O#qcV7M%2|!R`fq)Jd%ssFu98}xckT9X4%{iKWg$k(WkYDV}t3* z2Xc=7`du^=@2NHVPBV20NnrozB5$tI!}mLUYLImq&vef8IF?`uTm3`ZB;aylo8Y}mrS44ASAxC z0+tfeCztj4L~k~}Oxjt0gSt*D_fMa(YYD#Ol;jR3{YhVR3cjW4L=q2Asnk~aL%lKo zUgt8uV*!1e72xc;mP%~`=3h^xV!(P}2kaILM~p+y~o2ARU!Bsf?r7G*5XbIto`l*{!1#NR=3{ zzecu3m;9-7zhm{~OD?)4|JOJxQP}_)8eK}`r_z4@=B3LNK>l+$Pr+XWwDXr(`6Pb} z=Q;SRCsT!uu0qOha&;eYI41NSFK@We8><-LAKzOdT`lfidhfdQt#1l%;Czza?Ba`g znXVFq^dW*8-8~ghuQvlU!|BvJrt*b+nLb43wYs|y@Veeiutir1HtItFO-8KO%}X1* z#LB2x^HA&y3%3H%boPXGe-)p5bl5muZ*}oNc^ga=CXtVh5)*9vMDKAU>_b>H!yf#z zFvD8}Tgjd=VWZX`k Date: Tue, 2 Dec 2025 22:05:37 -0500 Subject: [PATCH 059/131] add extend writing (adjacent blocks free) --- fs/rustezfs/ezfs.rs | 37 ++++++++++++++++++++++++++++--- fs/rustezfs/sb.rs | 53 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 84 insertions(+), 6 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 5b3eff7f4baeee..ba8d909f56d8b4 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -350,9 +350,13 @@ impl iomap::Operations for RustEzFs { let start_block: u64 = (pos >> sb.blocksize_bits()).try_into()?; let end_block: u64 = ((pos + length - 1) >> sb.blocksize_bits()).try_into()?; + pr_info!("start_block: {start_block}, end_block: {end_block}\n"); + let ez_blk_num = ezfs_inode.data_blk_num(); let ez_blk_count = inode.blocks() / 8; + pr_info!("blk_num: {ez_blk_num}, ez_blk_count: {ez_blk_count}\n"); + let phys = if ez_blk_num > 0 { ez_blk_num + start_block } else { @@ -381,6 +385,7 @@ impl iomap::Operations for RustEzFs { pr_info!("WRITING\n"); + // TODO: find the max number of blocks let blocks_needed = end_block + 1; let blocks_to_add = blocks_needed - ez_blk_count; @@ -404,6 +409,8 @@ impl iomap::Operations for RustEzFs { MOVE, // File has no adjacent, free block and must be moved } + let mut free_data_blocks = ezfs_sb.free_data_blocks.lock(); + let case_type = if ez_blk_num == 0 { pr_info!("file has no blocks\n"); WriteCase::NEW @@ -415,7 +422,27 @@ impl iomap::Operations for RustEzFs { WriteCase::WITHIN } else { pr_info!("extend: we need to allocate blocks\n"); - WriteCase::MOVE + + let can_extend = true; + let start = ez_blk_sidx + ez_blk_count; + let limit = ez_blk_sidx + blocks_needed; + + // TODO: Check if limit extends beyond the final block + + pr_info!("start={start} - limit={limit}\n"); + + // REMOVE, just for debugging + for s in start..limit { + if free_data_blocks.is_set(s.try_into()?) { + pr_info!("s={s} is_set, we can't expand\n"); + } + } + + if (start..limit).any(|bit| free_data_blocks.is_set(bit)) { + WriteCase::MOVE + } else { + WriteCase::EXTEND + } } }; @@ -428,8 +455,12 @@ impl iomap::Operations for RustEzFs { pr_info!("easiest write\n"); } WriteCase::EXTEND => { - pr_info!("semi easy writ\n"); - return Err(EIO); + pr_info!("semi easy write\n"); + for bit in ez_blk_count..blocks_needed { + free_data_blocks.set_bit(bit); + } + + map.set_flags(iomap::map_flags::NEW); } WriteCase::MOVE => { pr_info!("Hardest write\n"); diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index 3637cdfa3ad8c8..0da917c95e22bc 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -2,12 +2,13 @@ use crate::defs::{EZFS_BLOCK_SIZE, EZFS_MAX_DATA_BLKS, EZFS_MAX_INODES}; use crate::inode::InodeStore; use crate::RustEzFs; use core::mem::size_of; +use core::ops::{Deref, DerefMut}; use kernel::fs::FileSystem; -use kernel::inode; use kernel::new_mutex; use kernel::prelude::*; use kernel::sync::Mutex; use kernel::transmute::FromBytes; +use kernel::{block, inode}; #[repr(C)] pub(crate) struct EzfsSuperblockDiskRaw { @@ -36,6 +37,52 @@ impl EzfsSuperblockDisk { // which accept any bit pattern. The struct is #[repr(C)] for consistent layout. unsafe impl FromBytes for EzfsSuperblockDisk {} +#[repr(transparent)] +pub(crate) struct Bitmap { + inner: [u32; N], +} + +impl Bitmap { + #[inline] + pub(crate) fn is_set(&self, block_num: u64) -> bool { + let idx: usize = (block_num / 32) as usize; + let mask = 1 << (block_num % 32); + (self.inner[idx] & mask) != 0 + } + + #[inline] + pub(crate) fn set_bit(&mut self, block_num: u64) -> () { + let idx: usize = (block_num / 32) as usize; + let mask = 1 << (block_num % 32); + self.inner[idx] |= mask + } + + #[inline] + pub(crate) fn clear_bit(&mut self, block_num: u64) -> () { + let idx: usize = (block_num / 32) as usize; + let mask = 1 << (block_num % 32); + self.inner[idx] &= !mask + } + + const fn new(inner: [u32; N]) -> Self { + Self { inner } + } +} + +impl Deref for Bitmap { + type Target = [u32; N]; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for Bitmap { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} + #[pin_data] pub(crate) struct EzfsSuperblock { pub(crate) version: u64, @@ -44,7 +91,7 @@ pub(crate) struct EzfsSuperblock { #[pin] pub(crate) free_inodes: Mutex<[u32; (EZFS_MAX_INODES / 32) + 1]>, #[pin] - pub(crate) free_data_blocks: Mutex<[u32; (EZFS_MAX_DATA_BLKS / 32) + 1]>, + pub(crate) free_data_blocks: Mutex>, #[pin] pub(crate) zero_data_blocks: Mutex<[u8; (EZFS_MAX_DATA_BLKS / 32) + 1]>, pub(crate) mapper: inode::Mapper, @@ -60,7 +107,7 @@ impl EzfsSuperblock { magic: disk_sb.data.magic, disk_blocks: disk_sb.data.disk_blocks, free_inodes <- new_mutex!(disk_sb.data.free_inodes), - free_data_blocks <- new_mutex!(disk_sb.data.free_data_blocks), + free_data_blocks <- new_mutex!(Bitmap::new(disk_sb.data.free_data_blocks)), zero_data_blocks <- new_mutex!(disk_sb.data.zero_data_blocks), mapper, }) From b155702da906d67890f35aa378ed226ccbb01728 Mon Sep 17 00:00:00 2001 From: lsig Date: Tue, 2 Dec 2025 23:26:16 -0500 Subject: [PATCH 060/131] [VFS/ezfs] create file checkpoint --- fs/rustezfs/ezfs.rs | 75 ++++++++++++++- fs/rustezfs/inode.rs | 62 +++++++++++- rust/helpers/fs.c | 5 + rust/helpers/task.c | 5 + rust/kernel/inode.rs | 221 +++++++++++++++++++++++++++++++++++++++++-- rust/kernel/sb.rs | 10 +- rust/kernel/task.rs | 38 +++++++- 7 files changed, 405 insertions(+), 11 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 755fae6c0ba763..a7ea9e87079837 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -20,7 +20,9 @@ use kernel::inode::{INode, INodeState, Mapper, Params, Type}; use kernel::iov::IovIterDest; use kernel::prelude::*; use kernel::sb::{New, SuperBlock, Type as SuperType}; -use kernel::time::UNIX_EPOCH; +use kernel::task::{Kgid, Kuid}; +use kernel::time::hrtimer::HrTimerExpires; +use kernel::time::{Instant, Monotonic, NSEC_PER_SEC, UNIX_EPOCH}; use kernel::transmute::FromBytes; use kernel::types::{ARef, Lockable, Locked}; use kernel::{address_space, iomap}; @@ -85,7 +87,7 @@ impl RustEzFs { inode.set_iops(Self::IOPS).set_aops(Self::AOPS); - inode.init(Params { + inode.init_from_disk(Params { typ, mode: ezfs_inode.mode().try_into()?, size: ezfs_inode.file_size().try_into()?, @@ -98,6 +100,63 @@ impl RustEzFs { atime: ezfs_inode.atime()?, value: ezfs_inode, }) + // TODO: move unlock_new_inode from instantiate + } + + fn new_inode( + dir: &Locked<&INode, kernel::inode::ReadSem>, + mode: u32, + ) -> Result> { + let sb = dir.super_block(); + let mut new_inode = sb.new_inode()?; + + let ino = 0; // TODO + + let typ = match mode & fs::mode::S_IFMT { + fs::mode::S_IFREG => { + new_inode.set_fops(Self::FILE_FOPS); + Type::Reg + } + fs::mode::S_IFDIR => { + new_inode.set_fops(Self::DIR_FOPS); + Type::Dir + } + _ => return Err(ENOENT), + }; + + let (uid, gid) = new_inode.init_owner(dir, mode.try_into()?); + + new_inode + .set_iops(Self::IOPS) + .set_aops(Self::AOPS) + .set_ino(ino); + + let now = Instant::::now().as_nanos() / NSEC_PER_SEC; + let mut ezfs_inode = EzfsInode::default() + .set_mode(mode.try_into()?) + .set_uid(Kuid::from_raw(uid).into_uid_in_init_ns()) + .set_gid(Kgid::from_raw(gid).into_gid_in_init_ns()) + .set_atime(now) + .set_mtime(now) + .set_ctime(now); + + let mut ready_inode = new_inode.init_new(Params { + typ, + mode: ezfs_inode.mode().try_into()?, + size: ezfs_inode.file_size().try_into()?, + blocks: ezfs_inode.nblocks() * 8, + nlink: ezfs_inode.nlink(), + uid: ezfs_inode.uid(), + gid: ezfs_inode.gid(), + ctime: ezfs_inode.ctime()?, + mtime: ezfs_inode.mtime()?, + atime: ezfs_inode.atime()?, + value: ezfs_inode, + })?; + + ready_inode.mark_dirty(); + + Ok(ready_inode) } } @@ -185,6 +244,18 @@ impl kernel::inode::Operations for RustEzFs { dentry.splice_alias(inode) } + + fn create( + parent: &Locked<&INode, kernel::inode::ReadSem>, + dentry: dentry::Unhashed<'_, Self::FileSystem>, + mode: u16, + _excl: bool, + ) -> Result { + let new_inode = Self::new_inode(parent, mode.into())?; + + new_inode.instantiate_dentry(&dentry); + Ok(0) + } } #[vtable] diff --git a/fs/rustezfs/inode.rs b/fs/rustezfs/inode.rs index 642448e1a72922..2e51ac0f7fc58e 100644 --- a/fs/rustezfs/inode.rs +++ b/fs/rustezfs/inode.rs @@ -6,7 +6,7 @@ use kernel::transmute::FromBytes; use kernel::uapi::{gid_t, mode_t, uid_t}; #[repr(C)] -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Default)] pub(crate) struct EzfsInode { mode: mode_t, uid: uid_t, @@ -60,6 +60,66 @@ impl EzfsInode { pub(crate) fn nblocks(&self) -> u64 { self.nblocks } + + pub(crate) fn set_mode(mut self, mode: u32) -> Self { + self.mode = mode; + + self + } + + pub(crate) fn set_uid(mut self, uid: u32) -> Self { + self.uid = uid; + + self + } + + pub(crate) fn set_gid(mut self, gid: u32) -> Self { + self.gid = gid; + + self + } + + pub(crate) fn set_atime(mut self, tv_sec: i64) -> Self { + self.i_atime = tv_sec; + + self + } + + pub(crate) fn set_mtime(mut self, tv_sec: i64) -> Self { + self.i_mtime = tv_sec; + + self + } + + pub(crate) fn set_ctime(mut self, tv_sec: i64) -> Self { + self.i_ctime = tv_sec; + + self + } + + pub(crate) fn set_nlink(mut self, nlink: u32) -> Self { + self.nlink = nlink; + + self + } + + pub(crate) fn set_data_block_num(mut self, data_block_num: u64) -> Self { + self.data_blk_num = data_block_num; + + self + } + + pub(crate) fn set_file_size(mut self, file_size: u64) -> Self { + self.file_size = file_size; + + self + } + + pub(crate) fn set_nblock(mut self, nblocks: u64) -> Self { + self.nblocks = nblocks; + + self + } } #[repr(C)] diff --git a/rust/helpers/fs.c b/rust/helpers/fs.c index d13ffd2407cb0c..416bd7022092a7 100644 --- a/rust/helpers/fs.c +++ b/rust/helpers/fs.c @@ -37,3 +37,8 @@ void *rust_helper_alloc_inode_sb(struct super_block *sb, { return alloc_inode_sb(sb, cache, gfp); } + +void rust_helper_mark_inode_dirty(struct inode *inode) +{ + mark_inode_dirty(inode); +} diff --git a/rust/helpers/task.c b/rust/helpers/task.c index 2c85bbc2727efe..fe8bd30b9b679d 100644 --- a/rust/helpers/task.c +++ b/rust/helpers/task.c @@ -45,6 +45,11 @@ bool rust_helper_uid_eq(kuid_t left, kuid_t right) return uid_eq(left, right); } +bool rust_helper_gid_eq(kgid_t left, kgid_t right) +{ + return gid_eq(left, right); +} + kuid_t rust_helper_current_euid(void) { return current_euid(); diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index ca0374b127edf2..d09793b2dd843a 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -1,16 +1,17 @@ use core::marker::PhantomData; use core::mem::{ManuallyDrop, MaybeUninit}; +use bindings::{init_user_ns, kgid_t, kuid_t}; use macros::vtable; use crate::address_space; use crate::dentry::{self, DEntry}; -use crate::error::{from_err_ptr, Result}; +use crate::error::{from_err_ptr, from_result, Result}; use crate::folio::{self, Folio}; use crate::fs::{self, mode, Registration}; use crate::fs::{file, PageOffset, UnspecifiedFS}; use crate::mem_cache::MemCache; -use crate::prelude::{EIO, ENOTSUPP, ERANGE, GFP_KERNEL}; +use crate::prelude::{EINVAL, EIO, ENOTSUPP, ERANGE, GFP_KERNEL}; use crate::sb::SuperBlock; use crate::str::CString; use crate::time::Timespec; @@ -55,6 +56,15 @@ pub trait Operations { ) -> Result>>> { Err(ENOTSUPP) } + + fn create( + _parent: &Locked<&INode, ReadSem>, + _dentry: dentry::Unhashed<'_, Self::FileSystem>, + _mode: u16, + _excl: bool, + ) -> Result { + Err(ENOTSUPP) + } } /// A node (inode) in the file index. @@ -65,9 +75,11 @@ pub trait Operations { /// /// Instances of this type are always ref-counted, that is, a call to `ihold` ensures that the /// allocation remains valid at least until the matching call to `iput`. -// TODO: should be default UnspecifiedFS #[repr(transparent)] -pub struct INode(pub(crate) Opaque, PhantomData); +pub struct INode( + pub(crate) Opaque, + PhantomData, +); impl INode { /// Creates a new inode reference from the given raw pointer. @@ -83,6 +95,10 @@ impl INode { unsafe { &*ptr.cast::() } } + pub(crate) const fn as_raw(&self) -> *const bindings::inode { + unsafe { self.0.get() as *const bindings::inode } + } + /// Returns the number of the inode. pub fn ino(&self) -> Ino { // SAFETY: `i_ino` is immutable, and `self` is guaranteed to be valid by the existence of a @@ -179,6 +195,13 @@ impl INode { }) } + pub fn mark_dirty(&self) { + // SAFETY: This is safe since it is guaranteed by the typestate + // that the inode has been inserted into the hash + let inode = unsafe { self.0.get() }; + unsafe { bindings::mark_inode_dirty(inode) }; + } + unsafe extern "C" fn inode_init_once_callback(outer_inode: *mut core::ffi::c_void) { let ptr = outer_inode.cast::>(); @@ -341,7 +364,7 @@ pub struct New( impl New { /// Initialises the new inode with the given parameters. - pub fn init(self, params: Params) -> Result>> { + pub fn init_from_disk(self, params: Params) -> Result>> { let outerp = unsafe { container_of!(self.0.as_ptr(), WithData, inode) }; // SAFETY: This is a newly-created inode. No other references to it exist, so it is @@ -437,6 +460,108 @@ impl New { Ok(unsafe { ARef::from_raw(manual.0.cast::>()) }) } + // Instantiated new inode with data but keep it locked + pub fn init_new(self, params: Params) -> Result> { + let outerp = unsafe { container_of!(self.0.as_ptr(), WithData, inode) }; + + // SAFETY: This is a newly-created inode. No other references to it exist, so it is + // safe to mutably dereference it. + let outer = unsafe { &mut *outerp }; + + // N.B. We must always write this to a newly allocated inode because the free callback + // expects the data to be initialised and drops it. + outer.data.write(params.value); + + let inode = &mut outer.inode; + let mode = match params.typ { + Type::Dir => bindings::S_IFDIR, + Type::Reg => { + // SAFETY: The `i_mapping` pointer doesn't change and is valid. + unsafe { bindings::mapping_set_large_folios(inode.i_mapping) }; + bindings::S_IFREG + } + Type::Lnk(str) => { + // If we are using `page_get_link`, we need to prevent the use of high mem. + if !inode.i_op.is_null() { + // SAFETY: We just checked that `i_op` is non-null, and we always just set it + // to valid values. + if unsafe { + (*inode.i_op).get_link == bindings::page_symlink_inode_operations.get_link + } { + // SAFETY: `inode` is valid for write as it's a new inode. + unsafe { bindings::inode_nohighmem(inode) }; + } + } + // TODO: Look into this + // if let Some(s) = str { + // inode.__bindgen_anon_5.i_link = s.into_foreign().cast::().cast_mut(); + // } + bindings::S_IFLNK + } + Type::Fifo => { + // SAFETY: `inode` is valid for write as it's a new inode. + unsafe { bindings::init_special_inode(inode, bindings::S_IFIFO as _, 0) }; + bindings::S_IFIFO + } + Type::Sock => { + // SAFETY: `inode` is valid for write as it's a new inode. + unsafe { bindings::init_special_inode(inode, bindings::S_IFSOCK as _, 0) }; + bindings::S_IFSOCK + } + Type::Chr(major, minor) => { + // SAFETY: `inode` is valid for write as it's a new inode. + unsafe { + bindings::init_special_inode( + inode, + bindings::S_IFCHR as _, + bindings::MKDEV(major, minor & bindings::MINORMASK), + ) + }; + bindings::S_IFCHR + } + Type::Blk(major, minor) => { + // SAFETY: `inode` is valid for write as it's a new inode. + unsafe { + bindings::init_special_inode( + inode, + bindings::S_IFBLK as _, + bindings::MKDEV(major, minor & bindings::MINORMASK), + ) + }; + bindings::S_IFBLK + } + }; + + inode.i_mode = (params.mode & 0o777) | u16::try_from(mode)?; + inode.i_size = params.size; + inode.i_blocks = params.blocks; + + inode.i_ctime_sec = params.ctime.tv_sec(); + inode.i_ctime_nsec = params.ctime.tv_nsec()?; + inode.i_mtime_sec = params.mtime.tv_sec(); + inode.i_mtime_nsec = params.mtime.tv_nsec()?; + inode.i_atime_sec = params.atime.tv_sec(); + inode.i_atime_nsec = params.atime.tv_nsec()?; + + // SAFETY: inode is a new inode, so it is valid for write. + unsafe { + bindings::set_nlink(inode, params.nlink); + bindings::i_uid_write(inode, params.uid); + bindings::i_gid_write(inode, params.gid); + } + + // SAFETY: inode is new and I_NEW is set, insert into hash + let ret = unsafe { bindings::insert_inode_locked(inode) }; + if ret != 0 { + return Err(EINVAL); + } + + let manual = ManuallyDrop::new(self); + // SAFETY: We transferred ownership of the refcount to `ARef` by preventing `drop` from + // being called with the `ManuallyDrop` instance created above. + Ok(Ready(manual.0, PhantomData)) + } + pub fn set_iops(&mut self, iops: Ops) -> &mut Self { let inode = unsafe { self.0.as_mut() }; inode.i_op = iops.0; @@ -458,6 +583,29 @@ impl New { inode.i_data.a_ops = aops.0; self } + + pub fn set_ino(&mut self, ino: Ino) -> &mut Self { + // SAFETY: By the type invariants, it's ok to modify the inode. + let inode = unsafe { self.0.as_mut() }; + inode.i_ino = ino; + self + } + + // Initilize uid and gid of a new inode and return (assoicated with a new file) + pub fn init_owner( + &mut self, + parent: &Locked<&INode, kernel::inode::ReadSem>, + mode: u16, + ) -> (kuid_t, kgid_t) { + let inode = unsafe { self.0.as_mut() }; + let parent = unsafe { parent.as_raw() }; + + unsafe { + bindings::inode_init_owner(&raw mut bindings::nop_mnt_idmap, inode, parent, mode); + } + + (inode.i_uid, inode.i_gid) + } } impl Drop for New { @@ -468,6 +616,38 @@ impl Drop for New { } } +/// An inode that is locked has been initilised but +/// needs to be inserted into hash and linked with dentry +/// +/// # Invariants +/// The inode is a new one, locked, and instantiated +pub struct Ready( + pub(crate) ptr::NonNull, + pub(crate) PhantomData, +); + +impl Ready { + pub fn mark_dirty(&mut self) { + // SAFETY: This is safe since it is guaranteed by the typestate + // that the inode has been inserted into the hash + let inode = unsafe { self.0.as_mut() }; + unsafe { bindings::mark_inode_dirty(inode) }; + } + + pub fn instantiate_dentry(self, dentry: &dentry::Unhashed<'_, T>) { + let inode_ptr = unsafe { self.0.as_ptr() }; + let dentry_ptr = unsafe { dentry.0 .0.get() }; + + // SAFETY: instantiates dentry and unlocks inode + // transfer ownership to C + unsafe { + bindings::d_instantiate_new(dentry_ptr, inode_ptr); + } + + core::mem::forget(self); + } +} + /// The type of an inode. pub enum Type { /// Named pipe (first-in, first-out) type. @@ -576,7 +756,11 @@ impl Ops { permission: None, get_inode_acl: None, readlink: None, - create: None, + create: if T::HAS_CREATE { + Some(Self::create_callback) + } else { + None + }, link: None, unlink: None, symlink: None, @@ -620,6 +804,31 @@ impl Ops { Ok(Some(ret)) => ManuallyDrop::new(ret).0.get(), } } + + // TODO: add mnt_idmap support + unsafe extern "C" fn create_callback( + _mnt_idmap_ptr: *mut bindings::mnt_idmap, + parent_ptr: *mut bindings::inode, + dentry_ptr: *mut bindings::dentry, + mode: u16, + excl: bool, + ) -> i32 { + from_result(|| { + // SAFETY: The C API guarantees that `parent_ptr` is a valid inode. + let parent = unsafe { INode::from_raw(parent_ptr) }; + + // SAFETY: The C API guarantees that `parent_ptr` is a valid inode. + let dentry = unsafe { DEntry::from_raw(dentry_ptr) }; + + // SAFETY: The C API guarantees that the inode's rw semaphore is locked at least in + // read mode. It does not expect callees to unlock it, so we make the locked object + // manually dropped to avoid unlocking it. + let locked = ManuallyDrop::new(unsafe { Locked::new(parent) }); + + let create = T::create(&locked, dentry::Unhashed(dentry), mode, excl)?; + Ok(i32::try_from(create)?) + }) + } } Self(&Table::::TABLE, PhantomData) } diff --git a/rust/kernel/sb.rs b/rust/kernel/sb.rs index 332ba404dc22f3..740f17fcee8025 100644 --- a/rust/kernel/sb.rs +++ b/rust/kernel/sb.rs @@ -86,7 +86,7 @@ impl SuperBlock { pub fn blocksize_bits(&self) -> u8 { // SAFETY: This should be fine?? - unsafe {(*self.0.get()).s_blocksize_bits} + unsafe { (*self.0.get()).s_blocksize_bits } } } @@ -150,4 +150,12 @@ impl SuperBlock { Ok(INodeState::Uninitilized(inode::New(inode, PhantomData))) } } + + pub fn new_inode(&self) -> Result> { + let sb_ptr = self.0.get(); + // SAFETY: sb is guaranteed to be valid because of TypeState + let new_inode = ptr::NonNull::new(unsafe { bindings::new_inode(sb_ptr) }).ok_or(ENOMEM)?; + + Ok(inode::New(new_inode, PhantomData)) + } } diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs index 49fad6de06740a..f71e71547e99e1 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -15,7 +15,7 @@ use crate::{ use core::{ cmp::{Eq, PartialEq}, ops::Deref, - ptr, + ptr::{self, addr_of_mut}, }; /// A sentinel value used for infinite timeouts. @@ -154,6 +154,12 @@ pub struct Kuid { kuid: bindings::kuid_t, } +/// The type of user identifiers (UIDs). +#[derive(Copy, Clone)] +pub struct Kgid { + kgid: bindings::kgid_t, +} + impl Task { /// Returns a raw pointer to the current task. /// @@ -390,6 +396,12 @@ impl Kuid { // SAFETY: Just an FFI call. unsafe { bindings::from_kuid(bindings::current_user_ns(), self.kuid) } } + + #[inline] + pub fn into_uid_in_init_ns(self) -> bindings::uid_t { + // SAFETY: Just an FFI call. + unsafe { bindings::from_kuid(addr_of_mut!(bindings::init_user_ns), self.kuid) } + } } impl PartialEq for Kuid { @@ -402,6 +414,30 @@ impl PartialEq for Kuid { impl Eq for Kuid {} +impl Kgid { + /// Create a `Kuid` given the raw C type. + #[inline] + pub fn from_raw(kgid: bindings::kgid_t) -> Self { + Self { kgid } + } + + #[inline] + pub fn into_gid_in_init_ns(self) -> bindings::gid_t { + // SAFETY: Just an FFI call. + unsafe { bindings::from_kgid(addr_of_mut!(bindings::init_user_ns), self.kgid) } + } +} + +impl PartialEq for Kgid { + #[inline] + fn eq(&self, other: &Kgid) -> bool { + // SAFETY: Just an FFI call. + unsafe { bindings::gid_eq(self.kgid, other.kgid) } + } +} + +impl Eq for Kgid {} + /// Annotation for functions that can sleep. /// /// Equivalent to the C side [`might_sleep()`], this function serves as From 38f845802ad88208362c030020e1dfb11b0ea7dd Mon Sep 17 00:00:00 2001 From: lsig Date: Tue, 2 Dec 2025 23:50:54 -0500 Subject: [PATCH 061/131] [ezfs] find first free inode --- fs/rustezfs/ezfs.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index a7ea9e87079837..b17c5b4942a5f9 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -100,7 +100,26 @@ impl RustEzFs { atime: ezfs_inode.atime()?, value: ezfs_inode, }) - // TODO: move unlock_new_inode from instantiate + } + + fn allocate_inode(sb: &SuperBlock) -> Result { + let ezfs_sb = sb.data(); + let mut free_inodes = ezfs_sb.free_inodes.lock(); + + for (word_idx, &word) in free_inodes.iter().enumerate() { + if word != !0u32 { + // Find first ZERO bit by inverting first + let bit_idx: u32 = (!word).leading_zeros(); + let inode_num: usize = (word_idx as usize * 32) + bit_idx as usize; + + if inode_num < EZFS_MAX_INODES { + free_inodes[word_idx] |= 1 << bit_idx; + return Ok(inode_num); + } + } + } + + Err(ENOSPC) } fn new_inode( @@ -110,7 +129,7 @@ impl RustEzFs { let sb = dir.super_block(); let mut new_inode = sb.new_inode()?; - let ino = 0; // TODO + let ino = Self::allocate_inode(sb)?; let typ = match mode & fs::mode::S_IFMT { fs::mode::S_IFREG => { From 4748d775396dac107d0bbd0abc6c1059cfd4e0a3 Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 3 Dec 2025 00:26:32 -0500 Subject: [PATCH 062/131] [ezfs] allocate new file --- fs/rustezfs/ezfs.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index b17c5b4942a5f9..4b778b20312144 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -108,13 +108,12 @@ impl RustEzFs { for (word_idx, &word) in free_inodes.iter().enumerate() { if word != !0u32 { - // Find first ZERO bit by inverting first - let bit_idx: u32 = (!word).leading_zeros(); + let bit_idx: u32 = (!word).trailing_zeros(); let inode_num: usize = (word_idx as usize * 32) + bit_idx as usize; if inode_num < EZFS_MAX_INODES { free_inodes[word_idx] |= 1 << bit_idx; - return Ok(inode_num); + return Ok(inode_num + 1); // FS is 1-indexed } } } @@ -130,6 +129,7 @@ impl RustEzFs { let mut new_inode = sb.new_inode()?; let ino = Self::allocate_inode(sb)?; + pr_info!("Allocating new inode: {:?}\n", ino); let typ = match mode & fs::mode::S_IFMT { fs::mode::S_IFREG => { @@ -155,6 +155,7 @@ impl RustEzFs { .set_mode(mode.try_into()?) .set_uid(Kuid::from_raw(uid).into_uid_in_init_ns()) .set_gid(Kgid::from_raw(gid).into_gid_in_init_ns()) + .set_nlink(1) .set_atime(now) .set_mtime(now) .set_ctime(now); @@ -270,9 +271,11 @@ impl kernel::inode::Operations for RustEzFs { mode: u16, _excl: bool, ) -> Result { - let new_inode = Self::new_inode(parent, mode.into())?; + pr_info!("Calling create from rustezfs\n"); + let new_inode = Self::new_inode(parent, mode.into())?; new_inode.instantiate_dentry(&dentry); + Ok(0) } } From 97058644cabde483dc594f776db9eed1550a9c84 Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 3 Dec 2025 00:30:39 -0500 Subject: [PATCH 063/131] [ezfs] add comment --- fs/rustezfs/ezfs.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 4b778b20312144..903eebb3488167 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -274,6 +274,9 @@ impl kernel::inode::Operations for RustEzFs { pr_info!("Calling create from rustezfs\n"); let new_inode = Self::new_inode(parent, mode.into())?; + + // TODO: Write DirEntry to memory + new_inode.instantiate_dentry(&dentry); Ok(0) From cae2ffe093196bce25980f98ad48074d0c377cb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Wed, 3 Dec 2025 01:36:07 -0500 Subject: [PATCH 064/131] add a MappingPage to wrap around read_mapping_page --- rust/helpers/mm.c | 5 +++ rust/helpers/pagemap.c | 5 +++ rust/kernel/sb.rs | 74 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 81 insertions(+), 3 deletions(-) diff --git a/rust/helpers/mm.c b/rust/helpers/mm.c index 8dec8e6d1c3212..25ff76c9d67e97 100644 --- a/rust/helpers/mm.c +++ b/rust/helpers/mm.c @@ -63,3 +63,8 @@ size_t rust_helper_folio_size(struct folio *folio) { return folio_size(folio); } + +void rust_helper_put_page(struct page *page) +{ + return put_page(page); +} diff --git a/rust/helpers/pagemap.c b/rust/helpers/pagemap.c index f0a017fc950714..fd763535bd7268 100644 --- a/rust/helpers/pagemap.c +++ b/rust/helpers/pagemap.c @@ -11,3 +11,8 @@ struct folio *rust_helper_read_mapping_folio(struct address_space *mapping, pgof { return read_mapping_folio(mapping, index, file); } + +struct page *rust_helper_read_mapping_page(struct address_space *mapping, pgoff_t index, struct file *file) +{ + return read_mapping_page(mapping, index, file); +} diff --git a/rust/kernel/sb.rs b/rust/kernel/sb.rs index 332ba404dc22f3..e081a066d8c46b 100644 --- a/rust/kernel/sb.rs +++ b/rust/kernel/sb.rs @@ -1,6 +1,11 @@ -use core::{marker::PhantomData, ptr}; +use core::{ + marker::PhantomData, + ops::Deref, + ptr::{self, NonNull}, +}; -use crate::error::{code::*, Result}; +use crate::error::{code::*, from_err_ptr, Result}; +use crate::page::{BorrowedPage, Page}; use crate::types::{ARef, ForeignOwnable}; use crate::{block, inode}; use crate::{ @@ -86,7 +91,70 @@ impl SuperBlock { pub fn blocksize_bits(&self) -> u8 { // SAFETY: This should be fine?? - unsafe {(*self.0.get()).s_blocksize_bits} + unsafe { (*self.0.get()).s_blocksize_bits } + } + + pub fn read_mapping_page<'a>(&'a self, index: u64) -> Result> { + let bdev = self.bdev(); + + // SAFETY: all block devices have a valid bd_mapping + let mapping = unsafe { (*bdev.0.get()).bd_mapping }; + + Ok(MappingPage::read(self, mapping, index)?) + } +} + +/// To be used when acquiring pages with read_mapping_page +pub struct MappingPage<'a> { + page: BorrowedPage<'a>, +} + +impl<'a> Deref for MappingPage<'a> { + type Target = Page; + fn deref(&self) -> &Self::Target { + &self.page + } +} + +impl<'a> MappingPage<'a> { + pub fn as_ptr(&self) -> *mut bindings::page { + self.page.as_ptr() + } + + /// `` determines the lifetime of this page reference + pub fn read( + _ctx: &'a C, + mapping: *mut bindings::address_space, + index: u64, + ) -> Result> { + // SAFETY: given a valid mapping and an index, the VFS will return a valid page + // or an error pointer + let page_ptr = from_err_ptr(unsafe { + bindings::read_mapping_page(mapping, index as usize, ptr::null_mut()) + })?; + + if page_ptr.is_null() { + return Err(EIO); + } + + // SAFETY: `vmalloc_to_page` returns a valid pointer to a `struct page` for a valid + // pointer to `Vmalloc` memory. + let page = unsafe { NonNull::new_unchecked(page_ptr) }; + + // SAFETY: `page` is a valid page + let borrowed_page = unsafe { BorrowedPage::from_raw(page) }; + + Ok(MappingPage { + page: borrowed_page, + }) + } +} + +impl<'a> Drop for MappingPage<'a> { + fn drop(&mut self) { + // SAFETY: `read_mapping_page` gave us a ref; dropping this wrapper + // means we're done with it, so we drop that ref. + unsafe { bindings::put_page(self.as_ptr()) }; } } From 8b30a263552ec7595c537261ae91d145d7ed9386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Wed, 3 Dec 2025 01:37:01 -0500 Subject: [PATCH 065/131] allow copying between pages --- rust/helpers/highmem.c | 6 ++++++ rust/kernel/page.rs | 8 ++++++++ 2 files changed, 14 insertions(+) create mode 100644 rust/helpers/highmem.c diff --git a/rust/helpers/highmem.c b/rust/helpers/highmem.c new file mode 100644 index 00000000000000..6f85fba5dd2884 --- /dev/null +++ b/rust/helpers/highmem.c @@ -0,0 +1,6 @@ +#include + +void rust_helper_copy_highpage(struct page *to, struct page *from) +{ + return copy_highpage(to, from); +} diff --git a/rust/kernel/page.rs b/rust/kernel/page.rs index 432fc0297d4a85..971313439067c9 100644 --- a/rust/kernel/page.rs +++ b/rust/kernel/page.rs @@ -340,6 +340,14 @@ impl Page { reader.read_raw(unsafe { core::slice::from_raw_parts_mut(dst.cast(), len) }) }) } + + pub fn copy_to(&self, to: &Page) { + let from_ptr = self.as_ptr(); + let to_ptr = to.as_ptr(); + + // SAFETY: `from_ptr` and `to_ptr` are both valid page pointers + unsafe { bindings::copy_highpage(to_ptr, from_ptr) } + } } impl Drop for Page { From 2023d4944e7a0b149074f16ddb4925683d737b75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Wed, 3 Dec 2025 02:15:39 -0500 Subject: [PATCH 066/131] add MOVE writes --- fs/rustezfs/ezfs.rs | 132 ++++++++++++++++++++++++++++++------------- fs/rustezfs/inode.rs | 2 +- rust/kernel/inode.rs | 22 ++++++++ 3 files changed, 116 insertions(+), 40 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index ba8d909f56d8b4..5ad1e36e2a77cf 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -40,6 +40,35 @@ struct RustEzFsModule { _p: PhantomData, } +macro_rules! min { + ($a:expr, $b:expr) => {{ + let a_val = $a; + let b_val = $b; + if a_val < b_val { + a_val + } else { + b_val + } + }}; +} + +fn get_max_blocks(sb: Pin<&EzfsSuperblock>) -> u64 { + min!(sb.disk_blocks - 2, EZFS_MAX_DATA_BLKS as u64) +} + +fn ezfs_move_block(mut from: u64, mut to: u64, sb: &SuperBlock) -> Result { + pr_info!("moving {from} -> {to}\n"); + from += EZFS_ROOT_DATABLOCK_NUMBER as u64; + to += EZFS_ROOT_DATABLOCK_NUMBER as u64; + + let src = sb.read_mapping_page(from)?; + let dst = sb.read_mapping_page(to)?; + + src.copy_to(&dst); + + Ok(()) +} + impl kernel::InPlaceModule for RustEzFsModule { fn init(module: &'static ThisModule) -> impl PinInit { try_pin_init!(Self { @@ -357,7 +386,7 @@ impl iomap::Operations for RustEzFs { pr_info!("blk_num: {ez_blk_num}, ez_blk_count: {ez_blk_count}\n"); - let phys = if ez_blk_num > 0 { + let mut phys = if ez_blk_num > 0 { ez_blk_num + start_block } else { 0 @@ -385,22 +414,15 @@ impl iomap::Operations for RustEzFs { pr_info!("WRITING\n"); - // TODO: find the max number of blocks + let max_blocks = get_max_blocks(ezfs_sb); + pr_info!("max blocks: {max_blocks}"); let blocks_needed = end_block + 1; let blocks_to_add = blocks_needed - ez_blk_count; - // // Shifted physical index - // let phys_sidx: i64 = if ez_blk_num > 0 { - // // phys should always be >= root datablock number - // (phys - EZFS_ROOT_DATABLOCK_NUMBER as u64).try_into()? - // } else { - // -1i64 - // }; - // - pr_info!( - "blocks: needed={blocks_needed}, to_add={blocks_to_add}, ez_blk_num: {ez_blk_num}\n" - ); - pr_info!("CASE\n"); + // TODO: is this necessary ? + if blocks_needed > max_blocks { + return Err(ENOSPC); + } enum WriteCase { NEW, // Write to an empty file without any allocated blocks @@ -410,39 +432,33 @@ impl iomap::Operations for RustEzFs { } let mut free_data_blocks = ezfs_sb.free_data_blocks.lock(); + let ez_blk_sidx = ez_blk_num - TryInto::::try_into(EZFS_ROOT_DATABLOCK_NUMBER)?; let case_type = if ez_blk_num == 0 { - pr_info!("file has no blocks\n"); WriteCase::NEW + } else if blocks_to_add <= 0 { + WriteCase::WITHIN } else { - let ez_blk_sidx = ez_blk_num - TryInto::::try_into(EZFS_ROOT_DATABLOCK_NUMBER)?; - - if blocks_to_add <= 0 { - pr_info!("inside: don't need additional blocks to perform write\n"); - WriteCase::WITHIN - } else { - pr_info!("extend: we need to allocate blocks\n"); + let start = ez_blk_sidx + ez_blk_count; + let end = ez_blk_sidx + blocks_needed; - let can_extend = true; - let start = ez_blk_sidx + ez_blk_count; - let limit = ez_blk_sidx + blocks_needed; - - // TODO: Check if limit extends beyond the final block + if end > max_blocks { + return Err(ENOSPC); + } - pr_info!("start={start} - limit={limit}\n"); + pr_info!("start={start} - limit={end}\n"); - // REMOVE, just for debugging - for s in start..limit { - if free_data_blocks.is_set(s.try_into()?) { - pr_info!("s={s} is_set, we can't expand\n"); - } + // REMOVE, just for debugging + for s in start..end { + if free_data_blocks.is_set(s.try_into()?) { + pr_info!("s={s} is_set, we can't expand\n"); } + } - if (start..limit).any(|bit| free_data_blocks.is_set(bit)) { - WriteCase::MOVE - } else { - WriteCase::EXTEND - } + if (start..end).any(|bit| free_data_blocks.is_set(bit)) { + WriteCase::MOVE + } else { + WriteCase::EXTEND } }; @@ -464,7 +480,45 @@ impl iomap::Operations for RustEzFs { } WriteCase::MOVE => { pr_info!("Hardest write\n"); - return Err(EIO); + + // Let's try to find a region of sequential free blocks + // of size `blocks_needed` to move our file to + let mut curr_block = 0; + let mut seen_free = 0; + while seen_free < blocks_needed && curr_block < max_blocks { + // if block isn't free, we reset counter + if free_data_blocks.is_set(curr_block) { + seen_free = 0; + } else { + seen_free += 1; + } + + curr_block += 1; + } + + if (seen_free < blocks_needed) { + return Err(ENOSPC); + } + + // Move all blocks within the file to new region + let new_block_start = curr_block - blocks_needed; + + if (ez_blk_num != 0) { + for j in 0..ez_blk_count { + let old = ez_blk_sidx + j; + let new = new_block_start + j; + + ezfs_move_block(old, new, sb); + + free_data_blocks.clear_bit(old); + free_data_blocks.set_bit(new); + } + } + + let mut ezfs_inode = unsafe { inode.data_mut() }; + ezfs_inode.data_blk_num = new_block_start + (EZFS_ROOT_DATABLOCK_NUMBER as u64); + phys = ezfs_inode.data_blk_num() + start_block; + map.set_flags(iomap::map_flags::NEW); } } diff --git a/fs/rustezfs/inode.rs b/fs/rustezfs/inode.rs index 642448e1a72922..bd1b2a95fac1cb 100644 --- a/fs/rustezfs/inode.rs +++ b/fs/rustezfs/inode.rs @@ -15,7 +15,7 @@ pub(crate) struct EzfsInode { i_mtime: i64, /* modified time */ i_ctime: i64, /* change time */ nlink: u32, - data_blk_num: u64, + pub data_blk_num: u64, file_size: u64, nblocks: u64, } diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index ca0374b127edf2..a8a0b36f754bbe 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -115,6 +115,28 @@ impl INode { unsafe { &*(*outerp).data.as_ptr() } } + /// Returns a mutable reference to the inode's associated data. + /// + /// # Safety + /// + /// - Callers must ensure exclusive access to this inode's data. + /// Typically this means holding the appropriate inode or fs-level lock + /// so that no other references (including shared ones) are being used + /// concurrently. + /// - No other references obtained via [`INode::data`] may be used while + /// the returned `&mut T::INodeData` is alive. + pub unsafe fn data_mut(&self) -> &mut T::INodeData { + if T::IS_UNSPECIFIED { + crate::build_error!("inode data type is unspecified"); + } + // TODO: Add safety + let outerp = unsafe { container_of!(self.0.get(), WithData, inode) }; + // SAFETY: `self` is guaranteed to be valid by the existence of a shared reference + // (`&self`) to it. Additionally, we know `T::INodeData` is always initialised in an + // `INode`. + unsafe { &mut *(*outerp).data.as_mut_ptr() } + } + /// Returns a mapper for this inode. /// /// # Safety From a6292ac52dfd9c24981315de2482e1aa98964d3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Wed, 3 Dec 2025 03:59:51 -0500 Subject: [PATCH 067/131] lock before writing --- fs/rustezfs/ezfs.rs | 6 +++++- fs/rustezfs/sb.rs | 12 +++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 5ad1e36e2a77cf..d67c3a274b5cda 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -414,8 +414,10 @@ impl iomap::Operations for RustEzFs { pr_info!("WRITING\n"); + // As we'll modify the file system below, we must acquire a lock + ezfs_sb.lock(); + let max_blocks = get_max_blocks(ezfs_sb); - pr_info!("max blocks: {max_blocks}"); let blocks_needed = end_block + 1; let blocks_to_add = blocks_needed - ez_blk_count; @@ -515,6 +517,8 @@ impl iomap::Operations for RustEzFs { } } + // SAFETY: we've acquired the super block lock and can therefore + // modify the ezfs inode let mut ezfs_inode = unsafe { inode.data_mut() }; ezfs_inode.data_blk_num = new_block_start + (EZFS_ROOT_DATABLOCK_NUMBER as u64); phys = ezfs_inode.data_blk_num() + start_block; diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index 0da917c95e22bc..c1302c82341460 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -6,7 +6,10 @@ use core::ops::{Deref, DerefMut}; use kernel::fs::FileSystem; use kernel::new_mutex; use kernel::prelude::*; -use kernel::sync::Mutex; +use kernel::sync::{ + lock::{mutex::MutexBackend, Guard}, + Mutex, +}; use kernel::transmute::FromBytes; use kernel::{block, inode}; @@ -94,6 +97,8 @@ pub(crate) struct EzfsSuperblock { pub(crate) free_data_blocks: Mutex>, #[pin] pub(crate) zero_data_blocks: Mutex<[u8; (EZFS_MAX_DATA_BLKS / 32) + 1]>, + #[pin] + sb_lock: Mutex<()>, pub(crate) mapper: inode::Mapper, } @@ -109,6 +114,7 @@ impl EzfsSuperblock { free_inodes <- new_mutex!(disk_sb.data.free_inodes), free_data_blocks <- new_mutex!(Bitmap::new(disk_sb.data.free_data_blocks)), zero_data_blocks <- new_mutex!(disk_sb.data.zero_data_blocks), + sb_lock <- new_mutex!(()), mapper, }) } @@ -116,4 +122,8 @@ impl EzfsSuperblock { pub(crate) fn magic(&self) -> u64 { self.magic } + + pub(crate) fn lock(&self) -> Guard<'_, (), MutexBackend> { + self.sb_lock.lock() + } } From 4c511aae8b09ea446d525f737263cc7543a781f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Wed, 3 Dec 2025 04:00:08 -0500 Subject: [PATCH 068/131] iomap_end --- fs/rustezfs/ezfs.rs | 36 +++++++++++++++++++++++++++++------- fs/rustezfs/inode.rs | 2 +- rust/helpers/fs.c | 5 +++++ rust/kernel/inode.rs | 12 ++++++++++++ rust/kernel/iomap.rs | 2 +- 5 files changed, 48 insertions(+), 9 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index d67c3a274b5cda..df2f5807cdccb2 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -57,7 +57,6 @@ fn get_max_blocks(sb: Pin<&EzfsSuperblock>) -> u64 { } fn ezfs_move_block(mut from: u64, mut to: u64, sb: &SuperBlock) -> Result { - pr_info!("moving {from} -> {to}\n"); from += EZFS_ROOT_DATABLOCK_NUMBER as u64; to += EZFS_ROOT_DATABLOCK_NUMBER as u64; @@ -448,11 +447,11 @@ impl iomap::Operations for RustEzFs { return Err(ENOSPC); } - pr_info!("start={start} - limit={end}\n"); + pr_info!("start={start} - end={end}\n"); // REMOVE, just for debugging for s in start..end { - if free_data_blocks.is_set(s.try_into()?) { + if free_data_blocks.is_set(s) { pr_info!("s={s} is_set, we can't expand\n"); } } @@ -474,7 +473,9 @@ impl iomap::Operations for RustEzFs { } WriteCase::EXTEND => { pr_info!("semi easy write\n"); - for bit in ez_blk_count..blocks_needed { + for i in ez_blk_count..blocks_needed { + let bit = ez_blk_sidx + i; + pr_info!("setting bit: {bit}\n"); free_data_blocks.set_bit(bit); } @@ -510,6 +511,8 @@ impl iomap::Operations for RustEzFs { let old = ez_blk_sidx + j; let new = new_block_start + j; + pr_info!("move: {old} -> {new}\n"); + ezfs_move_block(old, new, sb); free_data_blocks.clear_bit(old); @@ -533,14 +536,33 @@ impl iomap::Operations for RustEzFs { } fn end<'a>( - _inode: &'a INode, + inode: &'a INode, _pos: Offset, _length: Offset, - _written: isize, + written: isize, _flags: u32, _map: &iomap::Map<'a>, ) -> Result { - pr_info!("iomap_end()\n"); + if (written > 0) { + pr_info!("iomap_end()\n"); + let new_blocks = + ((inode.size() + (EZFS_BLOCK_SIZE as i64) - 1) / EZFS_BLOCK_SIZE as i64) as u64; + let sb = inode.super_block(); + let ezfs_sb = sb.data(); + + // We'll modify our inodes, let's lock first + ezfs_sb.lock(); + + // SAFETY: We've acquired the super block lock + unsafe { inode.set_blocks(new_blocks * 8) }; + let ezfs_inode = unsafe { inode.data_mut() }; + + ezfs_inode.nblocks = new_blocks; + + // TODO: + // - get inode store and update nblocks + // - mark inode dirty + } Ok(()) } } diff --git a/fs/rustezfs/inode.rs b/fs/rustezfs/inode.rs index bd1b2a95fac1cb..9fde2ec6fef9ff 100644 --- a/fs/rustezfs/inode.rs +++ b/fs/rustezfs/inode.rs @@ -17,7 +17,7 @@ pub(crate) struct EzfsInode { nlink: u32, pub data_blk_num: u64, file_size: u64, - nblocks: u64, + pub nblocks: u64, } impl EzfsInode { diff --git a/rust/helpers/fs.c b/rust/helpers/fs.c index 02429eb371b89a..32275353a93c3e 100644 --- a/rust/helpers/fs.c +++ b/rust/helpers/fs.c @@ -41,3 +41,8 @@ loff_t rust_helper_i_size_read(const struct inode *inode) { return i_size_read(inode); } + +void rust_helper_mark_inode_dirty(struct inode *inode) +{ + return mark_inode_dirty(inode); +} diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index a8a0b36f754bbe..32d6f42438ef2c 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -97,11 +97,23 @@ impl INode { unsafe { SuperBlock::from_raw((*self.0.get()).i_sb) } } + pub fn size(&self) -> i64 { + unsafe { (*self.0.get()).i_size } + } + pub fn blocks(&self) -> u64 { // SAFETY: this is ok unsafe { (*self.0.get()).i_blocks } } + pub unsafe fn set_blocks(&self, num_blocks: u64) { + unsafe { (*self.0.get()).i_blocks = num_blocks }; + } + + pub fn mark_dirty(&self) { + unsafe { bindings::mark_inode_dirty((self.0.get())) }; + } + /// Returns the data associated with the inode. pub fn data(&self) -> &T::INodeData { if T::IS_UNSPECIFIED { diff --git a/rust/kernel/iomap.rs b/rust/kernel/iomap.rs index d79d6a059276d3..e24d189a9f4c38 100644 --- a/rust/kernel/iomap.rs +++ b/rust/kernel/iomap.rs @@ -185,7 +185,7 @@ pub trait Operations { srcmap: &mut Map<'a>, ) -> Result; - /// Commits and/or unreserves space previously allocated using [`Operations::begin`]. `writte`n + /// Commits and/or unreserves space previously allocated using [`Operations::begin`]. `written` /// indicates the length of the successful write operation which needs to be commited, while /// the rest needs to be unreserved. `written` might be zero if no data was written. /// From c4ce9984a86528b25ef8c2686245f89c789e5ff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Wed, 3 Dec 2025 04:01:56 -0500 Subject: [PATCH 069/131] cleanup prints --- fs/rustezfs/ezfs.rs | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index df2f5807cdccb2..7b042fe40180bc 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -378,12 +378,12 @@ impl iomap::Operations for RustEzFs { let start_block: u64 = (pos >> sb.blocksize_bits()).try_into()?; let end_block: u64 = ((pos + length - 1) >> sb.blocksize_bits()).try_into()?; - pr_info!("start_block: {start_block}, end_block: {end_block}\n"); + // pr_info!("start_block: {start_block}, end_block: {end_block}\n"); let ez_blk_num = ezfs_inode.data_blk_num(); let ez_blk_count = inode.blocks() / 8; - pr_info!("blk_num: {ez_blk_num}, ez_blk_count: {ez_blk_count}\n"); + // pr_info!("blk_num: {ez_blk_num}, ez_blk_count: {ez_blk_count}\n"); let mut phys = if ez_blk_num > 0 { ez_blk_num + start_block @@ -396,9 +396,8 @@ impl iomap::Operations for RustEzFs { .set_offset(pos) .set_length(length as u64); + // We're reading if (flags & iomap::flags::WRITE == 0) { - pr_info!("READING\n"); - // Invalid read, block does not belong to inode if ez_blk_num == 0 || start_block >= ez_blk_count { map.set_type(iomap::Type::Hole) @@ -411,8 +410,7 @@ impl iomap::Operations for RustEzFs { return Ok(()); }; - pr_info!("WRITING\n"); - + // We're writing // As we'll modify the file system below, we must acquire a lock ezfs_sb.lock(); @@ -447,14 +445,7 @@ impl iomap::Operations for RustEzFs { return Err(ENOSPC); } - pr_info!("start={start} - end={end}\n"); - - // REMOVE, just for debugging - for s in start..end { - if free_data_blocks.is_set(s) { - pr_info!("s={s} is_set, we can't expand\n"); - } - } + // pr_info!("start={start} - end={end}\n"); if (start..end).any(|bit| free_data_blocks.is_set(bit)) { WriteCase::MOVE @@ -465,25 +456,19 @@ impl iomap::Operations for RustEzFs { match case_type { WriteCase::NEW => { - pr_info!("creating a file\n"); + pr_info!("adding to an empty file\n"); return Err(EIO); } - WriteCase::WITHIN => { - pr_info!("easiest write\n"); - } + WriteCase::WITHIN => {} WriteCase::EXTEND => { - pr_info!("semi easy write\n"); for i in ez_blk_count..blocks_needed { let bit = ez_blk_sidx + i; - pr_info!("setting bit: {bit}\n"); free_data_blocks.set_bit(bit); } map.set_flags(iomap::map_flags::NEW); } WriteCase::MOVE => { - pr_info!("Hardest write\n"); - // Let's try to find a region of sequential free blocks // of size `blocks_needed` to move our file to let mut curr_block = 0; @@ -511,8 +496,6 @@ impl iomap::Operations for RustEzFs { let old = ez_blk_sidx + j; let new = new_block_start + j; - pr_info!("move: {old} -> {new}\n"); - ezfs_move_block(old, new, sb); free_data_blocks.clear_bit(old); From 890991fe17fae67d89b38716dd2f48ea0b0888d3 Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 3 Dec 2025 13:12:58 -0500 Subject: [PATCH 070/131] [VFS] add safety --- rust/kernel/inode.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index d09793b2dd843a..0a3ad2641734ef 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -365,6 +365,7 @@ pub struct New( impl New { /// Initialises the new inode with the given parameters. pub fn init_from_disk(self, params: Params) -> Result>> { + // SAFETY: WithData has been allocated by VFS (allocate_inode_callback) let outerp = unsafe { container_of!(self.0.as_ptr(), WithData, inode) }; // SAFETY: This is a newly-created inode. No other references to it exist, so it is @@ -462,6 +463,7 @@ impl New { // Instantiated new inode with data but keep it locked pub fn init_new(self, params: Params) -> Result> { + // SAFETY: WithData has been allocated by VFS (allocate_inode_callback) let outerp = unsafe { container_of!(self.0.as_ptr(), WithData, inode) }; // SAFETY: This is a newly-created inode. No other references to it exist, so it is From 8b7c1b02712b12105a02cec65b2115489431c02e Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 3 Dec 2025 13:18:04 -0500 Subject: [PATCH 071/131] [VFS] remove wrong comment --- rust/kernel/inode.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index 0a3ad2641734ef..7aa1abec0f8217 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -559,8 +559,7 @@ impl New { } let manual = ManuallyDrop::new(self); - // SAFETY: We transferred ownership of the refcount to `ARef` by preventing `drop` from - // being called with the `ManuallyDrop` instance created above. + Ok(Ready(manual.0, PhantomData)) } From 4d3ae60ef06eb2a652144706726c9a36035c4679 Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 3 Dec 2025 13:21:47 -0500 Subject: [PATCH 072/131] [VFS] remove unecessary unsafe --- rust/kernel/inode.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index 7aa1abec0f8217..78376d51040ece 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -198,7 +198,7 @@ impl INode { pub fn mark_dirty(&self) { // SAFETY: This is safe since it is guaranteed by the typestate // that the inode has been inserted into the hash - let inode = unsafe { self.0.get() }; + let inode = self.0.get(); unsafe { bindings::mark_inode_dirty(inode) }; } @@ -636,8 +636,8 @@ impl Ready { } pub fn instantiate_dentry(self, dentry: &dentry::Unhashed<'_, T>) { - let inode_ptr = unsafe { self.0.as_ptr() }; - let dentry_ptr = unsafe { dentry.0 .0.get() }; + let inode_ptr = self.0.as_ptr(); + let dentry_ptr = dentry.0 .0.get(); // SAFETY: instantiates dentry and unlocks inode // transfer ownership to C From 648eb7858069691d48901f4e245dc5fd3f3d050d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Wed, 3 Dec 2025 19:23:34 -0500 Subject: [PATCH 073/131] cleanup write_iter --- fs/rustezfs/ezfs.rs | 35 +++++++------------------------- rust/kernel/fs/file.rs | 45 ++++++++++++++++++----------------------- rust/kernel/fs/kiocb.rs | 20 ++++++++++++++++++ rust/kernel/iomap.rs | 39 ++++++++++++++++++++++++++++------- 4 files changed, 79 insertions(+), 60 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 7b042fe40180bc..413409045d1038 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -315,45 +315,24 @@ impl file::Operations for RustEzFs { } fn write_iter( - _kiocb: Kiocb<'_, ::Data>, - _iov: &mut IovIterSource<'_>, + mut kiocb: Kiocb<'_, ::Data>, + mut iov: &mut IovIterSource<'_>, ) -> Result { pr_info!("write_iter\n"); - - let kiocb = _kiocb.as_raw(); - let iter = _iov.as_raw(); - let iomap_ops = iomap::map_table::(); - - // SAFETY: VFS guarantees kiocb is never null and can be dereferenced - // Theerefore, both operations below are valid - let flags = unsafe { (*kiocb).ki_flags as u32 }; // casting a bitmask to u32 is always ok - let file_ptr = unsafe { (*kiocb).ki_filp }; + let flags = kiocb.ki_flags(); + let file: &File = kiocb.ki_filp(); if flags & bindings::IOCB_DIRECT != 0 { return Err(EINVAL); // We don't support direct I/O } - // SAFETY: VFS will always provide a valid file pointer - let file_flags = unsafe { (*file_ptr).f_flags }; - - if (file_flags & bindings::O_APPEND) != 0 { - unsafe { (*kiocb).ki_pos = bindings::i_size_read((*(*file_ptr).f_mapping).host) }; + if (file.flags() & bindings::O_APPEND) != 0 { + *kiocb.ki_pos_mut() = file.host_inode().size(); } // SAFETY: We've got a valid kiocb and iov iter from our VFS and our iomap_ops is static // The function treats null pointers as valid inputs for the last two params - let ret: usize = unsafe { - bindings::iomap_file_buffered_write( - kiocb, - iter, - iomap_ops, - ptr::null(), - ptr::null_mut(), - ) - } - .try_into()?; - - Ok(ret) + iomap::file_buffered_write::(kiocb, iov) } } diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index 0877cca33a4691..2ff0e2db4ebb21 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -355,6 +355,12 @@ impl LocalFile { unsafe { INode::from_raw((*self.inner.get()).f_inode) } } + /// Returns the host inode of that file + pub fn host_inode(&self) -> &INode { + // SAFETY: f_mapping is always valid and requires a host + unsafe { INode::from_raw((*(*self.inner.get()).f_mapping).host) } + } + /// Returns the dentry associated with the file. pub fn dentry(&self) -> &DEntry { // SAFETY: `f_path` is an immutable field, so it's safe to read it. And will remain safe to @@ -583,19 +589,7 @@ pub trait Operations { Err(EINVAL) } - // /// Writes data from the caller's buffer to this file. - // /// - // /// Corresponds to the `write_iter` function pointer in `struct file_operations`. - // fn write( - // _data: ::Borrowed<'_>, - // _file: &File, - // _reader: &mut impl IoBufferReader, - // _offset: u64, - // ) -> Result { - // Err(EINVAL) - // } - - /// Write to this miscdevice. + /// Write to this file fn write_iter( _kiocb: Kiocb<'_, ::Data>, _iov: &mut IovIterSource<'_>, @@ -740,22 +734,23 @@ impl Ops { /// # Safety /// /// `kiocb` must be correspond to a valid file that is associated with a - /// `MiscDeviceRegistration`. `iter` must be a valid `struct iov_iter` for writing. + /// ``. `iter` must be a valid `struct iov_iter` for writing. unsafe extern "C" fn write_iter_callback( kiocb: *mut bindings::kiocb, iter: *mut bindings::iov_iter, ) -> isize { - pr_info!("write_iter_callback\n"); - // SAFETY: The caller provides a valid `struct kiocb` associated with a - // `MiscDeviceRegistration` file. - let kiocb = unsafe { Kiocb::from_raw(kiocb) }; - // SAFETY: This is a valid `struct iov_iter` for reading. - let iov = unsafe { IovIterSource::from_raw(iter) }; - - match T::write_iter(kiocb, iov) { - Ok(res) => res as isize, - Err(err) => err.to_errno() as isize, - } + from_result(|| { + pr_info!("write_iter_callback\n"); + // SAFETY: The caller provides a valid `struct kiocb` associated with a + // `` file. + let kiocb = unsafe { Kiocb::from_raw(kiocb) }; + // SAFETY: This is a valid `struct iov_iter` for reading. + let mut iov = unsafe { IovIterSource::from_raw(iter) }; + + let wrote = T::write_iter(kiocb, &mut iov)?; + + Ok(wrote.try_into()?) + }) } } Self { diff --git a/rust/kernel/fs/kiocb.rs b/rust/kernel/fs/kiocb.rs index 84c936cd69b0e9..6ef514f05cdf0c 100644 --- a/rust/kernel/fs/kiocb.rs +++ b/rust/kernel/fs/kiocb.rs @@ -10,6 +10,8 @@ use core::marker::PhantomData; use core::ptr::NonNull; use kernel::types::ForeignOwnable; +use crate::fs::{File, FileSystem}; + /// Wrapper for the kernel's `struct kiocb`. /// /// Currently this abstractions is incomplete and is essentially just a tuple containing a @@ -65,4 +67,22 @@ impl<'a, T: ForeignOwnable> Kiocb<'a, T> { // SAFETY: We have exclusive access to the kiocb, so we can write to `ki_pos`. unsafe { &mut (*self.as_raw()).ki_pos } } + + pub fn ki_flags(&self) -> u32 { + // CAST: ki_flags is a bit mask and has the same + // SAFETY: VFS guarantees kiocb is never null and can be dereferenced + // Therefore, both operations below are valid + unsafe { (*self.as_raw()).ki_flags as u32 } + } + + pub fn ki_filp(&self) -> &'a File + where + FS: FileSystem + ?Sized, + { + // SAFETY: VFS guarantees ki_filp is a valid file pointer + let file_ptr = unsafe { (*self.as_raw()).ki_filp }; + + // While the Kiocb exists, it will have a valid reference to the file pointer + unsafe { File::::from_raw_file(file_ptr) } + } } diff --git a/rust/kernel/iomap.rs b/rust/kernel/iomap.rs index ae341f221c66f2..5b485b2d297309 100644 --- a/rust/kernel/iomap.rs +++ b/rust/kernel/iomap.rs @@ -5,22 +5,22 @@ //! C headers: [`include/linux/iomap.h`](srctree/include/linux/iomap.h) use super::address_space; +use crate::error::to_result; +use crate::iov::IovIterSource; use crate::pr_info; -use crate::prelude::EIO; +use crate::prelude::{EIO, EOVERFLOW}; use crate::{ block, error::{from_result, Result}, - folio::Folio, - folio::PageCache, - fs::file::File, - fs::FileSystem, - fs::Offset, - types::Locked, + folio::{Folio, PageCache}, + fs::{file::File, FileSystem, Kiocb, Offset}, + types::{ForeignOwnable, Locked}, }; use crate::inode::INode; use core::marker::PhantomData; use core::mem; +use core::ptr; use macros::vtable; use uapi::writeback_control; @@ -350,3 +350,28 @@ pub const fn aops() -> address_space::Ops pub const fn map_table() -> &'static bindings::iomap_ops { return &Table::::MAP_TABLE; } + +pub fn file_buffered_write( + kiocb: Kiocb<'_, ::Data>, + iov: &mut IovIterSource<'_>, +) -> Result { + // SAFETY: + // - `kiocb.as_raw()` and `iov.as_raw()` are valid as given by the VFS/iov wrapper. + // - `map_table::()` is a static iomap_ops for this filesystem. + // - The last two args are allowed to be NULL by iomap. + let ret = unsafe { + bindings::iomap_file_buffered_write( + kiocb.as_raw(), + iov.as_raw(), + map_table::(), + ptr::null(), + ptr::null_mut(), + ) + }; + + // Returns Err if err is invalid + // We can't use it for Ok as it doesn't return usize + to_result(ret.try_into()?)?; + + ret.try_into().map_err(|_| EOVERFLOW) +} From 7ea1c1837b6a07ce5adcb64fcf1d4429d6db8686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Wed, 3 Dec 2025 19:33:03 -0500 Subject: [PATCH 074/131] complete merge --- fs/rustezfs/ezfs.rs | 7 ++++--- fs/rustezfs/inode.rs | 4 ++-- rust/kernel/inode.rs | 4 ---- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index a6414c6563440b..bde4b59bfe47aa 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -416,7 +416,7 @@ impl file::Operations for RustEzFs { ) -> Result { pr_info!("write_iter\n"); let flags = kiocb.ki_flags(); - let file: &File = kiocb.ki_filp(); + let file = kiocb.ki_filp(); if flags & bindings::IOCB_DIRECT != 0 { return Err(EINVAL); // We don't support direct I/O @@ -581,7 +581,8 @@ impl iomap::Operations for RustEzFs { // SAFETY: we've acquired the super block lock and can therefore // modify the ezfs inode let mut ezfs_inode = unsafe { inode.data_mut() }; - ezfs_inode.data_blk_num = new_block_start + (EZFS_ROOT_DATABLOCK_NUMBER as u64); + ezfs_inode + .set_data_block_num(new_block_start + (EZFS_ROOT_DATABLOCK_NUMBER as u64)); phys = ezfs_inode.data_blk_num() + start_block; map.set_flags(iomap::map_flags::NEW); } @@ -615,7 +616,7 @@ impl iomap::Operations for RustEzFs { unsafe { inode.set_blocks(new_blocks * 8) }; let ezfs_inode = unsafe { inode.data_mut() }; - ezfs_inode.nblocks = new_blocks; + ezfs_inode.set_nblocks(new_blocks); // TODO: // - get inode store and update nblocks diff --git a/fs/rustezfs/inode.rs b/fs/rustezfs/inode.rs index ca263447873405..2e51ac0f7fc58e 100644 --- a/fs/rustezfs/inode.rs +++ b/fs/rustezfs/inode.rs @@ -15,9 +15,9 @@ pub(crate) struct EzfsInode { i_mtime: i64, /* modified time */ i_ctime: i64, /* change time */ nlink: u32, - pub data_blk_num: u64, + data_blk_num: u64, file_size: u64, - pub nblocks: u64, + nblocks: u64, } impl EzfsInode { diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index 1e8f2c7cb05b90..0b740a1c567704 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -126,10 +126,6 @@ impl INode { unsafe { (*self.0.get()).i_blocks = num_blocks }; } - pub fn mark_dirty(&self) { - unsafe { bindings::mark_inode_dirty((self.0.get())) }; - } - /// Returns the data associated with the inode. pub fn data(&self) -> &T::INodeData { if T::IS_UNSPECIFIED { From 6c2873efc3df3336ca717a8be1ec5d000ece4dd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Wed, 3 Dec 2025 19:44:24 -0500 Subject: [PATCH 075/131] address comments --- fs/rustezfs/ezfs.rs | 56 +++++++++++++++++--------------------------- fs/rustezfs/inode.rs | 2 +- 2 files changed, 23 insertions(+), 35 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index bde4b59bfe47aa..a449ac79ecb0da 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -42,34 +42,6 @@ struct RustEzFsModule { _p: PhantomData, } -macro_rules! min { - ($a:expr, $b:expr) => {{ - let a_val = $a; - let b_val = $b; - if a_val < b_val { - a_val - } else { - b_val - } - }}; -} - -fn get_max_blocks(sb: Pin<&EzfsSuperblock>) -> u64 { - min!(sb.disk_blocks - 2, EZFS_MAX_DATA_BLKS as u64) -} - -fn ezfs_move_block(mut from: u64, mut to: u64, sb: &SuperBlock) -> Result { - from += EZFS_ROOT_DATABLOCK_NUMBER as u64; - to += EZFS_ROOT_DATABLOCK_NUMBER as u64; - - let src = sb.read_mapping_page(from)?; - let dst = sb.read_mapping_page(to)?; - - src.copy_to(&dst); - - Ok(()) -} - impl kernel::InPlaceModule for RustEzFsModule { fn init(module: &'static ThisModule) -> impl PinInit { try_pin_init!(Self { @@ -207,6 +179,22 @@ impl RustEzFs { Ok(ready_inode) } + + fn move_block(mut from: u64, mut to: u64, sb: &SuperBlock) -> Result { + from += EZFS_ROOT_DATABLOCK_NUMBER as u64; + to += EZFS_ROOT_DATABLOCK_NUMBER as u64; + + let src = sb.read_mapping_page(from)?; + let dst = sb.read_mapping_page(to)?; + + src.copy_to(&dst); + + Ok(()) + } + + fn get_max_blocks(sb: Pin<&EzfsSuperblock>) -> u64 { + (sb.disk_blocks - 2).min(EZFS_MAX_DATA_BLKS as u64) + } } impl FileSystem for RustEzFs { @@ -416,13 +404,13 @@ impl file::Operations for RustEzFs { ) -> Result { pr_info!("write_iter\n"); let flags = kiocb.ki_flags(); - let file = kiocb.ki_filp(); + let file: &File = kiocb.ki_filp(); if flags & bindings::IOCB_DIRECT != 0 { return Err(EINVAL); // We don't support direct I/O } - if (file.flags() & bindings::O_APPEND) != 0 { + if (file.flags() & file::flags::O_APPEND) != 0 { *kiocb.ki_pos_mut() = file.host_inode().size(); } @@ -489,7 +477,7 @@ impl iomap::Operations for RustEzFs { // As we'll modify the file system below, we must acquire a lock ezfs_sb.lock(); - let max_blocks = get_max_blocks(ezfs_sb); + let max_blocks = Self::get_max_blocks(ezfs_sb); let blocks_needed = end_block + 1; let blocks_to_add = blocks_needed - ez_blk_count; @@ -506,11 +494,11 @@ impl iomap::Operations for RustEzFs { } let mut free_data_blocks = ezfs_sb.free_data_blocks.lock(); - let ez_blk_sidx = ez_blk_num - TryInto::::try_into(EZFS_ROOT_DATABLOCK_NUMBER)?; + let ez_blk_sidx = ez_blk_num - (EZFS_ROOT_DATABLOCK_NUMBER as u64); let case_type = if ez_blk_num == 0 { WriteCase::NEW - } else if blocks_to_add <= 0 { + } else if blocks_to_add == 0 { WriteCase::WITHIN } else { let start = ez_blk_sidx + ez_blk_count; @@ -571,7 +559,7 @@ impl iomap::Operations for RustEzFs { let old = ez_blk_sidx + j; let new = new_block_start + j; - ezfs_move_block(old, new, sb); + Self::move_block(old, new, sb); free_data_blocks.clear_bit(old); free_data_blocks.set_bit(new); diff --git a/fs/rustezfs/inode.rs b/fs/rustezfs/inode.rs index 2e51ac0f7fc58e..cee71bd92a1ba9 100644 --- a/fs/rustezfs/inode.rs +++ b/fs/rustezfs/inode.rs @@ -115,7 +115,7 @@ impl EzfsInode { self } - pub(crate) fn set_nblock(mut self, nblocks: u64) -> Self { + pub(crate) fn set_nblocks(mut self, nblocks: u64) -> Self { self.nblocks = nblocks; self From 390249356b7e2f3129dd12aa915f95ec4100a91b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Wed, 3 Dec 2025 19:59:44 -0500 Subject: [PATCH 076/131] check for a sub --- fs/rustezfs/ezfs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index a449ac79ecb0da..a648f159da3525 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -479,7 +479,7 @@ impl iomap::Operations for RustEzFs { let max_blocks = Self::get_max_blocks(ezfs_sb); let blocks_needed = end_block + 1; - let blocks_to_add = blocks_needed - ez_blk_count; + let blocks_to_add = blocks_needed.checked_sub(ez_blk_count).ok_or(EIO)?; // TODO: is this necessary ? if blocks_needed > max_blocks { From fb38bf4bcf01f80f5d35bc6a5e5f3089d4ac37e1 Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 3 Dec 2025 20:10:13 -0500 Subject: [PATCH 077/131] [VFS] unlink infra setup --- fs/rustezfs/dir.rs | 4 ++- fs/rustezfs/ezfs.rs | 84 ++++++++++++++++++++++++++++++-------------- rust/kernel/inode.rs | 41 ++++++++++++++++++++- 3 files changed, 100 insertions(+), 29 deletions(-) diff --git a/fs/rustezfs/dir.rs b/fs/rustezfs/dir.rs index ae31a23a624e04..40a88ab6026f06 100644 --- a/fs/rustezfs/dir.rs +++ b/fs/rustezfs/dir.rs @@ -1,8 +1,9 @@ use crate::defs::{EZFS_FILENAME_BUF_SIZE, EZFS_MAX_CHILDREN}; use core::ops::Deref; -use kernel::transmute::FromBytes; +use kernel::transmute::{AsBytes, FromBytes}; #[repr(C)] +#[derive(Clone, Copy)] pub(crate) struct EzfsDirEntry { inode_no: u64, active: u8, @@ -44,3 +45,4 @@ impl Deref for DirEntryStore { // TODO: Add Safety unsafe impl FromBytes for DirEntryStore {} +unsafe impl AsBytes for DirEntryStore {} diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index a648f159da3525..085730f2874575 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -195,6 +195,34 @@ impl RustEzFs { fn get_max_blocks(sb: Pin<&EzfsSuperblock>) -> u64 { (sb.disk_blocks - 2).min(EZFS_MAX_DATA_BLKS as u64) } + + fn find_dir_entry( + parent: &Locked<&INode, kernel::inode::ReadSem>, + dentry: &dentry::Unhashed<'_, Self>, + ) -> Result> { + let h = parent.super_block().data(); + let ezfs_dir_inode = parent.data(); + let name = dentry.name(); + + if name.len() > EZFS_FILENAME_BUF_SIZE { + return Err(ENAMETOOLONG); + } + let offset = ezfs_dir_inode + .data_blk_num() + .checked_mul(EZFS_BLOCK_SIZE as u64) + .ok_or(EIO)?; + + let mapped = h.mapper.mapped_folio(offset.try_into()?)?; + let dir_entries = + DirEntryStore::from_bytes(&mapped[..size_of::()]).ok_or(EIO)?; + + let dir_entry = dir_entries + .iter() + .find(|x| x.is_active() && x.filename() == name) + .copied(); + + Ok(dir_entry) + } } impl FileSystem for RustEzFs { @@ -244,33 +272,8 @@ impl kernel::inode::Operations for RustEzFs { parent: &Locked<&INode, kernel::inode::ReadSem>, dentry: dentry::Unhashed<'_, Self::FileSystem>, ) -> Result>>> { - let sb = &*parent.super_block(); - let h = sb.data(); - - let name = dentry.name(); - pr_info!("lookup(name={:?})\n", core::str::from_utf8(name)); - - if name.len() > EZFS_FILENAME_BUF_SIZE { - return Err(ENAMETOOLONG); - } - - let ezfs_dir_inode = parent.data(); - // pr_info!("ezfs_dir inode number: {:?}", parent.ino()); - // pr_info!("ezfs dir inode links: {:?}", ezfs_dir_inode.nlink()); - // pr_info!("data_blk_num: {:?}", ezfs_dir_inode.data_blk_num()); - - let offset = ezfs_dir_inode - .data_blk_num() - .checked_mul(EZFS_BLOCK_SIZE as u64) - .ok_or(EIO)?; - - let mapped = h.mapper.mapped_folio(offset.try_into()?)?; - let dir_entries = - DirEntryStore::from_bytes(&mapped[..size_of::()]).ok_or(EIO)?; - - let dir_entry = dir_entries - .iter() - .find(|x| x.is_active() && x.filename() == name); + let sb = parent.super_block(); + let dir_entry = Self::find_dir_entry(parent, &dentry)?; let inode = if let Some(entry) = dir_entry { pr_info!("Inode found: {:?}\n", entry.inode_no()); @@ -292,7 +295,34 @@ impl kernel::inode::Operations for RustEzFs { let new_inode = Self::new_inode(parent, mode.into())?; + // TODO: Lock memory when writing DirEntries // TODO: Write DirEntry to memory + // + // let sb = parent.super_block(); + // let h = sb.data(); + // + // let ezfs_dir_inode = parent.data(); + // + // let offset = ezfs_dir_inode + // .data_blk_num() + // .checked_mul(EZFS_BLOCK_SIZE as u64) + // .ok_or(EIO)?; + // + // let mut mapped = h.mapper.mapped_folio(offset.try_into()?)?; + // let new_filename = dentry.name(); + // + // let dir_entries = + // DirEntryStore::from_bytes_mut(&mut mapped[..size_of::()]).ok_or(EIO)?; + // + // let dir_entry = dir_entries + // .iter_mut() + // .find(|x| !x.is_active()) + // .ok_or(ENOSPC)?; + // + // dir_entry + // .set_inode_no(new_inode.ino().try_into()?) + // .set_active() + // .set_filename(new_filename); new_inode.instantiate_dentry(&dentry); diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index 0b740a1c567704..39e1f465a4ea96 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -65,6 +65,13 @@ pub trait Operations { ) -> Result { Err(ENOTSUPP) } + + fn unlink( + _parent: &Locked<&INode, ReadSem>, + _dentry: dentry::Unhashed<'_, Self::FileSystem>, + ) -> Result { + Err(ENOTSUPP) + } } /// A node (inode) in the file index. @@ -677,6 +684,12 @@ impl Ready { core::mem::forget(self); } + /// Returns the number of the inode. + pub fn ino(&self) -> Ino { + // SAFETY: `i_ino` is immutable, and `self` is guaranteed to be valid by the existence of a + // shared reference (&self) to it. + unsafe { (*self.0.as_ref()).i_ino } + } } /// The type of an inode. @@ -793,7 +806,11 @@ impl Ops { None }, link: None, - unlink: None, + unlink: if T::HAS_UNLINK { + Some(Self::unlink_callback) + } else { + None + }, symlink: None, mkdir: None, rmdir: None, @@ -860,6 +877,28 @@ impl Ops { Ok(i32::try_from(create)?) }) } + + unsafe extern "C" fn unlink_callback( + inode_ptr: *mut bindings::inode, + dentry_ptr: *mut bindings::dentry, + ) -> i32 { + from_result(|| { + // SAFETY: The C API guarantees that `inode_ptr` is a valid inode. + let inode = unsafe { INode::from_raw(inode_ptr) }; + + // SAFETY: The C API guarantees that `dentry_ptr` is a valid inode. + let dentry = unsafe { DEntry::from_raw(dentry_ptr) }; + + // SAFETY: The C API guarantees that the inode's rw semaphore is locked at least in + // read mode. It does not expect callees to unlock it, so we make the locked object + // manually dropped to avoid unlocking it. + let locked = ManuallyDrop::new(unsafe { Locked::new(inode) }); + + let unlink = T::unlink(&locked, dentry::Unhashed(dentry))?; + + Ok(i32::try_from(unlink)?) + }) + } } Self(&Table::::TABLE, PhantomData) } From ebaee2f2d27a2df4b7789c2114b7cf9c0f509360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Wed, 3 Dec 2025 23:14:25 -0500 Subject: [PATCH 078/131] fix: saturate subtraction --- fs/rustezfs/ezfs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index a648f159da3525..672ff8aff79a7e 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -494,7 +494,7 @@ impl iomap::Operations for RustEzFs { } let mut free_data_blocks = ezfs_sb.free_data_blocks.lock(); - let ez_blk_sidx = ez_blk_num - (EZFS_ROOT_DATABLOCK_NUMBER as u64); + let ez_blk_sidx = ez_blk_num.saturating_sub(EZFS_ROOT_DATABLOCK_NUMBER as u64); let case_type = if ez_blk_num == 0 { WriteCase::NEW From 318641519a8f885bbe6d8338cd424a0f0fbbcf15 Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 3 Dec 2025 23:23:52 -0500 Subject: [PATCH 079/131] [VFS/ezfs] write dir folio checkpoint --- fs/rustezfs/dir.rs | 36 +++++++++++++++++++-- fs/rustezfs/ezfs.rs | 74 ++++++++++++++++++++++++++++--------------- rust/kernel/dentry.rs | 6 ++++ rust/kernel/folio.rs | 74 +++++++++++++++++++++++++++++++++++++++++-- rust/kernel/inode.rs | 8 +++++ 5 files changed, 168 insertions(+), 30 deletions(-) diff --git a/fs/rustezfs/dir.rs b/fs/rustezfs/dir.rs index 40a88ab6026f06..f54e3b15dc4b7d 100644 --- a/fs/rustezfs/dir.rs +++ b/fs/rustezfs/dir.rs @@ -1,6 +1,9 @@ use crate::defs::{EZFS_FILENAME_BUF_SIZE, EZFS_MAX_CHILDREN}; -use core::ops::Deref; -use kernel::transmute::{AsBytes, FromBytes}; +use core::ops::{Deref, DerefMut}; +use kernel::{ + prelude::*, + transmute::{AsBytes, FromBytes}, +}; #[repr(C)] #[derive(Clone, Copy)] @@ -28,6 +31,29 @@ impl EzfsDirEntry { &self.filename[..len] } + + pub(crate) fn set_inode_no(&mut self, ino: u64) -> &mut Self { + self.inode_no = ino; + + self + } + + pub(crate) fn set_active(&mut self) -> &mut Self { + self.active = 1; + + self + } + + pub(crate) fn set_filename(&mut self, filename: &[u8]) -> Result<&mut Self> { + if filename.len() > self.filename.len() { + return Err(ENAMETOOLONG); + } + + self.filename[..filename.len()].copy_from_slice(filename); + self.filename[filename.len()..].fill(0); + + Ok(self) + } } #[repr(C)] @@ -43,6 +69,12 @@ impl Deref for DirEntryStore { } } +impl DerefMut for DirEntryStore { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.dir_entries + } +} + // TODO: Add Safety unsafe impl FromBytes for DirEntryStore {} unsafe impl AsBytes for DirEntryStore {} diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 085730f2874575..7c6e1009a7913e 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -297,37 +297,59 @@ impl kernel::inode::Operations for RustEzFs { // TODO: Lock memory when writing DirEntries // TODO: Write DirEntry to memory - // - // let sb = parent.super_block(); - // let h = sb.data(); - // - // let ezfs_dir_inode = parent.data(); - // - // let offset = ezfs_dir_inode - // .data_blk_num() - // .checked_mul(EZFS_BLOCK_SIZE as u64) - // .ok_or(EIO)?; - // - // let mut mapped = h.mapper.mapped_folio(offset.try_into()?)?; - // let new_filename = dentry.name(); - // - // let dir_entries = - // DirEntryStore::from_bytes_mut(&mut mapped[..size_of::()]).ok_or(EIO)?; - // - // let dir_entry = dir_entries - // .iter_mut() - // .find(|x| !x.is_active()) - // .ok_or(ENOSPC)?; - // - // dir_entry - // .set_inode_no(new_inode.ino().try_into()?) - // .set_active() - // .set_filename(new_filename); + + let sb = parent.super_block(); + let h = sb.data(); + + let ezfs_dir_inode = parent.data(); + + let offset = ezfs_dir_inode + .data_blk_num() + .checked_mul(EZFS_BLOCK_SIZE as u64) + .ok_or(EIO)?; + + let new_filename = dentry.name(); + + let folio: ARef>> = + parent.read_mapping_folio(offset.try_into()?)?; + + let locked_folio = folio.lock(); + let mut guard = locked_folio.map(offset.try_into()?)?; + let mut dir_entries = + DirEntryStore::from_bytes_mut(&mut guard[..size_of::()]).ok_or(EIO)?; + + let dir_entry = dir_entries + .iter_mut() + .find(|x| !x.is_active()) + .ok_or(ENOSPC)?; + + dir_entry + .set_inode_no(new_inode.ino().try_into()?) + .set_active() + .set_filename(new_filename)?; new_inode.instantiate_dentry(&dentry); Ok(0) } + + fn unlink( + parent: &Locked<&INode, kernel::inode::ReadSem>, + dentry: dentry::Unhashed<'_, Self::FileSystem>, + ) -> Result { + let inode = dentry.inode(); + + // TODO: Erase DirEntry from page + + // TODO: change m and ctime for parent and inode + + inode.drop_nlink(); + + inode.mark_dirty(); + parent.mark_dirty(); + + todo!() + } } #[vtable] diff --git a/rust/kernel/dentry.rs b/rust/kernel/dentry.rs index 4ac78913e3f16a..e5df9a54190572 100644 --- a/rust/kernel/dentry.rs +++ b/rust/kernel/dentry.rs @@ -43,6 +43,12 @@ impl DEntry { // `d_sb` is immutable, so it's safe to read it. unsafe { SuperBlock::from_raw((*self.0.get()).d_sb) } } + + /// Gets the associated inode with dentry + pub fn inode(&self) -> &INode { + // SAFETY: VFS locking ensures d_inode is stable during filesystem operations. + unsafe { INode::from_raw((*self.0.get()).d_inode) } + } } pub struct Unhashed<'a, T: FileSystem + ?Sized>(pub(crate) &'a DEntry); diff --git a/rust/kernel/folio.rs b/rust/kernel/folio.rs index d4dbf4973ecf95..6fd9f9596a6e3f 100644 --- a/rust/kernel/folio.rs +++ b/rust/kernel/folio.rs @@ -1,10 +1,15 @@ -use core::{marker::PhantomData, ops::Deref, ptr}; +use core::{ + marker::PhantomData, + ops::{Deref, DerefMut}, + ptr, +}; use crate::{ error::Result, fs::FileSystem, + pr_info, prelude::EDOM, - types::{Lockable, Locked, ARef, AlwaysRefCounted, Opaque}, + types::{ARef, AlwaysRefCounted, Lockable, Locked, Opaque}, }; /// The type of a [`Folio`] is unspecified. @@ -186,15 +191,80 @@ impl Drop for MapGuard<'_> { } } +/// A mapped mutable [`Folio`]. +pub struct MapGuardMut<'a> { + data: &'a mut [u8], + page: *mut bindings::page, +} + +impl Deref for MapGuardMut<'_> { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + self.data + } +} + +impl DerefMut for MapGuardMut<'_> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.data + } +} + +impl Drop for MapGuardMut<'_> { + fn drop(&mut self) { + pr_info!("Dropped guard, set pag dirty and unmapped\n"); + // SAFETY: A `MapGuard` instance is only created when `kmap` succeeds, so it's ok to unmap + // it when the guard is dropped. + unsafe { + bindings::set_page_dirty(self.page); + bindings::kunmap(self.page) + }; + } +} + // SAFETY: `raw_lock` calls folio_lock, which actually locks the folio. unsafe impl Lockable for Folio { fn raw_lock(&self) { + pr_info!("Locked folio\n"); // SAFETY: The folio is valid because the shared reference implies a non-zero refcount. unsafe { bindings::folio_lock(self.0.get()) } } unsafe fn unlock(&self) { + pr_info!("unlocked folio\n"); // SAFETY: The safety requirements guarantee that the folio is locked. unsafe { bindings::folio_unlock(self.0.get()) } } } + +impl>, S> Locked { + /// SAFETY: it is guarenteed that the folio is locked by the type invariant + pub fn map(&self, offset: usize) -> Result> { + if offset > self.size() { + return Err(EDOM); + } + + let page_index = offset / bindings::PAGE_SIZE; + let page_offset = offset % bindings::PAGE_SIZE; + + // SAFETY: We just checked that the index is within bounds of the folio. + let page = unsafe { bindings::folio_page(self.0.get(), page_index) }; + + // SAFETY: `page` is valid because it was returned by `folio_page` above. + let ptr = unsafe { bindings::kmap(page) }; + + let size = if self.test_highmem() { + bindings::PAGE_SIZE + } else { + self.size() + }; + + // SAFETY: We just mapped `ptr`, so it's valid for read. + let data = unsafe { + core::slice::from_raw_parts_mut(ptr.cast::().add(page_offset), size - page_offset) + }; + + Ok(MapGuardMut { data, page }) + } +} diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index 39e1f465a4ea96..723ae13202cedf 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -129,6 +129,7 @@ impl INode { unsafe { (*self.0.get()).i_blocks } } + // FIXME: Does this work??? pub unsafe fn set_blocks(&self, num_blocks: u64) { unsafe { (*self.0.get()).i_blocks = num_blocks }; } @@ -168,6 +169,13 @@ impl INode { unsafe { &mut *(*outerp).data.as_mut_ptr() } } + pub fn drop_nlink(&self) { + let inode_ptr = self.0.get(); + unsafe { + bindings::drop_nlink(inode_ptr); + } + } + /// Returns a mapper for this inode. /// /// # Safety From a727507742f8747ec352557d09504464e1164494 Mon Sep 17 00:00:00 2001 From: lsig Date: Thu, 4 Dec 2025 01:47:07 -0500 Subject: [PATCH 080/131] [VFS] checkpoint?? --- fs/rustezfs/ezfs.rs | 14 ++++++++++++-- rust/kernel/inode.rs | 13 +++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 7c6e1009a7913e..5faa915684b248 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -311,13 +311,16 @@ impl kernel::inode::Operations for RustEzFs { let new_filename = dentry.name(); let folio: ARef>> = - parent.read_mapping_folio(offset.try_into()?)?; + h.mapper.read_mapping_folio(offset.try_into()?)?; + let folio_start = 0; let locked_folio = folio.lock(); - let mut guard = locked_folio.map(offset.try_into()?)?; + let mut guard = locked_folio.map(folio_start)?; let mut dir_entries = DirEntryStore::from_bytes_mut(&mut guard[..size_of::()]).ok_or(EIO)?; + pr_info!("create: dir_entries vaddr: {:p}\n", dir_entries as *const _); + let dir_entry = dir_entries .iter_mut() .find(|x| !x.is_active()) @@ -329,6 +332,7 @@ impl kernel::inode::Operations for RustEzFs { .set_filename(new_filename)?; new_inode.instantiate_dentry(&dentry); + parent.mark_dirty(); Ok(0) } @@ -422,6 +426,12 @@ impl file::Operations for RustEzFs { let dir_entries = DirEntryStore::from_bytes(&mapped[..size_of::()]).ok_or(EIO)?; + pr_info!( + "readdir: dir_entries vaddr: {:p}\n", + dir_entries as *const _ + ); + pr_info!("readdir: mapped vaddr: {:p}\n", mapped.as_ptr()); + let inode_store_offset = EZFS_INODE_STORE_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE; let mapped_inode_store = h.mapper.mapped_folio(inode_store_offset.try_into()?)?; let inode_store = diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index 723ae13202cedf..8292746ec0157f 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -390,6 +390,19 @@ impl Mapper { map.cap_len((self.end - offset).try_into()?); Ok(map) } + + pub fn read_mapping_folio( + &self, + offset: Offset, + ) -> Result>>> { + if offset < self.begin || offset >= self.end { + return Err(ERANGE); + } + + let page_index = offset >> bindings::PAGE_SHIFT; + let mut folio = self.inode.read_mapping_folio(page_index.try_into()?); + folio + } } struct WithData { From 87dfdee8507bd896b6d408a7637ad88096f1cd15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Thu, 4 Dec 2025 02:08:54 -0500 Subject: [PATCH 081/131] implement writeback_ops to persist --- fs/rustezfs/ezfs.rs | 6 ++-- rust/kernel/iomap.rs | 73 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 65 insertions(+), 14 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 672ff8aff79a7e..a9bdb87f68befb 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -248,7 +248,7 @@ impl kernel::inode::Operations for RustEzFs { let h = sb.data(); let name = dentry.name(); - pr_info!("lookup(name={:?})\n", core::str::from_utf8(name)); + // pr_info!("lookup(name={:?})\n", core::str::from_utf8(name)); if name.len() > EZFS_FILENAME_BUF_SIZE { return Err(ENAMETOOLONG); @@ -330,7 +330,7 @@ impl file::Operations for RustEzFs { inode: &Locked<&INode, kernel::inode::ReadSem>, emitter: &mut file::DirEmitter, ) -> Result { - pr_info!("read_dir()\n"); + // pr_info!("read_dir()\n"); let pos: usize = emitter.pos().try_into().map_err(|_| ENOENT)?; if pos < 2 { @@ -430,7 +430,7 @@ impl iomap::Operations for RustEzFs { length: Offset, flags: u32, map: &mut iomap::Map<'a>, - srcmap: &mut iomap::Map<'a>, + srcmap: Option<&mut iomap::Map<'a>>, ) -> Result { pr_info!("iomap_begin()\n"); diff --git a/rust/kernel/iomap.rs b/rust/kernel/iomap.rs index 5b485b2d297309..a75d02cc360487 100644 --- a/rust/kernel/iomap.rs +++ b/rust/kernel/iomap.rs @@ -166,6 +166,16 @@ pub mod flags { pub const DAX: u32 = bindings::IOMAP_DAX; } +// TODO: We should probably have this instead +// /// WritebackOperations implemented by iomap users. +// pub trait WritebackOperations { +// type FileSystem: FileSystem + ?Sized; +// +// fn writeback_range<'a>(folio: &'a Folio) -> Result; +// +// fn writeback_submit<'a>() -> Result; +// } + /// Operations implemented by iomap users. pub trait Operations { /// File system that these operations are compatible with. @@ -182,7 +192,7 @@ pub trait Operations { length: Offset, flags: u32, map: &mut Map<'a>, - srcmap: &mut Map<'a>, + srcmap: Option<&mut Map<'a>>, ) -> Result; /// Commits and/or unreserves space previously allocated using [`Operations::begin`]. `written` @@ -207,27 +217,61 @@ struct Table(PhantomData); impl Table { const WRITEBACK_TABLE: bindings::iomap_writeback_ops = bindings::iomap_writeback_ops { writeback_range: Some(Self::writeback_range_callback), - writeback_submit: Some(Self::writeback_submit), + writeback_submit: Some(Self::writeback_submit_callback), }; extern "C" fn writeback_range_callback( _wpc: *mut bindings::iomap_writepage_ctx, - _folio: *mut bindings::folio, + folio_ptr: *mut bindings::folio, pos: u64, len: u32, end_pos: u64, ) -> isize { from_result(|| { pr_info!("writeback_range()\n"); - Ok(len.try_into()?) + + let address_space_ptr = + unsafe { (*folio_ptr).__bindgen_anon_1.__bindgen_anon_1.mapping }; + let inode_ptr = unsafe { (*address_space_ptr).host }; + + let map = unsafe { &mut (*_wpc).iomap }; + + let res = Self::iomap_begin_callback( + inode_ptr, + pos as Offset, + len as Offset, + flags::WRITE, + map, + ptr::null_mut(), + ); + + pr_info!("writeback_range: result={res}\n"); + + to_result(res)?; + + let ret = unsafe { + bindings::iomap_add_to_ioend( + _wpc, + folio_ptr, + pos.try_into()?, + end_pos.try_into()?, + len, + ) + }; + to_result(ret.try_into()?)?; + + Ok(ret) }) } - extern "C" fn writeback_submit(_wpc: *mut bindings::iomap_writepage_ctx, _error: i32) -> i32 { - from_result(|| { - pr_info!("writeback_submit()\n"); - Ok(0) - }) + extern "C" fn writeback_submit_callback( + _wpc: *mut bindings::iomap_writepage_ctx, + _error: i32, + ) -> i32 { + pr_info!("writeback_submit()\n"); + + // SAFETY: VFS/iomap guarantees `wpc` is valid here. + unsafe { bindings::iomap_ioend_writeback_submit(_wpc, _error) } } const MAP_TABLE: bindings::iomap_ops = bindings::iomap_ops { @@ -246,6 +290,14 @@ impl Table { from_result(|| { // SAFETY: The C API guarantees that `inode_ptr` is a valid inode. let inode = unsafe { INode::from_raw(inode_ptr) }; + + let srcmap_opt: Option<&mut Map<'_>> = if srcmap.is_null() { + None + } else { + // SAFETY: We've just confirmed that srcmap is not null + Some(unsafe { &mut *srcmap.cast::>() }) + }; + T::begin( inode, pos, @@ -253,8 +305,7 @@ impl Table { flags, // SAFETY: The C API guarantees that `map` is valid for write. unsafe { &mut *map.cast::>() }, - // SAFETY: The C API guarantees that `srcmap` is valid for write. - unsafe { &mut *srcmap.cast::>() }, + srcmap_opt, )?; Ok(0) }) From 447adb770d00caa845ab144f28e42b4883b7c31e Mon Sep 17 00:00:00 2001 From: lsig Date: Thu, 4 Dec 2025 02:09:18 -0500 Subject: [PATCH 082/131] [ezfs] rm works but evict inode needed --- fs/rustezfs/dir.rs | 10 ++++++++++ fs/rustezfs/ezfs.rs | 36 ++++++++++++++++++++++++++++++------ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/fs/rustezfs/dir.rs b/fs/rustezfs/dir.rs index f54e3b15dc4b7d..aa167b96aaa8b7 100644 --- a/fs/rustezfs/dir.rs +++ b/fs/rustezfs/dir.rs @@ -54,6 +54,16 @@ impl EzfsDirEntry { Ok(self) } + + pub(crate) fn zero(&mut self) -> &mut Self { + let len = self.filename.len(); + + self.inode_no = 0; + self.active = 0; + self.filename[..len].fill(0); + + self + } } #[repr(C)] diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 5faa915684b248..551bca0f24d08a 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -295,8 +295,7 @@ impl kernel::inode::Operations for RustEzFs { let new_inode = Self::new_inode(parent, mode.into())?; - // TODO: Lock memory when writing DirEntries - // TODO: Write DirEntry to memory + // TODO: Write Inode to memory let sb = parent.super_block(); let h = sb.data(); @@ -319,8 +318,6 @@ impl kernel::inode::Operations for RustEzFs { let mut dir_entries = DirEntryStore::from_bytes_mut(&mut guard[..size_of::()]).ok_or(EIO)?; - pr_info!("create: dir_entries vaddr: {:p}\n", dir_entries as *const _); - let dir_entry = dir_entries .iter_mut() .find(|x| !x.is_active()) @@ -341,18 +338,45 @@ impl kernel::inode::Operations for RustEzFs { parent: &Locked<&INode, kernel::inode::ReadSem>, dentry: dentry::Unhashed<'_, Self::FileSystem>, ) -> Result { + let sb = parent.super_block(); + let h = sb.data(); + let inode = dentry.inode(); + let filename = dentry.name(); + + let ezfs_dir_inode = parent.data(); + + // Erase DirEntry from page + let offset = ezfs_dir_inode + .data_blk_num() + .checked_mul(EZFS_BLOCK_SIZE as u64) + .ok_or(EIO)?; + + let folio: ARef>> = + h.mapper.read_mapping_folio(offset.try_into()?)?; + + let folio_start = 0; + let locked_folio = folio.lock(); + let mut guard = locked_folio.map(folio_start)?; + let mut dir_entries = + DirEntryStore::from_bytes_mut(&mut guard[..size_of::()]).ok_or(EIO)?; + + let dir_entry = dir_entries + .iter_mut() + .find(|x| x.filename() == filename) + .ok_or(ENOENT)?; - // TODO: Erase DirEntry from page + dir_entry.zero(); // TODO: change m and ctime for parent and inode + // TODO: Implemnt evict_inode inode.drop_nlink(); inode.mark_dirty(); parent.mark_dirty(); - todo!() + Ok(0) } } From 18f9850da94a763f206865fe993db9194ff20452 Mon Sep 17 00:00:00 2001 From: lsig Date: Thu, 4 Dec 2025 02:15:10 -0500 Subject: [PATCH 083/131] [ezfs] remove unnecessary prints --- fs/rustezfs/ezfs.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 551bca0f24d08a..f89522131fd980 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -450,12 +450,6 @@ impl file::Operations for RustEzFs { let dir_entries = DirEntryStore::from_bytes(&mapped[..size_of::()]).ok_or(EIO)?; - pr_info!( - "readdir: dir_entries vaddr: {:p}\n", - dir_entries as *const _ - ); - pr_info!("readdir: mapped vaddr: {:p}\n", mapped.as_ptr()); - let inode_store_offset = EZFS_INODE_STORE_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE; let mapped_inode_store = h.mapper.mapped_folio(inode_store_offset.try_into()?)?; let inode_store = From 2a14753da243b8ddae836cc32424be0f62a815d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Thu, 4 Dec 2025 02:22:47 -0500 Subject: [PATCH 084/131] cleanup --- rust/kernel/iomap.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/rust/kernel/iomap.rs b/rust/kernel/iomap.rs index a75d02cc360487..71bae6a86a9a1d 100644 --- a/rust/kernel/iomap.rs +++ b/rust/kernel/iomap.rs @@ -221,7 +221,7 @@ impl Table { }; extern "C" fn writeback_range_callback( - _wpc: *mut bindings::iomap_writepage_ctx, + wpc: *mut bindings::iomap_writepage_ctx, folio_ptr: *mut bindings::folio, pos: u64, len: u32, @@ -230,11 +230,19 @@ impl Table { from_result(|| { pr_info!("writeback_range()\n"); + // SAFETY: For this callback, iomap guarantees: + // - `folio_ptr` points to a live `struct folio`. + // - The folio remains valid and locked for the duration of this call. let address_space_ptr = unsafe { (*folio_ptr).__bindgen_anon_1.__bindgen_anon_1.mapping }; + + // SAFETY: when iomap_writepages is called, `mapping` is non-NULL and + // its `host` field points to the owning `struct inode`. let inode_ptr = unsafe { (*address_space_ptr).host }; - let map = unsafe { &mut (*_wpc).iomap }; + // SAFETY: `wpc` is guaranteed to be valid. + // `iomap` is valid storage that we are allowed to mutate. + let map = unsafe { &mut (*wpc).iomap }; let res = Self::iomap_begin_callback( inode_ptr, @@ -245,13 +253,13 @@ impl Table { ptr::null_mut(), ); - pr_info!("writeback_range: result={res}\n"); - to_result(res)?; + // SAFETY: all arguments provided were provided by the caller + // This is the go-to method for completing writebacks let ret = unsafe { bindings::iomap_add_to_ioend( - _wpc, + wpc, folio_ptr, pos.try_into()?, end_pos.try_into()?, From d044f27fd75783facf486638208d90e801a822d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Thu, 4 Dec 2025 02:36:35 -0500 Subject: [PATCH 085/131] address comments --- rust/kernel/iomap.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/rust/kernel/iomap.rs b/rust/kernel/iomap.rs index 71bae6a86a9a1d..866c02204d0e33 100644 --- a/rust/kernel/iomap.rs +++ b/rust/kernel/iomap.rs @@ -5,7 +5,7 @@ //! C headers: [`include/linux/iomap.h`](srctree/include/linux/iomap.h) use super::address_space; -use crate::error::to_result; +use crate::error::{to_result, Error}; use crate::iov::IovIterSource; use crate::pr_info; use crate::prelude::{EIO, EOVERFLOW}; @@ -244,7 +244,7 @@ impl Table { // `iomap` is valid storage that we are allowed to mutate. let map = unsafe { &mut (*wpc).iomap }; - let res = Self::iomap_begin_callback( + let ret = Self::iomap_begin_callback( inode_ptr, pos as Offset, len as Offset, @@ -253,7 +253,9 @@ impl Table { ptr::null_mut(), ); - to_result(res)?; + if ret < 0 { + return Err(Error::from_errno(ret.try_into()?)); + } // SAFETY: all arguments provided were provided by the caller // This is the go-to method for completing writebacks @@ -266,20 +268,23 @@ impl Table { len, ) }; - to_result(ret.try_into()?)?; + + if ret < 0 { + return Err(Error::from_errno(ret.try_into()?)); + } Ok(ret) }) } extern "C" fn writeback_submit_callback( - _wpc: *mut bindings::iomap_writepage_ctx, - _error: i32, + wpc: *mut bindings::iomap_writepage_ctx, + error: i32, ) -> i32 { pr_info!("writeback_submit()\n"); // SAFETY: VFS/iomap guarantees `wpc` is valid here. - unsafe { bindings::iomap_ioend_writeback_submit(_wpc, _error) } + unsafe { bindings::iomap_ioend_writeback_submit(wpc, error) } } const MAP_TABLE: bindings::iomap_ops = bindings::iomap_ops { From 6bc0487f9560089c03d789da413a2fe10b234ca9 Mon Sep 17 00:00:00 2001 From: lsig Date: Thu, 4 Dec 2025 02:43:50 -0500 Subject: [PATCH 086/131] [ezfs] add safety --- rust/kernel/inode.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index 8292746ec0157f..80655e0bbaaf09 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -171,6 +171,7 @@ impl INode { pub fn drop_nlink(&self) { let inode_ptr = self.0.get(); + // SAFETY: Inode ptr is guaranteed to be valid and instantiated do to the typestate unsafe { bindings::drop_nlink(inode_ptr); } From 48c742213322452c67d3bf976ebb8284c1f76afd Mon Sep 17 00:00:00 2001 From: lsig Date: Sat, 6 Dec 2025 16:07:07 -0500 Subject: [PATCH 087/131] [VFS] make sb operations generic --- fs/rustezfs/ezfs.rs | 5 +++ rust/kernel/fs.rs | 13 +++++-- rust/kernel/fs/file.rs | 3 +- rust/kernel/inode.rs | 3 +- rust/kernel/sb.rs | 81 +++++++++++++++++++++++++++++++++++++++++- 5 files changed, 98 insertions(+), 7 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index c153faf88e1bd7..04e9f4f2f86e8b 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -500,6 +500,11 @@ impl file::Operations for RustEzFs { } } +#[vtable] +impl kernel::sb::Operations for RustEzFs { + type FileSystem = Self; +} + impl iomap::Operations for RustEzFs { type FileSystem = Self; diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs index 85466d502f67e4..0763a017e23a65 100644 --- a/rust/kernel/fs.rs +++ b/rust/kernel/fs.rs @@ -69,7 +69,7 @@ pub mod mode { } /// A file system type. -pub trait FileSystem { +pub trait FileSystem: sb::Operations { /// Data associated with each file system instance (super-block). type Data: ForeignOwnable + Send + Sync; @@ -119,6 +119,12 @@ impl FileSystem for UnspecifiedFS { } } +// Minimal set of sb operations (just fallback on default) +#[vtable] +impl kernel::sb::Operations for UnspecifiedFS { + type FileSystem = Self; +} + /// A file system registration. #[pin_data(PinnedDrop)] pub struct Registration { @@ -247,7 +253,10 @@ impl Tables { // SAFETY: The callback contract guarantees that `sb_ptr`, from which `new_sb` is // derived, is valid for write. let sb = unsafe { &mut *new_sb.0.get() }; - sb.s_op = &Tables::::SUPER_BLOCK; + let sops = sb::Ops::::new::(); + let sops_ptr = unsafe { sops.inner }; + // sb.s_op = &Tables::::SUPER_BLOCK; + sb.s_op = sops_ptr; let mapper = if matches!(T::SUPER_TYPE, sb::Type::BlockDev) { // SAFETY: This is the only mapper created for this inode, so it is unique. diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index 2ff0e2db4ebb21..10b7ee5153df2f 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -7,8 +7,7 @@ //! C headers: [`include/linux/fs.h`](srctree/include/linux/fs.h) and //! [`include/linux/file.h`](srctree/include/linux/file.h) -use macros::vtable; - +use crate::prelude::*; use crate::{ bindings, cred::Credential, diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index 80655e0bbaaf09..e73668018116cc 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -2,7 +2,6 @@ use core::marker::PhantomData; use core::mem::{ManuallyDrop, MaybeUninit}; use bindings::{init_user_ns, kgid_t, kuid_t}; -use macros::vtable; use crate::address_space; use crate::dentry::{self, DEntry}; @@ -11,7 +10,7 @@ use crate::folio::{self, Folio}; use crate::fs::{self, mode, Registration}; use crate::fs::{file, PageOffset, UnspecifiedFS}; use crate::mem_cache::MemCache; -use crate::prelude::{EINVAL, EIO, ENOTSUPP, ERANGE, GFP_KERNEL}; +use crate::prelude::*; use crate::sb::SuperBlock; use crate::str::CString; use crate::time::Timespec; diff --git a/rust/kernel/sb.rs b/rust/kernel/sb.rs index 52bc261ad0f455..6e775e42816cb8 100644 --- a/rust/kernel/sb.rs +++ b/rust/kernel/sb.rs @@ -4,8 +4,8 @@ use core::{ ptr::{self, NonNull}, }; -use crate::error::{code::*, from_err_ptr, Result}; use crate::page::{BorrowedPage, Page}; +use crate::prelude::*; use crate::types::{ARef, ForeignOwnable}; use crate::{block, inode}; use crate::{ @@ -14,6 +14,10 @@ use crate::{ inode::{INodeState, Ino}, types::Opaque, }; +use crate::{ + error::{code::*, from_err_ptr, Result}, + inode::INode, +}; pub enum Type { /// Multiple independent superblocks may exist. @@ -22,6 +26,16 @@ pub enum Type { BlockDev, } +/// Operations implemented by super blocks +#[vtable] +pub trait Operations { + type FileSystem: FileSystem + ?Sized; + + fn evict_inode(_inode: &INode) -> Result { + Err(ENOTSUPP) + } +} + /// Indicates that a superblock in this typestate has data initialized. /// /// # Safety @@ -227,3 +241,68 @@ impl SuperBlock { Ok(inode::New(new_inode, PhantomData)) } } + +/// Represents inode operations. +pub struct Ops { + pub(crate) inner: *const bindings::super_operations, + _p: PhantomData, +} + +impl Ops { + pub const fn new + ?Sized>() -> Self { + struct Table(PhantomData); + impl Table { + const TABLE: bindings::super_operations = bindings::super_operations { + alloc_inode: if size_of::<::INodeData>() != 0 { + Some(INode::::alloc_inode_callback) + } else { + None + }, + destroy_inode: Some(INode::::destroy_inode_callback), + free_inode: None, + dirty_inode: None, + write_inode: None, + drop_inode: None, + evict_inode: if T::HAS_EVICT_INODE { + Some(Self::evict_inode_callback) + } else { + None + }, + put_super: None, + sync_fs: None, + freeze_super: None, + freeze_fs: None, + thaw_super: None, + unfreeze_fs: None, + statfs: None, + remount_fs: None, + remove_bdev: None, // TODO: New field, research + umount_begin: None, + show_options: None, + show_devname: None, + show_path: None, + show_stats: None, + #[cfg(CONFIG_QUOTA)] + quota_read: None, + #[cfg(CONFIG_QUOTA)] + quota_write: None, + #[cfg(CONFIG_QUOTA)] + get_dquots: None, + nr_cached_objects: None, + free_cached_objects: None, + shutdown: None, + }; + + unsafe extern "C" fn evict_inode_callback(inode_ptr: *mut bindings::inode) { + // SAFETY: The C API guarantees that `inode_ptr` is a valid inode. + let inode = unsafe { INode::from_raw(inode_ptr) }; + + T::evict_inode(inode); // TODO: Should this return something? + } + } + Self { + inner: &Table::::TABLE, + _p: PhantomData, + } + } +} From 81079da0a4b5b2a4a7d9cbb39648e6d59e61a4d4 Mon Sep 17 00:00:00 2001 From: lsig Date: Sun, 7 Dec 2025 21:11:55 -0500 Subject: [PATCH 088/131] [ezfs] evict_inode checkpoint --- fs/rustezfs/ezfs.rs | 28 ++++++++++++++++++++++++++++ fs/rustezfs/sb.rs | 10 +++++----- rust/kernel/inode.rs | 18 ++++++++++++++++++ 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 04e9f4f2f86e8b..182376847f6b6c 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -503,6 +503,34 @@ impl file::Operations for RustEzFs { #[vtable] impl kernel::sb::Operations for RustEzFs { type FileSystem = Self; + + fn evict_inode(inode: &INode) -> Result { + let sb = inode.super_block().data(); + + if (inode.nlink() == 0) { + let ino: u64 = inode.ino().try_into()?; + + let mut free_inodes = sb.free_inodes.lock(); + let mut free_data_blocks = sb.free_data_blocks.lock(); + let mut zero_data_blocks = sb.zero_data_blocks.lock(); + + let ezfs_inode = inode.data(); + let start = ezfs_inode.data_blk_num(); + let end = start + inode.blocks(); + + for data_blk in start..end { + free_data_blocks.clear_bit(data_blk - EZFS_ROOT_DATABLOCK_NUMBER as u64); + zero_data_blocks.clear_bit(data_blk - EZFS_ROOT_DATABLOCK_NUMBER as u64); + } + + free_inodes.clear_bit(ino); + } + + // TODO: Mark sb and inode store dirty + + inode.truncate_inode_pages_final(); + inode.clear(); + } } impl iomap::Operations for RustEzFs { diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index c1302c82341460..2a93ed5ec03f3d 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -20,7 +20,7 @@ pub(crate) struct EzfsSuperblockDiskRaw { disk_blocks: u64, free_inodes: [u32; (EZFS_MAX_INODES / 32) + 1], free_data_blocks: [u32; (EZFS_MAX_DATA_BLKS / 32) + 1], - zero_data_blocks: [u8; (EZFS_MAX_DATA_BLKS / 32) + 1], + zero_data_blocks: [u32; (EZFS_MAX_DATA_BLKS / 32) + 1], } // TODO: assert size is equal to 4096 bytes @@ -92,11 +92,11 @@ pub(crate) struct EzfsSuperblock { pub(crate) magic: u64, pub(crate) disk_blocks: u64, #[pin] - pub(crate) free_inodes: Mutex<[u32; (EZFS_MAX_INODES / 32) + 1]>, + pub(crate) free_inodes: Mutex>, #[pin] pub(crate) free_data_blocks: Mutex>, #[pin] - pub(crate) zero_data_blocks: Mutex<[u8; (EZFS_MAX_DATA_BLKS / 32) + 1]>, + pub(crate) zero_data_blocks: Mutex>, #[pin] sb_lock: Mutex<()>, pub(crate) mapper: inode::Mapper, @@ -111,9 +111,9 @@ impl EzfsSuperblock { version: disk_sb.data.version, magic: disk_sb.data.magic, disk_blocks: disk_sb.data.disk_blocks, - free_inodes <- new_mutex!(disk_sb.data.free_inodes), + free_inodes <- new_mutex!(Bitmap::new(disk_sb.data.free_inodes)), free_data_blocks <- new_mutex!(Bitmap::new(disk_sb.data.free_data_blocks)), - zero_data_blocks <- new_mutex!(disk_sb.data.zero_data_blocks), + zero_data_blocks <- new_mutex!(Bitmap::new(disk_sb.data.zero_data_blocks)), sb_lock <- new_mutex!(()), mapper, }) diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index e73668018116cc..804d11c6d6040a 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -128,6 +128,24 @@ impl INode { unsafe { (*self.0.get()).i_blocks } } + pub fn nlink(&self) -> u32 { + // SAFETY: this is ok + unsafe { (*self.0.get()).__bindgen_anon_1.i_nlink } + } + + pub fn truncate_inode_pages_final(&self) { + // SAFETY: type semantics guarentee that Inode is instatiated + let data = unsafe { ptr::addr_of_mut!((*self.0.get()).i_data) }; + unsafe { bindings::truncate_inode_pages_final(data) } + } + + // FIXME: should consume self so you can't call any methods after clearing + pub fn clear(&self) { + // SAFETY: type semantics guarentee that Inode is instatiated + let inode_ptr = self.0.get(); + unsafe { bindings::clear_inode(inode_ptr) } + } + // FIXME: Does this work??? pub unsafe fn set_blocks(&self, num_blocks: u64) { unsafe { (*self.0.get()).i_blocks = num_blocks }; From de33e2c26710424d50f3df3ce878520f235cdb11 Mon Sep 17 00:00:00 2001 From: lsig Date: Sun, 7 Dec 2025 21:52:40 -0500 Subject: [PATCH 089/131] [ezfs] clean up --- fs/rustezfs/dir.rs | 2 +- fs/rustezfs/ezfs.rs | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/fs/rustezfs/dir.rs b/fs/rustezfs/dir.rs index aa167b96aaa8b7..21025ab90cdb86 100644 --- a/fs/rustezfs/dir.rs +++ b/fs/rustezfs/dir.rs @@ -60,7 +60,7 @@ impl EzfsDirEntry { self.inode_no = 0; self.active = 0; - self.filename[..len].fill(0); + self.filename.fill(0); self } diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 182376847f6b6c..3f3e7fe28d0d68 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -369,7 +369,6 @@ impl kernel::inode::Operations for RustEzFs { dir_entry.zero(); // TODO: change m and ctime for parent and inode - // TODO: Implemnt evict_inode inode.drop_nlink(); @@ -419,7 +418,7 @@ impl file::Operations for RustEzFs { } } - let sb = &*inode.super_block(); + let sb = inode.super_block(); let h = sb.data(); let index = { @@ -505,11 +504,11 @@ impl kernel::sb::Operations for RustEzFs { type FileSystem = Self; fn evict_inode(inode: &INode) -> Result { - let sb = inode.super_block().data(); - if (inode.nlink() == 0) { + let sb = inode.super_block().data(); let ino: u64 = inode.ino().try_into()?; + // TODO: Make sub-struct which the mutex owns let mut free_inodes = sb.free_inodes.lock(); let mut free_data_blocks = sb.free_data_blocks.lock(); let mut zero_data_blocks = sb.zero_data_blocks.lock(); @@ -528,8 +527,11 @@ impl kernel::sb::Operations for RustEzFs { // TODO: Mark sb and inode store dirty + // TODO: Make clear consume inode inode.truncate_inode_pages_final(); inode.clear(); + + Ok(()) } } From 1df655cd832ec1323763458b9b1cabf5ecbb2f27 Mon Sep 17 00:00:00 2001 From: lsig Date: Sun, 7 Dec 2025 21:56:35 -0500 Subject: [PATCH 090/131] [VFS] clean up comment and unsafe --- rust/kernel/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs index 0763a017e23a65..39629140917bf8 100644 --- a/rust/kernel/fs.rs +++ b/rust/kernel/fs.rs @@ -254,8 +254,8 @@ impl Tables { // derived, is valid for write. let sb = unsafe { &mut *new_sb.0.get() }; let sops = sb::Ops::::new::(); - let sops_ptr = unsafe { sops.inner }; - // sb.s_op = &Tables::::SUPER_BLOCK; + let sops_ptr = sops.inner; + sb.s_op = sops_ptr; let mapper = if matches!(T::SUPER_TYPE, sb::Type::BlockDev) { From 4ee4cefa011d24ae43acc602688e01955f500b90 Mon Sep 17 00:00:00 2001 From: lsig Date: Mon, 8 Dec 2025 18:11:28 -0500 Subject: [PATCH 091/131] [ezfs/VFS] checkpoint clean up and write_inode --- fs/rustezfs/ezfs.rs | 78 ++++++++++++++++++++++++++++++-------------- fs/rustezfs/inode.rs | 35 ++++++++++++++++++-- fs/rustezfs/sb.rs | 27 +++++++-------- rust/kernel/fs.rs | 37 --------------------- rust/kernel/inode.rs | 37 +++++++++++++++++++++ rust/kernel/sb.rs | 30 +++++++++++++++-- 6 files changed, 163 insertions(+), 81 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 3f3e7fe28d0d68..05f3f4bbc824a0 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -64,14 +64,22 @@ impl RustEzFs { INodeState::Uninitilized(new_inode) => new_inode, }; - let h = &*sb.data(); + let ezfs_sb = sb.data(); + + { + // Check if inode is allocated + let sb_data = ezfs_sb.data.lock(); + if !sb_data.free_inodes.is_set(ino.try_into()?) { + return Err(ENOENT); + } + } let offset = EZFS_INODE_STORE_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE; - let mapped_inode_store = h.mapper.mapped_folio(offset.try_into()?)?; + let mapped_inode_store = ezfs_sb.mapper.mapped_folio(offset.try_into()?)?; let inode_store = InodeStore::from_bytes(&mapped_inode_store[..size_of::()]).ok_or(EIO)?; - let ezfs_inode = inode_store[ino - 1]; + let ezfs_inode = inode_store[ino - EZFS_ROOT_INODE_NUMBER]; let mode = ezfs_inode.mode(); let typ = match mode & fs::mode::S_IFMT { @@ -105,15 +113,15 @@ impl RustEzFs { fn allocate_inode(sb: &SuperBlock) -> Result { let ezfs_sb = sb.data(); - let mut free_inodes = ezfs_sb.free_inodes.lock(); + let mut sb_data = ezfs_sb.data.lock(); - for (word_idx, &word) in free_inodes.iter().enumerate() { + for (word_idx, &word) in sb_data.free_inodes.iter().enumerate() { if word != !0u32 { let bit_idx: u32 = (!word).trailing_zeros(); let inode_num: usize = (word_idx as usize * 32) + bit_idx as usize; if inode_num < EZFS_MAX_INODES { - free_inodes[word_idx] |= 1 << bit_idx; + sb_data.free_inodes[word_idx] |= 1 << bit_idx; return Ok(inode_num + 1); // FS is 1-indexed } } @@ -508,23 +516,25 @@ impl kernel::sb::Operations for RustEzFs { let sb = inode.super_block().data(); let ino: u64 = inode.ino().try_into()?; - // TODO: Make sub-struct which the mutex owns - let mut free_inodes = sb.free_inodes.lock(); - let mut free_data_blocks = sb.free_data_blocks.lock(); - let mut zero_data_blocks = sb.zero_data_blocks.lock(); - let ezfs_inode = inode.data(); let start = ezfs_inode.data_blk_num(); let end = start + inode.blocks(); + let mut sb_data = sb.data.lock(); + for data_blk in start..end { - free_data_blocks.clear_bit(data_blk - EZFS_ROOT_DATABLOCK_NUMBER as u64); - zero_data_blocks.clear_bit(data_blk - EZFS_ROOT_DATABLOCK_NUMBER as u64); + sb_data + .free_data_blocks + .clear_bit(data_blk - EZFS_ROOT_DATABLOCK_NUMBER as u64); + sb_data + .zero_data_blocks + .clear_bit(data_blk - EZFS_ROOT_DATABLOCK_NUMBER as u64); } - free_inodes.clear_bit(ino); + sb_data.free_inodes.clear_bit(ino); } + // TODO: remove inode from disk // TODO: Mark sb and inode store dirty // TODO: Make clear consume inode @@ -533,6 +543,26 @@ impl kernel::sb::Operations for RustEzFs { Ok(()) } + + fn write_inode(inode: &INode) -> Result { + let h = inode.super_block().data(); + let ino = inode.ino(); + let disk_inode = EzfsInode::from_vfs_inode(inode)?; + + let offset = (EZFS_INODE_STORE_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE) as u64; + let folio: ARef>> = + h.mapper.read_mapping_folio(offset.try_into()?)?; + + let folio_start = 0; + let locked_folio = folio.lock(); + let mut guard = locked_folio.map(folio_start)?; + let mut inodes = + InodeStore::from_bytes_mut(&mut guard[..size_of::()]).ok_or(EIO)?; + + inodes[ino - EZFS_ROOT_INODE_NUMBER] = disk_inode; + + Ok(0) + } } impl iomap::Operations for RustEzFs { @@ -590,7 +620,7 @@ impl iomap::Operations for RustEzFs { // We're writing // As we'll modify the file system below, we must acquire a lock - ezfs_sb.lock(); + let mut sb_data = ezfs_sb.data.lock(); let max_blocks = Self::get_max_blocks(ezfs_sb); let blocks_needed = end_block + 1; @@ -608,7 +638,6 @@ impl iomap::Operations for RustEzFs { MOVE, // File has no adjacent, free block and must be moved } - let mut free_data_blocks = ezfs_sb.free_data_blocks.lock(); let ez_blk_sidx = ez_blk_num.saturating_sub(EZFS_ROOT_DATABLOCK_NUMBER as u64); let case_type = if ez_blk_num == 0 { @@ -625,7 +654,7 @@ impl iomap::Operations for RustEzFs { // pr_info!("start={start} - end={end}\n"); - if (start..end).any(|bit| free_data_blocks.is_set(bit)) { + if (start..end).any(|bit| sb_data.free_data_blocks.is_set(bit)) { WriteCase::MOVE } else { WriteCase::EXTEND @@ -641,7 +670,7 @@ impl iomap::Operations for RustEzFs { WriteCase::EXTEND => { for i in ez_blk_count..blocks_needed { let bit = ez_blk_sidx + i; - free_data_blocks.set_bit(bit); + sb_data.free_data_blocks.set_bit(bit); } map.set_flags(iomap::map_flags::NEW); @@ -653,7 +682,7 @@ impl iomap::Operations for RustEzFs { let mut seen_free = 0; while seen_free < blocks_needed && curr_block < max_blocks { // if block isn't free, we reset counter - if free_data_blocks.is_set(curr_block) { + if sb_data.free_data_blocks.is_set(curr_block) { seen_free = 0; } else { seen_free += 1; @@ -676,8 +705,8 @@ impl iomap::Operations for RustEzFs { Self::move_block(old, new, sb); - free_data_blocks.clear_bit(old); - free_data_blocks.set_bit(new); + sb_data.free_data_blocks.clear_bit(old); + sb_data.free_data_blocks.set_bit(new); } } @@ -710,10 +739,11 @@ impl iomap::Operations for RustEzFs { let new_blocks = ((inode.size() + (EZFS_BLOCK_SIZE as i64) - 1) / EZFS_BLOCK_SIZE as i64) as u64; let sb = inode.super_block(); - let ezfs_sb = sb.data(); - + // TODO: do we need inode lock? and should we store inode store in sb? + // iomap locking docks (see locking hierarcy): https://docs.kernel.org/6.16/_sources/filesystems/iomap/design.rst.txt + // let ezfs_sb = sb.data(); // We'll modify our inodes, let's lock first - ezfs_sb.lock(); + // ezfs_sb.lock(); // SAFETY: We've acquired the super block lock unsafe { inode.set_blocks(new_blocks * 8) }; diff --git a/fs/rustezfs/inode.rs b/fs/rustezfs/inode.rs index cee71bd92a1ba9..9456802f99b0f7 100644 --- a/fs/rustezfs/inode.rs +++ b/fs/rustezfs/inode.rs @@ -1,8 +1,9 @@ -use crate::defs::*; -use core::ops::Deref; +use crate::{defs::*, RustEzFs}; +use core::ops::{Deref, DerefMut}; use kernel::error::Result; +use kernel::inode::INode; use kernel::time::Timespec; -use kernel::transmute::FromBytes; +use kernel::transmute::{AsBytes, FromBytes}; use kernel::uapi::{gid_t, mode_t, uid_t}; #[repr(C)] @@ -21,6 +22,27 @@ pub(crate) struct EzfsInode { } impl EzfsInode { + pub(crate) fn from_vfs_inode(vfs_inode: &INode) -> Result { + let mut disk_inode = EzfsInode::default(); + + let mtime_sec = vfs_inode.mtime()?.tv_sec(); + let ctime_sec = vfs_inode.ctime()?.tv_sec(); + let atime_sec = vfs_inode.atime()?.tv_sec(); + + disk_inode.set_file_size(vfs_inode.size().try_into()?); + disk_inode.set_nblocks(vfs_inode.blocks() / 8); + disk_inode.set_mode(vfs_inode.mode() as u32); + disk_inode.set_uid(vfs_inode.uid()); + disk_inode.set_gid(vfs_inode.gid()); + disk_inode.set_nlink(vfs_inode.nlink()); + disk_inode.set_atime(atime_sec); + disk_inode.set_ctime(ctime_sec); + disk_inode.set_mtime(mtime_sec); + disk_inode.set_data_block_num(vfs_inode.data().data_blk_num()); + + Ok(disk_inode) + } + pub(crate) fn mode(&self) -> mode_t { self.mode } @@ -135,5 +157,12 @@ impl Deref for InodeStore { } } +impl DerefMut for InodeStore { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inodes + } +} + // SAFETY: EzfsInode is FromBytes, so array of them is too unsafe impl FromBytes for InodeStore {} +unsafe impl AsBytes for InodeStore {} diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index 2a93ed5ec03f3d..c824d9d9602289 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -92,16 +92,16 @@ pub(crate) struct EzfsSuperblock { pub(crate) magic: u64, pub(crate) disk_blocks: u64, #[pin] - pub(crate) free_inodes: Mutex>, - #[pin] - pub(crate) free_data_blocks: Mutex>, - #[pin] - pub(crate) zero_data_blocks: Mutex>, - #[pin] - sb_lock: Mutex<()>, + pub(crate) data: Mutex, pub(crate) mapper: inode::Mapper, } +pub(crate) struct EzfsSuperblockData { + pub(crate) free_inodes: Bitmap<{ (EZFS_MAX_INODES / 32) + 1 }>, + pub(crate) free_data_blocks: Bitmap<{ (EZFS_MAX_DATA_BLKS / 32) + 1 }>, + pub(crate) zero_data_blocks: Bitmap<{ (EZFS_MAX_DATA_BLKS / 32) + 1 }>, +} + impl EzfsSuperblock { pub(crate) fn new( disk_sb: EzfsSuperblockDisk, @@ -111,10 +111,11 @@ impl EzfsSuperblock { version: disk_sb.data.version, magic: disk_sb.data.magic, disk_blocks: disk_sb.data.disk_blocks, - free_inodes <- new_mutex!(Bitmap::new(disk_sb.data.free_inodes)), - free_data_blocks <- new_mutex!(Bitmap::new(disk_sb.data.free_data_blocks)), - zero_data_blocks <- new_mutex!(Bitmap::new(disk_sb.data.zero_data_blocks)), - sb_lock <- new_mutex!(()), + data <- new_mutex!(EzfsSuperblockData { + free_inodes: Bitmap::new(disk_sb.data.free_inodes), + free_data_blocks: Bitmap::new(disk_sb.data.free_data_blocks), + zero_data_blocks: Bitmap::new(disk_sb.data.zero_data_blocks), + }), mapper, }) } @@ -122,8 +123,4 @@ impl EzfsSuperblock { pub(crate) fn magic(&self) -> u64 { self.magic } - - pub(crate) fn lock(&self) -> Guard<'_, (), MutexBackend> { - self.sb_lock.lock() - } } diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs index 39629140917bf8..a9fd584ae55521 100644 --- a/rust/kernel/fs.rs +++ b/rust/kernel/fs.rs @@ -290,41 +290,4 @@ impl Tables { Ok(0) }) } - - const SUPER_BLOCK: bindings::super_operations = bindings::super_operations { - alloc_inode: if size_of::() != 0 { - Some(INode::::alloc_inode_callback) - } else { - None - }, - destroy_inode: Some(INode::::destroy_inode_callback), - free_inode: None, - dirty_inode: None, - write_inode: None, - drop_inode: None, - evict_inode: None, - put_super: None, - sync_fs: None, - freeze_super: None, - freeze_fs: None, - thaw_super: None, - unfreeze_fs: None, - statfs: None, - remount_fs: None, - remove_bdev: None, // TODO: New field, research - umount_begin: None, - show_options: None, - show_devname: None, - show_path: None, - show_stats: None, - #[cfg(CONFIG_QUOTA)] - quota_read: None, - #[cfg(CONFIG_QUOTA)] - quota_write: None, - #[cfg(CONFIG_QUOTA)] - get_dquots: None, - nr_cached_objects: None, - free_cached_objects: None, - shutdown: None, - }; } diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index 804d11c6d6040a..848ca8792ea33a 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -133,6 +133,43 @@ impl INode { unsafe { (*self.0.get()).__bindgen_anon_1.i_nlink } } + pub fn ctime(&self) -> Result { + let sec = unsafe { (*self.0.get()).i_ctime_sec }; + let nsec = unsafe { (*self.0.get()).i_ctime_nsec }; + + Timespec::new(sec.try_into()?, nsec) + } + + pub fn mtime(&self) -> Result { + let sec = unsafe { (*self.0.get()).i_mtime_sec }; + let nsec = unsafe { (*self.0.get()).i_mtime_nsec }; + + Timespec::new(sec.try_into()?, nsec) + } + + pub fn atime(&self) -> Result { + let sec = unsafe { (*self.0.get()).i_atime_sec }; + let nsec = unsafe { (*self.0.get()).i_atime_nsec }; + + Timespec::new(sec.try_into()?, nsec) + } + + pub fn uid(&self) -> u32 { + let uid = unsafe { (*self.0.get()).i_uid }; + + uid.val + } + + pub fn gid(&self) -> u32 { + let gid = unsafe { (*self.0.get()).i_gid }; + + gid.val + } + + pub fn mode(&self) -> u16 { + unsafe { (*self.0.get()).i_mode } + } + pub fn truncate_inode_pages_final(&self) { // SAFETY: type semantics guarentee that Inode is instatiated let data = unsafe { ptr::addr_of_mut!((*self.0.get()).i_data) }; diff --git a/rust/kernel/sb.rs b/rust/kernel/sb.rs index 6e775e42816cb8..22baba29747c70 100644 --- a/rust/kernel/sb.rs +++ b/rust/kernel/sb.rs @@ -4,7 +4,6 @@ use core::{ ptr::{self, NonNull}, }; -use crate::page::{BorrowedPage, Page}; use crate::prelude::*; use crate::types::{ARef, ForeignOwnable}; use crate::{block, inode}; @@ -14,6 +13,10 @@ use crate::{ inode::{INodeState, Ino}, types::Opaque, }; +use crate::{ + error::from_result, + page::{BorrowedPage, Page}, +}; use crate::{ error::{code::*, from_err_ptr, Result}, inode::INode, @@ -34,6 +37,10 @@ pub trait Operations { fn evict_inode(_inode: &INode) -> Result { Err(ENOTSUPP) } + + fn write_inode(_inode: &INode) -> Result { + Err(ENOTSUPP) + } } /// Indicates that a superblock in this typestate has data initialized. @@ -261,7 +268,11 @@ impl Ops { destroy_inode: Some(INode::::destroy_inode_callback), free_inode: None, dirty_inode: None, - write_inode: None, + write_inode: if T::HAS_WRITE_INODE { + Some(Self::write_inode_callback) + } else { + None + }, drop_inode: None, evict_inode: if T::HAS_EVICT_INODE { Some(Self::evict_inode_callback) @@ -299,6 +310,21 @@ impl Ops { T::evict_inode(inode); // TODO: Should this return something? } + + unsafe extern "C" fn write_inode_callback( + inode_ptr: *mut bindings::inode, + _wbc: *mut bindings::writeback_control, + ) -> i32 { + // TODO: add support for wbc + from_result(|| { + // SAFETY: The C API guarantees that `inode_ptr` is a valid inode. + let inode = unsafe { INode::from_raw(inode_ptr) }; + + let write = T::write_inode(inode)?; + + Ok(i32::try_from(write)?) + }) + } } Self { inner: &Table::::TABLE, From 482c78bcd44ac000ddf9ac113992c20a45caa75a Mon Sep 17 00:00:00 2001 From: lsig Date: Mon, 8 Dec 2025 20:44:27 -0500 Subject: [PATCH 092/131] [ezfs/VFS] sync_fs write sb to disk --- fs/rustezfs/ezfs.rs | 20 +++++++++++++++++++- fs/rustezfs/sb.rs | 40 +++++++++++++++++++++++++++++++++++++++- rust/kernel/sb.rs | 25 ++++++++++++++++++++++++- 3 files changed, 82 insertions(+), 3 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 05f3f4bbc824a0..3b3c49072759d8 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -23,7 +23,7 @@ use kernel::sb::{New, SuperBlock, Type as SuperType}; use kernel::task::{Kgid, Kuid}; use kernel::time::hrtimer::HrTimerExpires; use kernel::time::{Instant, Monotonic, NSEC_PER_SEC, UNIX_EPOCH}; -use kernel::transmute::FromBytes; +use kernel::transmute::{AsBytes, FromBytes}; use kernel::types::{ARef, Lockable, Locked}; use kernel::{address_space, iomap}; use kernel::{c_str, fs, str::CStr}; @@ -545,6 +545,7 @@ impl kernel::sb::Operations for RustEzFs { } fn write_inode(inode: &INode) -> Result { + pr_info!("write inode called\n"); let h = inode.super_block().data(); let ino = inode.ino(); let disk_inode = EzfsInode::from_vfs_inode(inode)?; @@ -563,6 +564,23 @@ impl kernel::sb::Operations for RustEzFs { Ok(0) } + + fn sync_fs(sb: &SuperBlock) -> Result { + let ezfs_sb = sb.data(); + let disk_sb = ezfs_sb.to_disk(); + + let offset = (EZFS_SUPERBLOCK_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE) as u64; + let folio: ARef>> = + ezfs_sb.mapper.read_mapping_folio(offset.try_into()?)?; + + let folio_start = 0; + let locked_folio = folio.lock(); + let mut guard = locked_folio.map(folio_start)?; + + guard[..size_of::()].copy_from_slice(disk_sb.as_bytes()); + + Ok(0) + } } impl iomap::Operations for RustEzFs { diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index c824d9d9602289..04591541d502c3 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -10,7 +10,7 @@ use kernel::sync::{ lock::{mutex::MutexBackend, Guard}, Mutex, }; -use kernel::transmute::FromBytes; +use kernel::transmute::{AsBytes, FromBytes}; use kernel::{block, inode}; #[repr(C)] @@ -30,6 +30,28 @@ pub(crate) struct EzfsSuperblockDisk { _padding: [u8; EZFS_BLOCK_SIZE - size_of::()], } +impl Default for EzfsSuperblockDiskRaw { + fn default() -> Self { + Self { + version: 0, + magic: 0, + disk_blocks: 0, + free_inodes: [0; (EZFS_MAX_INODES / 32) + 1], + free_data_blocks: [0; (EZFS_MAX_DATA_BLKS / 32) + 1], + zero_data_blocks: [0; (EZFS_MAX_DATA_BLKS / 32) + 1], + } + } +} + +impl Default for EzfsSuperblockDisk { + fn default() -> Self { + Self { + data: EzfsSuperblockDiskRaw::default(), + _padding: [0; EZFS_BLOCK_SIZE - size_of::()], + } + } +} + impl EzfsSuperblockDisk { pub(crate) fn magic(&self) -> u64 { self.data.magic @@ -39,6 +61,7 @@ impl EzfsSuperblockDisk { // SAFETY: EzfsSuperblockDisk contains only primitive integer types (u32, u64, u8) // which accept any bit pattern. The struct is #[repr(C)] for consistent layout. unsafe impl FromBytes for EzfsSuperblockDisk {} +unsafe impl AsBytes for EzfsSuperblockDisk {} #[repr(transparent)] pub(crate) struct Bitmap { @@ -123,4 +146,19 @@ impl EzfsSuperblock { pub(crate) fn magic(&self) -> u64 { self.magic } + + pub(crate) fn to_disk(&self) -> EzfsSuperblockDisk { + let mut disk_sb = EzfsSuperblockDisk::default(); + + disk_sb.data.version = self.version; + disk_sb.data.magic = self.magic; + disk_sb.data.disk_blocks = self.disk_blocks; + + let sb_data = self.data.lock(); + disk_sb.data.free_inodes = *sb_data.free_inodes; + disk_sb.data.free_data_blocks = *sb_data.free_data_blocks; + disk_sb.data.zero_data_blocks = *sb_data.zero_data_blocks; + + disk_sb + } } diff --git a/rust/kernel/sb.rs b/rust/kernel/sb.rs index 22baba29747c70..5faedb94964422 100644 --- a/rust/kernel/sb.rs +++ b/rust/kernel/sb.rs @@ -41,6 +41,10 @@ pub trait Operations { fn write_inode(_inode: &INode) -> Result { Err(ENOTSUPP) } + + fn sync_fs(_sb: &SuperBlock) -> Result { + Err(ENOTSUPP) + } } /// Indicates that a superblock in this typestate has data initialized. @@ -280,7 +284,11 @@ impl Ops { None }, put_super: None, - sync_fs: None, + sync_fs: if T::HAS_SYNC_FS { + Some(Self::sync_fs_callback) + } else { + None + }, freeze_super: None, freeze_fs: None, thaw_super: None, @@ -325,6 +333,21 @@ impl Ops { Ok(i32::try_from(write)?) }) } + + unsafe extern "C" fn sync_fs_callback( + sb_ptr: *mut bindings::super_block, + _wait: i32, + ) -> i32 { + // TODO: add support for wait + from_result(|| { + // SAFETY: The C API guarantees that `sb_ptr` is a valid inode. + let sb = unsafe { SuperBlock::from_raw(sb_ptr) }; + + let sync_fs = T::sync_fs(sb)?; + + Ok(i32::try_from(sync_fs)?) + }) + } } Self { inner: &Table::::TABLE, From 0a0dae282e963ffdd60b65ed044ec9176c121b07 Mon Sep 17 00:00:00 2001 From: lsig Date: Mon, 8 Dec 2025 22:11:56 -0500 Subject: [PATCH 093/131] [ezfs] write sb and inode to disk --- fs/rustezfs/ezfs.rs | 39 ++++++++++++++++++++++++-------------- fs/rustezfs/inode.rs | 45 ++++++++++++++++++++++---------------------- 2 files changed, 48 insertions(+), 36 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 3b3c49072759d8..e16fd346abe847 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -9,7 +9,7 @@ mod inode; mod sb; use crate::dir::{DirEntryStore, EzfsDirEntry}; use crate::inode::{EzfsInode, InodeStore}; -use crate::sb::{EzfsSuperblock, EzfsSuperblockDisk}; +use crate::sb::{Bitmap, EzfsSuperblock, EzfsSuperblockDisk}; use defs::*; use kernel::bindings; use kernel::dentry; @@ -69,7 +69,10 @@ impl RustEzFs { { // Check if inode is allocated let sb_data = ezfs_sb.data.lock(); - if !sb_data.free_inodes.is_set(ino.try_into()?) { + if !sb_data + .free_inodes + .is_set((ino - EZFS_ROOT_INODE_NUMBER).try_into()?) + { return Err(ENOENT); } } @@ -160,7 +163,9 @@ impl RustEzFs { .set_ino(ino); let now = Instant::::now().as_nanos() / NSEC_PER_SEC; - let mut ezfs_inode = EzfsInode::default() + let mut ezfs_inode = EzfsInode::default(); + + ezfs_inode .set_mode(mode.try_into()?) .set_uid(Kuid::from_raw(uid).into_uid_in_init_ns()) .set_gid(Kgid::from_raw(gid).into_gid_in_init_ns()) @@ -185,6 +190,14 @@ impl RustEzFs { ready_inode.mark_dirty(); + // TODO: Should this be here or in the end of create? + let ezfs_sb = sb.data(); + let mut sb_data = ezfs_sb.data.lock(); + + sb_data + .free_inodes + .set_bit((ino - EZFS_ROOT_INODE_NUMBER) as u64); + Ok(ready_inode) } @@ -301,12 +314,11 @@ impl kernel::inode::Operations for RustEzFs { ) -> Result { pr_info!("Calling create from rustezfs\n"); - let new_inode = Self::new_inode(parent, mode.into())?; - - // TODO: Write Inode to memory + let mut new_inode = Self::new_inode(parent, mode.into())?; + let ino = new_inode.ino(); let sb = parent.super_block(); - let h = sb.data(); + let ezfs_sb = sb.data(); let ezfs_dir_inode = parent.data(); @@ -318,7 +330,7 @@ impl kernel::inode::Operations for RustEzFs { let new_filename = dentry.name(); let folio: ARef>> = - h.mapper.read_mapping_folio(offset.try_into()?)?; + ezfs_sb.mapper.read_mapping_folio(offset.try_into()?)?; let folio_start = 0; let locked_folio = folio.lock(); @@ -336,8 +348,8 @@ impl kernel::inode::Operations for RustEzFs { .set_active() .set_filename(new_filename)?; - new_inode.instantiate_dentry(&dentry); parent.mark_dirty(); + new_inode.instantiate_dentry(&dentry); Ok(0) } @@ -534,9 +546,6 @@ impl kernel::sb::Operations for RustEzFs { sb_data.free_inodes.clear_bit(ino); } - // TODO: remove inode from disk - // TODO: Mark sb and inode store dirty - // TODO: Make clear consume inode inode.truncate_inode_pages_final(); inode.clear(); @@ -566,8 +575,8 @@ impl kernel::sb::Operations for RustEzFs { } fn sync_fs(sb: &SuperBlock) -> Result { + pr_info!("sync_fs called\n"); let ezfs_sb = sb.data(); - let disk_sb = ezfs_sb.to_disk(); let offset = (EZFS_SUPERBLOCK_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE) as u64; let folio: ARef>> = @@ -577,6 +586,7 @@ impl kernel::sb::Operations for RustEzFs { let locked_folio = folio.lock(); let mut guard = locked_folio.map(folio_start)?; + let disk_sb = ezfs_sb.to_disk(); guard[..size_of::()].copy_from_slice(disk_sb.as_bytes()); Ok(0) @@ -765,7 +775,8 @@ impl iomap::Operations for RustEzFs { // SAFETY: We've acquired the super block lock unsafe { inode.set_blocks(new_blocks * 8) }; - let ezfs_inode = unsafe { inode.data_mut() }; + + let mut ezfs_inode = unsafe { inode.data_mut() }; ezfs_inode.set_nblocks(new_blocks); diff --git a/fs/rustezfs/inode.rs b/fs/rustezfs/inode.rs index 9456802f99b0f7..ab4d771ae8536a 100644 --- a/fs/rustezfs/inode.rs +++ b/fs/rustezfs/inode.rs @@ -23,22 +23,23 @@ pub(crate) struct EzfsInode { impl EzfsInode { pub(crate) fn from_vfs_inode(vfs_inode: &INode) -> Result { - let mut disk_inode = EzfsInode::default(); - let mtime_sec = vfs_inode.mtime()?.tv_sec(); let ctime_sec = vfs_inode.ctime()?.tv_sec(); let atime_sec = vfs_inode.atime()?.tv_sec(); - disk_inode.set_file_size(vfs_inode.size().try_into()?); - disk_inode.set_nblocks(vfs_inode.blocks() / 8); - disk_inode.set_mode(vfs_inode.mode() as u32); - disk_inode.set_uid(vfs_inode.uid()); - disk_inode.set_gid(vfs_inode.gid()); - disk_inode.set_nlink(vfs_inode.nlink()); - disk_inode.set_atime(atime_sec); - disk_inode.set_ctime(ctime_sec); - disk_inode.set_mtime(mtime_sec); - disk_inode.set_data_block_num(vfs_inode.data().data_blk_num()); + let mut disk_inode = EzfsInode::default(); + + disk_inode + .set_file_size(vfs_inode.size().try_into()?) + .set_nblocks(vfs_inode.blocks() / 8) + .set_mode(vfs_inode.mode().into()) + .set_uid(vfs_inode.uid()) + .set_gid(vfs_inode.gid()) + .set_nlink(vfs_inode.nlink()) + .set_atime(atime_sec) + .set_ctime(ctime_sec) + .set_mtime(mtime_sec) + .set_data_block_num(vfs_inode.data().data_blk_num()); Ok(disk_inode) } @@ -83,61 +84,61 @@ impl EzfsInode { self.nblocks } - pub(crate) fn set_mode(mut self, mode: u32) -> Self { + pub(crate) fn set_mode(&mut self, mode: u32) -> &mut Self { self.mode = mode; self } - pub(crate) fn set_uid(mut self, uid: u32) -> Self { + pub(crate) fn set_uid(&mut self, uid: u32) -> &mut Self { self.uid = uid; self } - pub(crate) fn set_gid(mut self, gid: u32) -> Self { + pub(crate) fn set_gid(&mut self, gid: u32) -> &mut Self { self.gid = gid; self } - pub(crate) fn set_atime(mut self, tv_sec: i64) -> Self { + pub(crate) fn set_atime(&mut self, tv_sec: i64) -> &mut Self { self.i_atime = tv_sec; self } - pub(crate) fn set_mtime(mut self, tv_sec: i64) -> Self { + pub(crate) fn set_mtime(&mut self, tv_sec: i64) -> &mut Self { self.i_mtime = tv_sec; self } - pub(crate) fn set_ctime(mut self, tv_sec: i64) -> Self { + pub(crate) fn set_ctime(&mut self, tv_sec: i64) -> &mut Self { self.i_ctime = tv_sec; self } - pub(crate) fn set_nlink(mut self, nlink: u32) -> Self { + pub(crate) fn set_nlink(&mut self, nlink: u32) -> &mut Self { self.nlink = nlink; self } - pub(crate) fn set_data_block_num(mut self, data_block_num: u64) -> Self { + pub(crate) fn set_data_block_num(&mut self, data_block_num: u64) -> &mut Self { self.data_blk_num = data_block_num; self } - pub(crate) fn set_file_size(mut self, file_size: u64) -> Self { + pub(crate) fn set_file_size(&mut self, file_size: u64) -> &mut Self { self.file_size = file_size; self } - pub(crate) fn set_nblocks(mut self, nblocks: u64) -> Self { + pub(crate) fn set_nblocks(&mut self, nblocks: u64) -> &mut Self { self.nblocks = nblocks; self From 50d53c689b3f377fa099c429161c6e3964593a6c Mon Sep 17 00:00:00 2001 From: lsig Date: Mon, 8 Dec 2025 22:15:58 -0500 Subject: [PATCH 094/131] [chore] remove unnecessary import --- fs/rustezfs/ezfs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index e16fd346abe847..f46cd13a51111b 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -9,7 +9,7 @@ mod inode; mod sb; use crate::dir::{DirEntryStore, EzfsDirEntry}; use crate::inode::{EzfsInode, InodeStore}; -use crate::sb::{Bitmap, EzfsSuperblock, EzfsSuperblockDisk}; +use crate::sb::{EzfsSuperblock, EzfsSuperblockDisk}; use defs::*; use kernel::bindings; use kernel::dentry; From 46b22be5e24a78805ebf40058f31f3196eaaa8b7 Mon Sep 17 00:00:00 2001 From: lsig Date: Mon, 8 Dec 2025 22:27:54 -0500 Subject: [PATCH 095/131] [ezfs] fix off by one error --- fs/rustezfs/ezfs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index f46cd13a51111b..36b68274d55423 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -543,7 +543,7 @@ impl kernel::sb::Operations for RustEzFs { .clear_bit(data_blk - EZFS_ROOT_DATABLOCK_NUMBER as u64); } - sb_data.free_inodes.clear_bit(ino); + sb_data.free_inodes.clear_bit(ino - EZFS_ROOT_INODE_NUMBER); } // TODO: Make clear consume inode From 1bf30941811ca6149c2db7068a5301acefc0cf81 Mon Sep 17 00:00:00 2001 From: lsig Date: Mon, 8 Dec 2025 22:50:44 -0500 Subject: [PATCH 096/131] [ezfs] fix off by one (bruh) --- fs/rustezfs/ezfs.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 36b68274d55423..82e5034863e1ad 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -526,7 +526,7 @@ impl kernel::sb::Operations for RustEzFs { fn evict_inode(inode: &INode) -> Result { if (inode.nlink() == 0) { let sb = inode.super_block().data(); - let ino: u64 = inode.ino().try_into()?; + let ino = inode.ino(); let ezfs_inode = inode.data(); let start = ezfs_inode.data_blk_num(); @@ -543,7 +543,9 @@ impl kernel::sb::Operations for RustEzFs { .clear_bit(data_blk - EZFS_ROOT_DATABLOCK_NUMBER as u64); } - sb_data.free_inodes.clear_bit(ino - EZFS_ROOT_INODE_NUMBER); + sb_data + .free_inodes + .clear_bit((ino - EZFS_ROOT_INODE_NUMBER) as u64); } // TODO: Make clear consume inode From b8209cc77cf4c1314b3548e71239c8112a75b2e1 Mon Sep 17 00:00:00 2001 From: lsig Date: Mon, 8 Dec 2025 22:51:05 -0500 Subject: [PATCH 097/131] [ezfs] rename variable --- fs/rustezfs/ezfs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 82e5034863e1ad..d59ba4158b629b 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -557,13 +557,13 @@ impl kernel::sb::Operations for RustEzFs { fn write_inode(inode: &INode) -> Result { pr_info!("write inode called\n"); - let h = inode.super_block().data(); + let ezfs_sb = inode.super_block().data(); let ino = inode.ino(); let disk_inode = EzfsInode::from_vfs_inode(inode)?; let offset = (EZFS_INODE_STORE_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE) as u64; let folio: ARef>> = - h.mapper.read_mapping_folio(offset.try_into()?)?; + ezfs_sb.mapper.read_mapping_folio(offset.try_into()?)?; let folio_start = 0; let locked_folio = folio.lock(); From c0ddf0863e2134a715a4afbf390e2b630046ee73 Mon Sep 17 00:00:00 2001 From: lsig Date: Tue, 9 Dec 2025 16:28:57 -0500 Subject: [PATCH 098/131] [ezfs] fix compiler warnings --- fs/rustezfs/dir.rs | 2 -- fs/rustezfs/ezfs.rs | 50 ++++++++++++++++++++++----------------------- fs/rustezfs/sb.rs | 13 ++---------- 3 files changed, 26 insertions(+), 39 deletions(-) diff --git a/fs/rustezfs/dir.rs b/fs/rustezfs/dir.rs index 21025ab90cdb86..6f956f87752e38 100644 --- a/fs/rustezfs/dir.rs +++ b/fs/rustezfs/dir.rs @@ -56,8 +56,6 @@ impl EzfsDirEntry { } pub(crate) fn zero(&mut self) -> &mut Self { - let len = self.filename.len(); - self.inode_no = 0; self.active = 0; self.filename.fill(0); diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index d59ba4158b629b..ccbc1343e3c4be 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 //! Easy filesystem written in Rust -#![allow(unused)] mod defs; mod dir; @@ -13,25 +12,24 @@ use crate::sb::{EzfsSuperblock, EzfsSuperblockDisk}; use defs::*; use kernel::bindings; use kernel::dentry; -use kernel::folio::{Folio, PageCache}; +use kernel::folio::Folio; use kernel::fs::Kiocb; use kernel::fs::{file, File, FileSystem, Offset, Registration}; use kernel::inode::{INode, INodeState, Mapper, Params, Type}; -use kernel::iov::{IovIterDest, IovIterSource}; +use kernel::iomap; +use kernel::iov::IovIterSource; use kernel::prelude::*; use kernel::sb::{New, SuperBlock, Type as SuperType}; use kernel::task::{Kgid, Kuid}; use kernel::time::hrtimer::HrTimerExpires; -use kernel::time::{Instant, Monotonic, NSEC_PER_SEC, UNIX_EPOCH}; +use kernel::time::{Instant, Monotonic, NSEC_PER_SEC}; use kernel::transmute::{AsBytes, FromBytes}; use kernel::types::{ARef, Lockable, Locked}; -use kernel::{address_space, iomap}; use kernel::{c_str, fs, str::CStr}; -use core::marker::{PhantomData, Send, Sync}; +use core::marker::PhantomData; use core::mem::size_of; -use core::ptr; -use pin_init::{pin_data, PinInit, PinnedDrop}; +use pin_init::{pin_data, PinInit}; struct RustEzFs; @@ -225,7 +223,7 @@ impl RustEzFs { let ezfs_dir_inode = parent.data(); let name = dentry.name(); - if name.len() > EZFS_FILENAME_BUF_SIZE { + if name.len() > EZFS_FILENAME_LENGTH { return Err(ENAMETOOLONG); } let offset = ezfs_dir_inode @@ -314,8 +312,8 @@ impl kernel::inode::Operations for RustEzFs { ) -> Result { pr_info!("Calling create from rustezfs\n"); - let mut new_inode = Self::new_inode(parent, mode.into())?; - let ino = new_inode.ino(); + let new_inode = Self::new_inode(parent, mode.into())?; + let ino: u64 = new_inode.ino().try_into()?; let sb = parent.super_block(); let ezfs_sb = sb.data(); @@ -335,7 +333,7 @@ impl kernel::inode::Operations for RustEzFs { let folio_start = 0; let locked_folio = folio.lock(); let mut guard = locked_folio.map(folio_start)?; - let mut dir_entries = + let dir_entries = DirEntryStore::from_bytes_mut(&mut guard[..size_of::()]).ok_or(EIO)?; let dir_entry = dir_entries @@ -344,7 +342,7 @@ impl kernel::inode::Operations for RustEzFs { .ok_or(ENOSPC)?; dir_entry - .set_inode_no(new_inode.ino().try_into()?) + .set_inode_no(ino) .set_active() .set_filename(new_filename)?; @@ -378,7 +376,7 @@ impl kernel::inode::Operations for RustEzFs { let folio_start = 0; let locked_folio = folio.lock(); let mut guard = locked_folio.map(folio_start)?; - let mut dir_entries = + let dir_entries = DirEntryStore::from_bytes_mut(&mut guard[..size_of::()]).ok_or(EIO)?; let dir_entry = dir_entries @@ -499,7 +497,7 @@ impl file::Operations for RustEzFs { fn write_iter( mut kiocb: Kiocb<'_, ::Data>, - mut iov: &mut IovIterSource<'_>, + iov: &mut IovIterSource<'_>, ) -> Result { pr_info!("write_iter\n"); let flags = kiocb.ki_flags(); @@ -524,7 +522,7 @@ impl kernel::sb::Operations for RustEzFs { type FileSystem = Self; fn evict_inode(inode: &INode) -> Result { - if (inode.nlink() == 0) { + if inode.nlink() == 0 { let sb = inode.super_block().data(); let ino = inode.ino(); @@ -568,7 +566,7 @@ impl kernel::sb::Operations for RustEzFs { let folio_start = 0; let locked_folio = folio.lock(); let mut guard = locked_folio.map(folio_start)?; - let mut inodes = + let inodes = InodeStore::from_bytes_mut(&mut guard[..size_of::()]).ok_or(EIO)?; inodes[ino - EZFS_ROOT_INODE_NUMBER] = disk_inode; @@ -605,7 +603,7 @@ impl iomap::Operations for RustEzFs { length: Offset, flags: u32, map: &mut iomap::Map<'a>, - srcmap: Option<&mut iomap::Map<'a>>, + _srcmap: Option<&mut iomap::Map<'a>>, ) -> Result { pr_info!("iomap_begin()\n"); @@ -635,7 +633,7 @@ impl iomap::Operations for RustEzFs { .set_length(length as u64); // We're reading - if (flags & iomap::flags::WRITE == 0) { + if flags & iomap::flags::WRITE == 0 { // Invalid read, block does not belong to inode if ez_blk_num == 0 || start_block >= ez_blk_count { map.set_type(iomap::Type::Hole) @@ -721,19 +719,19 @@ impl iomap::Operations for RustEzFs { curr_block += 1; } - if (seen_free < blocks_needed) { + if seen_free < blocks_needed { return Err(ENOSPC); } // Move all blocks within the file to new region let new_block_start = curr_block - blocks_needed; - if (ez_blk_num != 0) { + if ez_blk_num != 0 { for j in 0..ez_blk_count { let old = ez_blk_sidx + j; let new = new_block_start + j; - Self::move_block(old, new, sb); + Self::move_block(old, new, sb)?; sb_data.free_data_blocks.clear_bit(old); sb_data.free_data_blocks.set_bit(new); @@ -742,7 +740,7 @@ impl iomap::Operations for RustEzFs { // SAFETY: we've acquired the super block lock and can therefore // modify the ezfs inode - let mut ezfs_inode = unsafe { inode.data_mut() }; + let ezfs_inode = unsafe { inode.data_mut() }; ezfs_inode .set_data_block_num(new_block_start + (EZFS_ROOT_DATABLOCK_NUMBER as u64)); phys = ezfs_inode.data_blk_num() + start_block; @@ -764,11 +762,11 @@ impl iomap::Operations for RustEzFs { _flags: u32, _map: &iomap::Map<'a>, ) -> Result { - if (written > 0) { + if written > 0 { pr_info!("iomap_end()\n"); let new_blocks = ((inode.size() + (EZFS_BLOCK_SIZE as i64) - 1) / EZFS_BLOCK_SIZE as i64) as u64; - let sb = inode.super_block(); + // let sb = inode.super_block(); // TODO: do we need inode lock? and should we store inode store in sb? // iomap locking docks (see locking hierarcy): https://docs.kernel.org/6.16/_sources/filesystems/iomap/design.rst.txt // let ezfs_sb = sb.data(); @@ -778,7 +776,7 @@ impl iomap::Operations for RustEzFs { // SAFETY: We've acquired the super block lock unsafe { inode.set_blocks(new_blocks * 8) }; - let mut ezfs_inode = unsafe { inode.data_mut() }; + let ezfs_inode = unsafe { inode.data_mut() }; ezfs_inode.set_nblocks(new_blocks); diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index 04591541d502c3..367b861bfc174a 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -1,17 +1,12 @@ use crate::defs::{EZFS_BLOCK_SIZE, EZFS_MAX_DATA_BLKS, EZFS_MAX_INODES}; -use crate::inode::InodeStore; use crate::RustEzFs; use core::mem::size_of; use core::ops::{Deref, DerefMut}; -use kernel::fs::FileSystem; +use kernel::inode; use kernel::new_mutex; use kernel::prelude::*; -use kernel::sync::{ - lock::{mutex::MutexBackend, Guard}, - Mutex, -}; +use kernel::sync::Mutex; use kernel::transmute::{AsBytes, FromBytes}; -use kernel::{block, inode}; #[repr(C)] pub(crate) struct EzfsSuperblockDiskRaw { @@ -143,10 +138,6 @@ impl EzfsSuperblock { }) } - pub(crate) fn magic(&self) -> u64 { - self.magic - } - pub(crate) fn to_disk(&self) -> EzfsSuperblockDisk { let mut disk_sb = EzfsSuperblockDisk::default(); From 35f10c66a864b1dc3b5a2d896cf85e1eb58e96d9 Mon Sep 17 00:00:00 2001 From: lsig Date: Tue, 9 Dec 2025 16:57:51 -0500 Subject: [PATCH 099/131] [ezfs] fix clippy concrete warnings --- fs/rustezfs/ezfs.rs | 34 ++++++++++++++++------------------ fs/rustezfs/sb.rs | 4 ++-- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index ccbc1343e3c4be..a9cd0856fa9681 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -119,7 +119,7 @@ impl RustEzFs { for (word_idx, &word) in sb_data.free_inodes.iter().enumerate() { if word != !0u32 { let bit_idx: u32 = (!word).trailing_zeros(); - let inode_num: usize = (word_idx as usize * 32) + bit_idx as usize; + let inode_num: usize = (word_idx * 32) + bit_idx as usize; if inode_num < EZFS_MAX_INODES { sb_data.free_inodes[word_idx] |= 1 << bit_idx; @@ -164,7 +164,7 @@ impl RustEzFs { let mut ezfs_inode = EzfsInode::default(); ezfs_inode - .set_mode(mode.try_into()?) + .set_mode(mode) .set_uid(Kuid::from_raw(uid).into_uid_in_init_ns()) .set_gid(Kgid::from_raw(gid).into_gid_in_init_ns()) .set_nlink(1) @@ -430,10 +430,8 @@ impl file::Operations for RustEzFs { // pr_info!("read_dir()\n"); let pos: usize = emitter.pos().try_into().map_err(|_| ENOENT)?; - if pos < 2 { - if !emitter.emit_dots(file) { - return Ok(()); - } + if pos < 2 && !emitter.emit_dots(file) { + return Ok(()); } let sb = inode.super_block(); @@ -660,18 +658,18 @@ impl iomap::Operations for RustEzFs { } enum WriteCase { - NEW, // Write to an empty file without any allocated blocks - WITHIN, // File can fit written contents within allocated, unused block - EXTEND, // File has adjacent, free block to extend to - MOVE, // File has no adjacent, free block and must be moved + New, // Write to an empty file without any allocated blocks + Within, // File can fit written contents within allocated, unused block + Extend, // File has adjacent, free block to extend to + Move, // File has no adjacent, free block and must be moved } let ez_blk_sidx = ez_blk_num.saturating_sub(EZFS_ROOT_DATABLOCK_NUMBER as u64); let case_type = if ez_blk_num == 0 { - WriteCase::NEW + WriteCase::New } else if blocks_to_add == 0 { - WriteCase::WITHIN + WriteCase::Within } else { let start = ez_blk_sidx + ez_blk_count; let end = ez_blk_sidx + blocks_needed; @@ -683,19 +681,19 @@ impl iomap::Operations for RustEzFs { // pr_info!("start={start} - end={end}\n"); if (start..end).any(|bit| sb_data.free_data_blocks.is_set(bit)) { - WriteCase::MOVE + WriteCase::Move } else { - WriteCase::EXTEND + WriteCase::Extend } }; match case_type { - WriteCase::NEW => { + WriteCase::New => { pr_info!("adding to an empty file\n"); return Err(EIO); } - WriteCase::WITHIN => {} - WriteCase::EXTEND => { + WriteCase::Within => {} + WriteCase::Extend => { for i in ez_blk_count..blocks_needed { let bit = ez_blk_sidx + i; sb_data.free_data_blocks.set_bit(bit); @@ -703,7 +701,7 @@ impl iomap::Operations for RustEzFs { map.set_flags(iomap::map_flags::NEW); } - WriteCase::MOVE => { + WriteCase::Move => { // Let's try to find a region of sequential free blocks // of size `blocks_needed` to move our file to let mut curr_block = 0; diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index 367b861bfc174a..faaaba66f24c56 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -72,14 +72,14 @@ impl Bitmap { } #[inline] - pub(crate) fn set_bit(&mut self, block_num: u64) -> () { + pub(crate) fn set_bit(&mut self, block_num: u64) { let idx: usize = (block_num / 32) as usize; let mask = 1 << (block_num % 32); self.inner[idx] |= mask } #[inline] - pub(crate) fn clear_bit(&mut self, block_num: u64) -> () { + pub(crate) fn clear_bit(&mut self, block_num: u64) { let idx: usize = (block_num / 32) as usize; let mask = 1 << (block_num % 32); self.inner[idx] &= !mask From 3dd33aa862d4f0201e0f48a447d66359161bf02e Mon Sep 17 00:00:00 2001 From: lsig Date: Tue, 9 Dec 2025 20:34:05 -0500 Subject: [PATCH 100/131] [ezfs] fix read_iter --- fs/rustezfs/ezfs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index a9cd0856fa9681..17dd887a50d4b5 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -472,8 +472,8 @@ impl file::Operations for RustEzFs { let active_entries = dir_entries .iter() - .skip(index) - .filter(|&entry| entry.is_active()); + .filter(|&entry| entry.is_active()) + .skip(index); for entry in active_entries { let ino: usize = entry.inode_no().try_into()?; From 0835ed342072e71c3152047d465654056503160b Mon Sep 17 00:00:00 2001 From: lsig Date: Tue, 9 Dec 2025 22:02:47 -0500 Subject: [PATCH 101/131] [ezfs/VFS] mkdir checkpoint --- fs/rustezfs/ezfs.rs | 136 +++++++++++++++++++++++++++++++------------ fs/rustezfs/sb.rs | 4 ++ rust/kernel/inode.rs | 38 +++++++++++- 3 files changed, 140 insertions(+), 38 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 17dd887a50d4b5..aa2c16b69849af 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -131,12 +131,43 @@ impl RustEzFs { Err(ENOSPC) } + fn allocate_data_block(sb: &SuperBlock) -> Result { + let ezfs_sb = sb.data(); + + let data_block_num = { + let mut sb_data = ezfs_sb.data.lock(); + let max_blocks = Self::get_max_blocks(ezfs_sb); + let data_block_num = (0..max_blocks) + .find(|&x| !sb_data.free_data_blocks.is_set(x)) + .ok_or(ENOSPC)?; + + sb_data.free_data_blocks.set_bit(data_block_num); + + data_block_num + }; + + let offset = data_block_num + .checked_mul(EZFS_BLOCK_SIZE as u64) + .ok_or(EIO)?; + + let folio: ARef>> = + ezfs_sb.mapper.read_mapping_folio(offset.try_into()?)?; + + let folio_start = 0; + let locked_folio = folio.lock(); + let mut guard = locked_folio.map(folio_start)?; + guard.fill(0); + + Ok(data_block_num + EZFS_ROOT_DATABLOCK_NUMBER as u64) + } + fn new_inode( dir: &Locked<&INode, kernel::inode::ReadSem>, mode: u32, ) -> Result> { let sb = dir.super_block(); let mut new_inode = sb.new_inode()?; + let mut ezfs_inode = EzfsInode::default(); let ino = Self::allocate_inode(sb)?; pr_info!("Allocating new inode: {:?}\n", ino); @@ -144,10 +175,20 @@ impl RustEzFs { let typ = match mode & fs::mode::S_IFMT { fs::mode::S_IFREG => { new_inode.set_fops(Self::FILE_FOPS); + ezfs_inode.set_nlink(1); + Type::Reg } fs::mode::S_IFDIR => { new_inode.set_fops(Self::DIR_FOPS); + + let data_block_num = Self::allocate_data_block(sb)?; + ezfs_inode + .set_nlink(2) + .set_file_size(EZFS_BLOCK_SIZE as u64) + .set_nblocks(8) + .set_data_block_num(data_block_num); + Type::Dir } _ => return Err(ENOENT), @@ -161,13 +202,11 @@ impl RustEzFs { .set_ino(ino); let now = Instant::::now().as_nanos() / NSEC_PER_SEC; - let mut ezfs_inode = EzfsInode::default(); ezfs_inode .set_mode(mode) .set_uid(Kuid::from_raw(uid).into_uid_in_init_ns()) .set_gid(Kgid::from_raw(gid).into_gid_in_init_ns()) - .set_nlink(1) .set_atime(now) .set_mtime(now) .set_ctime(now); @@ -242,6 +281,53 @@ impl RustEzFs { Ok(dir_entry) } + + fn create_helper( + parent: &Locked<&INode, kernel::inode::ReadSem>, + dentry: dentry::Unhashed<'_, Self>, + mode: u16, + ) -> Result { + pr_info!("Calling create from rustezfs\n"); + + let new_inode = Self::new_inode(parent, mode.into())?; + let ino: u64 = new_inode.ino().try_into()?; + + let sb = parent.super_block(); + let ezfs_sb = sb.data(); + + let ezfs_dir_inode = parent.data(); + + let offset = ezfs_dir_inode + .data_blk_num() + .checked_mul(EZFS_BLOCK_SIZE as u64) + .ok_or(EIO)?; + + let new_filename = dentry.name(); + + let folio: ARef>> = + ezfs_sb.mapper.read_mapping_folio(offset.try_into()?)?; + + let folio_start = 0; + let locked_folio = folio.lock(); + let mut guard = locked_folio.map(folio_start)?; + let dir_entries = + DirEntryStore::from_bytes_mut(&mut guard[..size_of::()]).ok_or(EIO)?; + + let dir_entry = dir_entries + .iter_mut() + .find(|x| !x.is_active()) + .ok_or(ENOSPC)?; + + dir_entry + .set_inode_no(ino) + .set_active() + .set_filename(new_filename)?; + + parent.mark_dirty(); + new_inode.instantiate_dentry(&dentry); + + Ok(0) + } } impl FileSystem for RustEzFs { @@ -312,44 +398,20 @@ impl kernel::inode::Operations for RustEzFs { ) -> Result { pr_info!("Calling create from rustezfs\n"); - let new_inode = Self::new_inode(parent, mode.into())?; - let ino: u64 = new_inode.ino().try_into()?; - - let sb = parent.super_block(); - let ezfs_sb = sb.data(); - - let ezfs_dir_inode = parent.data(); - - let offset = ezfs_dir_inode - .data_blk_num() - .checked_mul(EZFS_BLOCK_SIZE as u64) - .ok_or(EIO)?; - - let new_filename = dentry.name(); - - let folio: ARef>> = - ezfs_sb.mapper.read_mapping_folio(offset.try_into()?)?; - - let folio_start = 0; - let locked_folio = folio.lock(); - let mut guard = locked_folio.map(folio_start)?; - let dir_entries = - DirEntryStore::from_bytes_mut(&mut guard[..size_of::()]).ok_or(EIO)?; - - let dir_entry = dir_entries - .iter_mut() - .find(|x| !x.is_active()) - .ok_or(ENOSPC)?; + Self::create_helper(parent, dentry, mode) + } - dir_entry - .set_inode_no(ino) - .set_active() - .set_filename(new_filename)?; + fn mkdir( + parent: &Locked<&INode, kernel::inode::ReadSem>, + dentry: dentry::Unhashed<'_, Self::FileSystem>, + mode: u16, + ) -> Result>>> { + pr_info!("Calling mkdir from rustezfs\n"); - parent.mark_dirty(); - new_inode.instantiate_dentry(&dentry); + Self::create_helper(parent, dentry, mode)?; - Ok(0) + // Since we use d_instantiate_new we don't return a dentry + Ok(None) } fn unlink( diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index faaaba66f24c56..8940eb72b25596 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -152,4 +152,8 @@ impl EzfsSuperblock { disk_sb } + + pub(crate) fn disk_blocks(&self) -> u64 { + self.disk_blocks + } } diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index 848ca8792ea33a..d8648494de99da 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -71,6 +71,14 @@ pub trait Operations { ) -> Result { Err(ENOTSUPP) } + + fn mkdir( + _parent: &Locked<&INode, ReadSem>, + _dentry: dentry::Unhashed<'_, Self::FileSystem>, + _mode: u16, + ) -> Result>>> { + Err(ENOTSUPP) + } } /// A node (inode) in the file index. @@ -888,7 +896,11 @@ impl Ops { None }, symlink: None, - mkdir: None, + mkdir: if T::HAS_MKDIR { + Some(Self::mkdir_callback) + } else { + None + }, rmdir: None, mknod: None, rename: None, @@ -975,6 +987,30 @@ impl Ops { Ok(i32::try_from(unlink)?) }) } + + unsafe extern "C" fn mkdir_callback( + _mnt_idmap_ptr: *mut bindings::mnt_idmap, + parent_ptr: *mut bindings::inode, + dentry_ptr: *mut bindings::dentry, + mode: u16, + ) -> *mut bindings::dentry { + // SAFETY: The C API guarantees that `parent_ptr` is a valid inode. + let parent = unsafe { INode::from_raw(parent_ptr) }; + + // SAFETY: The C API guarantees that `dentry_ptr` is a valid dentry. + let dentry = unsafe { DEntry::from_raw(dentry_ptr) }; + + // SAFETY: The C API guarantees that the inode's rw semaphore is locked at least in + // read mode. It does not expect callees to unlock it, so we make the locked object + // manually dropped to avoid unlocking it. + let locked = ManuallyDrop::new(unsafe { Locked::new(parent) }); + + match T::mkdir(&locked, dentry::Unhashed(dentry), mode) { + Err(e) => e.to_ptr(), + Ok(None) => ptr::null_mut(), + Ok(Some(ret)) => ManuallyDrop::new(ret).0.get(), + } + } } Self(&Table::::TABLE, PhantomData) } From 045b8b438d9ace6f68aff9bda2d85ef6a9099792 Mon Sep 17 00:00:00 2001 From: lsig Date: Tue, 9 Dec 2025 22:30:54 -0500 Subject: [PATCH 102/131] [ezfs] mkdir --- fs/rustezfs/ezfs.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index aa2c16b69849af..b10e748d79c34f 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -13,6 +13,7 @@ use defs::*; use kernel::bindings; use kernel::dentry; use kernel::folio::Folio; +use kernel::fs::mode::S_IFDIR; use kernel::fs::Kiocb; use kernel::fs::{file, File, FileSystem, Offset, Registration}; use kernel::inode::{INode, INodeState, Mapper, Params, Type}; @@ -191,6 +192,7 @@ impl RustEzFs { Type::Dir } + // FIXME: iget_failed called twice when this happens _ => return Err(ENOENT), }; @@ -287,7 +289,7 @@ impl RustEzFs { dentry: dentry::Unhashed<'_, Self>, mode: u16, ) -> Result { - pr_info!("Calling create from rustezfs\n"); + pr_info!("Calling create helper from rustezfs\n"); let new_inode = Self::new_inode(parent, mode.into())?; let ino: u64 = new_inode.ino().try_into()?; @@ -408,7 +410,7 @@ impl kernel::inode::Operations for RustEzFs { ) -> Result>>> { pr_info!("Calling mkdir from rustezfs\n"); - Self::create_helper(parent, dentry, mode)?; + Self::create_helper(parent, dentry, mode | S_IFDIR as u16)?; // Since we use d_instantiate_new we don't return a dentry Ok(None) From e364d05fc2407141f3240d3b3cfdfb80244b0958 Mon Sep 17 00:00:00 2001 From: lsig Date: Tue, 9 Dec 2025 22:37:22 -0500 Subject: [PATCH 103/131] [ezfs] remove unused function --- fs/rustezfs/sb.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index 8940eb72b25596..faaaba66f24c56 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -152,8 +152,4 @@ impl EzfsSuperblock { disk_sb } - - pub(crate) fn disk_blocks(&self) -> u64 { - self.disk_blocks - } } From f92baf8491de7881d4d4f8901f9ae8b08d629faf Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 10 Dec 2025 12:30:26 -0500 Subject: [PATCH 104/131] [ezfs/VFS] rmdir checkpoint --- fs/rustezfs/ezfs.rs | 31 +++++++++++++++++++++++++++++++ rust/kernel/error.rs | 1 + rust/kernel/inode.rs | 35 ++++++++++++++++++++++++++++++++++- 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index b10e748d79c34f..27872429676a8d 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -416,6 +416,37 @@ impl kernel::inode::Operations for RustEzFs { Ok(None) } + fn rmdir( + parent: &Locked<&INode, kernel::inode::ReadSem>, + dentry: dentry::Unhashed<'_, Self::FileSystem>, + ) -> Result { + let inode = dentry.inode(); + let ezfs_inode = inode.data(); + + let offset = ezfs_inode + .data_blk_num() + .checked_mul(EZFS_BLOCK_SIZE as u64) + .ok_or(EIO)?; + + let mapped = h.mapper.mapped_folio(offset.try_into()?)?; + let dir_entries = + DirEntryStore::from_bytes(&mapped[..size_of::()]).ok_or(EIO)?; + + for entry in dir_entries.iter() { + if entry.is_active() { + return Err(ENOTEMPTY); + } + } + + Self::unlink(parent, dentry)?; + + inode.drop_nlink(); + parent.drop_nlink(); + + inode.mark_dirty(); + parent.mark_dirty(); + } + fn unlink( parent: &Locked<&INode, kernel::inode::ReadSem>, dentry: dentry::Unhashed<'_, Self::FileSystem>, diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index ae66a481556bd9..a3633efacfa949 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -88,6 +88,7 @@ pub mod code { declare_err!(ERECALLCONFLICT, "Conflict with recalled state."); declare_err!(ENOGRACE, "NFS file lock reclaim refused."); declare_err!(ENAMETOOLONG, "File name too long"); + declare_err!(ENOTEMPTY, "Directory not empty"); } /// Generic integer kernel error. diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index d8648494de99da..d00d1e25f26025 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -79,6 +79,13 @@ pub trait Operations { ) -> Result>>> { Err(ENOTSUPP) } + + fn rmdir( + _parent: &Locked<&INode, ReadSem>, + _dentry: dentry::Unhashed<'_, Self::FileSystem>, + ) -> Result { + Err(ENOTSUPP) + } } /// A node (inode) in the file index. @@ -901,7 +908,11 @@ impl Ops { } else { None }, - rmdir: None, + rmdir: if T::HAS_RMDIR { + Some(Self::rmdir_callback) + } else { + None + }, mknod: None, rename: None, setattr: None, @@ -1011,6 +1022,28 @@ impl Ops { Ok(Some(ret)) => ManuallyDrop::new(ret).0.get(), } } + + unsafe extern "C" fn rmdir_callback( + inode_ptr: *mut bindings::inode, + dentry_ptr: *mut bindings::dentry, + ) -> i32 { + from_result(|| { + // SAFETY: The C API guarantees that `inode_ptr` is a valid inode. + let inode = unsafe { INode::from_raw(inode_ptr) }; + + // SAFETY: The C API guarantees that `dentry_ptr` is a valid inode. + let dentry = unsafe { DEntry::from_raw(dentry_ptr) }; + + // SAFETY: The C API guarantees that the inode's rw semaphore is locked at least in + // read mode. It does not expect callees to unlock it, so we make the locked object + // manually dropped to avoid unlocking it. + let locked = ManuallyDrop::new(unsafe { Locked::new(inode) }); + + let rmdir = T::rmdir(&locked, dentry::Unhashed(dentry))?; + + Ok(i32::try_from(rmdir)?) + }) + } } Self(&Table::::TABLE, PhantomData) } From 72316411d0884e95087fff78aeeab01adb37e4a5 Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 10 Dec 2025 13:07:46 -0500 Subject: [PATCH 105/131] [ezfs/VFS] rmdir --- fs/rustezfs/ezfs.rs | 17 +++++++++-------- rust/helpers/fs.c | 10 ++++++++++ rust/kernel/inode.rs | 16 ++++++++++++++++ 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 27872429676a8d..d1673ee0c9bc32 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -412,6 +412,8 @@ impl kernel::inode::Operations for RustEzFs { Self::create_helper(parent, dentry, mode | S_IFDIR as u16)?; + parent.inc_link_count(); + // Since we use d_instantiate_new we don't return a dentry Ok(None) } @@ -420,6 +422,7 @@ impl kernel::inode::Operations for RustEzFs { parent: &Locked<&INode, kernel::inode::ReadSem>, dentry: dentry::Unhashed<'_, Self::FileSystem>, ) -> Result { + let ezfs_sb = parent.super_block().data(); let inode = dentry.inode(); let ezfs_inode = inode.data(); @@ -428,7 +431,7 @@ impl kernel::inode::Operations for RustEzFs { .checked_mul(EZFS_BLOCK_SIZE as u64) .ok_or(EIO)?; - let mapped = h.mapper.mapped_folio(offset.try_into()?)?; + let mapped = ezfs_sb.mapper.mapped_folio(offset.try_into()?)?; let dir_entries = DirEntryStore::from_bytes(&mapped[..size_of::()]).ok_or(EIO)?; @@ -438,13 +441,13 @@ impl kernel::inode::Operations for RustEzFs { } } + inode.dec_link_count(); // drop link for "." + Self::unlink(parent, dentry)?; - inode.drop_nlink(); - parent.drop_nlink(); + parent.dec_link_count(); - inode.mark_dirty(); - parent.mark_dirty(); + Ok(0) } fn unlink( @@ -483,9 +486,7 @@ impl kernel::inode::Operations for RustEzFs { // TODO: change m and ctime for parent and inode - inode.drop_nlink(); - - inode.mark_dirty(); + inode.dec_link_count(); parent.mark_dirty(); Ok(0) diff --git a/rust/helpers/fs.c b/rust/helpers/fs.c index b58447c7fdd98b..5bb264d2c15f0b 100644 --- a/rust/helpers/fs.c +++ b/rust/helpers/fs.c @@ -46,3 +46,13 @@ void rust_helper_mark_inode_dirty(struct inode *inode) { mark_inode_dirty(inode); } + +void rust_helper_inode_inc_link_count(struct inode *inode) +{ + inode_inc_link_count(inode); +} + +void rust_helper_inode_dec_link_count(struct inode *inode) +{ + inode_dec_link_count(inode); +} diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index d00d1e25f26025..4fee1b64f19fbb 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -246,6 +246,22 @@ impl INode { } } + pub fn inc_link_count(&self) { + let inode_ptr = self.0.get(); + // SAFETY: Inode ptr is guaranteed to be valid and instantiated do to the typestate + unsafe { + bindings::inode_inc_link_count(inode_ptr); + } + } + + pub fn dec_link_count(&self) { + let inode_ptr = self.0.get(); + // SAFETY: Inode ptr is guaranteed to be valid and instantiated do to the typestate + unsafe { + bindings::inode_dec_link_count(inode_ptr); + } + } + /// Returns a mapper for this inode. /// /// # Safety From 43422f21390962bdea7266a0e1c0b882107a132c Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 10 Dec 2025 16:12:53 -0500 Subject: [PATCH 106/131] [ezfs] adjust allocate inode to new bitmap api --- fs/rustezfs/ezfs.rs | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index d1673ee0c9bc32..6420fcc3eb7fc5 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -117,15 +117,10 @@ impl RustEzFs { let ezfs_sb = sb.data(); let mut sb_data = ezfs_sb.data.lock(); - for (word_idx, &word) in sb_data.free_inodes.iter().enumerate() { - if word != !0u32 { - let bit_idx: u32 = (!word).trailing_zeros(); - let inode_num: usize = (word_idx * 32) + bit_idx as usize; - - if inode_num < EZFS_MAX_INODES { - sb_data.free_inodes[word_idx] |= 1 << bit_idx; - return Ok(inode_num + 1); // FS is 1-indexed - } + for idx in 0..EZFS_MAX_INODES { + if !sb_data.free_inodes.is_set(idx as u64) { + sb_data.free_inodes.set_bit(idx as u64); + return Ok(idx + 1); // FS is 1-indexed } } @@ -229,14 +224,6 @@ impl RustEzFs { ready_inode.mark_dirty(); - // TODO: Should this be here or in the end of create? - let ezfs_sb = sb.data(); - let mut sb_data = ezfs_sb.data.lock(); - - sb_data - .free_inodes - .set_bit((ino - EZFS_ROOT_INODE_NUMBER) as u64); - Ok(ready_inode) } From 13a4dad92e416e6cc11518a83bf20b17e5117120 Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 10 Dec 2025 21:05:45 -0500 Subject: [PATCH 107/131] [ezfs] move dir inc to inode creation --- fs/rustezfs/ezfs.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 6420fcc3eb7fc5..00a9e273f299c7 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -179,12 +179,15 @@ impl RustEzFs { new_inode.set_fops(Self::DIR_FOPS); let data_block_num = Self::allocate_data_block(sb)?; + ezfs_inode .set_nlink(2) .set_file_size(EZFS_BLOCK_SIZE as u64) .set_nblocks(8) .set_data_block_num(data_block_num); + dir.inc_link_count(); + Type::Dir } // FIXME: iget_failed called twice when this happens @@ -399,8 +402,6 @@ impl kernel::inode::Operations for RustEzFs { Self::create_helper(parent, dentry, mode | S_IFDIR as u16)?; - parent.inc_link_count(); - // Since we use d_instantiate_new we don't return a dentry Ok(None) } From 5b8cc7746d627ce81743e80586f603edb54abf9f Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 10 Dec 2025 22:04:19 -0500 Subject: [PATCH 108/131] [ezfs] fix dir time bug (bruh) --- fs/rustezfs/ezfs.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 00a9e273f299c7..83ebf49e1adc54 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -23,7 +23,7 @@ use kernel::prelude::*; use kernel::sb::{New, SuperBlock, Type as SuperType}; use kernel::task::{Kgid, Kuid}; use kernel::time::hrtimer::HrTimerExpires; -use kernel::time::{Instant, Monotonic, NSEC_PER_SEC}; +use kernel::time::{Instant, RealTime, NSEC_PER_SEC}; use kernel::transmute::{AsBytes, FromBytes}; use kernel::types::{ARef, Lockable, Locked}; use kernel::{c_str, fs, str::CStr}; @@ -58,13 +58,7 @@ impl RustEzFs { fn iget(sb: &SuperBlock, ino: usize) -> Result>> { pr_info!("iget(ino={ino})\n"); - let mut inode = match sb.get_or_create_inode(ino)? { - INodeState::Existing(inode) => return Ok(inode), - INodeState::Uninitilized(new_inode) => new_inode, - }; - let ezfs_sb = sb.data(); - { // Check if inode is allocated let sb_data = ezfs_sb.data.lock(); @@ -76,6 +70,11 @@ impl RustEzFs { } } + let mut inode = match sb.get_or_create_inode(ino)? { + INodeState::Existing(inode) => return Ok(inode), + INodeState::Uninitilized(new_inode) => new_inode, + }; + let offset = EZFS_INODE_STORE_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE; let mapped_inode_store = ezfs_sb.mapper.mapped_folio(offset.try_into()?)?; let inode_store = @@ -201,7 +200,7 @@ impl RustEzFs { .set_aops(Self::AOPS) .set_ino(ino); - let now = Instant::::now().as_nanos() / NSEC_PER_SEC; + let now = Instant::::now().as_nanos() / NSEC_PER_SEC; ezfs_inode .set_mode(mode) @@ -822,6 +821,7 @@ impl iomap::Operations for RustEzFs { // SAFETY: we've acquired the super block lock and can therefore // modify the ezfs inode + // FIXME: what about the inode lock? let ezfs_inode = unsafe { inode.data_mut() }; ezfs_inode .set_data_block_num(new_block_start + (EZFS_ROOT_DATABLOCK_NUMBER as u64)); From 62982a54714b78653c72e5eae014a17d2a0630e8 Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 10 Dec 2025 23:00:40 -0500 Subject: [PATCH 109/131] [ezfs] make bitmap safe --- fs/rustezfs/ezfs.rs | 16 ++++++++-------- fs/rustezfs/sb.rs | 26 ++++++++++++++++++++------ 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 83ebf49e1adc54..30792ddcd3178b 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -118,7 +118,7 @@ impl RustEzFs { for idx in 0..EZFS_MAX_INODES { if !sb_data.free_inodes.is_set(idx as u64) { - sb_data.free_inodes.set_bit(idx as u64); + sb_data.free_inodes.set_bit(idx as u64)?; return Ok(idx + 1); // FS is 1-indexed } } @@ -136,7 +136,7 @@ impl RustEzFs { .find(|&x| !sb_data.free_data_blocks.is_set(x)) .ok_or(ENOSPC)?; - sb_data.free_data_blocks.set_bit(data_block_num); + sb_data.free_data_blocks.set_bit(data_block_num)?; data_block_num }; @@ -616,15 +616,15 @@ impl kernel::sb::Operations for RustEzFs { for data_blk in start..end { sb_data .free_data_blocks - .clear_bit(data_blk - EZFS_ROOT_DATABLOCK_NUMBER as u64); + .clear_bit(data_blk - EZFS_ROOT_DATABLOCK_NUMBER as u64)?; sb_data .zero_data_blocks - .clear_bit(data_blk - EZFS_ROOT_DATABLOCK_NUMBER as u64); + .clear_bit(data_blk - EZFS_ROOT_DATABLOCK_NUMBER as u64)?; } sb_data .free_inodes - .clear_bit((ino - EZFS_ROOT_INODE_NUMBER) as u64); + .clear_bit((ino - EZFS_ROOT_INODE_NUMBER) as u64)?; } // TODO: Make clear consume inode @@ -779,7 +779,7 @@ impl iomap::Operations for RustEzFs { WriteCase::Extend => { for i in ez_blk_count..blocks_needed { let bit = ez_blk_sidx + i; - sb_data.free_data_blocks.set_bit(bit); + sb_data.free_data_blocks.set_bit(bit)?; } map.set_flags(iomap::map_flags::NEW); @@ -814,8 +814,8 @@ impl iomap::Operations for RustEzFs { Self::move_block(old, new, sb)?; - sb_data.free_data_blocks.clear_bit(old); - sb_data.free_data_blocks.set_bit(new); + sb_data.free_data_blocks.clear_bit(old)?; + sb_data.free_data_blocks.set_bit(new)?; } } diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index faaaba66f24c56..0506483795c3a5 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -66,23 +66,37 @@ pub(crate) struct Bitmap { impl Bitmap { #[inline] pub(crate) fn is_set(&self, block_num: u64) -> bool { - let idx: usize = (block_num / 32) as usize; + pr_info!("is set called"); + let idx = (block_num / 32) as usize; + if idx >= N { + return false; + } + let mask = 1 << (block_num % 32); (self.inner[idx] & mask) != 0 } #[inline] - pub(crate) fn set_bit(&mut self, block_num: u64) { - let idx: usize = (block_num / 32) as usize; + pub(crate) fn set_bit(&mut self, block_num: u64) -> Result { + pr_info!("set bit called"); + let idx = (block_num / 32) as usize; let mask = 1 << (block_num % 32); - self.inner[idx] |= mask + let val = self.inner.get_mut(idx).ok_or(EINVAL)?; + *val |= mask; + + Ok(()) } #[inline] - pub(crate) fn clear_bit(&mut self, block_num: u64) { + pub(crate) fn clear_bit(&mut self, block_num: u64) -> Result { + pr_info!("clear bit called"); + let idx: usize = (block_num / 32) as usize; let mask = 1 << (block_num % 32); - self.inner[idx] &= !mask + let val = self.inner.get_mut(idx).ok_or(EINVAL)?; + *val &= !mask; + + Ok(()) } const fn new(inner: [u32; N]) -> Self { From eb21cc86d3a8a2affc54cff85bdb5a31ceabdcde Mon Sep 17 00:00:00 2001 From: lsig Date: Thu, 11 Dec 2025 13:22:58 -0500 Subject: [PATCH 110/131] [ezfs] remove debug comments --- fs/rustezfs/sb.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index 0506483795c3a5..ed018fbf30befe 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -66,7 +66,6 @@ pub(crate) struct Bitmap { impl Bitmap { #[inline] pub(crate) fn is_set(&self, block_num: u64) -> bool { - pr_info!("is set called"); let idx = (block_num / 32) as usize; if idx >= N { return false; @@ -78,7 +77,6 @@ impl Bitmap { #[inline] pub(crate) fn set_bit(&mut self, block_num: u64) -> Result { - pr_info!("set bit called"); let idx = (block_num / 32) as usize; let mask = 1 << (block_num % 32); let val = self.inner.get_mut(idx).ok_or(EINVAL)?; @@ -89,8 +87,6 @@ impl Bitmap { #[inline] pub(crate) fn clear_bit(&mut self, block_num: u64) -> Result { - pr_info!("clear bit called"); - let idx: usize = (block_num / 32) as usize; let mask = 1 << (block_num % 32); let val = self.inner.get_mut(idx).ok_or(EINVAL)?; From 8048daa0f850e133f9e391c2163eb588f6b37f1c Mon Sep 17 00:00:00 2001 From: lsig Date: Thu, 11 Dec 2025 13:38:33 -0500 Subject: [PATCH 111/131] [ezfs] check inode allocation --- fs/rustezfs/ezfs.rs | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 30792ddcd3178b..245246b275e17d 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -56,20 +56,34 @@ impl RustEzFs { const IOPS: kernel::inode::Ops = kernel::inode::Ops::new::(); const AOPS: kernel::address_space::Ops = kernel::iomap::aops::(); + fn inode_allocated(sb: &SuperBlock, ino: usize) -> Result { + let ezfs_sb = sb.data(); + let sb_data = ezfs_sb.data.lock(); + + let idx: u64 = (ino - EZFS_ROOT_INODE_NUMBER).try_into()?; + + Ok(sb_data.free_inodes.is_set(idx)) + } + fn iget(sb: &SuperBlock, ino: usize) -> Result>> { pr_info!("iget(ino={ino})\n"); - let ezfs_sb = sb.data(); - { - // Check if inode is allocated - let sb_data = ezfs_sb.data.lock(); - if !sb_data - .free_inodes - .is_set((ino - EZFS_ROOT_INODE_NUMBER).try_into()?) - { - return Err(ENOENT); - } + // { + // // Check if inode is allocated + // let sb_data = ezfs_sb.data.lock(); + // if !sb_data + // .free_inodes + // .is_set((ino - EZFS_ROOT_INODE_NUMBER).try_into()?) + // { + // return Err(ENOENT); + // } + // } + + if !Self::inode_allocated(sb, ino)? { + return Err(ENOENT); } + let ezfs_sb = sb.data(); + let mut inode = match sb.get_or_create_inode(ino)? { INodeState::Existing(inode) => return Ok(inode), INodeState::Uninitilized(new_inode) => new_inode, From 575ca4f192dfaaed38a2cc363e855aab32c75ff7 Mon Sep 17 00:00:00 2001 From: lsig Date: Thu, 11 Dec 2025 13:38:55 -0500 Subject: [PATCH 112/131] [ezfs] remove old commented out code --- fs/rustezfs/ezfs.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 245246b275e17d..733de9456f607e 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -67,16 +67,6 @@ impl RustEzFs { fn iget(sb: &SuperBlock, ino: usize) -> Result>> { pr_info!("iget(ino={ino})\n"); - // { - // // Check if inode is allocated - // let sb_data = ezfs_sb.data.lock(); - // if !sb_data - // .free_inodes - // .is_set((ino - EZFS_ROOT_INODE_NUMBER).try_into()?) - // { - // return Err(ENOENT); - // } - // } if !Self::inode_allocated(sb, ino)? { return Err(ENOENT); From 1107bcb43c31e25734ebcb356ad094dc9924b914 Mon Sep 17 00:00:00 2001 From: lsig Date: Thu, 11 Dec 2025 14:23:38 -0500 Subject: [PATCH 113/131] [ezfs] follow same convention as inode for datablocks --- fs/rustezfs/ezfs.rs | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 733de9456f607e..85513033a1497d 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -123,7 +123,7 @@ impl RustEzFs { for idx in 0..EZFS_MAX_INODES { if !sb_data.free_inodes.is_set(idx as u64) { sb_data.free_inodes.set_bit(idx as u64)?; - return Ok(idx + 1); // FS is 1-indexed + return Ok(idx + EZFS_ROOT_INODE_NUMBER); // FS is 1-indexed } } @@ -132,18 +132,23 @@ impl RustEzFs { fn allocate_data_block(sb: &SuperBlock) -> Result { let ezfs_sb = sb.data(); + let max_blocks = Self::max_blocks(ezfs_sb); - let data_block_num = { - let mut sb_data = ezfs_sb.data.lock(); - let max_blocks = Self::get_max_blocks(ezfs_sb); - let data_block_num = (0..max_blocks) - .find(|&x| !sb_data.free_data_blocks.is_set(x)) - .ok_or(ENOSPC)?; + let mut sb_data = ezfs_sb.data.lock(); - sb_data.free_data_blocks.set_bit(data_block_num)?; + for idx in 0..max_blocks { + if !sb_data.free_data_blocks.is_set(idx) { + sb_data.free_data_blocks.set_bit(idx)?; + return Ok(idx + EZFS_ROOT_DATABLOCK_NUMBER as u64); + } + } - data_block_num - }; + Err(ENOSPC) + } + + fn zeroed_data_block(sb: &SuperBlock) -> Result { + let ezfs_sb = sb.data(); + let data_block_num = Self::allocate_data_block(sb)?; let offset = data_block_num .checked_mul(EZFS_BLOCK_SIZE as u64) @@ -157,7 +162,7 @@ impl RustEzFs { let mut guard = locked_folio.map(folio_start)?; guard.fill(0); - Ok(data_block_num + EZFS_ROOT_DATABLOCK_NUMBER as u64) + Ok(data_block_num) } fn new_inode( @@ -181,7 +186,7 @@ impl RustEzFs { fs::mode::S_IFDIR => { new_inode.set_fops(Self::DIR_FOPS); - let data_block_num = Self::allocate_data_block(sb)?; + let data_block_num = Self::zeroed_data_block(sb)?; ezfs_inode .set_nlink(2) @@ -245,7 +250,7 @@ impl RustEzFs { Ok(()) } - fn get_max_blocks(sb: Pin<&EzfsSuperblock>) -> u64 { + fn max_blocks(sb: Pin<&EzfsSuperblock>) -> u64 { (sb.disk_blocks - 2).min(EZFS_MAX_DATA_BLKS as u64) } @@ -735,7 +740,7 @@ impl iomap::Operations for RustEzFs { // As we'll modify the file system below, we must acquire a lock let mut sb_data = ezfs_sb.data.lock(); - let max_blocks = Self::get_max_blocks(ezfs_sb); + let max_blocks = Self::max_blocks(ezfs_sb); let blocks_needed = end_block + 1; let blocks_to_add = blocks_needed.checked_sub(ez_blk_count).ok_or(EIO)?; From 514c4616c8b2dc0d688ccbda82f059ab06647442 Mon Sep 17 00:00:00 2001 From: lsig Date: Thu, 11 Dec 2025 14:57:43 -0500 Subject: [PATCH 114/131] [ezfs] create deallocation functions --- fs/rustezfs/ezfs.rs | 50 ++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 85513033a1497d..e31f77ce10770b 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -30,6 +30,7 @@ use kernel::{c_str, fs, str::CStr}; use core::marker::PhantomData; use core::mem::size_of; +use core::ops::Range; use pin_init::{pin_data, PinInit}; struct RustEzFs; @@ -116,6 +117,34 @@ impl RustEzFs { }) } + fn deallocate_inode(sb: &SuperBlock, ino: usize) -> Result { + let ezfs_sb = sb.data(); + let mut sb_data = ezfs_sb.data.lock(); + + sb_data + .free_inodes + .clear_bit((ino - EZFS_ROOT_INODE_NUMBER) as u64)?; + + Ok(()) + } + + fn deallocate_data_blocks(sb: &SuperBlock, range: Range) -> Result { + let ezfs_sb = sb.data(); + let mut sb_data = ezfs_sb.data.lock(); + + for data_blk in range { + sb_data + .free_data_blocks + .clear_bit(data_blk - EZFS_ROOT_DATABLOCK_NUMBER as u64)?; + + sb_data + .zero_data_blocks + .clear_bit(data_blk - EZFS_ROOT_DATABLOCK_NUMBER as u64)?; + } + + Ok(()) + } + fn allocate_inode(sb: &SuperBlock) -> Result { let ezfs_sb = sb.data(); let mut sb_data = ezfs_sb.data.lock(); @@ -613,27 +642,14 @@ impl kernel::sb::Operations for RustEzFs { fn evict_inode(inode: &INode) -> Result { if inode.nlink() == 0 { - let sb = inode.super_block().data(); + let sb = inode.super_block(); let ino = inode.ino(); - let ezfs_inode = inode.data(); - let start = ezfs_inode.data_blk_num(); + let start = inode.data().data_blk_num(); let end = start + inode.blocks(); - let mut sb_data = sb.data.lock(); - - for data_blk in start..end { - sb_data - .free_data_blocks - .clear_bit(data_blk - EZFS_ROOT_DATABLOCK_NUMBER as u64)?; - sb_data - .zero_data_blocks - .clear_bit(data_blk - EZFS_ROOT_DATABLOCK_NUMBER as u64)?; - } - - sb_data - .free_inodes - .clear_bit((ino - EZFS_ROOT_INODE_NUMBER) as u64)?; + Self::deallocate_data_blocks(sb, start..end)?; + Self::deallocate_inode(sb, ino)?; } // TODO: Make clear consume inode From 68b511134828e3d32e8b2c227a8763cb9253aa44 Mon Sep 17 00:00:00 2001 From: lsig Date: Thu, 11 Dec 2025 15:47:13 -0500 Subject: [PATCH 115/131] [ezfs] adjust functions to formally verified counterpart --- fs/rustezfs/ezfs.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index e31f77ce10770b..540d57754fe703 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -61,7 +61,10 @@ impl RustEzFs { let ezfs_sb = sb.data(); let sb_data = ezfs_sb.data.lock(); - let idx: u64 = (ino - EZFS_ROOT_INODE_NUMBER).try_into()?; + let idx: u64 = ino + .checked_sub(EZFS_ROOT_INODE_NUMBER) + .ok_or(EINVAL)? + .try_into()?; Ok(sb_data.free_inodes.is_set(idx)) } @@ -123,7 +126,7 @@ impl RustEzFs { sb_data .free_inodes - .clear_bit((ino - EZFS_ROOT_INODE_NUMBER) as u64)?; + .clear_bit((ino.checked_sub(EZFS_ROOT_INODE_NUMBER).ok_or(EINVAL)?) as u64)?; Ok(()) } From d1b2a1be0f7ba2ac4aa0bcbc1308e7fdacdf4edd Mon Sep 17 00:00:00 2001 From: lsig Date: Thu, 11 Dec 2025 16:56:16 -0500 Subject: [PATCH 116/131] [ezfs] adjust for formal verification (no panics bby) --- fs/rustezfs/ezfs.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 540d57754fe703..d9c4ca99a7675a 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -164,7 +164,7 @@ impl RustEzFs { fn allocate_data_block(sb: &SuperBlock) -> Result { let ezfs_sb = sb.data(); - let max_blocks = Self::max_blocks(ezfs_sb); + let max_blocks = Self::max_blocks(ezfs_sb)?; let mut sb_data = ezfs_sb.data.lock(); @@ -282,8 +282,8 @@ impl RustEzFs { Ok(()) } - fn max_blocks(sb: Pin<&EzfsSuperblock>) -> u64 { - (sb.disk_blocks - 2).min(EZFS_MAX_DATA_BLKS as u64) + fn max_blocks(sb: Pin<&EzfsSuperblock>) -> Result { + Ok((sb.disk_blocks.checked_sub(2).ok_or(EINVAL)?).min(EZFS_MAX_DATA_BLKS as u64)) } fn find_dir_entry( @@ -759,7 +759,7 @@ impl iomap::Operations for RustEzFs { // As we'll modify the file system below, we must acquire a lock let mut sb_data = ezfs_sb.data.lock(); - let max_blocks = Self::max_blocks(ezfs_sb); + let max_blocks = Self::max_blocks(ezfs_sb)?; let blocks_needed = end_block + 1; let blocks_to_add = blocks_needed.checked_sub(ez_blk_count).ok_or(EIO)?; From 147fb2f31f96bb7d077bf417412d611a40279540 Mon Sep 17 00:00:00 2001 From: lsig Date: Thu, 11 Dec 2025 17:41:20 -0500 Subject: [PATCH 117/131] [ezfs] formally verify deallocate (no panic) --- fs/rustezfs/ezfs.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index d9c4ca99a7675a..ab08906a9ec85f 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -136,13 +136,12 @@ impl RustEzFs { let mut sb_data = ezfs_sb.data.lock(); for data_blk in range { - sb_data - .free_data_blocks - .clear_bit(data_blk - EZFS_ROOT_DATABLOCK_NUMBER as u64)?; + let blk_idx = data_blk + .checked_sub(EZFS_ROOT_DATABLOCK_NUMBER as u64) + .ok_or(EINVAL)?; - sb_data - .zero_data_blocks - .clear_bit(data_blk - EZFS_ROOT_DATABLOCK_NUMBER as u64)?; + sb_data.free_data_blocks.clear_bit(blk_idx)?; + sb_data.zero_data_blocks.clear_bit(blk_idx)?; } Ok(()) From 253c6e5f1655ba4807fb73888c01ed11b61004b8 Mon Sep 17 00:00:00 2001 From: lsig Date: Fri, 12 Dec 2025 12:59:35 -0500 Subject: [PATCH 118/131] [ezfs] transaction checkpoint --- fs/rustezfs/ezfs.rs | 59 +++---------------------- fs/rustezfs/sb.rs | 105 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 111 insertions(+), 53 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index ab08906a9ec85f..bb17150100315b 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -8,7 +8,7 @@ mod inode; mod sb; use crate::dir::{DirEntryStore, EzfsDirEntry}; use crate::inode::{EzfsInode, InodeStore}; -use crate::sb::{EzfsSuperblock, EzfsSuperblockDisk}; +use crate::sb::{EzfsSuperblock, EzfsSuperblockDisk, Transaction}; use defs::*; use kernel::bindings; use kernel::dentry; @@ -147,55 +147,6 @@ impl RustEzFs { Ok(()) } - fn allocate_inode(sb: &SuperBlock) -> Result { - let ezfs_sb = sb.data(); - let mut sb_data = ezfs_sb.data.lock(); - - for idx in 0..EZFS_MAX_INODES { - if !sb_data.free_inodes.is_set(idx as u64) { - sb_data.free_inodes.set_bit(idx as u64)?; - return Ok(idx + EZFS_ROOT_INODE_NUMBER); // FS is 1-indexed - } - } - - Err(ENOSPC) - } - - fn allocate_data_block(sb: &SuperBlock) -> Result { - let ezfs_sb = sb.data(); - let max_blocks = Self::max_blocks(ezfs_sb)?; - - let mut sb_data = ezfs_sb.data.lock(); - - for idx in 0..max_blocks { - if !sb_data.free_data_blocks.is_set(idx) { - sb_data.free_data_blocks.set_bit(idx)?; - return Ok(idx + EZFS_ROOT_DATABLOCK_NUMBER as u64); - } - } - - Err(ENOSPC) - } - - fn zeroed_data_block(sb: &SuperBlock) -> Result { - let ezfs_sb = sb.data(); - let data_block_num = Self::allocate_data_block(sb)?; - - let offset = data_block_num - .checked_mul(EZFS_BLOCK_SIZE as u64) - .ok_or(EIO)?; - - let folio: ARef>> = - ezfs_sb.mapper.read_mapping_folio(offset.try_into()?)?; - - let folio_start = 0; - let locked_folio = folio.lock(); - let mut guard = locked_folio.map(folio_start)?; - guard.fill(0); - - Ok(data_block_num) - } - fn new_inode( dir: &Locked<&INode, kernel::inode::ReadSem>, mode: u32, @@ -204,7 +155,9 @@ impl RustEzFs { let mut new_inode = sb.new_inode()?; let mut ezfs_inode = EzfsInode::default(); - let ino = Self::allocate_inode(sb)?; + let mut tx = Transaction::new(sb); + let ino = tx.allocate_inode()?; + pr_info!("Allocating new inode: {:?}\n", ino); let typ = match mode & fs::mode::S_IFMT { @@ -217,7 +170,8 @@ impl RustEzFs { fs::mode::S_IFDIR => { new_inode.set_fops(Self::DIR_FOPS); - let data_block_num = Self::zeroed_data_block(sb)?; + let max_blocks = Self::max_blocks(sb.data())?; + let data_block_num = tx.zeroed_data_block(max_blocks)?; ezfs_inode .set_nlink(2) @@ -265,6 +219,7 @@ impl RustEzFs { })?; ready_inode.mark_dirty(); + tx.commit(); Ok(ready_inode) } diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index ed018fbf30befe..a8f0442d5caf98 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -1,12 +1,18 @@ -use crate::defs::{EZFS_BLOCK_SIZE, EZFS_MAX_DATA_BLKS, EZFS_MAX_INODES}; +use crate::defs::{ + EZFS_BLOCK_SIZE, EZFS_MAX_DATA_BLKS, EZFS_MAX_INODES, EZFS_ROOT_DATABLOCK_NUMBER, + EZFS_ROOT_INODE_NUMBER, +}; use crate::RustEzFs; use core::mem::size_of; use core::ops::{Deref, DerefMut}; +use kernel::folio::Folio; use kernel::inode; use kernel::new_mutex; use kernel::prelude::*; +use kernel::sb::SuperBlock; use kernel::sync::Mutex; use kernel::transmute::{AsBytes, FromBytes}; +use kernel::types::{ARef, Lockable}; #[repr(C)] pub(crate) struct EzfsSuperblockDiskRaw { @@ -163,3 +169,100 @@ impl EzfsSuperblock { disk_sb } } + +pub(crate) struct Transaction<'a> { + sb: &'a SuperBlock, + allocated_inodes: KVec, + allocated_blocks: KVec, + committed: bool, +} + +impl<'a> Transaction<'a> { + pub(crate) fn new(sb: &'a SuperBlock) -> Self { + Self { + sb, + allocated_inodes: Vec::new(), + allocated_blocks: Vec::new(), + committed: false, + } + } + + pub(crate) fn allocate_inode(&mut self) -> Result { + let ezfs_sb = self.sb.data(); + let mut sb_data = ezfs_sb.data.lock(); + + for idx in 0..EZFS_MAX_INODES { + if !sb_data.free_inodes.is_set(idx as u64) { + sb_data.free_inodes.set_bit(idx as u64)?; + self.allocated_inodes.push(idx as u64, GFP_KERNEL)?; + return Ok(idx + EZFS_ROOT_INODE_NUMBER); + } + } + + Err(ENOSPC) + } + + pub(crate) fn allocate_data_block(&mut self, max_blocks: u64) -> Result { + let ezfs_sb = self.sb.data(); + + let mut sb_data = ezfs_sb.data.lock(); + + for idx in 0..max_blocks { + if !sb_data.free_data_blocks.is_set(idx) { + sb_data.free_data_blocks.set_bit(idx)?; + self.allocated_blocks.push(idx, GFP_KERNEL)?; + return Ok(idx + EZFS_ROOT_DATABLOCK_NUMBER as u64); + } + } + + Err(ENOSPC) + } + + pub(crate) fn zeroed_data_block(&mut self, max_blocks: u64) -> Result { + let ezfs_sb = self.sb.data(); + let data_block_num = self.allocate_data_block(max_blocks)?; + + let offset = data_block_num + .checked_mul(EZFS_BLOCK_SIZE as u64) + .ok_or(EIO)?; + + let folio: ARef>> = + ezfs_sb.mapper.read_mapping_folio(offset.try_into()?)?; + + let folio_start = 0; + let locked_folio = folio.lock(); + let mut guard = locked_folio.map(folio_start)?; + guard.fill(0); + + Ok(data_block_num) + } + + pub(crate) fn commit(mut self) { + self.committed = true; + } +} + +impl<'a> Drop for Transaction<'a> { + fn drop(&mut self) { + if !self.committed { + pr_info!( + "Rolling back transaction: {} inodes, {} blocks\n", + self.allocated_inodes.len(), + self.allocated_blocks.len() + ); + + let ezfs_sb = self.sb.data(); + let mut sb_data = ezfs_sb.data.lock(); + + // SAFETY: Index is guaranteed valid since it was successfully allocated + for &idx in &self.allocated_blocks { + let _ = sb_data.free_data_blocks.clear_bit(idx); + let _ = sb_data.zero_data_blocks.clear_bit(idx); + } + + for &idx in &self.allocated_inodes { + let _ = sb_data.free_inodes.clear_bit(idx); + } + } + } +} From c4b8f07d919c35a7fa719685842b12fa6157d0b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Sun, 14 Dec 2025 21:16:07 -0500 Subject: [PATCH 119/131] write to fresh files --- fs/rustezfs/ezfs.rs | 12 +++--------- rust/kernel/folio.rs | 3 --- rust/kernel/fs/file.rs | 2 -- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index bb17150100315b..a34a81541d3a4b 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -70,7 +70,7 @@ impl RustEzFs { } fn iget(sb: &SuperBlock, ino: usize) -> Result>> { - pr_info!("iget(ino={ino})\n"); + // pr_info!("iget(ino={ino})\n"); if !Self::inode_allocated(sb, ino)? { return Err(ENOENT); @@ -326,7 +326,6 @@ impl FileSystem for RustEzFs { sb: &mut SuperBlock, mapper: Option>, ) -> Result { - pr_info!("fill_super()\n"); let Some(mapper) = mapper else { return Err(EINVAL); }; @@ -349,7 +348,6 @@ impl FileSystem for RustEzFs { } fn init_root(sb: &SuperBlock) -> Result> { - pr_info!("init_root()\n"); let inode = Self::iget(sb, EZFS_ROOT_INODE_NUMBER)?; dentry::Root::try_new(inode) } @@ -367,7 +365,7 @@ impl kernel::inode::Operations for RustEzFs { let dir_entry = Self::find_dir_entry(parent, &dentry)?; let inode = if let Some(entry) = dir_entry { - pr_info!("Inode found: {:?}\n", entry.inode_no()); + // pr_info!("Inode found: {:?}\n", entry.inode_no()); Some(Self::iget(sb, entry.inode_no().try_into()?)?) } else { None @@ -753,10 +751,6 @@ impl iomap::Operations for RustEzFs { }; match case_type { - WriteCase::New => { - pr_info!("adding to an empty file\n"); - return Err(EIO); - } WriteCase::Within => {} WriteCase::Extend => { for i in ez_blk_count..blocks_needed { @@ -766,7 +760,7 @@ impl iomap::Operations for RustEzFs { map.set_flags(iomap::map_flags::NEW); } - WriteCase::Move => { + WriteCase::New | WriteCase::Move => { // Let's try to find a region of sequential free blocks // of size `blocks_needed` to move our file to let mut curr_block = 0; diff --git a/rust/kernel/folio.rs b/rust/kernel/folio.rs index 6fd9f9596a6e3f..e774949c82a4d8 100644 --- a/rust/kernel/folio.rs +++ b/rust/kernel/folio.rs @@ -213,7 +213,6 @@ impl DerefMut for MapGuardMut<'_> { impl Drop for MapGuardMut<'_> { fn drop(&mut self) { - pr_info!("Dropped guard, set pag dirty and unmapped\n"); // SAFETY: A `MapGuard` instance is only created when `kmap` succeeds, so it's ok to unmap // it when the guard is dropped. unsafe { @@ -226,13 +225,11 @@ impl Drop for MapGuardMut<'_> { // SAFETY: `raw_lock` calls folio_lock, which actually locks the folio. unsafe impl Lockable for Folio { fn raw_lock(&self) { - pr_info!("Locked folio\n"); // SAFETY: The folio is valid because the shared reference implies a non-zero refcount. unsafe { bindings::folio_lock(self.0.get()) } } unsafe fn unlock(&self) { - pr_info!("unlocked folio\n"); // SAFETY: The safety requirements guarantee that the folio is locked. unsafe { bindings::folio_unlock(self.0.get()) } } diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index 10b7ee5153df2f..9de73c2fe3da3d 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -726,7 +726,6 @@ impl Ops { kiocb: *mut bindings::kiocb, iter: *mut bindings::iov_iter, ) -> isize { - pr_info!("read_iter_callback\n"); return unsafe { bindings::generic_file_read_iter(kiocb, iter) }; } @@ -739,7 +738,6 @@ impl Ops { iter: *mut bindings::iov_iter, ) -> isize { from_result(|| { - pr_info!("write_iter_callback\n"); // SAFETY: The caller provides a valid `struct kiocb` associated with a // `` file. let kiocb = unsafe { Kiocb::from_raw(kiocb) }; From 2cfbde3907f167589d7e952a98a3ccfd44c424f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Mon, 15 Dec 2025 01:17:46 -0500 Subject: [PATCH 120/131] fix writes after backwards seeks --- fs/rustezfs/ezfs.rs | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index a34a81541d3a4b..1c1c27c8e86a4a 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -482,22 +482,6 @@ impl file::Operations for RustEzFs { file::generic_seek(file, offset, whence) } - // TODO: file::Operations currently just calls generic_file_read_iter directly - // we might want to move it here but that requires us being able to have both - // Kiocb and IovIterDest implement ::to_ptr(); Let's do that later - // fn read_iter( - // _kiocb: Kiocb<'_, ::Data>, - // _iov: &mut IovIterDest<'_>, - // ) -> Result { - // pr_info!("read_iter()\n"); - // - // // from_result(|| { - // // let res = unsafe { bindings::generic_file_read_iter() }; - // // }) - // - // Err(EINVAL) - // } - fn read_dir( file: &File, inode: &Locked<&INode, kernel::inode::ReadSem>, @@ -713,7 +697,7 @@ impl iomap::Operations for RustEzFs { let max_blocks = Self::max_blocks(ezfs_sb)?; let blocks_needed = end_block + 1; - let blocks_to_add = blocks_needed.checked_sub(ez_blk_count).ok_or(EIO)?; + let blocks_to_add = blocks_needed.saturating_sub(ez_blk_count); // TODO: is this necessary ? if blocks_needed > max_blocks { From 3ef829c1dcff9139c4c467c213aac03345c83ae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3fer=20Fannar=20Bj=C3=B6rnsson?= Date: Mon, 15 Dec 2025 01:30:43 -0500 Subject: [PATCH 121/131] remove `pr_info!`s --- fs/rustezfs/ezfs.rs | 28 ---------------------------- fs/rustezfs/sb.rs | 2 +- rust/kernel/address_space.rs | 3 --- rust/kernel/folio.rs | 1 - rust/kernel/fs/file.rs | 1 - rust/kernel/iomap.rs | 5 ----- 6 files changed, 1 insertion(+), 39 deletions(-) diff --git a/fs/rustezfs/ezfs.rs b/fs/rustezfs/ezfs.rs index 1c1c27c8e86a4a..ca1c0f4432bf5d 100644 --- a/fs/rustezfs/ezfs.rs +++ b/fs/rustezfs/ezfs.rs @@ -70,8 +70,6 @@ impl RustEzFs { } fn iget(sb: &SuperBlock, ino: usize) -> Result>> { - // pr_info!("iget(ino={ino})\n"); - if !Self::inode_allocated(sb, ino)? { return Err(ENOENT); } @@ -158,8 +156,6 @@ impl RustEzFs { let mut tx = Transaction::new(sb); let ino = tx.allocate_inode()?; - pr_info!("Allocating new inode: {:?}\n", ino); - let typ = match mode & fs::mode::S_IFMT { fs::mode::S_IFREG => { new_inode.set_fops(Self::FILE_FOPS); @@ -273,8 +269,6 @@ impl RustEzFs { dentry: dentry::Unhashed<'_, Self>, mode: u16, ) -> Result { - pr_info!("Calling create helper from rustezfs\n"); - let new_inode = Self::new_inode(parent, mode.into())?; let ino: u64 = new_inode.ino().try_into()?; @@ -365,7 +359,6 @@ impl kernel::inode::Operations for RustEzFs { let dir_entry = Self::find_dir_entry(parent, &dentry)?; let inode = if let Some(entry) = dir_entry { - // pr_info!("Inode found: {:?}\n", entry.inode_no()); Some(Self::iget(sb, entry.inode_no().try_into()?)?) } else { None @@ -380,8 +373,6 @@ impl kernel::inode::Operations for RustEzFs { mode: u16, _excl: bool, ) -> Result { - pr_info!("Calling create from rustezfs\n"); - Self::create_helper(parent, dentry, mode) } @@ -390,8 +381,6 @@ impl kernel::inode::Operations for RustEzFs { dentry: dentry::Unhashed<'_, Self::FileSystem>, mode: u16, ) -> Result>>> { - pr_info!("Calling mkdir from rustezfs\n"); - Self::create_helper(parent, dentry, mode | S_IFDIR as u16)?; // Since we use d_instantiate_new we don't return a dentry @@ -478,7 +467,6 @@ impl file::Operations for RustEzFs { type FileSystem = Self; fn seek(file: &File, offset: Offset, whence: file::Whence) -> Result { - pr_info!("seek()\n"); file::generic_seek(file, offset, whence) } @@ -487,7 +475,6 @@ impl file::Operations for RustEzFs { inode: &Locked<&INode, kernel::inode::ReadSem>, emitter: &mut file::DirEmitter, ) -> Result { - // pr_info!("read_dir()\n"); let pos: usize = emitter.pos().try_into().map_err(|_| ENOENT)?; if pos < 2 && !emitter.emit_dots(file) { @@ -507,14 +494,11 @@ impl file::Operations for RustEzFs { disk_pos / size_of::() }; - // pr_info!("emitter index: {:?}", index); - if index >= EZFS_MAX_CHILDREN { return Ok(()); } let ezfs_dir_inode = inode.data(); - // pr_info!("inode data_blk_num: {:?}", ezfs_dir_inode.data_blk_num()); let offset = ezfs_dir_inode .data_blk_num() @@ -557,7 +541,6 @@ impl file::Operations for RustEzFs { mut kiocb: Kiocb<'_, ::Data>, iov: &mut IovIterSource<'_>, ) -> Result { - pr_info!("write_iter\n"); let flags = kiocb.ki_flags(); let file: &File = kiocb.ki_filp(); @@ -599,7 +582,6 @@ impl kernel::sb::Operations for RustEzFs { } fn write_inode(inode: &INode) -> Result { - pr_info!("write inode called\n"); let ezfs_sb = inode.super_block().data(); let ino = inode.ino(); let disk_inode = EzfsInode::from_vfs_inode(inode)?; @@ -620,7 +602,6 @@ impl kernel::sb::Operations for RustEzFs { } fn sync_fs(sb: &SuperBlock) -> Result { - pr_info!("sync_fs called\n"); let ezfs_sb = sb.data(); let offset = (EZFS_SUPERBLOCK_DATABLOCK_NUMBER * EZFS_BLOCK_SIZE) as u64; @@ -650,8 +631,6 @@ impl iomap::Operations for RustEzFs { map: &mut iomap::Map<'a>, _srcmap: Option<&mut iomap::Map<'a>>, ) -> Result { - pr_info!("iomap_begin()\n"); - let sb = inode.super_block(); let ezfs_sb: Pin<&EzfsSuperblock> = sb.data(); let ezfs_inode = inode.data(); @@ -659,13 +638,9 @@ impl iomap::Operations for RustEzFs { let start_block: u64 = (pos >> sb.blocksize_bits()).try_into()?; let end_block: u64 = ((pos + length - 1) >> sb.blocksize_bits()).try_into()?; - // pr_info!("start_block: {start_block}, end_block: {end_block}\n"); - let ez_blk_num = ezfs_inode.data_blk_num(); let ez_blk_count = inode.blocks() / 8; - // pr_info!("blk_num: {ez_blk_num}, ez_blk_count: {ez_blk_count}\n"); - let mut phys = if ez_blk_num > 0 { ez_blk_num + start_block } else { @@ -725,8 +700,6 @@ impl iomap::Operations for RustEzFs { return Err(ENOSPC); } - // pr_info!("start={start} - end={end}\n"); - if (start..end).any(|bit| sb_data.free_data_blocks.is_set(bit)) { WriteCase::Move } else { @@ -805,7 +778,6 @@ impl iomap::Operations for RustEzFs { _map: &iomap::Map<'a>, ) -> Result { if written > 0 { - pr_info!("iomap_end()\n"); let new_blocks = ((inode.size() + (EZFS_BLOCK_SIZE as i64) - 1) / EZFS_BLOCK_SIZE as i64) as u64; // let sb = inode.super_block(); diff --git a/fs/rustezfs/sb.rs b/fs/rustezfs/sb.rs index a8f0442d5caf98..881e2493d03f03 100644 --- a/fs/rustezfs/sb.rs +++ b/fs/rustezfs/sb.rs @@ -245,7 +245,7 @@ impl<'a> Transaction<'a> { impl<'a> Drop for Transaction<'a> { fn drop(&mut self) { if !self.committed { - pr_info!( + pr_warn!( "Rolling back transaction: {} inodes, {} blocks\n", self.allocated_inodes.len(), self.allocated_blocks.len() diff --git a/rust/kernel/address_space.rs b/rust/kernel/address_space.rs index 5e8842f180ffa6..63271d825eb322 100644 --- a/rust/kernel/address_space.rs +++ b/rust/kernel/address_space.rs @@ -4,7 +4,6 @@ //! //! C headers: [`include/linux/fs.h`](srctree/include/linux/fs.h) -use crate::pr_info; use crate::{ error::{from_result, Result}, folio::Folio, @@ -69,8 +68,6 @@ impl Ops { folio_ptr: *mut bindings::folio, ) -> i32 { from_result(|| { - pr_info!("RUSTEZFS: in read_folio_callback\n"); - let file = if file_ptr.is_null() { None } else { diff --git a/rust/kernel/folio.rs b/rust/kernel/folio.rs index e774949c82a4d8..a7356cc25c109b 100644 --- a/rust/kernel/folio.rs +++ b/rust/kernel/folio.rs @@ -7,7 +7,6 @@ use core::{ use crate::{ error::Result, fs::FileSystem, - pr_info, prelude::EDOM, types::{ARef, AlwaysRefCounted, Lockable, Locked, Opaque}, }; diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index 9de73c2fe3da3d..badba9786c45c7 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -22,7 +22,6 @@ use crate::{ user, }; -use crate::pr_info; use core::{marker::PhantomData, mem::ManuallyDrop, ptr}; /// Flags associated with a [`File`]. diff --git a/rust/kernel/iomap.rs b/rust/kernel/iomap.rs index 866c02204d0e33..9be71c4c16597b 100644 --- a/rust/kernel/iomap.rs +++ b/rust/kernel/iomap.rs @@ -7,7 +7,6 @@ use super::address_space; use crate::error::{to_result, Error}; use crate::iov::IovIterSource; -use crate::pr_info; use crate::prelude::{EIO, EOVERFLOW}; use crate::{ block, @@ -228,8 +227,6 @@ impl Table { end_pos: u64, ) -> isize { from_result(|| { - pr_info!("writeback_range()\n"); - // SAFETY: For this callback, iomap guarantees: // - `folio_ptr` points to a live `struct folio`. // - The folio remains valid and locked for the duration of this call. @@ -281,8 +278,6 @@ impl Table { wpc: *mut bindings::iomap_writepage_ctx, error: i32, ) -> i32 { - pr_info!("writeback_submit()\n"); - // SAFETY: VFS/iomap guarantees `wpc` is valid here. unsafe { bindings::iomap_ioend_writeback_submit(wpc, error) } } From e0dab6a0088584e4ee26e2ed07043f9fb4cbbbdc Mon Sep 17 00:00:00 2001 From: lsig Date: Fri, 19 Dec 2025 12:02:37 -0500 Subject: [PATCH 122/131] [chore] add readme for rezfs --- README.REZFS.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 README.REZFS.md diff --git a/README.REZFS.md b/README.REZFS.md new file mode 100644 index 00000000000000..27ec6f36698316 --- /dev/null +++ b/README.REZFS.md @@ -0,0 +1,15 @@ +# How to setup RezFS + +1. ```cp RUSTFS_CONFIG .config``` +2. ```make LLVM=1``` +3. ```sudo make modules_install && sudo make install``` +4. ```sudo reboot``` +5. ```Select your newly built kernel in GRUB``` +6. Create a disk image: ```dd bs=4096 count=1000 if=/dev/zero of=ez_disk.img``` +7. Format the disk image: ```fs/rustezfs/format_disk_as_ezfs ez_disk.img 1000``` +8. Find a loop device: ```sudo losetup --find --show ez_disk.img``` +9. Load file system: ```sudo insmod fs/rustezfs/rustezfs.ko``` +10. Create mount point: ```mkdir /mnt/ez``` +11. Mount file system: ```sudo mount -t rustezfs /dev/loop /mnt/ez``` + +if you land in trouble you can follow this guide for kernel development: https://w4118.github.io/ From 36628b6cb09f460a8620604f9af43a38a4f13436 Mon Sep 17 00:00:00 2001 From: lsig Date: Thu, 29 Jan 2026 11:22:08 -0500 Subject: [PATCH 123/131] [clippy] address warnings --- rust/kernel/block.rs | 2 +- rust/kernel/fs/file.rs | 22 +++++++++------------- rust/kernel/inode.rs | 36 ++++++++++++++---------------------- rust/kernel/iomap.rs | 6 +++--- rust/kernel/sb.rs | 4 ++-- rust/kernel/user.rs | 2 +- 6 files changed, 30 insertions(+), 42 deletions(-) diff --git a/rust/kernel/block.rs b/rust/kernel/block.rs index 1aef16bbca393c..9386a6ed5705f5 100644 --- a/rust/kernel/block.rs +++ b/rust/kernel/block.rs @@ -56,7 +56,7 @@ impl Device { pub fn inode(&self) -> &INode { // SAFETY: `bd_inode` is never reassigned. let mapping = unsafe { (*self.0.get()).bd_mapping }; - // TODO: Why is this safe + // TODO: add safety let inode_ptr = unsafe { (*mapping).host }; // SAFET: `ptr` is valid as long as the block device remains valid as well. unsafe { INode::from_raw(inode_ptr) } diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index badba9786c45c7..589e44cd6fca62 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -725,7 +725,7 @@ impl Ops { kiocb: *mut bindings::kiocb, iter: *mut bindings::iov_iter, ) -> isize { - return unsafe { bindings::generic_file_read_iter(kiocb, iter) }; + unsafe { bindings::generic_file_read_iter(kiocb, iter) } } /// # Safety @@ -741,9 +741,9 @@ impl Ops { // `` file. let kiocb = unsafe { Kiocb::from_raw(kiocb) }; // SAFETY: This is a valid `struct iov_iter` for reading. - let mut iov = unsafe { IovIterSource::from_raw(iter) }; + let iov = unsafe { IovIterSource::from_raw(iter) }; - let wrote = T::write_iter(kiocb, &mut iov)?; + let wrote = T::write_iter(kiocb, iov)?; Ok(wrote.try_into()?) }) @@ -824,7 +824,7 @@ impl Ops { // been succesfully emitted: this is because we want users to see them before // the error. match T::read_dir(file, &locked, emitter) { - Ok(_) => Ok(0), + Ok(()) => Ok(0), Err(e) => { if emitter.pos() == orig_pos { Err(e) @@ -960,7 +960,7 @@ impl DirEmitter { name_len, self.0.pos, ino, - etype as _, + etype as u32, ) }; if ret { @@ -970,16 +970,12 @@ impl DirEmitter { } pub fn emit_dots(&mut self, file: &File) -> bool { - if self.0.pos == 0 { - if !self.emit(1, b".", file.inode().ino() as u64, DirEntryType::Dir) { - return false; - } + if self.0.pos == 0 && !self.emit(1, b".", file.inode().ino() as u64, DirEntryType::Dir) { + return false; } - if self.0.pos == 1 { - if !self.emit(1, b"..", file.parent_ino() as u64, DirEntryType::Dir) { - return false; - } + if self.0.pos == 1 && !self.emit(1, b"..", file.parent_ino() as u64, DirEntryType::Dir) { + return false; } true diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index 4fee1b64f19fbb..0a813d20e54d36 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -117,7 +117,7 @@ impl INode { } pub(crate) const fn as_raw(&self) -> *const bindings::inode { - unsafe { self.0.get() as *const bindings::inode } + self.0.get().cast_const() } /// Returns the number of the inode. @@ -193,12 +193,11 @@ impl INode { // FIXME: should consume self so you can't call any methods after clearing pub fn clear(&self) { - // SAFETY: type semantics guarentee that Inode is instatiated let inode_ptr = self.0.get(); unsafe { bindings::clear_inode(inode_ptr) } } - // FIXME: Does this work??? + // FIXME: Smells bad pub unsafe fn set_blocks(&self, num_blocks: u64) { unsafe { (*self.0.get()).i_blocks = num_blocks }; } @@ -208,7 +207,7 @@ impl INode { if T::IS_UNSPECIFIED { crate::build_error!("inode data type is unspecified"); } - // TODO: Add safety + // SAFETY: Inode is guaranteed to be instantiated because of the typestate let outerp = unsafe { container_of!(self.0.get(), WithData, inode) }; // SAFETY: `self` is guaranteed to be valid by the existence of a shared reference // (`&self`) to it. Additionally, we know `T::INodeData` is always initialised in an @@ -230,7 +229,7 @@ impl INode { if T::IS_UNSPECIFIED { crate::build_error!("inode data type is unspecified"); } - // TODO: Add safety + // SAFETY: Inode is guaranteed to be instantiated because of the typestate let outerp = unsafe { container_of!(self.0.get(), WithData, inode) }; // SAFETY: `self` is guaranteed to be valid by the existence of a shared reference // (`&self`) to it. Additionally, we know `T::INodeData` is always initialised in an @@ -301,11 +300,7 @@ impl INode { index: PageOffset, ) -> Result>>> { let folio = from_err_ptr(unsafe { - bindings::read_mapping_folio( - (*self.0.get()).i_mapping, - index.try_into()?, - ptr::null_mut(), - ) + bindings::read_mapping_folio((*self.0.get()).i_mapping, index, ptr::null_mut()) })?; let ptr = ptr::NonNull::new(folio) .ok_or(EIO)? @@ -327,8 +322,6 @@ impl INode { } pub fn mark_dirty(&self) { - // SAFETY: This is safe since it is guaranteed by the typestate - // that the inode has been inserted into the hash let inode = self.0.get(); unsafe { bindings::mark_inode_dirty(inode) }; } @@ -486,8 +479,7 @@ impl Mapper { } let page_index = offset >> bindings::PAGE_SHIFT; - let mut folio = self.inode.read_mapping_folio(page_index.try_into()?); - folio + self.inode.read_mapping_folio(page_index.try_into()?) } } @@ -548,12 +540,12 @@ impl New { } Type::Fifo => { // SAFETY: `inode` is valid for write as it's a new inode. - unsafe { bindings::init_special_inode(inode, bindings::S_IFIFO as _, 0) }; + unsafe { bindings::init_special_inode(inode, bindings::S_IFIFO as u16, 0) }; bindings::S_IFIFO } Type::Sock => { // SAFETY: `inode` is valid for write as it's a new inode. - unsafe { bindings::init_special_inode(inode, bindings::S_IFSOCK as _, 0) }; + unsafe { bindings::init_special_inode(inode, bindings::S_IFSOCK as u16, 0) }; bindings::S_IFSOCK } Type::Chr(major, minor) => { @@ -572,7 +564,7 @@ impl New { unsafe { bindings::init_special_inode( inode, - bindings::S_IFBLK as _, + bindings::S_IFBLK as u16, bindings::MKDEV(major, minor & bindings::MINORMASK), ) }; @@ -646,12 +638,12 @@ impl New { } Type::Fifo => { // SAFETY: `inode` is valid for write as it's a new inode. - unsafe { bindings::init_special_inode(inode, bindings::S_IFIFO as _, 0) }; + unsafe { bindings::init_special_inode(inode, bindings::S_IFIFO as u16, 0) }; bindings::S_IFIFO } Type::Sock => { // SAFETY: `inode` is valid for write as it's a new inode. - unsafe { bindings::init_special_inode(inode, bindings::S_IFSOCK as _, 0) }; + unsafe { bindings::init_special_inode(inode, bindings::S_IFSOCK as u16, 0) }; bindings::S_IFSOCK } Type::Chr(major, minor) => { @@ -659,7 +651,7 @@ impl New { unsafe { bindings::init_special_inode( inode, - bindings::S_IFCHR as _, + bindings::S_IFCHR as u16, bindings::MKDEV(major, minor & bindings::MINORMASK), ) }; @@ -670,7 +662,7 @@ impl New { unsafe { bindings::init_special_inode( inode, - bindings::S_IFBLK as _, + bindings::S_IFBLK as u16, bindings::MKDEV(major, minor & bindings::MINORMASK), ) }; @@ -795,7 +787,7 @@ impl Ready { pub fn ino(&self) -> Ino { // SAFETY: `i_ino` is immutable, and `self` is guaranteed to be valid by the existence of a // shared reference (&self) to it. - unsafe { (*self.0.as_ref()).i_ino } + unsafe { self.0.as_ref().i_ino } } } diff --git a/rust/kernel/iomap.rs b/rust/kernel/iomap.rs index 9be71c4c16597b..d078fd88cb3c95 100644 --- a/rust/kernel/iomap.rs +++ b/rust/kernel/iomap.rs @@ -244,14 +244,14 @@ impl Table { let ret = Self::iomap_begin_callback( inode_ptr, pos as Offset, - len as Offset, + Offset::from(len), flags::WRITE, map, ptr::null_mut(), ); if ret < 0 { - return Err(Error::from_errno(ret.try_into()?)); + return Err(Error::from_errno(ret)); } // SAFETY: all arguments provided were provided by the caller @@ -407,7 +407,7 @@ pub const fn aops() -> address_space::Ops } pub const fn map_table() -> &'static bindings::iomap_ops { - return &Table::::MAP_TABLE; + &Table::::MAP_TABLE } pub fn file_buffered_write( diff --git a/rust/kernel/sb.rs b/rust/kernel/sb.rs index 5faedb94964422..6abae48694a6cf 100644 --- a/rust/kernel/sb.rs +++ b/rust/kernel/sb.rs @@ -125,7 +125,7 @@ impl SuperBlock { // SAFETY: all block devices have a valid bd_mapping let mapping = unsafe { (*bdev.0.get()).bd_mapping }; - Ok(MappingPage::read(self, mapping, index)?) + MappingPage::read(self, mapping, index) } } @@ -238,7 +238,7 @@ impl SuperBlock { ARef::from_raw(inode.cast()) })) } else { - // SAFETY: The new inode is valid but not fully initialised yet, so it's ok to create a + // The new inode is valid but not fully initialised yet, so it's ok to create a // `inode::New`. Ok(INodeState::Uninitilized(inode::New(inode, PhantomData))) } diff --git a/rust/kernel/user.rs b/rust/kernel/user.rs index 38326d2fa7aed0..a9585881e578f9 100644 --- a/rust/kernel/user.rs +++ b/rust/kernel/user.rs @@ -25,7 +25,7 @@ impl Writer { bindings::copy_to_user( self.ptr.cast::(), data.as_ptr().cast::(), - data.len().try_into()?, + data.len(), ) }; if pending != 0 { From 676d94e239d69985b16bcc67f239d08ff7a26c9b Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 4 Feb 2026 12:01:00 -0500 Subject: [PATCH 124/131] [CLIPPY] add safety comments --- rust/kernel/block.rs | 6 +++--- rust/kernel/dentry.rs | 2 +- rust/kernel/folio.rs | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/rust/kernel/block.rs b/rust/kernel/block.rs index 9386a6ed5705f5..c4243ae1457fa7 100644 --- a/rust/kernel/block.rs +++ b/rust/kernel/block.rs @@ -54,11 +54,11 @@ impl Device { // TODO: Maybe this should be dealt with in the Address space struct instead of here // Also should be default type instead of generic pub fn inode(&self) -> &INode { - // SAFETY: `bd_inode` is never reassigned. + // SAFETY: `bd_mapping` is never reassigned. let mapping = unsafe { (*self.0.get()).bd_mapping }; - // TODO: add safety + // SAFETY: `mapping` is set if device is initilized. let inode_ptr = unsafe { (*mapping).host }; - // SAFET: `ptr` is valid as long as the block device remains valid as well. + // SAFETY: `ptr` is valid as long as the block device remains valid as well. unsafe { INode::from_raw(inode_ptr) } } } diff --git a/rust/kernel/dentry.rs b/rust/kernel/dentry.rs index e5df9a54190572..d12d17049ec495 100644 --- a/rust/kernel/dentry.rs +++ b/rust/kernel/dentry.rs @@ -40,7 +40,7 @@ impl DEntry { /// Returns the superblock of the dentry. pub fn super_block(&self) -> &SuperBlock { - // `d_sb` is immutable, so it's safe to read it. + // SAFETY: `d_sb` is immutable, so it's safe to read it. unsafe { SuperBlock::from_raw((*self.0.get()).d_sb) } } diff --git a/rust/kernel/folio.rs b/rust/kernel/folio.rs index a7356cc25c109b..eb590e8a7dc939 100644 --- a/rust/kernel/folio.rs +++ b/rust/kernel/folio.rs @@ -157,6 +157,7 @@ impl Deref for Mapped<'_, S> { type Target = [u8]; fn deref(&self) -> &Self::Target { + // SAFETY: Mapped is initilized so `data`, is valid for read. unsafe { core::slice::from_raw_parts(self.data, self.data_len) } } } From 0fec832c552d031e360a7676891e04796eff4b90 Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 4 Feb 2026 12:11:30 -0500 Subject: [PATCH 125/131] [CLIPPY] add safety comments --- rust/kernel/fs/file.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index 589e44cd6fca62..3903982f62ce7b 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -369,6 +369,7 @@ impl LocalFile { pub fn parent_ino(&self) -> usize { let dentry = self.dentry().0.get(); + // SAFETY: dentry is guarenteed to be valid, thus okay to get its parent_ino unsafe { bindings::d_parent_ino(dentry) } } } @@ -541,6 +542,7 @@ pub fn generic_seek( offset: Offset, whence: Whence, ) -> Result { + // SAFETY: generic_file_llseek returns an offset (err if n < 0) which is dealt with below let n = unsafe { bindings::generic_file_llseek(file.inner.get(), offset, whence as i32) }; if n < 0 { Err(Error::from_errno(n.try_into()?)) @@ -605,8 +607,8 @@ pub struct Ops { impl Ops { /// Returns file operations for page-cache-based ro files. pub fn generic_ro_file() -> Self { - // SAFETY: This is a constant in C, it never changes. Self { + // SAFETY: This is a constant in C, it never changes. inner: unsafe { &bindings::generic_ro_fops }, _p: PhantomData, } From a33189174a19adb76b0e63aa46a86e21f095011c Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 4 Feb 2026 12:34:00 -0500 Subject: [PATCH 126/131] [CLIPPY] add safety comments --- rust/kernel/fs.rs | 7 +++++++ rust/kernel/fs/file.rs | 2 ++ rust/kernel/fs/kiocb.rs | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs index a9fd584ae55521..6a7abbafc11a5d 100644 --- a/rust/kernel/fs.rs +++ b/rust/kernel/fs.rs @@ -145,6 +145,8 @@ impl Registration { // SAFETY: `try_ffi_init` guarantees that `fs_ptr` is valid for write. unsafe { fs_ptr.write(bindings::file_system_type::default()) }; + // SAFETY: `try_ffi_init` guarantees that `fs_ptr` is valid for write, and it has + // just been initialised above, so it's also valid for read. let fs = unsafe { &mut *fs_ptr }; fs.owner = module.0; fs.name = T::NAME.as_char_ptr(); @@ -190,6 +192,7 @@ impl Registration { }, } + // SAFETY: sb_ptr must be valid (caller responsibility) let ptr = unsafe { (*sb_ptr).s_fs_info }; if !ptr.is_null() { // SAFETY: The only place where `s_fs_info` is assigned is `NewSuperBlock::init`, where @@ -232,9 +235,13 @@ impl Tables { unsafe extern "C" fn get_tree_callback(fc: *mut bindings::fs_context) -> ffi::c_int { match T::SUPER_TYPE { + // SAFETY: the function contract guarentees the `fc` is a valid fs_context and + // fill_super_callback is a valid function pointer with the correct signature sb::Type::BlockDev => unsafe { bindings::get_tree_bdev(fc, Some(Self::fill_super_callback)) }, + // SAFETY: the function contract guarentees the `fc` is a valid fs_context and + // fill_super_callback is a valid function pointer with the correct signature sb::Type::Independent => unsafe { bindings::get_tree_nodev(fc, Some(Self::fill_super_callback)) }, diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index 3903982f62ce7b..298a2db806ae1d 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -727,6 +727,8 @@ impl Ops { kiocb: *mut bindings::kiocb, iter: *mut bindings::iov_iter, ) -> isize { + // SAFETY: returns copied bytes, caller deals with error (negative numbers, hence + // isize), should be improved to be specifible instead of relying on generic unsafe { bindings::generic_file_read_iter(kiocb, iter) } } diff --git a/rust/kernel/fs/kiocb.rs b/rust/kernel/fs/kiocb.rs index 6ef514f05cdf0c..6bc4b7b7d8f025 100644 --- a/rust/kernel/fs/kiocb.rs +++ b/rust/kernel/fs/kiocb.rs @@ -82,7 +82,7 @@ impl<'a, T: ForeignOwnable> Kiocb<'a, T> { // SAFETY: VFS guarantees ki_filp is a valid file pointer let file_ptr = unsafe { (*self.as_raw()).ki_filp }; - // While the Kiocb exists, it will have a valid reference to the file pointer + // SAFETY: While the Kiocb exists, it will have a valid reference to the file pointer unsafe { File::::from_raw_file(file_ptr) } } } From 0103864df031c7e98db64f089c82422e9936b0b4 Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 4 Feb 2026 12:53:23 -0500 Subject: [PATCH 127/131] [CLIPPY] add safety comments --- rust/kernel/inode.rs | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index 0a813d20e54d36..6e57e5d1706af2 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -135,53 +135,63 @@ impl INode { } pub fn size(&self) -> i64 { + // SAFETY: inode is guaranteed to be in a valid sate due to type state unsafe { (*self.0.get()).i_size } } pub fn blocks(&self) -> u64 { - // SAFETY: this is ok + // SAFETY: inode is guaranteed to be in a valid sate due to type state unsafe { (*self.0.get()).i_blocks } } pub fn nlink(&self) -> u32 { - // SAFETY: this is ok + // SAFETY: inode is guaranteed to be in a valid sate due to type state unsafe { (*self.0.get()).__bindgen_anon_1.i_nlink } } pub fn ctime(&self) -> Result { + // SAFETY: inode is guaranteed to be in a valid sate due to type state let sec = unsafe { (*self.0.get()).i_ctime_sec }; + // SAFETY: inode is guaranteed to be in a valid sate due to type state let nsec = unsafe { (*self.0.get()).i_ctime_nsec }; Timespec::new(sec.try_into()?, nsec) } pub fn mtime(&self) -> Result { + // SAFETY: inode is guaranteed to be in a valid sate due to type state let sec = unsafe { (*self.0.get()).i_mtime_sec }; + // SAFETY: inode is guaranteed to be in a valid sate due to type state let nsec = unsafe { (*self.0.get()).i_mtime_nsec }; Timespec::new(sec.try_into()?, nsec) } pub fn atime(&self) -> Result { + // SAFETY: inode is guaranteed to be in a valid sate due to type state let sec = unsafe { (*self.0.get()).i_atime_sec }; + // SAFETY: inode is guaranteed to be in a valid sate due to type state let nsec = unsafe { (*self.0.get()).i_atime_nsec }; Timespec::new(sec.try_into()?, nsec) } pub fn uid(&self) -> u32 { + // SAFETY: inode is guaranteed to be in a valid sate due to type state let uid = unsafe { (*self.0.get()).i_uid }; uid.val } pub fn gid(&self) -> u32 { + // SAFETY: inode is guaranteed to be in a valid sate due to type state let gid = unsafe { (*self.0.get()).i_gid }; gid.val } pub fn mode(&self) -> u16 { + // SAFETY: inode is guaranteed to be in a valid sate due to type state unsafe { (*self.0.get()).i_mode } } @@ -239,7 +249,7 @@ impl INode { pub fn drop_nlink(&self) { let inode_ptr = self.0.get(); - // SAFETY: Inode ptr is guaranteed to be valid and instantiated do to the typestate + // SAFETY: Inode ptr is guaranteed to be valid and instantiated due to the typestate unsafe { bindings::drop_nlink(inode_ptr); } @@ -247,7 +257,7 @@ impl INode { pub fn inc_link_count(&self) { let inode_ptr = self.0.get(); - // SAFETY: Inode ptr is guaranteed to be valid and instantiated do to the typestate + // SAFETY: Inode ptr is guaranteed to be valid and instantiated due to the typestate unsafe { bindings::inode_inc_link_count(inode_ptr); } @@ -255,7 +265,7 @@ impl INode { pub fn dec_link_count(&self) { let inode_ptr = self.0.get(); - // SAFETY: Inode ptr is guaranteed to be valid and instantiated do to the typestate + // SAFETY: Inode ptr is guaranteed to be valid and instantiated due to the typestate unsafe { bindings::inode_dec_link_count(inode_ptr); } @@ -299,6 +309,7 @@ impl INode { &self, index: PageOffset, ) -> Result>>> { + // SAFETY: Inode is valid due to typestate and err is handled let folio = from_err_ptr(unsafe { bindings::read_mapping_folio((*self.0.get()).i_mapping, index, ptr::null_mut()) })?; @@ -323,6 +334,7 @@ impl INode { pub fn mark_dirty(&self) { let inode = self.0.get(); + // SAFETY: Inode is in the correct state unsafe { bindings::mark_inode_dirty(inode) }; } @@ -373,6 +385,7 @@ impl INode { // embedded in a `Registration`, which is guaranteed to be valid because it has a // superblock associated to it. let reg = unsafe { &*container_of!(super_type, Registration, fs) }; + // SAFETY: WithData has been allocated by VFS (allocate_inode_callback) let ptr = unsafe { container_of!(inode, WithData, inode) }; if !is_bad { @@ -399,7 +412,7 @@ impl INode { // to free the inode. unsafe { bindings::free_inode_nonrcu(inode) }; } else { - // The callback contract guarantees that the inode was previously allocated via the + // SAFETY: The callback contract guarantees that the inode was previously allocated via the // `alloc_inode_callback` callback, so it is safe to free it back to the cache. unsafe { bindings::kmem_cache_free( @@ -427,6 +440,7 @@ unsafe impl AlwaysRefCounted for INode { /// Indicates that the an inode's rw semapahore is locked in read (shared) mode. pub struct ReadSem; +// SAFETY: `raw_lock` calls `inode_lock_shared` which locks the inode in shared mode. unsafe impl Lockable for INode { fn raw_lock(&self) { // SAFETY: Since there's a reference to the inode, it must be valid. @@ -553,7 +567,7 @@ impl New { unsafe { bindings::init_special_inode( inode, - bindings::S_IFCHR as _, + bindings::S_IFCHR as u16, bindings::MKDEV(major, minor & bindings::MINORMASK), ) }; @@ -700,6 +714,8 @@ impl New { } pub fn set_iops(&mut self, iops: Ops) -> &mut Self { + // SAFETY: its okay to mutate the Inode since its still locked which is enforced by the + // typestate let inode = unsafe { self.0.as_mut() }; inode.i_op = iops.0; self @@ -734,9 +750,13 @@ impl New { parent: &Locked<&INode, kernel::inode::ReadSem>, mode: u16, ) -> (kuid_t, kgid_t) { + // SAFETY: its okay to mutate the parent since it is locked, and inode is in the correct + // typestate let inode = unsafe { self.0.as_mut() }; - let parent = unsafe { parent.as_raw() }; + let parent = parent.as_raw(); + // SAFETY: inode hasn't been idmapped so passing in nop_mnt_idmap is expected, + // inode in valid typestate, and parent locked unsafe { bindings::inode_init_owner(&raw mut bindings::nop_mnt_idmap, inode, parent, mode); } @@ -767,8 +787,10 @@ impl Ready { pub fn mark_dirty(&mut self) { // SAFETY: This is safe since it is guaranteed by the typestate // that the inode has been inserted into the hash - let inode = unsafe { self.0.as_mut() }; - unsafe { bindings::mark_inode_dirty(inode) }; + unsafe { + let inode = { self.0.as_mut() }; + bindings::mark_inode_dirty(inode); + } } pub fn instantiate_dentry(self, dentry: &dentry::Unhashed<'_, T>) { From 67e8ff972724d4124f87ea6734c145ccdbd4de2b Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 4 Feb 2026 13:06:57 -0500 Subject: [PATCH 128/131] [CLIPPY] add safety comments --- rust/kernel/inode.rs | 2 -- rust/kernel/sb.rs | 11 +++++++---- rust/kernel/user.rs | 2 ++ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index 6e57e5d1706af2..f4c193d5aaa1bd 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -802,8 +802,6 @@ impl Ready { unsafe { bindings::d_instantiate_new(dentry_ptr, inode_ptr); } - - core::mem::forget(self); } /// Returns the number of the inode. pub fn ino(&self) -> Ino { diff --git a/rust/kernel/sb.rs b/rust/kernel/sb.rs index 6abae48694a6cf..a0849bb22fe30b 100644 --- a/rust/kernel/sb.rs +++ b/rust/kernel/sb.rs @@ -125,7 +125,8 @@ impl SuperBlock { // SAFETY: all block devices have a valid bd_mapping let mapping = unsafe { (*bdev.0.get()).bd_mapping }; - MappingPage::read(self, mapping, index) + // SAFETY: mapping is initilized above + unsafe { MappingPage::read(self, mapping, index) } } } @@ -147,7 +148,7 @@ impl<'a> MappingPage<'a> { } /// `` determines the lifetime of this page reference - pub fn read( + pub unsafe fn read( _ctx: &'a C, mapping: *mut bindings::address_space, index: u64, @@ -202,8 +203,10 @@ impl SuperBlock { // SAFETY: This method is only available if the typestate implements `DataInited`, whose // safety requirements include `s_fs_info` being properly initialised. - let ptr = unsafe { (*self.0.get()).s_fs_info }; - unsafe { T::Data::borrow(ptr) } + unsafe { + let ptr = (*self.0.get()).s_fs_info; + T::Data::borrow(ptr) + } } /// Tries to get an existing inode or create a new one if it doesn't exist yet. diff --git a/rust/kernel/user.rs b/rust/kernel/user.rs index a9585881e578f9..4e442f738d4275 100644 --- a/rust/kernel/user.rs +++ b/rust/kernel/user.rs @@ -21,6 +21,8 @@ impl Writer { return Err(EFAULT); } + // SAFETY: `len <= self.len` is checked above, ensuring `self.ptr` points to + // at least `len` bytes of valid userspace memory, and `data` is a valid slice. let pending = unsafe { bindings::copy_to_user( self.ptr.cast::(), From c6b305aad47e5a8fe51c88a27b5ab830d2954cc6 Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 4 Feb 2026 13:32:27 -0500 Subject: [PATCH 129/131] [CLIPPY] add function description --- rust/kernel/fs/file.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index 298a2db806ae1d..782eb65adb07e5 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -666,6 +666,11 @@ impl Ops { uring_cmd_iopoll: None, }; + /// Seek into a file, file system dependant + /// + /// # Safety + /// + /// `file_ptr` must be a reference to a valid `struct file` unsafe extern "C" fn seek_callback( file_ptr: *mut bindings::file, offset: bindings::loff_t, @@ -680,6 +685,12 @@ impl Ops { }) } + /// Read a file, file system dependant + /// + /// # Safety + /// + /// `file_ptr` must be a reference to a valid `struct file` + /// `ptr` must point to allocated memory which is at least of `len` bytes unsafe extern "C" fn read_callback( file_ptr: *mut bindings::file, ptr: *mut core::ffi::c_char, @@ -804,6 +815,12 @@ impl Ops { uring_cmd_iopoll: None, }; + /// Read a directory, file system dependant + /// + /// # Safety + /// + /// `file_ptr` must be a reference to a valid `struct file` + /// `ctx_ptr` must be a reference to a valid `struct dir_context` unsafe extern "C" fn read_dir_callback( file_ptr: *mut bindings::file, ctx_ptr: *mut bindings::dir_context, From 706ab854472a2439c0ce453f8682636390056017 Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 4 Feb 2026 13:36:48 -0500 Subject: [PATCH 130/131] [CLIPPY] add function safety comments --- rust/kernel/fs.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs index 6a7abbafc11a5d..b0739f0d895486 100644 --- a/rust/kernel/fs.rs +++ b/rust/kernel/fs.rs @@ -163,6 +163,9 @@ impl Registration { }) } + /// # Safety + /// + /// `fc_ptr` must be a reference to a valid `struct fs_context` unsafe extern "C" fn init_fs_context_callback( fc_ptr: *mut bindings::fs_context, ) -> ffi::c_int { @@ -174,6 +177,9 @@ impl Registration { }) } + /// # Safety + /// + /// `sb_ptr` must be a reference to a valid `struct super_block` unsafe extern "C" fn kill_sb_callback( sb_ptr: *mut bindings::super_block, ) { @@ -233,6 +239,9 @@ impl Tables { dup: None, }; + /// # Safety + /// + /// `fc` must be a reference to a valid `struct fc_context` unsafe extern "C" fn get_tree_callback(fc: *mut bindings::fs_context) -> ffi::c_int { match T::SUPER_TYPE { // SAFETY: the function contract guarentees the `fc` is a valid fs_context and @@ -248,6 +257,9 @@ impl Tables { } } + /// # Safety + /// + /// `sb_ptr` must be a reference to a valid `struct super_block` unsafe extern "C" fn fill_super_callback( sb_ptr: *mut bindings::super_block, _fc: *mut bindings::fs_context, From d10a716a1f66c13effc444c0769b60d9d7b0a399 Mon Sep 17 00:00:00 2001 From: lsig Date: Wed, 4 Feb 2026 16:03:23 -0500 Subject: [PATCH 131/131] [CLIPPY] add safety comments to functions --- rust/kernel/inode.rs | 22 ++++++++++++---------- rust/kernel/sb.rs | 13 +++++++------ 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/rust/kernel/inode.rs b/rust/kernel/inode.rs index f4c193d5aaa1bd..120faa8fd7d5a5 100644 --- a/rust/kernel/inode.rs +++ b/rust/kernel/inode.rs @@ -338,7 +338,7 @@ impl INode { unsafe { bindings::mark_inode_dirty(inode) }; } - unsafe extern "C" fn inode_init_once_callback(outer_inode: *mut core::ffi::c_void) { + extern "C" fn inode_init_once_callback(outer_inode: *mut core::ffi::c_void) { let ptr = outer_inode.cast::>(); // SAFETY: This is only used in `new`, so we know that we have a valid `inode::WithData` @@ -346,7 +346,7 @@ impl INode { unsafe { bindings::inode_init_once(ptr::addr_of_mut!((*ptr).inode)) }; } - pub(crate) unsafe extern "C" fn alloc_inode_callback( + pub(crate) extern "C" fn alloc_inode_callback( sb: *mut bindings::super_block, ) -> *mut bindings::inode { // SAFETY: The callback contract guarantees that `sb` is valid for read. @@ -372,7 +372,7 @@ impl INode { unsafe { ptr::addr_of_mut!((*ptr).inode) } } - pub(crate) unsafe extern "C" fn destroy_inode_callback(inode: *mut bindings::inode) { + pub(crate) extern "C" fn destroy_inode_callback(inode: *mut bindings::inode) { // SAFETY: By the C contract, `inode` is a valid pointer. let is_bad = unsafe { bindings::is_bad_inode(inode) }; @@ -431,6 +431,9 @@ unsafe impl AlwaysRefCounted for INode { unsafe { bindings::ihold(self.0.get()) }; } + /// # Safety + /// + /// Caller must guarantee the reference count of 'obj' is greater than 0 unsafe fn dec_ref(obj: ptr::NonNull) { // SAFETY: The safety requirements guarantee that the refcount is nonzero. unsafe { bindings::iput(obj.as_ref().0.get()) } @@ -980,9 +983,8 @@ impl Ops { } } - // TODO: add mnt_idmap support - unsafe extern "C" fn create_callback( - _mnt_idmap_ptr: *mut bindings::mnt_idmap, + extern "C" fn create_callback( + _mnt_idmap_ptr: *mut bindings::mnt_idmap, // TODO: add mnt_idmap support parent_ptr: *mut bindings::inode, dentry_ptr: *mut bindings::dentry, mode: u16, @@ -992,7 +994,7 @@ impl Ops { // SAFETY: The C API guarantees that `parent_ptr` is a valid inode. let parent = unsafe { INode::from_raw(parent_ptr) }; - // SAFETY: The C API guarantees that `parent_ptr` is a valid inode. + // SAFETY: The C API guarantees that `denty_ptr` is a valid dentry. let dentry = unsafe { DEntry::from_raw(dentry_ptr) }; // SAFETY: The C API guarantees that the inode's rw semaphore is locked at least in @@ -1005,7 +1007,7 @@ impl Ops { }) } - unsafe extern "C" fn unlink_callback( + extern "C" fn unlink_callback( inode_ptr: *mut bindings::inode, dentry_ptr: *mut bindings::dentry, ) -> i32 { @@ -1027,7 +1029,7 @@ impl Ops { }) } - unsafe extern "C" fn mkdir_callback( + extern "C" fn mkdir_callback( _mnt_idmap_ptr: *mut bindings::mnt_idmap, parent_ptr: *mut bindings::inode, dentry_ptr: *mut bindings::dentry, @@ -1051,7 +1053,7 @@ impl Ops { } } - unsafe extern "C" fn rmdir_callback( + extern "C" fn rmdir_callback( inode_ptr: *mut bindings::inode, dentry_ptr: *mut bindings::dentry, ) -> i32 { diff --git a/rust/kernel/sb.rs b/rust/kernel/sb.rs index a0849bb22fe30b..f64b971f6bd08a 100644 --- a/rust/kernel/sb.rs +++ b/rust/kernel/sb.rs @@ -148,6 +148,10 @@ impl<'a> MappingPage<'a> { } /// `` determines the lifetime of this page reference + /// + /// # Safety + /// + /// `mapping` must point to a valid reference of `struct address_space` pub unsafe fn read( _ctx: &'a C, mapping: *mut bindings::address_space, @@ -315,14 +319,14 @@ impl Ops { shutdown: None, }; - unsafe extern "C" fn evict_inode_callback(inode_ptr: *mut bindings::inode) { + extern "C" fn evict_inode_callback(inode_ptr: *mut bindings::inode) { // SAFETY: The C API guarantees that `inode_ptr` is a valid inode. let inode = unsafe { INode::from_raw(inode_ptr) }; T::evict_inode(inode); // TODO: Should this return something? } - unsafe extern "C" fn write_inode_callback( + extern "C" fn write_inode_callback( inode_ptr: *mut bindings::inode, _wbc: *mut bindings::writeback_control, ) -> i32 { @@ -337,10 +341,7 @@ impl Ops { }) } - unsafe extern "C" fn sync_fs_callback( - sb_ptr: *mut bindings::super_block, - _wait: i32, - ) -> i32 { + extern "C" fn sync_fs_callback(sb_ptr: *mut bindings::super_block, _wait: i32) -> i32 { // TODO: add support for wait from_result(|| { // SAFETY: The C API guarantees that `sb_ptr` is a valid inode.