From e1a27d486c2374f46abd264f3fd6561815155ebd Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 28 Nov 2014 01:27:57 +0100 Subject: [PATCH] add support for zram compressed tmpfs Signed-off-by: John Crispin --- CMakeLists.txt | 7 +++- initd/early.c | 43 +++++++++---------- initd/init.h | 9 ++++ initd/zram.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 165 insertions(+), 22 deletions(-) create mode 100644 initd/zram.c diff --git a/CMakeLists.txt b/CMakeLists.txt index a8a7517..92907fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,11 @@ IF(DEBUG) ADD_DEFINITIONS(-DDEBUG -g3) ENDIF() +IF(ZRAM_TMPFS) + ADD_DEFINITIONS(-DZRAM_TMPFS) + SET(SOURCES_ZRAM initd/zram.c) +ENDIF() + add_subdirectory(upgraded) ADD_EXECUTABLE(procd ${SOURCES}) @@ -31,7 +36,7 @@ INSTALL(TARGETS procd ADD_EXECUTABLE(init initd/init.c initd/early.c initd/preinit.c initd/mkdev.c watchdog.c - utils/utils.c) + utils/utils.c ${SOURCES_ZRAM}) TARGET_LINK_LIBRARIES(init ${LIBS}) INSTALL(TARGETS init RUNTIME DESTINATION sbin diff --git a/initd/early.c b/initd/early.c index c622aec..5a83d2c 100644 --- a/initd/early.c +++ b/initd/early.c @@ -25,25 +25,6 @@ #include "init.h" static void -early_mounts(void) -{ - mount("proc", "/proc", "proc", MS_NOATIME, 0); - mount("sysfs", "/sys", "sysfs", MS_NOATIME, 0); - mount("none", "/sys/fs/cgroup", "cgroup", 0, 0); - - mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOATIME, NULL); - mkdir("/tmp/run", 0777); - mkdir("/tmp/lock", 0777); - mkdir("/tmp/state", 0777); - symlink("/tmp", "/var"); - - mount("tmpfs", "/dev", "tmpfs", MS_NOATIME, "mode=0755,size=512K"); - mkdir("/dev/shm", 0755); - mkdir("/dev/pts", 0755); - mount("devpts", "/dev/pts", "devpts", MS_NOATIME, "mode=600"); -} - -static void early_dev(void) { mkdev("*", 0600); @@ -78,6 +59,28 @@ early_console(const char *dev) } static void +early_mounts(void) +{ + mount("proc", "/proc", "proc", MS_NOATIME, 0); + mount("sysfs", "/sys", "sysfs", MS_NOATIME, 0); + mount("tmpfs", "/dev", "tmpfs", MS_NOATIME, "mode=0755,size=512K"); + mkdir("/dev/shm", 0755); + mkdir("/dev/pts", 0755); + mount("devpts", "/dev/pts", "devpts", MS_NOATIME, "mode=600"); + early_dev(); + + early_console("/dev/console"); + if (mount_zram_on_tmp()) + mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOATIME, NULL); + else + mkdev("*", 0600); + mkdir("/tmp/run", 0777); + mkdir("/tmp/lock", 0777); + mkdir("/tmp/state", 0777); + symlink("/tmp", "/var"); +} + +static void early_env(void) { setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin", 1); @@ -90,9 +93,7 @@ early(void) return; early_mounts(); - early_dev(); early_env(); - early_console("/dev/console"); LOG("Console is alive\n"); } diff --git a/initd/init.h b/initd/init.h index 1321cf8..274645b 100644 --- a/initd/init.h +++ b/initd/init.h @@ -14,10 +14,19 @@ #ifndef _INIT_H__ #define _INIT_H__ +#include + #include "../log.h" void preinit(void); void early(void); int mkdev(const char *progname, int progmode); +#ifdef ZRAM_TMPFS +int mount_zram_on_tmp(void); +#else +static inline int mount_zram_on_tmp(void) { + return -ENOSYS; +} +#endif #endif 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; +} -- 2.11.0