fscrypt: move body of fscrypt_prepare_setattr() out-of-line
[linux-2.6-microblaze.git] / fs / crypto / hooks.c
index 20b0df4..1c16dba 100644 (file)
@@ -54,15 +54,12 @@ EXPORT_SYMBOL_GPL(fscrypt_file_open);
 int __fscrypt_prepare_link(struct inode *inode, struct inode *dir,
                           struct dentry *dentry)
 {
-       int err;
-
-       err = fscrypt_require_key(dir);
-       if (err)
-               return err;
-
-       /* ... in case we looked up no-key name before key was added */
-       if (dentry->d_flags & DCACHE_NOKEY_NAME)
+       if (fscrypt_is_nokey_name(dentry))
                return -ENOKEY;
+       /*
+        * We don't need to separately check that the directory inode's key is
+        * available, as it's implied by the dentry not being a no-key name.
+        */
 
        if (!fscrypt_has_permitted_context(dir, inode))
                return -EXDEV;
@@ -75,19 +72,13 @@ int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry,
                             struct inode *new_dir, struct dentry *new_dentry,
                             unsigned int flags)
 {
-       int err;
-
-       err = fscrypt_require_key(old_dir);
-       if (err)
-               return err;
-
-       err = fscrypt_require_key(new_dir);
-       if (err)
-               return err;
-
-       /* ... in case we looked up no-key name(s) before key was added */
-       if ((old_dentry->d_flags | new_dentry->d_flags) & DCACHE_NOKEY_NAME)
+       if (fscrypt_is_nokey_name(old_dentry) ||
+           fscrypt_is_nokey_name(new_dentry))
                return -ENOKEY;
+       /*
+        * We don't need to separately check that the directory inodes' keys are
+        * available, as it's implied by the dentries not being no-key names.
+        */
 
        if (old_dir != new_dir) {
                if (IS_ENCRYPTED(new_dir) &&
@@ -123,6 +114,20 @@ int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
 }
 EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup);
 
+int __fscrypt_prepare_readdir(struct inode *dir)
+{
+       return fscrypt_get_encryption_info(dir);
+}
+EXPORT_SYMBOL_GPL(__fscrypt_prepare_readdir);
+
+int __fscrypt_prepare_setattr(struct dentry *dentry, struct iattr *attr)
+{
+       if (attr->ia_valid & ATTR_SIZE)
+               return fscrypt_require_key(d_inode(dentry));
+       return 0;
+}
+EXPORT_SYMBOL_GPL(__fscrypt_prepare_setattr);
+
 /**
  * fscrypt_prepare_setflags() - prepare to change flags with FS_IOC_SETFLAGS
  * @inode: the inode on which flags are being changed
@@ -138,6 +143,7 @@ int fscrypt_prepare_setflags(struct inode *inode,
                             unsigned int oldflags, unsigned int flags)
 {
        struct fscrypt_info *ci;
+       struct key *key;
        struct fscrypt_master_key *mk;
        int err;
 
@@ -153,13 +159,14 @@ int fscrypt_prepare_setflags(struct inode *inode,
                ci = inode->i_crypt_info;
                if (ci->ci_policy.version != FSCRYPT_POLICY_V2)
                        return -EINVAL;
-               mk = ci->ci_master_key->payload.data[0];
-               down_read(&mk->mk_secret_sem);
+               key = ci->ci_master_key;
+               mk = key->payload.data[0];
+               down_read(&key->sem);
                if (is_master_key_secret_present(&mk->mk_secret))
                        err = fscrypt_derive_dirhash_key(ci, mk);
                else
                        err = -ENOKEY;
-               up_read(&mk->mk_secret_sem);
+               up_read(&key->sem);
                return err;
        }
        return 0;