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

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>

authored by

Arnd Bergmann and committed by
Miquel Raynal
d22d5f47 27b045eb

+21 -22
+21 -22
drivers/mtd/nftlcore.c
··· 228 228 return BLOCK_NIL; 229 229 } 230 230 231 + static noinline_for_stack void NFTL_move_block(struct mtd_info *mtd, loff_t src, loff_t dst) 232 + { 233 + unsigned char movebuf[512]; 234 + struct nftl_oob oob; 235 + size_t retlen; 236 + int ret; 237 + 238 + ret = mtd_read(mtd, src, 512, &retlen, movebuf); 239 + if (ret < 0 && !mtd_is_bitflip(ret)) { 240 + ret = mtd_read(mtd, src, 512, &retlen, movebuf); 241 + if (ret != -EIO) 242 + printk("Error went away on retry.\n"); 243 + } 244 + memset(&oob, 0xff, sizeof(struct nftl_oob)); 245 + oob.b.Status = oob.b.Status1 = SECTOR_USED; 246 + 247 + nftl_write(mtd, dst, 512, &retlen, movebuf, (char *)&oob); 248 + } 249 + 231 250 static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock ) 232 251 { 233 252 struct mtd_info *mtd = nftl->mbd.mtd; ··· 408 389 */ 409 390 pr_debug("Folding chain %d into unit %d\n", thisVUC, targetEUN); 410 391 for (block = 0; block < nftl->EraseSize / 512 ; block++) { 411 - unsigned char movebuf[512]; 412 - int ret; 413 - 414 392 /* If it's in the target EUN already, or if it's pending write, do nothing */ 415 393 if (BlockMap[block] == targetEUN || 416 394 (pendingblock == (thisVUC * (nftl->EraseSize / 512) + block))) { ··· 419 403 if (BlockMap[block] == BLOCK_NIL) 420 404 continue; 421 405 422 - ret = mtd_read(mtd, 423 - (nftl->EraseSize * BlockMap[block]) + (block * 512), 424 - 512, 425 - &retlen, 426 - movebuf); 427 - if (ret < 0 && !mtd_is_bitflip(ret)) { 428 - ret = mtd_read(mtd, 429 - (nftl->EraseSize * BlockMap[block]) + (block * 512), 430 - 512, 431 - &retlen, 432 - movebuf); 433 - if (ret != -EIO) 434 - printk("Error went away on retry.\n"); 435 - } 436 - memset(&oob, 0xff, sizeof(struct nftl_oob)); 437 - oob.b.Status = oob.b.Status1 = SECTOR_USED; 438 - 439 - nftl_write(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 440 - (block * 512), 512, &retlen, movebuf, (char *)&oob); 406 + NFTL_move_block(mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512), 407 + (nftl->EraseSize * targetEUN) + (block * 512)); 441 408 } 442 409 443 410 /* add the header so that it is now a valid chain */