Skip to content

Commit 490799c

Browse files
amotintonyhutter
authored andcommitted
Linux: Report reclaimable memory to kernel as such (openzfs#16385)
Linux provides SLAB_RECLAIM_ACCOUNT and __GFP_RECLAIMABLE flags to mark memory allocations that can be freed via shinker calls. It should allow kernel to tune and group such allocations for lower memory fragmentation and better reclamation under pressure. This patch marks as reclaimable most of ARC memory, directly evictable via ZFS shrinker, plus also dnode/znode/sa memory, indirectly evictable via kernel's superblock shrinker. Signed-off-by: Alexander Motin <[email protected]> Sponsored by: iXsystems, Inc. Reviewed-by: Tony Hutter <[email protected]> Reviewed-by: Allan Jude <[email protected]>
1 parent 847c0fc commit 490799c

File tree

14 files changed

+29
-14
lines changed

14 files changed

+29
-14
lines changed

include/os/freebsd/spl/sys/kmem.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ MALLOC_DECLARE(M_SOLARIS);
4949
#define KM_NOSLEEP M_NOWAIT
5050
#define KM_NORMALPRI 0
5151
#define KMC_NODEBUG UMA_ZONE_NODUMP
52+
#define KMC_RECLAIMABLE 0x0
5253

5354
typedef struct vmem vmem_t;
5455

include/os/linux/spl/sys/kmem_cache.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ typedef enum kmc_bit {
4545
KMC_BIT_TOTAL = 18, /* Proc handler helper bit */
4646
KMC_BIT_ALLOC = 19, /* Proc handler helper bit */
4747
KMC_BIT_MAX = 20, /* Proc handler helper bit */
48+
KMC_BIT_RECLAIMABLE = 21, /* Can be freed by shrinker */
4849
} kmc_bit_t;
4950

5051
/* kmem move callback return values */
@@ -66,9 +67,7 @@ typedef enum kmem_cbrc {
6667
#define KMC_TOTAL (1 << KMC_BIT_TOTAL)
6768
#define KMC_ALLOC (1 << KMC_BIT_ALLOC)
6869
#define KMC_MAX (1 << KMC_BIT_MAX)
69-
70-
#define KMC_REAP_CHUNK INT_MAX
71-
#define KMC_DEFAULT_SEEKS 1
70+
#define KMC_RECLAIMABLE (1 << KMC_BIT_RECLAIMABLE)
7271

7372
extern struct list_head spl_kmem_cache_list;
7473
extern struct rw_semaphore spl_kmem_cache_sem;

include/sys/zfs_context.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ void procfs_list_add(procfs_list_t *procfs_list, void *p);
414414
#define KM_NORMALPRI 0 /* not needed with UMEM_DEFAULT */
415415
#define KMC_NODEBUG UMC_NODEBUG
416416
#define KMC_KVMEM 0x0
417+
#define KMC_RECLAIMABLE 0x0
417418
#define kmem_alloc(_s, _f) umem_alloc(_s, _f)
418419
#define kmem_zalloc(_s, _f) umem_zalloc(_s, _f)
419420
#define kmem_free(_b, _s) umem_free(_b, _s)

module/os/freebsd/zfs/abd_os.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ void
300300
abd_init(void)
301301
{
302302
abd_chunk_cache = kmem_cache_create("abd_chunk", PAGE_SIZE, 0,
303-
NULL, NULL, NULL, NULL, 0, KMC_NODEBUG);
303+
NULL, NULL, NULL, NULL, 0, KMC_NODEBUG | KMC_RECLAIMABLE);
304304

305305
wmsum_init(&abd_sums.abdstat_struct_size, 0);
306306
wmsum_init(&abd_sums.abdstat_scatter_cnt, 0);

module/os/freebsd/zfs/zfs_znode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ zfs_znode_init(void)
236236
ASSERT3P(znode_cache, ==, NULL);
237237
znode_cache = kmem_cache_create("zfs_znode_cache",
238238
sizeof (znode_t), 0, zfs_znode_cache_constructor,
239-
zfs_znode_cache_destructor, NULL, NULL, NULL, 0);
239+
zfs_znode_cache_destructor, NULL, NULL, NULL, KMC_RECLAIMABLE);
240240
}
241241

242242
static znode_t *

module/os/linux/spl/spl-kmem-cache.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ kv_alloc(spl_kmem_cache_t *skc, int size, int flags)
144144
gfp_t lflags = kmem_flags_convert(flags);
145145
void *ptr;
146146

147+
if (skc->skc_flags & KMC_RECLAIMABLE)
148+
lflags |= __GFP_RECLAIMABLE;
147149
ptr = spl_vmalloc(size, lflags | __GFP_HIGHMEM);
148150

149151
/* Resulting allocated memory will be page aligned */
@@ -424,6 +426,8 @@ spl_emergency_alloc(spl_kmem_cache_t *skc, int flags, void **obj)
424426
if (!empty)
425427
return (-EEXIST);
426428

429+
if (skc->skc_flags & KMC_RECLAIMABLE)
430+
lflags |= __GFP_RECLAIMABLE;
427431
ske = kmalloc(sizeof (*ske), lflags);
428432
if (ske == NULL)
429433
return (-ENOMEM);
@@ -663,6 +667,7 @@ spl_magazine_destroy(spl_kmem_cache_t *skc)
663667
* KMC_KVMEM Force kvmem backed SPL cache
664668
* KMC_SLAB Force Linux slab backed cache
665669
* KMC_NODEBUG Disable debugging (unsupported)
670+
* KMC_RECLAIMABLE Memory can be freed under pressure
666671
*/
667672
spl_kmem_cache_t *
668673
spl_kmem_cache_create(const char *name, size_t size, size_t align,
@@ -780,6 +785,9 @@ spl_kmem_cache_create(const char *name, size_t size, size_t align,
780785
if (size > spl_kmem_cache_slab_limit)
781786
goto out;
782787

788+
if (skc->skc_flags & KMC_RECLAIMABLE)
789+
slabflags |= SLAB_RECLAIM_ACCOUNT;
790+
783791
#if defined(SLAB_USERCOPY)
784792
/*
785793
* Required for PAX-enabled kernels if the slab is to be

module/os/linux/spl/spl-zlib.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ spl_zlib_init(void)
202202
zlib_workspace_cache = kmem_cache_create(
203203
"spl_zlib_workspace_cache",
204204
size, 0, NULL, NULL, NULL, NULL, NULL,
205-
KMC_KVMEM);
205+
KMC_KVMEM | KMC_RECLAIMABLE);
206206
if (!zlib_workspace_cache)
207207
return (-ENOMEM);
208208

module/os/linux/zfs/abd_os.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ abd_alloc_chunks(abd_t *abd, size_t size)
281281
struct sg_table table;
282282
struct scatterlist *sg;
283283
struct page *page, *tmp_page = NULL;
284-
gfp_t gfp = __GFP_NOWARN | GFP_NOIO;
284+
gfp_t gfp = __GFP_RECLAIMABLE | __GFP_NOWARN | GFP_NOIO;
285285
gfp_t gfp_comp = (gfp | __GFP_NORETRY | __GFP_COMP) & ~__GFP_RECLAIM;
286286
unsigned int max_order = MIN(zfs_abd_scatter_max_order,
287287
ABD_MAX_ORDER - 1);
@@ -403,7 +403,7 @@ abd_alloc_chunks(abd_t *abd, size_t size)
403403
struct scatterlist *sg = NULL;
404404
struct sg_table table;
405405
struct page *page;
406-
gfp_t gfp = __GFP_NOWARN | GFP_NOIO;
406+
gfp_t gfp = __GFP_RECLAIMABLE | __GFP_NOWARN | GFP_NOIO;
407407
int nr_pages = abd_chunkcnt_for_bytes(size);
408408
int i = 0;
409409

@@ -762,7 +762,7 @@ abd_init(void)
762762
int i;
763763

764764
abd_cache = kmem_cache_create("abd_t", sizeof (abd_t),
765-
0, NULL, NULL, NULL, NULL, NULL, 0);
765+
0, NULL, NULL, NULL, NULL, NULL, KMC_RECLAIMABLE);
766766

767767
wmsum_init(&abd_sums.abdstat_struct_size, 0);
768768
wmsum_init(&abd_sums.abdstat_linear_cnt, 0);

module/os/linux/zfs/zfs_znode.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,8 @@ zfs_znode_init(void)
194194
ASSERT(znode_cache == NULL);
195195
znode_cache = kmem_cache_create("zfs_znode_cache",
196196
sizeof (znode_t), 0, zfs_znode_cache_constructor,
197-
zfs_znode_cache_destructor, NULL, NULL, NULL, KMC_SLAB);
197+
zfs_znode_cache_destructor, NULL, NULL, NULL,
198+
KMC_SLAB | KMC_RECLAIMABLE);
198199

199200
ASSERT(znode_hold_cache == NULL);
200201
znode_hold_cache = kmem_cache_create("zfs_znode_hold_cache",

module/zfs/arc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1258,7 +1258,7 @@ buf_init(void)
12581258
}
12591259

12601260
hdr_full_cache = kmem_cache_create("arc_buf_hdr_t_full", HDR_FULL_SIZE,
1261-
0, hdr_full_cons, hdr_full_dest, NULL, NULL, NULL, 0);
1261+
0, hdr_full_cons, hdr_full_dest, NULL, NULL, NULL, KMC_RECLAIMABLE);
12621262
hdr_l2only_cache = kmem_cache_create("arc_buf_hdr_t_l2only",
12631263
HDR_L2ONLY_SIZE, 0, hdr_l2only_cons, hdr_l2only_dest, NULL,
12641264
NULL, NULL, 0);

module/zfs/dnode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ dnode_init(void)
298298
{
299299
ASSERT(dnode_cache == NULL);
300300
dnode_cache = kmem_cache_create("dnode_t", sizeof (dnode_t),
301-
0, dnode_cons, dnode_dest, NULL, NULL, NULL, 0);
301+
0, dnode_cons, dnode_dest, NULL, NULL, NULL, KMC_RECLAIMABLE);
302302
kmem_cache_set_move(dnode_cache, dnode_move);
303303

304304
wmsum_init(&dnode_sums.dnode_hold_dbuf_hold, 0);

module/zfs/lz4_zfs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -867,7 +867,8 @@ void
867867
lz4_init(void)
868868
{
869869
lz4_cache = kmem_cache_create("lz4_cache",
870-
sizeof (struct refTables), 0, NULL, NULL, NULL, NULL, NULL, 0);
870+
sizeof (struct refTables), 0, NULL, NULL, NULL, NULL, NULL,
871+
KMC_RECLAIMABLE);
871872
}
872873

873874
void

module/zfs/sa.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ sa_cache_init(void)
235235
{
236236
sa_cache = kmem_cache_create("sa_cache",
237237
sizeof (sa_handle_t), 0, sa_cache_constructor,
238-
sa_cache_destructor, NULL, NULL, NULL, 0);
238+
sa_cache_destructor, NULL, NULL, NULL, KMC_RECLAIMABLE);
239239
}
240240

241241
void

module/zfs/zio.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ zio_init(void)
194194
cflags = (zio_exclude_metadata || size > zio_buf_debug_limit) ?
195195
KMC_NODEBUG : 0;
196196
data_cflags = KMC_NODEBUG;
197+
if (abd_size_alloc_linear(size)) {
198+
cflags |= KMC_RECLAIMABLE;
199+
data_cflags |= KMC_RECLAIMABLE;
200+
}
197201
if (cflags == data_cflags) {
198202
/*
199203
* Resulting kmem caches would be identical.

0 commit comments

Comments
 (0)