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