Re: [PATCH 1/2] hfs: detect node 0 btree map corruption at mount time

From: Viacheslav Dubeyko

Date: Fri Aug 14 2026 - 00:10:35 EST


On Fri, 2026-08-14 at 10:31 +0800, Tao Yu wrote:
> HFS+ already validates that the btree map keeps node 0 marked as in-
> use
> when the tree is opened. HFS lacks the same check, so a corrupted
> volume
> can proceed past mount with a broken node bitmap and only fail later
> in
> write paths.
>
> Port the node 0 bitmap validation to HFS. If the header node is not
> marked as allocated in the on-disk map, warn that the btree bitmap is
> corrupted and force the filesystem read-only so users can repair it
> with
> fsck.hfs.
>
> This keeps the HFS mount-time behavior aligned with HFS+ and catches
> the
> corruption closer to where it becomes observable.
>
> Signed-off-by: Tao Yu <tao1.yu@xxxxxxxxx>
> ---
>  fs/hfs/btree.c | 60
> ++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 60 insertions(+)
>
> diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
> index 2eb37a2f64e86..14114318ec724 100644
> --- a/fs/hfs/btree.c
> +++ b/fs/hfs/btree.c
> @@ -15,12 +15,59 @@
>  
>  #include "btree.h"
>  
> +static bool hfs_bmap_test_bit(struct hfs_bnode *node, u32
> node_bit_idx)
> +{
> + u16 rec_idx, off, len;
> + u32 byte_offset;
> + u8 byte, mask;
> +
> + if (node->this == 0) {
> + if (node->type != HFS_NODE_HEADER) {
> + pr_err("hfs: invalid btree header node\n");
> + return false;
> + }
> + rec_idx = 2;
> + } else {
> + if (node->type != HFS_NODE_MAP) {
> + pr_err("hfs: invalid btree map node\n");
> + return false;
> + }
> + rec_idx = 0;
> + }
> +
> + len = hfs_brec_lenoff(node, rec_idx, &off);
> + if (!len)
> + return false;
> +
> + byte_offset = node_bit_idx / BITS_PER_BYTE;
> + if (byte_offset >= len)
> + return false;
> +
> + byte = hfs_bnode_read_u8(node, off + byte_offset);
> + mask = 1 << (7 - (node_bit_idx % BITS_PER_BYTE));
> +
> + return byte & mask;
> +}
> +
> +static const char *hfs_btree_name(u32 cnid)
> +{
> + switch (cnid) {
> + case HFS_EXT_CNID:
> + return "Extents Overflow File";
> + case HFS_CAT_CNID:
> + return "Catalog File";
> + default:
> + return "Unknown B-tree";
> + }
> +}
> +
>  /* Get a reference to a B*Tree and do some initial checks */
>  struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id,
> btree_keycmp keycmp)
>  {
>   struct hfs_btree *tree;
>   struct hfs_btree_header_rec *head;
>   struct address_space *mapping;
> + struct hfs_bnode *node;
>   struct folio *folio;
>   struct buffer_head *bh;
>   unsigned int size;
> @@ -155,6 +202,19 @@ struct hfs_btree *hfs_btree_open(struct
> super_block *sb, u32 id, btree_keycmp ke
>   kunmap_local(head);
>   folio_unlock(folio);
>   folio_put(folio);
> +
> + node = hfs_bnode_find(tree, 0);
> + if (IS_ERR(node))
> + goto free_inode;
> +
> + if (!hfs_bmap_test_bit(node, 0)) {
> + pr_warn("(%s): %s (cnid 0x%x) map record invalid or
> bitmap corruption detected, forcing read-only.\n",
> + sb->s_id, hfs_btree_name(id), id);
> + pr_warn("Run fsck.hfs to repair.\n");
> + sb->s_flags |= SB_RDONLY;
> + }
> +
> + hfs_bnode_put(node);
>   return tree;
>  
>  fail_folio:

Sorry, but this patch [1] already has implemented this functionality.
And this patch is in HFS/HFS+ tree (for-next branch).

Thanks,
Slava.

[1]
https://lore.kernel.org/r/20260716074150.1660-1-aditya.ansh182@xxxxxxxxx