aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/disk-io.c17
-rw-r--r--fs/btrfs/extent-tree.c7
-rw-r--r--fs/btrfs/transaction.c21
-rw-r--r--fs/btrfs/transaction.h2
-rw-r--r--fs/btrfs/tree-log.c29
6 files changed, 54 insertions, 24 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 2ed6918f32e5..eb65fd808883 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -668,6 +668,8 @@ struct btrfs_root {
668 struct btrfs_key root_key; 668 struct btrfs_key root_key;
669 struct btrfs_fs_info *fs_info; 669 struct btrfs_fs_info *fs_info;
670 struct inode *inode; 670 struct inode *inode;
671 struct extent_io_tree dirty_log_pages;
672
671 struct kobject root_kobj; 673 struct kobject root_kobj;
672 struct completion kobj_unregister; 674 struct completion kobj_unregister;
673 struct mutex objectid_mutex; 675 struct mutex objectid_mutex;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 5edb7f885799..57fbf107e59f 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -777,6 +777,8 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
777 spin_lock_init(&root->list_lock); 777 spin_lock_init(&root->list_lock);
778 mutex_init(&root->objectid_mutex); 778 mutex_init(&root->objectid_mutex);
779 mutex_init(&root->log_mutex); 779 mutex_init(&root->log_mutex);
780 extent_io_tree_init(&root->dirty_log_pages,
781 fs_info->btree_inode->i_mapping, GFP_NOFS);
780 782
781 btrfs_leaf_ref_tree_init(&root->ref_tree_struct); 783 btrfs_leaf_ref_tree_init(&root->ref_tree_struct);
782 root->ref_tree = &root->ref_tree_struct; 784 root->ref_tree = &root->ref_tree_struct;
@@ -819,11 +821,23 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans,
819 struct btrfs_fs_info *fs_info) 821 struct btrfs_fs_info *fs_info)
820{ 822{
821 struct extent_buffer *eb; 823 struct extent_buffer *eb;
824 struct btrfs_root *log_root_tree = fs_info->log_root_tree;
825 u64 start = 0;
826 u64 end = 0;
822 int ret; 827 int ret;
823 828
824 if (!fs_info->log_root_tree) 829 if (!log_root_tree)
825 return 0; 830 return 0;
826 831
832 while(1) {
833 ret = find_first_extent_bit(&log_root_tree->dirty_log_pages,
834 0, &start, &end, EXTENT_DIRTY);
835 if (ret)
836 break;
837
838 clear_extent_dirty(&log_root_tree->dirty_log_pages,
839 start, end, GFP_NOFS);
840 }
827 eb = fs_info->log_root_tree->node; 841 eb = fs_info->log_root_tree->node;
828 842
829 WARN_ON(btrfs_header_level(eb) != 0); 843 WARN_ON(btrfs_header_level(eb) != 0);
@@ -1412,7 +1426,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1412 memset(&BTRFS_I(fs_info->btree_inode)->location, 0, 1426 memset(&BTRFS_I(fs_info->btree_inode)->location, 0,
1413 sizeof(struct btrfs_key)); 1427 sizeof(struct btrfs_key));
1414 insert_inode_hash(fs_info->btree_inode); 1428 insert_inode_hash(fs_info->btree_inode);
1415 mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS);
1416 1429
1417 mutex_init(&fs_info->trans_mutex); 1430 mutex_init(&fs_info->trans_mutex);
1418 mutex_init(&fs_info->tree_log_mutex); 1431 mutex_init(&fs_info->tree_log_mutex);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index c479d71e2869..c0bb6b9ac4c6 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2392,8 +2392,13 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
2392 btrfs_tree_lock(buf); 2392 btrfs_tree_lock(buf);
2393 clean_tree_block(trans, root, buf); 2393 clean_tree_block(trans, root, buf);
2394 btrfs_set_buffer_uptodate(buf); 2394 btrfs_set_buffer_uptodate(buf);
2395 set_extent_dirty(&trans->transaction->dirty_pages, buf->start, 2395 if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) {
2396 set_extent_dirty(&root->dirty_log_pages, buf->start,
2397 buf->start + buf->len - 1, GFP_NOFS);
2398 } else {
2399 set_extent_dirty(&trans->transaction->dirty_pages, buf->start,
2396 buf->start + buf->len - 1, GFP_NOFS); 2400 buf->start + buf->len - 1, GFP_NOFS);
2401 }
2397 trans->blocks_used++; 2402 trans->blocks_used++;
2398 return buf; 2403 return buf;
2399} 2404}
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 61a377bcb2fb..151b00d52593 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -302,23 +302,18 @@ int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans,
302} 302}
303 303
304 304
305int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, 305int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
306 struct btrfs_root *root) 306 struct extent_io_tree *dirty_pages)
307{ 307{
308 int ret; 308 int ret;
309 int err = 0; 309 int err = 0;
310 int werr = 0; 310 int werr = 0;
311 struct extent_io_tree *dirty_pages;
312 struct page *page; 311 struct page *page;
313 struct inode *btree_inode = root->fs_info->btree_inode; 312 struct inode *btree_inode = root->fs_info->btree_inode;
314 u64 start = 0; 313 u64 start = 0;
315 u64 end; 314 u64 end;
316 unsigned long index; 315 unsigned long index;
317 316
318 if (!trans || !trans->transaction) {
319 return filemap_write_and_wait(btree_inode->i_mapping);
320 }
321 dirty_pages = &trans->transaction->dirty_pages;
322 while(1) { 317 while(1) {
323 ret = find_first_extent_bit(dirty_pages, start, &start, &end, 318 ret = find_first_extent_bit(dirty_pages, start, &start, &end,
324 EXTENT_DIRTY); 319 EXTENT_DIRTY);
@@ -385,6 +380,18 @@ int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
385 return werr; 380 return werr;
386} 381}
387 382
383int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
384 struct btrfs_root *root)
385{
386 if (!trans || !trans->transaction) {
387 struct inode *btree_inode;
388 btree_inode = root->fs_info->btree_inode;
389 return filemap_write_and_wait(btree_inode->i_mapping);
390 }
391 return btrfs_write_and_wait_marked_extents(root,
392 &trans->transaction->dirty_pages);
393}
394
388static int update_cowonly_root(struct btrfs_trans_handle *trans, 395static int update_cowonly_root(struct btrfs_trans_handle *trans,
389 struct btrfs_root *root) 396 struct btrfs_root *root)
390{ 397{
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index cc63650d60d6..eef2cb7d7e78 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -99,4 +99,6 @@ int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans,
99 struct btrfs_root *root); 99 struct btrfs_root *root);
100void btrfs_throttle(struct btrfs_root *root); 100void btrfs_throttle(struct btrfs_root *root);
101int btrfs_record_root_in_trans(struct btrfs_root *root); 101int btrfs_record_root_in_trans(struct btrfs_root *root);
102int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
103 struct extent_io_tree *dirty_pages);
102#endif 104#endif
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index ae96451bc223..bfa710800963 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -1954,10 +1954,6 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
1954 int ret; 1954 int ret;
1955 unsigned long batch; 1955 unsigned long batch;
1956 struct btrfs_root *log = root->log_root; 1956 struct btrfs_root *log = root->log_root;
1957 struct walk_control wc = {
1958 .write = 1,
1959 .process_func = process_one_buffer
1960 };
1961 1957
1962 mutex_lock(&log->fs_info->tree_log_mutex); 1958 mutex_lock(&log->fs_info->tree_log_mutex);
1963 if (atomic_read(&log->fs_info->tree_log_commit)) { 1959 if (atomic_read(&log->fs_info->tree_log_commit)) {
@@ -1985,18 +1981,11 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
1985 if (batch == log->fs_info->tree_log_batch) 1981 if (batch == log->fs_info->tree_log_batch)
1986 break; 1982 break;
1987 } 1983 }
1988 ret = walk_log_tree(trans, log, &wc);
1989 BUG_ON(ret);
1990
1991 ret = walk_log_tree(trans, log->fs_info->log_root_tree, &wc);
1992 BUG_ON(ret);
1993
1994 wc.wait = 1;
1995 1984
1996 ret = walk_log_tree(trans, log, &wc); 1985 ret = btrfs_write_and_wait_marked_extents(log, &log->dirty_log_pages);
1997 BUG_ON(ret); 1986 BUG_ON(ret);
1998 1987 ret = btrfs_write_and_wait_marked_extents(root->fs_info->log_root_tree,
1999 ret = walk_log_tree(trans, log->fs_info->log_root_tree, &wc); 1988 &root->fs_info->log_root_tree->dirty_log_pages);
2000 BUG_ON(ret); 1989 BUG_ON(ret);
2001 1990
2002 btrfs_set_super_log_root(&root->fs_info->super_for_commit, 1991 btrfs_set_super_log_root(&root->fs_info->super_for_commit,
@@ -2025,6 +2014,8 @@ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root)
2025 int ret; 2014 int ret;
2026 struct btrfs_root *log; 2015 struct btrfs_root *log;
2027 struct key; 2016 struct key;
2017 u64 start;
2018 u64 end;
2028 struct walk_control wc = { 2019 struct walk_control wc = {
2029 .free = 1, 2020 .free = 1,
2030 .process_func = process_one_buffer 2021 .process_func = process_one_buffer
@@ -2037,6 +2028,16 @@ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root)
2037 ret = walk_log_tree(trans, log, &wc); 2028 ret = walk_log_tree(trans, log, &wc);
2038 BUG_ON(ret); 2029 BUG_ON(ret);
2039 2030
2031 while(1) {
2032 ret = find_first_extent_bit(&log->dirty_log_pages,
2033 0, &start, &end, EXTENT_DIRTY);
2034 if (ret)
2035 break;
2036
2037 clear_extent_dirty(&log->dirty_log_pages,
2038 start, end, GFP_NOFS);
2039 }
2040
2040 log = root->log_root; 2041 log = root->log_root;
2041 ret = btrfs_del_root(trans, root->fs_info->log_root_tree, 2042 ret = btrfs_del_root(trans, root->fs_info->log_root_tree,
2042 &log->root_key); 2043 &log->root_key);