Re: On https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=775c17386a6fd
Joseph Qi <[email protected]> Fri, 29 May 2026 09:28:11 +0800
| Newsgroups | dev.linux.lists.ocfs2-devel |
|---|---|
| Message-ID | <[email protected]> |
On 5/28/26 10:42 PM, Dmitry Antipov wrote:
> On Wed, 2026-05-27 at 15:52 +0800, Joseph Qi wrote:
>
>> ocfs2_validate_dx_root() returns -EROFS
>> ocfs2_read_blocks() goto read_failure → put_bh, bhs[0]=NULL, return -EROFS
>> ocfs2_read_block() returns -EROFS
>> ocfs2_read_dx_root() returns -EROFS
>> ocfs2_find_entry_dx() goto out, returns -EROFS
>>
>> On a second read of the same block, ocfs2_buffer_uptodate(ci, bh)
>> returns false (block was never added to the ocfs2 metadata cache because
>> the first read failed), so the block is re-read from disk and
>> re-validated — failing again.
>>
>> Am I missing something?
>
> It seems that I've got the point. In ocfs2_read_blocks(), it's wrong
> to assume that non-NULL BH returned by sb_getblk() is exclusively
> owned by the caller and so put_bh() always drops b_count from 1 to 0.
> If it is not so, BH remains on hold and likely to be returned by the
> next call to sb_getblk() unchanged - that is, with BH_Uptodate bit set
> even if it has failed validation previously. So BH_Uptodate should be
> cleared immediately after validate() callback has detected some data
> inconsistency, regardless of what may happens next with that BH:
>
It makes sense. Thanks to figure this out.
Could you please send a formal patch to fix this issue?
Thanks,
Joseph
> diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c
> index 701d27d908d4..6114299b121e 100644
> --- a/fs/ocfs2/buffer_head_io.c
> +++ b/fs/ocfs2/buffer_head_io.c
> @@ -350,8 +350,6 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
> wait_on_buffer(bh);
> put_bh(bh);
> bhs[i] = NULL;
> - } else if (bh && buffer_uptodate(bh)) {
> - clear_buffer_uptodate(bh);
> }
> continue;
> }
> @@ -380,8 +378,11 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
> BUG_ON(buffer_jbd(bh));
> clear_buffer_needs_validate(bh);
> status = validate(sb, bh);
> - if (status)
> + if (status) {
> + if (buffer_uptodate(bh))
> + clear_buffer_uptodate(bh);
> goto read_failure;
> + }
> }
> }
>
> Dmitry