diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.h | 2 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 17 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 7 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 21 | ||||
-rw-r--r-- | fs/btrfs/transaction.h | 2 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 29 |
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 | ||
305 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, | 305 | int 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 | ||
383 | int 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 | |||
388 | static int update_cowonly_root(struct btrfs_trans_handle *trans, | 395 | static 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); |
100 | void btrfs_throttle(struct btrfs_root *root); | 100 | void btrfs_throttle(struct btrfs_root *root); |
101 | int btrfs_record_root_in_trans(struct btrfs_root *root); | 101 | int btrfs_record_root_in_trans(struct btrfs_root *root); |
102 | int 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); |