fuse: support ioctl on directories
authorMiklos Szeredi <mszeredi@suse.cz>
Tue, 13 Dec 2011 10:58:49 +0000 (11:58 +0100)
committerMiklos Szeredi <mszeredi@suse.cz>
Tue, 13 Dec 2011 10:58:49 +0000 (11:58 +0100)
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>
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/fuse_i.h
include/linux/fuse.h

index 9f63e493a9b6f79b1d4c3b667074742c2c29821a..344577933f620cc1df0e580a762fbea58659b918 100644 (file)
@@ -1182,6 +1182,30 @@ static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
        return fuse_fsync_common(file, start, end, datasync, 1);
 }
 
+static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
+                           unsigned long arg)
+{
+       struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
+
+       /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
+       if (fc->minor < 18)
+               return -ENOTTY;
+
+       return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
+}
+
+static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
+                                  unsigned long arg)
+{
+       struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
+
+       if (fc->minor < 18)
+               return -ENOTTY;
+
+       return fuse_ioctl_common(file, cmd, arg,
+                                FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
+}
+
 static bool update_mtime(unsigned ivalid)
 {
        /* Always update if mtime is explicitly set  */
@@ -1596,6 +1620,8 @@ static const struct file_operations fuse_dir_operations = {
        .open           = fuse_dir_open,
        .release        = fuse_dir_release,
        .fsync          = fuse_dir_fsync,
+       .unlocked_ioctl = fuse_dir_ioctl,
+       .compat_ioctl   = fuse_dir_compat_ioctl,
 };
 
 static const struct inode_operations fuse_common_inode_operations = {
index c297425cba713c773f9bcf6d7f9d07359819c83a..4a199fd93fbddaace1a65f74bc3872bfcbb76cc5 100644 (file)
@@ -1926,8 +1926,8 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
 }
 EXPORT_SYMBOL_GPL(fuse_do_ioctl);
 
-static long fuse_file_ioctl_common(struct file *file, unsigned int cmd,
-                                  unsigned long arg, unsigned int flags)
+long fuse_ioctl_common(struct file *file, unsigned int cmd,
+                      unsigned long arg, unsigned int flags)
 {
        struct inode *inode = file->f_dentry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
@@ -1944,13 +1944,13 @@ static long fuse_file_ioctl_common(struct file *file, unsigned int cmd,
 static long fuse_file_ioctl(struct file *file, unsigned int cmd,
                            unsigned long arg)
 {
-       return fuse_file_ioctl_common(file, cmd, arg, 0);
+       return fuse_ioctl_common(file, cmd, arg, 0);
 }
 
 static long fuse_file_compat_ioctl(struct file *file, unsigned int cmd,
                                   unsigned long arg)
 {
-       return fuse_file_ioctl_common(file, cmd, arg, FUSE_IOCTL_COMPAT);
+       return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_COMPAT);
 }
 
 /*
index cf6db0a932192c30d6dc65a327cca84e7258a5dc..09337bcc255427fe16dbcb1f6c4605831c3cae92 100644 (file)
@@ -765,6 +765,8 @@ ssize_t fuse_direct_io(struct file *file, const char __user *buf,
                       size_t count, loff_t *ppos, int write);
 long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
                   unsigned int flags);
+long fuse_ioctl_common(struct file *file, unsigned int cmd,
+                      unsigned long arg, unsigned int flags);
 unsigned fuse_file_poll(struct file *file, poll_table *wait);
 int fuse_dev_release(struct inode *inode, struct file *file);
 
index 464cff52686092c0f862f551b2db53ed3050b629..446c89718b9cdb986f80feaba08ab4593d865607 100644 (file)
@@ -50,6 +50,9 @@
  *
  * 7.17
  *  - add FUSE_FLOCK_LOCKS and FUSE_RELEASE_FLOCK_UNLOCK
+ *
+ * 7.18
+ *  - add FUSE_IOCTL_DIR flag
  */
 
 #ifndef _LINUX_FUSE_H
@@ -81,7 +84,7 @@
 #define FUSE_KERNEL_VERSION 7
 
 /** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 17
+#define FUSE_KERNEL_MINOR_VERSION 18
 
 /** The node ID of the root inode */
 #define FUSE_ROOT_ID 1
@@ -214,6 +217,7 @@ struct fuse_file_lock {
  * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed
  * FUSE_IOCTL_RETRY: retry with new iovecs
  * FUSE_IOCTL_32BIT: 32bit ioctl
+ * FUSE_IOCTL_DIR: is a directory
  *
  * FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs
  */
@@ -221,6 +225,7 @@ struct fuse_file_lock {
 #define FUSE_IOCTL_UNRESTRICTED        (1 << 1)
 #define FUSE_IOCTL_RETRY       (1 << 2)
 #define FUSE_IOCTL_32BIT       (1 << 3)
+#define FUSE_IOCTL_DIR         (1 << 4)
 
 #define FUSE_IOCTL_MAX_IOV     256