From e1a27d486c2374f46abd264f3fd6561815155ebd Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 28 Nov 2014 01:27:57 +0100 Subject: add support for zram compressed tmpfs Signed-off-by: John Crispin --- initd/zram.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 initd/zram.c (limited to 'initd/zram.c') diff --git a/initd/zram.c b/initd/zram.c new file mode 100644 index 0000000..4dc1d2e --- /dev/null +++ b/initd/zram.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "../log.h" + +#include "init.h" + +#define KB(x) (x * 1024) + +#define ZRAM_MOD_PATH "/lib/modules/%s/zram.ko" +#define EXT4_MOD_PATH "/lib/modules/%s/ext4.ko" + +static long +proc_meminfo(void) +{ + FILE *fp; + char line[256]; + char *key; + long val = KB(16); + + fp = fopen("/proc/meminfo", "r"); + if (fp == NULL) { + ERROR("Can't open /proc/meminfo: %s\n", strerror(errno)); + return errno; + } + + while (fgets(line, sizeof(line), fp)) { + key = strtok(line, ":"); + if (strcasecmp(key, "MemTotal")) + continue; + val = atol(strtok(NULL, " kB\n")); + break; + } + fclose(fp); + + if (val > KB(32)) + val = KB(16); + + return val; +} + +static int +early_insmod(char *module) +{ + pid_t pid = fork(); + + if (!pid) { + char *modprobe[] = { "/usr/sbin/modprobe", NULL, NULL }; + char *path; + struct utsname ver; + + uname(&ver); + path = alloca(sizeof(module) + strlen(ver.release) + 1); + sprintf(path, module, ver.release); + modprobe[1] = path; + execvp(modprobe[0], modprobe); + ERROR("Can't exec /usr/sbin/modprobe\n"); + exit(-1); + } + + if (pid <= 0) { + ERROR("Can't exec /usr/sbin/modprobe\n"); + return -1; + } else { + waitpid(pid, NULL, 0); + } + + return 0; +} + + +int +mount_zram_on_tmp(void) +{ + char *mkfs[] = { "/usr/sbin/mkfs.ext4", "-b", "4096", "-F", "-L", "TEMP", "-m", "0", "/dev/zram0", NULL }; + FILE *fp; + long zramsize; + pid_t pid; + int ret; + + if (early_insmod(ZRAM_MOD_PATH) || early_insmod(EXT4_MOD_PATH)) { + ERROR("failed to insmod zram support\n"); + return -1; + } + + mkdev("*", 0600); + + zramsize = proc_meminfo() / 2; + fp = fopen("/sys/block/zram0/disksize", "r+"); + if (fp == NULL) { + ERROR("Can't open /sys/block/zram0/disksize: %s\n", strerror(errno)); + return errno; + } + fprintf(fp, "%ld", KB(zramsize)); + fclose(fp); + + pid = fork(); + if (!pid) { + execvp(mkfs[0], mkfs); + ERROR("Can't exec /sbin/mkfs.ext4\n"); + exit(-1); + } else if (pid <= 0) { + ERROR("Can't exec /sbin/mkfs.ext4\n"); + return -1; + } else { + waitpid(pid, NULL, 0); + } + + ret = mount("/dev/zram0", "/tmp", "ext4", MS_NOSUID | MS_NODEV | MS_NOATIME, "errors=continue,noquota"); + if (ret < 0) { + ERROR("Can't mount /dev/zram0 on /tmp: %s\n", strerror(errno)); + return errno; + } + + LOG("Using up to %ld kB of RAM as ZRAM storage on /mnt\n", zramsize); + + return 0; +} -- cgit v1.2.3