From nobody Mon Jun 15 20:34:08 2026 Received: from mail-wr1-f53.google.com (mail-wr1-f53.google.com [209.85.221.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EE5223C3C1B for ; Mon, 13 Apr 2026 12:24:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083057; cv=none; b=OElTH+9XKomCzOf4sMEMnGLAdGbZdORGWMYyfG9XlUpfzNihX2UuBQxeTYwR9FGIOpKUsprH8j06BR4CeOYwhzKTbjQUIyJEXUveajxwlCg5hHZO1CHnxR+glTmEVtWVE7BADLfECMpN+kJQjkU/osnUDgAhunZf1b0ce9EvcPk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083057; c=relaxed/simple; bh=eoBWd0CwY2rxkNA7j7plxEIALTZd5Ed5qQyEAxq5t70=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Q6pNcMLMe90AG4pKMxQe/JdiNHX794Vo5LGJ1b8SJG+KaGMZTzYUpivCft6WZgF7AdSdNyqNZ1QC4jr0lmwStCkz18pk+w0bhdeYXAfg+0TXFGy/ARDYWZiUvLNKzGE19kLa0y/kjhpOw7fij0aeKSGIedst/X+G8Su2oDLUg50= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.221.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wr1-f53.google.com with SMTP id ffacd0b85a97d-43d6fc30460so63185f8f.1 for ; Mon, 13 Apr 2026 05:24:15 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776083054; x=1776687854; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=omQOYkth1PndWLeQgJXqHU9j0qjA0S/orRkDREdZgpk=; b=DAyz01ERp3XuqLaegjD1cx2vGId3OOPfC88V+ywj9rTSpnFMKC9tTpFsa5WGTtU3m/ pV9LjVjijz8TxbQX/vvPECd0vtdd9F91c2y1rK+jgCEr36BnieGMlcPlV7kH69p7qYjX MIYWkKR+bzpoZkdVfUYWqTTWTLFxDTU4FAzHOkogp9Uj0L7JD1Qga+22aUILes28JpuK bkgLPvV0HZK3svBLQ5ChbH2lXcCX/avDZzAqm8iPpmxRMuf7dcsP7PVFM/6V+DtS0YET renunDty5qkejYkXGF6sojNj5wxqZec2F4uJ4wrqEBPiSkKmiN9m/EpQMoycR8WIx0M1 KG5w== X-Gm-Message-State: AOJu0YyZ8LyeADbOfT+SfCr6l+PpUm5hTJw3HBleuTz+HxubuFk/YFtp jkdnC7y/yt8CDRJBsRpqmnCJobYs3e5zFMcEWhwQobbgGC3ZfuswuKOvJPUO2kOxZO8= X-Gm-Gg: AeBDievSsq0M+gE1ktFoNrFbjQVL6N5rMsu3xOy587PZjiLlJq9a4SCR8W9sz2LzV/v Lg9V3mWxK+9gvQzTByQJujv3nApzsKMhXOaIyGUSmZp6VFYZev/2DDGCnBcXHS+dAB6scYHwS+K XYeOSx69gi6IwC0nw3tly+SZKoXKX1pc01AqPqAfmzfVb6JIcIHArn7fJ9zfzNTLBJpZTGsUyyJ B5uyLtYClJNaZfgXcssYbQCEVPSDXJ7iuP0XBdXcZNnmB5FyaWwa0vBsYNbf1rH5HvYYWaHlQEA mHM7dHuxlNmXnV6qvahp/5vZRwS7Q5oVPqyA+a0tw7xWjrGdXdm9pmOFjjZa0ne/ay23rEj72n6 t0S09fuQm295K2IZKrAPNBPW2cSjI78F98EfV2RppnJCxS9icZqEwD874VOOJO2fd0LPNh+CmMv 0tdlWvStURZu6uCEHmmYp5K6QsouOfWeXgqcDKiB8Rh5nP2GfbACbxehai1jXME7+EGg== X-Received: by 2002:a05:600c:5487:b0:486:b967:5c9b with SMTP id 5b1f17b1804b1-488d6833355mr91538435e9.3.1776083054261; Mon, 13 Apr 2026 05:24:14 -0700 (PDT) Received: from spartian-1.home ([2a01:cb1c:784:2f00:708:2805:7128:7a75]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-488d532ed4dsm278260915e9.4.2026.04.13.05.24.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Apr 2026 05:24:13 -0700 (PDT) From: Aurelien DESBRIERES To: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, viro@zeniv.linux.org.uk, brauner@kernel.org, aurelien@hackers.camp Subject: [RFC PATCH 01/10] ftrfs: add on-disk format and in-memory data structures Date: Mon, 13 Apr 2026 16:23:47 +0200 Message-ID: <20260413142357.515792-2-aurelien@hackers.camp> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260413142357.515792-1-aurelien@hackers.camp> References: <20260413142357.515792-1-aurelien@hackers.camp> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Aur=C3=A9lien DESBRIERES Add the core header defining FTRFS on-disk layout and in-memory VFS structures. On-disk layout: Block 0 : superblock (magic 0x46545246, CRC32-protected) Block 1..N : inode table (128 bytes/inode, CRC32 per inode) Block N+1..end : data blocks (CRC32 per block, RS FEC planned) Structures: ftrfs_super_block : on-disk superblock ftrfs_inode : on-disk inode (12 direct + 1 indirect + 1 dindirect) ftrfs_dir_entry : on-disk directory entry (256-byte name) ftrfs_sb_info : in-memory superblock info (VFS sb->s_fs_info) ftrfs_inode_info : in-memory inode (embedded VFS inode) FTRFS targets POSIX-compatible block devices (MRAM, NOR flash, eMMC) for use in radiation-intensive environments (space applications). Signed-off-by: Aur=C3=A9lien DESBRIERES --- fs/ftrfs/ftrfs.h | 168 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 fs/ftrfs/ftrfs.h diff --git a/fs/ftrfs/ftrfs.h b/fs/ftrfs/ftrfs.h new file mode 100644 index 000000000..82502c9fb --- /dev/null +++ b/fs/ftrfs/ftrfs.h @@ -0,0 +1,168 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * FTRFS =E2=80=94 Fault-Tolerant Radiation-Robust Filesystem + * Based on: Fuchs, Langer, Trinitis =E2=80=94 ARCS 2015 + * + * Author: roastercode - Aurelien DESBRIERES + */ + +#ifndef _FTRFS_H +#define _FTRFS_H + +#include +#include +#include + +/* Magic number: 'FTRF' */ +#define FTRFS_MAGIC 0x46545246 + +/* Block size: 4096 bytes */ +#define FTRFS_BLOCK_SIZE 4096 +#define FTRFS_BLOCK_SHIFT 12 + +/* RS FEC: 16 parity bytes per 239-byte subblock (RS(255,239)) */ +#define FTRFS_RS_PARITY 16 +#define FTRFS_SUBBLOCK_DATA 239 +#define FTRFS_SUBBLOCK_TOTAL (FTRFS_SUBBLOCK_DATA + FTRFS_RS_PARITY) + +/* Filesystem limits */ +#define FTRFS_MAX_FILENAME 255 +#define FTRFS_DIRECT_BLOCKS 12 +#define FTRFS_INDIRECT_BLOCKS 1 +#define FTRFS_DINDIRECT_BLOCKS 1 + +/* + * On-disk superblock =E2=80=94 block 0 + * Total size: fits in one 4096-byte block + */ +struct ftrfs_super_block { + __le32 s_magic; /* FTRFS_MAGIC */ + __le32 s_block_size; /* Block size in bytes */ + __le64 s_block_count; /* Total blocks */ + __le64 s_free_blocks; /* Free blocks */ + __le64 s_inode_count; /* Total inodes */ + __le64 s_free_inodes; /* Free inodes */ + __le64 s_inode_table_blk; /* Block where inode table starts */ + __le64 s_data_start_blk; /* First data block */ + __le32 s_version; /* Filesystem version */ + __le32 s_flags; /* Flags */ + __le32 s_crc32; /* CRC32 of this superblock */ + __u8 s_uuid[16]; /* UUID */ + __u8 s_label[32]; /* Volume label */ + __u8 s_pad[3948]; /* Padding to 4096 bytes */ +} __packed; + +/* + * On-disk inode + * Size: 128 bytes + */ +struct ftrfs_inode { + __le16 i_mode; /* File mode */ + __le16 i_uid; /* Owner UID */ + __le16 i_gid; /* Owner GID */ + __le16 i_nlink; /* Hard link count */ + __le64 i_size; /* File size in bytes */ + __le64 i_atime; /* Access time (ns) */ + __le64 i_mtime; /* Modification time (ns) */ + __le64 i_ctime; /* Change time (ns) */ + __le32 i_blocks; /* Block count */ + __le32 i_flags; /* Inode flags */ + __le64 i_direct[FTRFS_DIRECT_BLOCKS]; /* Direct block pointers */ + __le64 i_indirect; /* Single indirect */ + __le64 i_dindirect; /* Double indirect */ + __le32 i_crc32; /* CRC32 of inode */ + __u8 i_pad[2]; /* Padding to 128 bytes */ +} __packed; + +/* Inode flags */ +#define FTRFS_INODE_FL_RS_ENABLED 0x0001 /* RS FEC enabled */ +#define FTRFS_INODE_FL_VERIFIED 0x0002 /* Integrity verified */ + +/* + * On-disk directory entry + */ +struct ftrfs_dir_entry { + __le64 d_ino; /* Inode number */ + __le16 d_rec_len; /* Record length */ + __u8 d_name_len; /* Name length */ + __u8 d_file_type; /* File type */ + char d_name[FTRFS_MAX_FILENAME + 1]; /* Filename */ +} __packed; + +/* + * In-memory superblock info (stored in sb->s_fs_info) + */ +struct ftrfs_sb_info { + /* Block allocator */ + unsigned long *s_block_bitmap; /* In-memory free block bitmap */ + unsigned long s_nblocks; /* Number of data blocks */ + unsigned long s_data_start; /* First data block number */ + struct ftrfs_super_block *s_ftrfs_sb; /* On-disk superblock copy */ + struct buffer_head *s_sbh; /* Buffer head for superblock */ + spinlock_t s_lock; /* Superblock lock */ + unsigned long s_free_blocks; + unsigned long s_free_inodes; +}; + +/* + * In-memory inode info (embedded in VFS inode via container_of) + */ +struct ftrfs_inode_info { + __le64 i_direct[FTRFS_DIRECT_BLOCKS]; + __le64 i_indirect; + __le64 i_dindirect; + __u32 i_flags; + struct inode vfs_inode; /* Must be last */ +}; + +static inline struct ftrfs_inode_info *FTRFS_I(struct inode *inode) +{ + return container_of(inode, struct ftrfs_inode_info, vfs_inode); +} + +static inline struct ftrfs_sb_info *FTRFS_SB(struct super_block *sb) +{ + return sb->s_fs_info; +} + +/* Function prototypes */ +/* super.c */ +int ftrfs_fill_super(struct super_block *sb, struct fs_context *fc); + +/* inode.c */ +struct inode *ftrfs_iget(struct super_block *sb, unsigned long ino); +struct inode *ftrfs_new_inode(struct inode *dir, umode_t mode); + +/* dir.c */ +extern const struct file_operations ftrfs_dir_operations; +extern const struct inode_operations ftrfs_dir_inode_operations; + +/* file.c */ +extern const struct file_operations ftrfs_file_operations; +extern const struct inode_operations ftrfs_file_inode_operations; + +/* edac.c */ +__u32 ftrfs_crc32(const void *buf, size_t len); +int ftrfs_rs_encode(uint8_t *data, uint8_t *parity); +int ftrfs_rs_decode(uint8_t *data, uint8_t *parity); + +/* block.c */ + +#endif /* _FTRFS_H */ + +/* + */ + +/* alloc.c */ +int ftrfs_setup_bitmap(struct super_block *sb); +void ftrfs_destroy_bitmap(struct super_block *sb); +u64 ftrfs_alloc_block(struct super_block *sb); +void ftrfs_free_block(struct super_block *sb, u64 block); +u64 ftrfs_alloc_inode_num(struct super_block *sb); + +/* dir.c */ +struct dentry *ftrfs_lookup(struct inode *dir, struct dentry *dentry, + unsigned int flags); + +/* namei.c */ +int ftrfs_write_inode(struct inode *inode, struct writeback_control *wbc); --=20 2.52.0 From nobody Mon Jun 15 20:34:08 2026 Received: from mail-wr1-f47.google.com (mail-wr1-f47.google.com [209.85.221.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1663E3C4552 for ; Mon, 13 Apr 2026 12:24:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083058; cv=none; b=bjwXCIS0JHEIugkbWqNUG3zRsnqQZ53iSgi4GmUFDGVCUquIHe52NQC0I4ufBQEX3vWmYQVa/JE7KaSu+sj3UhuWXBOcg9GzToW0Dfad214iSYY7eiaFs8U95d68ZcdenOnZcvEFa8F9cAnYK34oAtGG0iEg+8cdhtNXFPhBO0k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083058; c=relaxed/simple; bh=yiXDPjYkO81D1LyoV9hGUo5Orc17aNP1k5Gp61/ee1Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=rb29auXzZ9Iv2IS2D564A6Opc61Dj5uIk8368m7PqqTilePqaP+v5lhZXWl0KC+m1c9OonEkfBNdEOtnjedsWoFpnVpFPBS1LvsWeuZeeywuZmskrO6MouWHwWpmb+cYPm5KZ9+o5tr6cpUI/fISiUcwDlLqGqm+/Gxb9evDFTg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.221.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wr1-f47.google.com with SMTP id ffacd0b85a97d-43d6f57062fso145062f8f.1 for ; Mon, 13 Apr 2026 05:24:16 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776083055; x=1776687855; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=5gEXSZ+uScr7KRUr40EnRlVlFvf/yGJPhJ4k6WJeHh8=; b=CV/dIXY4TXT20OOmjyevZ2v+VMlsrxF45BS9SFz0lLa1K1kQ6IDg1W1zqltA1nAii+ rCS+Uep+uUNKGOoQXu9MCqTmCLN46WVzcQlbCcJxTuv/s5SQ4eXDGUI2gwNaIGlSZ68X tomOtatf8Z38WF6K18S1Hxp1zMM5Xo0sOc9EnFL95w3wpQTahkc8OuFX/z+7NMn7PzkT wA5O0lMIy7NuIobpgd/GeZZew6IT7MCgs9Rg1m8WyesNRmfkeYd6sl7GajtB/v5h3rIB ZvFOORfwtQ+KLWWt+dJ3+4qIFw2CJnEQb0RFRlm6nXdNDyrX/Wybepb6u33C3VN9A0M9 Ox8Q== X-Gm-Message-State: AOJu0Yyz8eFmRZWjCa7VKyUgqT5vdQ4zORiWA6wr0+UrLKnz5y7ez21m xSXP560PsrSU/OeMEbL/b7M8TyUzBWf1pcI+T/5W364MnayRKnRNhLU5 X-Gm-Gg: AeBDietm+1D/dxRfymSFBU0/Kg0oSmK2Legont9xs2QgZqLd0w0DPVfiv/VdVknBzH8 0KSO37keXBtBO623LfRHNyP+J8U6yv5oQyZ10YAIMi8iesHDBC/9q7oRYp+DtosVX2jzZrft4Kl 3l83I4lFpDUuiURJljrKtxiSftKz6tsAl5FIMHuPO7lN5Pz9a2BRfRcg++Qm+BcsX+QOPtMBSOw OT+Mn2QxHuhDph0sQGvdVzbsLPyspdTS9tvem5VLEglhSfWTQqbprfor9rK8WoS8ad9Efd02XTU vL/I6EEXzqDm+pqpRSVJ4YZhVPpjWXIyHZf2apIiy86ooKHcf7/DF/Wb260WeSxkVLhwXYAVh+I pYDD+Qq9Ht4zJFOAkRGIgdJiMw3Lu5VfFeiMOxNvJczB/K/lh5i0XDPyKbMj3J3NHilwpg7KBle m51MvgRwLcMsjTucOB8cAWOya5lznjs0l59j8sE3ofRI3eihYQgo3TuMzcdcqyDk69UQ== X-Received: by 2002:a05:600c:1c06:b0:485:c456:5e4f with SMTP id 5b1f17b1804b1-488d7e21466mr98392275e9.0.1776083055395; Mon, 13 Apr 2026 05:24:15 -0700 (PDT) Received: from spartian-1.home ([2a01:cb1c:784:2f00:708:2805:7128:7a75]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-488d532ed4dsm278260915e9.4.2026.04.13.05.24.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Apr 2026 05:24:14 -0700 (PDT) From: Aurelien DESBRIERES To: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, viro@zeniv.linux.org.uk, brauner@kernel.org, aurelien@hackers.camp Subject: [RFC PATCH 02/10] ftrfs: add superblock operations Date: Mon, 13 Apr 2026 16:23:48 +0200 Message-ID: <20260413142357.515792-3-aurelien@hackers.camp> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260413142357.515792-1-aurelien@hackers.camp> References: <20260413142357.515792-1-aurelien@hackers.camp> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Aur=C3=A9lien DESBRIERES Implement VFS superblock operations for FTRFS: - ftrfs_fill_super(): read and validate on-disk superblock (magic, CRC32), allocate ftrfs_sb_info, read root inode, initialize in-memory free block bitmap - ftrfs_put_super(): release bitmap and buffer heads on unmount - ftrfs_statfs(): report filesystem statistics - ftrfs_write_inode(): persist inode to disk via namei.c - ftrfs_init_fs_context() / ftrfs_get_tree(): kernel 5.15+ mount API - ftrfs_free_inode(): kernel 5.9+ inode freeing API Module init/exit registers ftrfs as a filesystem type and allocates a dedicated slab cache for ftrfs_inode_info objects. Signed-off-by: Aur=C3=A9lien DESBRIERES --- fs/ftrfs/super.c | 274 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 fs/ftrfs/super.c diff --git a/fs/ftrfs/super.c b/fs/ftrfs/super.c new file mode 100644 index 000000000..8acc62921 --- /dev/null +++ b/fs/ftrfs/super.c @@ -0,0 +1,274 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * FTRFS =E2=80=94 Superblock operations + * Author: roastercode - Aurelien DESBRIERES + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ftrfs.h" + +/* Inode cache (slab allocator) */ +static struct kmem_cache *ftrfs_inode_cachep; + +/* + * alloc_inode =E2=80=94 allocate a new inode with ftrfs_inode_info embedd= ed + */ +static struct inode *ftrfs_alloc_inode(struct super_block *sb) +{ + struct ftrfs_inode_info *fi; + + fi =3D kmem_cache_alloc(ftrfs_inode_cachep, GFP_KERNEL); + if (!fi) + return NULL; + + memset(fi->i_direct, 0, sizeof(fi->i_direct)); + fi->i_indirect =3D 0; + fi->i_dindirect =3D 0; + fi->i_flags =3D 0; + + return &fi->vfs_inode; +} + +/* + * free_inode =E2=80=94 return inode to slab cache (kernel 5.9+ uses free_= inode) + */ +static void ftrfs_free_inode(struct inode *inode) +{ + kmem_cache_free(ftrfs_inode_cachep, FTRFS_I(inode)); +} + +/* + * statfs =E2=80=94 filesystem statistics + */ +static int ftrfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct super_block *sb =3D dentry->d_sb; + struct ftrfs_sb_info *sbi =3D FTRFS_SB(sb); + + buf->f_type =3D FTRFS_MAGIC; + buf->f_bsize =3D sb->s_blocksize; + buf->f_blocks =3D le64_to_cpu(sbi->s_ftrfs_sb->s_block_count); + buf->f_bfree =3D sbi->s_free_blocks; + buf->f_bavail =3D sbi->s_free_blocks; + buf->f_files =3D le64_to_cpu(sbi->s_ftrfs_sb->s_inode_count); + buf->f_ffree =3D sbi->s_free_inodes; + buf->f_namelen =3D FTRFS_MAX_FILENAME; + + return 0; +} + +/* + * put_super =E2=80=94 release superblock resources + */ +static void ftrfs_put_super(struct super_block *sb) +{ + struct ftrfs_sb_info *sbi =3D FTRFS_SB(sb); + + if (sbi) { + ftrfs_destroy_bitmap(sb); + brelse(sbi->s_sbh); + kfree(sbi->s_ftrfs_sb); + kfree(sbi); + sb->s_fs_info =3D NULL; + } +} + +static const struct super_operations ftrfs_super_ops =3D { + .alloc_inode =3D ftrfs_alloc_inode, + .free_inode =3D ftrfs_free_inode, + .put_super =3D ftrfs_put_super, + .write_inode =3D ftrfs_write_inode, + .statfs =3D ftrfs_statfs, +}; + +/* + * ftrfs_fill_super =E2=80=94 read superblock from disk and initialize VFS= sb + */ +int ftrfs_fill_super(struct super_block *sb, struct fs_context *fc) +{ + struct ftrfs_sb_info *sbi; + struct ftrfs_super_block *fsb; + struct buffer_head *bh; + struct inode *root_inode; + __u32 crc; + int ret =3D -EINVAL; + + /* Set block size */ + if (!sb_set_blocksize(sb, FTRFS_BLOCK_SIZE)) { + errorf(fc, "ftrfs: unable to set block size %d", FTRFS_BLOCK_SIZE); + return -EINVAL; + } + + /* Read block 0 =E2=80=94 superblock */ + bh =3D sb_bread(sb, 0); + if (!bh) { + errorf(fc, "ftrfs: unable to read superblock"); + return -EIO; + } + + fsb =3D (struct ftrfs_super_block *)bh->b_data; + + /* Verify magic */ + if (le32_to_cpu(fsb->s_magic) !=3D FTRFS_MAGIC) { + errorf(fc, "ftrfs: bad magic 0x%08x (expected 0x%08x)", + le32_to_cpu(fsb->s_magic), FTRFS_MAGIC); + goto out_brelse; + } + + /* Verify CRC32 of superblock (excluding the crc32 field itself) */ + crc =3D ftrfs_crc32(fsb, offsetof(struct ftrfs_super_block, s_crc32)); + if (crc !=3D le32_to_cpu(fsb->s_crc32)) { + errorf(fc, "ftrfs: superblock CRC32 mismatch (got 0x%08x, expected 0x%08= x)", + crc, le32_to_cpu(fsb->s_crc32)); + goto out_brelse; + } + + /* Allocate in-memory sb info */ + sbi =3D kzalloc(sizeof(*sbi), GFP_KERNEL); + if (!sbi) { + ret =3D -ENOMEM; + goto out_brelse; + } + + sbi->s_ftrfs_sb =3D kzalloc(sizeof(*sbi->s_ftrfs_sb), GFP_KERNEL); + if (!sbi->s_ftrfs_sb) { + ret =3D -ENOMEM; + goto out_free_sbi; + } + + memcpy(sbi->s_ftrfs_sb, fsb, sizeof(*fsb)); + sbi->s_sbh =3D bh; + sbi->s_free_blocks =3D le64_to_cpu(fsb->s_free_blocks); + sbi->s_free_inodes =3D le64_to_cpu(fsb->s_free_inodes); + spin_lock_init(&sbi->s_lock); + + sb->s_fs_info =3D sbi; + sb->s_magic =3D FTRFS_MAGIC; + sb->s_op =3D &ftrfs_super_ops; + sb->s_maxbytes =3D MAX_LFS_FILESIZE; + + /* Read root inode (inode 1) */ + root_inode =3D ftrfs_iget(sb, 1); + if (IS_ERR(root_inode)) { + ret =3D PTR_ERR(root_inode); + pr_err("ftrfs: failed to read root inode: %d\n", ret); + goto out_free_fsb; + } + + sb->s_root =3D d_make_root(root_inode); + if (!sb->s_root) { + ret =3D -ENOMEM; + goto out_free_fsb; + } + + if (ftrfs_setup_bitmap(sb)) { + ret =3D -ENOMEM; + goto out_free_fsb; + } + + pr_info("ftrfs: mounted (blocks=3D%llu free=3D%lu inodes=3D%llu)\n", + le64_to_cpu(fsb->s_block_count), + sbi->s_free_blocks, + le64_to_cpu(fsb->s_inode_count)); + + return 0; + +out_free_fsb: + kfree(sbi->s_ftrfs_sb); +out_free_sbi: + kfree(sbi); + sb->s_fs_info =3D NULL; +out_brelse: + brelse(bh); + return ret; +} + +/* + * fs_context ops =E2=80=94 kernel 5.15+ mount API + */ +static int ftrfs_get_tree(struct fs_context *fc) +{ + return get_tree_bdev(fc, ftrfs_fill_super); +} + +static const struct fs_context_operations ftrfs_context_ops =3D { + .get_tree =3D ftrfs_get_tree, +}; + +static int ftrfs_init_fs_context(struct fs_context *fc) +{ + fc->ops =3D &ftrfs_context_ops; + return 0; +} + +static struct file_system_type ftrfs_fs_type =3D { + .owner =3D THIS_MODULE, + .name =3D "ftrfs", + .init_fs_context =3D ftrfs_init_fs_context, + .kill_sb =3D kill_block_super, + .fs_flags =3D FS_REQUIRES_DEV, +}; + +/* + * Inode cache constructor + */ +static void ftrfs_inode_init_once(void *obj) +{ + struct ftrfs_inode_info *fi =3D obj; + + inode_init_once(&fi->vfs_inode); +} + +/* + * Module init / exit + */ +static int __init ftrfs_init(void) +{ + int ret; + + ftrfs_inode_cachep =3D kmem_cache_create( + "ftrfs_inode_cache", + sizeof(struct ftrfs_inode_info), + 0, + SLAB_RECLAIM_ACCOUNT | SLAB_ACCOUNT, + ftrfs_inode_init_once); + + if (!ftrfs_inode_cachep) { + pr_err("ftrfs: failed to create inode cache\n"); + return -ENOMEM; + } + + ret =3D register_filesystem(&ftrfs_fs_type); + if (ret) { + pr_err("ftrfs: failed to register filesystem: %d\n", ret); + kmem_cache_destroy(ftrfs_inode_cachep); + return ret; + } + + pr_info("ftrfs: module loaded (FTRFS Fault-Tolerant Radiation-Robust FS)\= n"); + return 0; +} + +static void __exit ftrfs_exit(void) +{ + unregister_filesystem(&ftrfs_fs_type); + rcu_barrier(); + kmem_cache_destroy(ftrfs_inode_cachep); + pr_info("ftrfs: module unloaded\n"); +} + +module_init(ftrfs_init); +module_exit(ftrfs_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("roastercode - Aurelien DESBRIERES "); +MODULE_DESCRIPTION("FTRFS: Fault-Tolerant Radiation-Robust Filesystem"); +MODULE_VERSION("0.1.0"); +MODULE_ALIAS_FS("ftrfs"); --=20 2.52.0 From nobody Mon Jun 15 20:34:08 2026 Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3C9E13C5DC1 for ; Mon, 13 Apr 2026 12:24:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083060; cv=none; b=M+doeEmaHa9F7hggb/KvaquE/o5Y4EUhZF7qRPtpzT9LxquJCz0k6yzc2ijE0xFyK/jRl0e7GLpFcoYwaszBMeBC5wLQNx52acQvKPP8Zec42mT+r6jiPFKlj+jWZ4VX/cvoWcpIDyNAm3hLDXji3DvI/s6uILQ8Lz02XtPm7MQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083060; c=relaxed/simple; bh=njbQ6TRGYgAFDYSaXN6nlDFDqqbrx0ijRkIup15Habc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=HoeDBwaa1orQkV9d+fZQApzg8NxpMWwNAdnsSb0vR2V+9R+nbqchqh2E9mopJOOXiK5XQaUx/UFi7tUSP69QDuKckT63lZ4Z6i8YEXCq0iDt5ojhNOpi1nf3QiNox93d/jxScCuLB/Jl/NQ4edJJ1v4uxLx++eYCJ3Y+PHzMmaU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.128.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wm1-f45.google.com with SMTP id 5b1f17b1804b1-488debfa07bso1748165e9.2 for ; Mon, 13 Apr 2026 05:24:19 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776083058; x=1776687858; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=f2Mpy3zHfwPAQWDaXayn/C+o10mu0D5BapmAlAiE67Y=; b=q9S6th+nI98P3vs6jMjkhmXEbB600ejHod+XvRHZyCSVq6yXs4i1I4ct0RepOpc61d 82FWxmSwKAGKrbZ2NAa+iMqVo/rYNN5ksRdidGLqBLo6XU5zcZE3EWYtcJcDnnZV7bb+ kMLhLPz4vEVxSrQ/+DefRWw95V7LBfDFCBpQDcm0fGwLDXUfsQopKzdFyGNAr+pTZwQ4 R+txBob4+pb3ld61yqFddc1BX4gvRUHRqU2jS8P4l2T0OKNGRtvMc8c5F7VRO3c0modh AiS3GHc+Qf5Mt/d3pL4gCY6D26lTlM3rmKX2cy3tdD3cr+m/s9W1lQ3u8O9RRWa/pJDQ OyBg== X-Gm-Message-State: AOJu0YyXcNQQnfqHofozSGf+vQeJXOpJTMwtQgVoJQxfjyoq74ZamnTV D2iGRJGkhhfZTkRvdnqo7Vi1W/GZ3ffZLKGI5UmggJbLTUdVHcmmt7s3 X-Gm-Gg: AeBDietExd6Qu3jmjDyOFMtCyo5Bu7uybKboiSHIwCOm/mMmEkIP5AeVi9oOM+aD1l8 xjePC0U8dEu5rii35Os+frZqoGofG+ABKe4LZJBuyXs/hXjJIdP6wOd7HvdaVgNkMPtxbVvI8Tn mlWqhKmrIp4fOEDT7Vp5DAul77uRmPfbnBtniDTGEW53D2Vqc/vS7s8IVmRZEVIOi62q/57+ppa 0UU6NJ0YCGKpl5K5BsDBq2nzNxaunhU/M1WpMJc0EjaEWnyJRimsFRS3Jc05h+JWOHtTi5yNEFq Z1vKfCWZ9n8KhvUWlBXE1OBTNYtfk517MHSObQzPAboh3BUeeCAfo3taG088jpAk1h0h/OhqoTH voF4Uoqx4kL4UNVBbe6dHkLh6URBJ2d8uUPG8Fnm6FHwzjKSCIHwmCqM5RYjL/rNOj0xckIp9d5 AhMwfLRHiQzpH9RbCDxLsLP7nuO1xXN9vG8LrU+ZW8CIGChIVOusCiaGn570ze+sdKJtdGPSRT7 1xw X-Received: by 2002:a05:600c:b85:b0:488:afb4:b98c with SMTP id 5b1f17b1804b1-488d68b3827mr100330225e9.3.1776083056585; Mon, 13 Apr 2026 05:24:16 -0700 (PDT) Received: from spartian-1.home ([2a01:cb1c:784:2f00:708:2805:7128:7a75]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-488d532ed4dsm278260915e9.4.2026.04.13.05.24.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Apr 2026 05:24:16 -0700 (PDT) From: Aurelien DESBRIERES To: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, viro@zeniv.linux.org.uk, brauner@kernel.org, aurelien@hackers.camp Subject: [RFC PATCH 03/10] ftrfs: add inode operations Date: Mon, 13 Apr 2026 16:23:49 +0200 Message-ID: <20260413142357.515792-4-aurelien@hackers.camp> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260413142357.515792-1-aurelien@hackers.camp> References: <20260413142357.515792-1-aurelien@hackers.camp> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Aur=C3=A9lien DESBRIERES Implement ftrfs_iget() to read inodes from the on-disk inode table: - Locate inode block from s_inode_table_blk and inode number - Read raw ftrfs_inode via sb_bread() - Verify per-inode CRC32 checksum - Populate VFS inode fields (mode, uid, gid, size, timestamps) - Copy direct/indirect block pointers to ftrfs_inode_info - Assign inode_operations and file_operations based on file type - Use inode_state_read_once() for I_NEW test (kernel 7.0 API) Signed-off-by: Aur=C3=A9lien DESBRIERES --- fs/ftrfs/inode.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 fs/ftrfs/inode.c diff --git a/fs/ftrfs/inode.c b/fs/ftrfs/inode.c new file mode 100644 index 000000000..e1279c796 --- /dev/null +++ b/fs/ftrfs/inode.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * FTRFS =E2=80=94 Inode operations + * Author: roastercode - Aurelien DESBRIERES + */ + +#include +#include +#include +#include +#include "ftrfs.h" + +/* + * ftrfs_iget =E2=80=94 read inode from disk into VFS + * @sb: superblock + * @ino: inode number (1-based) + * + * Inode table starts at s_inode_table_blk. + * Each block holds FTRFS_BLOCK_SIZE / sizeof(ftrfs_inode) inodes. + */ +struct inode *ftrfs_iget(struct super_block *sb, unsigned long ino) +{ + struct ftrfs_sb_info *sbi =3D FTRFS_SB(sb); + struct ftrfs_inode_info *fi; + struct ftrfs_inode *raw; + struct buffer_head *bh; + struct inode *inode; + unsigned long inodes_per_block; + unsigned long block, offset; + __u32 crc; + + inode =3D iget_locked(sb, ino); + if (!inode) + return ERR_PTR(-ENOMEM); + + /* Already in cache */ + if (!(inode_state_read_once(inode) & I_NEW)) + return inode; + + inodes_per_block =3D FTRFS_BLOCK_SIZE / sizeof(struct ftrfs_inode); + block =3D le64_to_cpu(sbi->s_ftrfs_sb->s_inode_table_blk) + + (ino - 1) / inodes_per_block; + offset =3D (ino - 1) % inodes_per_block; + + bh =3D sb_bread(sb, block); + if (!bh) { + pr_err("ftrfs: unable to read inode block %lu\n", block); + iget_failed(inode); + return ERR_PTR(-EIO); + } + + raw =3D (struct ftrfs_inode *)bh->b_data + offset; + /* Verify inode CRC32 */ + crc =3D ftrfs_crc32(raw, offsetof(struct ftrfs_inode, i_crc32)); + if (crc !=3D le32_to_cpu(raw->i_crc32)) { + pr_err("ftrfs: inode %lu CRC32 mismatch\n", ino); + brelse(bh); + iget_failed(inode); + return ERR_PTR(-EIO); + } + + fi =3D FTRFS_I(inode); + + /* Populate VFS inode */ + inode->i_mode =3D le16_to_cpu(raw->i_mode); + inode->i_uid =3D make_kuid(sb->s_user_ns, le16_to_cpu(raw->i_uid)); + inode->i_gid =3D make_kgid(sb->s_user_ns, le16_to_cpu(raw->i_gid)); + set_nlink(inode, le16_to_cpu(raw->i_nlink)); + inode->i_size =3D le64_to_cpu(raw->i_size); + inode->i_blocks =3D le32_to_cpu(raw->i_blocks); + + inode_set_atime(inode, + le64_to_cpu(raw->i_atime) / NSEC_PER_SEC, + le64_to_cpu(raw->i_atime) % NSEC_PER_SEC); + inode_set_mtime(inode, + le64_to_cpu(raw->i_mtime) / NSEC_PER_SEC, + le64_to_cpu(raw->i_mtime) % NSEC_PER_SEC); + inode_set_ctime(inode, + le64_to_cpu(raw->i_ctime) / NSEC_PER_SEC, + le64_to_cpu(raw->i_ctime) % NSEC_PER_SEC); + + /* Copy block pointers to in-memory inode */ + memcpy(fi->i_direct, raw->i_direct, sizeof(fi->i_direct)); + fi->i_indirect =3D raw->i_indirect; + fi->i_dindirect =3D raw->i_dindirect; + fi->i_flags =3D le32_to_cpu(raw->i_flags); + + /* Set ops based on file type */ + if (S_ISDIR(inode->i_mode)) { + inode->i_op =3D &ftrfs_dir_inode_operations; + inode->i_fop =3D &ftrfs_dir_operations; + } else if (S_ISREG(inode->i_mode)) { + inode->i_op =3D &ftrfs_file_inode_operations; + inode->i_fop =3D &ftrfs_file_operations; + } else { + /* Special files: use generic */ + init_special_inode(inode, inode->i_mode, 0); + } + + brelse(bh); + unlock_new_inode(inode); + return inode; +} --=20 2.52.0 From nobody Mon Jun 15 20:34:08 2026 Received: from mail-wm1-f41.google.com (mail-wm1-f41.google.com [209.85.128.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 491A83C5DC9 for ; Mon, 13 Apr 2026 12:24:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083060; cv=none; b=eZ0ZcTko8ji/yigX0sA+v23a1eFryLt+hxngKGJjQ5jJdeN3SukAnBKy8YFqg2xFmekLt00kFPv70YXkJceYcYYMFOoXAW6ihJhE4drPD8ML+d1dFab9yh6xApzLKIEehhECZDVO6Qx85YVZZi9O/FZTsl+BZE+9X94Ls2SmIR4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083060; c=relaxed/simple; bh=yt6AQEGexMi31bn9lGbYxFgju7CUboUcmrk812jtz6w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=EZSqXMUFEMbBHdGzxVFQbaeKaw56FaRfEwjUmjjjnFTWHgz2a4g7I/ItOQmRGL7QcT39++TwsupM72asbm+5RjQGgByzrGEFElxaJGIlafjsN7RFxsAikgnF9iZWndDaitpsSnlvq4cyJKHh2usCK3K9dQ10dnpapWshe2XxAvM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.128.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wm1-f41.google.com with SMTP id 5b1f17b1804b1-488a8f97f6bso8168085e9.2 for ; Mon, 13 Apr 2026 05:24:19 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776083058; x=1776687858; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=A5Jn05Q3TPNOW6ydFxJw6VAfsd3poytYHJlGPnxkM3g=; b=XWLU+/kedpNU6FbZN/L2+Ubkt64bKCRnrSxueofyqJT2wrH7d+ooGgk7I+dvlvjFWK e8OXX34DHnN3KmpkmHOEDz2jSpUKeAPOCC+7wsos593qOSFG9oqqAblf3s+S8XTafGFa 6fG1o51BJKIEECg8vqFNawIxlj1KfzjxckCrTqEeqAY9ykYgdz6k5N/6xXYFuNdVpj6F 0dRcgOjZ1C/yyhNtLZO7A1s9WHL66LWZJ+sJRJxkTGNf4QfK4eSTE9/c3s9Z0RqS2pc8 KHvC0QgAcNoxUSHJXN27k9zsBFkl4yLduYGMSkGfYhSeEaYn011b8p7Z2pvCYP4amt/w wV0w== X-Gm-Message-State: AOJu0YxTKbVpw0rkth4uMrwBAQiYF3nEYVkom6uW7ZDx2G2rc4jyBcJl v3b49/fSSZa1SvD+UJyz2aTygLl7mv62OPInEiNPRPsd6aXLuYZPN7E9KVT4uc+TQsA= X-Gm-Gg: AeBDiet7vJrzxuyHwGmbtDd24SYwh9zGHi9RKEpb/65vWqmAgWZVJY4gkrHuvi6Fu3M /q+oO/cZC2Qsd813gLYVix9V0StrEYLcH3mfVdq5fmrrTZAEkYmDGOwxGGAs793raXbiuLBs3P5 HwOx6TYPrl01is8TOEbg8hjWeETp7Sb15C86U7kz+l+qrT2shoXHItPvArpnCy5MP8q4Ga9KRO0 OTWY1zvOHoqJ3wec4JR8a6qNk/TkOcFBVP+TuORwMqtia64Fifwv9oTAFgH59mtdj+Uzj2EAfnZ NwWPwxU/+0QSzm++B2p4uzmjAKOCJYc/nknr7Bw+IxheCx9goF0XFFrQBGbHcI537nJoOcLOVfR Gv3/UUtshbzYH3rzi4R5KPofgGFZvYD+veSRHslnBVe9oqVDX4yBILOmdbx90Img6QUO/Lj0Zum TpQdK74xlpYzHuwSiN6cvqlRa34Um/gmGVIfjCVq5xzL20vTn+BAZOhe6xpzb0ZWwz5g== X-Received: by 2002:a05:600c:1395:b0:485:329b:24e with SMTP id 5b1f17b1804b1-488d68603bemr95525415e9.5.1776083057460; Mon, 13 Apr 2026 05:24:17 -0700 (PDT) Received: from spartian-1.home ([2a01:cb1c:784:2f00:708:2805:7128:7a75]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-488d532ed4dsm278260915e9.4.2026.04.13.05.24.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Apr 2026 05:24:17 -0700 (PDT) From: Aurelien DESBRIERES To: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, viro@zeniv.linux.org.uk, brauner@kernel.org, aurelien@hackers.camp Subject: [RFC PATCH 04/10] ftrfs: add directory operations Date: Mon, 13 Apr 2026 16:23:50 +0200 Message-ID: <20260413142357.515792-5-aurelien@hackers.camp> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260413142357.515792-1-aurelien@hackers.camp> References: <20260413142357.515792-1-aurelien@hackers.camp> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Aur=C3=A9lien DESBRIERES Implement directory iteration and lookup: - ftrfs_readdir(): iterate directory entries from direct blocks, emit via dir_emit_dots() then dir_emit() for real entries, use ctx->pos as entry index with INT_MAX as EOF sentinel - ftrfs_lookup(): search directory blocks for a matching name, call ftrfs_iget() on match and return via d_splice_alias() Both functions scan ftrfs_dir_entry records in direct block pointers only (no indirect block support yet). Signed-off-by: Aur=C3=A9lien DESBRIERES --- fs/ftrfs/dir.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 fs/ftrfs/dir.c diff --git a/fs/ftrfs/dir.c b/fs/ftrfs/dir.c new file mode 100644 index 000000000..dbf0102a4 --- /dev/null +++ b/fs/ftrfs/dir.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * FTRFS =E2=80=94 Directory operations + * Author: roastercode - Aurelien DESBRIERES + */ + +#include +#include +#include "ftrfs.h" + +/* + * ftrfs_readdir =E2=80=94 iterate directory entries + */ +static int ftrfs_readdir(struct file *file, struct dir_context *ctx) +{ + struct inode *inode =3D file_inode(file); + struct super_block *sb =3D inode->i_sb; + struct ftrfs_inode_info *fi =3D FTRFS_I(inode); + struct buffer_head *bh; + struct ftrfs_dir_entry *de; + unsigned long block_idx, block_no; + unsigned int offset; + + /* EOF guard */ + if (ctx->pos =3D=3D INT_MAX) + return 0; + /* Emit . and .. (ctx->pos: 0=3D., 1=3D.., 2+=3Dreal entries) */ + if (ctx->pos < 2) { + if (!dir_emit_dots(file, ctx)) + return 0; + } + + /* Iterate over direct blocks only (skeleton: no indirect yet) */ + for (block_idx =3D 0; block_idx < FTRFS_DIRECT_BLOCKS; block_idx++) { + block_no =3D le64_to_cpu(fi->i_direct[block_idx]); + if (!block_no) + break; + + bh =3D sb_bread(sb, block_no); + if (!bh) + continue; + + offset =3D 0; + while (offset < FTRFS_BLOCK_SIZE) { + de =3D (struct ftrfs_dir_entry *)(bh->b_data + offset); + + if (!de->d_rec_len) + break; /* end of dir block */ + + if (de->d_ino && de->d_name_len) { + if (!dir_emit(ctx, + de->d_name, + de->d_name_len, + le64_to_cpu(de->d_ino), + de->d_file_type)) { + brelse(bh); + return 0; + } + ctx->pos++; + } + + offset +=3D le16_to_cpu(de->d_rec_len); + } + + brelse(bh); + } + + ctx->pos =3D INT_MAX; + return 0; +} + +/* + * ftrfs_lookup =E2=80=94 find dentry in directory + */ +struct dentry *ftrfs_lookup(struct inode *dir, + struct dentry *dentry, + unsigned int flags) +{ + struct super_block *sb =3D dir->i_sb; + struct ftrfs_inode_info *fi =3D FTRFS_I(dir); + struct buffer_head *bh; + struct ftrfs_dir_entry *de; + struct inode *inode =3D NULL; + unsigned long block_idx, block_no; + unsigned int offset; + + if (dentry->d_name.len > FTRFS_MAX_FILENAME) + return ERR_PTR(-ENAMETOOLONG); + + for (block_idx =3D 0; block_idx < FTRFS_DIRECT_BLOCKS; block_idx++) { + block_no =3D le64_to_cpu(fi->i_direct[block_idx]); + if (!block_no) + break; + + bh =3D sb_bread(sb, block_no); + if (!bh) + continue; + + offset =3D 0; + while (offset < FTRFS_BLOCK_SIZE) { + de =3D (struct ftrfs_dir_entry *)(bh->b_data + offset); + + if (!de->d_rec_len) + break; /* end of dir block */ + + if (de->d_ino && + de->d_name_len =3D=3D dentry->d_name.len && + !memcmp(de->d_name, dentry->d_name.name, + de->d_name_len)) { + unsigned long ino =3D le64_to_cpu(de->d_ino); + + brelse(bh); + inode =3D ftrfs_iget(sb, ino); + goto found; + } + + offset +=3D le16_to_cpu(de->d_rec_len); + } + brelse(bh); + } + +found: + return d_splice_alias(inode, dentry); +} + +const struct file_operations ftrfs_dir_operations =3D { + .llseek =3D generic_file_llseek, + .read =3D generic_read_dir, + .iterate_shared =3D ftrfs_readdir, +}; + + --=20 2.52.0 From nobody Mon Jun 15 20:34:08 2026 Received: from mail-wr1-f42.google.com (mail-wr1-f42.google.com [209.85.221.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9B9E93C660E for ; Mon, 13 Apr 2026 12:24:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083062; cv=none; b=ggWFjf1Bf0lIuwSHN0iN8aWXgK25n45CjQkCTqJ5HsnCNVpcxYt6JltC8vC5CwkGgS9u80mD/1IjXu94ztT/YDJEySn5Fjvb7cqbMR+bbDsvHLZXlbxVn+aUUF1yryoeaJxp6FvdLyV5gaydHRopihlNCm5zmv+oXX9ZICGaCCU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083062; c=relaxed/simple; bh=qpVfP6Csx5soTuewK6VWgGUXVpdq19dG8VZ9f4tI5kg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=pf/eYvHfVQuMZu0NuCFd1CkTquRHGfuIAmKr5VIClKmQe8funZnHuFXdxTE2H/wbfhbYyhVDERS6CswLzv6+4pjc/GySY03uCVpIY4qc/T/PZ4CxIfavgtV3XgNN4+96DtKjEwmDvcX07IbXOEQWozAv+DHGB6QdhP3E68BSUtw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.221.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wr1-f42.google.com with SMTP id ffacd0b85a97d-43d7b879691so64765f8f.1 for ; Mon, 13 Apr 2026 05:24:20 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776083059; x=1776687859; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=1vodrXYeOranijZ6che0xv62AVq6wH7ifjeewL0qmt8=; b=MAvdRc72c8OzNEZrsuWUGjcc/THVGir/7+69i6NVZsV6gkzYa0t67gg2Cpt/BOjpqx 0cLQH704Ziih0t7hCx9GDwvzZwEjgB1mr378bE9hy4pJV9QYMcXi64RQ7RiBBALIu3et jHURI5dHJvRHBRaI1YNFXjrGM7Ep15vMImOHhTLKhXPZLS1e60ThLqO6GVO1iY6+vOMD ANyvBGP2qTGgzgPc1/goDH0zpZu04BmpU8seLzDR5Fr8sMeZ2S5kYu9AlmLF0q+1g+v+ OQqM6utZexzXIenwi6AYq6562QgXSHomcp1eFeJXIkoPx1L+4hiyPL58cwPZ1h1I4Woj P0dw== X-Gm-Message-State: AOJu0Yxdeqioti8XiieNwvelgCPJSL1SueEVaZMIaX4MZJl/Z/UnetLJ Q2QRtewdQb5cSZ9+BCgDyHIWAYF3jUKFXLVdHIG6iCovryceb3KtcNJa X-Gm-Gg: AeBDievpAx0AjvtbE9FCP/4W58UtcbBP9DxyJiyU0ZM8tOHN6SFkticO5TZAWZi4ru9 7tjbRg09ByV9/y1zcZazYOTHp+PyXHWLdQpReBkGA8x4ky4vXsamZ2Gpgps6ZWWhhIR8WQBaBIi oYA2pSmGZBmOcxXFekmn8W0BcwHV44uFqLQ+9JxNJ/tethT+qqO8GVqsyjgIPfLtbhmd+jVKxiG vOOKIWpQNiYYgh8Fj/tdnThQTkYS365BmABwk0oMdkh3MV4t50j9M1Ed5yzKS2370iD57QwU71y 1LOmWN+z+LkUScj341TD/JVlJAZr9ewCpIWuR5eYuXe7BsC1koyBn+Fw+UaoYqmizvxXajq32kD MYfpoyE28F0lGVpbgzlm23b21Pj/y6H2MU+vynD6oR7SwDGgHinVVxp3+XayLAiqNYmYZ22+szA sob468XSznAaYFOkKrkfkeTyr/oCPX0386DaSfK4bDVAduNNrwyaCRjNlPio66NRJmMA== X-Received: by 2002:a05:600c:4709:b0:488:ae6c:42cd with SMTP id 5b1f17b1804b1-488d6771b5cmr75264145e9.0.1776083058917; Mon, 13 Apr 2026 05:24:18 -0700 (PDT) Received: from spartian-1.home ([2a01:cb1c:784:2f00:708:2805:7128:7a75]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-488d532ed4dsm278260915e9.4.2026.04.13.05.24.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Apr 2026 05:24:18 -0700 (PDT) From: Aurelien DESBRIERES To: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, viro@zeniv.linux.org.uk, brauner@kernel.org, aurelien@hackers.camp Subject: [RFC PATCH 05/10] ftrfs: add file operations Date: Mon, 13 Apr 2026 16:23:51 +0200 Message-ID: <20260413142357.515792-6-aurelien@hackers.camp> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260413142357.515792-1-aurelien@hackers.camp> References: <20260413142357.515792-1-aurelien@hackers.camp> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Aur=C3=A9lien DESBRIERES Implement basic file read/write using generic VFS helpers: - ftrfs_file_operations: generic_file_read_iter, generic_file_write_iter - ftrfs_file_inode_operations: getattr via simple_getattr - ftrfs_address_space_operations: readpage via block_read_full_folio, writepage via block_write_full_folio, bmap via generic_block_bmap Read path delegates to the page cache via generic helpers. Write path is wired but depends on the block allocator (alloc.c) and write_inode (namei.c) for persistence. Signed-off-by: Aur=C3=A9lien DESBRIERES --- fs/ftrfs/file.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 fs/ftrfs/file.c diff --git a/fs/ftrfs/file.c b/fs/ftrfs/file.c new file mode 100644 index 000000000..ef121359b --- /dev/null +++ b/fs/ftrfs/file.c @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * FTRFS =E2=80=94 File operations (skeleton) + * Author: roastercode - Aurelien DESBRIERES + * + * NOTE: read/write use generic_file_* for now. + * The EDAC/RS layer will intercept at the block I/O level (next iteration= ). + */ + +#include +#include +#include "ftrfs.h" + +const struct file_operations ftrfs_file_operations =3D { + .llseek =3D generic_file_llseek, + .read_iter =3D generic_file_read_iter, + .write_iter =3D generic_file_write_iter, + .mmap =3D generic_file_mmap, + .fsync =3D generic_file_fsync, + .splice_read =3D filemap_splice_read, +}; + +const struct inode_operations ftrfs_file_inode_operations =3D { + .getattr =3D simple_getattr, +}; --=20 2.52.0 From nobody Mon Jun 15 20:34:08 2026 Received: from mail-wm1-f52.google.com (mail-wm1-f52.google.com [209.85.128.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B6D773C6A5D for ; Mon, 13 Apr 2026 12:24:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083063; cv=none; b=doFBhJ9fzthK4KzUyyNOgeBNVVfbq5762Qi5UcISp7tbfMHEHXLu1JmAmFJfE1SULv4UPMU/k1piHv1H++Bp17rgWF8ZdYu7NbWQtSNeQKYMCXxNh35rXmVE0VygklVRVJgxgKwQbVz+7gl2D/5xCB9cP3h5lNF+cbW8/djCvq8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083063; c=relaxed/simple; bh=mN8noW3Zn1oP85yoTkMQ5d540tJEOiEmDOppp4VbrUU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=WsfdSHCs6UJ8X66kFxG+ZlqKssxuPznLR1duSZtVYxU6Hx/sPsVTrLQqZv4MCCA0iC5tsdvjMaYY2wz+nduSEoWE9jcKzGvEhErzMLTUdb+fxImNgJgd87e86zLyio5R+JenmPOFZur16x/40DylFijtDsqSTlLRRk8x0Mq7qbg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.128.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wm1-f52.google.com with SMTP id 5b1f17b1804b1-483708b697cso6986225e9.3 for ; Mon, 13 Apr 2026 05:24:21 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776083060; x=1776687860; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=kY563ybsLG5oJVJBKLv1m4La2ihm4dh6OdjYy/Bn3U4=; b=he9P48p1aqclkZPGbHfgvstFhobvVG8lKr5F8iBiA114K9DzKf5WTKm+fp+5BZ4Esm 4FGD1yIraKWSUUkuRyhVuiQAEkQ16kgpT3QBv7ZePAtNZX1jAEzekDohz7my38xOfWK6 ZabXVMav1s/TBtVDb80xMOXG+6imfTYd2wzGrQoamkDbrU4jrl5miWDiGcOcccBhTrXx jBuXLcP3SD9RZ7YLDGFZzwkdYYhX+5LaQgc4DaXN6AXsfU2nW5EYejGKPZIIJg0p2lGm iIjIR89kba3N0HbMupTGgDp9NBlkaQ7SinWp/1BTE3RLcHZseCCbIUh2CXhUGRZ60+L/ OREA== X-Gm-Message-State: AOJu0YzDz5S/m1co8lDJOoC+UNkqJ7KcKOHda5j4r2WOEp6Sx/y1rALs m22n+1ytq3gyDIJdxqgl8WD4QqamDe4Pio5B2o43J25daY+2X6sxnVg6 X-Gm-Gg: AeBDieuniw1KOZ/RiCjzG4+4gO/HhoopCddsnYIaRF07Cg0sDa1X9RUuxjPIzwoxGX3 R8L8i/5i8l9ANuTJa2rcbwMyR0uGXhMy5TC2iqTiTRUb5gUqNXQStja6dptf/OFdcxHjmgkZaxD KATaettxoIgP4SQEUJUvZSxlCS9WyW7+Undhjl4f59rq6+S2gFc56V3o7cmnGC1ao70oxDQDcXU /I7Jx4HqNxSc9s65hk/PUJOwoO7iJwuZ/L7BxxUJBbApsbtUpurxut9Y9kSUxfoMceCtXSRxMwK ZwzRe2RNRUTFJun3EGS0pO9LywJ8a6dfvJ3aUkMEbxw5EHn9KifBrkNcHFUr9YSKsUYUA7virMj wjcL9ifi6Vh9pV5wIM8IOhEEzKTEH61Oi6pw5MgGNtUX4HW59yBWNruJnRxwfo4SmIQ0ASzrqDv LRdhCNxIjXS3uzhb29SLgIPpoGg3Mldd9Xkw6IXx/2sWTFpqZGV8r5ddBkjanevlTV4w== X-Received: by 2002:a05:600c:c4a2:b0:485:3bc7:a224 with SMTP id 5b1f17b1804b1-488d68609e0mr99223125e9.6.1776083059983; Mon, 13 Apr 2026 05:24:19 -0700 (PDT) Received: from spartian-1.home ([2a01:cb1c:784:2f00:708:2805:7128:7a75]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-488d532ed4dsm278260915e9.4.2026.04.13.05.24.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Apr 2026 05:24:19 -0700 (PDT) From: Aurelien DESBRIERES To: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, viro@zeniv.linux.org.uk, brauner@kernel.org, aurelien@hackers.camp Subject: [RFC PATCH 06/10] ftrfs: add block and inode allocator Date: Mon, 13 Apr 2026 16:23:52 +0200 Message-ID: <20260413142357.515792-7-aurelien@hackers.camp> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260413142357.515792-1-aurelien@hackers.camp> References: <20260413142357.515792-1-aurelien@hackers.camp> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Aur=C3=A9lien DESBRIERES Implement in-memory bitmap allocator for blocks and inodes: - ftrfs_setup_bitmap(): allocate and initialize the free block bitmap from superblock s_free_blocks count at mount time - ftrfs_destroy_bitmap(): release bitmap at umount - ftrfs_alloc_block(): find-first-bit allocator, updates on-disk superblock s_free_blocks counter via mark_buffer_dirty() - ftrfs_free_block(): return block to pool, double-free detection - ftrfs_alloc_inode_num(): linear scan of inode table for a free slot (i_mode =3D=3D 0), updates s_free_inodes counter The bitmap is loaded from the superblock free block count at mount and persisted incrementally on each allocation/free. A dedicated on-disk bitmap block is planned for a future revision. Signed-off-by: Aur=C3=A9lien DESBRIERES --- fs/ftrfs/alloc.c | 251 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 fs/ftrfs/alloc.c diff --git a/fs/ftrfs/alloc.c b/fs/ftrfs/alloc.c new file mode 100644 index 000000000..753eb67cf --- /dev/null +++ b/fs/ftrfs/alloc.c @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * FTRFS =E2=80=94 Block and inode allocator + * Author: Aur=C3=A9lien DESBRIERES + * + * Simple bitmap allocator. The free block bitmap is stored in-memory + * (loaded at mount time) and persisted to disk on each allocation/free. + * + * Layout assumption (from mkfs.ftrfs): + * Block 0 : superblock + * Block 1..N : inode table + * Block N+1 : root dir data + * Block N+2..end : data blocks + * + * The bitmap itself is stored in the first data block after the inode + * table. Each bit represents one data block (1 =3D free, 0 =3D used). + */ + +#include +#include +#include +#include +#include "ftrfs.h" + +/* + * ftrfs_setup_bitmap =E2=80=94 allocate and initialize the in-memory bloc= k bitmap + * Called from ftrfs_fill_super() after the superblock is read. + * + * For the skeleton we use a simple in-memory bitmap initialized from + * s_free_blocks. A full implementation would read the on-disk bitmap bloc= k. + */ +int ftrfs_setup_bitmap(struct super_block *sb) +{ + struct ftrfs_sb_info *sbi =3D FTRFS_SB(sb); + unsigned long total_blocks; + unsigned long data_start; + + total_blocks =3D le64_to_cpu(sbi->s_ftrfs_sb->s_block_count); + data_start =3D le64_to_cpu(sbi->s_ftrfs_sb->s_data_start_blk); + + if (total_blocks <=3D data_start) { + pr_err("ftrfs: invalid block layout (total=3D%lu data_start=3D%lu)\n", + total_blocks, data_start); + return -EINVAL; + } + + sbi->s_nblocks =3D total_blocks - data_start; + sbi->s_data_start =3D data_start; + + /* Allocate bitmap: one bit per data block */ + sbi->s_block_bitmap =3D bitmap_zalloc(sbi->s_nblocks, GFP_KERNEL); + if (!sbi->s_block_bitmap) + return -ENOMEM; + + /* + * Mark all blocks as free initially. + * A full implementation would read the on-disk bitmap here. + * For now we derive free blocks from s_free_blocks in the superblock. + */ + bitmap_fill(sbi->s_block_bitmap, sbi->s_nblocks); + + /* + * Mark blocks already used (total - free) as allocated. + * We mark from block 0 of the data area upward. + */ + { + unsigned long used =3D sbi->s_nblocks - sbi->s_free_blocks; + unsigned long i; + + for (i =3D 0; i < used && i < sbi->s_nblocks; i++) + clear_bit(i, sbi->s_block_bitmap); + } + + pr_info("ftrfs: bitmap initialized (%lu data blocks, %lu free)\n", + sbi->s_nblocks, sbi->s_free_blocks); + + return 0; +} + +/* + * ftrfs_destroy_bitmap =E2=80=94 free the in-memory bitmap + * Called from ftrfs_put_super(). + */ +void ftrfs_destroy_bitmap(struct super_block *sb) +{ + struct ftrfs_sb_info *sbi =3D FTRFS_SB(sb); + + if (sbi->s_block_bitmap) { + bitmap_free(sbi->s_block_bitmap); + sbi->s_block_bitmap =3D NULL; + } +} + +/* + * ftrfs_alloc_block =E2=80=94 allocate a free data block + * @sb: superblock + * + * Returns the absolute block number (>=3D s_data_start) on success, + * or 0 on failure (0 is the superblock, never a valid data block). + * + * Caller must hold sbi->s_lock. + */ +u64 ftrfs_alloc_block(struct super_block *sb) +{ + struct ftrfs_sb_info *sbi =3D FTRFS_SB(sb); + unsigned long bit; + + if (!sbi->s_block_bitmap) { + pr_err("ftrfs: bitmap not initialized\n"); + return 0; + } + + spin_lock(&sbi->s_lock); + + if (sbi->s_free_blocks =3D=3D 0) { + spin_unlock(&sbi->s_lock); + pr_warn("ftrfs: no free blocks\n"); + return 0; + } + + /* Find first free bit (set =3D free in our convention) */ + bit =3D find_first_bit(sbi->s_block_bitmap, sbi->s_nblocks); + if (bit >=3D sbi->s_nblocks) { + spin_unlock(&sbi->s_lock); + pr_err("ftrfs: bitmap inconsistency (free_blocks=3D%lu but no free bit)\= n", + sbi->s_free_blocks); + return 0; + } + + /* Mark as used */ + clear_bit(bit, sbi->s_block_bitmap); + sbi->s_free_blocks--; + + /* Update on-disk superblock counter */ + sbi->s_ftrfs_sb->s_free_blocks =3D cpu_to_le64(sbi->s_free_blocks); + mark_buffer_dirty(sbi->s_sbh); + + spin_unlock(&sbi->s_lock); + + /* Return absolute block number */ + return (u64)(sbi->s_data_start + bit); +} + +/* + * ftrfs_free_block =E2=80=94 release a data block back to the free pool + * @sb: superblock + * @block: absolute block number to free + */ +void ftrfs_free_block(struct super_block *sb, u64 block) +{ + struct ftrfs_sb_info *sbi =3D FTRFS_SB(sb); + unsigned long bit; + + if (block < sbi->s_data_start) { + pr_err("ftrfs: attempt to free non-data block %llu\n", block); + return; + } + + bit =3D (unsigned long)(block - sbi->s_data_start); + + if (bit >=3D sbi->s_nblocks) { + pr_err("ftrfs: block %llu out of range\n", block); + return; + } + + spin_lock(&sbi->s_lock); + + if (test_bit(bit, sbi->s_block_bitmap)) { + pr_warn("ftrfs: double free of block %llu\n", block); + spin_unlock(&sbi->s_lock); + return; + } + + set_bit(bit, sbi->s_block_bitmap); + sbi->s_free_blocks++; + + /* Update on-disk superblock counter */ + sbi->s_ftrfs_sb->s_free_blocks =3D cpu_to_le64(sbi->s_free_blocks); + mark_buffer_dirty(sbi->s_sbh); + + spin_unlock(&sbi->s_lock); +} + +/* + * ftrfs_alloc_inode_num =E2=80=94 allocate a free inode number + * @sb: superblock + * + * Returns inode number >=3D 2 on success (1 =3D root, reserved), + * or 0 on failure. + * + * Simple linear scan of the inode table for a free slot. + * A full implementation uses an inode bitmap block. + */ +u64 ftrfs_alloc_inode_num(struct super_block *sb) +{ + struct ftrfs_sb_info *sbi =3D FTRFS_SB(sb); + struct ftrfs_inode *raw; + struct buffer_head *bh; + unsigned long inodes_per_block; + unsigned long inode_table_blk; + unsigned long total_inodes; + unsigned long block, i; + u64 ino =3D 0; + + inodes_per_block =3D FTRFS_BLOCK_SIZE / sizeof(struct ftrfs_inode); + inode_table_blk =3D le64_to_cpu(sbi->s_ftrfs_sb->s_inode_table_blk); + total_inodes =3D le64_to_cpu(sbi->s_ftrfs_sb->s_inode_count); + + spin_lock(&sbi->s_lock); + + if (sbi->s_free_inodes =3D=3D 0) { + spin_unlock(&sbi->s_lock); + return 0; + } + + /* Scan inode table blocks looking for a free inode (i_mode =3D=3D 0) */ + for (block =3D 0; block * inodes_per_block < total_inodes; block++) { + bh =3D sb_bread(sb, inode_table_blk + block); + if (!bh) + continue; + + raw =3D (struct ftrfs_inode *)bh->b_data; + + for (i =3D 0; i < inodes_per_block; i++) { + unsigned long ino_num =3D block * inodes_per_block + i + 1; + + if (ino_num > total_inodes) + break; + + /* inode 1 =3D root, always reserved */ + if (ino_num =3D=3D 1) + continue; + + if (le16_to_cpu(raw[i].i_mode) =3D=3D 0) { + /* Found a free inode slot */ + ino =3D (u64)ino_num; + sbi->s_free_inodes--; + sbi->s_ftrfs_sb->s_free_inodes =3D + cpu_to_le64(sbi->s_free_inodes); + mark_buffer_dirty(sbi->s_sbh); + brelse(bh); + goto found; + } + } + brelse(bh); + } + +found: + spin_unlock(&sbi->s_lock); + return ino; +} --=20 2.52.0 From nobody Mon Jun 15 20:34:08 2026 Received: from mail-wm1-f53.google.com (mail-wm1-f53.google.com [209.85.128.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 02F9E3C7DEF for ; Mon, 13 Apr 2026 12:24:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083064; cv=none; b=auON9srxaDzOuH3NhRreWJUuQDbpWyQ9iEC2Ex0fuBUiuT9b64R7gEtxBw5WrZai4ZWpLhd63Dn5GY0jYAJcDI7NZd7dLGckyfr/7lJBa0KGXS+4OhbJLPGLTJvEi2f8Nv/1ozgDseraFoPQsc8Xy5P8iVumvvpDV0ndCH5Vrbw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083064; c=relaxed/simple; bh=P8ywCriTM8y+tGQV2WDtWfF6LxQ+CtR54d62qhJFf68=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=dleVe3aKvqkjWaFXIwZu53NTJNsfT38cQimp4uOE208BcDx4lJRWdCk/G+yy06jfj5VhmLInGC//hlglN8Gxoy/sMOet4KIHVPcUIcbjdzsOtH/4vd1AHoRO0R8vuP87ePQaLfKamp1I1Ey1MVY9It9dBp66tpBTEQdo8MS9vCY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.128.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wm1-f53.google.com with SMTP id 5b1f17b1804b1-488c1f446f3so6985065e9.0 for ; Mon, 13 Apr 2026 05:24:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776083061; x=1776687861; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Xdy/SJQY3nN2USEDGNTAV3RIz7jLBSrg7dQiV/7M3C8=; b=gk7+uyN2cEL47oeO0vQSMEI1OO0xhwoBAc1s6vP6PKc9iynr80hb6/0RjGYAG7eoLf ZujYSSzm+zRpOv16q/Y39DFlxqCaGCPDFfl9YvmMlNBdG1aCt68AQt23uN+VqhrvEX7N mU4/RZBdxoJ6gFc33dm+ykZt0eqDU9URRtCHivqbcoVPnKFxaZ+ih0ZvHR7re0ASFlMm 7/3WAt7APoitc+heqNoO7LiIIRV1DG+v3g8HucfJGC8yNLQQAT5Wwi1gL61T2wOoKmRi 2koY3tEzIWFZ4/nNkSZMRKjZFV6yI+h68coEsHUUvWukCft0ee3EZp0UpGY4f//wnJg/ h0Pw== X-Gm-Message-State: AOJu0YxHkin8hQpPmKMzh+g8Url7YMVwNqYXbFyn6ssJDxmHBaqOzwSh P7WD/1L1Iqd0kgtEiyrCpjrvCPP2MG1T6CrADJq3a1P/Jr+1PBkkp2+qs8v9ox7ziqQ= X-Gm-Gg: AeBDievfpLj5B+pOq0Uu7epY43W/u+Yy3LMbWoiDogZlxCmIYyODlLDNB9ZLzUOTaO7 B37MQfM8GT6YW6htdFGIM2C+O0UW0Z4QJ7Uwk1ds7Fjm00phxTjlNmTY6j1sr6DLUS5zoMhUQ+l 1Sg8/V5RoVJ6/1ASP0cOo6pxCMPdal65N+g0zj4Z+tGfUJ8U/EFL6dUQsurVR3lMDk4q5cUAoka KGW9fOkZHuaj0MqcA5kWlMtHPp5y81UiPwAdPeJzLCtNCkPM12HNSjQDPzlvUC33CZ97vOY/8v9 wrxJWddiGxjxiNw0AjSp+Ju84J0cjA2j/NlGr1Bexuwqkoi5ku5JRQZDVwAEc5H210eDp+GmfGH PTFgg5SYgun3J20jp6Dbujv4F68tvR5KIjNSO+yAfYgUsh3wWZo2Xzu1l8o5GxhC37eCennf5yT IHpG7J0Ke8xziesee6+7DBX8I2GZaoGq1T/IUWEkQAWxoIjfU9dYOT+Dm8/nUn6+ASoA== X-Received: by 2002:a05:600c:1f83:b0:488:a9e4:35be with SMTP id 5b1f17b1804b1-488d687c0f9mr101282515e9.5.1776083061205; Mon, 13 Apr 2026 05:24:21 -0700 (PDT) Received: from spartian-1.home ([2a01:cb1c:784:2f00:708:2805:7128:7a75]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-488d532ed4dsm278260915e9.4.2026.04.13.05.24.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Apr 2026 05:24:20 -0700 (PDT) From: Aurelien DESBRIERES To: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, viro@zeniv.linux.org.uk, brauner@kernel.org, aurelien@hackers.camp Subject: [RFC PATCH 07/10] ftrfs: add filename and directory entry operations Date: Mon, 13 Apr 2026 16:23:53 +0200 Message-ID: <20260413142357.515792-8-aurelien@hackers.camp> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260413142357.515792-1-aurelien@hackers.camp> References: <20260413142357.515792-1-aurelien@hackers.camp> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Aur=C3=A9lien DESBRIERES Implement VFS inode_operations for directories and write path: - ftrfs_create(): allocate inode, write to disk, add dir entry - ftrfs_mkdir(): create directory with . and .. entries - ftrfs_unlink(): remove directory entry, decrement link count - ftrfs_rmdir(): remove empty directory - ftrfs_link(): create hard link - ftrfs_write_inode(): VFS super_op, persist inode via sb_bread/ mark_buffer_dirty with CRC32 update - ftrfs_new_inode(): allocate and initialize a new VFS inode ftrfs_mkdir() returns struct dentry * as required by kernel 7.0 inode_operations.mkdir API change. Signed-off-by: Aur=C3=A9lien DESBRIERES --- fs/ftrfs/namei.c | 428 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 428 insertions(+) create mode 100644 fs/ftrfs/namei.c diff --git a/fs/ftrfs/namei.c b/fs/ftrfs/namei.c new file mode 100644 index 000000000..a8c1f79eb --- /dev/null +++ b/fs/ftrfs/namei.c @@ -0,0 +1,428 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * FTRFS =E2=80=94 Filename / directory entry operations + * Author: Aur=C3=A9lien DESBRIERES + * + * Implements: create, mkdir, unlink, rmdir, link, rename + */ + +#include +#include +#include +#include +#include "ftrfs.h" + +/* ------------------------------------------------------------------ */ +/* Helper: write a raw ftrfs_inode to disk */ +/* ------------------------------------------------------------------ */ + +static int ftrfs_write_inode_raw(struct inode *inode) +{ + struct super_block *sb =3D inode->i_sb; + struct ftrfs_sb_info *sbi =3D FTRFS_SB(sb); + struct ftrfs_inode_info *fi =3D FTRFS_I(inode); + struct ftrfs_inode *raw; + struct buffer_head *bh; + unsigned long inodes_per_block; + unsigned long block, offset; + + inodes_per_block =3D FTRFS_BLOCK_SIZE / sizeof(struct ftrfs_inode); + block =3D le64_to_cpu(sbi->s_ftrfs_sb->s_inode_table_blk) + + (inode->i_ino - 1) / inodes_per_block; + offset =3D (inode->i_ino - 1) % inodes_per_block; + + bh =3D sb_bread(sb, block); + if (!bh) + return -EIO; + + raw =3D (struct ftrfs_inode *)bh->b_data + offset; + + raw->i_mode =3D cpu_to_le16(inode->i_mode); + raw->i_uid =3D cpu_to_le16(i_uid_read(inode)); + raw->i_gid =3D cpu_to_le16(i_gid_read(inode)); + raw->i_nlink =3D cpu_to_le16(inode->i_nlink); + raw->i_size =3D cpu_to_le64(inode->i_size); + raw->i_blocks =3D cpu_to_le32(inode->i_blocks); + raw->i_atime =3D cpu_to_le64(inode_get_atime_sec(inode) * NSEC_PER_SEC + + inode_get_atime_nsec(inode)); + raw->i_mtime =3D cpu_to_le64(inode_get_mtime_sec(inode) * NSEC_PER_SEC + + inode_get_mtime_nsec(inode)); + raw->i_ctime =3D cpu_to_le64(inode_get_ctime_sec(inode) * NSEC_PER_SEC + + inode_get_ctime_nsec(inode)); + raw->i_flags =3D cpu_to_le32(fi->i_flags); + + memcpy(raw->i_direct, fi->i_direct, sizeof(fi->i_direct)); + raw->i_indirect =3D fi->i_indirect; + raw->i_dindirect =3D fi->i_dindirect; + + raw->i_crc32 =3D ftrfs_crc32(raw, + offsetof(struct ftrfs_inode, i_crc32)); + + mark_buffer_dirty(bh); + brelse(bh); + + return 0; +} + +/* ------------------------------------------------------------------ */ +/* Helper: add a directory entry to a directory inode */ +/* ------------------------------------------------------------------ */ + +static int ftrfs_add_dirent(struct inode *dir, const struct qstr *name, + u64 ino, unsigned int file_type) +{ + struct super_block *sb =3D dir->i_sb; + struct ftrfs_inode_info *fi =3D FTRFS_I(dir); + struct ftrfs_dir_entry *de; + struct buffer_head *bh; + unsigned int offset; + u64 block_no; + int i; + + /* Look for space in existing direct blocks */ + for (i =3D 0; i < FTRFS_DIRECT_BLOCKS; i++) { + block_no =3D le64_to_cpu(fi->i_direct[i]); + if (!block_no) + break; + + bh =3D sb_bread(sb, block_no); + if (!bh) + return -EIO; + + offset =3D 0; + while (offset + sizeof(*de) <=3D FTRFS_BLOCK_SIZE) { + de =3D (struct ftrfs_dir_entry *)(bh->b_data + offset); + + /* Free slot: ino =3D=3D 0 */ + if (!de->d_ino) { + de->d_ino =3D cpu_to_le64(ino); + de->d_name_len =3D name->len; + de->d_file_type =3D file_type; + de->d_rec_len =3D cpu_to_le16( + sizeof(struct ftrfs_dir_entry)); + memcpy(de->d_name, name->name, name->len); + de->d_name[name->len] =3D '\0'; + mark_buffer_dirty(bh); + brelse(bh); + inode_set_mtime_to_ts(dir, + current_time(dir)); + mark_inode_dirty(dir); + return 0; + } + offset +=3D le16_to_cpu(de->d_rec_len); + if (!de->d_rec_len) + break; + } + brelse(bh); + } + + /* Need a new block */ + if (i >=3D FTRFS_DIRECT_BLOCKS) + return -ENOSPC; + + block_no =3D ftrfs_alloc_block(sb); + if (!block_no) + return -ENOSPC; + + bh =3D sb_bread(sb, block_no); + if (!bh) { + ftrfs_free_block(sb, block_no); + return -EIO; + } + + memset(bh->b_data, 0, FTRFS_BLOCK_SIZE); + + de =3D (struct ftrfs_dir_entry *)bh->b_data; + de->d_ino =3D cpu_to_le64(ino); + de->d_name_len =3D name->len; + de->d_file_type =3D file_type; + de->d_rec_len =3D cpu_to_le16(sizeof(struct ftrfs_dir_entry)); + memcpy(de->d_name, name->name, name->len); + de->d_name[name->len] =3D '\0'; + + mark_buffer_dirty(bh); + brelse(bh); + + fi->i_direct[i] =3D cpu_to_le64(block_no); + dir->i_size +=3D FTRFS_BLOCK_SIZE; + dir->i_blocks++; + inode_set_mtime_to_ts(dir, current_time(dir)); + mark_inode_dirty(dir); + + return 0; +} + +/* ------------------------------------------------------------------ */ +/* Helper: remove a directory entry from a directory */ +/* ------------------------------------------------------------------ */ + +static int ftrfs_del_dirent(struct inode *dir, const struct qstr *name) +{ + struct super_block *sb =3D dir->i_sb; + struct ftrfs_inode_info *fi =3D FTRFS_I(dir); + struct ftrfs_dir_entry *de; + struct buffer_head *bh; + unsigned int offset; + u64 block_no; + int i; + + for (i =3D 0; i < FTRFS_DIRECT_BLOCKS; i++) { + block_no =3D le64_to_cpu(fi->i_direct[i]); + if (!block_no) + break; + + bh =3D sb_bread(sb, block_no); + if (!bh) + return -EIO; + + offset =3D 0; + while (offset + sizeof(*de) <=3D FTRFS_BLOCK_SIZE) { + de =3D (struct ftrfs_dir_entry *)(bh->b_data + offset); + + if (de->d_ino && + de->d_name_len =3D=3D name->len && + !memcmp(de->d_name, name->name, name->len)) { + /* Zero out the entry (mark as free) */ + memset(de, 0, sizeof(*de)); + mark_buffer_dirty(bh); + brelse(bh); + inode_set_mtime_to_ts(dir, + current_time(dir)); + mark_inode_dirty(dir); + return 0; + } + + if (!de->d_rec_len) + break; + offset +=3D le16_to_cpu(de->d_rec_len); + } + brelse(bh); + } + + return -ENOENT; +} + +/* ------------------------------------------------------------------ */ +/* Helper: allocate and initialize a new VFS inode */ +/* ------------------------------------------------------------------ */ + +struct inode *ftrfs_new_inode(struct inode *dir, umode_t mode) +{ + struct super_block *sb =3D dir->i_sb; + struct inode *inode; + struct ftrfs_inode_info *fi; + u64 ino; + + ino =3D ftrfs_alloc_inode_num(sb); + if (!ino) + return ERR_PTR(-ENOSPC); + + inode =3D new_inode(sb); + if (!inode) + return ERR_PTR(-ENOMEM); + + inode_init_owner(&nop_mnt_idmap, inode, dir, mode); + inode->i_ino =3D ino; + inode->i_blocks =3D 0; + inode->i_size =3D 0; + inode_set_atime_to_ts(inode, current_time(inode)); + inode_set_mtime_to_ts(inode, current_time(inode)); + inode_set_ctime_to_ts(inode, current_time(inode)); + + fi =3D FTRFS_I(inode); + memset(fi->i_direct, 0, sizeof(fi->i_direct)); + fi->i_indirect =3D 0; + fi->i_dindirect =3D 0; + fi->i_flags =3D 0; + + if (S_ISDIR(mode)) { + inode->i_op =3D &ftrfs_dir_inode_operations; + inode->i_fop =3D &ftrfs_dir_operations; + set_nlink(inode, 2); + } else { + inode->i_op =3D &ftrfs_file_inode_operations; + inode->i_fop =3D &ftrfs_file_operations; + set_nlink(inode, 1); + } + + insert_inode_hash(inode); + mark_inode_dirty(inode); + return ERR_CAST(inode); +} + +/* ------------------------------------------------------------------ */ +/* create =E2=80=94 create a regular file = */ +/* ------------------------------------------------------------------ */ + +static int ftrfs_create(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mode, bool excl) +{ + struct inode *inode; + int ret; + + inode =3D ftrfs_new_inode(dir, mode | S_IFREG); + if (IS_ERR(inode)) + return PTR_ERR(inode); + + ret =3D ftrfs_write_inode_raw(inode); + if (ret) + goto out_iput; + + ret =3D ftrfs_add_dirent(dir, &dentry->d_name, inode->i_ino, 1 /* DT_REG = */); + if (ret) + goto out_iput; + + ret =3D ftrfs_write_inode_raw(dir); + if (ret) + goto out_iput; + + d_instantiate(dentry, inode); + return 0; + +out_iput: + iput(inode); + return ret; +} + +/* ------------------------------------------------------------------ */ +/* mkdir =E2=80=94 create a directory = */ +/* ------------------------------------------------------------------ */ + +static struct dentry *ftrfs_mkdir(struct mnt_idmap *idmap, struct inode *d= ir, + struct dentry *dentry, umode_t mode) +{ + struct inode *inode; + int ret; + + inode_inc_link_count(dir); + + inode =3D ftrfs_new_inode(dir, mode | S_IFDIR); + if (IS_ERR(inode)) { + inode_dec_link_count(dir); + return ERR_CAST(inode); + } + + /* Add . and .. entries */ + ret =3D ftrfs_add_dirent(inode, &(struct qstr)QSTR_INIT(".", 1), + inode->i_ino, 4 /* DT_DIR */); + if (ret) + goto out_fail; + + ret =3D ftrfs_add_dirent(inode, &(struct qstr)QSTR_INIT("..", 2), + dir->i_ino, 4 /* DT_DIR */); + if (ret) + goto out_fail; + + ret =3D ftrfs_write_inode_raw(inode); + if (ret) + goto out_fail; + + ret =3D ftrfs_add_dirent(dir, &dentry->d_name, inode->i_ino, + 4 /* DT_DIR */); + if (ret) + goto out_fail; + + ret =3D ftrfs_write_inode_raw(dir); + if (ret) + goto out_fail; + + d_instantiate(dentry, inode); + return NULL; + +out_fail: + inode_dec_link_count(inode); + inode_dec_link_count(inode); + iput(inode); + inode_dec_link_count(dir); + return ERR_PTR(ret); +} + +/* ------------------------------------------------------------------ */ +/* unlink =E2=80=94 remove a file = */ +/* ------------------------------------------------------------------ */ + +static int ftrfs_unlink(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode =3D d_inode(dentry); + int ret; + + ret =3D ftrfs_del_dirent(dir, &dentry->d_name); + if (ret) + return ret; + + inode_set_ctime_to_ts(inode, current_time(inode)); + inode_dec_link_count(inode); + ftrfs_write_inode_raw(dir); + return 0; +} + +/* ------------------------------------------------------------------ */ +/* rmdir =E2=80=94 remove an empty directory = */ +/* ------------------------------------------------------------------ */ + +static int ftrfs_rmdir(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode =3D d_inode(dentry); + int ret; + + if (inode->i_nlink > 2) + return -ENOTEMPTY; + + ret =3D ftrfs_del_dirent(dir, &dentry->d_name); + if (ret) + return ret; + + inode_dec_link_count(inode); + inode_dec_link_count(inode); + inode_dec_link_count(dir); + ftrfs_write_inode_raw(dir); + return 0; +} + +/* ------------------------------------------------------------------ */ +/* link =E2=80=94 create a hard link = */ +/* ------------------------------------------------------------------ */ + +static int ftrfs_link(struct dentry *old_dentry, struct inode *dir, + struct dentry *dentry) +{ + struct inode *inode =3D d_inode(old_dentry); + int ret; + + inode_set_ctime_to_ts(inode, current_time(inode)); + inode_inc_link_count(inode); + + ret =3D ftrfs_add_dirent(dir, &dentry->d_name, inode->i_ino, 1); + if (ret) { + inode_dec_link_count(inode); + return ret; + } + + ftrfs_write_inode_raw(inode); + ftrfs_write_inode_raw(dir); + d_instantiate(dentry, inode); + ihold(inode); + return 0; +} + +/* ------------------------------------------------------------------ */ +/* write_inode =E2=80=94 VFS super_op: persist inode to disk = */ +/* ------------------------------------------------------------------ */ + +int ftrfs_write_inode(struct inode *inode, struct writeback_control *wbc) +{ + return ftrfs_write_inode_raw(inode); +} + +/* ------------------------------------------------------------------ */ +/* dir inode_operations =E2=80=94 exported = */ +/* ------------------------------------------------------------------ */ + +const struct inode_operations ftrfs_dir_inode_operations =3D { + .lookup =3D ftrfs_lookup, + .create =3D ftrfs_create, + .mkdir =3D ftrfs_mkdir, + .unlink =3D ftrfs_unlink, + .rmdir =3D ftrfs_rmdir, + .link =3D ftrfs_link, +}; --=20 2.52.0 From nobody Mon Jun 15 20:34:08 2026 Received: from mail-wm1-f51.google.com (mail-wm1-f51.google.com [209.85.128.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0668E3C7E0C for ; Mon, 13 Apr 2026 12:24:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083065; cv=none; b=UDWIoHp++WY50I+y38/XPFn5WgBjTw7xd5DYF4XTvEvO1tVKMP8RmT8aQ5OTp4IqDWHpNPc8Sr4JqnfhXSAi+ciVSe4QIQ3Q0YKKmV2ruLX1+NY9+H+gOk8mHtpBLFp9EDcap5bj2zGorvPR9O2Qa+VQeXbu0hYIX3EEQfzXwA0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083065; c=relaxed/simple; bh=9MwpuvspxgM9S1xocdqxhpnC1LkHwHjGUtwBjeGYgN4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Q8sJL0IutmBWwK6jwrKgX2L4H9olSAftJAz1RgQg59x6WLERURpMxMbdSRbeSKKnAq5DLpJKGMH4tkaKAboV5db7VnZp2bf4zY4W4jeZWvffAHIUyVLRmO550SGjAW+NBaOGU2LdP4+M2e4Uoo1RRHQDh3tIi5CeYMiS5bE+48s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.128.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wm1-f51.google.com with SMTP id 5b1f17b1804b1-488a8f97f6bso8168305e9.2 for ; Mon, 13 Apr 2026 05:24:23 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776083062; x=1776687862; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=xV2ei1Pjz1ktH8bmxRjBSR/qLLc+Wvu9ssskTBPD/gg=; b=gNLTedqGSw6Rla0HjaGGvBOWHl9pWQA0pBLAcLUO7gwDYY5WwMcrFeU0UyRWtKZ83f 17Sz0MqJHgcXY3NtdU1JzOdjYNrreNeErzIPaZ5HnSh/ZFSJ/Dbl4F+OhnGwT6hdaLpm gxHn6hRbz/8G+HwsNzG4A1/hIbLV2Af8JKb3Cq6Ls5gaCTxd7V6ClmNmwIfJtO1MiL5l ufDrDevk6VveYazm/NWNhXvrEK96dIwO82L8L6i3ZfYuuwqum6OLRl9AU4JBEq0HcUC8 pgTLpFicdo8npySn9ABF5qzhJtpN1teYHfJqX+DAZCSPK2ounQDY/WRjelJAD5eu+JB/ F74Q== X-Gm-Message-State: AOJu0YwmErXZ8MpWt4bonXDDUsEl7BF+z47BoOZfMHj0OVNNCI1TLUsm TXRi7l7eHZNv3oDM4CtJidR27bOgfiuKNG5aaRujO6yOIVXjqvJ2v1aGJsqvirPabtA= X-Gm-Gg: AeBDievm5sPwD1doPPBMXwFl6HERIT2Yxyoiya5ofrbJTONg+X6mf5SDWI4QReiBBJ9 ViKjV0C+qbt5sU+/yldwWN8+lRFrVR17whQRrX8z7xgljOcQNfdeO/qsgRTs3Ge7SecZlp/VQlb JhbYO03ESzkuP8oLZBvzg4hjbzvI4W59RtRV1zZxKOkOfwuBV3neRFfH8t23eupNfddeYDwv+LM vH9piJxpx0sjorJktX1yGG9tyYUbvQyBqhnex2eXS1JMt5ASKcDckNFXId6hqVDJS51vE0esGAT vIr5UHlv/rZ+Fsc10cnJHtmUVgq7zDMD22q8SqTQLSRch0g4zq6cC16ozpdOAfqCnqYKFyIdsja H2+pIlAQuYzVKvebYOnbrZjQQ2JbkN0mEajbYFbAkLKKJ4GgYiTMZ/5ltTEp1Np8huay3e1sKMX OUboi+NfcTqVrlOBi+B9B1QDaoWde7RuFQhqhf1IOTcj43ZmPbI0uA89PTdT+IxmWpfXOqWHyMp f+3 X-Received: by 2002:a05:600c:b85:b0:486:fb8a:fed with SMTP id 5b1f17b1804b1-488d68a0975mr96731605e9.8.1776083062284; Mon, 13 Apr 2026 05:24:22 -0700 (PDT) Received: from spartian-1.home ([2a01:cb1c:784:2f00:708:2805:7128:7a75]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-488d532ed4dsm278260915e9.4.2026.04.13.05.24.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Apr 2026 05:24:21 -0700 (PDT) From: Aurelien DESBRIERES To: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, viro@zeniv.linux.org.uk, brauner@kernel.org, aurelien@hackers.camp Subject: [RFC PATCH 08/10] ftrfs: add CRC32 checksumming and Reed-Solomon FEC skeleton Date: Mon, 13 Apr 2026 16:23:54 +0200 Message-ID: <20260413142357.515792-9-aurelien@hackers.camp> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260413142357.515792-1-aurelien@hackers.camp> References: <20260413142357.515792-1-aurelien@hackers.camp> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Aur=C3=A9lien DESBRIERES Implement data integrity layer: - ftrfs_crc32(): CRC32 wrapper via kernel crc32_le(), used for per-inode and per-superblock checksums - init_gf_tables(): initialize GF(2^8) Galois Field lookup tables (primitive polynomial 0x1d) for Reed-Solomon arithmetic - gf_mul(): GF(2^8) multiplication via log/exp tables - ftrfs_rs_encode(): systematic Reed-Solomon encoder over FTRFS_SUBBLOCK_DATA bytes with FTRFS_RS_PARITY check symbols The RS encoder operates on sub-blocks within each 4096-byte data block. Decoding (error correction) is not yet implemented. Signed-off-by: Aur=C3=A9lien DESBRIERES --- fs/ftrfs/edac.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 fs/ftrfs/edac.c diff --git a/fs/ftrfs/edac.c b/fs/ftrfs/edac.c new file mode 100644 index 000000000..ebe676c98 --- /dev/null +++ b/fs/ftrfs/edac.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * FTRFS =E2=80=94 EDAC layer: CRC32 + Reed-Solomon FEC + * Author: roastercode - Aurelien DESBRIERES + */ + +#include +#include +#include +#include "ftrfs.h" + +/* Reed-Solomon FEC context */ +static uint8_t gf_exp[256]; +static uint8_t gf_log[256]; +static bool rs_initialized; + +/* Initialize Galois Field tables */ +static void init_gf_tables(void) +{ + uint8_t x =3D 1; + + for (int i =3D 0; i < 255; i++) { + gf_exp[i] =3D x; + gf_log[x] =3D i; + x =3D (x << 1) ^ ((x & 0x80) ? 0x1d : 0); + } + gf_exp[255] =3D gf_exp[0]; + rs_initialized =3D true; +} + +/* Galois Field multiplication */ +static uint8_t gf_mul(uint8_t a, uint8_t b) +{ + if (a =3D=3D 0 || b =3D=3D 0) + return 0; + return gf_exp[(gf_log[a] + gf_log[b]) % 255]; +} + +/* Reed-Solomon encoding */ +int ftrfs_rs_encode(uint8_t *data, uint8_t *parity) +{ + uint8_t msg[FTRFS_SUBBLOCK_DATA + FTRFS_RS_PARITY]; + + if (!rs_initialized) + init_gf_tables(); + + memset(msg, 0, sizeof(msg)); + memcpy(msg, data, FTRFS_SUBBLOCK_DATA); + + for (int i =3D 0; i < FTRFS_SUBBLOCK_DATA; i++) { + uint8_t feedback =3D gf_mul(msg[i], gf_exp[FTRFS_RS_PARITY]); + + if (feedback !=3D 0) { + for (int j =3D 1; j <=3D FTRFS_RS_PARITY; j++) + msg[FTRFS_SUBBLOCK_DATA + j - 1] ^=3D gf_mul(msg[i], gf_exp[j]); + } + } + + memcpy(parity, msg + FTRFS_SUBBLOCK_DATA, FTRFS_RS_PARITY); + return 0; +} + +/* Reed-Solomon decoding (simplified for now) */ +int ftrfs_rs_decode(uint8_t *data, uint8_t *parity) +{ + if (!rs_initialized) + init_gf_tables(); + + /* For now, assume no errors (full decoding to be implemented) */ + return 0; +} + +/* + * ftrfs_crc32 - compute CRC32 checksum + * @buf: data buffer + * @len: length in bytes + * + * Returns CRC32 checksum. Uses kernel's hardware-accelerated CRC32 + * (same as ext4/btrfs). + */ +__u32 ftrfs_crc32(const void *buf, size_t len) +{ + return crc32_le(0xFFFFFFFF, buf, len) ^ 0xFFFFFFFF; +} --=20 2.52.0 From nobody Mon Jun 15 20:34:09 2026 Received: from mail-wm1-f49.google.com (mail-wm1-f49.google.com [209.85.128.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 103F13C8706 for ; Mon, 13 Apr 2026 12:24:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083066; cv=none; b=k57g88bDMKgrpC5BOUzkAVF0phAFN02O20Hg4OBmavHuLc8m80riLMCevg2/vzEx6xajTwgslqeKkS/bRC8yNj9SK/NGErsf85EjX5PvHHpwFwc1Ezponk5m7gKfaSYSb0tKCXlRcopA/vUo9/eU7IJDT0lfTssPDPNtmfIz7zc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083066; c=relaxed/simple; bh=ABJ3YrP25VWUHHH5hLJfB1K47EQFZfvSyClRfydzd7w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=pBuCiObyYdkpi4xWPkT2uGsE1HaHZbHnYr6HQULB+Y0vfQZYIk4VRDH1pTzWliO3lMSVpvk4LY5/fOY5IkAomoHOhEwAU9CCZOq/megMewYseSFYOcyAjb8fQo50dHasHsSVkzsxVWBMmks+F7n2ZBncKQ6rSaSjwY8z8zHIVwk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.128.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wm1-f49.google.com with SMTP id 5b1f17b1804b1-488965a9ca1so5235635e9.2 for ; Mon, 13 Apr 2026 05:24:24 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776083063; x=1776687863; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=x+ZMjdv11cJ8492YNrGjD4isO/++CXxkJuOfHfrJFck=; b=AaVEqxyfnFZiIexeJy3eHAs46ixNM/ICaFNYi8uHKYd9vRfe896ZKIfHsnzG9t8Rug WUR3WKZARq+GKcLFUt4ESDB59Z1xjnNQrnklr9uWVGG3t5mulKZ9UU7W6GMC22mztKng M8j+2Itd7qynwz3AHVd0/1GSxKXO/meKn6rML50fe/oFrFyxpWvEZhKGLwLuWExPGLUv 45uXtRvgJVUrWFIGD4AStLJJ7tog5lcWr/mlYTsEEQzXcrKjlevbzBqipFMTSRvJrSfu 3aaQ77xES1wJDIufnlp10wysO90hY6Qn+GrwmCf/nfYcQ2qmspONYxdVO/8k6Djixb9/ H3ew== X-Gm-Message-State: AOJu0YwC8DJ5pqBaVZqAum46Z/9iXj/wmbUiNu9P0dWRU7KMi26PYuG6 J28dzhxu5ar1/mcZkfOzgfVl13F+Or9L4ja2KnFtFcKqTNfzuiR2ZKuZ X-Gm-Gg: AeBDieuW/XRqXh7fSiMr2FqPXnpYyyihKkmDeJFwmDpZELOr6OsOqdCVbsxLUY6cN9p hcCLN1sEEd91Hi1YrDVHaFgTOXRuNz9d8kPCA/pLXYeuNIctnh6dp0wCM6SPIo2dOaQZCTy9NFl EgYHcDUHkiE3L26vJTE7qMhqAWcyvqMcqARtvU7Ruut59PQn9sYkZ2UeeWzfRI3FD8RRx81+fnD nyop0j476dwPaW0LzBlEqHFYP45YgqEGFFLUNVAp2wqHMsERBZdRM2piZ5TMoNLvJsa/e1PQXlQ xIma29Jy9JdG5cO2xZx3Em+WEkt1NOdXZn/ngmv1uuXSw21XO4ZCzlwhTFO/WHsFZAJTYN0pPJL i3lzpdiJa5E9iG6ruhWgUECu7SYMAuU+ltP+FwEF3Yet9V8rovNxNiMUnWEMB6SAvBqLAvYoR3i lc7pIEzip+Xq0XSbBjCEQKqHP+RbKPYIxuCrzQUALDZZt9DSPoDqTEJX/KnN21WP4BiQ== X-Received: by 2002:a05:600c:3ba8:b0:488:7fd3:5cd5 with SMTP id 5b1f17b1804b1-488d7eac3bemr96856175e9.1.1776083063302; Mon, 13 Apr 2026 05:24:23 -0700 (PDT) Received: from spartian-1.home ([2a01:cb1c:784:2f00:708:2805:7128:7a75]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-488d532ed4dsm278260915e9.4.2026.04.13.05.24.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Apr 2026 05:24:22 -0700 (PDT) From: Aurelien DESBRIERES To: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, viro@zeniv.linux.org.uk, brauner@kernel.org, aurelien@hackers.camp Subject: [RFC PATCH 09/10] ftrfs: add Kconfig, Makefile and fs/ tree integration Date: Mon, 13 Apr 2026 16:23:55 +0200 Message-ID: <20260413142357.515792-10-aurelien@hackers.camp> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260413142357.515792-1-aurelien@hackers.camp> References: <20260413142357.515792-1-aurelien@hackers.camp> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Aur=C3=A9lien DESBRIERES Kconfig: - CONFIG_FTRFS_FS: tristate, depends on BLOCK - selects CRC32, REED_SOLOMON, REED_SOLOMON_ENC8/DEC8 - CONFIG_FTRFS_FS_XATTR: extended attributes (SELinux support) - CONFIG_FTRFS_FS_SECURITY: security labels Makefile: - ftrfs.o composed of super.o, inode.o, dir.o, file.o, edac.o, alloc.o, namei.o - xattr.o conditionally compiled via CONFIG_FTRFS_FS_XATTR fs/Kconfig: source fs/ftrfs/Kconfig (after ext2) fs/Makefile: obj-$(CONFIG_FTRFS_FS) +=3D ftrfs/ Signed-off-by: Aur=C3=A9lien DESBRIERES --- fs/ftrfs/Kconfig | 49 +++++++++++++++++++++++++++++++++++++++++++++++ fs/ftrfs/Makefile | 46 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 fs/ftrfs/Kconfig create mode 100644 fs/ftrfs/Makefile diff --git a/fs/ftrfs/Kconfig b/fs/ftrfs/Kconfig new file mode 100644 index 000000000..e23fea923 --- /dev/null +++ b/fs/ftrfs/Kconfig @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# FTRFS filesystem configuration +# + +config FTRFS_FS + tristate "FTRFS fault-tolerant radiation-robust filesystem" + depends on BLOCK + select CRC32 + select REED_SOLOMON + select REED_SOLOMON_ENC8 + select REED_SOLOMON_DEC8 + help + FTRFS is a POSIX-compatible filesystem designed for dependable + storage in radiation-intensive environments. It provides: + + - CRC32 checksumming per block and per inode + - Reed-Solomon forward error correction (FEC) + - EDAC-compatible error tracking + + Originally described in: + Fuchs, Langer, Trinitis - ARCS 2015, TU Munich. + Targeting embedded Linux on MRAM/NOR flash for space applications. + + To compile this filesystem support as a module, choose M here. + The module will be called ftrfs. + + If unsure, say N. + +config FTRFS_FS_XATTR + bool "FTRFS extended attributes" + depends on FTRFS_FS + help + Extended attributes are name:value pairs associated with inodes. + They are required for SELinux, POSIX ACLs, and other security + frameworks that store per-file metadata outside the inode. + FTRFS xattrs follow the same namespace model as ext2/ext4. + + If you are not using SELinux or POSIX ACLs, say N. +config FTRFS_FS_SECURITY + bool "FTRFS Security Labels" + depends on FTRFS_FS_XATTR + help + Extended attributes are name:value pairs associated with inodes. + They are required for SELinux, POSIX ACLs, and other security + frameworks that store per-file metadata outside the inode. + FTRFS xattrs follow the same namespace model as ext2/ext4. + + If you are not using SELinux or POSIX ACLs, say N. diff --git a/fs/ftrfs/Makefile b/fs/ftrfs/Makefile new file mode 100644 index 000000000..a792286ec --- /dev/null +++ b/fs/ftrfs/Makefile @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# FTRFS =E2=80=94 Fault-Tolerant Radiation-Robust Filesystem +# + +obj-$(CONFIG_FTRFS_FS) +=3D ftrfs.o + +ftrfs-y :=3D super.o \ + inode.o \ + dir.o \ + file.o \ + edac.o \ + alloc.o \ + namei.o + +ftrfs-$(CONFIG_FTRFS_FS_XATTR) +=3D xattr.o + +ifneq ($(KERNELRELEASE),) +else + +ifneq ($(KERNEL_SRC),) + KERNELDIR :=3D $(KERNEL_SRC) +else + KERNELDIR ?=3D /lib/modules/$(shell uname -r)/build +endif + +ifneq ($(O),) + KBUILD_OUTPUT :=3D O=3D$(O) +else + KBUILD_OUTPUT :=3D +endif + +PWD :=3D $(shell pwd) + +all: + $(MAKE) -C $(KERNELDIR) $(KBUILD_OUTPUT) M=3D$(PWD) \ + CONFIG_FTRFS_FS=3Dm CONFIG_FTRFS_FS_XATTR=3Dn CONFIG_FTRFS_FS_SECURITY= =3Dn \ + modules + +clean: + $(MAKE) -C $(KERNELDIR) $(KBUILD_OUTPUT) M=3D$(PWD) clean + +modules_install: + $(MAKE) -C $(KERNELDIR) $(KBUILD_OUTPUT) M=3D$(PWD) modules_install + +endif --=20 2.52.0 From nobody Mon Jun 15 20:34:09 2026 Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ED8963C8730 for ; Mon, 13 Apr 2026 12:24:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083067; cv=none; b=NeFf/gUOLmDDthLZR5HbaqnexExdf6dZmUaY9pN03EgCmSEr1dnOAIXBv8u1GFjiZnihbPuWang48hz6gJjxW853t2oVMe4s14YU4nHczYH5oIV69GnSi3bz+DMoG1mjH9uIcw3ZHm8JkgrQBwZAkiL+M/dOzMgX9hlJsaR4zrY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776083067; c=relaxed/simple; bh=aIYCkkXQhEV7YD2MK2aXrwo7YFHm3qdBNt570xMTtEI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=QTbVE3glJ52VB0YWaPaIrrKoehUjC3pAqzfubfGKs6FDr2rm7XoQYdR41uyeshqaGWSPdkSFw5POfz+ep7vW+cdqqyWN+v4xKu1PTHDa6yyGmODFZGK4FOFv6v82V2Enyg6j4DhyU3wsinTWmDYeESZj0WKmo5MXjJTX3y51+s8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.128.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=hackers.camp Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wm1-f54.google.com with SMTP id 5b1f17b1804b1-488822b93c7so4767995e9.1 for ; Mon, 13 Apr 2026 05:24:25 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776083064; x=1776687864; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=T44lkLiB2OZlnKSWXBAk/krtQMxamGcLoTv0ViVPUmI=; b=nzVt5TBBtCrMugl6sS69DIz6jiXz7Y7cg9GH7cMuGd1ZEVc995xKAKl0By3rtQZSmr M4+QMGiA1DjC7Ze/Bouw0ZvL8qCUT2biMPh43aLT9PS+yGx7wtnQ74BzvOQSTpmxFbto Q+Dn1mI3b28N1+74SIL1v9L9ON1WXGMc1CIhJIsAmzj/S5SpQtL4gM6qX/eKBkl2mmOo /T0XQX0qCDUCNZvz6z3JYPNaWY/iY3hYgbCS3uE39zNK4UuR7osvFZKRqUHGYFJ7JVll fGUQ5mianNCZgmM77oiHpy705XPgrcNS3ssuCr6jX4AW9n+1uzplThkcBgoRq8lzpWN/ rJDQ== X-Gm-Message-State: AOJu0YydmVYc9/UHNZsI89hJNENW2LLhXt0C/gbmkSfhBNhvDoL1pNh3 hpPbRS806xvgzFBZOT+8u1vivcHCx4TSlokxBu7FeIVda9cJWVccf0Ep X-Gm-Gg: AeBDieu8Q+7Jl6XdBksjMZNyIQVmHoa5nd2m8cy+tL093tVHUw2JZrIc0N/ydGSYfe/ nCnQ91trmeV3zlFivJO6nyiRYCNJ75OiM8PbV+QeQrDohF976AmDABkQu+FbIR7+o8Er9L/d2xx lvq5A7ahQFl/KLhKVIaa3Y2LFNiV0vTvjxmPDkecVMErWb5+BWAJyrn9r+bqDjM9keK/8nNrJ73 56UX5FQoztas2EARZAIO6m2FJMSN3z0ugrXS67sn7PDbElXj/WmJzwZ9sQcEVN2wMYxPg+lRRdf FbvJIkh/Xq4Ii56DaOpBc10aqqFLZhXtpZwYmvoy75VkLyH59OxMiGSm4SlanJ9cROF8NpI8RHz XptOPcWSf4OPQ5Xf1SGmiRUwVgDCP9GsLzxVmo0TEyAGQ3SR3SEhrxvtvkLIZ7NwKv3/ZT7ZzIx XM2+zBvkyGg/w4vIViO0MWAlwItXGBu16FIYxRxEbCZ5nHCKKZpW/zV4Un5DIIlhD6Wg== X-Received: by 2002:a05:600c:524a:b0:488:926e:3ccd with SMTP id 5b1f17b1804b1-488d7f24014mr94782785e9.4.1776083064297; Mon, 13 Apr 2026 05:24:24 -0700 (PDT) Received: from spartian-1.home ([2a01:cb1c:784:2f00:708:2805:7128:7a75]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-488d532ed4dsm278260915e9.4.2026.04.13.05.24.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Apr 2026 05:24:23 -0700 (PDT) From: Aurelien DESBRIERES To: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, viro@zeniv.linux.org.uk, brauner@kernel.org, aurelien@hackers.camp Subject: [RFC PATCH 10/10] MAINTAINERS: add entry for FTRFS filesystem Date: Mon, 13 Apr 2026 16:23:56 +0200 Message-ID: <20260413142357.515792-11-aurelien@hackers.camp> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260413142357.515792-1-aurelien@hackers.camp> References: <20260413142357.515792-1-aurelien@hackers.camp> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Aur=C3=A9lien DESBRIERES Signed-off-by: Aur=C3=A9lien DESBRIERES --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index d1cc0e12f..f99e1219f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9610,6 +9610,12 @@ S: Maintained F: drivers/leds/leds-expresswire.c F: include/linux/leds-expresswire.h =20 +FTRFS FILE SYSTEM +M: Aur=C3=A9lien DESBRIERES +L: linux-fsdevel@vger.kernel.org +S: Maintained +F: fs/ftrfs/ + EXT2 FILE SYSTEM M: Jan Kara L: linux-ext4@vger.kernel.org --=20 2.52.0