mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-02 00:00:03 +03:00
Simple stupid memory reclaim code
This commit is contained in:
parent
e9afb70d26
commit
3347339bbd
2
Makefile
2
Makefile
@ -13,7 +13,7 @@ CFLAGS+=-std=gnu89 -O2 -g -MMD -Wall \
|
||||
-DNO_BCACHEFS_FS \
|
||||
-DNO_BCACHEFS_SYSFS \
|
||||
$(EXTRA_CFLAGS)
|
||||
LDFLAGS+=-O2 -g
|
||||
LDFLAGS+=$(CFLAGS)
|
||||
|
||||
CC_VERSION=$(shell $(CC) -v 2>&1|grep -E '(gcc|clang) version')
|
||||
|
||||
|
@ -19,7 +19,9 @@ struct shrinker {
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
static inline int register_shrinker(struct shrinker *shrinker) { return 0; }
|
||||
static inline void unregister_shrinker(struct shrinker *shrinker) {}
|
||||
int register_shrinker(struct shrinker *);
|
||||
void unregister_shrinker(struct shrinker *);
|
||||
|
||||
void run_shrinkers(void);
|
||||
|
||||
#endif /* __TOOLS_LINUX_SHRINKER_H */
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/page.h>
|
||||
#include <linux/shrinker.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define ARCH_KMALLOC_MINALIGN 16
|
||||
@ -14,8 +15,11 @@
|
||||
|
||||
static inline void *kmalloc(size_t size, gfp_t flags)
|
||||
{
|
||||
void *p = malloc(size);
|
||||
void *p;
|
||||
|
||||
run_shrinkers();
|
||||
|
||||
p = malloc(size);
|
||||
if (p && (flags & __GFP_ZERO))
|
||||
memset(p, 0, size);
|
||||
|
||||
@ -24,24 +28,31 @@ static inline void *kmalloc(size_t size, gfp_t flags)
|
||||
|
||||
static inline void *krealloc(void *old, size_t size, gfp_t flags)
|
||||
{
|
||||
void *new = kmalloc(size, flags);
|
||||
void *new;
|
||||
|
||||
if (new && (flags & __GFP_ZERO))
|
||||
run_shrinkers();
|
||||
|
||||
new = malloc(size);
|
||||
if (!new)
|
||||
return NULL;
|
||||
|
||||
if (flags & __GFP_ZERO)
|
||||
memset(new, 0, size);
|
||||
|
||||
if (new) {
|
||||
memcpy(new, old,
|
||||
min(malloc_usable_size(old),
|
||||
malloc_usable_size(new)));
|
||||
free(old);
|
||||
}
|
||||
memcpy(new, old,
|
||||
min(malloc_usable_size(old),
|
||||
malloc_usable_size(new)));
|
||||
free(old);
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
#define kzalloc(size, flags) calloc(1, size)
|
||||
#define kcalloc(n, size, flags) calloc(n, size)
|
||||
#define kmalloc_array(n, size, flags) calloc(n, size)
|
||||
#define kzalloc(size, flags) kmalloc(size, flags|__GFP_ZERO)
|
||||
#define kmalloc_array(n, size, flags) \
|
||||
((size) != 0 && (n) > SIZE_MAX / (size) \
|
||||
? NULL : kmalloc(n * size, flags))
|
||||
|
||||
#define kcalloc(n, size, flags) kmalloc_array(n, size, flags|__GFP_ZERO)
|
||||
|
||||
#define kfree(p) free(p)
|
||||
#define kvfree(p) free(p)
|
||||
@ -50,8 +61,11 @@ static inline void *krealloc(void *old, size_t size, gfp_t flags)
|
||||
static inline struct page *alloc_pages(gfp_t flags, unsigned int order)
|
||||
{
|
||||
size_t size = PAGE_SIZE << order;
|
||||
void *p = memalign(PAGE_SIZE, size);
|
||||
void *p;
|
||||
|
||||
run_shrinkers();
|
||||
|
||||
p = aligned_alloc(PAGE_SIZE, size);
|
||||
if (p && (flags & __GFP_ZERO))
|
||||
memset(p, 0, size);
|
||||
|
||||
@ -91,7 +105,7 @@ static inline void vunmap(const void *addr) {}
|
||||
static inline void *vmap(struct page **pages, unsigned int count,
|
||||
unsigned long flags, unsigned prot)
|
||||
{
|
||||
return page_address(pages[0]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define is_vmalloc_addr(page) 0
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "linux/slab.h"
|
||||
#include "tools-util.h"
|
||||
|
||||
#define PAGE_KERNEL 0
|
||||
@ -13,16 +14,21 @@
|
||||
|
||||
static inline void *__vmalloc(unsigned long size, gfp_t gfp_mask, unsigned prot)
|
||||
{
|
||||
void *p = aligned_alloc(PAGE_SIZE, size);
|
||||
void *p;
|
||||
|
||||
if (p && prot == PAGE_KERNEL_EXEC) {
|
||||
if (mprotect(p, size, PROT_READ|PROT_WRITE|PROT_EXEC)) {
|
||||
vfree(p);
|
||||
p = NULL;
|
||||
}
|
||||
run_shrinkers();
|
||||
|
||||
p = aligned_alloc(PAGE_SIZE, size);
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
if (prot == PAGE_KERNEL_EXEC &&
|
||||
mprotect(p, size, PROT_READ|PROT_WRITE|PROT_EXEC)) {
|
||||
vfree(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (p && (gfp_mask & __GFP_ZERO))
|
||||
if (gfp_mask & __GFP_ZERO)
|
||||
memset(p, 0, size);
|
||||
|
||||
return p;
|
||||
|
@ -64,7 +64,7 @@ struct dev_opts {
|
||||
static inline struct dev_opts dev_opts_default()
|
||||
{
|
||||
return (struct dev_opts) {
|
||||
.data_allowed = ~0 << 2,
|
||||
.data_allowed = ~0U << 2,
|
||||
};
|
||||
}
|
||||
|
||||
|
87
linux/shrinker.c
Normal file
87
linux/shrinker.c
Normal file
@ -0,0 +1,87 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/shrinker.h>
|
||||
|
||||
#include "tools-util.h"
|
||||
|
||||
static LIST_HEAD(shrinker_list);
|
||||
static DEFINE_MUTEX(shrinker_lock);
|
||||
|
||||
int register_shrinker(struct shrinker *shrinker)
|
||||
{
|
||||
mutex_lock(&shrinker_lock);
|
||||
list_add_tail(&shrinker->list, &shrinker_list);
|
||||
mutex_unlock(&shrinker_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void unregister_shrinker(struct shrinker *shrinker)
|
||||
{
|
||||
mutex_lock(&shrinker_lock);
|
||||
list_del(&shrinker->list);
|
||||
mutex_unlock(&shrinker_lock);
|
||||
}
|
||||
|
||||
struct meminfo {
|
||||
u64 total;
|
||||
u64 available;
|
||||
|
||||
};
|
||||
|
||||
static u64 parse_meminfo_line(const char *line)
|
||||
{
|
||||
u64 v;
|
||||
|
||||
if (sscanf(line, " %llu kB", &v) < 1)
|
||||
die("sscanf error");
|
||||
return v << 10;
|
||||
}
|
||||
|
||||
static struct meminfo read_meminfo(void)
|
||||
{
|
||||
struct meminfo ret = { 0 };
|
||||
size_t len, n = 0;
|
||||
char *line = NULL;
|
||||
const char *v;
|
||||
FILE *f;
|
||||
|
||||
f = fopen("/proc/meminfo", "r");
|
||||
if (!f)
|
||||
die("error opening /proc/meminfo: %m");
|
||||
|
||||
while ((len = getline(&line, &n, f)) != -1) {
|
||||
if ((v = strcmp_prefix(line, "MemTotal:")))
|
||||
ret.total = parse_meminfo_line(v);
|
||||
|
||||
if ((v = strcmp_prefix(line, "MemAvailable:")))
|
||||
ret.available = parse_meminfo_line(v);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
free(line);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void run_shrinkers(void)
|
||||
{
|
||||
struct shrinker *shrinker;
|
||||
struct meminfo info = read_meminfo();
|
||||
s64 want_shrink = (info.total >> 2) - info.available;
|
||||
|
||||
if (want_shrink <= 0)
|
||||
return;
|
||||
|
||||
mutex_lock(&shrinker_lock);
|
||||
list_for_each_entry(shrinker, &shrinker_list, list) {
|
||||
struct shrink_control sc = {
|
||||
.nr_to_scan = want_shrink >> PAGE_SHIFT
|
||||
};
|
||||
|
||||
shrinker->scan_objects(shrinker, &sc);
|
||||
}
|
||||
mutex_unlock(&shrinker_lock);
|
||||
}
|
Loading…
Reference in New Issue
Block a user