X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fext3%2Fdir.c;fp=fs%2Fext3%2Fdir.c;h=6611801322ce8e231272a3a18720422ae6f227aa;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=f11d6ca4675065e2dc46ac693c9341d46b39c3bf;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index f11d6ca46..661180132 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c @@ -39,7 +39,7 @@ static int ext3_dx_readdir(struct file * filp, static int ext3_release_dir (struct inode * inode, struct file * filp); -const struct file_operations ext3_dir_operations = { +struct file_operations ext3_dir_operations = { .llseek = generic_file_llseek, .read = generic_read_dir, .readdir = ext3_readdir, /* we take BKL. needed?*/ @@ -95,10 +95,11 @@ static int ext3_readdir(struct file * filp, void * dirent, filldir_t filldir) { int error = 0; - unsigned long offset; - int i, stored; - struct ext3_dir_entry_2 *de; - struct super_block *sb; + unsigned long offset, blk; + int i, num, stored; + struct buffer_head * bh, * tmp, * bha[16]; + struct ext3_dir_entry_2 * de; + struct super_block * sb; int err; struct inode *inode = filp->f_dentry->d_inode; int ret = 0; @@ -123,30 +124,12 @@ static int ext3_readdir(struct file * filp, } #endif stored = 0; + bh = NULL; offset = filp->f_pos & (sb->s_blocksize - 1); while (!error && !stored && filp->f_pos < inode->i_size) { - unsigned long blk = filp->f_pos >> EXT3_BLOCK_SIZE_BITS(sb); - struct buffer_head map_bh; - struct buffer_head *bh = NULL; - - map_bh.b_state = 0; - err = ext3_get_blocks_handle(NULL, inode, blk, 1, - &map_bh, 0, 0); - if (err > 0) { - page_cache_readahead(sb->s_bdev->bd_inode->i_mapping, - &filp->f_ra, - filp, - map_bh.b_blocknr >> - (PAGE_CACHE_SHIFT - inode->i_blkbits), - 1); - bh = ext3_bread(NULL, inode, blk, 0, &err); - } - - /* - * We ignore I/O errors on directories so users have a chance - * of recovering data when there's a bad sector - */ + blk = (filp->f_pos) >> EXT3_BLOCK_SIZE_BITS(sb); + bh = ext3_bread(NULL, inode, blk, 0, &err); if (!bh) { ext3_error (sb, "ext3_readdir", "directory #%lu contains a hole at offset %lu", @@ -158,6 +141,26 @@ static int ext3_readdir(struct file * filp, continue; } + /* + * Do the readahead + */ + if (!offset) { + for (i = 16 >> (EXT3_BLOCK_SIZE_BITS(sb) - 9), num = 0; + i > 0; i--) { + tmp = ext3_getblk (NULL, inode, ++blk, 0, &err); + if (tmp && !buffer_uptodate(tmp) && + !buffer_locked(tmp)) + bha[num++] = tmp; + else + brelse (tmp); + } + if (num) { + ll_rw_block (READA, num, bha); + for (i = 0; i < num; i++) + brelse (bha[i]); + } + } + revalidate: /* If the dir block has changed since the last call to * readdir(2), then we might be pointing to an invalid @@ -287,7 +290,7 @@ static void free_rb_tree_fname(struct rb_root *root) * beginning of the loop and try to free the parent * node. */ - parent = rb_parent(n); + parent = n->rb_parent; fname = rb_entry(n, struct fname, rb_hash); while (fname) { struct fname * old = fname;