summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2025-06-10 11:25:22 +0200
committerMiquel Raynal <miquel.raynal@bootlin.com>2025-06-18 11:16:35 +0200
commitd22d5f47ecb2c4e140c0ee52204f4dd8fd0e85eb (patch)
tree92c727901be192af349e0b9a7327f9b9cc1cddd4
parent27b045eb3e30ce9a436b8ee5bcb4869f7e3522a6 (diff)
mtd: nftl: reduce stack usage in NFTL_movebuf()
The code in the ntfl write function is rather complex, and it contains a 512 byte on-stack buffer. The combination of these two leads to using more than the per-function stack warning limit in some configurations, especially with KASAN enabled: drivers/mtd/nftlcore.c:673:12: error: stack frame size (1328) exceeds limit (1280) in 'nftl_writeblock' [-Werror,-Wframe-larger-than] Avoid this warning by moving the on-stack buffer into a separate function that only copies one part of the device to another. This does not really help with the total maximum stack usage in the (non-KASAN) normal case, but it does two things: - no single function has more than the warning limit - the complexity goes down, so the parent function ends up spilling few local variables, and the total actually goes down slightly. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-rw-r--r--drivers/mtd/nftlcore.c43
1 files changed, 21 insertions, 22 deletions
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index 64d319e959b2..868aa3d35d09 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -228,6 +228,25 @@ static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate )
return BLOCK_NIL;
}
+static noinline_for_stack void NFTL_move_block(struct mtd_info *mtd, loff_t src, loff_t dst)
+{
+ unsigned char movebuf[512];
+ struct nftl_oob oob;
+ size_t retlen;
+ int ret;
+
+ ret = mtd_read(mtd, src, 512, &retlen, movebuf);
+ if (ret < 0 && !mtd_is_bitflip(ret)) {
+ ret = mtd_read(mtd, src, 512, &retlen, movebuf);
+ if (ret != -EIO)
+ printk("Error went away on retry.\n");
+ }
+ memset(&oob, 0xff, sizeof(struct nftl_oob));
+ oob.b.Status = oob.b.Status1 = SECTOR_USED;
+
+ nftl_write(mtd, dst, 512, &retlen, movebuf, (char *)&oob);
+}
+
static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock )
{
struct mtd_info *mtd = nftl->mbd.mtd;
@@ -389,9 +408,6 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
*/
pr_debug("Folding chain %d into unit %d\n", thisVUC, targetEUN);
for (block = 0; block < nftl->EraseSize / 512 ; block++) {
- unsigned char movebuf[512];
- int ret;
-
/* If it's in the target EUN already, or if it's pending write, do nothing */
if (BlockMap[block] == targetEUN ||
(pendingblock == (thisVUC * (nftl->EraseSize / 512) + block))) {
@@ -403,25 +419,8 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
if (BlockMap[block] == BLOCK_NIL)
continue;
- ret = mtd_read(mtd,
- (nftl->EraseSize * BlockMap[block]) + (block * 512),
- 512,
- &retlen,
- movebuf);
- if (ret < 0 && !mtd_is_bitflip(ret)) {
- ret = mtd_read(mtd,
- (nftl->EraseSize * BlockMap[block]) + (block * 512),
- 512,
- &retlen,
- movebuf);
- if (ret != -EIO)
- printk("Error went away on retry.\n");
- }
- memset(&oob, 0xff, sizeof(struct nftl_oob));
- oob.b.Status = oob.b.Status1 = SECTOR_USED;
-
- nftl_write(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) +
- (block * 512), 512, &retlen, movebuf, (char *)&oob);
+ NFTL_move_block(mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512),
+ (nftl->EraseSize * targetEUN) + (block * 512));
}
/* add the header so that it is now a valid chain */