@@ -346,8 +346,9 @@ struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx(
if (res == 0)
return NULL;
- if (!ext4_has_encryption_key(inode))
- ext4_generate_encryption_key(inode);
+ res = ext4_generate_encryption_key(inode);
+ if (res)
+ return ERR_PTR(res);
/* Get a crypto context based on the key.
* A new context is allocated if no context matches the requested key.
@@ -99,9 +99,17 @@ int ext4_generate_encryption_key(struct inode *inode)
struct ext4_encryption_context ctx;
struct user_key_payload *ukp;
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
- int res = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
- EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
- &ctx, sizeof(ctx));
+ int res;
+
+ mutex_lock(&ei->i_encryption_lock);
+ if (ext4_has_encryption_key(inode)) {
+ mutex_unlock(&ei->i_encryption_lock);
+ return 0;
+ }
+
+ res = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
+ EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
+ &ctx, sizeof(ctx));
if (res != sizeof(ctx)) {
if (res > 0)
@@ -154,6 +162,7 @@ out:
key_put(keyring_key);
if (res < 0)
crypt_key->mode = EXT4_ENCRYPTION_MODE_INVALID;
+ mutex_unlock(&ei->i_encryption_lock);
return res;
}
@@ -989,6 +989,7 @@ struct ext4_inode_info {
#ifdef CONFIG_EXT4_FS_ENCRYPTION
/* Encryption params */
struct ext4_encryption_key i_encryption_key;
+ struct mutex i_encryption_lock;
#endif
};
@@ -948,6 +948,9 @@ static void init_once(void *foo)
init_rwsem(&ei->xattr_sem);
init_rwsem(&ei->i_data_sem);
init_rwsem(&ei->i_mmap_sem);
+#ifdef CONFIG_EXT4_FS_ENCRYPTION
+ mutex_init(&ei->i_encryption_lock);
+#endif
inode_init_once(&ei->vfs_inode);
}