Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

jffs2: reduce stack usage in jffs2_build_xattr_subsystem()

Use kcalloc() for allocation/flush of 128 pointers table to
reduce stack usage.

Function now returns -ENOMEM or 0 on success.

stackusage
Before:
./fs/jffs2/xattr.c:775 jffs2_build_xattr_subsystem 1208
dynamic,bounded

After:
./fs/jffs2/xattr.c:775 jffs2_build_xattr_subsystem 192
dynamic,bounded

Also update definition when CONFIG_JFFS2_FS_XATTR is not enabled

Tested with an MTD mount point and some user set/getfattr.

Many current target on OpenWRT also suffer from a compilation warning
(that become an error with CONFIG_WERROR) with the following output:

fs/jffs2/xattr.c: In function 'jffs2_build_xattr_subsystem':
fs/jffs2/xattr.c:887:1: error: the frame size of 1088 bytes is larger than 1024 bytes [-Werror=frame-larger-than=]
887 | }
| ^

Using dynamic allocation fix this compilation warning.

Fixes: c9f700f840bd ("[JFFS2][XATTR] using 'delete marker' for xdatum/xref deletion")
Reported-by: Tim Gardner <tim.gardner@canonical.com>
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Ron Economos <re@w6rz.net>
Reported-by: Nathan Chancellor <nathan@kernel.org>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Signed-off-by: Fabian Frederick <fabf@skynet.be>
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Cc: stable@vger.kernel.org
Message-Id: <20230506045612.16616-1-ansuelsmth@gmail.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>

authored by

Fabian Frederick and committed by
Christian Brauner
1168f095 55650b2f

+15 -7
+4 -1
fs/jffs2/build.c
··· 211 211 ic->scan_dents = NULL; 212 212 cond_resched(); 213 213 } 214 - jffs2_build_xattr_subsystem(c); 214 + ret = jffs2_build_xattr_subsystem(c); 215 + if (ret) 216 + goto exit; 217 + 215 218 c->flags &= ~JFFS2_SB_FLAG_BUILDING; 216 219 217 220 dbg_fsbuild("FS build complete\n");
+9 -4
fs/jffs2/xattr.c
··· 772 772 } 773 773 774 774 #define XREF_TMPHASH_SIZE (128) 775 - void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) 775 + int jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) 776 776 { 777 777 struct jffs2_xattr_ref *ref, *_ref; 778 - struct jffs2_xattr_ref *xref_tmphash[XREF_TMPHASH_SIZE]; 778 + struct jffs2_xattr_ref **xref_tmphash; 779 779 struct jffs2_xattr_datum *xd, *_xd; 780 780 struct jffs2_inode_cache *ic; 781 781 struct jffs2_raw_node_ref *raw; ··· 784 784 785 785 BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING)); 786 786 787 + xref_tmphash = kcalloc(XREF_TMPHASH_SIZE, 788 + sizeof(struct jffs2_xattr_ref *), GFP_KERNEL); 789 + if (!xref_tmphash) 790 + return -ENOMEM; 791 + 787 792 /* Phase.1 : Merge same xref */ 788 - for (i=0; i < XREF_TMPHASH_SIZE; i++) 789 - xref_tmphash[i] = NULL; 790 793 for (ref=c->xref_temp; ref; ref=_ref) { 791 794 struct jffs2_xattr_ref *tmp; 792 795 ··· 887 884 "%u of xref (%u dead, %u orphan) found.\n", 888 885 xdatum_count, xdatum_unchecked_count, xdatum_orphan_count, 889 886 xref_count, xref_dead_count, xref_orphan_count); 887 + kfree(xref_tmphash); 888 + return 0; 890 889 } 891 890 892 891 struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
+2 -2
fs/jffs2/xattr.h
··· 71 71 #ifdef CONFIG_JFFS2_FS_XATTR 72 72 73 73 extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c); 74 - extern void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c); 74 + extern int jffs2_build_xattr_subsystem(struct jffs2_sb_info *c); 75 75 extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c); 76 76 77 77 extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, ··· 103 103 #else 104 104 105 105 #define jffs2_init_xattr_subsystem(c) 106 - #define jffs2_build_xattr_subsystem(c) 106 + #define jffs2_build_xattr_subsystem(c) (0) 107 107 #define jffs2_clear_xattr_subsystem(c) 108 108 109 109 #define jffs2_xattr_do_crccheck_inode(c, ic)