Loading fs/btrfs/disk-io.c +28 −1 Original line number Original line Diff line number Diff line Loading @@ -5,6 +5,7 @@ #include <linux/scatterlist.h> #include <linux/scatterlist.h> #include <linux/swap.h> #include <linux/swap.h> #include <linux/radix-tree.h> #include <linux/radix-tree.h> #include <linux/file.h> #include "ctree.h" #include "ctree.h" #include "disk-io.h" #include "disk-io.h" #include "transaction.h" #include "transaction.h" Loading Loading @@ -253,6 +254,29 @@ static struct address_space_operations btree_aops = { .sync_page = block_sync_page, .sync_page = block_sync_page, }; }; int readahead_tree_block(struct btrfs_root *root, u64 blocknr) { struct buffer_head *bh = NULL; bh = btrfs_find_create_tree_block(root, blocknr); if (!bh) return 0; if (buffer_uptodate(bh)) goto done; if (test_set_buffer_locked(bh)) goto done; if (!buffer_uptodate(bh)) { get_bh(bh); bh->b_end_io = end_buffer_read_sync; submit_bh(READ, bh); } else { unlock_buffer(bh); } done: brelse(bh); return 0; } struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) { { struct buffer_head *bh = NULL; struct buffer_head *bh = NULL; Loading @@ -270,11 +294,14 @@ struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) wait_on_buffer(bh); wait_on_buffer(bh); if (!buffer_uptodate(bh)) if (!buffer_uptodate(bh)) goto fail; goto fail; csum_tree_block(root, bh, 1); } else { } else { unlock_buffer(bh); unlock_buffer(bh); } } uptodate: uptodate: if (!buffer_checked(bh)) { csum_tree_block(root, bh, 1); set_buffer_checked(bh); } if (check_tree_block(root, bh)) if (check_tree_block(root, bh)) BUG(); BUG(); return bh; return bh; Loading fs/btrfs/disk-io.h +6 −0 Original line number Original line Diff line number Diff line Loading @@ -5,6 +5,11 @@ #define BTRFS_SUPER_INFO_OFFSET (16 * 1024) #define BTRFS_SUPER_INFO_OFFSET (16 * 1024) enum btrfs_bh_state_bits { BH_Checked = BH_PrivateStart, }; BUFFER_FNS(Checked, checked); static inline struct btrfs_node *btrfs_buffer_node(struct buffer_head *bh) static inline struct btrfs_node *btrfs_buffer_node(struct buffer_head *bh) { { return (struct btrfs_node *)bh->b_data; return (struct btrfs_node *)bh->b_data; Loading @@ -21,6 +26,7 @@ static inline struct btrfs_header *btrfs_buffer_header(struct buffer_head *bh) } } struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr); struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr); int readahead_tree_block(struct btrfs_root *root, u64 blocknr); struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, u64 blocknr); u64 blocknr); int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, Loading fs/btrfs/extent-tree.c +1 −0 Original line number Original line Diff line number Diff line Loading @@ -812,6 +812,7 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, BUG_ON(ret); BUG_ON(ret); buf = btrfs_find_create_tree_block(root, ins.objectid); buf = btrfs_find_create_tree_block(root, ins.objectid); set_buffer_uptodate(buf); set_buffer_uptodate(buf); set_buffer_checked(buf); set_radix_bit(&trans->transaction->dirty_pages, buf->b_page->index); set_radix_bit(&trans->transaction->dirty_pages, buf->b_page->index); return buf; return buf; } } Loading fs/btrfs/super.c +28 −0 Original line number Original line Diff line number Diff line Loading @@ -585,6 +585,31 @@ printk("adding new root for inode %lu root %p (found %p)\n", inode->i_ino, sub_r return d_splice_alias(inode, dentry); return d_splice_alias(inode, dentry); } } static void reada_leaves(struct btrfs_root *root, struct btrfs_path *path) { struct btrfs_node *node; int i; int nritems; u64 objectid; u64 item_objectid; u64 blocknr; int slot; if (!path->nodes[1]) return; node = btrfs_buffer_node(path->nodes[1]); slot = path->slots[1]; objectid = btrfs_disk_key_objectid(&node->ptrs[slot].key); nritems = btrfs_header_nritems(&node->header); for (i = slot; i < nritems; i++) { item_objectid = btrfs_disk_key_objectid(&node->ptrs[i].key); if (item_objectid != objectid) break; blocknr = btrfs_node_blockptr(node, i); readahead_tree_block(root, blocknr); } } static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { { struct inode *inode = filp->f_path.dentry->d_inode; struct inode *inode = filp->f_path.dentry->d_inode; Loading Loading @@ -619,6 +644,7 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) if (ret < 0) if (ret < 0) goto err; goto err; advance = 0; advance = 0; reada_leaves(root, path); while(1) { while(1) { leaf = btrfs_buffer_leaf(path->nodes[0]); leaf = btrfs_buffer_leaf(path->nodes[0]); nritems = btrfs_header_nritems(&leaf->header); nritems = btrfs_header_nritems(&leaf->header); Loading @@ -631,6 +657,8 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) leaf = btrfs_buffer_leaf(path->nodes[0]); leaf = btrfs_buffer_leaf(path->nodes[0]); nritems = btrfs_header_nritems(&leaf->header); nritems = btrfs_header_nritems(&leaf->header); slot = path->slots[0]; slot = path->slots[0]; if (path->slots[1] == 0) reada_leaves(root, path); } else { } else { slot++; slot++; path->slots[0]++; path->slots[0]++; Loading Loading
fs/btrfs/disk-io.c +28 −1 Original line number Original line Diff line number Diff line Loading @@ -5,6 +5,7 @@ #include <linux/scatterlist.h> #include <linux/scatterlist.h> #include <linux/swap.h> #include <linux/swap.h> #include <linux/radix-tree.h> #include <linux/radix-tree.h> #include <linux/file.h> #include "ctree.h" #include "ctree.h" #include "disk-io.h" #include "disk-io.h" #include "transaction.h" #include "transaction.h" Loading Loading @@ -253,6 +254,29 @@ static struct address_space_operations btree_aops = { .sync_page = block_sync_page, .sync_page = block_sync_page, }; }; int readahead_tree_block(struct btrfs_root *root, u64 blocknr) { struct buffer_head *bh = NULL; bh = btrfs_find_create_tree_block(root, blocknr); if (!bh) return 0; if (buffer_uptodate(bh)) goto done; if (test_set_buffer_locked(bh)) goto done; if (!buffer_uptodate(bh)) { get_bh(bh); bh->b_end_io = end_buffer_read_sync; submit_bh(READ, bh); } else { unlock_buffer(bh); } done: brelse(bh); return 0; } struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) { { struct buffer_head *bh = NULL; struct buffer_head *bh = NULL; Loading @@ -270,11 +294,14 @@ struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) wait_on_buffer(bh); wait_on_buffer(bh); if (!buffer_uptodate(bh)) if (!buffer_uptodate(bh)) goto fail; goto fail; csum_tree_block(root, bh, 1); } else { } else { unlock_buffer(bh); unlock_buffer(bh); } } uptodate: uptodate: if (!buffer_checked(bh)) { csum_tree_block(root, bh, 1); set_buffer_checked(bh); } if (check_tree_block(root, bh)) if (check_tree_block(root, bh)) BUG(); BUG(); return bh; return bh; Loading
fs/btrfs/disk-io.h +6 −0 Original line number Original line Diff line number Diff line Loading @@ -5,6 +5,11 @@ #define BTRFS_SUPER_INFO_OFFSET (16 * 1024) #define BTRFS_SUPER_INFO_OFFSET (16 * 1024) enum btrfs_bh_state_bits { BH_Checked = BH_PrivateStart, }; BUFFER_FNS(Checked, checked); static inline struct btrfs_node *btrfs_buffer_node(struct buffer_head *bh) static inline struct btrfs_node *btrfs_buffer_node(struct buffer_head *bh) { { return (struct btrfs_node *)bh->b_data; return (struct btrfs_node *)bh->b_data; Loading @@ -21,6 +26,7 @@ static inline struct btrfs_header *btrfs_buffer_header(struct buffer_head *bh) } } struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr); struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr); int readahead_tree_block(struct btrfs_root *root, u64 blocknr); struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, u64 blocknr); u64 blocknr); int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, Loading
fs/btrfs/extent-tree.c +1 −0 Original line number Original line Diff line number Diff line Loading @@ -812,6 +812,7 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, BUG_ON(ret); BUG_ON(ret); buf = btrfs_find_create_tree_block(root, ins.objectid); buf = btrfs_find_create_tree_block(root, ins.objectid); set_buffer_uptodate(buf); set_buffer_uptodate(buf); set_buffer_checked(buf); set_radix_bit(&trans->transaction->dirty_pages, buf->b_page->index); set_radix_bit(&trans->transaction->dirty_pages, buf->b_page->index); return buf; return buf; } } Loading
fs/btrfs/super.c +28 −0 Original line number Original line Diff line number Diff line Loading @@ -585,6 +585,31 @@ printk("adding new root for inode %lu root %p (found %p)\n", inode->i_ino, sub_r return d_splice_alias(inode, dentry); return d_splice_alias(inode, dentry); } } static void reada_leaves(struct btrfs_root *root, struct btrfs_path *path) { struct btrfs_node *node; int i; int nritems; u64 objectid; u64 item_objectid; u64 blocknr; int slot; if (!path->nodes[1]) return; node = btrfs_buffer_node(path->nodes[1]); slot = path->slots[1]; objectid = btrfs_disk_key_objectid(&node->ptrs[slot].key); nritems = btrfs_header_nritems(&node->header); for (i = slot; i < nritems; i++) { item_objectid = btrfs_disk_key_objectid(&node->ptrs[i].key); if (item_objectid != objectid) break; blocknr = btrfs_node_blockptr(node, i); readahead_tree_block(root, blocknr); } } static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { { struct inode *inode = filp->f_path.dentry->d_inode; struct inode *inode = filp->f_path.dentry->d_inode; Loading Loading @@ -619,6 +644,7 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) if (ret < 0) if (ret < 0) goto err; goto err; advance = 0; advance = 0; reada_leaves(root, path); while(1) { while(1) { leaf = btrfs_buffer_leaf(path->nodes[0]); leaf = btrfs_buffer_leaf(path->nodes[0]); nritems = btrfs_header_nritems(&leaf->header); nritems = btrfs_header_nritems(&leaf->header); Loading @@ -631,6 +657,8 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) leaf = btrfs_buffer_leaf(path->nodes[0]); leaf = btrfs_buffer_leaf(path->nodes[0]); nritems = btrfs_header_nritems(&leaf->header); nritems = btrfs_header_nritems(&leaf->header); slot = path->slots[0]; slot = path->slots[0]; if (path->slots[1] == 0) reada_leaves(root, path); } else { } else { slot++; slot++; path->slots[0]++; path->slots[0]++; Loading