2.4.36-stable kernel tree
Revision | 72a9d5aa5e1e1602f861f8b893d8d57a08f30734 (tree) |
---|---|
Zeit | 2008-04-16 17:06:58 |
Autor | Glen Nakamura <glen@imod...> |
Commiter | Willy Tarreau |
ext2_readdir() filp->f_pos fix (try #2)
This patch reintroduces a fixed version of reverted commit
c30306fb287323591c854a0982d9fa5351859b45 from Dann Frazier :
Note from Glen :
This fix was confirmed by both Dann Frazier and Pascal Hambourg.
Note from Willy :
The code now differs from 2.6 only by commit
2d7f2ea9c989853310c7f6e8be52cc090cc8e66b which is only in 2.6.
The reporter, Al Masoud, provided the test case which could not be
reproduced on 2.4 (neither with nor without the fix above), so the
patch in question has *not* been applied to 2.4.
Dann will take the same approach for the Debian update.
@@ -240,7 +240,7 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) | ||
240 | 240 | loff_t pos = filp->f_pos; |
241 | 241 | struct inode *inode = filp->f_dentry->d_inode; |
242 | 242 | struct super_block *sb = inode->i_sb; |
243 | - unsigned offset = pos & ~PAGE_CACHE_MASK; | |
243 | + unsigned int offset = pos & ~PAGE_CACHE_MASK; | |
244 | 244 | unsigned long n = pos >> PAGE_CACHE_SHIFT; |
245 | 245 | unsigned long npages = dir_pages(inode); |
246 | 246 | unsigned chunk_mask = ~(ext2_chunk_size(inode)-1); |
@@ -260,6 +260,10 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) | ||
260 | 260 | struct page *page = ext2_get_page(inode, n); |
261 | 261 | |
262 | 262 | if (IS_ERR(page)) { |
263 | + ext2_error(sb, __FUNCTION__, | |
264 | + "bad page in #%lu", | |
265 | + inode->i_ino); | |
266 | + filp->f_pos += PAGE_CACHE_SIZE - offset; | |
263 | 267 | ret = -EIO; |
264 | 268 | goto done; |
265 | 269 | } |
@@ -270,7 +274,7 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) | ||
270 | 274 | } |
271 | 275 | de = (ext2_dirent *)(kaddr+offset); |
272 | 276 | limit = kaddr + PAGE_CACHE_SIZE - EXT2_DIR_REC_LEN(1); |
273 | - for ( ;(char*)de <= limit; de = ext2_next_entry(de)) | |
277 | + for ( ;(char*)de <= limit; de = ext2_next_entry(de)) { | |
274 | 278 | if (de->inode) { |
275 | 279 | int over; |
276 | 280 | unsigned char d_type = DT_UNKNOWN; |
@@ -287,11 +291,12 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) | ||
287 | 291 | goto done; |
288 | 292 | } |
289 | 293 | } |
294 | + filp->f_pos += le16_to_cpu(de->rec_len); | |
295 | + } | |
290 | 296 | ext2_put_page(page); |
291 | 297 | } |
292 | 298 | |
293 | 299 | done: |
294 | - filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset; | |
295 | 300 | filp->f_version = inode->i_version; |
296 | 301 | UPDATE_ATIME(inode); |
297 | 302 | return ret; |