diff options
-rw-r--r-- | fs/btrfs/disk-io.c | 29 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 6 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 1 | ||||
-rw-r--r-- | fs/btrfs/super.c | 28 |
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 | ||
257 | int 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 | } | ||
275 | done: | ||
276 | brelse(bh); | ||
277 | return 0; | ||
278 | } | ||
279 | |||
256 | struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) | 280 | struct 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 | } |
277 | uptodate: | 300 | uptodate: |
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 | ||
8 | enum btrfs_bh_state_bits { | ||
9 | BH_Checked = BH_PrivateStart, | ||
10 | }; | ||
11 | BUFFER_FNS(Checked, checked); | ||
12 | |||
8 | static inline struct btrfs_node *btrfs_buffer_node(struct buffer_head *bh) | 13 | static 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 | ||
23 | struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr); | 28 | struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr); |
29 | int readahead_tree_block(struct btrfs_root *root, u64 blocknr); | ||
24 | struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, | 30 | struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, |
25 | u64 blocknr); | 31 | u64 blocknr); |
26 | int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 32 | int 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 | ||
588 | static 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 | |||
588 | static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 613 | static 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]++; |