aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Van Braeckel <tomvanbraeckel@gmail.com>2015-01-11 23:22:16 -0500
committerMiklos Szeredi <mszeredi@suse.cz>2015-03-19 10:29:22 -0400
commit94e4fe2cab3d43b3ba7c3f721743006a8c9d913a (patch)
treeb6bb327977ae0e4a1173ab32bb4f93f9b460e17e
parentaa991b3b267e24f578bac7b09cc57579b660304b (diff)
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 <giedriuswork@gmail.com> Reported-by: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Tom Van Braeckel <tomvanbraeckel@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
-rw-r--r--fs/fuse/dev.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 71c4619af333..39706c57ad3c 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,
1353 return err; 1353 return err;
1354} 1354}
1355 1355
1356static int fuse_dev_open(struct inode *inode, struct file *file)
1357{
1358 /*
1359 * The fuse device's file's private_data is used to hold
1360 * the fuse_conn(ection) when it is mounted, and is used to
1361 * keep track of whether the file has been mounted already.
1362 */
1363 file->private_data = NULL;
1364 return 0;
1365}
1366
1356static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov, 1367static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov,
1357 unsigned long nr_segs, loff_t pos) 1368 unsigned long nr_segs, loff_t pos)
1358{ 1369{
@@ -2220,6 +2231,7 @@ static int fuse_dev_fasync(int fd, struct file *file, int on)
2220 2231
2221const struct file_operations fuse_dev_operations = { 2232const struct file_operations fuse_dev_operations = {
2222 .owner = THIS_MODULE, 2233 .owner = THIS_MODULE,
2234 .open = fuse_dev_open,
2223 .llseek = no_llseek, 2235 .llseek = no_llseek,
2224 .read = do_sync_read, 2236 .read = do_sync_read,
2225 .aio_read = fuse_dev_read, 2237 .aio_read = fuse_dev_read,