Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 090d1875 authored by Chris Mason's avatar Chris Mason Committed by David Woodhouse
Browse files

Btrfs: directory readahead

parent 31f3c99b
Loading
Loading
Loading
Loading
+28 −1
Original line number Original line Diff line number Diff line
@@ -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"
@@ -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;
@@ -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;
+6 −0
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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,
+1 −0
Original line number Original line Diff line number Diff line
@@ -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;
}
}
+28 −0
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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);
@@ -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]++;