lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20240516190345.957477-23-amiculas@cisco.com>
Date: Thu, 16 May 2024 22:03:45 +0300
From: Ariel Miculas <amiculas@...co.com>
To: rust-for-linux@...r.kernel.org
Cc: linux-kernel@...r.kernel.org, linux-fsdevel@...r.kernel.org,
        tycho@...ho.pizza, brauner@...nel.org, viro@...iv.linux.org.uk,
        ojeda@...nel.org, alex.gaynor@...il.com, wedsonaf@...il.com,
        shallyn@...co.com, Ariel Miculas <amiculas@...co.com>
Subject: [RFC PATCH v3 22/22] fs: puzzlefs: implement statfs for puzzlefs

In order to use a filesystem as a lower filesystem in an overlay, it
must implement statfs.

Signed-off-by: Ariel Miculas <amiculas@...co.com>
---
 fs/puzzlefs/puzzle/inode.rs | 26 ++++++++++++++++++++++++--
 fs/puzzlefs/puzzlefs.rs     | 21 +++++++++++++++++++--
 2 files changed, 43 insertions(+), 4 deletions(-)

diff --git a/fs/puzzlefs/puzzle/inode.rs b/fs/puzzlefs/puzzle/inode.rs
index 318edbdc5163..a34f1064b632 100644
--- a/fs/puzzlefs/puzzle/inode.rs
+++ b/fs/puzzlefs/puzzle/inode.rs
@@ -14,6 +14,8 @@
 pub(crate) struct PuzzleFS {
     pub(crate) oci: Image,
     layers: Vec<format::MetadataBlob>,
+    pub(crate) total_inodes: u64,
+    pub(crate) total_block_size: u64,
 }
 
 impl PuzzleFS {
@@ -22,13 +24,33 @@ pub(crate) fn open(oci_root_dir: &CStr, rootfs_path: &CStr) -> Result<PuzzleFS>
         let oci = Image::open(vfs_mount)?;
         let rootfs = oci.open_rootfs_blob(rootfs_path)?;
 
+        let mut total_block_size = 0;
+        let mut total_inodes: u64 = 0;
         let mut layers = Vec::new();
         for md in rootfs.metadatas.iter() {
             let digest = Digest::try_from(md)?;
-            layers.push(oci.open_metadata_blob(&digest)?, GFP_KERNEL)?;
+            let layer = oci.open_metadata_blob(&digest)?;
+
+            // This may take up too much time, but we need to implement statfs if we want to use
+            // puzzlefs as a lower filesystem in overlayfs
+            let inodes = layer.get_inode_vector()?;
+            total_inodes += u64::from(inodes.len());
+            for inode_number in 0..inodes.len() {
+                let inode = Inode::from_capnp(inodes.get(inode_number))?;
+                if let InodeMode::File { chunks } = inode.mode {
+                    total_block_size += chunks.iter().map(|chunk| chunk.len).sum::<u64>();
+                }
+            }
+
+            layers.push(layer, GFP_KERNEL)?;
         }
 
-        Ok(PuzzleFS { oci, layers })
+        Ok(PuzzleFS {
+            oci,
+            layers,
+            total_inodes,
+            total_block_size,
+        })
     }
 
     pub(crate) fn find_inode(&self, ino: u64) -> Result<Inode> {
diff --git a/fs/puzzlefs/puzzlefs.rs b/fs/puzzlefs/puzzlefs.rs
index 932f31917992..633f60983849 100644
--- a/fs/puzzlefs/puzzlefs.rs
+++ b/fs/puzzlefs/puzzlefs.rs
@@ -4,7 +4,7 @@
 
 use kernel::fs::{
     address_space, dentry, dentry::DEntry, file, file::DirEntryType, file::File, inode,
-    inode::INode, sb, Offset,
+    inode::INode, sb, Offset, Stat,
 };
 use kernel::prelude::*;
 use kernel::types::{ARef, Either, Locked};
@@ -23,6 +23,10 @@
     license: "GPL",
 }
 
+const PUZZLEFS_BSIZE: u64 = 1 << PUZZLEFS_BSIZE_BITS;
+const PUZZLEFS_BSIZE_BITS: u8 = 12;
+const PUZZLEFS_MAGIC: usize = 0x7a7a7570;
+
 fn mode_to_fs_type(inode: &Inode) -> Result<DirEntryType> {
     Ok(match inode.mode {
         InodeMode::File { .. } => DirEntryType::Reg,
@@ -156,7 +160,7 @@ fn fill_super(
         );
 
         let puzzlefs = puzzlefs?;
-        sb.set_magic(0x7a7a7570);
+        sb.set_magic(PUZZLEFS_MAGIC);
         Ok(Box::new(puzzlefs, GFP_KERNEL)?)
     }
 
@@ -194,6 +198,19 @@ fn read_xattr(
         }
         Err(ENODATA)
     }
+
+    fn statfs(dentry: &DEntry<Self>) -> Result<Stat> {
+        let puzzlefs = dentry.super_block().data();
+
+        Ok(Stat {
+            magic: PUZZLEFS_MAGIC,
+            namelen: isize::MAX,
+            bsize: PUZZLEFS_BSIZE as _,
+            // Round total_block_size up
+            blocks: (puzzlefs.total_block_size + PUZZLEFS_BSIZE - 1) / PUZZLEFS_BSIZE,
+            files: puzzlefs.total_inodes,
+        })
+    }
 }
 
 #[vtable]
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ