Skip to content

Commit d913897

Browse files
Kyeongdon Kimtorvalds
authored andcommitted
zram: try vmalloc() after kmalloc()
When we're using LZ4 multi compression streams for zram swap, we found out page allocation failure message in system running test. That was not only once, but a few(2 - 5 times per test). Also, some failure cases were continually occurring to try allocation order 3. In order to make parallel compression private data, we should call kzalloc() with order 2/3 in runtime(lzo/lz4). But if there is no order 2/3 size memory to allocate in that time, page allocation fails. This patch makes to use vmalloc() as fallback of kmalloc(), this prevents page alloc failure warning. After using this, we never found warning message in running test, also It could reduce process startup latency about 60-120ms in each case. For reference a call trace : Binder_1: page allocation failure: order:3, mode:0x10c0d0 CPU: 0 PID: 424 Comm: Binder_1 Tainted: GW 3.10.49-perf-g991d02b-dirty #20 Call trace: dump_backtrace+0x0/0x270 show_stack+0x10/0x1c dump_stack+0x1c/0x28 warn_alloc_failed+0xfc/0x11c __alloc_pages_nodemask+0x724/0x7f0 __get_free_pages+0x14/0x5c kmalloc_order_trace+0x38/0xd8 zcomp_lz4_create+0x2c/0x38 zcomp_strm_alloc+0x34/0x78 zcomp_strm_multi_find+0x124/0x1ec zcomp_strm_find+0xc/0x18 zram_bvec_rw+0x2fc/0x780 zram_make_request+0x25c/0x2d4 generic_make_request+0x80/0xbc submit_bio+0xa4/0x15c __swap_writepage+0x218/0x230 swap_writepage+0x3c/0x4c shrink_page_list+0x51c/0x8d0 shrink_inactive_list+0x3f8/0x60c shrink_lruvec+0x33c/0x4cc shrink_zone+0x3c/0x100 try_to_free_pages+0x2b8/0x54c __alloc_pages_nodemask+0x514/0x7f0 __get_free_pages+0x14/0x5c proc_info_read+0x50/0xe4 vfs_read+0xa0/0x12c SyS_read+0x44/0x74 DMA: 3397*4kB (MC) 26*8kB (RC) 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 13796kB [[email protected]: change vmalloc gfp and adding comment about gfp] [[email protected]: tweak comments and styles] Signed-off-by: Kyeongdon Kim <[email protected]> Signed-off-by: Minchan Kim <[email protected]> Acked-by: Sergey Senozhatsky <[email protected]> Sergey Senozhatsky <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 3d5fe03 commit d913897

File tree

2 files changed

+42
-4
lines changed

2 files changed

+42
-4
lines changed

drivers/block/zram/zcomp_lz4.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,36 @@
1010
#include <linux/kernel.h>
1111
#include <linux/slab.h>
1212
#include <linux/lz4.h>
13+
#include <linux/vmalloc.h>
14+
#include <linux/mm.h>
1315

1416
#include "zcomp_lz4.h"
1517

1618
static void *zcomp_lz4_create(void)
1719
{
18-
return kzalloc(LZ4_MEM_COMPRESS, GFP_NOIO);
20+
void *ret;
21+
22+
/*
23+
* This function can be called in swapout/fs write path
24+
* so we can't use GFP_FS|IO. And it assumes we already
25+
* have at least one stream in zram initialization so we
26+
* don't do best effort to allocate more stream in here.
27+
* A default stream will work well without further multiple
28+
* streams. That's why we use NORETRY | NOWARN.
29+
*/
30+
ret = kzalloc(LZ4_MEM_COMPRESS, GFP_NOIO | __GFP_NORETRY |
31+
__GFP_NOWARN);
32+
if (!ret)
33+
ret = __vmalloc(LZ4_MEM_COMPRESS,
34+
GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN |
35+
__GFP_ZERO | __GFP_HIGHMEM,
36+
PAGE_KERNEL);
37+
return ret;
1938
}
2039

2140
static void zcomp_lz4_destroy(void *private)
2241
{
23-
kfree(private);
42+
kvfree(private);
2443
}
2544

2645
static int zcomp_lz4_compress(const unsigned char *src, unsigned char *dst,

drivers/block/zram/zcomp_lzo.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,36 @@
1010
#include <linux/kernel.h>
1111
#include <linux/slab.h>
1212
#include <linux/lzo.h>
13+
#include <linux/vmalloc.h>
14+
#include <linux/mm.h>
1315

1416
#include "zcomp_lzo.h"
1517

1618
static void *lzo_create(void)
1719
{
18-
return kzalloc(LZO1X_MEM_COMPRESS, GFP_NOIO);
20+
void *ret;
21+
22+
/*
23+
* This function can be called in swapout/fs write path
24+
* so we can't use GFP_FS|IO. And it assumes we already
25+
* have at least one stream in zram initialization so we
26+
* don't do best effort to allocate more stream in here.
27+
* A default stream will work well without further multiple
28+
* streams. That's why we use NORETRY | NOWARN.
29+
*/
30+
ret = kzalloc(LZO1X_MEM_COMPRESS, GFP_NOIO | __GFP_NORETRY |
31+
__GFP_NOWARN);
32+
if (!ret)
33+
ret = __vmalloc(LZO1X_MEM_COMPRESS,
34+
GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN |
35+
__GFP_ZERO | __GFP_HIGHMEM,
36+
PAGE_KERNEL);
37+
return ret;
1938
}
2039

2140
static void lzo_destroy(void *private)
2241
{
23-
kfree(private);
42+
kvfree(private);
2443
}
2544

2645
static int lzo_compress(const unsigned char *src, unsigned char *dst,

0 commit comments

Comments
 (0)