aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext3/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext3/dir.c')
-rw-r--r--fs/ext3/dir.c55
1 files changed, 26 insertions, 29 deletions
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
index 832867aef3dc..f37528ed222e 100644
--- a/fs/ext3/dir.c
+++ b/fs/ext3/dir.c
@@ -39,7 +39,7 @@ static int ext3_dx_readdir(struct file * filp,
39static int ext3_release_dir (struct inode * inode, 39static int ext3_release_dir (struct inode * inode,
40 struct file * filp); 40 struct file * filp);
41 41
42struct file_operations ext3_dir_operations = { 42const struct file_operations ext3_dir_operations = {
43 .llseek = generic_file_llseek, 43 .llseek = generic_file_llseek,
44 .read = generic_read_dir, 44 .read = generic_read_dir,
45 .readdir = ext3_readdir, /* we take BKL. needed?*/ 45 .readdir = ext3_readdir, /* we take BKL. needed?*/
@@ -95,11 +95,10 @@ static int ext3_readdir(struct file * filp,
95 void * dirent, filldir_t filldir) 95 void * dirent, filldir_t filldir)
96{ 96{
97 int error = 0; 97 int error = 0;
98 unsigned long offset, blk; 98 unsigned long offset;
99 int i, num, stored; 99 int i, stored;
100 struct buffer_head * bh, * tmp, * bha[16]; 100 struct ext3_dir_entry_2 *de;
101 struct ext3_dir_entry_2 * de; 101 struct super_block *sb;
102 struct super_block * sb;
103 int err; 102 int err;
104 struct inode *inode = filp->f_dentry->d_inode; 103 struct inode *inode = filp->f_dentry->d_inode;
105 int ret = 0; 104 int ret = 0;
@@ -124,12 +123,30 @@ static int ext3_readdir(struct file * filp,
124 } 123 }
125#endif 124#endif
126 stored = 0; 125 stored = 0;
127 bh = NULL;
128 offset = filp->f_pos & (sb->s_blocksize - 1); 126 offset = filp->f_pos & (sb->s_blocksize - 1);
129 127
130 while (!error && !stored && filp->f_pos < inode->i_size) { 128 while (!error && !stored && filp->f_pos < inode->i_size) {
131 blk = (filp->f_pos) >> EXT3_BLOCK_SIZE_BITS(sb); 129 unsigned long blk = filp->f_pos >> EXT3_BLOCK_SIZE_BITS(sb);
132 bh = ext3_bread(NULL, inode, blk, 0, &err); 130 struct buffer_head map_bh;
131 struct buffer_head *bh = NULL;
132
133 map_bh.b_state = 0;
134 err = ext3_get_blocks_handle(NULL, inode, blk, 1,
135 &map_bh, 0, 0);
136 if (err > 0) {
137 page_cache_readahead(sb->s_bdev->bd_inode->i_mapping,
138 &filp->f_ra,
139 filp,
140 map_bh.b_blocknr >>
141 (PAGE_CACHE_SHIFT - inode->i_blkbits),
142 1);
143 bh = ext3_bread(NULL, inode, blk, 0, &err);
144 }
145
146 /*
147 * We ignore I/O errors on directories so users have a chance
148 * of recovering data when there's a bad sector
149 */
133 if (!bh) { 150 if (!bh) {
134 ext3_error (sb, "ext3_readdir", 151 ext3_error (sb, "ext3_readdir",
135 "directory #%lu contains a hole at offset %lu", 152 "directory #%lu contains a hole at offset %lu",
@@ -138,26 +155,6 @@ static int ext3_readdir(struct file * filp,
138 continue; 155 continue;
139 } 156 }
140 157
141 /*
142 * Do the readahead
143 */
144 if (!offset) {
145 for (i = 16 >> (EXT3_BLOCK_SIZE_BITS(sb) - 9), num = 0;
146 i > 0; i--) {
147 tmp = ext3_getblk (NULL, inode, ++blk, 0, &err);
148 if (tmp && !buffer_uptodate(tmp) &&
149 !buffer_locked(tmp))
150 bha[num++] = tmp;
151 else
152 brelse (tmp);
153 }
154 if (num) {
155 ll_rw_block (READA, num, bha);
156 for (i = 0; i < num; i++)
157 brelse (bha[i]);
158 }
159 }
160
161revalidate: 158revalidate:
162 /* If the dir block has changed since the last call to 159 /* If the dir block has changed since the last call to
163 * readdir(2), then we might be pointing to an invalid 160 * readdir(2), then we might be pointing to an invalid