]> git.ipfire.org Git - thirdparty/util-linux.git/blob - sys-utils/zramctl.c
libmount: (tabdiff) use list_add_tail() in more robust way
[thirdparty/util-linux.git] / sys-utils / zramctl.c
1 /*
2 * zramctl - control compressed block devices in RAM
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>
26 #include <sys/types.h>
27 #include <dirent.h>
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"
39 #include "strv.h"
40 #include "path.h"
41 #include "pathnames.h"
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 */
52 struct colinfo {
53 const char *name;
54 double whint;
55 int flags;
56 const char *help;
57 };
58
59 enum {
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,
68 COL_MEMLIMIT,
69 COL_MEMUSED,
70 COL_MIGRATED,
71 COL_MOUNTPOINT
72 };
73
74 static const struct colinfo infos[] = {
75 [COL_NAME] = { "NAME", 0.25, 0, N_("zram device name") },
76 [COL_DISKSIZE] = { "DISKSIZE", 5, SCOLS_FL_RIGHT, N_("limit on the uncompressed amount of data") },
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") },
79 [COL_ALGORITHM] = { "ALGORITHM", 3, 0, N_("the selected compression algorithm") },
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") },
83 [COL_MEMLIMIT] = { "MEM-LIMIT", 5, SCOLS_FL_RIGHT, N_("memory limit used to store compressed data") },
84 [COL_MEMUSED] = { "MEM-USED", 5, SCOLS_FL_RIGHT, N_("memory zram have been consumed to store compressed data") },
85 [COL_MIGRATED] = { "MIGRATED", 5, SCOLS_FL_RIGHT, N_("number of objects migrated by compaction") },
86 [COL_MOUNTPOINT]= { "MOUNTPOINT",0.10, SCOLS_FL_TRUNC, N_("where the device is mounted") },
87 };
88
89 static int columns[ARRAY_SIZE(infos) * 2] = {-1};
90 static int ncolumns;
91
92 enum {
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
102 static 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
112 struct zram {
113 char devname[32];
114 struct path_cxt *sysfs; /* device specific sysfs directory */
115 char **mm_stat;
116
117 unsigned int mm_stat_probed : 1,
118 control_probed : 1,
119 has_control : 1; /* has /sys/class/zram-control/ */
120 };
121
122 static unsigned int raw, no_headings, inbytes;
123 static struct path_cxt *__control;
124
125 static 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
132 static const struct colinfo *get_column_info(int num)
133 {
134 return &infos[ get_column_id(num) ];
135 }
136
137 static 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
151 static 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
160 static 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);
166 else {
167 strncpy(z->devname, devname, sizeof(z->devname));
168 z->devname[sizeof(z->devname) - 1] = '\0';
169 }
170
171 DBG(fprintf(stderr, "set devname: %s", z->devname));
172 ul_unref_path(z->sysfs);
173 z->sysfs = NULL;
174 zram_reset_stat(z);
175 }
176
177 static int zram_get_devnum(struct zram *z)
178 {
179 int n;
180
181 assert(z);
182
183 if (sscanf(z->devname, "/dev/zram%d", &n) == 1)
184 return n;
185 return -EINVAL;
186 }
187
188 static struct zram *new_zram(const char *devname)
189 {
190 struct zram *z = xcalloc(1, sizeof(struct zram));
191
192 DBG(fprintf(stderr, "new: %p", z));
193 if (devname)
194 zram_set_devname(z, devname, 0);
195 return z;
196 }
197
198 static void free_zram(struct zram *z)
199 {
200 if (!z)
201 return;
202 DBG(fprintf(stderr, "free: %p", z));
203 ul_unref_path(z->sysfs);
204 zram_reset_stat(z);
205 free(z);
206 }
207
208 static struct path_cxt *zram_get_sysfs(struct zram *z)
209 {
210 assert(z);
211
212 if (!z->sysfs) {
213 dev_t devno = sysfs_devname_to_devno(z->devname);
214 if (!devno)
215 return NULL;
216 z->sysfs = ul_new_sysfs_path(devno, NULL, NULL);
217 if (!z->sysfs)
218 return NULL;
219 if (*z->devname != '/')
220 /* canonicalize the device name according to /sys */
221 sysfs_blkdev_get_path(z->sysfs, z->devname, sizeof(z->devname));
222 }
223
224 return z->sysfs;
225 }
226
227 static inline int zram_exist(struct zram *z)
228 {
229 assert(z);
230
231 errno = 0;
232 if (zram_get_sysfs(z) == NULL) {
233 errno = ENODEV;
234 return 0;
235 }
236
237 DBG(fprintf(stderr, "%s exists", z->devname));
238 return 1;
239 }
240
241 static int zram_set_u64parm(struct zram *z, const char *attr, uint64_t num)
242 {
243 struct path_cxt *sysfs = zram_get_sysfs(z);
244 if (!sysfs)
245 return -EINVAL;
246 DBG(fprintf(stderr, "%s writing %ju to %s", z->devname, num, attr));
247 return ul_path_write_u64(sysfs, num, attr);
248 }
249
250 static int zram_set_strparm(struct zram *z, const char *attr, const char *str)
251 {
252 struct path_cxt *sysfs = zram_get_sysfs(z);
253 if (!sysfs)
254 return -EINVAL;
255 DBG(fprintf(stderr, "%s writing %s to %s", z->devname, str, attr));
256 return ul_path_write_string(sysfs, str, attr);
257 }
258
259
260 static int zram_used(struct zram *z)
261 {
262 uint64_t size;
263 struct path_cxt *sysfs = zram_get_sysfs(z);
264
265 if (sysfs &&
266 ul_path_read_u64(sysfs, &size, "disksize") == 0 &&
267 size > 0) {
268
269 DBG(fprintf(stderr, "%s used", z->devname));
270 return 1;
271 }
272 DBG(fprintf(stderr, "%s unused", z->devname));
273 return 0;
274 }
275
276 static int zram_has_control(struct zram *z)
277 {
278 if (!z->control_probed) {
279 z->has_control = access(_PATH_SYS_CLASS "/zram-control/", F_OK) == 0 ? 1 : 0;
280 z->control_probed = 1;
281 DBG(fprintf(stderr, "zram-control: %s", z->has_control ? "yes" : "no"));
282 }
283
284 return z->has_control;
285 }
286
287 static struct path_cxt *zram_get_control(void)
288 {
289 if (!__control)
290 __control = ul_new_path(_PATH_SYS_CLASS "/zram-control");
291 return __control;
292 }
293
294 static int zram_control_add(struct zram *z)
295 {
296 int n;
297 struct path_cxt *ctl;
298
299 if (!zram_has_control(z) || !(ctl = zram_get_control()))
300 return -ENOSYS;
301
302 if (ul_path_read_s32(ctl, &n, "hot_add") != 0 || n < 0)
303 return n;
304
305 DBG(fprintf(stderr, "hot-add: %d", n));
306 zram_set_devname(z, NULL, n);
307 return 0;
308 }
309
310 static int zram_control_remove(struct zram *z)
311 {
312 struct path_cxt *ctl;
313 int n;
314
315 if (!zram_has_control(z) || !(ctl = zram_get_control()))
316 return -ENOSYS;
317
318 n = zram_get_devnum(z);
319 if (n < 0)
320 return n;
321
322 DBG(fprintf(stderr, "hot-remove: %d", n));
323 return ul_path_write_u64(ctl, n, "hot_remove");
324 }
325
326 static struct zram *find_free_zram(void)
327 {
328 struct zram *z = new_zram(NULL);
329 size_t i;
330 int isfree = 0;
331
332 for (i = 0; isfree == 0; i++) {
333 DBG(fprintf(stderr, "find free: checking zram%zu", i));
334 zram_set_devname(z, NULL, i);
335 if (!zram_exist(z) && zram_control_add(z) != 0)
336 break;
337 isfree = !zram_used(z);
338 }
339 if (!isfree) {
340 free_zram(z);
341 z = NULL;
342 }
343 return z;
344 }
345
346 static char *get_mm_stat(struct zram *z, size_t idx, int bytes)
347 {
348 struct path_cxt *sysfs;
349 const char *name;
350 char *str = NULL;
351 uint64_t num;
352
353 assert(idx < ARRAY_SIZE(mm_stat_names));
354 assert(z);
355
356 sysfs = zram_get_sysfs(z);
357 if (!sysfs)
358 return NULL;
359
360 /* Linux >= 4.1 uses /sys/block/zram<id>/mm_stat */
361 if (!z->mm_stat && !z->mm_stat_probed) {
362 if (ul_path_read_string(sysfs, &str, "mm_stat") > 0 && str) {
363 z->mm_stat = strv_split(str, " ");
364
365 /* make sure kernel provides mm_stat as expected */
366 if (strv_length(z->mm_stat) < ARRAY_SIZE(mm_stat_names)) {
367 strv_free(z->mm_stat);
368 z->mm_stat = NULL;
369 }
370 }
371 z->mm_stat_probed = 1;
372 free(str);
373 str = NULL;
374 }
375
376 if (z->mm_stat) {
377 if (bytes)
378 return xstrdup(z->mm_stat[idx]);
379
380 num = strtou64_or_err(z->mm_stat[idx], _("Failed to parse mm_stat"));
381 return size_to_human_string(SIZE_SUFFIX_1LETTER, num);
382 }
383
384 /* Linux < 4.1 uses /sys/block/zram<id>/<attrname> */
385 name = mm_stat_names[idx];
386 if (bytes) {
387 ul_path_read_string(sysfs, &str, name);
388 return str;
389
390 } else if (ul_path_read_u64(sysfs, &num, name) == 0)
391 return size_to_human_string(SIZE_SUFFIX_1LETTER, num);
392
393 return NULL;
394 }
395
396 static void fill_table_row(struct libscols_table *tb, struct zram *z)
397 {
398 static struct libscols_line *ln;
399 struct path_cxt *sysfs;
400 size_t i;
401 uint64_t num;
402
403 assert(tb);
404 assert(z);
405
406 DBG(fprintf(stderr, "%s: filling status table", z->devname));
407
408 sysfs = zram_get_sysfs(z);
409 if (!sysfs)
410 return;
411
412 ln = scols_table_new_line(tb, NULL);
413 if (!ln)
414 err(EXIT_FAILURE, _("failed to allocate output line"));
415
416 for (i = 0; i < (size_t) ncolumns; i++) {
417 char *str = NULL;
418
419 switch (get_column_id(i)) {
420 case COL_NAME:
421 str = xstrdup(z->devname);
422 break;
423 case COL_DISKSIZE:
424 if (inbytes)
425 ul_path_read_string(sysfs, &str, "disksize");
426
427 else if (ul_path_read_u64(sysfs, &num, "disksize") == 0)
428 str = size_to_human_string(SIZE_SUFFIX_1LETTER, num);
429 break;
430 case COL_ALGORITHM:
431 {
432 char *alg = NULL;
433
434 ul_path_read_string(sysfs, &alg, "comp_algorithm");
435 if (alg) {
436 char* lbr = strrchr(alg, '[');
437 char* rbr = strrchr(alg, ']');
438
439 if (lbr != NULL && rbr != NULL && rbr - lbr > 1)
440 str = xstrndup(lbr + 1, rbr - lbr - 1);
441 free(alg);
442 }
443 break;
444 }
445 case COL_MOUNTPOINT:
446 {
447 char path[PATH_MAX] = { '\0' };
448 int fl;
449
450 check_mount_point(z->devname, &fl, path, sizeof(path));
451 if (*path)
452 str = xstrdup(path);
453 break;
454 }
455 case COL_STREAMS:
456 ul_path_read_string(sysfs, &str, "max_comp_streams");
457 break;
458 case COL_ZEROPAGES:
459 str = get_mm_stat(z, MM_ZERO_PAGES, 1);
460 break;
461 case COL_ORIG_SIZE:
462 str = get_mm_stat(z, MM_ORIG_DATA_SIZE, inbytes);
463 break;
464 case COL_COMP_SIZE:
465 str = get_mm_stat(z, MM_COMPR_DATA_SIZE, inbytes);
466 break;
467 case COL_MEMTOTAL:
468 str = get_mm_stat(z, MM_MEM_USED_TOTAL, inbytes);
469 break;
470 case COL_MEMLIMIT:
471 str = get_mm_stat(z, MM_MEM_LIMIT, inbytes);
472 break;
473 case COL_MEMUSED:
474 str = get_mm_stat(z, MM_MEM_USED_MAX, inbytes);
475 break;
476 case COL_MIGRATED:
477 str = get_mm_stat(z, MM_NUM_MIGRATED, inbytes);
478 break;
479 }
480 if (str && scols_line_refer_data(ln, i, str))
481 err(EXIT_FAILURE, _("failed to add output data"));
482 }
483 }
484
485 static void status(struct zram *z)
486 {
487 struct libscols_table *tb;
488 size_t i;
489 DIR *dir;
490 struct dirent *d;
491
492 scols_init_debug(0);
493
494 tb = scols_new_table();
495 if (!tb)
496 err(EXIT_FAILURE, _("failed to allocate output table"));
497
498 scols_table_enable_raw(tb, raw);
499 scols_table_enable_noheadings(tb, no_headings);
500
501 for (i = 0; i < (size_t) ncolumns; i++) {
502 const struct colinfo *col = get_column_info(i);
503
504 if (!scols_table_new_column(tb, col->name, col->whint, col->flags))
505 err(EXIT_FAILURE, _("failed to initialize output column"));
506 }
507
508 if (z) {
509 /* just one device specified */
510 fill_table_row(tb, z);
511 goto print_table;
512 }
513
514 /* list all used devices */
515 z = new_zram(NULL);
516 if (!(dir = opendir(_PATH_DEV)))
517 err(EXIT_FAILURE, _("cannot open %s"), _PATH_DEV);
518
519 while ((d = readdir(dir))) {
520 int n;
521 if (sscanf(d->d_name, "zram%d", &n) != 1)
522 continue;
523 zram_set_devname(z, NULL, n);
524 if (zram_exist(z) && zram_used(z))
525 fill_table_row(tb, z);
526 }
527 closedir(dir);
528 free_zram(z);
529
530 print_table:
531 scols_print_table(tb);
532 scols_unref_table(tb);
533 }
534
535 static void __attribute__((__noreturn__)) usage(void)
536 {
537 FILE *out = stdout;
538 size_t i;
539
540 fputs(USAGE_HEADER, out);
541 fprintf(out, _( " %1$s [options] <device>\n"
542 " %1$s -r <device> [...]\n"
543 " %1$s [options] -f | <device> -s <size>\n"),
544 program_invocation_short_name);
545
546 fputs(USAGE_SEPARATOR, out);
547 fputs(_("Set up and control zram devices.\n"), out);
548
549 fputs(USAGE_OPTIONS, out);
550 fputs(_(" -a, --algorithm lzo|lz4|lz4hc|deflate|842 compression algorithm to use\n"), out);
551 fputs(_(" -b, --bytes print sizes in bytes rather than in human readable format\n"), out);
552 fputs(_(" -f, --find find a free device\n"), out);
553 fputs(_(" -n, --noheadings don't print headings\n"), out);
554 fputs(_(" -o, --output <list> columns to use for status output\n"), out);
555 fputs(_(" --output-all output all columns\n"), out);
556 fputs(_(" --raw use raw status output format\n"), out);
557 fputs(_(" -r, --reset reset all specified devices\n"), out);
558 fputs(_(" -s, --size <size> device size\n"), out);
559 fputs(_(" -t, --streams <number> number of compression streams\n"), out);
560
561 fputs(USAGE_SEPARATOR, out);
562 printf(USAGE_HELP_OPTIONS(27));
563
564 fputs(USAGE_COLUMNS, out);
565 for (i = 0; i < ARRAY_SIZE(infos); i++)
566 fprintf(out, " %11s %s\n", infos[i].name, _(infos[i].help));
567
568 printf(USAGE_MAN_TAIL("zramctl(8)"));
569 exit(EXIT_SUCCESS);
570 }
571
572 /* actions */
573 enum {
574 A_NONE = 0,
575 A_STATUS,
576 A_CREATE,
577 A_FINDONLY,
578 A_RESET
579 };
580
581 int main(int argc, char **argv)
582 {
583 uintmax_t size = 0, nstreams = 0;
584 char *algorithm = NULL;
585 int rc = 0, c, find = 0, act = A_NONE;
586 struct zram *zram = NULL;
587
588 enum {
589 OPT_RAW = CHAR_MAX + 1,
590 OPT_LIST_TYPES
591 };
592
593 static const struct option longopts[] = {
594 { "algorithm", required_argument, NULL, 'a' },
595 { "bytes", no_argument, NULL, 'b' },
596 { "find", no_argument, NULL, 'f' },
597 { "help", no_argument, NULL, 'h' },
598 { "output", required_argument, NULL, 'o' },
599 { "output-all",no_argument, NULL, OPT_LIST_TYPES },
600 { "noheadings",no_argument, NULL, 'n' },
601 { "reset", no_argument, NULL, 'r' },
602 { "raw", no_argument, NULL, OPT_RAW },
603 { "size", required_argument, NULL, 's' },
604 { "streams", required_argument, NULL, 't' },
605 { "version", no_argument, NULL, 'V' },
606 { NULL, 0, NULL, 0 }
607 };
608
609 static const ul_excl_t excl[] = {
610 { 'f', 'o', 'r' },
611 { 'o', 'r', 's' },
612 { 0 }
613 };
614 int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
615
616 setlocale(LC_ALL, "");
617 bindtextdomain(PACKAGE, LOCALEDIR);
618 textdomain(PACKAGE);
619 atexit(close_stdout);
620
621 while ((c = getopt_long(argc, argv, "a:bfho:nrs:t:V", longopts, NULL)) != -1) {
622
623 err_exclusive_options(c, longopts, excl, excl_st);
624
625 switch (c) {
626 case 'a':
627 algorithm = optarg;
628 break;
629 case 'b':
630 inbytes = 1;
631 break;
632 case 'f':
633 find = 1;
634 break;
635 case 'o':
636 ncolumns = string_to_idarray(optarg,
637 columns, ARRAY_SIZE(columns),
638 column_name_to_id);
639 if (ncolumns < 0)
640 return EXIT_FAILURE;
641 break;
642 case OPT_LIST_TYPES:
643 for (ncolumns = 0; (size_t)ncolumns < ARRAY_SIZE(infos); ncolumns++)
644 columns[ncolumns] = ncolumns;
645 break;
646 case 's':
647 size = strtosize_or_err(optarg, _("failed to parse size"));
648 act = A_CREATE;
649 break;
650 case 't':
651 nstreams = strtou64_or_err(optarg, _("failed to parse streams"));
652 break;
653 case 'r':
654 act = A_RESET;
655 break;
656 case OPT_RAW:
657 raw = 1;
658 break;
659 case 'n':
660 no_headings = 1;
661 break;
662 case 'V':
663 printf(UTIL_LINUX_VERSION);
664 return EXIT_SUCCESS;
665 case 'h':
666 usage();
667 default:
668 errtryhelp(EXIT_FAILURE);
669 }
670 }
671
672 if (find && optind < argc)
673 errx(EXIT_FAILURE, _("option --find is mutually exclusive "
674 "with <device>"));
675 if (act == A_NONE)
676 act = find ? A_FINDONLY : A_STATUS;
677
678 if (act != A_RESET && optind + 1 < argc)
679 errx(EXIT_FAILURE, _("only one <device> at a time is allowed"));
680
681 if ((act == A_STATUS || act == A_FINDONLY) && (algorithm || nstreams))
682 errx(EXIT_FAILURE, _("options --algorithm and --streams "
683 "must be combined with --size"));
684
685 ul_path_init_debug();
686 ul_sysfs_init_debug();
687
688 switch (act) {
689 case A_STATUS:
690 if (!ncolumns) { /* default columns */
691 columns[ncolumns++] = COL_NAME;
692 columns[ncolumns++] = COL_ALGORITHM;
693 columns[ncolumns++] = COL_DISKSIZE;
694 columns[ncolumns++] = COL_ORIG_SIZE;
695 columns[ncolumns++] = COL_COMP_SIZE;
696 columns[ncolumns++] = COL_MEMTOTAL;
697 columns[ncolumns++] = COL_STREAMS;
698 columns[ncolumns++] = COL_MOUNTPOINT;
699 }
700 if (optind < argc) {
701 zram = new_zram(argv[optind++]);
702 if (!zram_exist(zram))
703 err(EXIT_FAILURE, "%s", zram->devname);
704 }
705 status(zram);
706 free_zram(zram);
707 break;
708 case A_RESET:
709 if (optind == argc)
710 errx(EXIT_FAILURE, _("no device specified"));
711 while (optind < argc) {
712 zram = new_zram(argv[optind]);
713 if (!zram_exist(zram)
714 || zram_set_u64parm(zram, "reset", 1)) {
715 warn(_("%s: failed to reset"), zram->devname);
716 rc = 1;
717 }
718 zram_control_remove(zram);
719 free_zram(zram);
720 optind++;
721 }
722 break;
723 case A_FINDONLY:
724 zram = find_free_zram();
725 if (!zram)
726 errx(EXIT_FAILURE, _("no free zram device found"));
727 printf("%s\n", zram->devname);
728 free_zram(zram);
729 break;
730 case A_CREATE:
731 if (find) {
732 zram = find_free_zram();
733 if (!zram)
734 errx(EXIT_FAILURE, _("no free zram device found"));
735 } else if (optind == argc)
736 errx(EXIT_FAILURE, _("no device specified"));
737 else {
738 zram = new_zram(argv[optind]);
739 if (!zram_exist(zram))
740 err(EXIT_FAILURE, "%s", zram->devname);
741 }
742
743 if (zram_set_u64parm(zram, "reset", 1))
744 err(EXIT_FAILURE, _("%s: failed to reset"), zram->devname);
745
746 if (nstreams &&
747 zram_set_u64parm(zram, "max_comp_streams", nstreams))
748 err(EXIT_FAILURE, _("%s: failed to set number of streams"), zram->devname);
749
750 if (algorithm &&
751 zram_set_strparm(zram, "comp_algorithm", algorithm))
752 err(EXIT_FAILURE, _("%s: failed to set algorithm"), zram->devname);
753
754 if (zram_set_u64parm(zram, "disksize", size))
755 err(EXIT_FAILURE, _("%s: failed to set disksize (%ju bytes)"),
756 zram->devname, size);
757 if (find)
758 printf("%s\n", zram->devname);
759 free_zram(zram);
760 break;
761 }
762
763 ul_unref_path(__control);
764 return rc ? EXIT_FAILURE : EXIT_SUCCESS;
765 }