2024-02-03 17:57:48

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH v3 02/26] ext4: convert to exclusive lock while inserting delalloc extents

On Sat, Jan 27, 2024 at 09:58:01AM +0800, Zhang Yi wrote:
> From: Zhang Yi <[email protected]>
>
> ext4_da_map_blocks() only hold i_data_sem in shared mode and i_rwsem
> when inserting delalloc extents, it could be raced by another querying
> path of ext4_map_blocks() without i_rwsem, .e.g buffered read path.
> Suppose we buffered read a file containing just a hole, and without any
> cached extents tree, then it is raced by another delayed buffered write
> to the same area or the near area belongs to the same hole, and the new
> delalloc extent could be overwritten to a hole extent.
>
> pread() pwrite()
> filemap_read_folio()
> ext4_mpage_readpages()
> ext4_map_blocks()
> down_read(i_data_sem)
> ext4_ext_determine_hole()
> //find hole
> ext4_ext_put_gap_in_cache()
> ext4_es_find_extent_range()
> //no delalloc extent
> ext4_da_map_blocks()
> down_read(i_data_sem)
> ext4_insert_delayed_block()
> //insert delalloc extent
> ext4_es_insert_extent()
> //overwrite delalloc extent to hole
>
> This race could lead to inconsistent delalloc extents tree and
> incorrect reserved space counter. Fix this by converting to hold
> i_data_sem in exclusive mode when adding a new delalloc extent in
> ext4_da_map_blocks().
>
> Cc: [email protected]
> Signed-off-by: Zhang Yi <[email protected]>
> Suggested-by: Jan Kara <[email protected]>
> Reviewed-by: Jan Kara <[email protected]>

Thanks, applied.

- Ted