From 0d2783626a53d4c922f82d51fa675cb5d13f0d36 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 26 Feb 2015 11:45:47 +0100 Subject: fuse: notify: don't move pages fuse_try_move_page() is not prepared for replacing pages that have already been read. Reported-by: Al Viro Signed-off-by: Miklos Szeredi Cc: stable@vger.kernel.org --- fs/fuse/dev.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs') diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index ed19a7d..b0d7e13 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1797,6 +1797,9 @@ copy_finish: static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, unsigned int size, struct fuse_copy_state *cs) { + /* Don't try to move pages (yet) */ + cs->move_pages = 0; + switch (code) { case FUSE_NOTIFY_POLL: return fuse_notify_poll(fc, size, cs); -- cgit v1.1 From aa991b3b267e24f578bac7b09cc57579b660304b Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 26 Feb 2015 11:45:47 +0100 Subject: fuse: set stolen page uptodate Regular pipe buffers' ->steal method (generic_pipe_buf_steal()) doesn't set PG_uptodate. Don't warn on this condition, just set the uptodate flag. Signed-off-by: Miklos Szeredi Cc: stable@vger.kernel.org --- fs/fuse/dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index b0d7e13..71c4619 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -890,8 +890,8 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) newpage = buf->page; - if (WARN_ON(!PageUptodate(newpage))) - return -EIO; + if (!PageUptodate(newpage)) + SetPageUptodate(newpage); ClearPageMappedToDisk(newpage); -- cgit v1.1 From 94e4fe2cab3d43b3ba7c3f721743006a8c9d913a Mon Sep 17 00:00:00 2001 From: Tom Van Braeckel Date: Mon, 12 Jan 2015 05:22:16 +0100 Subject: fuse: explicitly set /dev/fuse file's private_data The misc subsystem (which is used for /dev/fuse) initializes private_data to point to the misc device when a driver has registered a custom open file operation, and initializes it to NULL when a custom open file operation has *not* been provided. This subtle quirk is confusing, to the point where kernel code registers *empty* file open operations to have private_data point to the misc device structure. And it leads to bugs, where the addition or removal of a custom open file operation surprisingly changes the initial contents of a file's private_data structure. So to simplify things in the misc subsystem, a patch [1] has been proposed to *always* set the private_data to point to the misc device, instead of only doing this when a custom open file operation has been registered. But before this patch can be applied we need to modify drivers that make the assumption that a misc device file's private_data is initialized to NULL because they didn't register a custom open file operation, so they don't rely on this assumption anymore. FUSE uses private_data to store the fuse_conn and errors out if this is not initialized to NULL at mount time. Hence, we now set a file's private_data to NULL explicitly, to be independent of whatever value the misc subsystem initializes it to by default. [1] https://lkml.org/lkml/2014/12/4/939 Reported-by: Giedrius Statkevicius Reported-by: Thierry Reding Signed-off-by: Tom Van Braeckel Signed-off-by: Miklos Szeredi --- fs/fuse/dev.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'fs') diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 71c4619..39706c5 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1353,6 +1353,17 @@ static ssize_t fuse_dev_do_read(struct fuse_conn *fc, struct file *file, return err; } +static int fuse_dev_open(struct inode *inode, struct file *file) +{ + /* + * The fuse device's file's private_data is used to hold + * the fuse_conn(ection) when it is mounted, and is used to + * keep track of whether the file has been mounted already. + */ + file->private_data = NULL; + return 0; +} + static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { @@ -2220,6 +2231,7 @@ static int fuse_dev_fasync(int fd, struct file *file, int on) const struct file_operations fuse_dev_operations = { .owner = THIS_MODULE, + .open = fuse_dev_open, .llseek = no_llseek, .read = do_sync_read, .aio_read = fuse_dev_read, -- cgit v1.1