Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e6f58a1 authored by Nick Piggin's avatar Nick Piggin Committed by Linus Torvalds
Browse files

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: default avatarNick Piggin <npiggin@suse.de>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent fb53b309
Loading
Loading
Loading
Loading
+32 −14
Original line number Diff line number Diff line
@@ -444,22 +444,25 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file,
	return outarg.size;
}

static int fuse_prepare_write(struct file *file, struct page *page,
			      unsigned offset, unsigned to)
static int fuse_write_begin(struct file *file, struct address_space *mapping,
			loff_t pos, unsigned len, unsigned flags,
			struct page **pagep, void **fsdata)
{
	/* No op */
	pgoff_t index = pos >> PAGE_CACHE_SHIFT;

	*pagep = __grab_cache_page(mapping, index);
	if (!*pagep)
		return -ENOMEM;
	return 0;
}

static int fuse_commit_write(struct file *file, struct page *page,
			     unsigned offset, unsigned to)
static int fuse_buffered_write(struct file *file, struct inode *inode,
			       loff_t pos, unsigned count, struct page *page)
{
	int err;
	size_t nres;
	unsigned count = to - offset;
	struct inode *inode = page->mapping->host;
	struct fuse_conn *fc = get_fuse_conn(inode);
	loff_t pos = page_offset(page) + offset;
	unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
	struct fuse_req *req;

	if (is_bad_inode(inode))
@@ -475,20 +478,35 @@ static int fuse_commit_write(struct file *file, struct page *page,
	nres = fuse_send_write(req, file, inode, pos, count);
	err = req->out.h.error;
	fuse_put_request(fc, req);
	if (!err && nres != count)
	if (!err && !nres)
		err = -EIO;
	if (!err) {
		pos += count;
		pos += nres;
		spin_lock(&fc->lock);
		if (pos > inode->i_size)
			i_size_write(inode, pos);
		spin_unlock(&fc->lock);

		if (offset == 0 && to == PAGE_CACHE_SIZE)
		if (count == PAGE_CACHE_SIZE)
			SetPageUptodate(page);
	}
	fuse_invalidate_attr(inode);
	return err;
	return err ? err : nres;
}

static int fuse_write_end(struct file *file, struct address_space *mapping,
			loff_t pos, unsigned len, unsigned copied,
			struct page *page, void *fsdata)
{
	struct inode *inode = mapping->host;
	int res = 0;

	if (copied)
		res = fuse_buffered_write(file, inode, pos, copied, page);

	unlock_page(page);
	page_cache_release(page);
	return res;
}

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 = {

static const struct address_space_operations fuse_file_aops  = {
	.readpage	= fuse_readpage,
	.prepare_write	= fuse_prepare_write,
	.commit_write	= fuse_commit_write,
	.write_begin	= fuse_write_begin,
	.write_end	= fuse_write_end,
	.readpages	= fuse_readpages,
	.set_page_dirty	= fuse_set_page_dirty,
	.bmap		= fuse_bmap,