Commit 49a83003 authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] Use llseek instead of f_pos= for directory seeking

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: default avatarNeil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 58556e5f
...@@ -1477,10 +1477,12 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, ...@@ -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); err = nfsd_open(rqstp, fhp, S_IFDIR, MAY_READ, &file);
if (err) if (err)
goto out; 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 * 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, ...@@ -1496,7 +1498,7 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
err = nfserrno(err); err = nfserrno(err);
else else
err = cdp->err; err = cdp->err;
*offsetp = file.f_pos; *offsetp = vfs_llseek(&file, 0, 1);
if (err == nfserr_eof || err == nfserr_toosmall) if (err == nfserr_eof || err == nfserr_toosmall)
err = nfs_ok; /* can still be found in ->err */ err = nfs_ok; /* can still be found in ->err */
......
...@@ -76,14 +76,12 @@ loff_t remote_llseek(struct file *file, loff_t offset, int origin) ...@@ -76,14 +76,12 @@ loff_t remote_llseek(struct file *file, loff_t offset, int origin)
unlock_kernel(); unlock_kernel();
return retval; return retval;
} }
EXPORT_SYMBOL(remote_llseek); EXPORT_SYMBOL(remote_llseek);
loff_t no_llseek(struct file *file, loff_t offset, int origin) loff_t no_llseek(struct file *file, loff_t offset, int origin)
{ {
return -ESPIPE; return -ESPIPE;
} }
EXPORT_SYMBOL(no_llseek); EXPORT_SYMBOL(no_llseek);
loff_t default_llseek(struct file *file, loff_t offset, int origin) 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) ...@@ -109,10 +107,9 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin)
unlock_kernel(); unlock_kernel();
return retval; return retval;
} }
EXPORT_SYMBOL(default_llseek); 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); 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) ...@@ -121,6 +118,7 @@ static inline loff_t llseek(struct file *file, loff_t offset, int origin)
fn = file->f_op->llseek; fn = file->f_op->llseek;
return fn(file, offset, origin); return fn(file, offset, origin);
} }
EXPORT_SYMBOL(vfs_llseek);
asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin) 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) ...@@ -135,7 +133,7 @@ asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
retval = -EINVAL; retval = -EINVAL;
if (origin <= 2) { if (origin <= 2) {
loff_t res = llseek(file, offset, origin); loff_t res = vfs_llseek(file, offset, origin);
retval = res; retval = res;
if (res != (loff_t)retval) if (res != (loff_t)retval)
retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */ 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, ...@@ -165,7 +163,7 @@ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
if (origin > 2) if (origin > 2)
goto out_putf; 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); origin);
retval = (int)offset; retval = (int)offset;
......
...@@ -1341,6 +1341,8 @@ extern ino_t find_inode_number(struct dentry *, struct qstr *); ...@@ -1341,6 +1341,8 @@ extern ino_t find_inode_number(struct dentry *, struct qstr *);
/* needed for stackable file system support */ /* needed for stackable file system support */
extern loff_t default_llseek(struct file *file, loff_t offset, int origin); 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 inode_init_once(struct inode *);
extern void iput(struct inode *); extern void iput(struct inode *);
extern struct inode * igrab(struct inode *); extern struct inode * igrab(struct inode *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment