+ if (it->it_op & IT_CREAT && encrypt) {
+ if (unlikely(filename_is_volatile(dentry->d_name.name,
+ dentry->d_name.len, NULL))) {
+ /* get encryption context from reference file */
+ int ctx_size = LLCRYPT_ENC_CTX_SIZE;
+ struct lustre_sb_info *lsi;
+ struct file *ref_file;
+ struct inode *ref_inode;
+ void *ctx;
+
+ rc = volatile_ref_file(dentry->d_name.name,
+ dentry->d_name.len,
+ &ref_file);
+ if (rc)
+ GOTO(out, retval = ERR_PTR(rc));
+
+ ref_inode = file_inode(ref_file);
+ if (!ref_inode) {
+ fput(ref_file);
+ GOTO(inherit, rc = -EINVAL);
+ }
+
+ lsi = s2lsi(ref_inode->i_sb);
+
+getctx:
+ OBD_ALLOC(ctx, ctx_size);
+ if (!ctx)
+ GOTO(out, retval = ERR_PTR(-ENOMEM));
+
+#ifdef CONFIG_LL_ENCRYPTION
+ rc = lsi->lsi_cop->get_context(ref_inode,
+ ctx, ctx_size);
+#elif defined(HAVE_LUSTRE_CRYPTO)
+ rc = ref_inode->i_sb->s_cop->get_context(ref_inode,
+ ctx, ctx_size);
+#else
+ rc = -ENODATA;
+#endif
+ if (rc == -ERANGE) {
+ OBD_FREE(ctx, ctx_size);
+ ctx_size *= 2;
+ goto getctx;
+ }
+ fput(ref_file);
+ if (rc < 0) {
+ OBD_FREE(ctx, ctx_size);
+ GOTO(inherit, rc);
+ }
+
+ op_data->op_file_encctx_size = rc;
+ if (rc == ctx_size) {
+ op_data->op_file_encctx = ctx;
+ } else {
+ OBD_ALLOC(op_data->op_file_encctx,
+ op_data->op_file_encctx_size);
+ if (!op_data->op_file_encctx) {
+ OBD_FREE(ctx, ctx_size);
+ GOTO(out, retval = ERR_PTR(-ENOMEM));
+ }
+ memcpy(op_data->op_file_encctx, ctx,
+ op_data->op_file_encctx_size);
+ OBD_FREE(ctx, ctx_size);
+ }
+ } else {
+inherit:
+ rc = llcrypt_inherit_context(parent, NULL, op_data,
+ false);
+ if (rc)
+ GOTO(out, retval = ERR_PTR(rc));
+ }
+ if (encctx != NULL)
+ *encctx = op_data->op_file_encctx;
+ if (encctxlen != NULL)
+ *encctxlen = op_data->op_file_encctx_size;
+ } else {
+ if (encctx != NULL)
+ *encctx = NULL;
+ if (encctxlen != NULL)
+ *encctxlen = 0;
+ }