if (fname->name_len > NAME_MAX || fname->ctext_len > NAME_MAX)
                return -EIO;
 
-       ret = __fscrypt_prepare_readdir(fname->dir);
-       if (ret)
+       ret = ceph_fscrypt_prepare_readdir(fname->dir);
+       if (ret < 0)
                return ret;
 
        /*
        fscrypt_fname_free_buffer(&_tname);
        return ret;
 }
+
+/**
+ * ceph_fscrypt_prepare_readdir - simple __fscrypt_prepare_readdir() wrapper
+ * @dir: directory inode for readdir prep
+ *
+ * Simple wrapper around __fscrypt_prepare_readdir() that will mark directory as
+ * non-complete if this call results in having the directory unlocked.
+ *
+ * Returns:
+ *     1 - if directory was locked and key is now loaded (i.e. dir is unlocked)
+ *     0 - if directory is still locked
+ *   < 0 - if __fscrypt_prepare_readdir() fails
+ */
+int ceph_fscrypt_prepare_readdir(struct inode *dir)
+{
+       bool had_key = fscrypt_has_encryption_key(dir);
+       int err;
+
+       if (!IS_ENCRYPTED(dir))
+               return 0;
+
+       err = __fscrypt_prepare_readdir(dir);
+       if (err)
+               return err;
+       if (!had_key && fscrypt_has_encryption_key(dir)) {
+               /* directory just got unlocked, mark it as not complete */
+               ceph_dir_clear_complete(dir);
+               return 1;
+       }
+       return 0;
+}
 
 
 int ceph_fname_to_usr(const struct ceph_fname *fname, struct fscrypt_str *tname,
                      struct fscrypt_str *oname, bool *is_nokey);
+int ceph_fscrypt_prepare_readdir(struct inode *dir);
 
 #else /* CONFIG_FS_ENCRYPTION */
 
        oname->len = fname->name_len;
        return 0;
 }
+
+static inline int ceph_fscrypt_prepare_readdir(struct inode *dir)
+{
+       return 0;
+}
 #endif /* CONFIG_FS_ENCRYPTION */
 
 #endif
 
                ctx->pos = 2;
        }
 
-       err = fscrypt_prepare_readdir(inode);
-       if (err)
+       err = ceph_fscrypt_prepare_readdir(inode);
+       if (err < 0)
                return err;
 
        spin_lock(&ci->i_ceph_lock);
                return ERR_PTR(-ENAMETOOLONG);
 
        if (IS_ENCRYPTED(dir)) {
-               err = __fscrypt_prepare_readdir(dir);
-               if (err)
+               err = ceph_fscrypt_prepare_readdir(dir);
+               if (err < 0)
                        return ERR_PTR(err);
                if (!fscrypt_has_encryption_key(dir)) {
                        spin_lock(&dentry->d_lock);
 
        if (!IS_ENCRYPTED(dir))
                goto success;
 
-       ret = __fscrypt_prepare_readdir(dir);
-       if (ret)
+       ret = ceph_fscrypt_prepare_readdir(dir);
+       if (ret < 0)
                return ERR_PTR(ret);
 
        /* No key? Just ignore it. */
                        spin_unlock(&cur->d_lock);
                        parent = dget_parent(cur);
 
-                       ret = __fscrypt_prepare_readdir(d_inode(parent));
+                       ret = ceph_fscrypt_prepare_readdir(d_inode(parent));
                        if (ret < 0) {
                                dput(parent);
                                dput(cur);