aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/disk-io.c29
-rw-r--r--fs/btrfs/disk-io.h6
-rw-r--r--fs/btrfs/extent-tree.c1
-rw-r--r--fs/btrfs/super.c28
4 files changed, 63 insertions, 1 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index e1b6e13a5ae8..354524adf984 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -5,6 +5,7 @@
5#include <linux/scatterlist.h> 5#include <linux/scatterlist.h>
6#include <linux/swap.h> 6#include <linux/swap.h>
7#include <linux/radix-tree.h> 7#include <linux/radix-tree.h>
8#include <linux/file.h>
8#include "ctree.h" 9#include "ctree.h"
9#include "disk-io.h" 10#include "disk-io.h"
10#include "transaction.h" 11#include "transaction.h"
@@ -253,6 +254,29 @@ static struct address_space_operations btree_aops = {
253 .sync_page = block_sync_page, 254 .sync_page = block_sync_page,
254}; 255};
255 256
257int readahead_tree_block(struct btrfs_root *root, u64 blocknr)
258{
259 struct buffer_head *bh = NULL;
260
261 bh = btrfs_find_create_tree_block(root, blocknr);
262 if (!bh)
263 return 0;
264 if (buffer_uptodate(bh))
265 goto done;
266 if (test_set_buffer_locked(bh))
267 goto done;
268 if (!buffer_uptodate(bh)) {
269 get_bh(bh);
270 bh->b_end_io = end_buffer_read_sync;
271 submit_bh(READ, bh);
272 } else {
273 unlock_buffer(bh);
274 }
275done:
276 brelse(bh);
277 return 0;
278}
279
256struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) 280struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr)
257{ 281{
258 struct buffer_head *bh = NULL; 282 struct buffer_head *bh = NULL;
@@ -270,11 +294,14 @@ struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr)
270 wait_on_buffer(bh); 294 wait_on_buffer(bh);
271 if (!buffer_uptodate(bh)) 295 if (!buffer_uptodate(bh))
272 goto fail; 296 goto fail;
273 csum_tree_block(root, bh, 1);
274 } else { 297 } else {
275 unlock_buffer(bh); 298 unlock_buffer(bh);
276 } 299 }
277uptodate: 300uptodate:
301 if (!buffer_checked(bh)) {
302 csum_tree_block(root, bh, 1);
303 set_buffer_checked(bh);
304 }
278 if (check_tree_block(root, bh)) 305 if (check_tree_block(root, bh))
279 BUG(); 306 BUG();
280 return bh; 307 return bh;
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index 444ebb0141ae..1ee7d2a55b5b 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -5,6 +5,11 @@
5 5
6#define BTRFS_SUPER_INFO_OFFSET (16 * 1024) 6#define BTRFS_SUPER_INFO_OFFSET (16 * 1024)
7 7
8enum btrfs_bh_state_bits {
9 BH_Checked = BH_PrivateStart,
10};
11BUFFER_FNS(Checked, checked);
12
8static inline struct btrfs_node *btrfs_buffer_node(struct buffer_head *bh) 13static inline struct btrfs_node *btrfs_buffer_node(struct buffer_head *bh)
9{ 14{
10 return (struct btrfs_node *)bh->b_data; 15 return (struct btrfs_node *)bh->b_data;
@@ -21,6 +26,7 @@ static inline struct btrfs_header *btrfs_buffer_header(struct buffer_head *bh)
21} 26}
22 27
23struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr); 28struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr);
29int readahead_tree_block(struct btrfs_root *root, u64 blocknr);
24struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, 30struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root,
25 u64 blocknr); 31 u64 blocknr);
26int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, 32int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 8b8cbe25fffb..2837fddf7b1c 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -812,6 +812,7 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
812 BUG_ON(ret); 812 BUG_ON(ret);
813 buf = btrfs_find_create_tree_block(root, ins.objectid); 813 buf = btrfs_find_create_tree_block(root, ins.objectid);
814 set_buffer_uptodate(buf); 814 set_buffer_uptodate(buf);
815 set_buffer_checked(buf);
815 set_radix_bit(&trans->transaction->dirty_pages, buf->b_page->index); 816 set_radix_bit(&trans->transaction->dirty_pages, buf->b_page->index);
816 return buf; 817 return buf;
817} 818}
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 7ecbe7c86186..a29a781b86c2 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -585,6 +585,31 @@ printk("adding new root for inode %lu root %p (found %p)\n", inode->i_ino, sub_r
585 return d_splice_alias(inode, dentry); 585 return d_splice_alias(inode, dentry);
586} 586}
587 587
588static void reada_leaves(struct btrfs_root *root, struct btrfs_path *path)
589{
590 struct btrfs_node *node;
591 int i;
592 int nritems;
593 u64 objectid;
594 u64 item_objectid;
595 u64 blocknr;
596 int slot;
597
598 if (!path->nodes[1])
599 return;
600 node = btrfs_buffer_node(path->nodes[1]);
601 slot = path->slots[1];
602 objectid = btrfs_disk_key_objectid(&node->ptrs[slot].key);
603 nritems = btrfs_header_nritems(&node->header);
604 for (i = slot; i < nritems; i++) {
605 item_objectid = btrfs_disk_key_objectid(&node->ptrs[i].key);
606 if (item_objectid != objectid)
607 break;
608 blocknr = btrfs_node_blockptr(node, i);
609 readahead_tree_block(root, blocknr);
610 }
611}
612
588static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) 613static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
589{ 614{
590 struct inode *inode = filp->f_path.dentry->d_inode; 615 struct inode *inode = filp->f_path.dentry->d_inode;
@@ -619,6 +644,7 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
619 if (ret < 0) 644 if (ret < 0)
620 goto err; 645 goto err;
621 advance = 0; 646 advance = 0;
647 reada_leaves(root, path);
622 while(1) { 648 while(1) {
623 leaf = btrfs_buffer_leaf(path->nodes[0]); 649 leaf = btrfs_buffer_leaf(path->nodes[0]);
624 nritems = btrfs_header_nritems(&leaf->header); 650 nritems = btrfs_header_nritems(&leaf->header);
@@ -631,6 +657,8 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
631 leaf = btrfs_buffer_leaf(path->nodes[0]); 657 leaf = btrfs_buffer_leaf(path->nodes[0]);
632 nritems = btrfs_header_nritems(&leaf->header); 658 nritems = btrfs_header_nritems(&leaf->header);
633 slot = path->slots[0]; 659 slot = path->slots[0];
660 if (path->slots[1] == 0)
661 reada_leaves(root, path);
634 } else { 662 } else {
635 slot++; 663 slot++;
636 path->slots[0]++; 664 path->slots[0]++;