
From: Neil Brown <neilb@cse.unsw.edu.au>

nfsd currently just sets f_pos when seeking in a directory.  This bypasses
any checking and other handling that a filesystem might want to do.

So instead, we define "vfs_llseek" to be an exported "llseek", and use
that, both to seek at the start, and the find the new position at the end.

Thanks to
    "Derrick Schommer" <dschommer@acopia.com>
    "Trond Myklebust" <trond.myklebust@fys.uio.no>

Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/nfsd/vfs.c      |   10 ++++++----
 25-akpm/fs/read_write.c    |   10 ++++------
 25-akpm/include/linux/fs.h |    2 ++
 3 files changed, 12 insertions(+), 10 deletions(-)

diff -puN fs/nfsd/vfs.c~use-llseek-instead-of-f_pos=-for-directory-seeking fs/nfsd/vfs.c
--- 25/fs/nfsd/vfs.c~use-llseek-instead-of-f_pos=-for-directory-seeking	2004-07-05 16:08:54.341788152 -0700
+++ 25-akpm/fs/nfsd/vfs.c	2004-07-05 16:08:54.349786936 -0700
@@ -1477,10 +1477,12 @@ nfsd_readdir(struct svc_rqst *rqstp, str
 	err = nfsd_open(rqstp, fhp, S_IFDIR, MAY_READ, &file);
 	if (err)
 		goto out;
-	if (offset > ~(u32) 0)
-		goto out_close;
 
-	file.f_pos = offset;
+	offset = vfs_llseek(&file, offset, 0);
+	if (offset < 0) {
+		err = nfserrno((int)offset);
+		goto out_close;
+	}
 
 	/*
 	 * Read the directory entries. This silly loop is necessary because
@@ -1496,7 +1498,7 @@ nfsd_readdir(struct svc_rqst *rqstp, str
 		err = nfserrno(err);
 	else
 		err = cdp->err;
-	*offsetp = file.f_pos;
+	*offsetp = vfs_llseek(&file, 0, 1);
 
 	if (err == nfserr_eof || err == nfserr_toosmall)
 		err = nfs_ok; /* can still be found in ->err */
diff -puN fs/read_write.c~use-llseek-instead-of-f_pos=-for-directory-seeking fs/read_write.c
--- 25/fs/read_write.c~use-llseek-instead-of-f_pos=-for-directory-seeking	2004-07-05 16:08:54.342788000 -0700
+++ 25-akpm/fs/read_write.c	2004-07-05 16:08:54.350786784 -0700
@@ -76,14 +76,12 @@ loff_t remote_llseek(struct file *file, 
 	unlock_kernel();
 	return retval;
 }
-
 EXPORT_SYMBOL(remote_llseek);
 
 loff_t no_llseek(struct file *file, loff_t offset, int origin)
 {
 	return -ESPIPE;
 }
-
 EXPORT_SYMBOL(no_llseek);
 
 loff_t default_llseek(struct file *file, loff_t offset, int origin)
@@ -109,10 +107,9 @@ loff_t default_llseek(struct file *file,
 	unlock_kernel();
 	return retval;
 }
-
 EXPORT_SYMBOL(default_llseek);
 
-static inline loff_t llseek(struct file *file, loff_t offset, int origin)
+loff_t vfs_llseek(struct file *file, loff_t offset, int origin)
 {
 	loff_t (*fn)(struct file *, loff_t, int);
 
@@ -121,6 +118,7 @@ static inline loff_t llseek(struct file 
 		fn = file->f_op->llseek;
 	return fn(file, offset, origin);
 }
+EXPORT_SYMBOL(vfs_llseek);
 
 asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
 {
@@ -135,7 +133,7 @@ asmlinkage off_t sys_lseek(unsigned int 
 
 	retval = -EINVAL;
 	if (origin <= 2) {
-		loff_t res = llseek(file, offset, origin);
+		loff_t res = vfs_llseek(file, offset, origin);
 		retval = res;
 		if (res != (loff_t)retval)
 			retval = -EOVERFLOW;	/* LFS: should only happen on 32 bit platforms */
@@ -165,7 +163,7 @@ asmlinkage long sys_llseek(unsigned int 
 	if (origin > 2)
 		goto out_putf;
 
-	offset = llseek(file, ((loff_t) offset_high << 32) | offset_low,
+	offset = vfs_llseek(file, ((loff_t) offset_high << 32) | offset_low,
 			origin);
 
 	retval = (int)offset;
diff -puN include/linux/fs.h~use-llseek-instead-of-f_pos=-for-directory-seeking include/linux/fs.h
--- 25/include/linux/fs.h~use-llseek-instead-of-f_pos=-for-directory-seeking	2004-07-05 16:08:54.345787544 -0700
+++ 25-akpm/include/linux/fs.h	2004-07-05 16:08:54.352786480 -0700
@@ -1352,6 +1352,8 @@ extern ino_t find_inode_number(struct de
 /* needed for stackable file system support */
 extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
 
+extern loff_t vfs_llseek(struct file *file, loff_t offset, int origin);
+
 extern void inode_init_once(struct inode *);
 extern void iput(struct inode *);
 extern struct inode * igrab(struct inode *);
_
