diff options
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r-- | fs/fuse/file.c | 53 |
1 files changed, 39 insertions, 14 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 2ca86141d13a..63d2980df5c9 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -163,6 +163,9 @@ static int fuse_flush(struct file *file) | |||
163 | struct fuse_flush_in inarg; | 163 | struct fuse_flush_in inarg; |
164 | int err; | 164 | int err; |
165 | 165 | ||
166 | if (is_bad_inode(inode)) | ||
167 | return -EIO; | ||
168 | |||
166 | if (fc->no_flush) | 169 | if (fc->no_flush) |
167 | return 0; | 170 | return 0; |
168 | 171 | ||
@@ -199,6 +202,9 @@ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync, | |||
199 | struct fuse_fsync_in inarg; | 202 | struct fuse_fsync_in inarg; |
200 | int err; | 203 | int err; |
201 | 204 | ||
205 | if (is_bad_inode(inode)) | ||
206 | return -EIO; | ||
207 | |||
202 | if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir)) | 208 | if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir)) |
203 | return 0; | 209 | return 0; |
204 | 210 | ||
@@ -272,16 +278,22 @@ static int fuse_readpage(struct file *file, struct page *page) | |||
272 | { | 278 | { |
273 | struct inode *inode = page->mapping->host; | 279 | struct inode *inode = page->mapping->host; |
274 | struct fuse_conn *fc = get_fuse_conn(inode); | 280 | struct fuse_conn *fc = get_fuse_conn(inode); |
275 | loff_t pos = (loff_t) page->index << PAGE_CACHE_SHIFT; | 281 | struct fuse_req *req; |
276 | struct fuse_req *req = fuse_get_request(fc); | 282 | int err; |
277 | int err = -EINTR; | 283 | |
284 | err = -EIO; | ||
285 | if (is_bad_inode(inode)) | ||
286 | goto out; | ||
287 | |||
288 | err = -EINTR; | ||
289 | req = fuse_get_request(fc); | ||
278 | if (!req) | 290 | if (!req) |
279 | goto out; | 291 | goto out; |
280 | 292 | ||
281 | req->out.page_zeroing = 1; | 293 | req->out.page_zeroing = 1; |
282 | req->num_pages = 1; | 294 | req->num_pages = 1; |
283 | req->pages[0] = page; | 295 | req->pages[0] = page; |
284 | fuse_send_read(req, file, inode, pos, PAGE_CACHE_SIZE); | 296 | fuse_send_read(req, file, inode, page_offset(page), PAGE_CACHE_SIZE); |
285 | err = req->out.h.error; | 297 | err = req->out.h.error; |
286 | fuse_put_request(fc, req); | 298 | fuse_put_request(fc, req); |
287 | if (!err) | 299 | if (!err) |
@@ -295,7 +307,7 @@ static int fuse_readpage(struct file *file, struct page *page) | |||
295 | static int fuse_send_readpages(struct fuse_req *req, struct file *file, | 307 | static int fuse_send_readpages(struct fuse_req *req, struct file *file, |
296 | struct inode *inode) | 308 | struct inode *inode) |
297 | { | 309 | { |
298 | loff_t pos = (loff_t) req->pages[0]->index << PAGE_CACHE_SHIFT; | 310 | loff_t pos = page_offset(req->pages[0]); |
299 | size_t count = req->num_pages << PAGE_CACHE_SHIFT; | 311 | size_t count = req->num_pages << PAGE_CACHE_SHIFT; |
300 | unsigned i; | 312 | unsigned i; |
301 | req->out.page_zeroing = 1; | 313 | req->out.page_zeroing = 1; |
@@ -345,6 +357,10 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
345 | struct fuse_conn *fc = get_fuse_conn(inode); | 357 | struct fuse_conn *fc = get_fuse_conn(inode); |
346 | struct fuse_readpages_data data; | 358 | struct fuse_readpages_data data; |
347 | int err; | 359 | int err; |
360 | |||
361 | if (is_bad_inode(inode)) | ||
362 | return -EIO; | ||
363 | |||
348 | data.file = file; | 364 | data.file = file; |
349 | data.inode = inode; | 365 | data.inode = inode; |
350 | data.req = fuse_get_request(fc); | 366 | data.req = fuse_get_request(fc); |
@@ -402,8 +418,13 @@ static int fuse_commit_write(struct file *file, struct page *page, | |||
402 | unsigned count = to - offset; | 418 | unsigned count = to - offset; |
403 | struct inode *inode = page->mapping->host; | 419 | struct inode *inode = page->mapping->host; |
404 | struct fuse_conn *fc = get_fuse_conn(inode); | 420 | struct fuse_conn *fc = get_fuse_conn(inode); |
405 | loff_t pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + offset; | 421 | loff_t pos = page_offset(page) + offset; |
406 | struct fuse_req *req = fuse_get_request(fc); | 422 | struct fuse_req *req; |
423 | |||
424 | if (is_bad_inode(inode)) | ||
425 | return -EIO; | ||
426 | |||
427 | req = fuse_get_request(fc); | ||
407 | if (!req) | 428 | if (!req) |
408 | return -EINTR; | 429 | return -EINTR; |
409 | 430 | ||
@@ -454,7 +475,7 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf, | |||
454 | 475 | ||
455 | nbytes = min(nbytes, (unsigned) FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT); | 476 | nbytes = min(nbytes, (unsigned) FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT); |
456 | npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; | 477 | npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; |
457 | npages = min(npages, FUSE_MAX_PAGES_PER_REQ); | 478 | npages = min(max(npages, 1), FUSE_MAX_PAGES_PER_REQ); |
458 | down_read(¤t->mm->mmap_sem); | 479 | down_read(¤t->mm->mmap_sem); |
459 | npages = get_user_pages(current, current->mm, user_addr, npages, write, | 480 | npages = get_user_pages(current, current->mm, user_addr, npages, write, |
460 | 0, req->pages, NULL); | 481 | 0, req->pages, NULL); |
@@ -475,12 +496,16 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf, | |||
475 | size_t nmax = write ? fc->max_write : fc->max_read; | 496 | size_t nmax = write ? fc->max_write : fc->max_read; |
476 | loff_t pos = *ppos; | 497 | loff_t pos = *ppos; |
477 | ssize_t res = 0; | 498 | ssize_t res = 0; |
478 | struct fuse_req *req = fuse_get_request(fc); | 499 | struct fuse_req *req; |
500 | |||
501 | if (is_bad_inode(inode)) | ||
502 | return -EIO; | ||
503 | |||
504 | req = fuse_get_request(fc); | ||
479 | if (!req) | 505 | if (!req) |
480 | return -EINTR; | 506 | return -EINTR; |
481 | 507 | ||
482 | while (count) { | 508 | while (count) { |
483 | size_t tmp; | ||
484 | size_t nres; | 509 | size_t nres; |
485 | size_t nbytes = min(count, nmax); | 510 | size_t nbytes = min(count, nmax); |
486 | int err = fuse_get_user_pages(req, buf, nbytes, !write); | 511 | int err = fuse_get_user_pages(req, buf, nbytes, !write); |
@@ -488,8 +513,8 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf, | |||
488 | res = err; | 513 | res = err; |
489 | break; | 514 | break; |
490 | } | 515 | } |
491 | tmp = (req->num_pages << PAGE_SHIFT) - req->page_offset; | 516 | nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset; |
492 | nbytes = min(nbytes, tmp); | 517 | nbytes = min(count, nbytes); |
493 | if (write) | 518 | if (write) |
494 | nres = fuse_send_write(req, file, inode, pos, nbytes); | 519 | nres = fuse_send_write(req, file, inode, pos, nbytes); |
495 | else | 520 | else |
@@ -535,9 +560,9 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf, | |||
535 | struct inode *inode = file->f_dentry->d_inode; | 560 | struct inode *inode = file->f_dentry->d_inode; |
536 | ssize_t res; | 561 | ssize_t res; |
537 | /* Don't allow parallel writes to the same file */ | 562 | /* Don't allow parallel writes to the same file */ |
538 | down(&inode->i_sem); | 563 | mutex_lock(&inode->i_mutex); |
539 | res = fuse_direct_io(file, buf, count, ppos, 1); | 564 | res = fuse_direct_io(file, buf, count, ppos, 1); |
540 | up(&inode->i_sem); | 565 | mutex_unlock(&inode->i_mutex); |
541 | return res; | 566 | return res; |
542 | } | 567 | } |
543 | 568 | ||