Btrfs: create a helper to create em for IO

We have similar codes to create and insert extent mapping around IO path,
this merges them into a single helper.

Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Liu Bo 2017-01-31 07:50:22 -08:00 committed by David Sterba
parent 4136135b08
commit 6f9994dbab
1 changed files with 74 additions and 115 deletions

View File

@ -109,11 +109,11 @@ static noinline int cow_file_range(struct inode *inode,
u64 start, u64 end, u64 delalloc_end, u64 start, u64 end, u64 delalloc_end,
int *page_started, unsigned long *nr_written, int *page_started, unsigned long *nr_written,
int unlock, struct btrfs_dedupe_hash *hash); int unlock, struct btrfs_dedupe_hash *hash);
static struct extent_map *create_pinned_em(struct inode *inode, u64 start, static struct extent_map *create_io_em(struct inode *inode, u64 start, u64 len,
u64 len, u64 orig_start, u64 orig_start, u64 block_start,
u64 block_start, u64 block_len, u64 block_len, u64 orig_block_len,
u64 orig_block_len, u64 ram_bytes, u64 ram_bytes, int compress_type,
int type); int type);
static int btrfs_dirty_inode(struct inode *inode); static int btrfs_dirty_inode(struct inode *inode);
@ -697,7 +697,6 @@ static noinline void submit_compressed_extents(struct inode *inode,
struct btrfs_key ins; struct btrfs_key ins;
struct extent_map *em; struct extent_map *em;
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
struct extent_io_tree *io_tree; struct extent_io_tree *io_tree;
int ret = 0; int ret = 0;
@ -785,46 +784,19 @@ static noinline void submit_compressed_extents(struct inode *inode,
* here we're doing allocation and writeback of the * here we're doing allocation and writeback of the
* compressed pages * compressed pages
*/ */
btrfs_drop_extent_cache(inode, async_extent->start, em = create_io_em(inode, async_extent->start,
async_extent->start + async_extent->ram_size, /* len */
async_extent->ram_size - 1, 0); async_extent->start, /* orig_start */
ins.objectid, /* block_start */
em = alloc_extent_map(); ins.offset, /* block_len */
if (!em) { ins.offset, /* orig_block_len */
ret = -ENOMEM; async_extent->ram_size, /* ram_bytes */
goto out_free_reserve; async_extent->compress_type,
} BTRFS_ORDERED_COMPRESSED);
em->start = async_extent->start; if (IS_ERR(em))
em->len = async_extent->ram_size; /* ret value is not necessary due to void function */
em->orig_start = em->start;
em->mod_start = em->start;
em->mod_len = em->len;
em->block_start = ins.objectid;
em->block_len = ins.offset;
em->orig_block_len = ins.offset;
em->ram_bytes = async_extent->ram_size;
em->bdev = fs_info->fs_devices->latest_bdev;
em->compress_type = async_extent->compress_type;
set_bit(EXTENT_FLAG_PINNED, &em->flags);
set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
em->generation = -1;
while (1) {
write_lock(&em_tree->lock);
ret = add_extent_mapping(em_tree, em, 1);
write_unlock(&em_tree->lock);
if (ret != -EEXIST) {
free_extent_map(em);
break;
}
btrfs_drop_extent_cache(inode, async_extent->start,
async_extent->start +
async_extent->ram_size - 1, 0);
}
if (ret)
goto out_free_reserve; goto out_free_reserve;
free_extent_map(em);
ret = btrfs_add_ordered_extent_compress(inode, ret = btrfs_add_ordered_extent_compress(inode,
async_extent->start, async_extent->start,
@ -959,7 +931,6 @@ static noinline int cow_file_range(struct inode *inode,
u64 blocksize = fs_info->sectorsize; u64 blocksize = fs_info->sectorsize;
struct btrfs_key ins; struct btrfs_key ins;
struct extent_map *em; struct extent_map *em;
struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
int ret = 0; int ret = 0;
if (btrfs_is_free_space_inode(inode)) { if (btrfs_is_free_space_inode(inode)) {
@ -1012,39 +983,18 @@ static noinline int cow_file_range(struct inode *inode,
if (ret < 0) if (ret < 0)
goto out_unlock; goto out_unlock;
em = alloc_extent_map();
if (!em) {
ret = -ENOMEM;
goto out_reserve;
}
em->start = start;
em->orig_start = em->start;
ram_size = ins.offset; ram_size = ins.offset;
em->len = ins.offset; em = create_io_em(inode, start, ins.offset, /* len */
em->mod_start = em->start; start, /* orig_start */
em->mod_len = em->len; ins.objectid, /* block_start */
ins.offset, /* block_len */
em->block_start = ins.objectid; ins.offset, /* orig_block_len */
em->block_len = ins.offset; ram_size, /* ram_bytes */
em->orig_block_len = ins.offset; BTRFS_COMPRESS_NONE, /* compress_type */
em->ram_bytes = ram_size; 0 /* type */);
em->bdev = fs_info->fs_devices->latest_bdev; if (IS_ERR(em))
set_bit(EXTENT_FLAG_PINNED, &em->flags);
em->generation = -1;
while (1) {
write_lock(&em_tree->lock);
ret = add_extent_mapping(em_tree, em, 1);
write_unlock(&em_tree->lock);
if (ret != -EEXIST) {
free_extent_map(em);
break;
}
btrfs_drop_extent_cache(inode, start,
start + ram_size - 1, 0);
}
if (ret)
goto out_reserve; goto out_reserve;
free_extent_map(em);
cur_alloc_size = ins.offset; cur_alloc_size = ins.offset;
ret = btrfs_add_ordered_extent(inode, start, ins.objectid, ret = btrfs_add_ordered_extent(inode, start, ins.objectid,
@ -1251,6 +1201,7 @@ static noinline int run_delalloc_nocow(struct inode *inode,
struct btrfs_path *path; struct btrfs_path *path;
struct btrfs_file_extent_item *fi; struct btrfs_file_extent_item *fi;
struct btrfs_key found_key; struct btrfs_key found_key;
struct extent_map *em;
u64 cow_start; u64 cow_start;
u64 cur_offset; u64 cur_offset;
u64 extent_end; u64 extent_end;
@ -1431,35 +1382,28 @@ static noinline int run_delalloc_nocow(struct inode *inode,
} }
if (extent_type == BTRFS_FILE_EXTENT_PREALLOC) { if (extent_type == BTRFS_FILE_EXTENT_PREALLOC) {
struct extent_map *em; u64 orig_start = found_key.offset - extent_offset;
struct extent_map_tree *em_tree;
em_tree = &BTRFS_I(inode)->extent_tree; em = create_io_em(inode, cur_offset, num_bytes,
em = alloc_extent_map(); orig_start,
BUG_ON(!em); /* -ENOMEM */ disk_bytenr, /* block_start */
em->start = cur_offset; num_bytes, /* block_len */
em->orig_start = found_key.offset - extent_offset; disk_num_bytes, /* orig_block_len */
em->len = num_bytes; ram_bytes, BTRFS_COMPRESS_NONE,
em->block_len = num_bytes; BTRFS_ORDERED_PREALLOC);
em->block_start = disk_bytenr; if (IS_ERR(em)) {
em->orig_block_len = disk_num_bytes; if (!nolock && nocow)
em->ram_bytes = ram_bytes; btrfs_end_write_no_snapshoting(root);
em->bdev = fs_info->fs_devices->latest_bdev; if (nocow)
em->mod_start = em->start; btrfs_dec_nocow_writers(fs_info,
em->mod_len = em->len; disk_bytenr);
set_bit(EXTENT_FLAG_PINNED, &em->flags); ret = PTR_ERR(em);
set_bit(EXTENT_FLAG_FILLING, &em->flags); goto error;
em->generation = -1;
while (1) {
write_lock(&em_tree->lock);
ret = add_extent_mapping(em_tree, em, 1);
write_unlock(&em_tree->lock);
if (ret != -EEXIST) {
free_extent_map(em);
break;
}
btrfs_drop_extent_cache(inode, em->start,
em->start + em->len - 1, 0);
} }
free_extent_map(em);
}
if (extent_type == BTRFS_FILE_EXTENT_PREALLOC) {
type = BTRFS_ORDERED_PREALLOC; type = BTRFS_ORDERED_PREALLOC;
} else { } else {
type = BTRFS_ORDERED_NOCOW; type = BTRFS_ORDERED_NOCOW;
@ -7207,9 +7151,11 @@ static struct extent_map *btrfs_create_dio_extent(struct inode *inode,
int ret; int ret;
if (type != BTRFS_ORDERED_NOCOW) { if (type != BTRFS_ORDERED_NOCOW) {
em = create_pinned_em(inode, start, len, orig_start, em = create_io_em(inode, start, len, orig_start,
block_start, block_len, orig_block_len, block_start, block_len, orig_block_len,
ram_bytes, type); ram_bytes,
BTRFS_COMPRESS_NONE, /* compress_type */
type);
if (IS_ERR(em)) if (IS_ERR(em))
goto out; goto out;
} }
@ -7545,17 +7491,23 @@ static int lock_extent_direct(struct inode *inode, u64 lockstart, u64 lockend,
return ret; return ret;
} }
static struct extent_map *create_pinned_em(struct inode *inode, u64 start, /* The callers of this must take lock_extent() */
u64 len, u64 orig_start, static struct extent_map *create_io_em(struct inode *inode, u64 start, u64 len,
u64 block_start, u64 block_len, u64 orig_start, u64 block_start,
u64 orig_block_len, u64 ram_bytes, u64 block_len, u64 orig_block_len,
int type) u64 ram_bytes, int compress_type,
int type)
{ {
struct extent_map_tree *em_tree; struct extent_map_tree *em_tree;
struct extent_map *em; struct extent_map *em;
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
int ret; int ret;
ASSERT(type == BTRFS_ORDERED_PREALLOC ||
type == BTRFS_ORDERED_COMPRESSED ||
type == BTRFS_ORDERED_NOCOW ||
type == 0);
em_tree = &BTRFS_I(inode)->extent_tree; em_tree = &BTRFS_I(inode)->extent_tree;
em = alloc_extent_map(); em = alloc_extent_map();
if (!em) if (!em)
@ -7563,8 +7515,6 @@ static struct extent_map *create_pinned_em(struct inode *inode, u64 start,
em->start = start; em->start = start;
em->orig_start = orig_start; em->orig_start = orig_start;
em->mod_start = start;
em->mod_len = len;
em->len = len; em->len = len;
em->block_len = block_len; em->block_len = block_len;
em->block_start = block_start; em->block_start = block_start;
@ -7575,6 +7525,10 @@ static struct extent_map *create_pinned_em(struct inode *inode, u64 start,
set_bit(EXTENT_FLAG_PINNED, &em->flags); set_bit(EXTENT_FLAG_PINNED, &em->flags);
if (type == BTRFS_ORDERED_PREALLOC) if (type == BTRFS_ORDERED_PREALLOC)
set_bit(EXTENT_FLAG_FILLING, &em->flags); set_bit(EXTENT_FLAG_FILLING, &em->flags);
else if (type == BTRFS_ORDERED_COMPRESSED) {
set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
em->compress_type = compress_type;
}
do { do {
btrfs_drop_extent_cache(inode, em->start, btrfs_drop_extent_cache(inode, em->start,
@ -7582,6 +7536,10 @@ static struct extent_map *create_pinned_em(struct inode *inode, u64 start,
write_lock(&em_tree->lock); write_lock(&em_tree->lock);
ret = add_extent_mapping(em_tree, em, 1); ret = add_extent_mapping(em_tree, em, 1);
write_unlock(&em_tree->lock); write_unlock(&em_tree->lock);
/*
* The caller has taken lock_extent(), who could race with us
* to add em?
*/
} while (ret == -EEXIST); } while (ret == -EEXIST);
if (ret) { if (ret) {
@ -7589,6 +7547,7 @@ static struct extent_map *create_pinned_em(struct inode *inode, u64 start,
return ERR_PTR(ret); return ERR_PTR(ret);
} }
/* em got 2 refs now, callers needs to do free_extent_map once. */
return em; return em;
} }