mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Baokun Li <libaokun@huaweicloud.com>
To: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Cc: linux-ext4@vger.kernel.org, tytso@mit.edu,
	adilger.kernel@dilger.ca, jack@suse.cz, ritesh.list@gmail.com,
	linux-kernel@vger.kernel.org, yi.zhang@huawei.com,
	yangerkun@huawei.com, Baokun Li <libaokun1@huawei.com>,
	zhanchengbin <zhanchengbin1@huawei.com>,
	Baokun Li <libaokun@huaweicloud.com>
Subject: Re: [PATCH 02/20] ext4: prevent partial update of the extents path
Date: Mon, 15 Jul 2024 20:33:27 +0800	[thread overview]
Message-ID: <9fd554c7-dc0c-4969-9f2a-1c99356fccce@huaweicloud.com> (raw)
In-Reply-To: <ZpPx3kuO36lp9/Um@li-bb2b2a4c-3307-11b2-a85c-8fa5c3a69313.ibm.com>

Hi Ojaswin!

On 2024/7/14 23:42, Ojaswin Mujoo wrote:
> On Wed, Jul 10, 2024 at 12:06:36PM +0800, libaokun@huaweicloud.com wrote:
>> From: Baokun Li <libaokun1@huawei.com>
>>
>> In ext4_ext_rm_idx() and ext4_ext_correct_indexes(), there is no proper
>> rollback of already executed updates when updating a level of the extents
>> path fails, so we may get an inconsistent extents tree, which may trigger
>> some bad things in errors=continue mode.
>>
>> Hence clear the verified bit of modified extents buffers if the tree fails
>> to be updated in ext4_ext_rm_idx() or ext4_ext_correct_indexes(), which
>> forces the extents buffers to be checked in ext4_valid_extent_entries(),
>> ensuring that the extents tree is consistent.
>>
>> Signed-off-by: zhanchengbin <zhanchengbin1@huawei.com>
>> Link: https://lore.kernel.org/r/20230213080514.535568-3-zhanchengbin1@huawei.com/
>> Signed-off-by: Baokun Li <libaokun1@huawei.com>
>> ---
>>   fs/ext4/extents.c | 31 +++++++++++++++++++++++++++----
>>   1 file changed, 27 insertions(+), 4 deletions(-)
>>
>> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
>> index bff3666c891a..4d589d34b30e 100644
>> --- a/fs/ext4/extents.c
>> +++ b/fs/ext4/extents.c
>> @@ -1749,12 +1749,23 @@ static int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode,
>>        break;
>>      err = ext4_ext_get_access(handle, inode, path + k);
>>      if (err)
>> -     break;
>> +     goto clean;
>>      path[k].p_idx->ei_block = border;
>>      err = ext4_ext_dirty(handle, inode, path + k);
>>      if (err)
>> -     break;
>> +     goto clean;
>>    }
>> + return 0;
>> +
>> +clean:
>> + /*
>> +  * The path[k].p_bh is either unmodified or with no verified bit
>> +  * set (see ext4_ext_get_access()). So just clear the verified bit
>> +  * of the successfully modified extents buffers, which will force
>> +  * these extents to be checked to avoid using inconsistent data.
>> +  */
>> + while (++k < depth)
>> +   clear_buffer_verified(path[k].p_bh);
>>   
>>    return err;
>>   }
>> @@ -2312,12 +2323,24 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
>>        break;
>>      err = ext4_ext_get_access(handle, inode, path + k);
>>      if (err)
>> -     break;
>> +     goto clean;
>>      path[k].p_idx->ei_block = path[k + 1].p_idx->ei_block;
>>      err = ext4_ext_dirty(handle, inode, path + k);
>>      if (err)
>> -     break;
>> +     goto clean;
>>    }
>> + return 0;
>> +
>> +clean:
>> + /*
>> +  * The path[k].p_bh is either unmodified or with no verified bit
>> +  * set (see ext4_ext_get_access()). So just clear the verified bit
>> +  * of the successfully modified extents buffers, which will force
>> +  * these extents to be checked to avoid using inconsistent data.
>> +  */
>> + while (++k < depth)
>> +   clear_buffer_verified(path[k].p_bh);
>> +
>>    return err;
>>   }
> Hi Baokun,
>
> So I wanted to understand the extent handling paths for a whil and thought this
> patchset was a good chance to finally take sometime and do that.
>
> I do have a question based on my understanding of this extent deletion code:
>
> So IIUC, ext4_find_extent() will return a path where buffer of each node is
> verified (via bh = read_extent_tree_block()). So imagine we have the following
> path (d=depth, blk=idx.ei_block, v=verified, nv=not-verified):
>
> +------+     +------+     +------+     +------+     +------+
> |d=0   |     |d=1   |     |d=2   |     |d=3   |     |      |
> |blk=1 | --> |blk=1 | --> |blk=1 | --> |blk=1 | --> |pblk=1|
> |(v)   |     |(v)   |     |(v)   |     |(v)   |     |      |
> +------+     +------+     +------+     +------+     +------+
>                                         |d=3   |     +------+
>                                         |blk=2 | --> |      |
>                                         |(v)   |     |pblk=2|
>                                         +------+     |      |
>                                                      +------+
>
> Here, the the last column are the leaf nodes with only 1 extent in them.  Now,
> say we want to punch the leaf having pblk=1. We'll eventually call
> ext4_ext_rm_leaf() -> ext4_ext_rm_idx() to remove the index at depth = 3 and
> try fixin up the indices in path with ei_block = 2
>
> Suppose we error out at depth == 1. After the cleanup (introduced in this
> patch), we'll mark depth = 1 to 4 as non verified:
>
> +------+     +------+     +------+     +------+     +------+
> |d=0   |     |d=1   |     |d=2   |     |d=3   |     |      |
> |blk=1 | --> |blk=1 | --> |blk=2 | --> |blk=2 | --> |pblk=2|
> |(v)   |     |(nv)  |     |(nv)  |     |(nv)  |     |(nv)  |
> +------+     +------+     +------+     +------+     +------+
Exactly right!
>
> And we return and we won't actually mark the FS corrupt until we try to check
> the bh at depth = 1 above. In this case, the first node is still pointing to
> wrong ei_block but is marked valid. Aren't we silently leaving the tree in an
> inconsistent state which might lead to corrupted lookups until we actually
> touch the affected bh and realise that there's a corruption.
>
> Am I missing some codepath here? Should we maybe try to clear_valid for the
> whole tree?
>
> (I hope the formatting of diagram comes out correct :) )
>
> Regards,
> ojaswin
But the journal will ensure the consistency of the extents path after
this patch.

When ext4_ext_get_access() or ext4_ext_dirty() returns an error in
ext4_ext_rm_idx() and ext4_ext_correct_indexes(), this may cause
the extents tree to be inconsistent. But the inconsistency just
exists in memory and doesn't land on disk.

For ext4_ext_get_access(), the handle must have been aborted
when it returned an error, as follows:

ext4_ext_get_access
ext4_journal_get_write_access
__ext4_journal_get_write_access
err = jbd2_journal_get_write_access
if (err)
ext4_journal_abort_handle

For ext4_ext_dirty(), since path->p_bh must not be null and handle
must be valid, handle is aborted anyway when an error is returned:

ext4_ext_dirty __ext4_ext_dirty if (path->p_bh) 
__ext4_handle_dirty_metadata if (ext4_handle_valid(handle)) err = 
jbd2_journal_dirty_metadata if (!is_handle_aborted(handle) && 
WARN_ON_ONCE(err)) ext4_journal_abort_handle
Thus the extents tree will only be inconsistent in memory, so only
the verified bit of the modified buffer needs to be cleared to avoid
these inconsistent data being used in memory.

Regards,
Baokun


  reply	other threads:[~2024-07-15 12:33 UTC|newest]

Thread overview: 84+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-10  4:06 [PATCH 00/20] ext4: some bugfixes and cleanups for ext4 " libaokun
2024-07-10  4:06 ` [PATCH 01/20] ext4: refactor ext4_ext_rm_idx() to index 'path' libaokun
2024-07-24 18:44   ` Jan Kara
2024-07-25  9:14   ` Ojaswin Mujoo
2024-07-10  4:06 ` [PATCH 02/20] ext4: prevent partial update of the extents path libaokun
2024-07-14 15:42   ` Ojaswin Mujoo
2024-07-15 12:33     ` Baokun Li [this message]
2024-07-15 12:41       ` Baokun Li
2024-07-16  9:54         ` Ojaswin Mujoo
2024-07-16 11:54           ` Baokun Li
2024-07-17  5:29             ` Ojaswin Mujoo
2024-07-17  6:11               ` Baokun Li
2024-07-24  6:23                 ` Ojaswin Mujoo
2024-07-25  5:35                   ` Baokun Li
2024-07-25  8:48                     ` Ojaswin Mujoo
2024-07-24 18:53   ` Jan Kara
2024-07-10  4:06 ` [PATCH 03/20] ext4: fix double brelse() the buffer " libaokun
2024-07-24 19:01   ` Jan Kara
2024-07-26 11:45   ` Ojaswin Mujoo
2024-07-30  8:47     ` Baokun Li
2024-08-01  6:26       ` Ojaswin Mujoo
2024-07-10  4:06 ` [PATCH 04/20] ext4: add new ext4_ext_path_brelse() helper libaokun
2024-07-24 19:02   ` Jan Kara
2024-07-26 11:53   ` Ojaswin Mujoo
2024-07-10  4:06 ` [PATCH 05/20] ext4: fix slab-use-after-free in ext4_split_extent_at() libaokun
2024-07-24 19:13   ` Jan Kara
2024-07-27 10:36   ` Ojaswin Mujoo
2024-07-30  8:57     ` Baokun Li
2024-07-30  9:26       ` Ojaswin Mujoo
2024-07-10  4:06 ` [PATCH 06/20] ext4: avoid use-after-free in ext4_ext_show_leaf() libaokun
2024-07-24 19:16   ` Jan Kara
2024-07-25  5:41     ` Baokun Li
2024-07-27 10:43   ` Ojaswin Mujoo
2024-07-10  4:06 ` [PATCH 07/20] ext4: drop ppath from ext4_ext_replay_update_ex() to avoid double-free libaokun
2024-07-25 10:31   ` Jan Kara
2024-07-27 11:18   ` Ojaswin Mujoo
2024-07-10  4:06 ` [PATCH 08/20] ext4: get rid of ppath in ext4_find_extent() libaokun
2024-07-25 10:38   ` Jan Kara
2024-07-27  6:18     ` Baokun Li
2024-07-29 11:28       ` Jan Kara
2024-07-30 10:03   ` Ojaswin Mujoo
2024-07-10  4:06 ` [PATCH 09/20] ext4: get rid of ppath in get_ext_path() libaokun
2024-07-25 10:41   ` Jan Kara
2024-08-01  7:16   ` Ojaswin Mujoo
2024-07-10  4:06 ` [PATCH 10/20] ext4: get rid of ppath in ext4_ext_create_new_leaf() libaokun
2024-07-25 10:46   ` Jan Kara
2024-07-27  6:35     ` Baokun Li
2024-08-02  7:34   ` Ojaswin Mujoo
2024-08-02 13:07     ` Baokun Li
2024-07-10  4:06 ` [PATCH 11/20] ext4: get rid of ppath in ext4_ext_insert_extent() libaokun
2024-07-25 10:59   ` Jan Kara
2024-08-02  8:01   ` Ojaswin Mujoo
2024-07-10  4:06 ` [PATCH 12/20] ext4: get rid of ppath in ext4_split_extent_at() libaokun
2024-07-25 11:07   ` Jan Kara
2024-07-27  6:42     ` Baokun Li
2024-08-21  3:19       ` Theodore Ts'o
2024-08-21  3:29         ` Baokun Li
2024-08-02  8:12   ` Ojaswin Mujoo
2024-07-10  4:06 ` [PATCH 13/20] ext4: get rid of ppath in ext4_force_split_extent_at() libaokun
2024-07-25 11:14   ` Jan Kara
2024-08-02 20:01   ` Ojaswin Mujoo
2024-08-03  2:23     ` Baokun Li
2024-07-10  4:06 ` [PATCH 14/20] ext4: get rid of ppath in ext4_split_extent() libaokun
2024-07-25 12:07   ` Jan Kara
2024-08-02 20:17   ` Ojaswin Mujoo
2024-07-10  4:06 ` [PATCH 15/20] ext4: get rid of ppath in ext4_split_convert_extents() libaokun
2024-07-25 12:12   ` Jan Kara
2024-08-02 20:26   ` Ojaswin Mujoo
2024-07-10  4:06 ` [PATCH 16/20] ext4: get rid of ppath in ext4_convert_unwritten_extents_endio() libaokun
2024-07-25 12:14   ` Jan Kara
2024-08-02 20:28   ` Ojaswin Mujoo
2024-07-10  4:06 ` [PATCH 17/20] ext4: get rid of ppath in ext4_ext_convert_to_initialized() libaokun
2024-07-25 12:18   ` Jan Kara
2024-08-02 20:38   ` Ojaswin Mujoo
2024-07-10  4:06 ` [PATCH 18/20] ext4: get rid of ppath in ext4_ext_handle_unwritten_extents() libaokun
2024-07-25 12:22   ` Jan Kara
2024-08-02 20:44   ` Ojaswin Mujoo
2024-07-10  4:06 ` [PATCH 19/20] ext4: get rid of ppath in convert_initialized_extent() libaokun
2024-07-25 12:23   ` Jan Kara
2024-08-02 20:46   ` Ojaswin Mujoo
2024-07-10  4:06 ` [PATCH 20/20] ext4: avoid unnecessary extent path frees and allocations libaokun
2024-07-25 12:31   ` Jan Kara
2024-08-02 20:58   ` Ojaswin Mujoo
2024-07-25  9:02 ` [PATCH 00/20] ext4: some bugfixes and cleanups for ext4 extents path Ojaswin Mujoo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9fd554c7-dc0c-4969-9f2a-1c99356fccce@huaweicloud.com \
    --to=libaokun@huaweicloud.com \
    --cc=adilger.kernel@dilger.ca \
    --cc=jack@suse.cz \
    --cc=libaokun1@huawei.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=ojaswin@linux.ibm.com \
    --cc=ritesh.list@gmail.com \
    --cc=tytso@mit.edu \
    --cc=yangerkun@huawei.com \
    --cc=yi.zhang@huawei.com \
    --cc=zhanchengbin1@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®