diff -wur /dev/null b/fs/ext4/critical_encode.h
--- /dev/null
+++ b/fs/ext4/critical_encode.h
-@@ -0,0 +1,74 @@
+@@ -0,0 +1,103 @@
+/*
+ * critical_encode.h
+ *
+ return (char *)q - dst;
+}
+
++static inline int ext4_setup_filename(struct inode *dir,
++ const struct qstr *iname,
++ int lookup,
++ struct qstr *qstr)
++{
++ if (lookup && unlikely(!IS_LUSTRE_MOUNT(dir->i_sb)) &&
++ EXT4_I(dir)->i_flags & EXT4_ENCRYPT_FL &&
++ strnchr(iname->name, iname->len, '=')) {
++ /* Only proceed to critical decode if
++ * iname contains escape char '='.
++ */
++ int len = iname->len;
++ char *buf;
++
++ buf = kmalloc(len, GFP_NOFS);
++ if (!buf)
++ return -ENOMEM;
++
++ len = critical_decode(iname->name, len, buf);
++ qstr->name = buf;
++ qstr->len = len;
++ } else {
++ qstr->name = iname->name;
++ qstr->len = iname->len;
++ }
++
++ return 0;
++}
++
+#endif /* _CRITICAL_ENCODE_H */
diff -wur a/fs/ext4/namei.c b/fs/ext4/namei.c
--- a/fs/ext4/namei.c
/* found a match - just to be sure, do a full check */
if (ext4_check_dir_entry(dir, NULL, de, bh, bh->b_data,
bh->b_size, offset))
-@@ -1588,8 +1589,10 @@ struct buffer_head *__ext4_find_entry
+@@ -1588,8 +1589,9 @@ struct buffer_head *__ext4_find_entry
buffer */
int num = 0;
ext4_lblk_t nblocks;
-+ char *buf = NULL;
int i, err = 0;
int namelen;
-+ struct qstr qstr;
++ struct qstr qstr = QSTR_INIT(NULL, 0);
*res_dir = NULL;
sb = dir->i_sb;
-@@ -1597,6 +1600,24 @@ struct buffer_head *__ext4_find_entry
+@@ -1597,6 +1600,11 @@ struct buffer_head *__ext4_find_entry
if (namelen > EXT4_NAME_LEN)
return NULL;
-+ if (unlikely(!IS_LUSTRE_MOUNT(dir->i_sb)) &&
-+ EXT4_I(dir)->i_flags & EXT4_ENCRYPT_FL &&
-+ strnchr(d_name->name, d_name->len, '=')) {
-+ /* Only proceed to critical decode if
-+ * iname contains escape char '='.
-+ */
-+ int len = d_name->len;
-+
-+ buf = kmalloc(len, GFP_NOFS);
-+ if (!buf)
-+ return ERR_PTR(-ENOMEM);
-+
-+ len = critical_decode(d_name->name, len, buf);
-+ qstr.name = buf;
-+ qstr.len = len;
-+ d_name = &qstr;
-+ }
++ err = ext4_setup_filename(dir, d_name, 1, &qstr);
++ if (err)
++ return ERR_PTR(err);
++ d_name = &qstr;
+
if (ext4_has_inline_data(dir)) {
int has_inline_data = 1;
for (; ra_ptr < ra_max; ra_ptr++)
brelse(bh_use[ra_ptr]);
+out_free:
-+ if (buf)
-+ kfree(buf);
++ if (qstr.name != name)
++ kfree(qstr.name);
return ret;
}
EXPORT_SYMBOL(__ext4_find_entry);