Commit 5e6f58a1d7ce2fd5ef099f9aec5b3e3f7ba176b4

Authored by Nick Piggin
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

... ... @@ -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,