trace: use standard POSIX header for basename()
[project/procd.git] / initd / zram.c
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <errno.h>
6 #include <fcntl.h>
7
8 #include <sys/utsname.h>
9 #include <sys/mount.h>
10 #include <sys/types.h>
11 #include <sys/wait.h>
12 #include <sys/stat.h>
13
14 #include "../log.h"
15 #include "../container.h"
16
17 #include "init.h"
18
19 #define KB(x) (x * 1024)
20
21 #define ZRAM_MOD_PATH "/lib/modules/%s/zram.ko"
22 #define EXT4_MOD_PATH "/lib/modules/%s/ext4.ko"
23
24 static long
25 proc_meminfo(void)
26 {
27 FILE *fp;
28 char line[256];
29 char *key;
30 long val = KB(16);
31
32 fp = fopen("/proc/meminfo", "r");
33 if (fp == NULL) {
34 ERROR("Can't open /proc/meminfo: %m\n");
35 return errno;
36 }
37
38 while (fgets(line, sizeof(line), fp)) {
39 key = strtok(line, ":");
40 if (strcasecmp(key, "MemTotal"))
41 continue;
42 val = atol(strtok(NULL, " kB\n"));
43 break;
44 }
45 fclose(fp);
46
47 if (val > KB(32))
48 val = KB(32);
49
50 return val;
51 }
52
53 static int
54 early_insmod(char *module)
55 {
56 pid_t pid = fork();
57 char *modprobe[] = { "/sbin/modprobe", NULL, NULL };
58
59 if (!pid) {
60 char *path;
61 struct utsname ver;
62
63 uname(&ver);
64 path = alloca(strlen(module) + strlen(ver.release) + 1);
65 sprintf(path, module, ver.release);
66 modprobe[1] = path;
67 execvp(modprobe[0], modprobe);
68 ERROR("Can't exec %s: %m\n", modprobe[0]);
69 exit(EXIT_FAILURE);
70 }
71
72 if (pid <= 0) {
73 ERROR("Can't exec %s: %m\n", modprobe[0]);
74 return -1;
75 } else {
76 waitpid(pid, NULL, 0);
77 }
78
79 return 0;
80 }
81
82
83 int
84 mount_zram_on_tmp(void)
85 {
86 char *mkfs[] = { "/usr/sbin/mkfs.ext4", "-b", "4096", "-F", "-L", "TEMP", "-m", "0", "/dev/zram0", NULL };
87 FILE *fp;
88 long zramsize;
89 pid_t pid;
90 int ret;
91
92 if (early_insmod(ZRAM_MOD_PATH) || early_insmod(EXT4_MOD_PATH)) {
93 ERROR("failed to insmod zram support\n");
94 return -1;
95 }
96
97 mkdev("*", 0600);
98
99 zramsize = proc_meminfo() / 2;
100 fp = fopen("/sys/block/zram0/disksize", "r+");
101 if (fp == NULL) {
102 ERROR("Can't open /sys/block/zram0/disksize: %m\n");
103 return errno;
104 }
105 fprintf(fp, "%ld", KB(zramsize));
106 fclose(fp);
107
108 pid = fork();
109 if (!pid) {
110 execvp(mkfs[0], mkfs);
111 ERROR("Can't exec %s: %m\n", mkfs[0]);
112 exit(EXIT_FAILURE);
113 } else if (pid <= 0) {
114 ERROR("Can't exec %s: %m\n", mkfs[0]);
115 return -1;
116 } else {
117 waitpid(pid, NULL, 0);
118 }
119
120 if (!is_container()) {
121 ret = mount("/dev/zram0", "/tmp", "ext4", MS_NOSUID | MS_NODEV | MS_NOATIME, "errors=continue,noquota");
122 if (ret < 0) {
123 ERROR("Can't mount /dev/zram0 on /tmp: %m\n");
124 return errno;
125 }
126 }
127
128 LOG("Using up to %ld kB of RAM as ZRAM storage on /mnt\n", zramsize);
129
130 ret = chmod("/tmp", 01777);
131 if (ret < 0) {
132 ERROR("Can't set /tmp mode to 1777: %m\n");
133 return errno;
134 }
135
136 return 0;
137 }