--- /dev/null
+From 0aba4860b0d0216a1a300484ff536171894d49d8 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Tue, 20 Dec 2022 12:38:45 +0100
+Subject: udf: Allocate name buffer in directory iterator on heap
+
+From: Jan Kara <jack@suse.cz>
+
+commit 0aba4860b0d0216a1a300484ff536171894d49d8 upstream.
+
+Currently we allocate name buffer in directory iterators (struct
+udf_fileident_iter) on stack. These structures are relatively large
+(some 360 bytes on 64-bit architectures). For udf_rename() which needs
+to keep three of these structures in parallel the stack usage becomes
+rather heavy - 1536 bytes in total. Allocate the name buffer in the
+iterator from heap to avoid excessive stack usage.
+
+Link: https://lore.kernel.org/all/202212200558.lK9x1KW0-lkp@intel.com
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/udf/directory.c | 25 ++++++++++++++++---------
+ fs/udf/udfdecl.h | 2 +-
+ 2 files changed, 17 insertions(+), 10 deletions(-)
+
+--- a/fs/udf/directory.c
++++ b/fs/udf/directory.c
+@@ -248,9 +248,14 @@ int udf_fiiter_init(struct udf_fileident
+ iter->elen = 0;
+ iter->epos.bh = NULL;
+ iter->name = NULL;
+-
+- if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
+- return udf_copy_fi(iter);
++ iter->namebuf = kmalloc(UDF_NAME_LEN_CS0, GFP_KERNEL);
++ if (!iter->namebuf)
++ return -ENOMEM;
++
++ if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
++ err = udf_copy_fi(iter);
++ goto out;
++ }
+
+ if (inode_bmap(dir, iter->pos >> dir->i_blkbits, &iter->epos,
+ &iter->eloc, &iter->elen, &iter->loffset) !=
+@@ -260,17 +265,17 @@ int udf_fiiter_init(struct udf_fileident
+ udf_err(dir->i_sb,
+ "position %llu not allocated in directory (ino %lu)\n",
+ (unsigned long long)pos, dir->i_ino);
+- return -EFSCORRUPTED;
++ err = -EFSCORRUPTED;
++ goto out;
+ }
+ err = udf_fiiter_load_bhs(iter);
+ if (err < 0)
+- return err;
++ goto out;
+ err = udf_copy_fi(iter);
+- if (err < 0) {
++out:
++ if (err < 0)
+ udf_fiiter_release(iter);
+- return err;
+- }
+- return 0;
++ return err;
+ }
+
+ int udf_fiiter_advance(struct udf_fileident_iter *iter)
+@@ -307,6 +312,8 @@ void udf_fiiter_release(struct udf_filei
+ brelse(iter->bh[0]);
+ brelse(iter->bh[1]);
+ iter->bh[0] = iter->bh[1] = NULL;
++ kfree(iter->namebuf);
++ iter->namebuf = NULL;
+ }
+
+ static void udf_copy_to_bufs(void *buf1, int len1, void *buf2, int len2,
+--- a/fs/udf/udfdecl.h
++++ b/fs/udf/udfdecl.h
+@@ -99,7 +99,7 @@ struct udf_fileident_iter {
+ struct extent_position epos; /* Position after the above extent */
+ struct fileIdentDesc fi; /* Copied directory entry */
+ uint8_t *name; /* Pointer to entry name */
+- uint8_t namebuf[UDF_NAME_LEN_CS0]; /* Storage for entry name in case
++ uint8_t *namebuf; /* Storage for entry name in case
+ * the name is split between two blocks
+ */
+ };