[lvc-project] [PATCH 2/2] ocfs2: validate cl_bpc in allocator inodes to prevent divide-by-zero

Joseph Qi joseph.qi at linux.alibaba.com
Thu Oct 30 11:48:20 MSK 2025



On 2025/10/30 16:11, Dmitry Antipov wrote:
> On 10/30/25 7:22 AM, Heming Zhao wrote:
> 
>> One way I considered uses the inode block number to bypass global_bitmap.
>> the code seems ugly (demo):
>>
>> ```
>> osb = OCFS2_SB(sb);
>> inode = ocfs2_get_system_file_inode(osb, GLOBAL_BITMAP_SYSTEM_INODE, OCFS2_INVALID_SLOT)
>>
>> if (OCFS2_I(inode)->ip_blkno != le64_to_cpu(fe->i_blkno))
>>    goto by_pass_the_check;
> 
> This is what happens in ocfs2_initialize_super(), and, IIUC, the global (cluster) bitmap
> is the only dinode which can have cl_bpc set to 1. So what about the following:
> 
> diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
> index 709afbfd1f9f..a8138c150d81 100644
> --- a/fs/ocfs2/inode.c
> +++ b/fs/ocfs2/inode.c
> @@ -1520,7 +1520,18 @@ int ocfs2_validate_inode_block(struct super_block *sb,
>                                          le16_to_cpu(cl->cl_next_free_rec));
>                         goto bail;
>                 }
> -               if (le16_to_cpu(cl->cl_bpc) != bpc) {
> +
> +               if (OCFS2_SB(sb)->bitmap_blkno == 0 && le16_to_cpu(cl->cl_bpc) == 1)
> +                       /* This dinode represents a cluster bitmap, and we're reading
> +                        * it for the first time from ocfs2_initialize_super().
> +                        */
> +                       ;
> +               else if (OCFS2_SB(sb)->bitmap_blkno == le64_to_cpu(di->i_blkno))
> +                       /* This dinode represents a cluster bitmap, and we can
> +                        * recognize it by using the known block number.
> +                        */
> +                       ;
> +               else if (le16_to_cpu(cl->cl_bpc) != bpc) {
>                         rc = ocfs2_error(sb, "Invalid dinode %llu: bits per cluster %u\n",
>                                          (unsigned long long)bh->b_blocknr,
>                                          le16_to_cpu(cl->cl_bpc));
> 
We don't have a simple flag to identify the global bitmap.
AFAIK, we may check it through:
  1. i_clusters, global bitmap has the whole volume clusters set in this
     field.
  2. i_blkno, which is set during mkfs.

But now we face the situation during the mount when initialize super,
which means the corresponding fields in ocfs2_super is 0 as of now.

And I've also found during runtime, we can validate through:

static inline int ocfs2_is_cluster_bitmap(struct inode *inode)
{
	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
	return osb->bitmap_blkno == OCFS2_I(inode)->ip_blkno;
}

So here we may check it something like:

if (OCFS2_SB(sb)->bitmap_blkno &&
    (OCFS2_SB(sb)->bitmap_blkno != le64_to_cpu(di->i_blkno) &&
    (le16_to_cpu(cl->cl_bpc) != bpc))

Joseph






More information about the lvc-project mailing list