Skip to content

Commit

Permalink
Btrfs: Add fallocate support v2
Browse files Browse the repository at this point in the history
This patch updates btrfs-progs for fallocate support.

fallocate is a little different in Btrfs because we need to tell the
COW system that a given preallocated extent doesn't need to be
cow'd as long as there are no snapshots of it.  This leverages the
-o nodatacow checks.
 
Signed-off-by: Yan Zheng <[email protected]>
  • Loading branch information
Yan Zheng authored and chrismason-xx committed Oct 30, 2008
1 parent 80ff385 commit d899e05
Show file tree
Hide file tree
Showing 10 changed files with 563 additions and 117 deletions.
9 changes: 7 additions & 2 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -462,8 +462,9 @@ struct btrfs_root_item {
u8 level;
} __attribute__ ((__packed__));

#define BTRFS_FILE_EXTENT_REG 0
#define BTRFS_FILE_EXTENT_INLINE 1
#define BTRFS_FILE_EXTENT_INLINE 0
#define BTRFS_FILE_EXTENT_REG 1
#define BTRFS_FILE_EXTENT_PREALLOC 2

struct btrfs_file_extent_item {
/*
Expand Down Expand Up @@ -868,6 +869,7 @@ struct btrfs_root {
#define BTRFS_INODE_NODATACOW (1 << 1)
#define BTRFS_INODE_READONLY (1 << 2)
#define BTRFS_INODE_NOCOMPRESS (1 << 3)
#define BTRFS_INODE_PREALLOC (1 << 4)
#define btrfs_clear_flag(inode, flag) (BTRFS_I(inode)->flags &= \
~BTRFS_INODE_##flag)
#define btrfs_set_flag(inode, flag) (BTRFS_I(inode)->flags |= \
Expand Down Expand Up @@ -1924,6 +1926,9 @@ extern struct file_operations btrfs_file_operations;
int btrfs_drop_extents(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct inode *inode,
u64 start, u64 end, u64 inline_limit, u64 *hint_block);
int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct inode *inode, u64 start, u64 end);
int btrfs_release_file(struct inode *inode, struct file *file);

/* tree-defrag.c */
Expand Down
65 changes: 36 additions & 29 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -2147,6 +2147,9 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
total_needed += empty_size;

block_group = btrfs_lookup_block_group(root->fs_info, search_start);
if (!block_group)
block_group = btrfs_lookup_first_block_group(root->fs_info,
search_start);
space_info = __find_space_info(root->fs_info, data);

down_read(&space_info->groups_sem);
Expand Down Expand Up @@ -3426,9 +3429,7 @@ static int noinline __next_ref_path(struct btrfs_trans_handle *trans,
next:
level--;
btrfs_release_path(extent_root, path);
if (need_resched()) {
cond_resched();
}
cond_resched();
}
/* reached lowest level */
ret = 1;
Expand Down Expand Up @@ -3539,9 +3540,7 @@ static int noinline __next_ref_path(struct btrfs_trans_handle *trans,
}

btrfs_release_path(extent_root, path);
if (need_resched()) {
cond_resched();
}
cond_resched();
}
/* reached max tree level, but no tree root found. */
BUG();
Expand Down Expand Up @@ -3654,8 +3653,9 @@ static int noinline get_new_locations(struct inode *reloc_inode,
exts[nr].encryption = btrfs_file_extent_encryption(leaf, fi);
exts[nr].other_encoding = btrfs_file_extent_other_encoding(leaf,
fi);
WARN_ON(exts[nr].offset > 0);
WARN_ON(exts[nr].num_bytes != exts[nr].disk_num_bytes);
BUG_ON(exts[nr].offset > 0);
BUG_ON(exts[nr].compression || exts[nr].encryption);
BUG_ON(exts[nr].num_bytes != exts[nr].disk_num_bytes);

cur_pos += exts[nr].num_bytes;
nr++;
Expand Down Expand Up @@ -3709,6 +3709,7 @@ static int noinline replace_one_extent(struct btrfs_trans_handle *trans,
u32 nritems;
int nr_scaned = 0;
int extent_locked = 0;
int extent_type;
int ret;

memcpy(&key, leaf_key, sizeof(key));
Expand Down Expand Up @@ -3781,8 +3782,9 @@ static int noinline replace_one_extent(struct btrfs_trans_handle *trans,
}
fi = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_file_extent_item);
if ((btrfs_file_extent_type(leaf, fi) !=
BTRFS_FILE_EXTENT_REG) ||
extent_type = btrfs_file_extent_type(leaf, fi);
if ((extent_type != BTRFS_FILE_EXTENT_REG &&
extent_type != BTRFS_FILE_EXTENT_PREALLOC) ||
(btrfs_file_extent_disk_bytenr(leaf, fi) !=
extent_key->objectid)) {
path->slots[0]++;
Expand Down Expand Up @@ -3865,16 +3867,10 @@ static int noinline replace_one_extent(struct btrfs_trans_handle *trans,

if (nr_extents == 1) {
/* update extent pointer in place */
btrfs_set_file_extent_generation(leaf, fi,
trans->transid);
btrfs_set_file_extent_disk_bytenr(leaf, fi,
new_extents[0].disk_bytenr);
btrfs_set_file_extent_disk_num_bytes(leaf, fi,
new_extents[0].disk_num_bytes);
btrfs_set_file_extent_ram_bytes(leaf, fi,
new_extents[0].ram_bytes);
ext_offset += new_extents[0].offset;
btrfs_set_file_extent_offset(leaf, fi, ext_offset);
btrfs_mark_buffer_dirty(leaf);

btrfs_drop_extent_cache(inode, key.offset,
Expand All @@ -3901,6 +3897,8 @@ static int noinline replace_one_extent(struct btrfs_trans_handle *trans,
btrfs_release_path(root, path);
key.offset += num_bytes;
} else {
BUG_ON(1);
#if 0
u64 alloc_hint;
u64 extent_len;
int i;
Expand Down Expand Up @@ -3977,6 +3975,7 @@ static int noinline replace_one_extent(struct btrfs_trans_handle *trans,
break;
}
BUG_ON(i >= nr_extents);
#endif
}

if (extent_locked) {
Expand Down Expand Up @@ -4156,15 +4155,10 @@ static int noinline replace_extents_in_leaf(struct btrfs_trans_handle *trans,
ref->extents[ext_index].bytenr = new_extent->disk_bytenr;
ref->extents[ext_index].num_bytes = new_extent->disk_num_bytes;

btrfs_set_file_extent_generation(leaf, fi, trans->transid);
btrfs_set_file_extent_ram_bytes(leaf, fi,
new_extent->ram_bytes);
btrfs_set_file_extent_disk_bytenr(leaf, fi,
new_extent->disk_bytenr);
btrfs_set_file_extent_disk_num_bytes(leaf, fi,
new_extent->disk_num_bytes);
new_extent->offset += btrfs_file_extent_offset(leaf, fi);
btrfs_set_file_extent_offset(leaf, fi, new_extent->offset);
btrfs_mark_buffer_dirty(leaf);

ret = btrfs_inc_extent_ref(trans, root,
Expand Down Expand Up @@ -4625,12 +4619,15 @@ static int noinline relocate_one_extent(struct btrfs_root *extent_root,
*/
if (!new_extents) {
u64 group_start = group->key.objectid;
new_extents = kmalloc(sizeof(*new_extents),
GFP_NOFS);
nr_extents = 1;
ret = get_new_locations(reloc_inode,
extent_key,
group_start, 0,
group_start, 1,
&new_extents,
&nr_extents);
if (ret < 0)
if (ret)
goto out;
}
btrfs_record_root_in_trans(found_root);
Expand Down Expand Up @@ -4762,7 +4759,8 @@ static int __insert_orphan_inode(struct btrfs_trans_handle *trans,
btrfs_set_inode_generation(leaf, item, 1);
btrfs_set_inode_size(leaf, item, size);
btrfs_set_inode_mode(leaf, item, S_IFREG | 0600);
btrfs_set_inode_flags(leaf, item, BTRFS_INODE_NODATASUM);
btrfs_set_inode_flags(leaf, item, BTRFS_INODE_NODATASUM |
BTRFS_INODE_NOCOMPRESS);
btrfs_mark_buffer_dirty(leaf);
btrfs_release_path(root, path);
out:
Expand Down Expand Up @@ -4835,6 +4833,7 @@ int btrfs_relocate_block_group(struct btrfs_root *root, u64 group_start)
struct inode *reloc_inode;
struct btrfs_block_group_cache *block_group;
struct btrfs_key key;
u64 skipped;
u64 cur_byte;
u64 total_found;
u32 nritems;
Expand Down Expand Up @@ -4864,6 +4863,7 @@ int btrfs_relocate_block_group(struct btrfs_root *root, u64 group_start)
btrfs_start_delalloc_inodes(info->tree_root);
btrfs_wait_ordered_extents(info->tree_root, 0);
again:
skipped = 0;
total_found = 0;
progress = 0;
key.objectid = block_group->key.objectid;
Expand Down Expand Up @@ -4926,6 +4926,8 @@ int btrfs_relocate_block_group(struct btrfs_root *root, u64 group_start)
ret = relocate_one_extent(root, path, &key, block_group,
reloc_inode, pass);
BUG_ON(ret < 0);
if (ret > 0)
skipped++;

key.objectid = cur_byte;
key.type = 0;
Expand All @@ -4944,6 +4946,11 @@ int btrfs_relocate_block_group(struct btrfs_root *root, u64 group_start)
printk("btrfs found %llu extents in pass %d\n",
(unsigned long long)total_found, pass);
pass++;
if (total_found == skipped && pass > 2) {
iput(reloc_inode);
reloc_inode = create_reloc_inode(info, block_group);
pass = 0;
}
goto again;
}

Expand Down Expand Up @@ -5011,17 +5018,17 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
while ((n = rb_last(&info->block_group_cache_tree)) != NULL) {
block_group = rb_entry(n, struct btrfs_block_group_cache,
cache_node);

spin_unlock(&info->block_group_cache_lock);
btrfs_remove_free_space_cache(block_group);
spin_lock(&info->block_group_cache_lock);

rb_erase(&block_group->cache_node,
&info->block_group_cache_tree);
spin_unlock(&info->block_group_cache_lock);

btrfs_remove_free_space_cache(block_group);
down_write(&block_group->space_info->groups_sem);
list_del(&block_group->list);
up_write(&block_group->space_info->groups_sem);
kfree(block_group);

spin_lock(&info->block_group_cache_lock);
}
spin_unlock(&info->block_group_cache_lock);
return 0;
Expand Down
12 changes: 9 additions & 3 deletions fs/btrfs/extent_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -2015,6 +2015,8 @@ printk("2bad mapping end %Lu cur %Lu\n", end, cur);
}
bdev = em->bdev;
block_start = em->block_start;
if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
block_start = EXTENT_MAP_HOLE;
free_extent_map(em);
em = NULL;

Expand Down Expand Up @@ -2769,14 +2771,18 @@ sector_t extent_bmap(struct address_space *mapping, sector_t iblock,
struct inode *inode = mapping->host;
u64 start = iblock << inode->i_blkbits;
sector_t sector = 0;
size_t blksize = (1 << inode->i_blkbits);
struct extent_map *em;

em = get_extent(inode, NULL, 0, start, (1 << inode->i_blkbits), 0);
lock_extent(&BTRFS_I(inode)->io_tree, start, start + blksize - 1,
GFP_NOFS);
em = get_extent(inode, NULL, 0, start, blksize, 0);
unlock_extent(&BTRFS_I(inode)->io_tree, start, start + blksize - 1,
GFP_NOFS);
if (!em || IS_ERR(em))
return 0;

if (em->block_start == EXTENT_MAP_INLINE ||
em->block_start == EXTENT_MAP_HOLE)
if (em->block_start > EXTENT_MAP_LAST_BYTE)
goto out;

sector = (em->block_start + start - em->start) >> inode->i_blkbits;
Expand Down
1 change: 1 addition & 0 deletions fs/btrfs/extent_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#define EXTENT_FLAG_PINNED 0 /* this entry not yet on disk, don't free it */
#define EXTENT_FLAG_COMPRESSED 1
#define EXTENT_FLAG_VACANCY 2 /* no file extent item found */
#define EXTENT_FLAG_PREALLOC 3 /* pre-allocated extent */

struct extent_map {
struct rb_node rb_node;
Expand Down
Loading

0 comments on commit d899e05

Please sign in to comment.