[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