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?*/
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;
}
#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",
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
* 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;