Commit d64dab90 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs

Pull btrfs fixes from Chris Mason:
 "We've got more bug fixes in my for-linus branch:

  One of these fixes another corner of the compression oops from last
  time.  Miao nailed down some problems with concurrent snapshot
  deletion and drive balancing.

  I kept out one of his patches for more testing, but these are all
  stable"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
  Btrfs: fix oops caused by the space balance and dead roots
  Btrfs: insert orphan roots into fs radix tree
  Btrfs: limit delalloc pages outside of find_delalloc_range
  Btrfs: use right root when checking for hash collision
parents d192f0d5 c00869f1
...@@ -1561,8 +1561,9 @@ int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info, ...@@ -1561,8 +1561,9 @@ int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info,
return ret; return ret;
} }
struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info,
struct btrfs_key *location) struct btrfs_key *location,
bool check_ref)
{ {
struct btrfs_root *root; struct btrfs_root *root;
int ret; int ret;
...@@ -1586,7 +1587,7 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, ...@@ -1586,7 +1587,7 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
again: again:
root = btrfs_lookup_fs_root(fs_info, location->objectid); root = btrfs_lookup_fs_root(fs_info, location->objectid);
if (root) { if (root) {
if (btrfs_root_refs(&root->root_item) == 0) if (check_ref && btrfs_root_refs(&root->root_item) == 0)
return ERR_PTR(-ENOENT); return ERR_PTR(-ENOENT);
return root; return root;
} }
...@@ -1595,7 +1596,7 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, ...@@ -1595,7 +1596,7 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
if (IS_ERR(root)) if (IS_ERR(root))
return root; return root;
if (btrfs_root_refs(&root->root_item) == 0) { if (check_ref && btrfs_root_refs(&root->root_item) == 0) {
ret = -ENOENT; ret = -ENOENT;
goto fail; goto fail;
} }
......
...@@ -68,8 +68,17 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_root *tree_root, ...@@ -68,8 +68,17 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_root *tree_root,
int btrfs_init_fs_root(struct btrfs_root *root); int btrfs_init_fs_root(struct btrfs_root *root);
int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info, int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info,
struct btrfs_root *root); struct btrfs_root *root);
struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
struct btrfs_key *location); struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info,
struct btrfs_key *key,
bool check_ref);
static inline struct btrfs_root *
btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
struct btrfs_key *location)
{
return btrfs_get_fs_root(fs_info, location, true);
}
int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info); int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info);
void btrfs_btree_balance_dirty(struct btrfs_root *root); void btrfs_btree_balance_dirty(struct btrfs_root *root);
void btrfs_btree_balance_dirty_nodelay(struct btrfs_root *root); void btrfs_btree_balance_dirty_nodelay(struct btrfs_root *root);
......
...@@ -1490,10 +1490,8 @@ static noinline u64 find_delalloc_range(struct extent_io_tree *tree, ...@@ -1490,10 +1490,8 @@ static noinline u64 find_delalloc_range(struct extent_io_tree *tree,
cur_start = state->end + 1; cur_start = state->end + 1;
node = rb_next(node); node = rb_next(node);
total_bytes += state->end - state->start + 1; total_bytes += state->end - state->start + 1;
if (total_bytes >= max_bytes) { if (total_bytes >= max_bytes)
*end = *start + max_bytes - 1;
break; break;
}
if (!node) if (!node)
break; break;
} }
...@@ -1635,10 +1633,9 @@ static noinline u64 find_lock_delalloc_range(struct inode *inode, ...@@ -1635,10 +1633,9 @@ static noinline u64 find_lock_delalloc_range(struct inode *inode,
/* /*
* make sure to limit the number of pages we try to lock down * make sure to limit the number of pages we try to lock down
* if we're looping.
*/ */
if (delalloc_end + 1 - delalloc_start > max_bytes && loops) if (delalloc_end + 1 - delalloc_start > max_bytes)
delalloc_end = delalloc_start + PAGE_CACHE_SIZE - 1; delalloc_end = delalloc_start + max_bytes - 1;
/* step two, lock all the pages after the page that has start */ /* step two, lock all the pages after the page that has start */
ret = lock_delalloc_pages(inode, locked_page, ret = lock_delalloc_pages(inode, locked_page,
...@@ -1649,8 +1646,7 @@ static noinline u64 find_lock_delalloc_range(struct inode *inode, ...@@ -1649,8 +1646,7 @@ static noinline u64 find_lock_delalloc_range(struct inode *inode,
*/ */
free_extent_state(cached_state); free_extent_state(cached_state);
if (!loops) { if (!loops) {
unsigned long offset = (*start) & (PAGE_CACHE_SIZE - 1); max_bytes = PAGE_CACHE_SIZE;
max_bytes = PAGE_CACHE_SIZE - offset;
loops = 1; loops = 1;
goto again; goto again;
} else { } else {
......
...@@ -7986,7 +7986,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -7986,7 +7986,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
/* check for collisions, even if the name isn't there */ /* check for collisions, even if the name isn't there */
ret = btrfs_check_dir_item_collision(root, new_dir->i_ino, ret = btrfs_check_dir_item_collision(dest, new_dir->i_ino,
new_dentry->d_name.name, new_dentry->d_name.name,
new_dentry->d_name.len); new_dentry->d_name.len);
......
...@@ -588,7 +588,7 @@ static struct btrfs_root *read_fs_root(struct btrfs_fs_info *fs_info, ...@@ -588,7 +588,7 @@ static struct btrfs_root *read_fs_root(struct btrfs_fs_info *fs_info,
else else
key.offset = (u64)-1; key.offset = (u64)-1;
return btrfs_read_fs_root_no_name(fs_info, &key); return btrfs_get_fs_root(fs_info, &key, false);
} }
#ifdef BTRFS_COMPAT_EXTENT_TREE_V0 #ifdef BTRFS_COMPAT_EXTENT_TREE_V0
......
...@@ -299,11 +299,6 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root) ...@@ -299,11 +299,6 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
continue; continue;
} }
if (btrfs_root_refs(&root->root_item) == 0) {
btrfs_add_dead_root(root);
continue;
}
err = btrfs_init_fs_root(root); err = btrfs_init_fs_root(root);
if (err) { if (err) {
btrfs_free_fs_root(root); btrfs_free_fs_root(root);
...@@ -318,6 +313,9 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root) ...@@ -318,6 +313,9 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
btrfs_free_fs_root(root); btrfs_free_fs_root(root);
break; break;
} }
if (btrfs_root_refs(&root->root_item) == 0)
btrfs_add_dead_root(root);
} }
btrfs_free_path(path); btrfs_free_path(path);
......
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