aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2011-12-13 05:58:49 -0500
committerMiklos Szeredi <mszeredi@suse.cz>2011-12-13 05:58:49 -0500
commitb18da0c56e9ff43a007b6c8e302c62e720964151 (patch)
treedca57bc1042c576474529768533d6efb88716f35
parentc411cc88d873b3f68635a04691f7f115c46bc39e (diff)
fuse: support ioctl on directories
Multiplexing filesystems may want to support ioctls on the underlying files and directores (e.g. FS_IOC_{GET,SET}FLAGS). Ioctl support on directories was missing so add it now. Reported-by: Antonio SJ Musumeci <bile@landofbile.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
-rw-r--r--fs/fuse/dir.c26
-rw-r--r--fs/fuse/file.c8
-rw-r--r--fs/fuse/fuse_i.h2
-rw-r--r--include/linux/fuse.h7
4 files changed, 38 insertions, 5 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 9f63e493a9b6..344577933f62 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1182,6 +1182,30 @@ static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
1182 return fuse_fsync_common(file, start, end, datasync, 1); 1182 return fuse_fsync_common(file, start, end, datasync, 1);
1183} 1183}
1184 1184
1185static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1186 unsigned long arg)
1187{
1188 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1189
1190 /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1191 if (fc->minor < 18)
1192 return -ENOTTY;
1193
1194 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1195}
1196
1197static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1198 unsigned long arg)
1199{
1200 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1201
1202 if (fc->minor < 18)
1203 return -ENOTTY;
1204
1205 return fuse_ioctl_common(file, cmd, arg,
1206 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1207}
1208
1185static bool update_mtime(unsigned ivalid) 1209static bool update_mtime(unsigned ivalid)
1186{ 1210{
1187 /* Always update if mtime is explicitly set */ 1211 /* Always update if mtime is explicitly set */
@@ -1596,6 +1620,8 @@ static const struct file_operations fuse_dir_operations = {
1596 .open = fuse_dir_open, 1620 .open = fuse_dir_open,
1597 .release = fuse_dir_release, 1621 .release = fuse_dir_release,
1598 .fsync = fuse_dir_fsync, 1622 .fsync = fuse_dir_fsync,
1623 .unlocked_ioctl = fuse_dir_ioctl,
1624 .compat_ioctl = fuse_dir_compat_ioctl,
1599}; 1625};
1600 1626
1601static const struct inode_operations fuse_common_inode_operations = { 1627static const struct inode_operations fuse_common_inode_operations = {
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index c297425cba71..4a199fd93fbd 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1926,8 +1926,8 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
1926} 1926}
1927EXPORT_SYMBOL_GPL(fuse_do_ioctl); 1927EXPORT_SYMBOL_GPL(fuse_do_ioctl);
1928 1928
1929static long fuse_file_ioctl_common(struct file *file, unsigned int cmd, 1929long fuse_ioctl_common(struct file *file, unsigned int cmd,
1930 unsigned long arg, unsigned int flags) 1930 unsigned long arg, unsigned int flags)
1931{ 1931{
1932 struct inode *inode = file->f_dentry->d_inode; 1932 struct inode *inode = file->f_dentry->d_inode;
1933 struct fuse_conn *fc = get_fuse_conn(inode); 1933 struct fuse_conn *fc = get_fuse_conn(inode);
@@ -1944,13 +1944,13 @@ static long fuse_file_ioctl_common(struct file *file, unsigned int cmd,
1944static long fuse_file_ioctl(struct file *file, unsigned int cmd, 1944static long fuse_file_ioctl(struct file *file, unsigned int cmd,
1945 unsigned long arg) 1945 unsigned long arg)
1946{ 1946{
1947 return fuse_file_ioctl_common(file, cmd, arg, 0); 1947 return fuse_ioctl_common(file, cmd, arg, 0);
1948} 1948}
1949 1949
1950static long fuse_file_compat_ioctl(struct file *file, unsigned int cmd, 1950static long fuse_file_compat_ioctl(struct file *file, unsigned int cmd,
1951 unsigned long arg) 1951 unsigned long arg)
1952{ 1952{
1953 return fuse_file_ioctl_common(file, cmd, arg, FUSE_IOCTL_COMPAT); 1953 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_COMPAT);
1954} 1954}
1955 1955
1956/* 1956/*
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index cf6db0a93219..09337bcc2554 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -765,6 +765,8 @@ ssize_t fuse_direct_io(struct file *file, const char __user *buf,
765 size_t count, loff_t *ppos, int write); 765 size_t count, loff_t *ppos, int write);
766long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, 766long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
767 unsigned int flags); 767 unsigned int flags);
768long fuse_ioctl_common(struct file *file, unsigned int cmd,
769 unsigned long arg, unsigned int flags);
768unsigned fuse_file_poll(struct file *file, poll_table *wait); 770unsigned fuse_file_poll(struct file *file, poll_table *wait);
769int fuse_dev_release(struct inode *inode, struct file *file); 771int fuse_dev_release(struct inode *inode, struct file *file);
770 772
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index 464cff526860..446c89718b9c 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -50,6 +50,9 @@
50 * 50 *
51 * 7.17 51 * 7.17
52 * - add FUSE_FLOCK_LOCKS and FUSE_RELEASE_FLOCK_UNLOCK 52 * - add FUSE_FLOCK_LOCKS and FUSE_RELEASE_FLOCK_UNLOCK
53 *
54 * 7.18
55 * - add FUSE_IOCTL_DIR flag
53 */ 56 */
54 57
55#ifndef _LINUX_FUSE_H 58#ifndef _LINUX_FUSE_H
@@ -81,7 +84,7 @@
81#define FUSE_KERNEL_VERSION 7 84#define FUSE_KERNEL_VERSION 7
82 85
83/** Minor version number of this interface */ 86/** Minor version number of this interface */
84#define FUSE_KERNEL_MINOR_VERSION 17 87#define FUSE_KERNEL_MINOR_VERSION 18
85 88
86/** The node ID of the root inode */ 89/** The node ID of the root inode */
87#define FUSE_ROOT_ID 1 90#define FUSE_ROOT_ID 1
@@ -214,6 +217,7 @@ struct fuse_file_lock {
214 * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed 217 * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed
215 * FUSE_IOCTL_RETRY: retry with new iovecs 218 * FUSE_IOCTL_RETRY: retry with new iovecs
216 * FUSE_IOCTL_32BIT: 32bit ioctl 219 * FUSE_IOCTL_32BIT: 32bit ioctl
220 * FUSE_IOCTL_DIR: is a directory
217 * 221 *
218 * FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs 222 * FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs
219 */ 223 */
@@ -221,6 +225,7 @@ struct fuse_file_lock {
221#define FUSE_IOCTL_UNRESTRICTED (1 << 1) 225#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
222#define FUSE_IOCTL_RETRY (1 << 2) 226#define FUSE_IOCTL_RETRY (1 << 2)
223#define FUSE_IOCTL_32BIT (1 << 3) 227#define FUSE_IOCTL_32BIT (1 << 3)
228#define FUSE_IOCTL_DIR (1 << 4)
224 229
225#define FUSE_IOCTL_MAX_IOV 256 230#define FUSE_IOCTL_MAX_IOV 256
226 231