From: Jan Blunck <j.blunck@tu-harburg.de>

If the whole directory is read, ext2_readdir() sets the f_pos to a multiple
of the page size (because of the conditions of the outer for loop).  This
sets the wrong f_pos for directory inodes on ext2 partitions with a block
size differing from the page size.

Signed-off-by: Jan Blunck <j.blunck@tu-harburg.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/ext2/dir.c |   11 ++++++++---
 1 files changed, 8 insertions(+), 3 deletions(-)

diff -puN fs/ext2/dir.c~ext2_readdir-filp-f_pos-fix fs/ext2/dir.c
--- 25/fs/ext2/dir.c~ext2_readdir-filp-f_pos-fix	2004-07-31 16:47:38.960683648 -0700
+++ 25-akpm/fs/ext2/dir.c	2004-07-31 16:47:38.964683040 -0700
@@ -251,7 +251,7 @@ ext2_readdir (struct file * filp, void *
 	loff_t pos = filp->f_pos;
 	struct inode *inode = filp->f_dentry->d_inode;
 	struct super_block *sb = inode->i_sb;
-	unsigned offset = pos & ~PAGE_CACHE_MASK;
+	unsigned int offset = pos & ~PAGE_CACHE_MASK;
 	unsigned long n = pos >> PAGE_CACHE_SHIFT;
 	unsigned long npages = dir_pages(inode);
 	unsigned chunk_mask = ~(ext2_chunk_size(inode)-1);
@@ -270,8 +270,13 @@ ext2_readdir (struct file * filp, void *
 		ext2_dirent *de;
 		struct page *page = ext2_get_page(inode, n);
 
-		if (IS_ERR(page))
+		if (IS_ERR(page)) {
+			ext2_error(sb, __FUNCTION__,
+				   "bad page in #%lu",
+				   inode->i_ino);
+			filp->f_pos += PAGE_CACHE_SIZE - offset;
 			continue;
+		}
 		kaddr = page_address(page);
 		if (need_revalidate) {
 			offset = ext2_validate_entry(kaddr, offset, chunk_mask);
@@ -303,6 +308,7 @@ ext2_readdir (struct file * filp, void *
 					goto success;
 				}
 			}
+			filp->f_pos += le16_to_cpu(de->rec_len);
 		}
 		ext2_put_page(page);
 	}
@@ -310,7 +316,6 @@ ext2_readdir (struct file * filp, void *
 success:
 	ret = 0;
 done:
-	filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
 	filp->f_version = inode->i_version;
 	return ret;
 }
_