From patchwork Mon Sep 16 13:55:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yiyang Wu X-Patchwork-Id: 13805527 Received: from mail.tlmp.cc (unknown [148.135.17.20]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 88C57156F36; Mon, 16 Sep 2024 14:04:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.135.17.20 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726495497; cv=none; b=DCdB+oCE+TlW1D8sUYNSzP1qyB7QFZSMvs3vERQm6kIuJ8J69VCYauc0fiBInFYOmMu/yKG5dn0HEyVGfzSCeIsH2UeyjTRDVZJ+n488GQbuRxIwghJ/mStlJJFtzNG/5DLAfH16OLyz24Jo2bjX83+ZWq2RT5HA21SszIZt1Ps= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726495497; c=relaxed/simple; bh=82Pe3spVi8IHf0iaRSv2lTfetUa49rokuqEYMW7OxSA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mv3ojCjheY0l4m7WnHuPabLSx2CITaU7dVjQYcAPBzPK1MsvMkA6aqB/glP8qlFKp+DyicRlKJRM0lOadggCQAjpGfH7A6Fo0BCxRQdyUbMClOZTb16p9alOA7MCZtjXiAzA9HxZbOhXEeNO8ZkE5CLLrh9NAIna+rlkxeNhgD4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc; spf=pass smtp.mailfrom=tlmp.cc; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b=QPrZ5t4h; arc=none smtp.client-ip=148.135.17.20 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b="QPrZ5t4h" Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id AFBD969960; Mon, 16 Sep 2024 09:55:58 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tlmp.cc; s=dkim; t=1726494959; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=wrfeI6c5Fy2/wr4QW/RT84D3Z/gYFwXLPq/0MCJKzS4=; b=QPrZ5t4her/8AqCU4Iaw76WzB/tVPUXjSJhli+A3tTxISQP/t20LUrFmoq2j2c7foKM7W1 yeMmsFJg84bfucAURCoKi5pL/ENBe6x2RWV8+Sj/IKKhZsAP6xHPMsxp7swp2XZ1njlF7z fsg+jQJjB0DCkPGguMjNbbURnPoFcB+0Ig0ZOX2H1y4vzAyMwwIOewohYrOhWU7bf5h5fq JVKLji3Jsz6hk0fJFjSDzpv7vCczn8KCoKk93/TZ03jb2TfK5N+eYwQoXN0t2BvBNojFhE liZpXCNMlx7kNFvP6nzDKXa8Mfbq/p55GtVXvRloNzfWZEp4KGYBoQZTr+ZkpQ== From: Yiyang Wu To: linux-erofs@lists.ozlabs.org Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 01/24] erofs: lift up erofs_fill_inode to global Date: Mon, 16 Sep 2024 21:55:18 +0800 Message-ID: <20240916135541.98096-2-toolmanp@tlmp.cc> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240916135541.98096-1-toolmanp@tlmp.cc> References: <20240916135541.98096-1-toolmanp@tlmp.cc> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Last-TLS-Session-Version: TLSv1.3 Lift up erofs_fill_inode as a global symbol so that rust_helpers can use it for better compatibility. Signed-off-by: Yiyang Wu --- fs/erofs/inode.c | 2 +- fs/erofs/internal.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c index db29190656eb..d2fd51fcebd2 100644 --- a/fs/erofs/inode.c +++ b/fs/erofs/inode.c @@ -196,7 +196,7 @@ static int erofs_read_inode(struct inode *inode) return err; } -static int erofs_fill_inode(struct inode *inode) +int erofs_fill_inode(struct inode *inode) { struct erofs_inode *vi = EROFS_I(inode); int err; diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 4efd578d7c62..8674a4cb9d39 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -416,6 +416,7 @@ int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map); void erofs_onlinefolio_init(struct folio *folio); void erofs_onlinefolio_split(struct folio *folio); void erofs_onlinefolio_end(struct folio *folio, int err); +int erofs_fill_inode(struct inode *inode); struct inode *erofs_iget(struct super_block *sb, erofs_nid_t nid); int erofs_getattr(struct mnt_idmap *idmap, const struct path *path, struct kstat *stat, u32 request_mask, From patchwork Mon Sep 16 13:55:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yiyang Wu X-Patchwork-Id: 13805449 Received: from mail.tlmp.cc (unknown [148.135.17.20]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0408F155359; Mon, 16 Sep 2024 13:56:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.135.17.20 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726494971; cv=none; b=mOKXseVKUMVpX7xyatswRcEDIkbU7OysoXkWliywV44J1zyRKqabb5aWr0K1x2G6AgkLZGZLdeGAQlWrE7fDubaRq/PKIudzHmmvylJnCIh1MBmeoBOTZw+b+mbOTf653SQZXH3Mk/z8KPXBQR+6hoKjAZx+6rFVLI4FXVdr5EU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726494971; c=relaxed/simple; bh=d/XOj0hoNuU9nqfS2fwNSQ1cJ90NqcO0hLBokdH7oBY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EPYY60WlyKC96g+3qqjTXrDFCGaW9xXhw0+Elp990NfHWKiXtTXiP2jNfqVand6IxLUcSr24Sq4EPKqejM+K8hit+kA0PvzwjX0RDVVlAd8OVtRGvmHFJ1CIADIS3JyD0QS1ygHPMuwwLiG6FPGXJucaIjnnEeHOcOLwi93RYGA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc; spf=pass smtp.mailfrom=tlmp.cc; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b=WoxzAX5P; arc=none smtp.client-ip=148.135.17.20 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b="WoxzAX5P" Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id B6B4E6997B; Mon, 16 Sep 2024 09:56:03 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tlmp.cc; s=dkim; t=1726494964; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=eiSTaIp2oxZp3XntcBK5EeEI9ViTxMs6XcQ702Or/vY=; b=WoxzAX5PeehcV41pLyQhBKH4D4cyn5EkS57ZSbYTxXHdCEC2oz2WGp604DMrT7Bh1+NKIM aICmeX5CaU2WBrBRze+VXuOByOYJtUeV/7MlgwpXWKMEzfTX1v3pVqiCD+YkgAt1vjNV26 RoVMEa/n3Tg+33o3VTiaMw8HWH/+8fjUrK9CODklVnmhZYNYRMl8B1g4pqJCjvFVn5N0Cy nxhbvnXxqPi4t6D+BXooZ0YQtJSJDeu49XSPo0sFm9iMYNRYq8FtTgMb6H2N2siO0ppmI1 /gLmefmcZnSjVMgHFC5V4uzzHZHmktTws/kHcqQK7/u+NfYo3teCSQNoJN3PMA== From: Yiyang Wu To: linux-erofs@lists.ozlabs.org Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 02/24] erofs: add superblock data structure in Rust Date: Mon, 16 Sep 2024 21:55:19 +0800 Message-ID: <20240916135541.98096-3-toolmanp@tlmp.cc> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240916135541.98096-1-toolmanp@tlmp.cc> References: <20240916135541.98096-1-toolmanp@tlmp.cc> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Last-TLS-Session-Version: TLSv1.3 This patch adds a compilable super_rs.rs and introduces superblock data structure in Rust. Note that this patch leaves C-side code untouched. Signed-off-by: Yiyang Wu --- fs/erofs/Kconfig | 10 ++ fs/erofs/Makefile | 1 + fs/erofs/rust/erofs_sys.rs | 22 +++++ fs/erofs/rust/erofs_sys/superblock.rs | 132 ++++++++++++++++++++++++++ fs/erofs/rust/mod.rs | 4 + fs/erofs/super_rs.rs | 9 ++ 6 files changed, 178 insertions(+) create mode 100644 fs/erofs/rust/erofs_sys.rs create mode 100644 fs/erofs/rust/erofs_sys/superblock.rs create mode 100644 fs/erofs/rust/mod.rs create mode 100644 fs/erofs/super_rs.rs diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig index 6ea60661fa55..e2883efbf497 100644 --- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig @@ -178,3 +178,13 @@ config EROFS_FS_PCPU_KTHREAD_HIPRI at higher priority. If unsure, say N. + +config EROFS_FS_RUST + bool "EROFS use RUST Replacement (EXPERIMENTAL)" + depends on EROFS_FS && RUST + help + This permits EROFS to use EXPERIMENTAL Rust implementation + for EROFS. This should be considered as an experimental + feature for now. + + If unsure, say N. diff --git a/fs/erofs/Makefile b/fs/erofs/Makefile index 4331d53c7109..fb46a2c7fb50 100644 --- a/fs/erofs/Makefile +++ b/fs/erofs/Makefile @@ -9,3 +9,4 @@ erofs-$(CONFIG_EROFS_FS_ZIP_DEFLATE) += decompressor_deflate.o erofs-$(CONFIG_EROFS_FS_ZIP_ZSTD) += decompressor_zstd.o erofs-$(CONFIG_EROFS_FS_BACKED_BY_FILE) += fileio.o erofs-$(CONFIG_EROFS_FS_ONDEMAND) += fscache.o +erofs-$(CONFIG_EROFS_FS_RUST) += super_rs.o diff --git a/fs/erofs/rust/erofs_sys.rs b/fs/erofs/rust/erofs_sys.rs new file mode 100644 index 000000000000..0f1400175fc2 --- /dev/null +++ b/fs/erofs/rust/erofs_sys.rs @@ -0,0 +1,22 @@ +#![allow(dead_code)] +// Copyright 2024 Yiyang Wu +// SPDX-License-Identifier: MIT or GPL-2.0-or-later + +//! A pure Rust implementation of the EROFS filesystem. +//! Technical Details are documented in the [EROFS Documentation](https://erofs.docs.kernel.org/en/latest/) + +// It's unavoidable to import alloc here. Since there are so many backends there and if we want to +// to use trait object to export Filesystem pointer. The alloc crate here is necessary. + +#[cfg(not(CONFIG_EROFS_FS = "y"))] +extern crate alloc; + +/// Erofs requires block index to a 32 bit unsigned integer. +pub(crate) type Blk = u32; +/// Erofs requires normal offset to be a 64bit unsigned integer. +pub(crate) type Off = u64; +/// Erofs requires inode nid to be a 64bit unsigned integer. +pub(crate) type Nid = u64; +/// Erofs Super Offset to read the ondisk superblock +pub(crate) const EROFS_SUPER_OFFSET: Off = 1024; +pub(crate) mod superblock; diff --git a/fs/erofs/rust/erofs_sys/superblock.rs b/fs/erofs/rust/erofs_sys/superblock.rs new file mode 100644 index 000000000000..213be6dbc553 --- /dev/null +++ b/fs/erofs/rust/erofs_sys/superblock.rs @@ -0,0 +1,132 @@ +// Copyright 2024 Yiyang Wu +// SPDX-License-Identifier: MIT or GPL-2.0-or-later + +use super::*; +use core::mem::size_of; + +/// The ondisk superblock structure. +#[derive(Debug, Clone, Copy, Default)] +#[repr(C)] +pub(crate) struct SuperBlock { + pub(crate) magic: u32, + pub(crate) checksum: i32, + pub(crate) feature_compat: i32, + pub(crate) blkszbits: u8, + pub(crate) sb_extslots: u8, + pub(crate) root_nid: i16, + pub(crate) inos: i64, + pub(crate) build_time: i64, + pub(crate) build_time_nsec: i32, + pub(crate) blocks: i32, + pub(crate) meta_blkaddr: u32, + pub(crate) xattr_blkaddr: u32, + pub(crate) uuid: [u8; 16], + pub(crate) volume_name: [u8; 16], + pub(crate) feature_incompat: i32, + pub(crate) compression: i16, + pub(crate) extra_devices: i16, + pub(crate) devt_slotoff: i16, + pub(crate) dirblkbits: u8, + pub(crate) xattr_prefix_count: u8, + pub(crate) xattr_prefix_start: i32, + pub(crate) packed_nid: i64, + pub(crate) xattr_filter_reserved: u8, + pub(crate) reserved: [u8; 23], +} + +impl TryFrom<&[u8]> for SuperBlock { + type Error = core::array::TryFromSliceError; + fn try_from(value: &[u8]) -> Result { + value[0..128].try_into() + } +} + +impl From<[u8; 128]> for SuperBlock { + fn from(value: [u8; 128]) -> Self { + Self { + magic: u32::from_le_bytes([value[0], value[1], value[2], value[3]]), + checksum: i32::from_le_bytes([value[4], value[5], value[6], value[7]]), + feature_compat: i32::from_le_bytes([value[8], value[9], value[10], value[11]]), + blkszbits: value[12], + sb_extslots: value[13], + root_nid: i16::from_le_bytes([value[14], value[15]]), + inos: i64::from_le_bytes([ + value[16], value[17], value[18], value[19], value[20], value[21], value[22], + value[23], + ]), + build_time: i64::from_le_bytes([ + value[24], value[25], value[26], value[27], value[28], value[29], value[30], + value[31], + ]), + build_time_nsec: i32::from_le_bytes([value[32], value[33], value[34], value[35]]), + blocks: i32::from_le_bytes([value[36], value[37], value[38], value[39]]), + meta_blkaddr: u32::from_le_bytes([value[40], value[41], value[42], value[43]]), + xattr_blkaddr: u32::from_le_bytes([value[44], value[45], value[46], value[47]]), + uuid: value[48..64].try_into().unwrap(), + volume_name: value[64..80].try_into().unwrap(), + feature_incompat: i32::from_le_bytes([value[80], value[81], value[82], value[83]]), + compression: i16::from_le_bytes([value[84], value[85]]), + extra_devices: i16::from_le_bytes([value[86], value[87]]), + devt_slotoff: i16::from_le_bytes([value[88], value[89]]), + dirblkbits: value[90], + xattr_prefix_count: value[91], + xattr_prefix_start: i32::from_le_bytes([value[92], value[93], value[94], value[95]]), + packed_nid: i64::from_le_bytes([ + value[96], value[97], value[98], value[99], value[100], value[101], value[102], + value[103], + ]), + xattr_filter_reserved: value[104], + reserved: value[105..128].try_into().unwrap(), + } + } +} + +pub(crate) type SuperBlockBuf = [u8; size_of::()]; +pub(crate) const SUPERBLOCK_EMPTY_BUF: SuperBlockBuf = [0; size_of::()]; + +/// Used for external address calculation. +pub(crate) struct Accessor { + pub(crate) base: Off, + pub(crate) off: Off, + pub(crate) len: Off, + pub(crate) nr: Off, +} + +impl Accessor { + pub(crate) fn new(address: Off, bits: Off) -> Self { + let sz = 1 << bits; + let mask = sz - 1; + Accessor { + base: (address >> bits) << bits, + off: address & mask, + len: sz - (address & mask), + nr: address >> bits, + } + } +} + +impl SuperBlock { + pub(crate) fn blk_access(&self, address: Off) -> Accessor { + Accessor::new(address, self.blkszbits as Off) + } + + pub(crate) fn blknr(&self, pos: Off) -> Blk { + (pos >> self.blkszbits) as Blk + } + + pub(crate) fn blkpos(&self, blk: Blk) -> Off { + (blk as Off) << self.blkszbits + } + + pub(crate) fn blksz(&self) -> Off { + 1 << self.blkszbits + } + + pub(crate) fn blk_round_up(&self, addr: Off) -> Blk { + ((addr + self.blksz() - 1) >> self.blkszbits) as Blk + } + + pub(crate) fn iloc(&self, nid: Nid) -> Off { + self.blkpos(self.meta_blkaddr) + ((nid as Off) << (5 as Off)) + } +} diff --git a/fs/erofs/rust/mod.rs b/fs/erofs/rust/mod.rs new file mode 100644 index 000000000000..e6c0731f2533 --- /dev/null +++ b/fs/erofs/rust/mod.rs @@ -0,0 +1,4 @@ +// Copyright 2024 Yiyang Wu +// SPDX-License-Identifier: MIT or GPL-2.0-or-later + +pub(crate) mod erofs_sys; diff --git a/fs/erofs/super_rs.rs b/fs/erofs/super_rs.rs new file mode 100644 index 000000000000..4b8cbef507e3 --- /dev/null +++ b/fs/erofs/super_rs.rs @@ -0,0 +1,9 @@ +// Copyright 2024 Yiyang Wu +// SPDX-License-Identifier: MIT or GPL-2.0-or-later + +//! EROFS Rust Kernel Module Helpers Implementation +//! This is only for experimental purpose. Feedback is always welcome. + +#[allow(dead_code)] +#[allow(missing_docs)] +pub(crate) mod rust; From patchwork Mon Sep 16 13:55:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yiyang Wu X-Patchwork-Id: 13805447 Received: from mail.tlmp.cc (unknown [148.135.17.20]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 935E1155A59; Mon, 16 Sep 2024 13:56:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.135.17.20 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726494970; cv=none; b=RY7w8D92Wco6PJsq72zP3iT0u9zcZy3GNh31nX29MyWCvRZjg++FtvBe9Nz7fmSuMdj4k8rgF0PjBfBcuz3VNUC6+2waiwCbyrSE7Qr/W8BxEJ2RxyN6uM20G+bCR/m24/zto2pHKQ7rYM4VAR666y8+fAp6BYGgOpGymCpvRKo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726494970; c=relaxed/simple; bh=vQLgpg+Uh6AnmzozA6msIhCQdsV7m8apo306xrKuq7U=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hcoJ5A7960sbi8wmIYOD3p/o2l0+E5xsqXKNyqe1JoYx4EGviG7IIPp0ysCD4C2XwKxdvG8gHPobY0ck41QleTHQ+hrQtu5uo4y3RybK8338AwcSIM/t+eWWak0ZiXo5WEn135EZ3hz+KQxmHYBE+PmfLrDSXECueq0wdqCI5O8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc; spf=pass smtp.mailfrom=tlmp.cc; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b=gyk0nQmk; arc=none smtp.client-ip=148.135.17.20 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b="gyk0nQmk" Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 8EAF26997C; Mon, 16 Sep 2024 09:56:05 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tlmp.cc; s=dkim; t=1726494966; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=ZuP3bujGZDBP75xkwLAFw1ksH6b/fY1knDKclkC/wOs=; b=gyk0nQmkxsEqOOxgE8ynnJjvoHp7k6fjXxzCvSyGQOfo+h9L0F5KJATkjaAn0pWRdTQET5 Ue3ZEkO9CNHy3yU0EEktidTpqs37MehOPJvMo1OfE+r8OWe6W5R1FAYIvXTk5R8vhMjngK /kFb/8wgj2A7qaVWEbHumKFTmOLw8Tx8NoSubGjhKlKjao3eo63ffH2xIeH5/GERY/SBwX I6N6IBG8vCe67HLzkEbYvzW3UmEaM+97jK8Ojlckv7G71Hyh54Ug2Ny5UMibB1ln0qr6yg tfFRmmQzVy8oFe/9IV0xkW75hEIocoxCZQWudbMlxHk8N6O/NkaKhZcC7gKfqQ== From: Yiyang Wu To: linux-erofs@lists.ozlabs.org Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 03/24] erofs: add Errno in Rust Date: Mon, 16 Sep 2024 21:55:20 +0800 Message-ID: <20240916135541.98096-4-toolmanp@tlmp.cc> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240916135541.98096-1-toolmanp@tlmp.cc> References: <20240916135541.98096-1-toolmanp@tlmp.cc> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Last-TLS-Session-Version: TLSv1.3 Introduce Errno to Rust side code. Note that in current Rust For Linux, Errnos are implemented as core::ffi::c_uint unit structs. However, EUCLEAN, a.k.a EFSCORRUPTED is missing from error crate. Since the errno_base hasn't changed for over 13 years, This patch merely serves as a temporary workaround for the missing errno in the Rust For Linux. Signed-off-by: Yiyang Wu --- fs/erofs/rust/erofs_sys.rs | 6 + fs/erofs/rust/erofs_sys/errnos.rs | 191 ++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 fs/erofs/rust/erofs_sys/errnos.rs diff --git a/fs/erofs/rust/erofs_sys.rs b/fs/erofs/rust/erofs_sys.rs index 0f1400175fc2..2bd1381da5ab 100644 --- a/fs/erofs/rust/erofs_sys.rs +++ b/fs/erofs/rust/erofs_sys.rs @@ -19,4 +19,10 @@ pub(crate) type Nid = u64; /// Erofs Super Offset to read the ondisk superblock pub(crate) const EROFS_SUPER_OFFSET: Off = 1024; +/// PosixResult as a type alias to kernel::error::Result +/// to avoid naming conflicts. +pub(crate) type PosixResult = Result; + +pub(crate) mod errnos; pub(crate) mod superblock; +pub(crate) use errnos::Errno; diff --git a/fs/erofs/rust/erofs_sys/errnos.rs b/fs/erofs/rust/erofs_sys/errnos.rs new file mode 100644 index 000000000000..40e5cdbcb353 --- /dev/null +++ b/fs/erofs/rust/erofs_sys/errnos.rs @@ -0,0 +1,191 @@ +// Copyright 2024 Yiyang Wu +// SPDX-License-Identifier: MIT or GPL-2.0-or-later + +#[repr(i32)] +#[non_exhaustive] +#[allow(clippy::upper_case_acronyms)] +#[derive(Debug, Copy, Clone, PartialEq)] +pub(crate) enum Errno { + NONE = 0, + EPERM, + ENOENT, + ESRCH, + EINTR, + EIO, + ENXIO, + E2BIG, + ENOEXEC, + EBADF, + ECHILD, + EAGAIN, + ENOMEM, + EACCES, + EFAULT, + ENOTBLK, + EBUSY, + EEXIST, + EXDEV, + ENODEV, + ENOTDIR, + EISDIR, + EINVAL, + ENFILE, + EMFILE, + ENOTTY, + ETXTBSY, + EFBIG, + ENOSPC, + ESPIPE, + EROFS, + EMLINK, + EPIPE, + EDOM, + ERANGE, + EDEADLK, + ENAMETOOLONG, + ENOLCK, + ENOSYS, + ENOTEMPTY, + ELOOP, + ENOMSG = 42, + EIDRM, + ECHRNG, + EL2NSYNC, + EL3HLT, + EL3RST, + ELNRNG, + EUNATCH, + ENOCSI, + EL2HLT, + EBADE, + EBADR, + EXFULL, + ENOANO, + EBADRQC, + EBADSLT, + EBFONT = 59, + ENOSTR, + ENODATA, + ETIME, + ENOSR, + ENONET, + ENOPKG, + EREMOTE, + ENOLINK, + EADV, + ESRMNT, + ECOMM, + EPROTO, + EMULTIHOP, + EDOTDOT, + EBADMSG, + EOVERFLOW, + ENOTUNIQ, + EBADFD, + EREMCHG, + ELIBACC, + ELIBBAD, + ELIBSCN, + ELIBMAX, + ELIBEXEC, + EILSEQ, + ERESTART, + ESTRPIPE, + EUSERS, + ENOTSOCK, + EDESTADDRREQ, + EMSGSIZE, + EPROTOTYPE, + ENOPROTOOPT, + EPROTONOSUPPORT, + ESOCKTNOSUPPORT, + EOPNOTSUPP, + EPFNOSUPPORT, + EAFNOSUPPORT, + EADDRINUSE, + EADDRNOTAVAIL, + ENETDOWN, + ENETUNREACH, + ENETRESET, + ECONNABORTED, + ECONNRESET, + ENOBUFS, + EISCONN, + ENOTCONN, + ESHUTDOWN, + ETOOMANYREFS, + ETIMEDOUT, + ECONNREFUSED, + EHOSTDOWN, + EHOSTUNREACH, + EALREADY, + EINPROGRESS, + ESTALE, + EUCLEAN, + ENOTNAM, + ENAVAIL, + EISNAM, + EREMOTEIO, + EDQUOT, + ENOMEDIUM, + EMEDIUMTYPE, + ECANCELED, + ENOKEY, + EKEYEXPIRED, + EKEYREVOKED, + EKEYREJECTED, + EOWNERDEAD, + ENOTRECOVERABLE, + ERFKILL, + EHWPOISON, + EUNKNOWN, +} + +impl From for Errno { + fn from(value: i32) -> Self { + if (-value) <= 0 || (-value) > Errno::EUNKNOWN as i32 { + Errno::EUNKNOWN + } else { + // Safety: The value is guaranteed to be a valid errno and the memory + // layout is the same for both types. + unsafe { core::mem::transmute(value) } + } + } +} + +impl From for i32 { + fn from(value: Errno) -> Self { + -(value as i32) + } +} + +/// Replacement for ERR_PTR in Linux Kernel. +impl From for *const core::ffi::c_void { + fn from(value: Errno) -> Self { + (-(value as core::ffi::c_long)) as *const core::ffi::c_void + } +} + +impl From for *mut core::ffi::c_void { + fn from(value: Errno) -> Self { + (-(value as core::ffi::c_long)) as *mut core::ffi::c_void + } +} + +/// Replacement for PTR_ERR in Linux Kernel. +impl From<*const core::ffi::c_void> for Errno { + fn from(value: *const core::ffi::c_void) -> Self { + (-(value as i32)).into() + } +} + +impl From<*mut core::ffi::c_void> for Errno { + fn from(value: *mut core::ffi::c_void) -> Self { + (-(value as i32)).into() + } +} +/// Replacement for IS_ERR in Linux Kernel. +#[inline(always)] +pub(crate) fn is_value_err(value: *const core::ffi::c_void) -> bool { + (value as core::ffi::c_ulong) >= (-4095 as core::ffi::c_long) as core::ffi::c_ulong +} From patchwork Mon Sep 16 13:55:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yiyang Wu X-Patchwork-Id: 13805448 Received: from mail.tlmp.cc (unknown [148.135.17.20]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4B544132122; Mon, 16 Sep 2024 13:56:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.135.17.20 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726494970; cv=none; b=J+uzvy8uU4XJd5hvpTa96xljoFh1eDAWQPDRn648+aebIAPnPztwjfGcKRk5s9Uyw4JSTJtzzk0oRIvhNTgRowDQOkGStD8ANeZuIivceZtQu6E6TtJ5sjIBccPOjXVCi3G+cR0y5elDFN+1Y9VhwbzStpWz4YZgfwBGAvRUBlw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726494970; c=relaxed/simple; bh=T87qpgWUFMOH9vDZIIusulZhnKGgYdYoqiUWGJAD3JA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PnN4w+FQDfS8vVwFC/epx+ONJWyUyYmkx+NL+CgnOpBYKGf2X66HcEPOQrKoXH8IdkPCS24R0KO9ga1dFquFajHq/1D7mnCgpPxgs9qrPNUfVL/pWNWN+4g8jsXD08xsy2NENivamQTv1vzbyTXXOhk4/4N1o7dsOce/KBbQJZE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc; spf=pass smtp.mailfrom=tlmp.cc; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b=gZEWWmKy; arc=none smtp.client-ip=148.135.17.20 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b="gZEWWmKy" Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 496286997D; Mon, 16 Sep 2024 09:56:07 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tlmp.cc; s=dkim; t=1726494968; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=eYDsY4wqAO9NUWwayzJIYghS8a27BSxppsolaWA5lxs=; b=gZEWWmKyv5QhK9EAxaWSqUbJLLmLD9oYn+CDX1Z7R21OyTyIDmytGlCA7fvRoknPzCqW+u cR1ccN/L37ejFpGKu/vjzNjS89YEEYtQRKqVigjNM6UJeM5EC0b/xWOcT5Kxm2DRKSHmST /IpN+xZWU407r+5FXBqYC2REg8E+dgD6zfXcPEahSw7uU2Yce7slicSuygg9FCs/WbO5L5 yYWesHS5Eub1vIzjfn63G7/8+ydliWreaxHZA8e1Id284Au29KdeE4Nb6gY7sCFF4wnkvs HddeuqSWxrgJptfT2n4N1bUqMxc5omHT9dFZ1x7u7pGN2rDU26ZekgO4E67duQ== From: Yiyang Wu To: linux-erofs@lists.ozlabs.org Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 04/24] erofs: add xattrs data structure in Rust Date: Mon, 16 Sep 2024 21:55:21 +0800 Message-ID: <20240916135541.98096-5-toolmanp@tlmp.cc> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240916135541.98096-1-toolmanp@tlmp.cc> References: <20240916135541.98096-1-toolmanp@tlmp.cc> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Last-TLS-Session-Version: TLSv1.3 This patch introduces on-disk and runtime data structure of Extended Attributes implementation in erofs_sys crate. This will be later used to implement the op handler. Signed-off-by: Yiyang Wu --- fs/erofs/rust/erofs_sys.rs | 12 +++ fs/erofs/rust/erofs_sys/xattrs.rs | 124 ++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 fs/erofs/rust/erofs_sys/xattrs.rs diff --git a/fs/erofs/rust/erofs_sys.rs b/fs/erofs/rust/erofs_sys.rs index 2bd1381da5ab..6f3c12665ed6 100644 --- a/fs/erofs/rust/erofs_sys.rs +++ b/fs/erofs/rust/erofs_sys.rs @@ -25,4 +25,16 @@ pub(crate) mod errnos; pub(crate) mod superblock; +pub(crate) mod xattrs; pub(crate) use errnos::Errno; + +/// Helper macro to round up or down a number. +#[macro_export] +macro_rules! round { + (UP, $x: expr, $y: expr) => { + ($x + $y - 1) / $y * $y + }; + (DOWN, $x: expr, $y: expr) => { + ($x / $y) * $y + }; +} diff --git a/fs/erofs/rust/erofs_sys/xattrs.rs b/fs/erofs/rust/erofs_sys/xattrs.rs new file mode 100644 index 000000000000..d1a110ef10dd --- /dev/null +++ b/fs/erofs/rust/erofs_sys/xattrs.rs @@ -0,0 +1,124 @@ +// Copyright 2024 Yiyang Wu +// SPDX-License-Identifier: MIT or GPL-2.0-or-later + +use alloc::vec::Vec; + +/// The header of the xattr entry index. +/// This is used to describe the superblock's xattrs collection. +#[derive(Clone, Copy)] +#[repr(C)] +pub(crate) struct XAttrSharedEntrySummary { + pub(crate) name_filter: u32, + pub(crate) shared_count: u8, + pub(crate) reserved: [u8; 7], +} + +impl From<[u8; 12]> for XAttrSharedEntrySummary { + fn from(value: [u8; 12]) -> Self { + Self { + name_filter: u32::from_le_bytes([value[0], value[1], value[2], value[3]]), + shared_count: value[4], + reserved: value[5..12].try_into().unwrap(), + } + } +} + +pub(crate) const XATTR_ENTRY_SUMMARY_BUF: [u8; 12] = [0u8; 12]; + +/// Represented as a inmemory memory entry index header used by SuperBlockInfo. +pub(crate) struct XAttrSharedEntries { + pub(crate) name_filter: u32, + pub(crate) shared_indexes: Vec, +} + +/// Represents the name index for infixes or prefixes. +#[repr(C)] +#[derive(Clone, Copy)] +pub(crate) struct XattrNameIndex(u8); + +impl core::cmp::PartialEq for XattrNameIndex { + fn eq(&self, other: &u8) -> bool { + if self.0 & EROFS_XATTR_LONG_PREFIX != 0 { + self.0 & EROFS_XATTR_LONG_MASK == *other + } else { + self.0 == *other + } + } +} + +impl XattrNameIndex { + pub(crate) fn is_long(&self) -> bool { + self.0 & EROFS_XATTR_LONG_PREFIX != 0 + } +} + +impl From for XattrNameIndex { + fn from(value: u8) -> Self { + Self(value) + } +} + +#[allow(clippy::from_over_into)] +impl Into for XattrNameIndex { + fn into(self) -> usize { + if self.0 & EROFS_XATTR_LONG_PREFIX != 0 { + (self.0 & EROFS_XATTR_LONG_MASK) as usize + } else { + self.0 as usize + } + } +} + +/// This is on-disk representation of xattrs entry header. +/// This is used to describe one extended attribute. +#[repr(C)] +#[derive(Clone, Copy)] +pub(crate) struct XAttrEntryHeader { + pub(crate) suffix_len: u8, + pub(crate) name_index: XattrNameIndex, + pub(crate) value_len: u16, +} + +impl From<[u8; 4]> for XAttrEntryHeader { + fn from(value: [u8; 4]) -> Self { + Self { + suffix_len: value[0], + name_index: value[1].into(), + value_len: u16::from_le_bytes(value[2..4].try_into().unwrap()), + } + } +} + +/// Xattr Common Infix holds the prefix index in the first byte and all the common infix data in +/// the rest of the bytes. +pub(crate) struct XAttrInfix(pub(crate) Vec); + +impl XAttrInfix { + fn prefix_index(&self) -> u8 { + self.0[0] + } + fn name(&self) -> &[u8] { + &self.0[1..] + } +} + +pub(crate) const EROFS_XATTR_LONG_PREFIX: u8 = 0x80; +pub(crate) const EROFS_XATTR_LONG_MASK: u8 = EROFS_XATTR_LONG_PREFIX - 1; + +/// Supported xattr prefixes +pub(crate) const EROFS_XATTRS_PREFIXS: [&[u8]; 7] = [ + b"", + b"user.", + b"system.posix_acl_access", + b"system.posix_acl_default", + b"trusted.", + b"", + b"security.", +]; + +/// Represents the value of an xattr entry or the size of it if the buffer is present in the query. +#[derive(Debug)] +pub(crate) enum XAttrValue { + Buffer(usize), + Vec(Vec), +} From patchwork Mon Sep 16 13:55:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yiyang Wu X-Patchwork-Id: 13805450 Received: from mail.tlmp.cc (unknown [148.135.17.20]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ECCC315624D; Mon, 16 Sep 2024 13:56:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.135.17.20 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726494972; cv=none; b=Jm6syxl7TC/d78goVcO07NPcH3SwA495a2Q5s16M8EMM11jmRzcyKz3M7cyQatGH6sYpF93ftvT/jijMNbfaSbYXaDVFhsxGGENmu8kgSm8Yo0pW8r/3kUdHKJa5tc9Q6y+CK5jmUIYSAhUELOzzhm/+HoyIWuUUHTHzTITonz0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726494972; c=relaxed/simple; bh=+GE0m90lwhlb9OljwVtEQsDCa+zy3VtJ1xGQMp1f3Pc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DyLqkkiSu6hC7Yivhh5aEpGOeV9w7hhNKcj4iJWM6hxkCLHW9tog9j0sM+NeuD8xaA3ZQCqMFv89D3ALqAr++ThKyICic3dsUtUfnIDG6qQ1qJn2mblrLMidQeAajYJh6iiEH69CaBR82fhnZQ8nXK6wfWf0iLvKQjqFBUD26y4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc; spf=pass smtp.mailfrom=tlmp.cc; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b=UtsePRwI; arc=none smtp.client-ip=148.135.17.20 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b="UtsePRwI" Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 0826F6997E; Mon, 16 Sep 2024 09:56:08 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tlmp.cc; s=dkim; t=1726494970; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=3lB7vMUDAoeBGlHx0db3VH42iw8zhtpQjBkF7LrP3EU=; b=UtsePRwIatPkFI6g47PQN+urQglWghy7rKD4qYfaMY4FAF4z5OzDxPTTk6gpz+Jigq9pCe pl8i1ARy+rPgNfNJTl6jhgPo8f8HIomuGZTdUYJEx+7EA0MtW0/owPnvnrQoKGVzi1mCzr c8thO7gcbdGFqC4ksq3XnA30zw06TcIDYt0+kXfh7Hjjv1yyh6YMUHquiG9DwXNOiQdO7K LnvGPgrtOAyUi0Yu1bnFW6t84EBtf1WiW5ZAv51o1YBPy7AsKlm8kJQRkQX5AKeZdO0H8+ KuiOVntwIN0NHGAiYCm/rw7MRKXSByhEaVgeutTYkbNEcFerTEeCahwW5rqhRQ== From: Yiyang Wu To: linux-erofs@lists.ozlabs.org Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 05/24] erofs: add inode data structure in Rust Date: Mon, 16 Sep 2024 21:55:22 +0800 Message-ID: <20240916135541.98096-6-toolmanp@tlmp.cc> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240916135541.98096-1-toolmanp@tlmp.cc> References: <20240916135541.98096-1-toolmanp@tlmp.cc> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Last-TLS-Session-Version: TLSv1.3 This patch introduces the same on-disk erofs data structure in rust and also introduces multiple helpers for inode i_format and chunk_indexing and later can be used to implement map_blocks. Signed-off-by: Yiyang Wu --- fs/erofs/rust/erofs_sys.rs | 1 + fs/erofs/rust/erofs_sys/inode.rs | 291 +++++++++++++++++++++++++++++++ 2 files changed, 292 insertions(+) create mode 100644 fs/erofs/rust/erofs_sys/inode.rs diff --git a/fs/erofs/rust/erofs_sys.rs b/fs/erofs/rust/erofs_sys.rs index 6f3c12665ed6..34267ec7772d 100644 --- a/fs/erofs/rust/erofs_sys.rs +++ b/fs/erofs/rust/erofs_sys.rs @@ -24,6 +24,7 @@ pub(crate) type PosixResult = Result; pub(crate) mod errnos; +pub(crate) mod inode; pub(crate) mod superblock; pub(crate) mod xattrs; pub(crate) use errnos::Errno; diff --git a/fs/erofs/rust/erofs_sys/inode.rs b/fs/erofs/rust/erofs_sys/inode.rs new file mode 100644 index 000000000000..1762023e97f8 --- /dev/null +++ b/fs/erofs/rust/erofs_sys/inode.rs @@ -0,0 +1,291 @@ +use super::xattrs::*; +use super::*; +use core::ffi::*; +use core::mem::size_of; + +/// Represents the compact bitfield of the Erofs Inode format. +#[repr(transparent)] +#[derive(Clone, Copy)] +pub(crate) struct Format(u16); + +pub(crate) const INODE_VERSION_MASK: u16 = 0x1; +pub(crate) const INODE_VERSION_BIT: u16 = 0; + +pub(crate) const INODE_LAYOUT_BIT: u16 = 1; +pub(crate) const INODE_LAYOUT_MASK: u16 = 0x7; + +/// Helper macro to extract property from the bitfield. +macro_rules! extract { + ($name: expr, $bit: expr, $mask: expr) => { + ($name >> $bit) & ($mask) + }; +} + +/// The Version of the Inode which represents whether this inode is extended or compact. +/// Extended inodes have more infos about nlinks + mtime. +/// This is documented in https://erofs.docs.kernel.org/en/latest/core_ondisk.html#inodes +#[repr(C)] +#[derive(Clone, Copy)] +pub(crate) enum Version { + Compat, + Extended, + Unknown, +} + +/// Represents the data layout backed by the Inode. +/// As Documented in https://erofs.docs.kernel.org/en/latest/core_ondisk.html#inode-data-layouts +#[repr(C)] +#[derive(Clone, Copy, PartialEq)] +pub(crate) enum Layout { + FlatPlain, + CompressedFull, + FlatInline, + CompressedCompact, + Chunk, + Unknown, +} + +#[repr(C)] +#[allow(non_camel_case_types)] +#[derive(Clone, Copy, Debug, PartialEq)] +pub(crate) enum Type { + Regular, + Directory, + Link, + Character, + Block, + Fifo, + Socket, + Unknown, +} + +/// This is format extracted from i_format bit representation. +/// This includes various infos and specs about the inode. +impl Format { + pub(crate) fn version(&self) -> Version { + match extract!(self.0, INODE_VERSION_BIT, INODE_VERSION_MASK) { + 0 => Version::Compat, + 1 => Version::Extended, + _ => Version::Unknown, + } + } + + pub(crate) fn layout(&self) -> Layout { + match extract!(self.0, INODE_LAYOUT_BIT, INODE_LAYOUT_MASK) { + 0 => Layout::FlatPlain, + 1 => Layout::CompressedFull, + 2 => Layout::FlatInline, + 3 => Layout::CompressedCompact, + 4 => Layout::Chunk, + _ => Layout::Unknown, + } + } +} + +/// Represents the compact inode which resides on-disk. +/// This is documented in https://erofs.docs.kernel.org/en/latest/core_ondisk.html#inodes +#[repr(C)] +#[derive(Clone, Copy)] +pub(crate) struct CompactInodeInfo { + pub(crate) i_format: Format, + pub(crate) i_xattr_icount: u16, + pub(crate) i_mode: u16, + pub(crate) i_nlink: u16, + pub(crate) i_size: u32, + pub(crate) i_reserved: [u8; 4], + pub(crate) i_u: [u8; 4], + pub(crate) i_ino: u32, + pub(crate) i_uid: u16, + pub(crate) i_gid: u16, + pub(crate) i_reserved2: [u8; 4], +} + +/// Represents the extended inode which resides on-disk. +/// This is documented in https://erofs.docs.kernel.org/en/latest/core_ondisk.html#inodes +#[repr(C)] +#[derive(Clone, Copy)] +pub(crate) struct ExtendedInodeInfo { + pub(crate) i_format: Format, + pub(crate) i_xattr_icount: u16, + pub(crate) i_mode: u16, + pub(crate) i_reserved: [u8; 2], + pub(crate) i_size: u64, + pub(crate) i_u: [u8; 4], + pub(crate) i_ino: u32, + pub(crate) i_uid: u32, + pub(crate) i_gid: u32, + pub(crate) i_mtime: u64, + pub(crate) i_mtime_nsec: u32, + pub(crate) i_nlink: u32, + pub(crate) i_reserved2: [u8; 16], +} + +/// Represents the inode info which is either compact or extended. +#[derive(Clone, Copy)] +pub(crate) enum InodeInfo { + Extended(ExtendedInodeInfo), + Compact(CompactInodeInfo), +} + +pub(crate) const CHUNK_BLKBITS_MASK: u16 = 0x1f; +pub(crate) const CHUNK_FORMAT_INDEX_BIT: u16 = 0x20; + +/// Represents on-disk chunk index of the file backing inode. +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub(crate) struct ChunkIndex { + pub(crate) advise: u16, + pub(crate) device_id: u16, + pub(crate) blkaddr: u32, +} + +impl From<[u8; 8]> for ChunkIndex { + fn from(u: [u8; 8]) -> Self { + let advise = u16::from_le_bytes([u[0], u[1]]); + let device_id = u16::from_le_bytes([u[2], u[3]]); + let blkaddr = u32::from_le_bytes([u[4], u[5], u[6], u[7]]); + ChunkIndex { + advise, + device_id, + blkaddr, + } + } +} + +/// Chunk format used for indicating the chunkbits and chunkindex. +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub(crate) struct ChunkFormat(pub(crate) u16); + +impl ChunkFormat { + pub(crate) fn is_chunkindex(&self) -> bool { + self.0 & CHUNK_FORMAT_INDEX_BIT != 0 + } + pub(crate) fn chunkbits(&self) -> u16 { + self.0 & CHUNK_BLKBITS_MASK + } +} + +/// Represents the inode spec which is either data or device. +#[derive(Clone, Copy, Debug)] +#[repr(u32)] +pub(crate) enum Spec { + Chunk(ChunkFormat), + RawBlk(u32), + Device(u32), + CompressedBlocks(u32), + Unknown, +} + +/// Convert the spec from the format of the inode based on the layout. +impl From<(&[u8; 4], Layout)> for Spec { + fn from(value: (&[u8; 4], Layout)) -> Self { + match value.1 { + Layout::FlatInline | Layout::FlatPlain => Spec::RawBlk(u32::from_le_bytes(*value.0)), + Layout::CompressedFull | Layout::CompressedCompact => { + Spec::CompressedBlocks(u32::from_le_bytes(*value.0)) + } + Layout::Chunk => Self::Chunk(ChunkFormat(u16::from_le_bytes([value.0[0], value.0[1]]))), + // We don't support compressed inlines or compressed chunks currently. + _ => Spec::Unknown, + } + } +} + +/// Helper functions for Inode Info. +impl InodeInfo { + const S_IFMT: u16 = 0o170000; + const S_IFSOCK: u16 = 0o140000; + const S_IFLNK: u16 = 0o120000; + const S_IFREG: u16 = 0o100000; + const S_IFBLK: u16 = 0o60000; + const S_IFDIR: u16 = 0o40000; + const S_IFCHR: u16 = 0o20000; + const S_IFIFO: u16 = 0o10000; + const S_ISUID: u16 = 0o4000; + const S_ISGID: u16 = 0o2000; + const S_ISVTX: u16 = 0o1000; + pub(crate) fn ino(&self) -> u32 { + match self { + Self::Extended(extended) => extended.i_ino, + Self::Compact(compact) => compact.i_ino, + } + } + + pub(crate) fn format(&self) -> Format { + match self { + Self::Extended(extended) => extended.i_format, + Self::Compact(compact) => compact.i_format, + } + } + + pub(crate) fn file_size(&self) -> Off { + match self { + Self::Extended(extended) => extended.i_size, + Self::Compact(compact) => compact.i_size as u64, + } + } + + pub(crate) fn inode_size(&self) -> Off { + match self { + Self::Extended(_) => 64, + Self::Compact(_) => 32, + } + } + + pub(crate) fn spec(&self) -> Spec { + let mode = match self { + Self::Extended(extended) => extended.i_mode, + Self::Compact(compact) => compact.i_mode, + }; + + let u = match self { + Self::Extended(extended) => &extended.i_u, + Self::Compact(compact) => &compact.i_u, + }; + + match mode & 0o170000 { + 0o40000 | 0o100000 | 0o120000 => Spec::from((u, self.format().layout())), + // We don't support device inodes currently. + _ => Spec::Unknown, + } + } + + pub(crate) fn inode_type(&self) -> Type { + let mode = match self { + Self::Extended(extended) => extended.i_mode, + Self::Compact(compact) => compact.i_mode, + }; + match mode & Self::S_IFMT { + Self::S_IFDIR => Type::Directory, // Directory + Self::S_IFREG => Type::Regular, // Regular File + Self::S_IFLNK => Type::Link, // Symbolic Link + Self::S_IFIFO => Type::Fifo, // FIFO + Self::S_IFSOCK => Type::Socket, // Socket + Self::S_IFBLK => Type::Block, // Block + Self::S_IFCHR => Type::Character, // Character + _ => Type::Unknown, + } + } + + pub(crate) fn xattr_size(&self) -> Off { + match self { + Self::Extended(extended) => { + size_of::() as Off + + (size_of::() as Off) * (extended.i_xattr_icount as Off - 1) + } + Self::Compact(_) => 0, + } + } + + pub(crate) fn xattr_count(&self) -> u16 { + match self { + Self::Extended(extended) => extended.i_xattr_icount, + Self::Compact(compact) => compact.i_xattr_icount, + } + } +} + +pub(crate) type CompactInodeInfoBuf = [u8; size_of::()]; +pub(crate) type ExtendedInodeInfoBuf = [u8; size_of::()]; +pub(crate) const DEFAULT_INODE_BUF: ExtendedInodeInfoBuf = [0; size_of::()]; From patchwork Mon Sep 16 13:55:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yiyang Wu X-Patchwork-Id: 13805451 Received: from mail.tlmp.cc (unknown [148.135.17.20]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AF12B1581F2; Mon, 16 Sep 2024 13:56:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.135.17.20 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726494974; cv=none; b=cgTpZF83+OcjD012/TFkIyUDt/olSSaWpHAPFUfBFwmEEgrFwXQyl+W4LxEXHFBga2idKvMu8diAIuyxjyHCGJy8FPF5YH2j8KBox0glggORyev+Ya72kVt2PAQ8Qz+EtWVRq3CxfPJ8+CPrMjd4xr0LXb4qjKgW2NHtrjJq5ss= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726494974; c=relaxed/simple; bh=nfHK1i9ph1376F4QA3EYzyMqATO930veypDKTSAKBl4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=h1WRy+2m+iQ5mYDExgR2hLNofpphKKALhxZnRKami7ebGj0Z1bJp2o7YEBhlLBzWUtaGFq1midRg7EcJbKd6OxeQysEP3fxAbgbMFWn3+JbGBbQtktb8PPtc5QMQyLVxG9EK9QCek5Xn67xzzg5+qlWc45VPHg/PTlIBZoJn9WQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc; spf=pass smtp.mailfrom=tlmp.cc; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b=mGxKwz3A; arc=none smtp.client-ip=148.135.17.20 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b="mGxKwz3A" Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id C7E2B6997C; Mon, 16 Sep 2024 09:56:10 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tlmp.cc; s=dkim; t=1726494971; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=fUBtB1guKBDyxePSsjzX2NyUyWv+dPs0ZXuq7FSRkmE=; b=mGxKwz3AdeaXEa+Zwv4zhcj0QPfvTzlnGjWzfjlWezQsRbE3bBoPx8/ftT/tdocBSMQ0fo LrFdFTZhsKHD4yaMuCHZTS5/ybTGly29AEwBdu/fikJDE7js+xJscqfqZQraDGnnqtOyn9 JT4PHznx8/VKrZWoOMUin0TMDGF1dJXkk5AbGRHWKH6E1wLwglj4xm27jLAM0tDXwZN0tB 85UzIuav1PuFzzBtLnF2Erfe3QQUzzCuqKjIUcXwazk1h58EJuxI0czudN6KA7IX3yOiTC bZQKi1P7XCNt7KmCcd9tbyvpKk0J/V9DbachkuYvPEiux2UDmPU7osSPjvDBEg== From: Yiyang Wu To: linux-erofs@lists.ozlabs.org Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 06/24] erofs: add alloc_helper in Rust Date: Mon, 16 Sep 2024 21:55:23 +0800 Message-ID: <20240916135541.98096-7-toolmanp@tlmp.cc> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240916135541.98096-1-toolmanp@tlmp.cc> References: <20240916135541.98096-1-toolmanp@tlmp.cc> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Last-TLS-Session-Version: TLSv1.3 In normal rust, heap related operations are infallible meaning that they do not throw errors and Rust will panic in usermode instead. However in kernel, it will throw AllocError this module helps to bridge the gaps and returns Errno universally. Signed-off-by: Yiyang Wu --- fs/erofs/rust/erofs_sys.rs | 1 + fs/erofs/rust/erofs_sys/alloc_helper.rs | 35 +++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 fs/erofs/rust/erofs_sys/alloc_helper.rs diff --git a/fs/erofs/rust/erofs_sys.rs b/fs/erofs/rust/erofs_sys.rs index 34267ec7772d..c6fd7f78ac97 100644 --- a/fs/erofs/rust/erofs_sys.rs +++ b/fs/erofs/rust/erofs_sys.rs @@ -23,6 +23,7 @@ /// to avoid naming conflicts. pub(crate) type PosixResult = Result; +pub(crate) mod alloc_helper; pub(crate) mod errnos; pub(crate) mod inode; pub(crate) mod superblock; diff --git a/fs/erofs/rust/erofs_sys/alloc_helper.rs b/fs/erofs/rust/erofs_sys/alloc_helper.rs new file mode 100644 index 000000000000..05ef2018d379 --- /dev/null +++ b/fs/erofs/rust/erofs_sys/alloc_helper.rs @@ -0,0 +1,35 @@ +// Copyright 2024 Yiyang Wu +// SPDX-License-Identifier: MIT or GPL-2.0-or-later + +/// This module provides helper functions for the alloc crate +/// Note that in linux kernel, the allocation is fallible however in userland it is not. +/// Since most of the functions depend on infallible allocation, here we provide helper functions +/// so that most of codes don't need to be changed. + +#[cfg(CONFIG_EROFS_FS = "y")] +use kernel::prelude::*; + +#[cfg(not(CONFIG_EROFS_FS = "y"))] +use alloc::vec; + +use super::*; +use alloc::boxed::Box; +use alloc::vec::Vec; + +pub(crate) fn push_vec(v: &mut Vec, value: T) -> PosixResult<()> { + v.push(value, GFP_KERNEL) + .map_or_else(|_| Err(Errno::ENOMEM), |_| Ok(())) +} + +pub(crate) fn extend_from_slice(v: &mut Vec, slice: &[T]) -> PosixResult<()> { + v.extend_from_slice(slice, GFP_KERNEL) + .map_or_else(|_| Err(Errno::ENOMEM), |_| Ok(())) +} + +pub(crate) fn heap_alloc(value: T) -> PosixResult> { + Box::new(value, GFP_KERNEL).map_or_else(|_| Err(Errno::ENOMEM), |v| Ok(v)) +} + +pub(crate) fn vec_with_capacity(capacity: usize) -> PosixResult> { + Vec::with_capacity(capacity, GFP_KERNEL).map_or_else(|_| Err(Errno::ENOMEM), |v| Ok(v)) +} From patchwork Mon Sep 16 13:55:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yiyang Wu X-Patchwork-Id: 13805452 Received: from mail.tlmp.cc (unknown [148.135.17.20]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 007C315852E; Mon, 16 Sep 2024 13:56:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.135.17.20 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726494976; cv=none; b=QUf1XNww2hnnBUTWKBS+p6MOfTSuvK7srWuriBYkHeOR6qmRiJ+3kkBJ3FsxJWZ/vrKQbwFQpq51gLJ0QW5f3k4qmvX86QdpQ/OPSP25OTaYyq+ovQkpYnX5PvvwD+7rId1Ag7TVXYhm3sOPBlNkp2ohi7XmXUXVVs/yIoK+V60= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726494976; c=relaxed/simple; bh=H9qZQ6sPOX6lomGbiY5NWabke+KIbETnJDwauhJvUys=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FPzDVI3kFiWwUKhKRyJFV4tfMyrZS97JlPtLEQzShRCyv3vpRzfvFCYr6PyKeiGD0HUhmMgT6B2Ea81PEoTjVpOBoN4B7pKXne0b0as4DlDXDl7qB0JJGMTsOe/I/lXzFe7efuKj2r5UZDPuJo0J1tgo5tyv3cwyWTLICEbyX7M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc; spf=pass smtp.mailfrom=tlmp.cc; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b=lWj1RcoQ; arc=none smtp.client-ip=148.135.17.20 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b="lWj1RcoQ" Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 7D8A26997B; Mon, 16 Sep 2024 09:56:12 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tlmp.cc; s=dkim; t=1726494973; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=RkMMOXQTsmanQe52UgGZbvf6dLNC+ICFQfOIzTuSzMo=; b=lWj1RcoQuWBLQcg52cSVUJlekfGYmj3eyjhUX1zRLg5iPFQua2BXf+5dlwA0+Lc8jXT9+y mhEoRsnJaaH9X7lCI38wRpiDni2rp/BQJ5lwFewaK/pvR610KrpNG/NUkgNhKcmNYCJmAp b1pfLeNHdJMtbkMKxyFkG6Rqxab08HRTEfs423n/2xiL/Zoa/un+P7GvIXjqp/YPsL1b35 +0j+IVX4g+2Xdb3m3fIQytqD5IHifDEru+0sCOsNgHPAmP2NBWUf0vUkqvFNw3paqDEIKs FNQAp23to/z/F9G43nJebIYU2LBl0ZXgWAeJaOH/rF0yRVy7SO6iIz8jfifnAw== From: Yiyang Wu To: linux-erofs@lists.ozlabs.org Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 07/24] erofs: add data abstraction in Rust Date: Mon, 16 Sep 2024 21:55:24 +0800 Message-ID: <20240916135541.98096-8-toolmanp@tlmp.cc> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240916135541.98096-1-toolmanp@tlmp.cc> References: <20240916135541.98096-1-toolmanp@tlmp.cc> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Last-TLS-Session-Version: TLSv1.3 Introduce Buffer, Source, Backend traits. Implement Uncompressed Backend and RefBuffer to be used in future data operations. Signed-off-by: Yiyang Wu --- fs/erofs/rust/erofs_sys.rs | 1 + fs/erofs/rust/erofs_sys/data.rs | 62 +++++++++++++++++++ fs/erofs/rust/erofs_sys/data/backends.rs | 4 ++ .../erofs_sys/data/backends/uncompressed.rs | 39 ++++++++++++ 4 files changed, 106 insertions(+) create mode 100644 fs/erofs/rust/erofs_sys/data.rs create mode 100644 fs/erofs/rust/erofs_sys/data/backends.rs create mode 100644 fs/erofs/rust/erofs_sys/data/backends/uncompressed.rs diff --git a/fs/erofs/rust/erofs_sys.rs b/fs/erofs/rust/erofs_sys.rs index c6fd7f78ac97..8cca2cd9b75f 100644 --- a/fs/erofs/rust/erofs_sys.rs +++ b/fs/erofs/rust/erofs_sys.rs @@ -24,6 +24,7 @@ pub(crate) type PosixResult = Result; pub(crate) mod alloc_helper; +pub(crate) mod data; pub(crate) mod errnos; pub(crate) mod inode; pub(crate) mod superblock; diff --git a/fs/erofs/rust/erofs_sys/data.rs b/fs/erofs/rust/erofs_sys/data.rs new file mode 100644 index 000000000000..284c8b1f3bd4 --- /dev/null +++ b/fs/erofs/rust/erofs_sys/data.rs @@ -0,0 +1,62 @@ +// Copyright 2024 Yiyang Wu +// SPDX-License-Identifier: MIT or GPL-2.0-or-later +pub(crate) mod backends; +use super::*; + +/// Represent some sort of generic data source. This cound be file, memory or even network. +/// Note that users should never use this directly please use backends instead. +pub(crate) trait Source { + fn fill(&self, data: &mut [u8], offset: Off) -> PosixResult; + fn as_buf<'a>(&'a self, offset: Off, len: Off) -> PosixResult>; +} + +/// Represents a generic data access backend that is backed by some sort of data source. +/// This often has temporary buffers to decompress the data from the data source. +/// The method signatures are the same as those of the Source trait. +pub(crate) trait Backend { + fn fill(&self, data: &mut [u8], offset: Off) -> PosixResult; + fn as_buf<'a>(&'a self, offset: Off, len: Off) -> PosixResult>; +} + +/// Represents a buffer trait which can yield its internal reference or be casted as an iterator of +/// DirEntries. +pub(crate) trait Buffer { + fn content(&self) -> &[u8]; +} + +/// Represents a buffer that holds a reference to a slice of data that +/// is borrowed from the thin air. +pub(crate) struct RefBuffer<'a> { + buf: &'a [u8], + start: usize, + len: usize, + put_buf: fn(*mut core::ffi::c_void), +} + +impl<'a> Buffer for RefBuffer<'a> { + fn content(&self) -> &[u8] { + &self.buf[self.start..self.start + self.len] + } +} + +impl<'a> RefBuffer<'a> { + pub(crate) fn new( + buf: &'a [u8], + start: usize, + len: usize, + put_buf: fn(*mut core::ffi::c_void), + ) -> Self { + Self { + buf, + start, + len, + put_buf, + } + } +} + +impl<'a> Drop for RefBuffer<'a> { + fn drop(&mut self) { + (self.put_buf)(self.buf.as_ptr() as *mut core::ffi::c_void) + } +} diff --git a/fs/erofs/rust/erofs_sys/data/backends.rs b/fs/erofs/rust/erofs_sys/data/backends.rs new file mode 100644 index 000000000000..3249f1af8be7 --- /dev/null +++ b/fs/erofs/rust/erofs_sys/data/backends.rs @@ -0,0 +1,4 @@ +// Copyright 2024 Yiyang Wu +// SPDX-License-Identifier: MIT or GPL-2.0-or-later + +pub(crate) mod uncompressed; diff --git a/fs/erofs/rust/erofs_sys/data/backends/uncompressed.rs b/fs/erofs/rust/erofs_sys/data/backends/uncompressed.rs new file mode 100644 index 000000000000..c1b1a60258f8 --- /dev/null +++ b/fs/erofs/rust/erofs_sys/data/backends/uncompressed.rs @@ -0,0 +1,39 @@ +// Copyright 2024 Yiyang Wu +// SPDX-License-Identifier: MIT or GPL-2.0-or-later + +use super::super::*; + +pub(crate) struct UncompressedBackend +where + T: Source, +{ + source: T, +} + +impl Backend for UncompressedBackend +where + T: Source, +{ + fn fill(&self, data: &mut [u8], offset: Off) -> PosixResult { + self.source.fill(data, offset) + } + + fn as_buf<'a>(&'a self, offset: Off, len: Off) -> PosixResult> { + self.source.as_buf(offset, len) + } +} + +impl UncompressedBackend { + pub(crate) fn new(source: T) -> Self { + Self { source } + } +} + +impl From for UncompressedBackend +where + T: Source, +{ + fn from(value: T) -> Self { + Self::new(value) + } +} From patchwork Mon Sep 16 13:55:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yiyang Wu X-Patchwork-Id: 13805453 Received: from mail.tlmp.cc (unknown [148.135.17.20]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D624B156654; Mon, 16 Sep 2024 13:56:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.135.17.20 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726494978; cv=none; b=NUduzQALRRogn1uAQOEW0Jx86tzCpAsEykT4JPslwXYe9IUkija2/PM98WV6eQnHlIdXSD7kNvU0BQvy5cxTGuRPyK7pM/CN3lChF+C77RsBM6hS3Qn/76xWcnca8gS2278jdx7r6vFXwGhBOif1P1t6RzMfZhi0i+C6YHhNQxc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726494978; c=relaxed/simple; bh=0c66dwnUGs7UBAhZ/nX2CQVs5yJOB4tBeg1XqoqkzKE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=H1GYRr1pFkr4O1/0R1N6njnDolWo7WLk+WJ2cTKLLDzpO/PlmmpS7ZCTLXz+0whIPEVv337u/QWZhj10YxjdGlny5ocPYmxmG5yElxZC5UXEUmZhynC3GTmYWHfAqSLeP2BV6BGC/3Ae2om5fEcv0fqK4ycJKwyI0xIgNklhF4A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc; spf=pass smtp.mailfrom=tlmp.cc; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b=RD9Zrmy4; arc=none smtp.client-ip=148.135.17.20 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b="RD9Zrmy4" Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id DCD7C6997E; Mon, 16 Sep 2024 09:56:14 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tlmp.cc; s=dkim; t=1726494976; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=RpwAvNBL1BrrWM3+ylO6h2C6ZxDk5XDbbYWzUi+PA6A=; b=RD9Zrmy4bnAEImb3l+5RmIvtBv7zzpA5277tsz28NEc29kpPHV2TkQFR0iP47WKY+05mGt uDA2J3GSyTW2VhipdhYWfkSQzSJeu+leX6EWumOqkYQH78h8dxxt1k0zdaOW5l60w7D3eR snDYYM+IoWKGgJKxfcW+CRv56yQY7095GKS72xgakamKZWssSuKp7rrTFGMRChcVmV4EV2 iezGjTojz87rgiQ00RMiTA73/kk326M23WBZ+3X6QUxCbCS4ipne+siy3ua8QkXsZAKqAI OPWnpud6JYZLZfj8fF5wVBAvQwKqZQ9WsDVtloLalbjXSAxci6+P69wNpm4RQw== From: Yiyang Wu To: linux-erofs@lists.ozlabs.org Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 08/24] erofs: add device data structure in Rust Date: Mon, 16 Sep 2024 21:55:25 +0800 Message-ID: <20240916135541.98096-9-toolmanp@tlmp.cc> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240916135541.98096-1-toolmanp@tlmp.cc> References: <20240916135541.98096-1-toolmanp@tlmp.cc> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Last-TLS-Session-Version: TLSv1.3 This patch introduce device data structure in Rust. It can later support chunk based block maps. Signed-off-by: Yiyang Wu --- fs/erofs/rust/erofs_sys.rs | 1 + fs/erofs/rust/erofs_sys/devices.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 fs/erofs/rust/erofs_sys/devices.rs diff --git a/fs/erofs/rust/erofs_sys.rs b/fs/erofs/rust/erofs_sys.rs index 8cca2cd9b75f..f1a1e491caec 100644 --- a/fs/erofs/rust/erofs_sys.rs +++ b/fs/erofs/rust/erofs_sys.rs @@ -25,6 +25,7 @@ pub(crate) mod alloc_helper; pub(crate) mod data; +pub(crate) mod devices; pub(crate) mod errnos; pub(crate) mod inode; pub(crate) mod superblock; diff --git a/fs/erofs/rust/erofs_sys/devices.rs b/fs/erofs/rust/erofs_sys/devices.rs new file mode 100644 index 000000000000..097676ee8720 --- /dev/null +++ b/fs/erofs/rust/erofs_sys/devices.rs @@ -0,0 +1,28 @@ +// Copyright 2024 Yiyang Wu +// SPDX-License-Identifier: MIT or GPL-2.0-or-later + +use alloc::vec::Vec; + +/// Device specification. +#[derive(Copy, Clone, Debug)] +pub(crate) struct DeviceSpec { + pub(crate) tags: [u8; 64], + pub(crate) blocks: u32, + pub(crate) mapped_blocks: u32, +} + +/// Device slot. +#[derive(Copy, Clone, Debug)] +#[repr(C)] +pub(crate) struct DeviceSlot { + tags: [u8; 64], + blocks: u32, + mapped_blocks: u32, + reserved: [u8; 56], +} + +/// Device information. +pub(crate) struct DeviceInfo { + pub(crate) mask: u16, + pub(crate) specs: Vec, +} From patchwork Mon Sep 16 13:55:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yiyang Wu X-Patchwork-Id: 13805454 Received: from mail.tlmp.cc (unknown [148.135.17.20]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DB6781586FE; Mon, 16 Sep 2024 13:56:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.135.17.20 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726494980; cv=none; b=sMkU2FpdQR0zljTmJZcC4Q43LKN7hj/qaLJFaIbbHt5slDt7d7QwYJb7mpiNEtJxf0UDXCFdxrR7+HnHSoRau5J/vuFWjIn6Dj0mdMZVeA1+qXc+x3uXYaEsfU4Ue7UkaW5XkpyINR4xZ/nL69Rjf+niU9cbNN2SIuu/up1JosU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726494980; c=relaxed/simple; bh=C6bzJ0ahOVi4Lz5NDHXNa2g12EqOHhJgzseFPgoTZoI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=om5t4JTsgWz4KRQ8gRdn9BqHrpnlGMpvksBJEyhWcKkkYdtI62Tae9h65XJjVVmHRybyesx2zNGRoAoPCxvUwEbxuf1DWHyo+dNhtz8kMkfAg5aU16PJ5dND44iDKN1MUn9I/hQf0SFbPEdzNZTvr9j0UvlV9hdUOf+7vZP1VN8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc; spf=pass smtp.mailfrom=tlmp.cc; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b=CCH/7Wpl; arc=none smtp.client-ip=148.135.17.20 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b="CCH/7Wpl" Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id A972E6997D; Mon, 16 Sep 2024 09:56:16 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tlmp.cc; s=dkim; t=1726494977; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=CeM2RxQ3ayEheLUMCn9fl9h9UhYePHokORV1b9tMe8Y=; b=CCH/7WplQihI8IQSOeM+qSyheqlKc/+3ge+BVwwr3F5KemwNkoKCxNMRnQ5KEjxI4pHhEG Yp3l0ZbMtH6z/O9zF8Rc26nGuHUWn8bx19wkKPrt4BeXbonNQrPlz2DFpN7Q9YItP2rbj2 q0bKdiKpmPkNoSNXo1wZlae5WbZLiFVfWLSkweVgwMI/m6ZJ2aDueAO/IUkcT+bEfDhNNG iAC0MfyYbPOKQX/767ZGpqgr2Cvkeb9Hykj33qkOFFhdAmX4ff24BsCfN/MMT1r1O/oCb5 Abalb/CnbSKVm3eG06+rw6hM/nYxXm9ujXXKb34nWe2ZoiH2mDwYqR2uPTjBcQ== From: Yiyang Wu To: linux-erofs@lists.ozlabs.org Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 09/24] erofs: add continuous iterators in Rust Date: Mon, 16 Sep 2024 21:55:26 +0800 Message-ID: <20240916135541.98096-10-toolmanp@tlmp.cc> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240916135541.98096-1-toolmanp@tlmp.cc> References: <20240916135541.98096-1-toolmanp@tlmp.cc> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Last-TLS-Session-Version: TLSv1.3 This patch adds a special iterator that is capable of iterating over a memory region in the granularity of a common page. This can be later used to read device buffer or fast symlink. Signed-off-by: Yiyang Wu --- fs/erofs/rust/erofs_sys/data.rs | 2 + fs/erofs/rust/erofs_sys/data/raw_iters.rs | 6 ++ .../rust/erofs_sys/data/raw_iters/ref_iter.rs | 68 +++++++++++++++++++ .../rust/erofs_sys/data/raw_iters/traits.rs | 13 ++++ 4 files changed, 89 insertions(+) create mode 100644 fs/erofs/rust/erofs_sys/data/raw_iters.rs create mode 100644 fs/erofs/rust/erofs_sys/data/raw_iters/ref_iter.rs create mode 100644 fs/erofs/rust/erofs_sys/data/raw_iters/traits.rs diff --git a/fs/erofs/rust/erofs_sys/data.rs b/fs/erofs/rust/erofs_sys/data.rs index 284c8b1f3bd4..483f3204ce42 100644 --- a/fs/erofs/rust/erofs_sys/data.rs +++ b/fs/erofs/rust/erofs_sys/data.rs @@ -1,6 +1,8 @@ // Copyright 2024 Yiyang Wu // SPDX-License-Identifier: MIT or GPL-2.0-or-later pub(crate) mod backends; +pub(crate) mod raw_iters; +use super::superblock::*; use super::*; /// Represent some sort of generic data source. This cound be file, memory or even network. diff --git a/fs/erofs/rust/erofs_sys/data/raw_iters.rs b/fs/erofs/rust/erofs_sys/data/raw_iters.rs new file mode 100644 index 000000000000..8f3bd250d252 --- /dev/null +++ b/fs/erofs/rust/erofs_sys/data/raw_iters.rs @@ -0,0 +1,6 @@ +// Copyright 2024 Yiyang Wu +// SPDX-License-Identifier: MIT or GPL-2.0-or-later + +pub(crate) mod ref_iter; +mod traits; +pub(crate) use traits::*; diff --git a/fs/erofs/rust/erofs_sys/data/raw_iters/ref_iter.rs b/fs/erofs/rust/erofs_sys/data/raw_iters/ref_iter.rs new file mode 100644 index 000000000000..5aa2b7f44f3d --- /dev/null +++ b/fs/erofs/rust/erofs_sys/data/raw_iters/ref_iter.rs @@ -0,0 +1,68 @@ +// Copyright 2024 Yiyang Wu +// SPDX-License-Identifier: MIT or GPL-2.0-or-later + +use super::super::*; +use super::*; + +/// Continous Ref Buffer Iterator which iterates over a range of disk addresses within the +/// the temp block size. Since the temp block is always the same size as page and it will not +/// overflow. +pub(crate) struct ContinuousRefIter<'a, B> +where + B: Backend, +{ + sb: &'a SuperBlock, + backend: &'a B, + offset: Off, + len: Off, +} + +impl<'a, B> ContinuousRefIter<'a, B> +where + B: Backend, +{ + pub(crate) fn new(sb: &'a SuperBlock, backend: &'a B, offset: Off, len: Off) -> Self { + Self { + sb, + backend, + offset, + len, + } + } +} + +impl<'a, B> Iterator for ContinuousRefIter<'a, B> +where + B: Backend, +{ + type Item = PosixResult>; + fn next(&mut self) -> Option { + if self.len == 0 { + return None; + } + let accessor = self.sb.blk_access(self.offset); + let len = accessor.len.min(self.len); + let result: Option = self.backend.as_buf(self.offset, len).map_or_else( + |e| Some(Err(e)), + |buf| { + self.offset += len; + self.len -= len; + Some(Ok(buf)) + }, + ); + result + } +} + +impl<'a, B> ContinuousBufferIter<'a> for ContinuousRefIter<'a, B> +where + B: Backend, +{ + fn advance_off(&mut self, offset: Off) { + self.offset += offset; + self.len -= offset + } + fn eof(&self) -> bool { + self.len == 0 + } +} diff --git a/fs/erofs/rust/erofs_sys/data/raw_iters/traits.rs b/fs/erofs/rust/erofs_sys/data/raw_iters/traits.rs new file mode 100644 index 000000000000..90b6a51658a9 --- /dev/null +++ b/fs/erofs/rust/erofs_sys/data/raw_iters/traits.rs @@ -0,0 +1,13 @@ +// Copyright 2024 Yiyang Wu +// SPDX-License-Identifier: MIT or GPL-2.0-or-later + +use super::super::*; + +/// Represents a basic iterator over a range of bytes from data backends. +/// Note that this is skippable and can be used to move the iterator's cursor forward. +pub(crate) trait ContinuousBufferIter<'a>: + Iterator>> +{ + fn advance_off(&mut self, offset: Off); + fn eof(&self) -> bool; +} From patchwork Mon Sep 16 13:55:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yiyang Wu X-Patchwork-Id: 13805455 Received: from mail.tlmp.cc (unknown [148.135.17.20]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 51EBF156654; Mon, 16 Sep 2024 13:56:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.135.17.20 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726494981; cv=none; b=LXumfHqSiH6NmjyKMc59pi+8sGDcmpGk7UKeCEgD2e1yM1kbV08LWX1FHrSA3Lys0GJ/APCGApQLpoNcboNjZhZiFSNTYOW/3Wju77XXi0l+zu0O4jZ46akfAlClwopA+8r3DZPsDjZpkthG0nBJPm9f/rem246gL+g50ZgaVfo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726494981; c=relaxed/simple; bh=C1ZrNRNACCjWx55UqgSqRNkayTakd+sKpVAO9zBzvsI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Hsh7Og7ZyG8gxvrYW0RkT2ywQxXjN6QwzGr3exVzVz6eoSKy4G/+JIQywANkdCjzUddcwQGmkPmZRIG8c90S1CxHhBcQLx1KdApXsKijbasvVoc6iNrlCWYXiHAOZwzeBRqvvYY+B7+wp1SVtzrt/73F8p1396QGWXTL1S7wPvM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc; spf=pass smtp.mailfrom=tlmp.cc; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b=JG0YywNm; arc=none smtp.client-ip=148.135.17.20 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=tlmp.cc Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=tlmp.cc header.i=@tlmp.cc header.b="JG0YywNm" Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 76EE76997F; Mon, 16 Sep 2024 09:56:18 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tlmp.cc; s=dkim; t=1726494979; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=TBJTDvYko+/iIPJGn9oa9UFP8352ieqw0qlVnvGk9ME=; b=JG0YywNmLao0k+8IkcmVMo1Tn7rk9cAoA/a1PrlMTUK/v/hLtORzSDc9yFLe7400qUxPlC MkjpSLGmtgq6XCcw9gcFCrKWn+V2JM0xqTm2dcI0+qnF9aS40Q9WIHJrZHXdygoyTaaQ8Z P95rw7havM9mbyYDXxu4/7K/TSXLT3MumjiadDjOaUe/ObcxklMdAsEUpcYDmp48F6vgWi vKVKIMQ6OHP2Vh8abqjXykdcWiiFMC7u84n8ED/9mBPaJKwXmNfPDSg83VAEA8mZjKzDZC JNgvi6SCATgor+5JvNps3qtIWoLk9cBufJZtCr0SDVwo0dtiE9IrmeddrLPMLA== From: Yiyang Wu To: linux-erofs@lists.ozlabs.org Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [RFC PATCH 10/24] erofs: add device_infos implementation in Rust Date: Mon, 16 Sep 2024 21:55:27 +0800 Message-ID: <20240916135541.98096-11-toolmanp@tlmp.cc> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240916135541.98096-1-toolmanp@tlmp.cc> References: <20240916135541.98096-1-toolmanp@tlmp.cc> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Last-TLS-Session-Version: TLSv1.3 Add device_infos implementation in rust. It will later be used to be put inside the SuperblockInfo. This mask and spec can later be used to chunk-based image file block mapping. Signed-off-by: Yiyang Wu --- fs/erofs/rust/erofs_sys/devices.rs | 47 ++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/fs/erofs/rust/erofs_sys/devices.rs b/fs/erofs/rust/erofs_sys/devices.rs index 097676ee8720..7495164c7bd0 100644 --- a/fs/erofs/rust/erofs_sys/devices.rs +++ b/fs/erofs/rust/erofs_sys/devices.rs @@ -1,6 +1,10 @@ // Copyright 2024 Yiyang Wu // SPDX-License-Identifier: MIT or GPL-2.0-or-later +use super::alloc_helper::*; +use super::data::raw_iters::*; +use super::data::*; +use super::*; use alloc::vec::Vec; /// Device specification. @@ -21,8 +25,51 @@ pub(crate) struct DeviceSlot { reserved: [u8; 56], } +impl From<[u8; 128]> for DeviceSlot { + fn from(data: [u8; 128]) -> Self { + Self { + tags: data[0..64].try_into().unwrap(), + blocks: u32::from_le_bytes([data[64], data[65], data[66], data[67]]), + mapped_blocks: u32::from_le_bytes([data[68], data[69], data[70], data[71]]), + reserved: data[72..128].try_into().unwrap(), + } + } +} + /// Device information. pub(crate) struct DeviceInfo { pub(crate) mask: u16, pub(crate) specs: Vec, } + +pub(crate) fn get_device_infos<'a>( + iter: &mut (dyn ContinuousBufferIter<'a> + 'a), +) -> PosixResult { + let mut specs = Vec::new(); + for data in iter { + let buffer = data?; + let mut cur: usize = 0; + let len = buffer.content().len(); + while cur + 128 <= len { + let slot_data: [u8; 128] = buffer.content()[cur..cur + 128].try_into().unwrap(); + let slot = DeviceSlot::from(slot_data); + cur += 128; + push_vec( + &mut specs, + DeviceSpec { + tags: slot.tags, + blocks: slot.blocks, + mapped_blocks: slot.mapped_blocks, + }, + )?; + } + } + + let mask = if specs.is_empty() { + 0 + } else { + (1 << (specs.len().ilog2() + 1)) - 1 + }; + + Ok(DeviceInfo { mask, specs }) +}