diff options
Diffstat (limited to 'fs/fuse')
-rw-r--r-- | fs/fuse/file.c | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index f79de7c8cdfa..11f22a3d728a 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -444,22 +444,25 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file, | |||
444 | return outarg.size; | 444 | return outarg.size; |
445 | } | 445 | } |
446 | 446 | ||
447 | static int fuse_prepare_write(struct file *file, struct page *page, | 447 | static int fuse_write_begin(struct file *file, struct address_space *mapping, |
448 | unsigned offset, unsigned to) | 448 | loff_t pos, unsigned len, unsigned flags, |
449 | struct page **pagep, void **fsdata) | ||
449 | { | 450 | { |
450 | /* No op */ | 451 | pgoff_t index = pos >> PAGE_CACHE_SHIFT; |
452 | |||
453 | *pagep = __grab_cache_page(mapping, index); | ||
454 | if (!*pagep) | ||
455 | return -ENOMEM; | ||
451 | return 0; | 456 | return 0; |
452 | } | 457 | } |
453 | 458 | ||
454 | static int fuse_commit_write(struct file *file, struct page *page, | 459 | static int fuse_buffered_write(struct file *file, struct inode *inode, |
455 | unsigned offset, unsigned to) | 460 | loff_t pos, unsigned count, struct page *page) |
456 | { | 461 | { |
457 | int err; | 462 | int err; |
458 | size_t nres; | 463 | size_t nres; |
459 | unsigned count = to - offset; | ||
460 | struct inode *inode = page->mapping->host; | ||
461 | struct fuse_conn *fc = get_fuse_conn(inode); | 464 | struct fuse_conn *fc = get_fuse_conn(inode); |
462 | loff_t pos = page_offset(page) + offset; | 465 | unsigned offset = pos & (PAGE_CACHE_SIZE - 1); |
463 | struct fuse_req *req; | 466 | struct fuse_req *req; |
464 | 467 | ||
465 | if (is_bad_inode(inode)) | 468 | if (is_bad_inode(inode)) |
@@ -475,20 +478,35 @@ static int fuse_commit_write(struct file *file, struct page *page, | |||
475 | nres = fuse_send_write(req, file, inode, pos, count); | 478 | nres = fuse_send_write(req, file, inode, pos, count); |
476 | err = req->out.h.error; | 479 | err = req->out.h.error; |
477 | fuse_put_request(fc, req); | 480 | fuse_put_request(fc, req); |
478 | if (!err && nres != count) | 481 | if (!err && !nres) |
479 | err = -EIO; | 482 | err = -EIO; |
480 | if (!err) { | 483 | if (!err) { |
481 | pos += count; | 484 | pos += nres; |
482 | spin_lock(&fc->lock); | 485 | spin_lock(&fc->lock); |
483 | if (pos > inode->i_size) | 486 | if (pos > inode->i_size) |
484 | i_size_write(inode, pos); | 487 | i_size_write(inode, pos); |
485 | spin_unlock(&fc->lock); | 488 | spin_unlock(&fc->lock); |
486 | 489 | ||
487 | if (offset == 0 && to == PAGE_CACHE_SIZE) | 490 | if (count == PAGE_CACHE_SIZE) |
488 | SetPageUptodate(page); | 491 | SetPageUptodate(page); |
489 | } | 492 | } |
490 | fuse_invalidate_attr(inode); | 493 | fuse_invalidate_attr(inode); |
491 | return err; | 494 | return err ? err : nres; |
495 | } | ||
496 | |||
497 | static int fuse_write_end(struct file *file, struct address_space *mapping, | ||
498 | loff_t pos, unsigned len, unsigned copied, | ||
499 | struct page *page, void *fsdata) | ||
500 | { | ||
501 | struct inode *inode = mapping->host; | ||
502 | int res = 0; | ||
503 | |||
504 | if (copied) | ||
505 | res = fuse_buffered_write(file, inode, pos, copied, page); | ||
506 | |||
507 | unlock_page(page); | ||
508 | page_cache_release(page); | ||
509 | return res; | ||
492 | } | 510 | } |
493 | 511 | ||
494 | static void fuse_release_user_pages(struct fuse_req *req, int write) | 512 | static void fuse_release_user_pages(struct fuse_req *req, int write) |
@@ -819,8 +837,8 @@ static const struct file_operations fuse_direct_io_file_operations = { | |||
819 | 837 | ||
820 | static const struct address_space_operations fuse_file_aops = { | 838 | static const struct address_space_operations fuse_file_aops = { |
821 | .readpage = fuse_readpage, | 839 | .readpage = fuse_readpage, |
822 | .prepare_write = fuse_prepare_write, | 840 | .write_begin = fuse_write_begin, |
823 | .commit_write = fuse_commit_write, | 841 | .write_end = fuse_write_end, |
824 | .readpages = fuse_readpages, | 842 | .readpages = fuse_readpages, |
825 | .set_page_dirty = fuse_set_page_dirty, | 843 | .set_page_dirty = fuse_set_page_dirty, |
826 | .bmap = fuse_bmap, | 844 | .bmap = fuse_bmap, |