aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/dev.c
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2006-01-06 03:19:40 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:33:56 -0500
commit1d3d752b471d2a3a1d5e4fe177e5e7d52abb4e4c (patch)
tree05c6c99ca02118e2c80199c36f4f6263cdf7986b /fs/fuse/dev.c
parent248d86e87d12da19eee602075f05a49a5215288b (diff)
[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>
Diffstat (limited to 'fs/fuse/dev.c')
-rw-r--r--fs/fuse/dev.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index e5bc3f8eebd0..1afdffdf80db 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -617,6 +617,7 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
617 struct fuse_copy_state cs; 617 struct fuse_copy_state cs;
618 unsigned reqsize; 618 unsigned reqsize;
619 619
620 restart:
620 spin_lock(&fuse_lock); 621 spin_lock(&fuse_lock);
621 fc = file->private_data; 622 fc = file->private_data;
622 err = -EPERM; 623 err = -EPERM;
@@ -632,20 +633,25 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
632 633
633 req = list_entry(fc->pending.next, struct fuse_req, list); 634 req = list_entry(fc->pending.next, struct fuse_req, list);
634 list_del_init(&req->list); 635 list_del_init(&req->list);
635 spin_unlock(&fuse_lock);
636 636
637 in = &req->in; 637 in = &req->in;
638 reqsize = req->in.h.len; 638 reqsize = in->h.len;
639 fuse_copy_init(&cs, 1, req, iov, nr_segs); 639 /* If request is too large, reply with an error and restart the read */
640 err = -EINVAL; 640 if (iov_length(iov, nr_segs) < reqsize) {
641 if (iov_length(iov, nr_segs) >= reqsize) { 641 req->out.h.error = -EIO;
642 err = fuse_copy_one(&cs, &in->h, sizeof(in->h)); 642 /* SETXATTR is special, since it may contain too large data */
643 if (!err) 643 if (in->h.opcode == FUSE_SETXATTR)
644 err = fuse_copy_args(&cs, in->numargs, in->argpages, 644 req->out.h.error = -E2BIG;
645 (struct fuse_arg *) in->args, 0); 645 request_end(fc, req);
646 goto restart;
646 } 647 }
648 spin_unlock(&fuse_lock);
649 fuse_copy_init(&cs, 1, req, iov, nr_segs);
650 err = fuse_copy_one(&cs, &in->h, sizeof(in->h));
651 if (!err)
652 err = fuse_copy_args(&cs, in->numargs, in->argpages,
653 (struct fuse_arg *) in->args, 0);
647 fuse_copy_finish(&cs); 654 fuse_copy_finish(&cs);
648
649 spin_lock(&fuse_lock); 655 spin_lock(&fuse_lock);
650 req->locked = 0; 656 req->locked = 0;
651 if (!err && req->interrupted) 657 if (!err && req->interrupted)