[PATCH] fuse: clean up request size limit checking

Change the way a too large request is handled.  Until now in this case the
device read returned -EINVAL and the operation returned -EIO.

Make it more flexibible by not returning -EINVAL from the read, but restarting
it instead.

Also remove the fixed limit on setxattr data and let the filesystem provide as
large a read buffer as it needs to handle the extended attribute data.

The symbolic link length is already checked by VFS to be less than PATH_MAX,
so the extra check against FUSE_SYMLINK_MAX is not needed.

The check in fuse_create_open() against FUSE_NAME_MAX is not needed, since the
dentry has already been looked up, and hence the name already checked.

Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Miklos Szeredi
2006-01-06 00:19:40 -08:00
committed by Linus Torvalds
parent 248d86e87d
commit 1d3d752b47
5 changed files with 26 additions and 33 deletions

View File

@ -617,6 +617,7 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
struct fuse_copy_state cs;
unsigned reqsize;
restart:
spin_lock(&fuse_lock);
fc = file->private_data;
err = -EPERM;
@ -632,20 +633,25 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
req = list_entry(fc->pending.next, struct fuse_req, list);
list_del_init(&req->list);
spin_unlock(&fuse_lock);
in = &req->in;
reqsize = req->in.h.len;
fuse_copy_init(&cs, 1, req, iov, nr_segs);
err = -EINVAL;
if (iov_length(iov, nr_segs) >= reqsize) {
err = fuse_copy_one(&cs, &in->h, sizeof(in->h));
if (!err)
err = fuse_copy_args(&cs, in->numargs, in->argpages,
(struct fuse_arg *) in->args, 0);
reqsize = in->h.len;
/* If request is too large, reply with an error and restart the read */
if (iov_length(iov, nr_segs) < reqsize) {
req->out.h.error = -EIO;
/* SETXATTR is special, since it may contain too large data */
if (in->h.opcode == FUSE_SETXATTR)
req->out.h.error = -E2BIG;
request_end(fc, req);
goto restart;
}
spin_unlock(&fuse_lock);
fuse_copy_init(&cs, 1, req, iov, nr_segs);
err = fuse_copy_one(&cs, &in->h, sizeof(in->h));
if (!err)
err = fuse_copy_args(&cs, in->numargs, in->argpages,
(struct fuse_arg *) in->args, 0);
fuse_copy_finish(&cs);
spin_lock(&fuse_lock);
req->locked = 0;
if (!err && req->interrupted)