Re: Possible bug with extent status tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Mar 11, 2013 at 09:38:34PM +0100, Jan Kara wrote:
>   Hello,
> 
>   while looking into the ext4 code I spotted one thing which I think is a
> bug introduced by extent status tree code. The problem is that
> ext4_map_blocks() checks extent status tree and if the extent is found, it
> doesn't call into ext4_ext_map_blocks(). However ext4_ext_direct_IO() expects
> that if the extent DIO is done to is unwritten, EXT4_IO_END_UNWRITTEN flag
> gets set in the io_end (or inode) flags and that happens only in
> ext4_ext_map_blocks().
> 
> The easiest fix seems to be to move setting of flags from
> ext4_ext_map_blocks() up into ext4_map_blocks() (or maybe even
> _ext4_get_block()). What do you think?

Hi Jan,

Thanks for reviewing the code.  But I don't think it is a potential bug.
Let's see what happens after adding extent status tree.  There are three
cases that we need to take care, a) no block has been allocated, b)
unwritten extent has been allocated, and c) written extent has been
allocated.

a) no block has been allocated.
In this case, both extent tree on disk and status tree in memory haven't
this extent.  When we do a extent-based dio write, ext4_get_block_write
will be called with EXT4_GET_BLOCKS_IO_CREATE_EXT flag.  In
ext4_map_blocks(), the codepath looks like:

ext4_map_blocks()
  ->ext4_es_lookup_extent()
    [no extent found in status tree]
  ->ext4_ext_map_blocks() without flags
    [no extent found in extent tree]
  ->ext4_ext_map_blocks() with EXT4_GET_BLOCKS_IO_CREATE_EXT
    ->ext4_mb_new_blocks()
      [allocate an unwritten extent]
    ->ext4_set_io_unwritten_flag()
      [set EXT4_IO_END_UNWRITTEN flag because _PRE_IO flag is set and an
       unwritten extent has been allocated]

In this case, we are safe.

b) unwritten extent has been allocated
In this case, both extent tree on disk and status tree in memory have an
unwritten extent, and codepath looks like:

ext4_map_blocks()
  ->ext4_es_lookup_extent()
    [unwritten extent found in status tree, EXT4_MAP_UNWRITTEN flag is
     marked in map->m_flags.  In the mean time, ext4_ext_map_blocks()
     isn't called]
  [But we don't return from ext4_map_blocks because EXT4_GET_BLOCKS_CREATE
   flag is set and EXT4_MAP_MAPPED flag is not set]
  ->ext4_ext_map_blocks() with EXT4_GET_BLOCKS_IO_CREATE_EXT
    ->ext4_ext_handle_uninitialized_extents()
      ->ext4_set_io_unwritten_flag()
        [set EXT4_IO_END_UNWRITTEN flag because _PRE_IO flag is set]

So it seems that there is no bug.

c) written extent has been allocated
In this case, both extent tree on disk and status tree in memory have an
written extent and codepath looks like:

ext4_map_blocks()
  ->ext4_es_lookup_extent()
    [written extent found in status tree, EXT4_MAP_MAPPED flag is set in
     map->m_flags.  In the mean time, ext4_ext_map_blocks() isn't called]
  [we return directly because retval > 0 and EXT4_MAP_MAPPED is set, and
   *EXT4_IO_END_UNWRITTEN flag is not set*]

I guess that you are aruging this case.  If we don't apply status tree
code, the codepath will look like:

ext4_map_blocks()
  ->ext4_ext_map_blocks() without flags
    [written extent found in extent tree.  We return directly because
     retval > 0 and EXT4_MAP_MAPPED is set.]

Thus, it seems we are safe.  Am I miss something?

Thanks,
                                                - Zheng
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Reiser Filesystem Development]     [Ceph FS]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite National Park]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]     [Linux Media]

  Powered by Linux