]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Use llseek instead of f_pos= for directory seeking
authorNeil Brown <neilb@cse.unsw.edu.au>
Sun, 11 Jul 2004 02:30:45 +0000 (19:30 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Sun, 11 Jul 2004 02:30:45 +0000 (19:30 -0700)
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>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/nfsd/vfs.c
fs/read_write.c
include/linux/fs.h

index 3c57bc31f5213c3bb6a5317ff3badb2029ef5d85..f7ac90d15961679c9c40e6e6739509da9b0c728e 100644 (file)
@@ -1477,10 +1477,12 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
        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, struct svc_fh *fhp, loff_t *offsetp,
                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 */
index f765a22b49cb50205acabb2fd9abffb2161d9974..481332642515c0a19e70f7da5b31743b7067cbda 100644 (file)
@@ -76,14 +76,12 @@ loff_t remote_llseek(struct file *file, loff_t offset, int origin)
        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, loff_t offset, int origin)
        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 *file, loff_t offset, int origin)
                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 fd, off_t offset, unsigned int origin)
 
        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 fd, unsigned long offset_high,
        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;
index e847ef6d20fbf251d0e63acaf6b276a1d4b35559..3d24beb4ac36ebd82a2c563d35322f956c0a0d3d 100644 (file)
@@ -1341,6 +1341,8 @@ extern ino_t find_inode_number(struct dentry *, struct qstr *);
 /* 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 *);