Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / fs / ext3 / dir.c
index 832867a..f37528e 100644 (file)
@@ -39,7 +39,7 @@ static int ext3_dx_readdir(struct file * filp,
 static int ext3_release_dir (struct inode * inode,
                                struct file * filp);
 
-struct file_operations ext3_dir_operations = {
+const struct file_operations ext3_dir_operations = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
        .readdir        = ext3_readdir,         /* we take BKL. needed?*/
@@ -95,11 +95,10 @@ static int ext3_readdir(struct file * filp,
                         void * dirent, filldir_t filldir)
 {
        int error = 0;
-       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;
+       unsigned long offset;
+       int i, stored;
+       struct ext3_dir_entry_2 *de;
+       struct super_block *sb;
        int err;
        struct inode *inode = filp->f_dentry->d_inode;
        int ret = 0;
@@ -124,12 +123,30 @@ 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) {
-               blk = (filp->f_pos) >> EXT3_BLOCK_SIZE_BITS(sb);
-               bh = ext3_bread(NULL, inode, blk, 0, &err);
+               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
+                */
                if (!bh) {
                        ext3_error (sb, "ext3_readdir",
                                "directory #%lu contains a hole at offset %lu",
@@ -138,26 +155,6 @@ 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