Commit 48c0d9ec authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable

* git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable:
  Btrfs: hold trans_mutex when using btrfs_record_root_in_trans
  Btrfs: make a lockdep class for the extent buffer locks
  Btrfs: fs/btrfs/volumes.c: remove useless kzalloc
  Btrfs: remove unused code in split_state()
  Btrfs: remove btrfs_init_path
  Btrfs: balance_level checks !child after access
  Btrfs: Avoid using __GFP_HIGHMEM with slab allocator
  Btrfs: don't clean old snapshots on sync(1)
  Btrfs: use larger metadata clusters in ssd mode
  Btrfs: process mount options on mount -o remount,
  Btrfs: make sure all pending extent operations are complete
parents 0637810f 24562425
...@@ -38,19 +38,12 @@ static int balance_node_right(struct btrfs_trans_handle *trans, ...@@ -38,19 +38,12 @@ static int balance_node_right(struct btrfs_trans_handle *trans,
static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct btrfs_path *path, int level, int slot); struct btrfs_path *path, int level, int slot);
inline void btrfs_init_path(struct btrfs_path *p)
{
memset(p, 0, sizeof(*p));
}
struct btrfs_path *btrfs_alloc_path(void) struct btrfs_path *btrfs_alloc_path(void)
{ {
struct btrfs_path *path; struct btrfs_path *path;
path = kmem_cache_alloc(btrfs_path_cachep, GFP_NOFS); path = kmem_cache_zalloc(btrfs_path_cachep, GFP_NOFS);
if (path) { if (path)
btrfs_init_path(path);
path->reada = 1; path->reada = 1;
}
return path; return path;
} }
...@@ -69,14 +62,38 @@ noinline void btrfs_set_path_blocking(struct btrfs_path *p) ...@@ -69,14 +62,38 @@ noinline void btrfs_set_path_blocking(struct btrfs_path *p)
/* /*
* reset all the locked nodes in the patch to spinning locks. * reset all the locked nodes in the patch to spinning locks.
*
* held is used to keep lockdep happy, when lockdep is enabled
* we set held to a blocking lock before we go around and
* retake all the spinlocks in the path. You can safely use NULL
* for held
*/ */
noinline void btrfs_clear_path_blocking(struct btrfs_path *p) noinline void btrfs_clear_path_blocking(struct btrfs_path *p,
struct extent_buffer *held)
{ {
int i; int i;
for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
#ifdef CONFIG_DEBUG_LOCK_ALLOC
/* lockdep really cares that we take all of these spinlocks
* in the right order. If any of the locks in the path are not
* currently blocking, it is going to complain. So, make really
* really sure by forcing the path to blocking before we clear
* the path blocking.
*/
if (held)
btrfs_set_lock_blocking(held);
btrfs_set_path_blocking(p);
#endif
for (i = BTRFS_MAX_LEVEL - 1; i >= 0; i--) {
if (p->nodes[i] && p->locks[i]) if (p->nodes[i] && p->locks[i])
btrfs_clear_lock_blocking(p->nodes[i]); btrfs_clear_lock_blocking(p->nodes[i]);
} }
#ifdef CONFIG_DEBUG_LOCK_ALLOC
if (held)
btrfs_clear_lock_blocking(held);
#endif
} }
/* this also releases the path */ /* this also releases the path */
...@@ -286,7 +303,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, ...@@ -286,7 +303,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
trans->transid, level, &ins); trans->transid, level, &ins);
BUG_ON(ret); BUG_ON(ret);
cow = btrfs_init_new_buffer(trans, root, prealloc_dest, cow = btrfs_init_new_buffer(trans, root, prealloc_dest,
buf->len); buf->len, level);
} else { } else {
cow = btrfs_alloc_free_block(trans, root, buf->len, cow = btrfs_alloc_free_block(trans, root, buf->len,
parent_start, parent_start,
...@@ -917,9 +934,9 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, ...@@ -917,9 +934,9 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
/* promote the child to a root */ /* promote the child to a root */
child = read_node_slot(root, mid, 0); child = read_node_slot(root, mid, 0);
BUG_ON(!child);
btrfs_tree_lock(child); btrfs_tree_lock(child);
btrfs_set_lock_blocking(child); btrfs_set_lock_blocking(child);
BUG_ON(!child);
ret = btrfs_cow_block(trans, root, child, mid, 0, &child, 0); ret = btrfs_cow_block(trans, root, child, mid, 0, &child, 0);
BUG_ON(ret); BUG_ON(ret);
...@@ -1566,7 +1583,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1566,7 +1583,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
if (!p->skip_locking) if (!p->skip_locking)
p->locks[level] = 1; p->locks[level] = 1;
btrfs_clear_path_blocking(p); btrfs_clear_path_blocking(p, NULL);
/* /*
* we have a lock on b and as long as we aren't changing * we have a lock on b and as long as we aren't changing
...@@ -1605,7 +1622,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1605,7 +1622,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_set_path_blocking(p); btrfs_set_path_blocking(p);
sret = split_node(trans, root, p, level); sret = split_node(trans, root, p, level);
btrfs_clear_path_blocking(p); btrfs_clear_path_blocking(p, NULL);
BUG_ON(sret > 0); BUG_ON(sret > 0);
if (sret) { if (sret) {
...@@ -1625,7 +1642,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1625,7 +1642,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_set_path_blocking(p); btrfs_set_path_blocking(p);
sret = balance_level(trans, root, p, level); sret = balance_level(trans, root, p, level);
btrfs_clear_path_blocking(p); btrfs_clear_path_blocking(p, NULL);
if (sret) { if (sret) {
ret = sret; ret = sret;
...@@ -1688,13 +1705,13 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1688,13 +1705,13 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
if (!p->skip_locking) { if (!p->skip_locking) {
int lret; int lret;
btrfs_clear_path_blocking(p); btrfs_clear_path_blocking(p, NULL);
lret = btrfs_try_spin_lock(b); lret = btrfs_try_spin_lock(b);
if (!lret) { if (!lret) {
btrfs_set_path_blocking(p); btrfs_set_path_blocking(p);
btrfs_tree_lock(b); btrfs_tree_lock(b);
btrfs_clear_path_blocking(p); btrfs_clear_path_blocking(p, b);
} }
} }
} else { } else {
...@@ -1706,7 +1723,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1706,7 +1723,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_set_path_blocking(p); btrfs_set_path_blocking(p);
sret = split_leaf(trans, root, key, sret = split_leaf(trans, root, key,
p, ins_len, ret == 0); p, ins_len, ret == 0);
btrfs_clear_path_blocking(p); btrfs_clear_path_blocking(p, NULL);
BUG_ON(sret > 0); BUG_ON(sret > 0);
if (sret) { if (sret) {
...@@ -3926,7 +3943,6 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key, ...@@ -3926,7 +3943,6 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
btrfs_release_path(root, path); btrfs_release_path(root, path);
goto again; goto again;
} else { } else {
btrfs_clear_path_blocking(path);
goto out; goto out;
} }
} }
...@@ -3946,7 +3962,7 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key, ...@@ -3946,7 +3962,7 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
path->locks[level - 1] = 1; path->locks[level - 1] = 1;
path->nodes[level - 1] = cur; path->nodes[level - 1] = cur;
unlock_up(path, level, 1); unlock_up(path, level, 1);
btrfs_clear_path_blocking(path); btrfs_clear_path_blocking(path, NULL);
} }
out: out:
if (ret == 0) if (ret == 0)
......
...@@ -43,11 +43,7 @@ struct btrfs_ordered_sum; ...@@ -43,11 +43,7 @@ struct btrfs_ordered_sum;
#define BTRFS_ACL_NOT_CACHED ((void *)-1) #define BTRFS_ACL_NOT_CACHED ((void *)-1)
#ifdef CONFIG_LOCKDEP #define BTRFS_MAX_LEVEL 8
# define BTRFS_MAX_LEVEL 7
#else
# define BTRFS_MAX_LEVEL 8
#endif
/* holds pointers to all of the tree roots */ /* holds pointers to all of the tree roots */
#define BTRFS_ROOT_TREE_OBJECTID 1ULL #define BTRFS_ROOT_TREE_OBJECTID 1ULL
...@@ -1715,7 +1711,8 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, ...@@ -1715,7 +1711,8 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
u64 empty_size); u64 empty_size);
struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
u64 bytenr, u32 blocksize); u64 bytenr, u32 blocksize,
int level);
int btrfs_alloc_extent(struct btrfs_trans_handle *trans, int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
u64 num_bytes, u64 parent, u64 min_bytes, u64 num_bytes, u64 parent, u64 min_bytes,
...@@ -1834,9 +1831,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, ...@@ -1834,9 +1831,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p); void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p);
struct btrfs_path *btrfs_alloc_path(void); struct btrfs_path *btrfs_alloc_path(void);
void btrfs_free_path(struct btrfs_path *p); void btrfs_free_path(struct btrfs_path *p);
void btrfs_init_path(struct btrfs_path *p);
void btrfs_set_path_blocking(struct btrfs_path *p); void btrfs_set_path_blocking(struct btrfs_path *p);
void btrfs_clear_path_blocking(struct btrfs_path *p);
void btrfs_unlock_up_safe(struct btrfs_path *p, int level); void btrfs_unlock_up_safe(struct btrfs_path *p, int level);
int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
......
...@@ -75,6 +75,40 @@ struct async_submit_bio { ...@@ -75,6 +75,40 @@ struct async_submit_bio {
struct btrfs_work work; struct btrfs_work work;
}; };
/* These are used to set the lockdep class on the extent buffer locks.
* The class is set by the readpage_end_io_hook after the buffer has
* passed csum validation but before the pages are unlocked.
*
* The lockdep class is also set by btrfs_init_new_buffer on freshly
* allocated blocks.
*
* The class is based on the level in the tree block, which allows lockdep
* to know that lower nodes nest inside the locks of higher nodes.
*
* We also add a check to make sure the highest level of the tree is
* the same as our lockdep setup here. If BTRFS_MAX_LEVEL changes, this
* code needs update as well.
*/
#ifdef CONFIG_DEBUG_LOCK_ALLOC
# if BTRFS_MAX_LEVEL != 8
# error
# endif
static struct lock_class_key btrfs_eb_class[BTRFS_MAX_LEVEL + 1];
static const char *btrfs_eb_name[BTRFS_MAX_LEVEL + 1] = {
/* leaf */
"btrfs-extent-00",
"btrfs-extent-01",
"btrfs-extent-02",
"btrfs-extent-03",
"btrfs-extent-04",
"btrfs-extent-05",
"btrfs-extent-06",
"btrfs-extent-07",
/* highest possible level */
"btrfs-extent-08",
};
#endif
/* /*
* extents on the btree inode are pretty simple, there's one extent * extents on the btree inode are pretty simple, there's one extent
* that covers the entire device * that covers the entire device
...@@ -347,6 +381,15 @@ static int check_tree_block_fsid(struct btrfs_root *root, ...@@ -347,6 +381,15 @@ static int check_tree_block_fsid(struct btrfs_root *root,
return ret; return ret;
} }
#ifdef CONFIG_DEBUG_LOCK_ALLOC
void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level)
{
lockdep_set_class_and_name(&eb->lock,
&btrfs_eb_class[level],
btrfs_eb_name[level]);
}
#endif
static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
struct extent_state *state) struct extent_state *state)
{ {
...@@ -392,6 +435,8 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, ...@@ -392,6 +435,8 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
} }
found_level = btrfs_header_level(eb); found_level = btrfs_header_level(eb);
btrfs_set_buffer_lockdep_class(eb, found_level);
ret = csum_tree_block(root, eb, 1); ret = csum_tree_block(root, eb, 1);
if (ret) if (ret)
ret = -EIO; ret = -EIO;
...@@ -1777,7 +1822,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, ...@@ -1777,7 +1822,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
ret = find_and_setup_root(tree_root, fs_info, ret = find_and_setup_root(tree_root, fs_info,
BTRFS_DEV_TREE_OBJECTID, dev_root); BTRFS_DEV_TREE_OBJECTID, dev_root);
dev_root->track_dirty = 1; dev_root->track_dirty = 1;
if (ret) if (ret)
goto fail_extent_root; goto fail_extent_root;
......
...@@ -101,4 +101,14 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, ...@@ -101,4 +101,14 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
int btrfs_add_log_tree(struct btrfs_trans_handle *trans, int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
struct btrfs_root *root); struct btrfs_root *root);
int btree_lock_page_hook(struct page *page); int btree_lock_page_hook(struct page *page);
#ifdef CONFIG_DEBUG_LOCK_ALLOC
void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level);
#else
static inline void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb,
int level)
{
}
#endif
#endif #endif
...@@ -1323,8 +1323,25 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, ...@@ -1323,8 +1323,25 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
int btrfs_extent_post_op(struct btrfs_trans_handle *trans, int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
struct btrfs_root *root) struct btrfs_root *root)
{ {
u64 start;
u64 end;
int ret;
while(1) {
finish_current_insert(trans, root->fs_info->extent_root, 1); finish_current_insert(trans, root->fs_info->extent_root, 1);
del_pending_extents(trans, root->fs_info->extent_root, 1); del_pending_extents(trans, root->fs_info->extent_root, 1);
/* is there more work to do? */
ret = find_first_extent_bit(&root->fs_info->pending_del,
0, &start, &end, EXTENT_WRITEBACK);
if (!ret)
continue;
ret = find_first_extent_bit(&root->fs_info->extent_ins,
0, &start, &end, EXTENT_WRITEBACK);
if (!ret)
continue;
break;
}
return 0; return 0;
} }
...@@ -2211,13 +2228,12 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, ...@@ -2211,13 +2228,12 @@ static int finish_current_insert(struct btrfs_trans_handle *trans,
u64 end; u64 end;
u64 priv; u64 priv;
u64 search = 0; u64 search = 0;
u64 skipped = 0;
struct btrfs_fs_info *info = extent_root->fs_info; struct btrfs_fs_info *info = extent_root->fs_info;
struct btrfs_path *path; struct btrfs_path *path;
struct pending_extent_op *extent_op, *tmp; struct pending_extent_op *extent_op, *tmp;
struct list_head insert_list, update_list; struct list_head insert_list, update_list;
int ret; int ret;
int num_inserts = 0, max_inserts; int num_inserts = 0, max_inserts, restart = 0;
path = btrfs_alloc_path(); path = btrfs_alloc_path();
INIT_LIST_HEAD(&insert_list); INIT_LIST_HEAD(&insert_list);
...@@ -2233,19 +2249,19 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, ...@@ -2233,19 +2249,19 @@ static int finish_current_insert(struct btrfs_trans_handle *trans,
ret = find_first_extent_bit(&info->extent_ins, search, &start, ret = find_first_extent_bit(&info->extent_ins, search, &start,
&end, EXTENT_WRITEBACK); &end, EXTENT_WRITEBACK);
if (ret) { if (ret) {
if (skipped && all && !num_inserts && if (restart && !num_inserts &&
list_empty(&update_list)) { list_empty(&update_list)) {
skipped = 0; restart = 0;
search = 0; search = 0;
continue; continue;
} }
mutex_unlock(&info->extent_ins_mutex);
break; break;
} }
ret = try_lock_extent(&info->extent_ins, start, end, GFP_NOFS); ret = try_lock_extent(&info->extent_ins, start, end, GFP_NOFS);
if (!ret) { if (!ret) {
skipped = 1; if (all)
restart = 1;
search = end + 1; search = end + 1;
if (need_resched()) { if (need_resched()) {
mutex_unlock(&info->extent_ins_mutex); mutex_unlock(&info->extent_ins_mutex);
...@@ -2264,7 +2280,7 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, ...@@ -2264,7 +2280,7 @@ static int finish_current_insert(struct btrfs_trans_handle *trans,
list_add_tail(&extent_op->list, &insert_list); list_add_tail(&extent_op->list, &insert_list);
search = end + 1; search = end + 1;
if (num_inserts == max_inserts) { if (num_inserts == max_inserts) {
mutex_unlock(&info->extent_ins_mutex); restart = 1;
break; break;
} }
} else if (extent_op->type == PENDING_BACKREF_UPDATE) { } else if (extent_op->type == PENDING_BACKREF_UPDATE) {
...@@ -2280,7 +2296,6 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, ...@@ -2280,7 +2296,6 @@ static int finish_current_insert(struct btrfs_trans_handle *trans,
* somebody marked this thing for deletion then just unlock it and be * somebody marked this thing for deletion then just unlock it and be
* done, the free_extents will handle it * done, the free_extents will handle it
*/ */
mutex_lock(&info->extent_ins_mutex);
list_for_each_entry_safe(extent_op, tmp, &update_list, list) { list_for_each_entry_safe(extent_op, tmp, &update_list, list) {
clear_extent_bits(&info->extent_ins, extent_op->bytenr, clear_extent_bits(&info->extent_ins, extent_op->bytenr,
extent_op->bytenr + extent_op->num_bytes - 1, extent_op->bytenr + extent_op->num_bytes - 1,
...@@ -2302,6 +2317,10 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, ...@@ -2302,6 +2317,10 @@ static int finish_current_insert(struct btrfs_trans_handle *trans,
if (!list_empty(&update_list)) { if (!list_empty(&update_list)) {
ret = update_backrefs(trans, extent_root, path, &update_list); ret = update_backrefs(trans, extent_root, path, &update_list);
BUG_ON(ret); BUG_ON(ret);
/* we may have COW'ed new blocks, so lets start over */
if (all)
restart = 1;
} }
/* /*
...@@ -2309,9 +2328,9 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, ...@@ -2309,9 +2328,9 @@ static int finish_current_insert(struct btrfs_trans_handle *trans,
* need to make sure everything is cleaned then reset everything and * need to make sure everything is cleaned then reset everything and
* go back to the beginning * go back to the beginning
*/ */
if (!num_inserts && all && skipped) { if (!num_inserts && restart) {
search = 0; search = 0;
skipped = 0; restart = 0;
INIT_LIST_HEAD(&update_list); INIT_LIST_HEAD(&update_list);
INIT_LIST_HEAD(&insert_list); INIT_LIST_HEAD(&insert_list);
goto again; goto again;
...@@ -2368,27 +2387,19 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, ...@@ -2368,27 +2387,19 @@ static int finish_current_insert(struct btrfs_trans_handle *trans,
BUG_ON(ret); BUG_ON(ret);
/* /*
* if we broke out of the loop in order to insert stuff because we hit * if restart is set for whatever reason we need to go back and start
* the maximum number of inserts at a time we can handle, then loop * searching through the pending list again.
* back and pick up where we left off *
*/ * We just inserted some extents, which could have resulted in new
if (num_inserts == max_inserts) { * blocks being allocated, which would result in new blocks needing
INIT_LIST_HEAD(&insert_list); * updates, so if all is set we _must_ restart to get the updated
INIT_LIST_HEAD(&update_list); * blocks.
num_inserts = 0;
goto again;
}
/*
* again, if we need to make absolutely sure there are no more pending
* extent operations left and we know that we skipped some, go back to
* the beginning and do it all again
*/ */
if (all && skipped) { if (restart || all) {
INIT_LIST_HEAD(&insert_list); INIT_LIST_HEAD(&insert_list);
INIT_LIST_HEAD(&update_list); INIT_LIST_HEAD(&update_list);
search = 0; search = 0;
skipped = 0; restart = 0;
num_inserts = 0; num_inserts = 0;
goto again; goto again;
} }
...@@ -2709,6 +2720,8 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, ...@@ -2709,6 +2720,8 @@ static int del_pending_extents(struct btrfs_trans_handle *trans,
goto again; goto again;
} }
if (!err)
finish_current_insert(trans, extent_root, 0);
return err; return err;
} }
...@@ -2859,6 +2872,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, ...@@ -2859,6 +2872,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
if (data & BTRFS_BLOCK_GROUP_METADATA) { if (data & BTRFS_BLOCK_GROUP_METADATA) {
last_ptr = &root->fs_info->last_alloc; last_ptr = &root->fs_info->last_alloc;
if (!btrfs_test_opt(root, SSD))
empty_cluster = 64 * 1024; empty_cluster = 64 * 1024;
} }
...@@ -3402,7 +3416,8 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, ...@@ -3402,7 +3416,8 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
u64 bytenr, u32 blocksize) u64 bytenr, u32 blocksize,
int level)
{ {
struct extent_buffer *buf; struct extent_buffer *buf;
...@@ -3410,6 +3425,7 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans, ...@@ -3410,6 +3425,7 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
if (!buf) if (!buf)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
btrfs_set_header_generation(buf, trans->transid); btrfs_set_header_generation(buf, trans->transid);
btrfs_set_buffer_lockdep_class(buf, level);
btrfs_tree_lock(buf); btrfs_tree_lock(buf);
clean_tree_block(trans, root, buf); clean_tree_block(trans, root, buf);
...@@ -3453,7 +3469,8 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, ...@@ -3453,7 +3469,8 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
return ERR_PTR(ret); return ERR_PTR(ret);
} }
buf = btrfs_init_new_buffer(trans, root, ins.objectid, blocksize); buf = btrfs_init_new_buffer(trans, root, ins.objectid,
blocksize, level);
return buf; return buf;
} }
...@@ -5641,7 +5658,9 @@ static noinline int relocate_one_extent(struct btrfs_root *extent_root, ...@@ -5641,7 +5658,9 @@ static noinline int relocate_one_extent(struct btrfs_root *extent_root,
prev_block = block_start; prev_block = block_start;
} }
mutex_lock(&extent_root->fs_info->trans_mutex);
btrfs_record_root_in_trans(found_root); btrfs_record_root_in_trans(found_root);
mutex_unlock(&extent_root->fs_info->trans_mutex);
if (ref_path->owner_objectid >= BTRFS_FIRST_FREE_OBJECTID) { if (ref_path->owner_objectid >= BTRFS_FIRST_FREE_OBJECTID) {
/* /*
* try to update data extent references while * try to update data extent references while
......
...@@ -415,8 +415,6 @@ static int split_state(struct extent_io_tree *tree, struct extent_state *orig, ...@@ -415,8 +415,6 @@ static int split_state(struct extent_io_tree *tree, struct extent_state *orig,
node = tree_insert(&tree->state, prealloc->end, &prealloc->rb_node); node = tree_insert(&tree->state, prealloc->end, &prealloc->rb_node);
if (node) { if (node) {
struct extent_state *found;
found = rb_entry(node, struct extent_state, rb_node);
free_extent_state(prealloc); free_extent_state(prealloc);
return -EEXIST; return -EEXIST;
} }
......
...@@ -84,7 +84,6 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, ...@@ -84,7 +84,6 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
search_key.type = 0; search_key.type = 0;
search_key.offset = 0; search_key.offset = 0;
btrfs_init_path(path);
start_found = 0; start_found = 0;
ret = btrfs_search_slot(trans, root, &search_key, path, 0, 0); ret = btrfs_search_slot(trans, root, &search_key, path, 0, 0);
if (ret < 0) if (ret < 0)
......
...@@ -2531,8 +2531,6 @@ noinline int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, ...@@ -2531,8 +2531,6 @@ noinline int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
key.offset = (u64)-1; key.offset = (u64)-1;
key.type = (u8)-1; key.type = (u8)-1;
btrfs_init_path(path);
search_again: search_again:
ret = btrfs_search_slot(trans, root, &key, path, -1, 1); ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
if (ret < 0) if (ret < 0)
...@@ -4263,7 +4261,7 @@ static int btrfs_releasepage(struct page *page, gfp_t gfp_flags) ...@@ -4263,7 +4261,7 @@ static int btrfs_releasepage(struct page *page, gfp_t gfp_flags)
{ {
if (PageWriteback(page) || PageDirty(page)) if (PageWriteback(page) || PageDirty(page))
return 0; return 0;
return __btrfs_releasepage(page, gfp_flags); return __btrfs_releasepage(page, gfp_flags & GFP_NOFS);
} }
static void btrfs_invalidatepage(struct page *page, unsigned long offset) static void btrfs_invalidatepage(struct page *page, unsigned long offset)
......
...@@ -25,21 +25,10 @@ ...@@ -25,21 +25,10 @@
#include "extent_io.h" #include "extent_io.h"
#include "locking.h" #include "locking.h"
/*
* btrfs_header_level() isn't free, so don't call it when lockdep isn't
* on
*/
#ifdef CONFIG_DEBUG_LOCK_ALLOC
static inline void spin_nested(struct extent_buffer *eb)
{
spin_lock_nested(&eb->lock, BTRFS_MAX_LEVEL - btrfs_header_level(eb));
}
#else
static inline void spin_nested(struct extent_buffer *eb) static inline void spin_nested(struct extent_buffer *eb)
{ {
spin_lock(&eb->lock); spin_lock(&eb->lock);
} }
#endif
/* /*
* Setting a lock to blocking will drop the spinlock and set the * Setting a lock to blocking will drop the spinlock and set the
......
...@@ -379,7 +379,6 @@ int btrfs_sync_fs(struct super_block *sb, int wait) ...@@ -379,7 +379,6 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
btrfs_start_delalloc_inodes(root); btrfs_start_delalloc_inodes(root);
btrfs_wait_ordered_extents(root, 0); btrfs_wait_ordered_extents(root, 0);
btrfs_clean_old_snapshots(root);
trans = btrfs_start_transaction(root, 1); trans = btrfs_start_transaction(root, 1);
ret = btrfs_commit_transaction(trans, root); ret = btrfs_commit_transaction(trans, root);
sb->s_dirt = 0; sb->s_dirt = 0;
...@@ -511,6 +510,10 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) ...@@ -511,6 +510,10 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
struct btrfs_root *root = btrfs_sb(sb); struct btrfs_root *root = btrfs_sb(sb);
int ret; int ret;
ret = btrfs_parse_options(root, data);
if (ret)
return -EINVAL;
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
return 0; return 0;
......
...@@ -688,7 +688,9 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root, ...@@ -688,7 +688,9 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
num_bytes -= btrfs_root_used(&dirty->root->root_item); num_bytes -= btrfs_root_used(&dirty->root->root_item);
bytes_used = btrfs_root_used(&root->root_item); bytes_used = btrfs_root_used(&root->root_item);
if (num_bytes) { if (num_bytes) {
mutex_lock(&root->fs_info->trans_mutex);
btrfs_record_root_in_trans(root); btrfs_record_root_in_trans(root);
mutex_unlock(&root->fs_info->trans_mutex);
btrfs_set_root_used(&root->root_item, btrfs_set_root_used(&root->root_item,
bytes_used - num_bytes); bytes_used - num_bytes);
} }
......
...@@ -2832,7 +2832,9 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree) ...@@ -2832,7 +2832,9 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
BUG_ON(!wc.replay_dest); BUG_ON(!wc.replay_dest);
wc.replay_dest->log_root = log; wc.replay_dest->log_root = log;
mutex_lock(&fs_info->trans_mutex);
btrfs_record_root_in_trans(wc.replay_dest); btrfs_record_root_in_trans(wc.replay_dest);
mutex_unlock(&fs_info->trans_mutex);
ret = walk_log_tree(trans, log, &wc); ret = walk_log_tree(trans, log, &wc);
BUG_ON(ret); BUG_ON(ret);
......
...@@ -2894,10 +2894,6 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, ...@@ -2894,10 +2894,6 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
free_extent_map(em); free_extent_map(em);
} }
map = kzalloc(sizeof(*map), GFP_NOFS);
if (!map)
return -ENOMEM;
em = alloc_extent_map(GFP_NOFS); em = alloc_extent_map(GFP_NOFS);
if (!em) if (!em)
return -ENOMEM; return -ENOMEM;
...@@ -3106,6 +3102,8 @@ int btrfs_read_sys_array(struct btrfs_root *root) ...@@ -3106,6 +3102,8 @@ int btrfs_read_sys_array(struct btrfs_root *root)
if (!sb) if (!sb)
return -ENOMEM; return -ENOMEM;
btrfs_set_buffer_uptodate(sb); btrfs_set_buffer_uptodate(sb);
btrfs_set_buffer_lockdep_class(sb, 0);
write_extent_buffer(sb, super_copy, 0, BTRFS_SUPER_INFO_SIZE); write_extent_buffer(sb, super_copy, 0, BTRFS_SUPER_INFO_SIZE);
array_size = btrfs_super_sys_array_size(super_copy); array_size = btrfs_super_sys_array_size(super_copy);
......
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