Commit e98bf64f authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba

btrfs: add extra sanity checks for create_io_em()

The function create_io_em() is called before we submit an IO, to update
the in-memory extent map for the involved range.

This patch changes the following aspects:

- Does not allow BTRFS_ORDERED_NOCOW type
  For real NOCOW (excluding NOCOW writes into preallocated ranges)
  writes, we never call create_io_em(), as we does not need to update
  the extent map at all.

  So remove the sanity check allowing BTRFS_ORDERED_NOCOW type.

- Add extra sanity checks
  * PREALLOC
    - @block_len == len
      For uncompressed writes.

  * REGULAR
    - @block_len == @orig_block_len == @ram_bytes == @len
      We're creating a new uncompressed extent, and referring all of it.

    - @orig_start == @start
      We haven no offset inside the extent.

  * COMPRESSED
    - valid @compress_type
    - @len <= @ram_bytes
      This is to co-operate with encoded writes, which can cause a new
      file extent referring only part of a uncompressed extent.
Reviewed-by: default avatarFilipe Manana <fdmanana@suse.com>
Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 4bdc558b
...@@ -7258,11 +7258,49 @@ static struct extent_map *create_io_em(struct btrfs_inode *inode, u64 start, ...@@ -7258,11 +7258,49 @@ static struct extent_map *create_io_em(struct btrfs_inode *inode, u64 start,
struct extent_map *em; struct extent_map *em;
int ret; int ret;
/*
* Note the missing NOCOW type.
*
* For pure NOCOW writes, we should not create an io extent map, but
* just reusing the existing one.
* Only PREALLOC writes (NOCOW write into preallocated range) can
* create an io extent map.
*/
ASSERT(type == BTRFS_ORDERED_PREALLOC || ASSERT(type == BTRFS_ORDERED_PREALLOC ||
type == BTRFS_ORDERED_COMPRESSED || type == BTRFS_ORDERED_COMPRESSED ||
type == BTRFS_ORDERED_NOCOW ||
type == BTRFS_ORDERED_REGULAR); type == BTRFS_ORDERED_REGULAR);
switch (type) {
case BTRFS_ORDERED_PREALLOC:
/* Uncompressed extents. */
ASSERT(block_len == len);
/* We're only referring part of a larger preallocated extent. */
ASSERT(block_len <= ram_bytes);
break;
case BTRFS_ORDERED_REGULAR:
/* Uncompressed extents. */
ASSERT(block_len == len);
/* COW results a new extent matching our file extent size. */
ASSERT(orig_block_len == len);
ASSERT(ram_bytes == len);
/* Since it's a new extent, we should not have any offset. */
ASSERT(orig_start == start);
break;
case BTRFS_ORDERED_COMPRESSED:
/* Must be compressed. */
ASSERT(compress_type != BTRFS_COMPRESS_NONE);
/*
* Encoded write can make us to refer to part of the
* uncompressed extent.
*/
ASSERT(len <= ram_bytes);
break;
}
em = alloc_extent_map(); em = alloc_extent_map();
if (!em) if (!em)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment