Whamcloud - gitweb
LU-17504 build: fix gcc-13 [-Werror=stringop-overread] error
[fs/lustre-release.git] / lustre / llite / crypto.c
index 3f69d39..728fa81 100644 (file)
 #include "llite_internal.h"
 
 #ifdef HAVE_LUSTRE_CRYPTO
+#include <libcfs/libcfs_crypto.h>
 
 static int ll_get_context(struct inode *inode, void *ctx, size_t len)
 {
-       struct dentry *dentry = d_find_any_alias(inode);
        int rc;
 
-       rc = ll_vfs_getxattr(dentry, inode, LL_XATTR_NAME_ENCRYPTION_CONTEXT,
-                            ctx, len);
-       if (dentry)
-               dput(dentry);
+       /* Get enc context xattr directly instead of going through the VFS,
+        * as there is no xattr handler for "encryption.".
+        */
+       rc = ll_xattr_list(inode, xattr_for_enc(inode),
+                          XATTR_ENCRYPTION_T, ctx, len, OBD_MD_FLXATTR);
 
        /* used as encryption unit size */
        if (S_ISREG(inode->i_mode))
@@ -60,12 +61,12 @@ int ll_set_encflags(struct inode *inode, void *encctx, __u32 encctxlen,
 
        if (encctx && encctxlen)
                rc = ll_xattr_cache_insert(inode,
-                                          LL_XATTR_NAME_ENCRYPTION_CONTEXT,
+                                          xattr_for_enc(inode),
                                           encctx, encctxlen);
        if (rc)
                return rc;
 
-       return preload ? llcrypt_get_encryption_info(inode) : 0;
+       return preload ? llcrypt_prepare_readdir(inode) : 0;
 }
 
 /* ll_set_context has 2 distinct behaviors, depending on the value of inode
@@ -75,15 +76,15 @@ int ll_set_encflags(struct inode *inode, void *encctx, __u32 encctxlen,
  *   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.
+ *   normal case, 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)
 {
-       struct dentry *dentry;
+       struct ptlrpc_request *req = NULL;
+       struct ll_sb_info *sbi;
        int rc;
 
        if (inode == NULL) {
@@ -104,46 +105,113 @@ static int ll_set_context(struct inode *inode, const void *ctx, size_t len,
        if (is_root_inode(inode))
                return -EPERM;
 
-       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);
+       sbi = ll_i2sbi(inode);
+       /* Send setxattr request to lower layers directly instead of going
+        * through the VFS, as there is no xattr handler for "encryption.".
+        */
+       rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode),
+                        OBD_MD_FLXATTR, xattr_for_enc(inode),
+                        ctx, len, XATTR_CREATE, ll_i2suppgid(inode), &req);
        if (rc)
                return rc;
+       ptlrpc_req_finished(req);
 
        return ll_set_encflags(inode, (void *)ctx, len, false);
 }
 
+/**
+ * ll_file_open_encrypt() - overlay to llcrypt_file_open
+ * @inode: the inode being opened
+ * @filp: the struct file being set up
+ *
+ * This overlay function is necessary to handle encrypted file open without
+ * the key. We allow this access pattern to applications that know what they
+ * are doing, by using the specific flag O_CIPHERTEXT.
+ * This flag is only compatible with O_DIRECT IOs, to make sure ciphertext
+ * data is wiped from page cache once IOs are finished.
+ */
+int ll_file_open_encrypt(struct inode *inode, struct file *filp)
+{
+       int rc;
+
+       rc = llcrypt_file_open(inode, filp);
+       if (likely(rc != -ENOKEY))
+               return rc;
+
+       if (rc == -ENOKEY &&
+           (filp->f_flags & O_CIPHERTEXT) == O_CIPHERTEXT &&
+           filp->f_flags & O_DIRECT)
+               /* allow open with O_CIPHERTEXT flag when we have O_DIRECT */
+               rc = 0;
+
+       return rc;
+}
+
 void llcrypt_free_ctx(void *encctx, __u32 size)
 {
        if (encctx)
                OBD_FREE(encctx, size);
 }
 
-bool ll_sbi_has_test_dummy_encryption(struct ll_sb_info *sbi)
+#ifdef HAVE_FSCRYPT_DUMMY_CONTEXT_ENABLED
+bool ll_sb_has_test_dummy_encryption(struct super_block *sb)
 {
-       return unlikely(sbi->ll_flags & LL_SBI_TEST_DUMMY_ENCRYPTION);
+       struct ll_sb_info *sbi = s2lsi(sb)->lsi_llsbi;
+
+       return sbi ?
+              unlikely(test_bit(LL_SBI_TEST_DUMMY_ENCRYPTION, sbi->ll_flags)) :
+              false;
 }
 
 static bool ll_dummy_context(struct inode *inode)
 {
-       struct ll_sb_info *sbi = ll_i2sbi(inode);
+       return ll_sb_has_test_dummy_encryption(inode->i_sb);
+}
+#else
+static const union llcrypt_policy *
+ll_get_dummy_policy(struct super_block *sb)
+{
+       struct lustre_sb_info *lsi = s2lsi(sb);
+
+#ifdef HAVE_FSCRYPT_DUMMY_POLICY
+       return lsi ? lsi->lsi_dummy_enc_policy.policy : NULL;
+#else
+       return lsi ? lsi->lsi_dummy_enc_policy.ctx : NULL;
+#endif
+}
 
-       return sbi ? ll_sbi_has_test_dummy_encryption(sbi) : false;
+bool ll_sb_has_test_dummy_encryption(struct super_block *sb)
+{
+       return ll_get_dummy_policy(sb) != NULL;
 }
+#endif
 
 bool ll_sbi_has_encrypt(struct ll_sb_info *sbi)
 {
-       return sbi->ll_flags & LL_SBI_ENCRYPT;
+       return test_bit(LL_SBI_ENCRYPT, sbi->ll_flags);
 }
 
 void ll_sbi_set_encrypt(struct ll_sb_info *sbi, bool set)
 {
+       if (set) {
+               set_bit(LL_SBI_ENCRYPT, sbi->ll_flags);
+       } else {
+               clear_bit(LL_SBI_ENCRYPT, sbi->ll_flags);
+               clear_bit(LL_SBI_TEST_DUMMY_ENCRYPTION, sbi->ll_flags);
+       }
+}
+
+bool ll_sbi_has_name_encrypt(struct ll_sb_info *sbi)
+{
+       return test_bit(LL_SBI_ENCRYPT_NAME, sbi->ll_flags);
+}
+
+void ll_sbi_set_name_encrypt(struct ll_sb_info *sbi, bool set)
+{
        if (set)
-               sbi->ll_flags |= LL_SBI_ENCRYPT;
+               set_bit(LL_SBI_ENCRYPT_NAME, sbi->ll_flags);
        else
-               sbi->ll_flags &=
-                       ~(LL_SBI_ENCRYPT | LL_SBI_TEST_DUMMY_ENCRYPTION);
+               clear_bit(LL_SBI_ENCRYPT_NAME, sbi->ll_flags);
 }
 
 static bool ll_empty_dir(struct inode *inode)
@@ -158,11 +226,390 @@ static bool ll_empty_dir(struct inode *inode)
        return true;
 }
 
+static int ll_digest_long_name(struct inode *dir, struct llcrypt_name *fname,
+                              struct lu_fid *fid, int digested)
+{
+       int rc = 0;
+
+       if (digested) {
+               /* Without the key, for long names user should have struct
+                * ll_digest_filename representation of the dentry instead of
+                * the name. So make sure it is valid, return fid and put
+                * excerpt of cipher text name in disk_name.
+                */
+               struct ll_digest_filename *digest;
+
+               if (fname->crypto_buf.len < sizeof(struct ll_digest_filename)) {
+                       rc = -EINVAL;
+                       goto out_free;
+               }
+               digest = (struct ll_digest_filename *)fname->disk_name.name;
+               *fid = digest->ldf_fid;
+               if (!fid_is_sane(fid)) {
+                       rc = -EINVAL;
+                       goto out_free;
+               }
+               fname->disk_name.name = digest->ldf_excerpt;
+               fname->disk_name.len = sizeof(digest->ldf_excerpt);
+       }
+       if (IS_ENCRYPTED(dir) &&
+           !name_is_dot_or_dotdot(fname->disk_name.name,
+                                  fname->disk_name.len)) {
+               int presented_len = critical_chars(fname->disk_name.name,
+                                                  fname->disk_name.len);
+               char *buf;
+
+               buf = kmalloc(presented_len + 1, GFP_NOFS);
+               if (!buf) {
+                       rc = -ENOMEM;
+                       goto out_free;
+               }
+
+               if (presented_len == fname->disk_name.len)
+                       memcpy(buf, fname->disk_name.name, presented_len);
+               else
+                       critical_encode(fname->disk_name.name,
+                                       fname->disk_name.len, buf);
+               buf[presented_len] = '\0';
+               kfree(fname->crypto_buf.name);
+               fname->crypto_buf.name = buf;
+               fname->crypto_buf.len = presented_len;
+               fname->disk_name.name = fname->crypto_buf.name;
+               fname->disk_name.len = fname->crypto_buf.len;
+       }
+out_free:
+       if (rc < 0)
+               llcrypt_free_filename(fname);
+
+       return rc;
+}
+
+/**
+ * ll_prepare_lookup() - overlay to llcrypt_prepare_lookup
+ * @dir: the directory that will be searched
+ * @de: the dentry contain the user-provided filename being searched for
+ * @fname: the filename information to be filled in
+ * @fid: fid retrieved from user-provided filename
+ *
+ * This overlay function is necessary to properly encode @fname after
+ * encryption, as it will be sent over the wire.
+ * This overlay function is also necessary to handle the case of operations
+ * carried out without the key. Normally llcrypt makes use of digested names in
+ * that case. Having a digested name works for local file systems that can call
+ * llcrypt_match_name(), but Lustre server side is not aware of encryption.
+ * FID and name hash can then easily be extracted and put into the
+ * requests sent to servers.
+ */
+int ll_prepare_lookup(struct inode *dir, struct dentry *de,
+                     struct llcrypt_name *fname, struct lu_fid *fid)
+{
+       struct qstr iname = QSTR_INIT(de->d_name.name, de->d_name.len);
+       int digested = 0;
+       int rc;
+
+       if (fid && IS_ENCRYPTED(dir) && llcrypt_policy_has_filename_enc(dir) &&
+           !llcrypt_has_encryption_key(dir)) {
+               struct lustre_sb_info *lsi = s2lsi(dir->i_sb);
+
+               if ((!(lsi->lsi_flags & LSI_FILENAME_ENC_B64_OLD_CLI) &&
+                    iname.name[0] == LLCRYPT_DIGESTED_CHAR) ||
+                   ((lsi->lsi_flags & LSI_FILENAME_ENC_B64_OLD_CLI) &&
+                    iname.name[0] == LLCRYPT_DIGESTED_CHAR_OLD))
+                       digested = 1;
+       }
+
+       iname.name += digested;
+       iname.len -= digested;
+
+       if (fid) {
+               fid->f_seq = 0;
+               fid->f_oid = 0;
+               fid->f_ver = 0;
+       }
+       if (unlikely(filename_is_volatile(iname.name,
+                                         iname.len, NULL))) {
+               /* keep volatile name as-is, matters for server side */
+               memset(fname, 0, sizeof(struct llcrypt_name));
+               fname->disk_name.name = (unsigned char *)iname.name;
+               fname->disk_name.len = iname.len;
+               rc = 0;
+       } else {
+                /* We should use ll_prepare_lookup() but Lustre handles the
+                 * digested form its own way, incompatible with llcrypt's
+                 * digested form.
+                 */
+               rc = llcrypt_setup_filename(dir, &iname, 1, fname);
+               if ((rc == 0 || rc == -ENOENT) &&
+#if defined(HAVE_FSCRYPT_NOKEY_NAME) && !defined(CONFIG_LL_ENCRYPTION)
+                   fname->is_nokey_name) {
+#else
+                   fname->is_ciphertext_name) {
+#endif
+                       spin_lock(&de->d_lock);
+                       de->d_flags |= DCACHE_NOKEY_NAME;
+                       spin_unlock(&de->d_lock);
+               }
+       }
+       if (rc == -ENOENT) {
+               if (((is_root_inode(dir) &&
+                    iname.len == strlen(dot_fscrypt_name) &&
+                    strncmp(iname.name, dot_fscrypt_name, iname.len) == 0) ||
+                    (!llcrypt_has_encryption_key(dir) &&
+                     unlikely(filename_is_volatile(iname.name,
+                                                   iname.len, NULL))))) {
+                       /* In case of subdir mount of an encrypted directory,
+                        * we allow lookup of /.fscrypt directory.
+                        */
+                       /* For purpose of migration or mirroring without enc key
+                        * we allow lookup of volatile file without enc context.
+                        */
+                       memset(fname, 0, sizeof(struct llcrypt_name));
+                       fname->disk_name.name = (unsigned char *)iname.name;
+                       fname->disk_name.len = iname.len;
+                       rc = 0;
+               } else if (!llcrypt_has_encryption_key(dir)) {
+                       rc = -ENOKEY;
+               }
+       }
+       if (rc)
+               return rc;
+
+       return ll_digest_long_name(dir, fname, fid, digested);
+}
+
+/**
+ * ll_setup_filename() - overlay to llcrypt_setup_filename
+ * @dir: the directory that will be searched
+ * @iname: the user-provided filename being searched for
+ * @lookup: 1 if we're allowed to proceed without the key because it's
+ *     ->lookup() or we're finding the dir_entry for deletion; 0 if we cannot
+ *     proceed without the key because we're going to create the dir_entry.
+ * @fname: the filename information to be filled in
+ * @fid: fid retrieved from user-provided filename
+ *
+ * This overlay function is necessary to properly encode @fname after
+ * encryption, as it will be sent over the wire.
+ * This overlay function is also necessary to handle the case of operations
+ * carried out without the key. Normally llcrypt makes use of digested names in
+ * that case. Having a digested name works for local file systems that can call
+ * llcrypt_match_name(), but Lustre server side is not aware of encryption.
+ * So for keyless @lookup operations on long names, for Lustre we choose to
+ * present to users the encoded struct ll_digest_filename, instead of a digested
+ * name. FID and name hash can then easily be extracted and put into the
+ * requests sent to servers.
+ */
+int ll_setup_filename(struct inode *dir, const struct qstr *iname,
+                     int lookup, struct llcrypt_name *fname,
+                     struct lu_fid *fid)
+{
+       int digested = 0;
+       struct qstr dname;
+       int rc;
+
+       if (fid && IS_ENCRYPTED(dir) && llcrypt_policy_has_filename_enc(dir) &&
+           !llcrypt_has_encryption_key(dir)) {
+               struct lustre_sb_info *lsi = s2lsi(dir->i_sb);
+
+               if ((!(lsi->lsi_flags & LSI_FILENAME_ENC_B64_OLD_CLI) &&
+                    iname->name[0] == LLCRYPT_DIGESTED_CHAR) ||
+                   ((lsi->lsi_flags & LSI_FILENAME_ENC_B64_OLD_CLI) &&
+                    iname->name[0] == LLCRYPT_DIGESTED_CHAR_OLD))
+                       digested = 1;
+       }
+
+       dname.name = iname->name + digested;
+       dname.len = iname->len - digested;
+
+       if (fid) {
+               fid->f_seq = 0;
+               fid->f_oid = 0;
+               fid->f_ver = 0;
+       }
+       if (unlikely(filename_is_volatile(iname->name,
+                                         iname->len, NULL))) {
+               /* keep volatile name as-is, matters for server side */
+               memset(fname, 0, sizeof(struct llcrypt_name));
+               fname->disk_name.name = (unsigned char *)iname->name;
+               fname->disk_name.len = iname->len;
+               rc = 0;
+       } else {
+               rc = llcrypt_setup_filename(dir, &dname, lookup, fname);
+       }
+       if (rc == -ENOENT && lookup) {
+               if (((is_root_inode(dir) &&
+                    iname->len == strlen(dot_fscrypt_name) &&
+                    strncmp(iname->name, dot_fscrypt_name, iname->len) == 0) ||
+                    (!llcrypt_has_encryption_key(dir) &&
+                     unlikely(filename_is_volatile(iname->name,
+                                                   iname->len, NULL))))) {
+                       /* In case of subdir mount of an encrypted directory,
+                        * we allow lookup of /.fscrypt directory.
+                        */
+                       /* For purpose of migration or mirroring without enc key
+                        * we allow lookup of volatile file without enc context.
+                        */
+                       memset(fname, 0, sizeof(struct llcrypt_name));
+                       fname->disk_name.name = (unsigned char *)iname->name;
+                       fname->disk_name.len = iname->len;
+                       rc = 0;
+               } else if (!llcrypt_has_encryption_key(dir)) {
+                       rc = -ENOKEY;
+               }
+       }
+       if (rc)
+               return rc;
+
+       return ll_digest_long_name(dir, fname, fid, digested);
+}
+
+/**
+ * ll_fname_disk_to_usr() - overlay to llcrypt_fname_disk_to_usr
+ * @inode: the inode to convert name
+ * @hash: major hash for inode
+ * @minor_hash: minor hash for inode
+ * @iname: the user-provided filename needing conversion
+ * @oname: the filename information to be filled in
+ * @fid: the user-provided fid for filename
+ *
+ * The caller must have allocated sufficient memory for the @oname string.
+ *
+ * This overlay function is necessary to properly decode @iname before
+ * decryption, as it comes from the wire.
+ * This overlay function is also necessary to handle the case of operations
+ * carried out without the key. Normally llcrypt makes use of digested names in
+ * that case. Having a digested name works for local file systems that can call
+ * llcrypt_match_name(), but Lustre server side is not aware of encryption.
+ * So for keyless @lookup operations on long names, for Lustre we choose to
+ * present to users the encoded struct ll_digest_filename, instead of a digested
+ * name. FID and name hash can then easily be extracted and put into the
+ * requests sent to servers.
+ */
+int ll_fname_disk_to_usr(struct inode *inode,
+                        u32 hash, u32 minor_hash,
+                        struct llcrypt_str *iname, struct llcrypt_str *oname,
+                        struct lu_fid *fid)
+{
+       struct llcrypt_str lltr = LLTR_INIT(iname->name, iname->len);
+       struct ll_digest_filename digest;
+       int digested = 0;
+       char *buf = NULL;
+       int rc;
+
+       if (IS_ENCRYPTED(inode)) {
+               if (!name_is_dot_or_dotdot(lltr.name, lltr.len) &&
+                   strnchr(lltr.name, lltr.len, '=')) {
+                       /* Only proceed to critical decode if
+                        * iname contains espace char '='.
+                        */
+                       int len = lltr.len;
+
+                       buf = kmalloc(len, GFP_NOFS);
+                       if (!buf)
+                               return -ENOMEM;
+
+                       len = critical_decode(lltr.name, len, buf);
+                       lltr.name = buf;
+                       lltr.len = len;
+               }
+               if (lltr.len > LL_CRYPTO_BLOCK_SIZE * 2 &&
+                   !llcrypt_has_encryption_key(inode) &&
+                   llcrypt_policy_has_filename_enc(inode)) {
+                       struct lustre_sb_info *lsi = s2lsi(inode->i_sb);
+
+                       digested = 1;
+                       /* Without the key for long names, set the dentry name
+                        * to the representing struct ll_digest_filename. It
+                        * will be encoded by llcrypt for display, and will
+                        * enable further lookup requests.
+                        */
+                       if (!fid)
+                               return -EINVAL;
+                       digest.ldf_fid = *fid;
+                       memcpy(digest.ldf_excerpt,
+                              LLCRYPT_EXTRACT_DIGEST(lltr.name, lltr.len),
+                              sizeof(digest.ldf_excerpt));
+
+                       lltr.name = (char *)&digest;
+                       lltr.len = sizeof(digest);
+
+                       if (!(lsi->lsi_flags & LSI_FILENAME_ENC_B64_OLD_CLI))
+                               oname->name[0] = LLCRYPT_DIGESTED_CHAR;
+                       else
+                               oname->name[0] = LLCRYPT_DIGESTED_CHAR_OLD;
+                       oname->name = oname->name + 1;
+                       oname->len--;
+               }
+       }
+
+       rc = llcrypt_fname_disk_to_usr(inode, hash, minor_hash, &lltr, oname);
+
+       kfree(buf);
+       oname->name = oname->name - digested;
+       oname->len = oname->len + digested;
+
+       return rc;
+}
+
+#if !defined(HAVE_FSCRYPT_D_REVALIDATE) || defined(CONFIG_LL_ENCRYPTION)
+/* Copied from llcrypt_d_revalidate, as it is not exported */
+/*
+ * Validate dentries in encrypted directories to make sure we aren't potentially
+ * caching stale dentries after a key has been added.
+ */
+int llcrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
+{
+       struct dentry *dir;
+       int err;
+       int valid;
+
+       /*
+        * Plaintext names are always valid, since llcrypt doesn't support
+        * reverting to ciphertext names without evicting the directory's inode
+        * -- which implies eviction of the dentries in the directory.
+        */
+       if (!llcrypt_is_nokey_name(dentry))
+               return 1;
+
+       /*
+        * Ciphertext name; valid if the directory's key is still unavailable.
+        *
+        * Although llcrypt forbids rename() on ciphertext names, we still must
+        * use dget_parent() here rather than use ->d_parent directly.  That's
+        * because a corrupted fs image may contain directory hard links, which
+        * the VFS handles by moving the directory's dentry tree in the dcache
+        * each time ->lookup() finds the directory and it already has a dentry
+        * elsewhere.  Thus ->d_parent can be changing, and we must safely grab
+        * a reference to some ->d_parent to prevent it from being freed.
+        */
+
+       if (flags & LOOKUP_RCU)
+               return -ECHILD;
+
+       dir = dget_parent(dentry);
+       err = llcrypt_prepare_readdir(d_inode(dir));
+       valid = !llcrypt_has_encryption_key(d_inode(dir));
+       dput(dir);
+
+       if (err < 0)
+               return err;
+
+       return valid;
+}
+#endif /* !HAVE_FSCRYPT_D_REVALIDATE || CONFIG_LL_ENCRYPTION */
+
 const struct llcrypt_operations lustre_cryptops = {
        .key_prefix             = "lustre:",
        .get_context            = ll_get_context,
        .set_context            = ll_set_context,
+#ifdef HAVE_FSCRYPT_DUMMY_CONTEXT_ENABLED
        .dummy_context          = ll_dummy_context,
+#else
+#ifdef HAVE_FSCRYPT_DUMMY_POLICY
+       .get_dummy_policy       = ll_get_dummy_policy,
+#else
+       .get_dummy_context      = ll_get_dummy_policy,
+#endif
+#endif /* !HAVE_FSCRYPT_DUMMY_CONTEXT_ENABLED */
        .empty_dir              = ll_empty_dir,
        .max_namelen            = NAME_MAX,
 };
@@ -173,11 +620,16 @@ int ll_set_encflags(struct inode *inode, void *encctx, __u32 encctxlen,
        return 0;
 }
 
+int ll_file_open_encrypt(struct inode *inode, struct file *filp)
+{
+       return llcrypt_file_open(inode, filp);
+}
+
 void llcrypt_free_ctx(void *encctx, __u32 size)
 {
 }
 
-bool ll_sbi_has_test_dummy_encryption(struct ll_sb_info *sbi)
+bool ll_sb_has_test_dummy_encryption(struct super_block *sb)
 {
        return false;
 }
@@ -190,5 +642,54 @@ bool ll_sbi_has_encrypt(struct ll_sb_info *sbi)
 void ll_sbi_set_encrypt(struct ll_sb_info *sbi, bool set)
 {
 }
+
+bool ll_sbi_has_name_encrypt(struct ll_sb_info *sbi)
+{
+       return false;
+}
+
+void ll_sbi_set_name_encrypt(struct ll_sb_info *sbi, bool set)
+{
+}
+
+int ll_prepare_lookup(struct inode *dir, struct dentry *de,
+                     struct llcrypt_name *fname, struct lu_fid *fid)
+{
+       const struct qstr *iname = &de->d_name;
+
+       if (fid) {
+               fid->f_seq = 0;
+               fid->f_oid = 0;
+               fid->f_ver = 0;
+       }
+
+       return llcrypt_setup_filename(dir, iname, 1, fname);
+}
+
+int ll_setup_filename(struct inode *dir, const struct qstr *iname,
+                     int lookup, struct llcrypt_name *fname,
+                     struct lu_fid *fid)
+{
+       if (fid) {
+               fid->f_seq = 0;
+               fid->f_oid = 0;
+               fid->f_ver = 0;
+       }
+
+       return llcrypt_setup_filename(dir, iname, lookup, fname);
+}
+
+int ll_fname_disk_to_usr(struct inode *inode,
+                        u32 hash, u32 minor_hash,
+                        struct llcrypt_str *iname, struct llcrypt_str *oname,
+                        struct lu_fid *fid)
+{
+       return llcrypt_fname_disk_to_usr(inode, hash, minor_hash, iname, oname);
+}
+
+int llcrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
+{
+       return 1;
+}
 #endif