diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2006-01-06 03:19:42 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-06 11:33:56 -0500 |
commit | 6ad84acab972f4dfc78e6fdb04c419f82c497d29 (patch) | |
tree | d1a1370c158fbbf42b5e6d66e5f8046ac7bb9485 /fs/fuse/file.c | |
parent | 3ec870d524c9150add120475c8ddcfa50574f98e (diff) |
[PATCH] fuse: ensure progress in read and write
In direct_io mode, send at least one page per reqest. Previously it was
possible that reqests with zero data were sent, and hence the read/write
didn't make any progress, resulting in an infinite (though interruptible)
loop.
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/file.c')
-rw-r--r-- | fs/fuse/file.c | 7 |
1 files changed, 3 insertions, 4 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index c989f0e9456b..05dedddf4289 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -475,7 +475,7 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf, | |||
475 | 475 | ||
476 | nbytes = min(nbytes, (unsigned) FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT); | 476 | nbytes = min(nbytes, (unsigned) FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT); |
477 | npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; | 477 | npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; |
478 | npages = min(npages, FUSE_MAX_PAGES_PER_REQ); | 478 | npages = min(max(npages, 1), FUSE_MAX_PAGES_PER_REQ); |
479 | down_read(¤t->mm->mmap_sem); | 479 | down_read(¤t->mm->mmap_sem); |
480 | npages = get_user_pages(current, current->mm, user_addr, npages, write, | 480 | npages = get_user_pages(current, current->mm, user_addr, npages, write, |
481 | 0, req->pages, NULL); | 481 | 0, req->pages, NULL); |
@@ -506,7 +506,6 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf, | |||
506 | return -EINTR; | 506 | return -EINTR; |
507 | 507 | ||
508 | while (count) { | 508 | while (count) { |
509 | size_t tmp; | ||
510 | size_t nres; | 509 | size_t nres; |
511 | size_t nbytes = min(count, nmax); | 510 | size_t nbytes = min(count, nmax); |
512 | int err = fuse_get_user_pages(req, buf, nbytes, !write); | 511 | int err = fuse_get_user_pages(req, buf, nbytes, !write); |
@@ -514,8 +513,8 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf, | |||
514 | res = err; | 513 | res = err; |
515 | break; | 514 | break; |
516 | } | 515 | } |
517 | tmp = (req->num_pages << PAGE_SHIFT) - req->page_offset; | 516 | nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset; |
518 | nbytes = min(nbytes, tmp); | 517 | nbytes = min(count, nbytes); |
519 | if (write) | 518 | if (write) |
520 | nres = fuse_send_write(req, file, inode, pos, nbytes); | 519 | nres = fuse_send_write(req, file, inode, pos, nbytes); |
521 | else | 520 | else |