static int ll_get_context(struct inode *inode, void *ctx, size_t len)
{
- struct dentry *dentry;
+ struct dentry *dentry = d_find_any_alias(inode);
int rc;
- if (hlist_empty(&inode->i_dentry))
- return -ENODATA;
-
- hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
- break;
- }
-
rc = ll_vfs_getxattr(dentry, inode, LL_XATTR_NAME_ENCRYPTION_CONTEXT,
ctx, len);
+ if (dentry)
+ dput(dentry);
/* used as encryption unit size */
if (S_ISREG(inode->i_mode))
return rc;
}
+int ll_set_encflags(struct inode *inode, void *encctx, __u32 encctxlen,
+ bool preload)
+{
+ unsigned int ext_flags;
+ int rc = 0;
+
+ /* used as encryption unit size */
+ if (S_ISREG(inode->i_mode))
+ inode->i_blkbits = LUSTRE_ENCRYPTION_BLOCKBITS;
+ ext_flags = ll_inode_to_ext_flags(inode->i_flags) | LUSTRE_ENCRYPT_FL;
+ ll_update_inode_flags(inode, ext_flags);
+
+ if (encctx && encctxlen)
+ rc = ll_xattr_cache_insert(inode,
+ LL_XATTR_NAME_ENCRYPTION_CONTEXT,
+ encctx, encctxlen);
+ if (rc)
+ return rc;
+
+ return preload ? llcrypt_get_encryption_info(inode) : 0;
+}
+
+/* ll_set_context has 2 distinct behaviors, depending on the value of inode
+ * parameter:
+ * - inode is NULL:
+ * passed fs_data is a struct md_op_data *. We need to store enc ctx in
+ * op_data, so that it will be sent along to the server with the request that
+ * the caller is preparing, thus saving a setxattr request.
+ * - inode is not NULL:
+ * normal case in which passed fs_data is a struct dentry *, letting proceed
+ * with setxattr operation.
+ * This use case should only be used when explicitly setting a new encryption
+ * policy on an existing, empty directory.
+ */
static int ll_set_context(struct inode *inode, const void *ctx, size_t len,
void *fs_data)
{
- unsigned int ext_flags;
struct dentry *dentry;
- struct md_op_data *op_data;
- struct ptlrpc_request *req = NULL;
int rc;
- if (inode == NULL)
- return 0;
+ if (inode == NULL) {
+ struct md_op_data *op_data = (struct md_op_data *)fs_data;
- ext_flags = ll_inode_to_ext_flags(inode->i_flags) | LUSTRE_ENCRYPT_FL;
- dentry = (struct dentry *)fs_data;
+ if (!op_data)
+ return -EINVAL;
+
+ OBD_ALLOC(op_data->op_file_encctx, len);
+ if (op_data->op_file_encctx == NULL)
+ return -ENOMEM;
+ op_data->op_file_encctx_size = len;
+ memcpy(op_data->op_file_encctx, ctx, len);
+ return 0;
+ }
/* Encrypting the root directory is not allowed */
- if (inode->i_ino == inode->i_sb->s_root->d_inode->i_ino)
+ if (is_root_inode(inode))
return -EPERM;
- op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
- LUSTRE_OPC_ANY, NULL);
- if (IS_ERR(op_data))
- return PTR_ERR(op_data);
-
- op_data->op_attr_flags = LUSTRE_ENCRYPT_FL;
- op_data->op_xvalid |= OP_XVALID_FLAGS;
- rc = md_setattr(ll_i2sbi(inode)->ll_md_exp, op_data, NULL, 0, &req);
- ll_finish_md_op_data(op_data);
- ptlrpc_req_finished(req);
- if (rc)
- return rc;
-
+ dentry = (struct dentry *)fs_data;
+ set_bit(LLIF_SET_ENC_CTX, &ll_i2info(inode)->lli_flags);
rc = ll_vfs_setxattr(dentry, inode, LL_XATTR_NAME_ENCRYPTION_CONTEXT,
ctx, len, XATTR_CREATE);
if (rc)
return rc;
- /* used as encryption unit size */
- if (S_ISREG(inode->i_mode))
- inode->i_blkbits = LUSTRE_ENCRYPTION_BLOCKBITS;
- ll_update_inode_flags(inode, ext_flags);
- return 0;
+ return ll_set_encflags(inode, (void *)ctx, len, false);
+}
+
+void llcrypt_free_ctx(void *encctx, __u32 size)
+{
+ if (encctx)
+ OBD_FREE(encctx, size);
}
-inline bool ll_sbi_has_test_dummy_encryption(struct ll_sb_info *sbi)
+bool ll_sbi_has_test_dummy_encryption(struct ll_sb_info *sbi)
{
return unlikely(sbi->ll_flags & LL_SBI_TEST_DUMMY_ENCRYPTION);
}
return sbi ? ll_sbi_has_test_dummy_encryption(sbi) : false;
}
-inline bool ll_sbi_has_encrypt(struct ll_sb_info *sbi)
+bool ll_sbi_has_encrypt(struct ll_sb_info *sbi)
{
return sbi->ll_flags & LL_SBI_ENCRYPT;
}
-inline void ll_sbi_set_encrypt(struct ll_sb_info *sbi, bool set)
+void ll_sbi_set_encrypt(struct ll_sb_info *sbi, bool set)
{
if (set)
sbi->ll_flags |= LL_SBI_ENCRYPT;
.max_namelen = NAME_MAX,
};
#else /* !HAVE_LUSTRE_CRYPTO */
-inline bool ll_sbi_has_test_dummy_encryption(struct ll_sb_info *sbi)
+int ll_set_encflags(struct inode *inode, void *encctx, __u32 encctxlen,
+ bool preload)
+{
+ return 0;
+}
+
+void llcrypt_free_ctx(void *encctx, __u32 size)
+{
+}
+
+bool ll_sbi_has_test_dummy_encryption(struct ll_sb_info *sbi)
{
return false;
}
-inline bool ll_sbi_has_encrypt(struct ll_sb_info *sbi)
+bool ll_sbi_has_encrypt(struct ll_sb_info *sbi)
{
return false;
}
-inline void ll_sbi_set_encrypt(struct ll_sb_info *sbi, bool set)
+void ll_sbi_set_encrypt(struct ll_sb_info *sbi, bool set)
{
}
#endif