Btrfs: smarter transaction writeback
authorChris Mason <chris.mason@oracle.com>
Sat, 28 Apr 2007 13:29:35 +0000 (09:29 -0400)
committerDavid Woodhouse <dwmw2@hera.kernel.org>
Sat, 28 Apr 2007 13:29:35 +0000 (09:29 -0400)
Signed-off-by: Chris Mason <chris.mason@oracle.com>
fs/btrfs/extent-tree.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h

index afc5267..652cf30 100644 (file)
@@ -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;
 }
 
index a10e902..1890e86 100644 (file)
@@ -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);
index 8a2545f..f9b8864 100644 (file)
@@ -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,
index 3cc2990..afe42d1 100644 (file)
@@ -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;
 };