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,
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 */
......
......@@ -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;
......
......@@ -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 *);
......
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