diff options
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 61 |
1 files changed, 34 insertions, 27 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 087074db0bd5..750f35a37aae 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/fs.h> | 19 | #include <linux/fs.h> |
20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
21 | #include <linux/writeback.h> | 21 | #include <linux/writeback.h> |
22 | #include <linux/pagemap.h> | ||
22 | #include "ctree.h" | 23 | #include "ctree.h" |
23 | #include "disk-io.h" | 24 | #include "disk-io.h" |
24 | #include "transaction.h" | 25 | #include "transaction.h" |
@@ -66,7 +67,9 @@ static int join_transaction(struct btrfs_root *root) | |||
66 | cur_trans->commit_done = 0; | 67 | cur_trans->commit_done = 0; |
67 | cur_trans->start_time = get_seconds(); | 68 | cur_trans->start_time = get_seconds(); |
68 | list_add_tail(&cur_trans->list, &root->fs_info->trans_list); | 69 | list_add_tail(&cur_trans->list, &root->fs_info->trans_list); |
69 | init_bit_radix(&cur_trans->dirty_pages); | 70 | extent_map_tree_init(&cur_trans->dirty_pages, |
71 | root->fs_info->btree_inode->i_mapping, | ||
72 | GFP_NOFS); | ||
70 | } else { | 73 | } else { |
71 | cur_trans->num_writers++; | 74 | cur_trans->num_writers++; |
72 | cur_trans->num_joined++; | 75 | cur_trans->num_joined++; |
@@ -88,7 +91,7 @@ static int record_root_in_trans(struct btrfs_root *root) | |||
88 | (unsigned long)root->root_key.objectid, | 91 | (unsigned long)root->root_key.objectid, |
89 | BTRFS_ROOT_DEFRAG_TAG); | 92 | BTRFS_ROOT_DEFRAG_TAG); |
90 | root->commit_root = root->node; | 93 | root->commit_root = root->node; |
91 | get_bh(root->node); | 94 | extent_buffer_get(root->node); |
92 | } else { | 95 | } else { |
93 | WARN_ON(1); | 96 | WARN_ON(1); |
94 | } | 97 | } |
@@ -144,29 +147,30 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
144 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, | 147 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, |
145 | struct btrfs_root *root) | 148 | struct btrfs_root *root) |
146 | { | 149 | { |
147 | unsigned long gang[16]; | ||
148 | int ret; | 150 | int ret; |
149 | int i; | ||
150 | int err; | 151 | int err; |
151 | int werr = 0; | 152 | int werr = 0; |
153 | struct extent_map_tree *dirty_pages; | ||
152 | struct page *page; | 154 | struct page *page; |
153 | struct radix_tree_root *dirty_pages; | ||
154 | struct inode *btree_inode = root->fs_info->btree_inode; | 155 | struct inode *btree_inode = root->fs_info->btree_inode; |
156 | u64 start; | ||
157 | u64 end; | ||
158 | unsigned long index; | ||
155 | 159 | ||
156 | if (!trans || !trans->transaction) { | 160 | if (!trans || !trans->transaction) { |
157 | return filemap_write_and_wait(btree_inode->i_mapping); | 161 | return filemap_write_and_wait(btree_inode->i_mapping); |
158 | } | 162 | } |
159 | dirty_pages = &trans->transaction->dirty_pages; | 163 | dirty_pages = &trans->transaction->dirty_pages; |
160 | while(1) { | 164 | while(1) { |
161 | ret = find_first_radix_bit(dirty_pages, gang, | 165 | ret = find_first_extent_bit(dirty_pages, 0, &start, &end, |
162 | 0, ARRAY_SIZE(gang)); | 166 | EXTENT_DIRTY); |
163 | if (!ret) | 167 | if (ret) |
164 | break; | 168 | break; |
165 | for (i = 0; i < ret; i++) { | 169 | clear_extent_dirty(dirty_pages, start, end, GFP_NOFS); |
166 | /* FIXME EIO */ | 170 | while(start <= end) { |
167 | clear_radix_bit(dirty_pages, gang[i]); | 171 | index = start >> PAGE_CACHE_SHIFT; |
168 | page = find_lock_page(btree_inode->i_mapping, | 172 | start = (index + 1) << PAGE_CACHE_SHIFT; |
169 | gang[i]); | 173 | page = find_lock_page(btree_inode->i_mapping, index); |
170 | if (!page) | 174 | if (!page) |
171 | continue; | 175 | continue; |
172 | if (PageWriteback(page)) { | 176 | if (PageWriteback(page)) { |
@@ -202,10 +206,11 @@ int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans, | |||
202 | btrfs_write_dirty_block_groups(trans, extent_root); | 206 | btrfs_write_dirty_block_groups(trans, extent_root); |
203 | while(1) { | 207 | while(1) { |
204 | old_extent_block = btrfs_root_blocknr(&extent_root->root_item); | 208 | old_extent_block = btrfs_root_blocknr(&extent_root->root_item); |
205 | if (old_extent_block == bh_blocknr(extent_root->node)) | 209 | if (old_extent_block == |
210 | extent_buffer_blocknr(extent_root->node)) | ||
206 | break; | 211 | break; |
207 | btrfs_set_root_blocknr(&extent_root->root_item, | 212 | btrfs_set_root_blocknr(&extent_root->root_item, |
208 | bh_blocknr(extent_root->node)); | 213 | extent_buffer_blocknr(extent_root->node)); |
209 | ret = btrfs_update_root(trans, tree_root, | 214 | ret = btrfs_update_root(trans, tree_root, |
210 | &extent_root->root_key, | 215 | &extent_root->root_key, |
211 | &extent_root->root_item); | 216 | &extent_root->root_item); |
@@ -279,9 +284,9 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans, | |||
279 | (unsigned long)root->root_key.objectid, | 284 | (unsigned long)root->root_key.objectid, |
280 | BTRFS_ROOT_TRANS_TAG); | 285 | BTRFS_ROOT_TRANS_TAG); |
281 | if (root->commit_root == root->node) { | 286 | if (root->commit_root == root->node) { |
282 | WARN_ON(bh_blocknr(root->node) != | 287 | WARN_ON(extent_buffer_blocknr(root->node) != |
283 | btrfs_root_blocknr(&root->root_item)); | 288 | btrfs_root_blocknr(&root->root_item)); |
284 | brelse(root->commit_root); | 289 | free_extent_buffer(root->commit_root); |
285 | root->commit_root = NULL; | 290 | root->commit_root = NULL; |
286 | 291 | ||
287 | /* make sure to update the root on disk | 292 | /* make sure to update the root on disk |
@@ -310,7 +315,7 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans, | |||
310 | 315 | ||
311 | root->root_key.offset = root->fs_info->generation; | 316 | root->root_key.offset = root->fs_info->generation; |
312 | btrfs_set_root_blocknr(&root->root_item, | 317 | btrfs_set_root_blocknr(&root->root_item, |
313 | bh_blocknr(root->node)); | 318 | extent_buffer_blocknr(root->node)); |
314 | err = btrfs_insert_root(trans, root->fs_info->tree_root, | 319 | err = btrfs_insert_root(trans, root->fs_info->tree_root, |
315 | &root->root_key, | 320 | &root->root_key, |
316 | &root->root_item); | 321 | &root->root_item); |
@@ -389,10 +394,10 @@ int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info) | |||
389 | for (i = 0; i < ret; i++) { | 394 | for (i = 0; i < ret; i++) { |
390 | root = gang[i]; | 395 | root = gang[i]; |
391 | last = root->root_key.objectid + 1; | 396 | last = root->root_key.objectid + 1; |
392 | btrfs_defrag_root(root, 1); | 397 | // btrfs_defrag_root(root, 1); |
393 | } | 398 | } |
394 | } | 399 | } |
395 | btrfs_defrag_root(info->extent_root, 1); | 400 | // btrfs_defrag_root(info->extent_root, 1); |
396 | return err; | 401 | return err; |
397 | } | 402 | } |
398 | 403 | ||
@@ -414,7 +419,7 @@ static int drop_dirty_roots(struct btrfs_root *tree_root, | |||
414 | dirty = list_entry(list->next, struct dirty_root, list); | 419 | dirty = list_entry(list->next, struct dirty_root, list); |
415 | list_del_init(&dirty->list); | 420 | list_del_init(&dirty->list); |
416 | 421 | ||
417 | num_blocks = btrfs_root_blocks_used(&dirty->root->root_item); | 422 | num_blocks = btrfs_root_used(&dirty->root->root_item); |
418 | root = dirty->latest_root; | 423 | root = dirty->latest_root; |
419 | 424 | ||
420 | while(1) { | 425 | while(1) { |
@@ -441,11 +446,11 @@ static int drop_dirty_roots(struct btrfs_root *tree_root, | |||
441 | } | 446 | } |
442 | BUG_ON(ret); | 447 | BUG_ON(ret); |
443 | 448 | ||
444 | num_blocks -= btrfs_root_blocks_used(&dirty->root->root_item); | 449 | num_blocks -= btrfs_root_used(&dirty->root->root_item); |
445 | blocks_used = btrfs_root_blocks_used(&root->root_item); | 450 | blocks_used = btrfs_root_used(&root->root_item); |
446 | if (num_blocks) { | 451 | if (num_blocks) { |
447 | record_root_in_trans(root); | 452 | record_root_in_trans(root); |
448 | btrfs_set_root_blocks_used(&root->root_item, | 453 | btrfs_set_root_used(&root->root_item, |
449 | blocks_used - num_blocks); | 454 | blocks_used - num_blocks); |
450 | } | 455 | } |
451 | ret = btrfs_del_root(trans, tree_root, &dirty->root->root_key); | 456 | ret = btrfs_del_root(trans, tree_root, &dirty->root->root_key); |
@@ -553,9 +558,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
553 | btrfs_set_super_generation(&root->fs_info->super_copy, | 558 | btrfs_set_super_generation(&root->fs_info->super_copy, |
554 | cur_trans->transid); | 559 | cur_trans->transid); |
555 | btrfs_set_super_root(&root->fs_info->super_copy, | 560 | btrfs_set_super_root(&root->fs_info->super_copy, |
556 | bh_blocknr(root->fs_info->tree_root->node)); | 561 | extent_buffer_blocknr(root->fs_info->tree_root->node)); |
557 | memcpy(root->fs_info->disk_super, &root->fs_info->super_copy, | 562 | |
558 | sizeof(root->fs_info->super_copy)); | 563 | write_extent_buffer(root->fs_info->sb_buffer, |
564 | &root->fs_info->super_copy, 0, | ||
565 | sizeof(root->fs_info->super_copy)); | ||
559 | 566 | ||
560 | btrfs_copy_pinned(root, &pinned_copy); | 567 | btrfs_copy_pinned(root, &pinned_copy); |
561 | 568 | ||