Skip to content

Commit

Permalink
fuse: Prepare to handle multiple pages in writeback
Browse files Browse the repository at this point in the history
The .writepages callback will issue writeback requests with more than one
page aboard. Make existing end/check code be aware of this.

Signed-off-by: Maxim Patlasov <MPatlasov@parallels.com>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
  • Loading branch information
Pavel Emelyanov authored and Miklos Szeredi committed Oct 1, 2013
1 parent adcadfa commit 385b126
Showing 1 changed file with 16 additions and 8 deletions.
24 changes: 16 additions & 8 deletions fs/fuse/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,8 @@ static bool fuse_page_is_writeback(struct inode *inode, pgoff_t index)

BUG_ON(req->inode != inode);
curr_index = req->misc.write.in.offset >> PAGE_CACHE_SHIFT;
if (curr_index == index) {
if (curr_index <= index &&
index < curr_index + req->num_pages) {
found = true;
break;
}
Expand Down Expand Up @@ -1409,7 +1410,10 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf,

static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req)
{
__free_page(req->pages[0]);
int i;

for (i = 0; i < req->num_pages; i++)
__free_page(req->pages[i]);
fuse_file_put(req->ff, false);
}

Expand All @@ -1418,11 +1422,14 @@ static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req)
struct inode *inode = req->inode;
struct fuse_inode *fi = get_fuse_inode(inode);
struct backing_dev_info *bdi = inode->i_mapping->backing_dev_info;
int i;

list_del(&req->writepages_entry);
dec_bdi_stat(bdi, BDI_WRITEBACK);
dec_zone_page_state(req->pages[0], NR_WRITEBACK_TEMP);
bdi_writeout_inc(bdi);
for (i = 0; i < req->num_pages; i++) {
dec_bdi_stat(bdi, BDI_WRITEBACK);
dec_zone_page_state(req->pages[i], NR_WRITEBACK_TEMP);
bdi_writeout_inc(bdi);
}
wake_up(&fi->page_waitq);
}

Expand All @@ -1434,14 +1441,15 @@ __acquires(fc->lock)
struct fuse_inode *fi = get_fuse_inode(req->inode);
loff_t size = i_size_read(req->inode);
struct fuse_write_in *inarg = &req->misc.write.in;
__u64 data_size = req->num_pages * PAGE_CACHE_SIZE;

if (!fc->connected)
goto out_free;

if (inarg->offset + PAGE_CACHE_SIZE <= size) {
inarg->size = PAGE_CACHE_SIZE;
if (inarg->offset + data_size <= size) {
inarg->size = data_size;
} else if (inarg->offset < size) {
inarg->size = size & (PAGE_CACHE_SIZE - 1);
inarg->size = size - inarg->offset;
} else {
/* Got truncated off completely */
goto out_free;
Expand Down

0 comments on commit 385b126

Please sign in to comment.