Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/mason/linux-btrfs

Pull btrfs fixes from Chris Mason:
 "Miao Xie has been very busy, fixing races and enospc problems and many
  other small but important pieces.

  Alexandre Oliva discovered some problems with how our error handling
  was interacting with the block layer and for now has disabled our
  partial handling of sub-page writes.  The real sub-page work is in a
  series of patches from IBM that we still need to integrate and test.
  The code Alexandre has turned off was really incomplete.

  Josef has more error handling fixes and an important fix for the new
  skinny extent format.

  This also has my fix for the tracepoint crash from late in 3.9.  It's
  the first stage in a larger clean up to get rid of btrfs_bio and make
  a proper bioset for all the items we need to tack into the bio.  For
  now the bioset only holds our mirror_num and stripe_index, but for the
  next merge window I'll shuffle more in."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (25 commits)
  Btrfs: use a btrfs bioset instead of abusing bio internals
  Btrfs: make sure roots are assigned before freeing their nodes
  Btrfs: explicitly use global_block_rsv for quota_tree
  btrfs: do away with non-whole_page extent I/O
  Btrfs: don't invoke btrfs_invalidate_inodes() in the spin lock context
  Btrfs: remove BUG_ON() in btrfs_read_fs_tree_no_radix()
  Btrfs: pause the space balance when remounting to R/O
  Btrfs: fix unprotected root node of the subvolume's inode rb-tree
  Btrfs: fix accessing a freed tree root
  Btrfs: return errno if possible when we fail to allocate memory
  Btrfs: update the global reserve if it is empty
  Btrfs: don't steal the reserved space from the global reserve if their space type is different
  Btrfs: optimize the error handle of use_block_rsv()
  Btrfs: don't use global block reservation for inode cache truncation
  Btrfs: don't abort the current transaction if there is no enough space for inode cache
  Correct allowed raid levels on balance.
  Btrfs: fix possible memory leak in replace_path()
  Btrfs: fix possible memory leak in the find_parent_nodes()
  Btrfs: don't allow device replace on RAID5/RAID6
  Btrfs: handle running extent ops with skinny metadata
  ...
  • Loading branch information
torvalds committed May 18, 2013
2 parents e510668 + c5cb6a0 commit 130901b
Show file tree
Hide file tree
Showing 21 changed files with 301 additions and 246 deletions.
3 changes: 2 additions & 1 deletion fs/btrfs/backref.c
Original file line number Diff line number Diff line change
Expand Up @@ -918,7 +918,8 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
ref->parent, bsz, 0);
if (!eb || !extent_buffer_uptodate(eb)) {
free_extent_buffer(eb);
return -EIO;
ret = -EIO;
goto out;
}
ret = find_extent_in_eb(eb, bytenr,
*extent_item_pos, &eie);
Expand Down
2 changes: 1 addition & 1 deletion fs/btrfs/check-integrity.c
Original file line number Diff line number Diff line change
Expand Up @@ -1700,7 +1700,7 @@ static int btrfsic_read_block(struct btrfsic_state *state,
unsigned int j;
DECLARE_COMPLETION_ONSTACK(complete);

bio = bio_alloc(GFP_NOFS, num_pages - i);
bio = btrfs_io_bio_alloc(GFP_NOFS, num_pages - i);
if (!bio) {
printk(KERN_INFO
"btrfsic: bio_alloc() for %u pages failed!\n",
Expand Down
4 changes: 3 additions & 1 deletion fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -951,10 +951,12 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
BUG_ON(ret); /* -ENOMEM */
}
if (new_flags != 0) {
int level = btrfs_header_level(buf);

ret = btrfs_set_disk_extent_flags(trans, root,
buf->start,
buf->len,
new_flags, 0);
new_flags, level, 0);
if (ret)
return ret;
}
Expand Down
8 changes: 4 additions & 4 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,12 @@ struct btrfs_ordered_sum;
/* holds checksums of all the data extents */
#define BTRFS_CSUM_TREE_OBJECTID 7ULL

/* for storing balance parameters in the root tree */
#define BTRFS_BALANCE_OBJECTID -4ULL

/* holds quota configuration and tracking */
#define BTRFS_QUOTA_TREE_OBJECTID 8ULL

/* for storing balance parameters in the root tree */
#define BTRFS_BALANCE_OBJECTID -4ULL

/* orhpan objectid for tracking unlinked/truncated files */
#define BTRFS_ORPHAN_OBJECTID -5ULL

Expand Down Expand Up @@ -3075,7 +3075,7 @@ int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
u64 bytenr, u64 num_bytes, u64 flags,
int is_data);
int level, int is_data);
int btrfs_free_extent(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid,
Expand Down
1 change: 1 addition & 0 deletions fs/btrfs/delayed-ref.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ struct btrfs_delayed_ref_node {
struct btrfs_delayed_extent_op {
struct btrfs_disk_key key;
u64 flags_to_set;
int level;
unsigned int update_key:1;
unsigned int update_flags:1;
unsigned int is_data:1;
Expand Down
5 changes: 5 additions & 0 deletions fs/btrfs/dev-replace.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,11 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
struct btrfs_device *tgt_device = NULL;
struct btrfs_device *src_device = NULL;

if (btrfs_fs_incompat(fs_info, RAID56)) {
pr_warn("btrfs: dev_replace cannot yet handle RAID5/RAID6\n");
return -EINVAL;
}

switch (args->start.cont_reading_from_srcdev_mode) {
case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS:
case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID:
Expand Down
52 changes: 30 additions & 22 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ static struct btrfs_lockdep_keyset {
{ .id = BTRFS_DEV_TREE_OBJECTID, .name_stem = "dev" },
{ .id = BTRFS_FS_TREE_OBJECTID, .name_stem = "fs" },
{ .id = BTRFS_CSUM_TREE_OBJECTID, .name_stem = "csum" },
{ .id = BTRFS_ORPHAN_OBJECTID, .name_stem = "orphan" },
{ .id = BTRFS_QUOTA_TREE_OBJECTID, .name_stem = "quota" },
{ .id = BTRFS_TREE_LOG_OBJECTID, .name_stem = "log" },
{ .id = BTRFS_TREE_RELOC_OBJECTID, .name_stem = "treloc" },
{ .id = BTRFS_DATA_RELOC_TREE_OBJECTID, .name_stem = "dreloc" },
Expand Down Expand Up @@ -1513,7 +1513,6 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
}

root->commit_root = btrfs_root_node(root);
BUG_ON(!root->node); /* -ENOMEM */
out:
if (location->objectid != BTRFS_TREE_LOG_OBJECTID) {
root->ref_cows = 1;
Expand Down Expand Up @@ -1988,30 +1987,33 @@ static void free_root_pointers(struct btrfs_fs_info *info, int chunk_root)
{
free_extent_buffer(info->tree_root->node);
free_extent_buffer(info->tree_root->commit_root);
free_extent_buffer(info->dev_root->node);
free_extent_buffer(info->dev_root->commit_root);
free_extent_buffer(info->extent_root->node);
free_extent_buffer(info->extent_root->commit_root);
free_extent_buffer(info->csum_root->node);
free_extent_buffer(info->csum_root->commit_root);
if (info->quota_root) {
free_extent_buffer(info->quota_root->node);
free_extent_buffer(info->quota_root->commit_root);
}

info->tree_root->node = NULL;
info->tree_root->commit_root = NULL;
info->dev_root->node = NULL;
info->dev_root->commit_root = NULL;
info->extent_root->node = NULL;
info->extent_root->commit_root = NULL;
info->csum_root->node = NULL;
info->csum_root->commit_root = NULL;

if (info->dev_root) {
free_extent_buffer(info->dev_root->node);
free_extent_buffer(info->dev_root->commit_root);
info->dev_root->node = NULL;
info->dev_root->commit_root = NULL;
}
if (info->extent_root) {
free_extent_buffer(info->extent_root->node);
free_extent_buffer(info->extent_root->commit_root);
info->extent_root->node = NULL;
info->extent_root->commit_root = NULL;
}
if (info->csum_root) {
free_extent_buffer(info->csum_root->node);
free_extent_buffer(info->csum_root->commit_root);
info->csum_root->node = NULL;
info->csum_root->commit_root = NULL;
}
if (info->quota_root) {
free_extent_buffer(info->quota_root->node);
free_extent_buffer(info->quota_root->commit_root);
info->quota_root->node = NULL;
info->quota_root->commit_root = NULL;
}

if (chunk_root) {
free_extent_buffer(info->chunk_root->node);
free_extent_buffer(info->chunk_root->commit_root);
Expand Down Expand Up @@ -3128,7 +3130,7 @@ static int write_dev_flush(struct btrfs_device *device, int wait)
* caller
*/
device->flush_bio = NULL;
bio = bio_alloc(GFP_NOFS, 0);
bio = btrfs_io_bio_alloc(GFP_NOFS, 0);
if (!bio)
return -ENOMEM;

Expand Down Expand Up @@ -3659,8 +3661,11 @@ static void btrfs_destroy_ordered_operations(struct btrfs_transaction *t,
ordered_operations);

list_del_init(&btrfs_inode->ordered_operations);
spin_unlock(&root->fs_info->ordered_extent_lock);

btrfs_invalidate_inodes(btrfs_inode->root);

spin_lock(&root->fs_info->ordered_extent_lock);
}

spin_unlock(&root->fs_info->ordered_extent_lock);
Expand Down Expand Up @@ -3782,8 +3787,11 @@ static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root)
list_del_init(&btrfs_inode->delalloc_inodes);
clear_bit(BTRFS_INODE_IN_DELALLOC_LIST,
&btrfs_inode->runtime_flags);
spin_unlock(&root->fs_info->delalloc_lock);

btrfs_invalidate_inodes(btrfs_inode->root);

spin_lock(&root->fs_info->delalloc_lock);
}

spin_unlock(&root->fs_info->delalloc_lock);
Expand All @@ -3808,7 +3816,7 @@ static int btrfs_destroy_marked_extents(struct btrfs_root *root,
while (start <= end) {
eb = btrfs_find_tree_block(root, start,
root->leafsize);
start += eb->len;
start += root->leafsize;
if (!eb)
continue;
wait_on_extent_buffer_writeback(eb);
Expand Down
94 changes: 50 additions & 44 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -2070,8 +2070,7 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans,
u32 item_size;
int ret;
int err = 0;
int metadata = (node->type == BTRFS_TREE_BLOCK_REF_KEY ||
node->type == BTRFS_SHARED_BLOCK_REF_KEY);
int metadata = !extent_op->is_data;

if (trans->aborted)
return 0;
Expand All @@ -2086,11 +2085,8 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans,
key.objectid = node->bytenr;

if (metadata) {
struct btrfs_delayed_tree_ref *tree_ref;

tree_ref = btrfs_delayed_node_to_tree_ref(node);
key.type = BTRFS_METADATA_ITEM_KEY;
key.offset = tree_ref->level;
key.offset = extent_op->level;
} else {
key.type = BTRFS_EXTENT_ITEM_KEY;
key.offset = node->num_bytes;
Expand Down Expand Up @@ -2719,7 +2715,7 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
u64 bytenr, u64 num_bytes, u64 flags,
int is_data)
int level, int is_data)
{
struct btrfs_delayed_extent_op *extent_op;
int ret;
Expand All @@ -2732,6 +2728,7 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans,
extent_op->update_flags = 1;
extent_op->update_key = 0;
extent_op->is_data = is_data ? 1 : 0;
extent_op->level = level;

ret = btrfs_add_delayed_extent_op(root->fs_info, trans, bytenr,
num_bytes, extent_op);
Expand Down Expand Up @@ -3109,6 +3106,11 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group,
WARN_ON(ret);

if (i_size_read(inode) > 0) {
ret = btrfs_check_trunc_cache_free_space(root,
&root->fs_info->global_block_rsv);
if (ret)
goto out_put;

ret = btrfs_truncate_free_space_cache(root, trans, path,
inode);
if (ret)
Expand Down Expand Up @@ -4562,6 +4564,8 @@ static void init_global_block_rsv(struct btrfs_fs_info *fs_info)
fs_info->csum_root->block_rsv = &fs_info->global_block_rsv;
fs_info->dev_root->block_rsv = &fs_info->global_block_rsv;
fs_info->tree_root->block_rsv = &fs_info->global_block_rsv;
if (fs_info->quota_root)
fs_info->quota_root->block_rsv = &fs_info->global_block_rsv;
fs_info->chunk_root->block_rsv = &fs_info->chunk_block_rsv;

update_global_block_rsv(fs_info);
Expand Down Expand Up @@ -6651,51 +6655,51 @@ use_block_rsv(struct btrfs_trans_handle *trans,
struct btrfs_block_rsv *block_rsv;
struct btrfs_block_rsv *global_rsv = &root->fs_info->global_block_rsv;
int ret;
bool global_updated = false;

block_rsv = get_block_rsv(trans, root);

if (block_rsv->size == 0) {
ret = reserve_metadata_bytes(root, block_rsv, blocksize,
BTRFS_RESERVE_NO_FLUSH);
/*
* If we couldn't reserve metadata bytes try and use some from
* the global reserve.
*/
if (ret && block_rsv != global_rsv) {
ret = block_rsv_use_bytes(global_rsv, blocksize);
if (!ret)
return global_rsv;
return ERR_PTR(ret);
} else if (ret) {
return ERR_PTR(ret);
}
if (unlikely(block_rsv->size == 0))
goto try_reserve;
again:
ret = block_rsv_use_bytes(block_rsv, blocksize);
if (!ret)
return block_rsv;

if (block_rsv->failfast)
return ERR_PTR(ret);

if (block_rsv->type == BTRFS_BLOCK_RSV_GLOBAL && !global_updated) {
global_updated = true;
update_global_block_rsv(root->fs_info);
goto again;
}

ret = block_rsv_use_bytes(block_rsv, blocksize);
if (btrfs_test_opt(root, ENOSPC_DEBUG)) {
static DEFINE_RATELIMIT_STATE(_rs,
DEFAULT_RATELIMIT_INTERVAL * 10,
/*DEFAULT_RATELIMIT_BURST*/ 1);
if (__ratelimit(&_rs))
WARN(1, KERN_DEBUG
"btrfs: block rsv returned %d\n", ret);
}
try_reserve:
ret = reserve_metadata_bytes(root, block_rsv, blocksize,
BTRFS_RESERVE_NO_FLUSH);
if (!ret)
return block_rsv;
if (ret && !block_rsv->failfast) {
if (btrfs_test_opt(root, ENOSPC_DEBUG)) {
static DEFINE_RATELIMIT_STATE(_rs,
DEFAULT_RATELIMIT_INTERVAL * 10,
/*DEFAULT_RATELIMIT_BURST*/ 1);
if (__ratelimit(&_rs))
WARN(1, KERN_DEBUG
"btrfs: block rsv returned %d\n", ret);
}
ret = reserve_metadata_bytes(root, block_rsv, blocksize,
BTRFS_RESERVE_NO_FLUSH);
if (!ret) {
return block_rsv;
} else if (ret && block_rsv != global_rsv) {
ret = block_rsv_use_bytes(global_rsv, blocksize);
if (!ret)
return global_rsv;
}
/*
* If we couldn't reserve metadata bytes try and use some from
* the global reserve if its space type is the same as the global
* reservation.
*/
if (block_rsv->type != BTRFS_BLOCK_RSV_GLOBAL &&
block_rsv->space_info == global_rsv->space_info) {
ret = block_rsv_use_bytes(global_rsv, blocksize);
if (!ret)
return global_rsv;
}

return ERR_PTR(-ENOSPC);
return ERR_PTR(ret);
}

static void unuse_block_rsv(struct btrfs_fs_info *fs_info,
Expand Down Expand Up @@ -6763,6 +6767,7 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
extent_op->update_key = 1;
extent_op->update_flags = 1;
extent_op->is_data = 0;
extent_op->level = level;

ret = btrfs_add_delayed_tree_ref(root->fs_info, trans,
ins.objectid,
Expand Down Expand Up @@ -6934,7 +6939,8 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans,
ret = btrfs_dec_ref(trans, root, eb, 0, wc->for_reloc);
BUG_ON(ret); /* -ENOMEM */
ret = btrfs_set_disk_extent_flags(trans, root, eb->start,
eb->len, flag, 0);
eb->len, flag,
btrfs_header_level(eb), 0);
BUG_ON(ret); /* -ENOMEM */
wc->flags[level] |= flag;
}
Expand Down
Loading

0 comments on commit 130901b

Please sign in to comment.