summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@openvz.org>2013-10-10 17:10:16 +0400
committerMiklos Szeredi <mszeredi@suse.cz>2014-04-02 15:38:47 +0200
commita92adc824ed5feaa2d4f7029f21170f574987aee (patch)
treec9eff424e5bcdf453915d7c6aed709d0d0fb24eb
parent650b22b941fa03590c4a3671e79ec2c96ea59e9a (diff)
downloadlinux-a92adc824ed5feaa2d4f7029f21170f574987aee.tar.gz
linux-a92adc824ed5feaa2d4f7029f21170f574987aee.tar.bz2
linux-a92adc824ed5feaa2d4f7029f21170f574987aee.zip
fuse: Prepare to handle short reads
A helper which gets called when read reports less bytes than was requested. See patch "trust kernel i_size only" for details. Signed-off-by: Maxim Patlasov <MPatlasov@parallels.com> Signed-off-by: Pavel Emelyanov <xemul@openvz.org> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
-rw-r--r--fs/fuse/file.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 2489aca4d1a6..592d7b48e421 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -671,6 +671,15 @@ static void fuse_read_update_size(struct inode *inode, loff_t size,
spin_unlock(&fc->lock);
}
+static void fuse_short_read(struct fuse_req *req, struct inode *inode,
+ u64 attr_ver)
+{
+ size_t num_read = req->out.args[0].size;
+
+ loff_t pos = page_offset(req->pages[0]) + num_read;
+ fuse_read_update_size(inode, pos, attr_ver);
+}
+
static int fuse_readpage(struct file *file, struct page *page)
{
struct fuse_io_priv io = { .async = 0, .file = file };
@@ -708,18 +717,18 @@ static int fuse_readpage(struct file *file, struct page *page)
req->page_descs[0].length = count;
num_read = fuse_send_read(req, &io, pos, count, NULL);
err = req->out.h.error;
- fuse_put_request(fc, req);
if (!err) {
/*
* Short read means EOF. If file size is larger, truncate it
*/
if (num_read < count)
- fuse_read_update_size(inode, pos + num_read, attr_ver);
+ fuse_short_read(req, inode, attr_ver);
SetPageUptodate(page);
}
+ fuse_put_request(fc, req);
fuse_invalidate_atime(inode);
out:
unlock_page(page);
@@ -742,13 +751,9 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req)
/*
* Short read means EOF. If file size is larger, truncate it
*/
- if (!req->out.h.error && num_read < count) {
- loff_t pos;
+ if (!req->out.h.error && num_read < count)
+ fuse_short_read(req, inode, req->misc.read.attr_ver);
- pos = page_offset(req->pages[0]) + num_read;
- fuse_read_update_size(inode, pos,
- req->misc.read.attr_ver);
- }
fuse_invalidate_atime(inode);
}