]> git.ipfire.org Git - thirdparty/util-linux.git/blame - sys-utils/zramctl.c
fstrim: ignore non-directory mountpoints
[thirdparty/util-linux.git] / sys-utils / zramctl.c
CommitLineData
0624d840 1/*
1c35e625 2 * zramctl - control compressed block devices in RAM
0624d840
KZ
3 *
4 * Copyright (c) 2014 Timofey Titovets <Nefelim4ag@gmail.com>
5 * Copyright (C) 2014 Karel Zak <kzak@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it would be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include <getopt.h>
22#include <stdlib.h>
23#include <string.h>
24#include <stdarg.h>
25#include <assert.h>
e1b1c7b0
JS
26#include <sys/types.h>
27#include <dirent.h>
0624d840
KZ
28
29#include <libsmartcols.h>
30
31#include "c.h"
32#include "nls.h"
33#include "closestream.h"
34#include "strutils.h"
35#include "xalloc.h"
36#include "sysfs.h"
37#include "optutils.h"
38#include "ismounted.h"
5388c862 39#include "strv.h"
1ceb4077 40#include "path.h"
62725810 41#include "pathnames.h"
0624d840
KZ
42
43/*#define CONFIG_ZRAM_DEBUG*/
44
45#ifdef CONFIG_ZRAM_DEBUG
46# define DBG(x) do { fputs("zram: ", stderr); x; fputc('\n', stderr); } while(0)
47#else
48# define DBG(x)
49#endif
50
51/* status output columns */
52struct colinfo {
53 const char *name;
54 double whint;
55 int flags;
56 const char *help;
57};
58
59enum {
60 COL_NAME = 0,
61 COL_DISKSIZE,
62 COL_ORIG_SIZE,
63 COL_COMP_SIZE,
64 COL_ALGORITHM,
65 COL_STREAMS,
66 COL_ZEROPAGES,
67 COL_MEMTOTAL,
bffc9174
KZ
68 COL_MEMLIMIT,
69 COL_MEMUSED,
70 COL_MIGRATED,
0624d840
KZ
71 COL_MOUNTPOINT
72};
73
74static const struct colinfo infos[] = {
75 [COL_NAME] = { "NAME", 0.25, 0, N_("zram device name") },
1c35e625 76 [COL_DISKSIZE] = { "DISKSIZE", 5, SCOLS_FL_RIGHT, N_("limit on the uncompressed amount of data") },
0624d840
KZ
77 [COL_ORIG_SIZE] = { "DATA", 5, SCOLS_FL_RIGHT, N_("uncompressed size of stored data") },
78 [COL_COMP_SIZE] = { "COMPR", 5, SCOLS_FL_RIGHT, N_("compressed size of stored data") },
1c35e625 79 [COL_ALGORITHM] = { "ALGORITHM", 3, 0, N_("the selected compression algorithm") },
0624d840
KZ
80 [COL_STREAMS] = { "STREAMS", 3, SCOLS_FL_RIGHT, N_("number of concurrent compress operations") },
81 [COL_ZEROPAGES] = { "ZERO-PAGES", 3, SCOLS_FL_RIGHT, N_("empty pages with no allocated memory") },
82 [COL_MEMTOTAL] = { "TOTAL", 5, SCOLS_FL_RIGHT, N_("all memory including allocator fragmentation and metadata overhead") },
bffc9174 83 [COL_MEMLIMIT] = { "MEM-LIMIT", 5, SCOLS_FL_RIGHT, N_("memory limit used to store compressed data") },
1ab7abac 84 [COL_MEMUSED] = { "MEM-USED", 5, SCOLS_FL_RIGHT, N_("memory zram have been consumed to store compressed data") },
75a8e726 85 [COL_MIGRATED] = { "MIGRATED", 5, SCOLS_FL_RIGHT, N_("number of objects migrated by compaction") },
0624d840 86 [COL_MOUNTPOINT]= { "MOUNTPOINT",0.10, SCOLS_FL_TRUNC, N_("where the device is mounted") },
0624d840
KZ
87};
88
89static int columns[ARRAY_SIZE(infos) * 2] = {-1};
90static int ncolumns;
91
5388c862
KZ
92enum {
93 MM_ORIG_DATA_SIZE = 0,
94 MM_COMPR_DATA_SIZE,
95 MM_MEM_USED_TOTAL,
96 MM_MEM_LIMIT,
97 MM_MEM_USED_MAX,
98 MM_ZERO_PAGES,
99 MM_NUM_MIGRATED
100};
101
102static const char *mm_stat_names[] = {
103 [MM_ORIG_DATA_SIZE] = "orig_data_size",
104 [MM_COMPR_DATA_SIZE] = "compr_data_size",
105 [MM_MEM_USED_TOTAL] = "mem_used_total",
106 [MM_MEM_LIMIT] = "mem_limit",
107 [MM_MEM_USED_MAX] = "mem_used_max",
108 [MM_ZERO_PAGES] = "zero_pages",
109 [MM_NUM_MIGRATED] = "num_migrated"
110};
111
0624d840
KZ
112struct zram {
113 char devname[32];
a6f0da16 114 struct path_cxt *sysfs; /* device specific sysfs directory */
5388c862
KZ
115 char **mm_stat;
116
62725810
KZ
117 unsigned int mm_stat_probed : 1,
118 control_probed : 1,
119 has_control : 1; /* has /sys/class/zram-control/ */
0624d840
KZ
120};
121
0624d840 122static unsigned int raw, no_headings, inbytes;
a6f0da16 123static struct path_cxt *__control;
0624d840 124
0624d840
KZ
125static int get_column_id(int num)
126{
127 assert(num < ncolumns);
128 assert(columns[num] < (int) ARRAY_SIZE(infos));
129 return columns[num];
130}
131
132static const struct colinfo *get_column_info(int num)
133{
134 return &infos[ get_column_id(num) ];
135}
136
137static int column_name_to_id(const char *name, size_t namesz)
138{
139 size_t i;
140
141 for (i = 0; i < ARRAY_SIZE(infos); i++) {
142 const char *cn = infos[i].name;
143
144 if (!strncasecmp(name, cn, namesz) && !*(cn + namesz))
145 return i;
146 }
147 warnx(_("unknown column: %s"), name);
148 return -1;
149}
150
1ceb4077
KZ
151static void zram_reset_stat(struct zram *z)
152{
153 if (z) {
154 strv_free(z->mm_stat);
155 z->mm_stat = NULL;
156 z->mm_stat_probed = 0;
157 }
158}
159
0624d840
KZ
160static void zram_set_devname(struct zram *z, const char *devname, size_t n)
161{
162 assert(z);
163
164 if (!devname)
165 snprintf(z->devname, sizeof(z->devname), "/dev/zram%zu", n);
380fe6ac
KZ
166 else
167 xstrncpy(z->devname, devname, sizeof(z->devname));
0624d840
KZ
168
169 DBG(fprintf(stderr, "set devname: %s", z->devname));
a6f0da16
KZ
170 ul_unref_path(z->sysfs);
171 z->sysfs = NULL;
1ceb4077 172 zram_reset_stat(z);
0624d840
KZ
173}
174
62725810
KZ
175static int zram_get_devnum(struct zram *z)
176{
177 int n;
178
179 assert(z);
180
181 if (sscanf(z->devname, "/dev/zram%d", &n) == 1)
182 return n;
183 return -EINVAL;
184}
185
0624d840
KZ
186static struct zram *new_zram(const char *devname)
187{
188 struct zram *z = xcalloc(1, sizeof(struct zram));
189
190 DBG(fprintf(stderr, "new: %p", z));
191 if (devname)
192 zram_set_devname(z, devname, 0);
193 return z;
194}
195
196static void free_zram(struct zram *z)
197{
198 if (!z)
199 return;
200 DBG(fprintf(stderr, "free: %p", z));
a6f0da16 201 ul_unref_path(z->sysfs);
1ceb4077 202 zram_reset_stat(z);
0624d840
KZ
203 free(z);
204}
205
a6f0da16 206static struct path_cxt *zram_get_sysfs(struct zram *z)
0624d840
KZ
207{
208 assert(z);
209
a6f0da16
KZ
210 if (!z->sysfs) {
211 dev_t devno = sysfs_devname_to_devno(z->devname);
0624d840
KZ
212 if (!devno)
213 return NULL;
a6f0da16
KZ
214 z->sysfs = ul_new_sysfs_path(devno, NULL, NULL);
215 if (!z->sysfs)
0624d840 216 return NULL;
a6f0da16 217 if (*z->devname != '/')
9e930041 218 /* canonicalize the device name according to /sys */
a6f0da16 219 sysfs_blkdev_get_path(z->sysfs, z->devname, sizeof(z->devname));
0624d840
KZ
220 }
221
a6f0da16 222 return z->sysfs;
0624d840
KZ
223}
224
225static inline int zram_exist(struct zram *z)
226{
227 assert(z);
228
116c9ce2
KZ
229 errno = 0;
230 if (zram_get_sysfs(z) == NULL) {
231 errno = ENODEV;
0624d840 232 return 0;
116c9ce2 233 }
0624d840
KZ
234
235 DBG(fprintf(stderr, "%s exists", z->devname));
236 return 1;
237}
238
239static int zram_set_u64parm(struct zram *z, const char *attr, uint64_t num)
240{
a6f0da16 241 struct path_cxt *sysfs = zram_get_sysfs(z);
0624d840
KZ
242 if (!sysfs)
243 return -EINVAL;
244 DBG(fprintf(stderr, "%s writing %ju to %s", z->devname, num, attr));
a6f0da16 245 return ul_path_write_u64(sysfs, num, attr);
0624d840
KZ
246}
247
248static int zram_set_strparm(struct zram *z, const char *attr, const char *str)
249{
a6f0da16 250 struct path_cxt *sysfs = zram_get_sysfs(z);
0624d840
KZ
251 if (!sysfs)
252 return -EINVAL;
253 DBG(fprintf(stderr, "%s writing %s to %s", z->devname, str, attr));
a6f0da16 254 return ul_path_write_string(sysfs, str, attr);
0624d840
KZ
255}
256
257
258static int zram_used(struct zram *z)
259{
260 uint64_t size;
a6f0da16 261 struct path_cxt *sysfs = zram_get_sysfs(z);
0624d840
KZ
262
263 if (sysfs &&
a6f0da16 264 ul_path_read_u64(sysfs, &size, "disksize") == 0 &&
0624d840
KZ
265 size > 0) {
266
267 DBG(fprintf(stderr, "%s used", z->devname));
268 return 1;
269 }
270 DBG(fprintf(stderr, "%s unused", z->devname));
271 return 0;
272}
273
62725810
KZ
274static int zram_has_control(struct zram *z)
275{
276 if (!z->control_probed) {
277 z->has_control = access(_PATH_SYS_CLASS "/zram-control/", F_OK) == 0 ? 1 : 0;
278 z->control_probed = 1;
279 DBG(fprintf(stderr, "zram-control: %s", z->has_control ? "yes" : "no"));
280 }
281
282 return z->has_control;
283}
284
a6f0da16
KZ
285static struct path_cxt *zram_get_control(void)
286{
287 if (!__control)
288 __control = ul_new_path(_PATH_SYS_CLASS "/zram-control");
289 return __control;
290}
291
62725810
KZ
292static int zram_control_add(struct zram *z)
293{
294 int n;
a6f0da16 295 struct path_cxt *ctl;
62725810 296
a6f0da16 297 if (!zram_has_control(z) || !(ctl = zram_get_control()))
62725810
KZ
298 return -ENOSYS;
299
a6f0da16 300 if (ul_path_read_s32(ctl, &n, "hot_add") != 0 || n < 0)
62725810
KZ
301 return n;
302
303 DBG(fprintf(stderr, "hot-add: %d", n));
304 zram_set_devname(z, NULL, n);
305 return 0;
306}
307
308static int zram_control_remove(struct zram *z)
309{
a6f0da16 310 struct path_cxt *ctl;
62725810
KZ
311 int n;
312
a6f0da16 313 if (!zram_has_control(z) || !(ctl = zram_get_control()))
62725810
KZ
314 return -ENOSYS;
315
316 n = zram_get_devnum(z);
317 if (n < 0)
318 return n;
319
320 DBG(fprintf(stderr, "hot-remove: %d", n));
a6f0da16 321 return ul_path_write_u64(ctl, n, "hot_remove");
62725810
KZ
322}
323
0624d840
KZ
324static struct zram *find_free_zram(void)
325{
326 struct zram *z = new_zram(NULL);
327 size_t i;
328 int isfree = 0;
329
330 for (i = 0; isfree == 0; i++) {
331 DBG(fprintf(stderr, "find free: checking zram%zu", i));
332 zram_set_devname(z, NULL, i);
62725810 333 if (!zram_exist(z) && zram_control_add(z) != 0)
0624d840
KZ
334 break;
335 isfree = !zram_used(z);
336 }
337 if (!isfree) {
338 free_zram(z);
339 z = NULL;
340 }
341 return z;
342}
343
624e147b 344static char *get_mm_stat(struct zram *z, size_t idx, int bytes)
5388c862 345{
a6f0da16 346 struct path_cxt *sysfs;
5388c862 347 const char *name;
a6f0da16 348 char *str = NULL;
5388c862
KZ
349 uint64_t num;
350
351 assert(idx < ARRAY_SIZE(mm_stat_names));
352 assert(z);
353
354 sysfs = zram_get_sysfs(z);
355 if (!sysfs)
356 return NULL;
357
358 /* Linux >= 4.1 uses /sys/block/zram<id>/mm_stat */
359 if (!z->mm_stat && !z->mm_stat_probed) {
a6f0da16 360 if (ul_path_read_string(sysfs, &str, "mm_stat") > 0 && str) {
5388c862 361 z->mm_stat = strv_split(str, " ");
2546d54b
KZ
362
363 /* make sure kernel provides mm_stat as expected */
364 if (strv_length(z->mm_stat) < ARRAY_SIZE(mm_stat_names)) {
365 strv_free(z->mm_stat);
366 z->mm_stat = NULL;
367 }
5388c862
KZ
368 }
369 z->mm_stat_probed = 1;
370 free(str);
a6f0da16 371 str = NULL;
5388c862
KZ
372 }
373
374 if (z->mm_stat) {
624e147b 375 if (bytes)
5388c862
KZ
376 return xstrdup(z->mm_stat[idx]);
377
378 num = strtou64_or_err(z->mm_stat[idx], _("Failed to parse mm_stat"));
379 return size_to_human_string(SIZE_SUFFIX_1LETTER, num);
380 }
381
382 /* Linux < 4.1 uses /sys/block/zram<id>/<attrname> */
383 name = mm_stat_names[idx];
a6f0da16
KZ
384 if (bytes) {
385 ul_path_read_string(sysfs, &str, name);
386 return str;
387
388 } else if (ul_path_read_u64(sysfs, &num, name) == 0)
5388c862 389 return size_to_human_string(SIZE_SUFFIX_1LETTER, num);
a6f0da16 390
5388c862
KZ
391 return NULL;
392}
393
0624d840
KZ
394static void fill_table_row(struct libscols_table *tb, struct zram *z)
395{
396 static struct libscols_line *ln;
a6f0da16 397 struct path_cxt *sysfs;
0624d840
KZ
398 size_t i;
399 uint64_t num;
400
401 assert(tb);
402 assert(z);
403
404 DBG(fprintf(stderr, "%s: filling status table", z->devname));
405
406 sysfs = zram_get_sysfs(z);
407 if (!sysfs)
408 return;
409
410 ln = scols_table_new_line(tb, NULL);
411 if (!ln)
780ce22c 412 err(EXIT_FAILURE, _("failed to allocate output line"));
0624d840
KZ
413
414 for (i = 0; i < (size_t) ncolumns; i++) {
415 char *str = NULL;
416
417 switch (get_column_id(i)) {
418 case COL_NAME:
419 str = xstrdup(z->devname);
420 break;
421 case COL_DISKSIZE:
422 if (inbytes)
a6f0da16
KZ
423 ul_path_read_string(sysfs, &str, "disksize");
424
425 else if (ul_path_read_u64(sysfs, &num, "disksize") == 0)
0624d840
KZ
426 str = size_to_human_string(SIZE_SUFFIX_1LETTER, num);
427 break;
0624d840
KZ
428 case COL_ALGORITHM:
429 {
a6f0da16 430 char *alg = NULL;
a3612b81 431
a6f0da16
KZ
432 ul_path_read_string(sysfs, &alg, "comp_algorithm");
433 if (alg) {
63bf2439
KZ
434 char* lbr = strrchr(alg, '[');
435 char* rbr = strrchr(alg, ']');
a3612b81 436
63bf2439
KZ
437 if (lbr != NULL && rbr != NULL && rbr - lbr > 1)
438 str = xstrndup(lbr + 1, rbr - lbr - 1);
a3612b81
LB
439 free(alg);
440 }
0624d840
KZ
441 break;
442 }
443 case COL_MOUNTPOINT:
444 {
445 char path[PATH_MAX] = { '\0' };
446 int fl;
447
448 check_mount_point(z->devname, &fl, path, sizeof(path));
449 if (*path)
450 str = xstrdup(path);
451 break;
452 }
453 case COL_STREAMS:
a6f0da16 454 ul_path_read_string(sysfs, &str, "max_comp_streams");
0624d840
KZ
455 break;
456 case COL_ZEROPAGES:
5388c862 457 str = get_mm_stat(z, MM_ZERO_PAGES, 1);
0624d840 458 break;
bffc9174
KZ
459 case COL_ORIG_SIZE:
460 str = get_mm_stat(z, MM_ORIG_DATA_SIZE, inbytes);
461 break;
462 case COL_COMP_SIZE:
463 str = get_mm_stat(z, MM_COMPR_DATA_SIZE, inbytes);
464 break;
0624d840 465 case COL_MEMTOTAL:
5388c862 466 str = get_mm_stat(z, MM_MEM_USED_TOTAL, inbytes);
0624d840 467 break;
bffc9174
KZ
468 case COL_MEMLIMIT:
469 str = get_mm_stat(z, MM_MEM_LIMIT, inbytes);
470 break;
471 case COL_MEMUSED:
472 str = get_mm_stat(z, MM_MEM_USED_MAX, inbytes);
473 break;
474 case COL_MIGRATED:
475 str = get_mm_stat(z, MM_NUM_MIGRATED, inbytes);
476 break;
0624d840 477 }
780ce22c 478 if (str && scols_line_refer_data(ln, i, str))
699ad3a1 479 err(EXIT_FAILURE, _("failed to add output data"));
0624d840
KZ
480 }
481}
482
483static void status(struct zram *z)
484{
485 struct libscols_table *tb;
486 size_t i;
e1b1c7b0
JS
487 DIR *dir;
488 struct dirent *d;
0624d840
KZ
489
490 scols_init_debug(0);
491
492 tb = scols_new_table();
493 if (!tb)
780ce22c 494 err(EXIT_FAILURE, _("failed to allocate output table"));
0624d840
KZ
495
496 scols_table_enable_raw(tb, raw);
497 scols_table_enable_noheadings(tb, no_headings);
498
499 for (i = 0; i < (size_t) ncolumns; i++) {
500 const struct colinfo *col = get_column_info(i);
501
502 if (!scols_table_new_column(tb, col->name, col->whint, col->flags))
503 err(EXIT_FAILURE, _("failed to initialize output column"));
504 }
505
e1b1c7b0
JS
506 if (z) {
507 /* just one device specified */
508 fill_table_row(tb, z);
509 goto print_table;
510 }
0624d840 511
e1b1c7b0
JS
512 /* list all used devices */
513 z = new_zram(NULL);
514 if (!(dir = opendir(_PATH_DEV)))
515 err(EXIT_FAILURE, _("cannot open %s"), _PATH_DEV);
516
517 while ((d = readdir(dir))) {
518 int n;
519 if (sscanf(d->d_name, "zram%d", &n) != 1)
520 continue;
521 zram_set_devname(z, NULL, n);
522 if (zram_exist(z) && zram_used(z))
523 fill_table_row(tb, z);
0624d840 524 }
e1b1c7b0
JS
525 closedir(dir);
526 free_zram(z);
0624d840 527
e1b1c7b0 528print_table:
0624d840
KZ
529 scols_print_table(tb);
530 scols_unref_table(tb);
531}
532
86be6a32 533static void __attribute__((__noreturn__)) usage(void)
0624d840 534{
86be6a32 535 FILE *out = stdout;
0624d840
KZ
536 size_t i;
537
538 fputs(USAGE_HEADER, out);
539 fprintf(out, _( " %1$s [options] <device>\n"
1c35e625 540 " %1$s -r <device> [...]\n"
0624d840
KZ
541 " %1$s [options] -f | <device> -s <size>\n"),
542 program_invocation_short_name);
543
451dbcfa
BS
544 fputs(USAGE_SEPARATOR, out);
545 fputs(_("Set up and control zram devices.\n"), out);
546
0624d840 547 fputs(USAGE_OPTIONS, out);
a3612b81 548 fputs(_(" -a, --algorithm lzo|lz4|lz4hc|deflate|842 compression algorithm to use\n"), out);
0624d840 549 fputs(_(" -b, --bytes print sizes in bytes rather than in human readable format\n"), out);
1c35e625 550 fputs(_(" -f, --find find a free device\n"), out);
0624d840
KZ
551 fputs(_(" -n, --noheadings don't print headings\n"), out);
552 fputs(_(" -o, --output <list> columns to use for status output\n"), out);
2e7ccec7 553 fputs(_(" --output-all output all columns\n"), out);
1c35e625 554 fputs(_(" --raw use raw status output format\n"), out);
0624d840
KZ
555 fputs(_(" -r, --reset reset all specified devices\n"), out);
556 fputs(_(" -s, --size <size> device size\n"), out);
423c0d75 557 fputs(_(" -t, --streams <number> number of compression streams\n"), out);
0624d840
KZ
558
559 fputs(USAGE_SEPARATOR, out);
f45f3ec3 560 printf(USAGE_HELP_OPTIONS(27));
0624d840 561
c3a4cfc5 562 fputs(USAGE_COLUMNS, out);
0624d840
KZ
563 for (i = 0; i < ARRAY_SIZE(infos); i++)
564 fprintf(out, " %11s %s\n", infos[i].name, _(infos[i].help));
565
f45f3ec3 566 printf(USAGE_MAN_TAIL("zramctl(8)"));
86be6a32 567 exit(EXIT_SUCCESS);
0624d840
KZ
568}
569
570/* actions */
571enum {
572 A_NONE = 0,
573 A_STATUS,
574 A_CREATE,
575 A_FINDONLY,
576 A_RESET
577};
578
579int main(int argc, char **argv)
580{
581 uintmax_t size = 0, nstreams = 0;
582 char *algorithm = NULL;
583 int rc = 0, c, find = 0, act = A_NONE;
584 struct zram *zram = NULL;
585
2e7ccec7
SK
586 enum {
587 OPT_RAW = CHAR_MAX + 1,
588 OPT_LIST_TYPES
589 };
0624d840
KZ
590
591 static const struct option longopts[] = {
592 { "algorithm", required_argument, NULL, 'a' },
1c35e625 593 { "bytes", no_argument, NULL, 'b' },
0624d840
KZ
594 { "find", no_argument, NULL, 'f' },
595 { "help", no_argument, NULL, 'h' },
0624d840 596 { "output", required_argument, NULL, 'o' },
2e7ccec7 597 { "output-all",no_argument, NULL, OPT_LIST_TYPES },
0624d840
KZ
598 { "noheadings",no_argument, NULL, 'n' },
599 { "reset", no_argument, NULL, 'r' },
600 { "raw", no_argument, NULL, OPT_RAW },
601 { "size", required_argument, NULL, 's' },
602 { "streams", required_argument, NULL, 't' },
603 { "version", no_argument, NULL, 'V' },
604 { NULL, 0, NULL, 0 }
605 };
606
607 static const ul_excl_t excl[] = {
608 { 'f', 'o', 'r' },
609 { 'o', 'r', 's' },
610 { 0 }
611 };
612 int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
613
614 setlocale(LC_ALL, "");
615 bindtextdomain(PACKAGE, LOCALEDIR);
616 textdomain(PACKAGE);
2c308875 617 close_stdout_atexit();
0624d840
KZ
618
619 while ((c = getopt_long(argc, argv, "a:bfho:nrs:t:V", longopts, NULL)) != -1) {
620
621 err_exclusive_options(c, longopts, excl, excl_st);
622
623 switch (c) {
624 case 'a':
0624d840
KZ
625 algorithm = optarg;
626 break;
627 case 'b':
628 inbytes = 1;
629 break;
630 case 'f':
631 find = 1;
632 break;
633 case 'o':
634 ncolumns = string_to_idarray(optarg,
635 columns, ARRAY_SIZE(columns),
636 column_name_to_id);
637 if (ncolumns < 0)
638 return EXIT_FAILURE;
639 break;
2e7ccec7
SK
640 case OPT_LIST_TYPES:
641 for (ncolumns = 0; (size_t)ncolumns < ARRAY_SIZE(infos); ncolumns++)
642 columns[ncolumns] = ncolumns;
643 break;
0624d840
KZ
644 case 's':
645 size = strtosize_or_err(optarg, _("failed to parse size"));
646 act = A_CREATE;
647 break;
648 case 't':
649 nstreams = strtou64_or_err(optarg, _("failed to parse streams"));
650 break;
651 case 'r':
652 act = A_RESET;
653 break;
654 case OPT_RAW:
655 raw = 1;
656 break;
657 case 'n':
658 no_headings = 1;
659 break;
2c308875 660
0624d840 661 case 'V':
2c308875 662 print_version(EXIT_SUCCESS);
0624d840 663 case 'h':
86be6a32 664 usage();
0624d840 665 default:
677ec86c 666 errtryhelp(EXIT_FAILURE);
0624d840
KZ
667 }
668 }
669
670 if (find && optind < argc)
671 errx(EXIT_FAILURE, _("option --find is mutually exclusive "
1c35e625 672 "with <device>"));
0624d840
KZ
673 if (act == A_NONE)
674 act = find ? A_FINDONLY : A_STATUS;
675
676 if (act != A_RESET && optind + 1 < argc)
929c7b28 677 errx(EXIT_FAILURE, _("only one <device> at a time is allowed"));
0624d840 678
1fa6c3e0
SK
679 if ((act == A_STATUS || act == A_FINDONLY) && (algorithm || nstreams))
680 errx(EXIT_FAILURE, _("options --algorithm and --streams "
681 "must be combined with --size"));
682
a6f0da16
KZ
683 ul_path_init_debug();
684 ul_sysfs_init_debug();
685
0624d840
KZ
686 switch (act) {
687 case A_STATUS:
0624d840
KZ
688 if (!ncolumns) { /* default columns */
689 columns[ncolumns++] = COL_NAME;
690 columns[ncolumns++] = COL_ALGORITHM;
691 columns[ncolumns++] = COL_DISKSIZE;
692 columns[ncolumns++] = COL_ORIG_SIZE;
693 columns[ncolumns++] = COL_COMP_SIZE;
694 columns[ncolumns++] = COL_MEMTOTAL;
695 columns[ncolumns++] = COL_STREAMS;
696 columns[ncolumns++] = COL_MOUNTPOINT;
697 }
116c9ce2 698 if (optind < argc) {
0624d840 699 zram = new_zram(argv[optind++]);
116c9ce2 700 if (!zram_exist(zram))
0a55b319 701 err(EXIT_FAILURE, "%s", zram->devname);
116c9ce2 702 }
0624d840
KZ
703 status(zram);
704 free_zram(zram);
705 break;
706 case A_RESET:
707 if (optind == argc)
708 errx(EXIT_FAILURE, _("no device specified"));
709 while (optind < argc) {
710 zram = new_zram(argv[optind]);
116c9ce2
KZ
711 if (!zram_exist(zram)
712 || zram_set_u64parm(zram, "reset", 1)) {
0624d840
KZ
713 warn(_("%s: failed to reset"), zram->devname);
714 rc = 1;
715 }
62725810 716 zram_control_remove(zram);
0624d840
KZ
717 free_zram(zram);
718 optind++;
719 }
720 break;
721 case A_FINDONLY:
722 zram = find_free_zram();
723 if (!zram)
1c35e625 724 errx(EXIT_FAILURE, _("no free zram device found"));
0624d840
KZ
725 printf("%s\n", zram->devname);
726 free_zram(zram);
727 break;
728 case A_CREATE:
729 if (find) {
730 zram = find_free_zram();
731 if (!zram)
1c35e625 732 errx(EXIT_FAILURE, _("no free zram device found"));
0624d840
KZ
733 } else if (optind == argc)
734 errx(EXIT_FAILURE, _("no device specified"));
116c9ce2 735 else {
0624d840 736 zram = new_zram(argv[optind]);
116c9ce2 737 if (!zram_exist(zram))
0a55b319 738 err(EXIT_FAILURE, "%s", zram->devname);
116c9ce2 739 }
0624d840
KZ
740
741 if (zram_set_u64parm(zram, "reset", 1))
742 err(EXIT_FAILURE, _("%s: failed to reset"), zram->devname);
743
744 if (nstreams &&
745 zram_set_u64parm(zram, "max_comp_streams", nstreams))
746 err(EXIT_FAILURE, _("%s: failed to set number of streams"), zram->devname);
747
748 if (algorithm &&
749 zram_set_strparm(zram, "comp_algorithm", algorithm))
750 err(EXIT_FAILURE, _("%s: failed to set algorithm"), zram->devname);
751
752 if (zram_set_u64parm(zram, "disksize", size))
753 err(EXIT_FAILURE, _("%s: failed to set disksize (%ju bytes)"),
754 zram->devname, size);
755 if (find)
756 printf("%s\n", zram->devname);
757 free_zram(zram);
758 break;
759 }
760
a6f0da16 761 ul_unref_path(__control);
0624d840
KZ
762 return rc ? EXIT_FAILURE : EXIT_SUCCESS;
763}