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 | |
| 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')
| -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 |
