atm: idt77252: fix a memleak in open_card_ubr0
[platform/kernel/linux-rpi.git] / fs / ceph / ioctl.c
index deac817..91a8491 100644 (file)
@@ -6,6 +6,7 @@
 #include "mds_client.h"
 #include "ioctl.h"
 #include <linux/ceph/striper.h>
+#include <linux/fscrypt.h>
 
 /*
  * ioctls
@@ -268,9 +269,96 @@ static long ceph_ioctl_syncio(struct file *file)
        return 0;
 }
 
+static int vet_mds_for_fscrypt(struct file *file)
+{
+       int i, ret = -EOPNOTSUPP;
+       struct ceph_mds_client  *mdsc = ceph_sb_to_mdsc(file_inode(file)->i_sb);
+
+       mutex_lock(&mdsc->mutex);
+       for (i = 0; i < mdsc->max_sessions; i++) {
+               struct ceph_mds_session *s = mdsc->sessions[i];
+
+               if (!s)
+                       continue;
+               if (test_bit(CEPHFS_FEATURE_ALTERNATE_NAME, &s->s_features))
+                       ret = 0;
+               break;
+       }
+       mutex_unlock(&mdsc->mutex);
+       return ret;
+}
+
+static long ceph_set_encryption_policy(struct file *file, unsigned long arg)
+{
+       int ret, got = 0;
+       struct inode *inode = file_inode(file);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+
+       /* encrypted directories can't have striped layout */
+       if (ci->i_layout.stripe_count > 1)
+               return -EINVAL;
+
+       ret = vet_mds_for_fscrypt(file);
+       if (ret)
+               return ret;
+
+       /*
+        * Ensure we hold these caps so that we _know_ that the rstats check
+        * in the empty_dir check is reliable.
+        */
+       ret = ceph_get_caps(file, CEPH_CAP_FILE_SHARED, 0, -1, &got);
+       if (ret)
+               return ret;
+
+       ret = fscrypt_ioctl_set_policy(file, (const void __user *)arg);
+       if (got)
+               ceph_put_cap_refs(ci, got);
+
+       return ret;
+}
+
+static const char *ceph_ioctl_cmd_name(const unsigned int cmd)
+{
+       switch (cmd) {
+       case CEPH_IOC_GET_LAYOUT:
+               return "get_layout";
+       case CEPH_IOC_SET_LAYOUT:
+               return "set_layout";
+       case CEPH_IOC_SET_LAYOUT_POLICY:
+               return "set_layout_policy";
+       case CEPH_IOC_GET_DATALOC:
+               return "get_dataloc";
+       case CEPH_IOC_LAZYIO:
+               return "lazyio";
+       case CEPH_IOC_SYNCIO:
+               return "syncio";
+       case FS_IOC_SET_ENCRYPTION_POLICY:
+               return "set_encryption_policy";
+       case FS_IOC_GET_ENCRYPTION_POLICY:
+               return "get_encryption_policy";
+       case FS_IOC_GET_ENCRYPTION_POLICY_EX:
+               return "get_encryption_policy_ex";
+       case FS_IOC_ADD_ENCRYPTION_KEY:
+               return "add_encryption_key";
+       case FS_IOC_REMOVE_ENCRYPTION_KEY:
+               return "remove_encryption_key";
+       case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
+               return "remove_encryption_key_all_users";
+       case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
+               return "get_encryption_key_status";
+       case FS_IOC_GET_ENCRYPTION_NONCE:
+               return "get_encryption_nonce";
+       default:
+               return "unknown";
+       }
+}
+
 long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       dout("ioctl file %p cmd %u arg %lu\n", file, cmd, arg);
+       int ret;
+
+       dout("ioctl file %p cmd %s arg %lu\n", file,
+            ceph_ioctl_cmd_name(cmd), arg);
        switch (cmd) {
        case CEPH_IOC_GET_LAYOUT:
                return ceph_ioctl_get_layout(file, (void __user *)arg);
@@ -289,6 +377,43 @@ long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
        case CEPH_IOC_SYNCIO:
                return ceph_ioctl_syncio(file);
+
+       case FS_IOC_SET_ENCRYPTION_POLICY:
+               return ceph_set_encryption_policy(file, arg);
+
+       case FS_IOC_GET_ENCRYPTION_POLICY:
+               ret = vet_mds_for_fscrypt(file);
+               if (ret)
+                       return ret;
+               return fscrypt_ioctl_get_policy(file, (void __user *)arg);
+
+       case FS_IOC_GET_ENCRYPTION_POLICY_EX:
+               ret = vet_mds_for_fscrypt(file);
+               if (ret)
+                       return ret;
+               return fscrypt_ioctl_get_policy_ex(file, (void __user *)arg);
+
+       case FS_IOC_ADD_ENCRYPTION_KEY:
+               ret = vet_mds_for_fscrypt(file);
+               if (ret)
+                       return ret;
+               return fscrypt_ioctl_add_key(file, (void __user *)arg);
+
+       case FS_IOC_REMOVE_ENCRYPTION_KEY:
+               return fscrypt_ioctl_remove_key(file, (void __user *)arg);
+
+       case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
+               return fscrypt_ioctl_remove_key_all_users(file,
+                                                         (void __user *)arg);
+
+       case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
+               return fscrypt_ioctl_get_key_status(file, (void __user *)arg);
+
+       case FS_IOC_GET_ENCRYPTION_NONCE:
+               ret = vet_mds_for_fscrypt(file);
+               if (ret)
+                       return ret;
+               return fscrypt_ioctl_get_nonce(file, (void __user *)arg);
        }
 
        return -ENOTTY;