mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
650b22b941
commit
a92adc824e
|
@ -671,6 +671,15 @@ static void fuse_read_update_size(struct inode *inode, loff_t size,
|
||||||
spin_unlock(&fc->lock);
|
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)
|
static int fuse_readpage(struct file *file, struct page *page)
|
||||||
{
|
{
|
||||||
struct fuse_io_priv io = { .async = 0, .file = file };
|
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;
|
req->page_descs[0].length = count;
|
||||||
num_read = fuse_send_read(req, &io, pos, count, NULL);
|
num_read = fuse_send_read(req, &io, pos, count, NULL);
|
||||||
err = req->out.h.error;
|
err = req->out.h.error;
|
||||||
fuse_put_request(fc, req);
|
|
||||||
|
|
||||||
if (!err) {
|
if (!err) {
|
||||||
/*
|
/*
|
||||||
* Short read means EOF. If file size is larger, truncate it
|
* Short read means EOF. If file size is larger, truncate it
|
||||||
*/
|
*/
|
||||||
if (num_read < count)
|
if (num_read < count)
|
||||||
fuse_read_update_size(inode, pos + num_read, attr_ver);
|
fuse_short_read(req, inode, attr_ver);
|
||||||
|
|
||||||
SetPageUptodate(page);
|
SetPageUptodate(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fuse_put_request(fc, req);
|
||||||
fuse_invalidate_atime(inode);
|
fuse_invalidate_atime(inode);
|
||||||
out:
|
out:
|
||||||
unlock_page(page);
|
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
|
* Short read means EOF. If file size is larger, truncate it
|
||||||
*/
|
*/
|
||||||
if (!req->out.h.error && num_read < count) {
|
if (!req->out.h.error && num_read < count)
|
||||||
loff_t pos;
|
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);
|
fuse_invalidate_atime(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue