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

MTD: nandsim: use less RAM

Nandsim consumes ~2x more RAM than the density of simulated device.
It becomes critical if we need to simulate 256MB NAND and run stress tests
on it.

We investigated the reasons. nandsim allocates space for pages using kmalloc
function. The size of LP nand page is 2112 bytes.
kmalloc gets space from slab pools by chunks 2^n. So if we need to kmalloc
2112 bytes, 4096 bytes will be consumed by system.
The best way to avoid this issue would be using kmem_cache allocations. AFAIK
this mechanism specially designed to handle cases when arrays of allocations
are used.

Signed-off-by: Alexey Korolev <akorolev@infradead.org>
Tested-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Acked-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>

authored by

Alexey Korolev and committed by
David Woodhouse
8a4c2495 a9fc8991

+18 -7
+18 -7
drivers/mtd/nand/nandsim.c
··· 303 303 /* The simulated NAND flash pages array */ 304 304 union ns_mem *pages; 305 305 306 + /* Slab allocator for nand pages */ 307 + struct kmem_cache *nand_pages_slab; 308 + 306 309 /* Internal buffer of page + OOB size bytes */ 307 310 union ns_mem buf; 308 311 ··· 438 435 static u_char ns_verify_buf[NS_LARGEST_PAGE_SIZE]; 439 436 440 437 /* 441 - * Allocate array of page pointers and initialize the array to NULL 442 - * pointers. 438 + * Allocate array of page pointers, create slab allocation for an array 439 + * and initialize the array by NULL pointers. 443 440 * 444 441 * RETURNS: 0 if success, -ENOMEM if memory alloc fails. 445 442 */ ··· 487 484 for (i = 0; i < ns->geom.pgnum; i++) { 488 485 ns->pages[i].byte = NULL; 489 486 } 487 + ns->nand_pages_slab = kmem_cache_create("nandsim", 488 + ns->geom.pgszoob, 0, 0, NULL); 489 + if (!ns->nand_pages_slab) { 490 + NS_ERR("cache_create: unable to create kmem_cache\n"); 491 + return -ENOMEM; 492 + } 490 493 491 494 return 0; 492 495 ··· 520 511 if (ns->pages) { 521 512 for (i = 0; i < ns->geom.pgnum; i++) { 522 513 if (ns->pages[i].byte) 523 - kfree(ns->pages[i].byte); 514 + kmem_cache_free(ns->nand_pages_slab, 515 + ns->pages[i].byte); 524 516 } 517 + kmem_cache_destroy(ns->nand_pages_slab); 525 518 vfree(ns->pages); 526 519 } 527 520 } ··· 1486 1475 for (i = 0; i < ns->geom.pgsec; i++) { 1487 1476 if (mypage->byte != NULL) { 1488 1477 NS_DBG("erase_sector: freeing page %d\n", ns->regs.row+i); 1489 - kfree(mypage->byte); 1478 + kmem_cache_free(ns->nand_pages_slab, mypage->byte); 1490 1479 mypage->byte = NULL; 1491 1480 } 1492 1481 mypage++; ··· 1549 1538 /* 1550 1539 * We allocate memory with GFP_NOFS because a flash FS may 1551 1540 * utilize this. If it is holding an FS lock, then gets here, 1552 - * then kmalloc runs writeback which goes to the FS again 1553 - * and deadlocks. This was seen in practice. 1541 + * then kernel memory alloc runs writeback which goes to the FS 1542 + * again and deadlocks. This was seen in practice. 1554 1543 */ 1555 - mypage->byte = kmalloc(ns->geom.pgszoob, GFP_NOFS); 1544 + mypage->byte = kmem_cache_alloc(ns->nand_pages_slab, GFP_NOFS); 1556 1545 if (mypage->byte == NULL) { 1557 1546 NS_ERR("prog_page: error allocating memory for page %d\n", ns->regs.row); 1558 1547 return -1;