Commit 5e6f58a1d7ce2fd5ef099f9aec5b3e3f7ba176b4
Committed by
Linus Torvalds
1 parent
fb53b30948
fuse: convert to new aops
[mszeredi] - don't send zero length write requests - it is not legal for the filesystem to return with zero written bytes Signed-off-by: Nick Piggin <npiggin@suse.de> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 1 changed file with 32 additions and 14 deletions Side-by-side Diff
fs/fuse/file.c
... | ... | @@ -444,22 +444,25 @@ |
444 | 444 | return outarg.size; |
445 | 445 | } |
446 | 446 | |
447 | -static int fuse_prepare_write(struct file *file, struct page *page, | |
448 | - unsigned offset, unsigned to) | |
447 | +static int fuse_write_begin(struct file *file, struct address_space *mapping, | |
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 | 456 | return 0; |
452 | 457 | } |
453 | 458 | |
454 | -static int fuse_commit_write(struct file *file, struct page *page, | |
455 | - unsigned offset, unsigned to) | |
459 | +static int fuse_buffered_write(struct file *file, struct inode *inode, | |
460 | + loff_t pos, unsigned count, struct page *page) | |
456 | 461 | { |
457 | 462 | int err; |
458 | 463 | size_t nres; |
459 | - unsigned count = to - offset; | |
460 | - struct inode *inode = page->mapping->host; | |
461 | 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 | 466 | struct fuse_req *req; |
464 | 467 | |
465 | 468 | if (is_bad_inode(inode)) |
466 | 469 | |
467 | 470 | |
468 | 471 | |
469 | 472 | |
... | ... | @@ -475,22 +478,37 @@ |
475 | 478 | nres = fuse_send_write(req, file, inode, pos, count); |
476 | 479 | err = req->out.h.error; |
477 | 480 | fuse_put_request(fc, req); |
478 | - if (!err && nres != count) | |
481 | + if (!err && !nres) | |
479 | 482 | err = -EIO; |
480 | 483 | if (!err) { |
481 | - pos += count; | |
484 | + pos += nres; | |
482 | 485 | spin_lock(&fc->lock); |
483 | 486 | if (pos > inode->i_size) |
484 | 487 | i_size_write(inode, pos); |
485 | 488 | spin_unlock(&fc->lock); |
486 | 489 | |
487 | - if (offset == 0 && to == PAGE_CACHE_SIZE) | |
490 | + if (count == PAGE_CACHE_SIZE) | |
488 | 491 | SetPageUptodate(page); |
489 | 492 | } |
490 | 493 | fuse_invalidate_attr(inode); |
491 | - return err; | |
494 | + return err ? err : nres; | |
492 | 495 | } |
493 | 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; | |
510 | +} | |
511 | + | |
494 | 512 | static void fuse_release_user_pages(struct fuse_req *req, int write) |
495 | 513 | { |
496 | 514 | unsigned i; |
... | ... | @@ -819,8 +837,8 @@ |
819 | 837 | |
820 | 838 | static const struct address_space_operations fuse_file_aops = { |
821 | 839 | .readpage = fuse_readpage, |
822 | - .prepare_write = fuse_prepare_write, | |
823 | - .commit_write = fuse_commit_write, | |
840 | + .write_begin = fuse_write_begin, | |
841 | + .write_end = fuse_write_end, | |
824 | 842 | .readpages = fuse_readpages, |
825 | 843 | .set_page_dirty = fuse_set_page_dirty, |
826 | 844 | .bmap = fuse_bmap, |