aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/extent-tree.c1
-rw-r--r--fs/btrfs/super.c1
-rw-r--r--fs/btrfs/transaction.c37
-rw-r--r--fs/btrfs/transaction.h1
4 files changed, 37 insertions, 3 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index afc5267515e..652cf305a96 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -762,6 +762,7 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
BUG_ON(ret);
buf = btrfs_find_create_tree_block(root, ins.objectid);
set_buffer_uptodate(buf);
+ set_radix_bit(&trans->transaction->dirty_pages, buf->b_page->index);
return buf;
}
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index a10e902d310..1890e8648db 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -980,7 +980,6 @@ static int btrfs_sync_fs(struct super_block *sb, int wait)
filemap_flush(root->fs_info->btree_inode->i_mapping);
return 0;
}
- filemap_write_and_wait(root->fs_info->btree_inode->i_mapping);
mutex_lock(&root->fs_info->fs_mutex);
trans = btrfs_start_transaction(root, 1);
ret = btrfs_commit_transaction(trans, root);
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 8a2545f6a5b..f9b8864dcc4 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -45,6 +45,7 @@ static int join_transaction(struct btrfs_root *root)
cur_trans->use_count = 1;
cur_trans->commit_done = 0;
list_add_tail(&cur_trans->list, &root->fs_info->trans_list);
+ init_bit_radix(&cur_trans->dirty_pages);
}
cur_trans->num_writers++;
return 0;
@@ -106,8 +107,40 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans,
int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
struct btrfs_root *root)
{
- filemap_write_and_wait(root->fs_info->btree_inode->i_mapping);
- return 0;
+ unsigned long gang[16];
+ int ret;
+ int i;
+ int err;
+ int werr = 0;
+ struct page *page;
+ struct radix_tree_root *dirty_pages;
+ struct inode *btree_inode = root->fs_info->btree_inode;
+
+ if (!trans || !trans->transaction) {
+ return filemap_write_and_wait(btree_inode->i_mapping);
+ }
+ dirty_pages = &trans->transaction->dirty_pages;
+ while(1) {
+ ret = find_first_radix_bit(dirty_pages, gang, ARRAY_SIZE(gang));
+ if (!ret)
+ break;
+ for (i = 0; i < ret; i++) {
+ /* FIXME EIO */
+ clear_radix_bit(dirty_pages, gang[i]);
+ page = find_lock_page(btree_inode->i_mapping,
+ gang[i]);
+ if (!page)
+ continue;
+ err = write_one_page(page, 0);
+ if (err)
+ werr = err;
+ page_cache_release(page);
+ }
+ }
+ err = filemap_fdatawait(btree_inode->i_mapping);
+ if (err)
+ werr = err;
+ return werr;
}
int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index 3cc29900a07..afe42d167ce 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -9,6 +9,7 @@ struct btrfs_transaction {
int commit_done;
int magic;
struct list_head list;
+ struct radix_tree_root dirty_pages;
wait_queue_head_t writer_wait;
wait_queue_head_t commit_wait;
};