Line data Source code
1 : #include "clusterautoconfig.h"
2 :
3 : #include <stdio.h>
4 : #include <stdlib.h>
5 : #include <string.h>
6 : #include <stdint.h>
7 : #include <inttypes.h>
8 : #include <sys/types.h>
9 : #include <sys/stat.h>
10 : #include <fcntl.h>
11 : #include <unistd.h>
12 : #include <time.h>
13 : #include <errno.h>
14 : #include <stdarg.h>
15 : #include <mntent.h>
16 : #include <ctype.h>
17 : #include <poll.h>
18 : #include <signal.h>
19 : #include <sys/time.h>
20 : #include <libintl.h>
21 : #include <sys/ioctl.h>
22 : #include <limits.h>
23 : #include <blkid.h>
24 : #include <locale.h>
25 : #include <uuid.h>
26 :
27 : #define _(String) gettext(String)
28 :
29 : #include "libgfs2.h"
30 : #include "gfs2_mkfs.h"
31 : #include "progress.h"
32 : #include "struct_print.h"
33 :
34 0 : static void print_usage(const char *prog_name)
35 : {
36 : int i;
37 : const char *option, *param, *desc;
38 0 : const char *options[] = {
39 : /* Translators: This is a usage string printed with --help.
40 : <size> and <number> here are the commandline parameters,
41 : e.g. mkfs.gfs2 -b <size> -j <number> /dev/sda */
42 0 : "-b", _("<size>"), _("File system block size, in bytes"),
43 0 : "-c", _("<size>"), _("Size of quota change file, in megabytes"),
44 0 : "-D", NULL, _("Enable debugging code"),
45 0 : "-h", NULL, _("Display this help, then exit"),
46 0 : "-J", _("<size>"), _("Size of journals, in megabytes"),
47 0 : "-j", _("<number>"), _("Number of journals"),
48 0 : "-K", NULL, _("Don't try to discard unused blocks"),
49 0 : "-O", NULL, _("Don't ask for confirmation"),
50 0 : "-o", _("<key>[=<value>][,...]"), _("Specify extended options. See '-o help'."),
51 0 : "-p", _("<name>"), _("Name of the locking protocol"),
52 0 : "-q", NULL, _("Don't print anything"),
53 0 : "-r", _("<size>"), _("Size of resource groups, in megabytes"),
54 0 : "-t", _("<name>"), _("Name of the lock table"),
55 0 : "-U", _("<UUID>"), _("The UUID of the file system"),
56 0 : "-V", NULL, _("Display program version information, then exit"),
57 : NULL, NULL, NULL /* Must be kept at the end */
58 : };
59 :
60 0 : printf("%s\n", _("Usage:"));
61 0 : printf("%s [%s] <%s> [%s]\n\n", prog_name, _("options"), _("device"), _("size"));
62 0 : printf(_("Create a gfs2 file system on a device. If a size, in blocks, is not "
63 : "specified, the whole device will be used."));
64 0 : printf("\n\n%s\n", _("Options:"));
65 :
66 0 : for (i = 0; options[i] != NULL; i += 3) {
67 0 : option = options[i];
68 0 : param = options[i + 1];
69 0 : desc = options[i + 2];
70 0 : printf("%3s %-22s %s\n", option, param ? param : "", desc);
71 : }
72 0 : }
73 :
74 0 : static void print_ext_opts(void)
75 : {
76 : int i;
77 0 : const char *options[] = {
78 0 : "help", _("Display this help, then exit"),
79 0 : "swidth=N", _("Specify the stripe width of the device, overriding probed values"),
80 0 : "sunit=N", _("Specify the stripe unit of the device, overriding probed values"),
81 0 : "align=[0|1]", _("Disable or enable alignment of resource groups"),
82 0 : "format=N", _("Specify the format version number"),
83 : NULL, NULL
84 : };
85 0 : printf(_("Extended options:\n"));
86 0 : for (i = 0; options[i] != NULL; i += 2) {
87 0 : printf("%15s %-22s\n", options[i], options[i + 1]);
88 : }
89 0 : }
90 :
91 : /**
92 : * Values probed by libblkid:
93 : * alignment_offset: offset, in bytes, of the start of the dev from its natural alignment
94 : * logical_sector_size: smallest addressable unit
95 : * minimum_io_size: device's preferred unit of I/O. RAID stripe unit.
96 : * optimal_io_size: biggest I/O we can submit without incurring a penalty. RAID stripe width.
97 : * physical_sector_size: the smallest unit we can write atomically
98 : */
99 : struct mkfs_dev {
100 : int fd;
101 : const char *path;
102 : struct stat stat;
103 : uint64_t size;
104 : unsigned long alignment_offset;
105 : unsigned long logical_sector_size;
106 : unsigned long minimum_io_size;
107 : unsigned long optimal_io_size;
108 : unsigned long physical_sector_size;
109 :
110 : unsigned int got_topol:1;
111 : };
112 :
113 : /* Number of resource groups */
114 : static uint64_t nrgrp = 0;
115 :
116 : struct mkfs_opts {
117 : unsigned bsize;
118 : unsigned qcsize;
119 : unsigned jsize;
120 : unsigned rgsize;
121 : unsigned long sunit;
122 : unsigned long swidth;
123 : unsigned format;
124 : uint64_t fssize;
125 : int journals;
126 : const char *lockproto;
127 : const char *locktable;
128 : const char *uuid;
129 : struct mkfs_dev dev;
130 : unsigned discard:1;
131 : unsigned root_inherit_jd:1;
132 :
133 : unsigned got_bsize:1;
134 : unsigned got_qcsize:1;
135 : unsigned got_jsize:1;
136 : unsigned got_rgsize:1;
137 : unsigned got_sunit:1;
138 : unsigned got_swidth:1;
139 : unsigned got_fssize:1;
140 : unsigned got_journals:1;
141 : unsigned got_lockproto:1;
142 : unsigned got_locktable:1;
143 : unsigned got_device:1;
144 : unsigned got_topol:1;
145 : unsigned got_format:1;
146 : unsigned got_uuid:1;
147 :
148 : unsigned override:1;
149 : unsigned quiet:1;
150 : unsigned debug:1;
151 : unsigned confirm:1;
152 : unsigned align;
153 : };
154 :
155 97 : static void opts_init(struct mkfs_opts *opts)
156 : {
157 97 : memset(opts, 0, sizeof(*opts));
158 97 : opts->discard = 1;
159 97 : opts->journals = 1;
160 97 : opts->bsize = LGFS2_DEFAULT_BSIZE;
161 97 : opts->jsize = LGFS2_DEFAULT_JSIZE;
162 97 : opts->qcsize = LGFS2_DEFAULT_QCSIZE;
163 97 : opts->rgsize = LGFS2_DEFAULT_RGSIZE;
164 97 : opts->lockproto = "lock_dlm";
165 97 : opts->locktable = "";
166 97 : opts->confirm = 1;
167 97 : opts->align = 1;
168 97 : opts->format = GFS2_FORMAT_FS;
169 97 : }
170 :
171 : static struct lgfs2_inum *mkfs_journals = NULL;
172 :
173 : #ifndef BLKDISCARD
174 : #define BLKDISCARD _IO(0x12,119)
175 : #endif
176 :
177 0 : static int discard_blocks(int fd, uint64_t len, int debug)
178 : {
179 : uint64_t range[2];
180 :
181 0 : range[0] = 0;
182 0 : range[1] = len;
183 0 : if (debug)
184 : /* Translators: "discard" is a request sent to a storage device to
185 : * discard a range of blocks. */
186 0 : printf(_("Issuing discard request: range: %"PRIu64" - %"PRIu64"..."),
187 : range[0], range[1]);
188 0 : if (ioctl(fd, BLKDISCARD, &range) < 0) {
189 0 : if (debug)
190 0 : printf("%s = %d\n", _("error"), errno);
191 0 : return errno;
192 : }
193 0 : if (debug)
194 0 : printf(_("Successful.\n"));
195 0 : return 0;
196 : }
197 :
198 : /**
199 : * Convert a human-readable size string to a long long.
200 : * Copied and adapted from xfs_mkfs.c.
201 : */
202 58 : static long long cvtnum(unsigned int blocksize, unsigned int sectorsize, const char *s)
203 : {
204 : long long i;
205 : char *sp;
206 :
207 58 : i = strtoll(s, &sp, 0);
208 58 : if (i == 0 && sp == s)
209 1 : return -1LL;
210 57 : if (*sp == '\0')
211 57 : return i;
212 :
213 0 : *sp = tolower(*sp);
214 0 : if (*sp == 'b' && sp[1] == '\0') {
215 0 : if (blocksize)
216 0 : return i * blocksize;
217 0 : fprintf(stderr, _("Block size not available yet.\n"));
218 0 : return -1LL;
219 : }
220 0 : if (*sp == 's' && sp[1] == '\0') {
221 0 : if (sectorsize)
222 0 : return i * sectorsize;
223 0 : return i * GFS2_BASIC_BLOCK;
224 : }
225 0 : if (*sp == 'k' && sp[1] == '\0')
226 0 : return 1024LL * i;
227 0 : if (*sp == 'm' && sp[1] == '\0')
228 0 : return 1024LL * 1024LL * i;
229 0 : if (*sp == 'g' && sp[1] == '\0')
230 0 : return 1024LL * 1024LL * 1024LL * i;
231 0 : if (*sp == 't' && sp[1] == '\0')
232 0 : return 1024LL * 1024LL * 1024LL * 1024LL * i;
233 0 : if (*sp == 'p' && sp[1] == '\0')
234 0 : return 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * i;
235 0 : if (*sp == 'e' && sp[1] == '\0')
236 0 : return 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * i;
237 0 : return -1LL;
238 : }
239 :
240 59 : static int parse_ulong(struct mkfs_opts *opts, const char *key, const char *val, unsigned long *pn,
241 : unsigned long max)
242 : {
243 : long long l;
244 59 : if (val == NULL || *val == '\0') {
245 1 : fprintf(stderr, _("Missing argument to '%s'\n"), key);
246 1 : return -1;
247 : }
248 58 : l = cvtnum(opts->bsize, 0, val);
249 58 : if ((max > 0 && l > max) || l < 0) {
250 4 : fprintf(stderr, _("Value of '%s' is invalid\n"), key);
251 4 : return -1;
252 : }
253 54 : *pn = (unsigned long)l;
254 54 : return 0;
255 : }
256 :
257 1 : static int parse_bool(struct mkfs_opts *opts, const char *key, const char *val, unsigned *pbool)
258 : {
259 1 : if (strnlen(val, 2) == 1) {
260 1 : if (*val == '0') {
261 1 : *pbool = 0;
262 1 : return 0;
263 : }
264 0 : if (*val == '1') {
265 0 : *pbool = 1;
266 0 : return 0;
267 : }
268 : }
269 0 : fprintf(stderr, _("Option '%s' must be either 1 or 0\n"), key);
270 0 : return -1;
271 : }
272 :
273 9 : static int parse_topology(struct mkfs_opts *opts, char *str)
274 : {
275 : char *opt;
276 9 : unsigned i = 0;
277 9 : unsigned long *topol[5] = {
278 9 : &opts->dev.alignment_offset,
279 9 : &opts->dev.logical_sector_size,
280 9 : &opts->dev.minimum_io_size,
281 9 : &opts->dev.optimal_io_size,
282 9 : &opts->dev.physical_sector_size
283 : };
284 :
285 54 : while ((opt = strsep(&str, ":")) != NULL) {
286 45 : if (i > 4) {
287 0 : fprintf(stderr, "Too many topology values.\n");
288 0 : return 1;
289 : }
290 45 : if (parse_ulong(opts, "test_topology", opt, topol[i], 0))
291 0 : return 1;
292 45 : i++;
293 : }
294 9 : if (i < 5) {
295 0 : fprintf(stderr, "Too few topology values.\n");
296 0 : return 1;
297 : }
298 9 : return 0;
299 : }
300 :
301 9 : static int parse_format(struct mkfs_opts *opts, char *str)
302 : {
303 : unsigned long ln;
304 :
305 9 : if (parse_ulong(opts, "format", str, &ln, LGFS2_FS_FORMAT_MAX) != 0)
306 2 : return -1;
307 :
308 7 : if (ln < LGFS2_FS_FORMAT_MIN) {
309 2 : fprintf(stderr, _("Invalid filesystem format: %s\n"), str);
310 2 : return -1;
311 : }
312 5 : opts->format = ln;
313 5 : opts->got_format = 1;
314 5 : return 0;
315 : }
316 :
317 6 : static int parse_root_inherit_jd(struct mkfs_opts *opts, const char *str)
318 : {
319 6 : unsigned long n = 0;
320 :
321 6 : if (str == NULL) { /* -o root_inherit_jdata */
322 1 : opts->root_inherit_jd = 1;
323 1 : return 0;
324 : }
325 : /* -o root_inherit_jdata=N */
326 5 : if (parse_ulong(opts, "root_inherit_jdata", str, &n, 1) != 0)
327 3 : return -1;
328 2 : opts->root_inherit_jd = (unsigned)n;
329 2 : return 0;
330 : }
331 :
332 25 : static int opt_parse_extended(char *str, struct mkfs_opts *opts)
333 : {
334 : char *opt;
335 43 : while ((opt = strsep(&str, ",")) != NULL) {
336 25 : char *key = strsep(&opt, "=");
337 25 : char *val = strsep(&opt, "=");
338 25 : if (key == NULL || *key == '\0') {
339 0 : fprintf(stderr, _("Missing argument to '-o' option\n"));
340 0 : return -1;
341 : }
342 25 : if (strcmp("sunit", key) == 0) {
343 0 : if (parse_ulong(opts, "sunit", val, &opts->sunit, 0) != 0)
344 0 : return -1;
345 0 : opts->got_sunit = 1;
346 25 : } else if (strcmp("swidth", key) == 0) {
347 0 : if (parse_ulong(opts, "swidth", val, &opts->swidth, 0) != 0)
348 0 : return -1;
349 0 : opts->got_swidth = 1;
350 25 : } else if (strcmp("align", key) == 0) {
351 1 : if (parse_bool(opts, "align", val, &opts->align) != 0)
352 0 : return -1;
353 24 : } else if (strcmp("test_topology", key) == 0) {
354 9 : if (parse_topology(opts, val) != 0)
355 0 : return -1;
356 17 : opts->got_topol = (opts->dev.logical_sector_size != 0 &&
357 8 : opts->dev.physical_sector_size != 0);
358 15 : } else if (strcmp("format", key) == 0) {
359 9 : if (parse_format(opts, val) != 0)
360 4 : return -1;
361 6 : } else if (strcmp("root_inherit_jdata", key) == 0) {
362 6 : if (parse_root_inherit_jd(opts, val) != 0)
363 3 : return -1;
364 0 : } else if (strcmp("help", key) == 0) {
365 0 : print_ext_opts();
366 0 : return 1;
367 : } else {
368 0 : fprintf(stderr, _("Invalid extended option (specified with -o): '%s'\n"), key);
369 0 : print_ext_opts();
370 0 : return -1;
371 : }
372 : }
373 18 : return 0;
374 : }
375 :
376 97 : static int opts_get(int argc, char *argv[], struct mkfs_opts *opts)
377 : {
378 : int ret;
379 : int c;
380 : while (1) {
381 541 : c = getopt(argc, argv, "-b:c:DhJ:j:KOo:p:qr:t:U:V");
382 541 : if (c == -1)
383 88 : break;
384 :
385 453 : switch (c) {
386 13 : case 'b':
387 13 : opts->bsize = atoi(optarg);
388 13 : opts->got_bsize = 1;
389 13 : break;
390 4 : case 'c':
391 4 : opts->qcsize = atoi(optarg);
392 4 : opts->got_qcsize = 1;
393 4 : break;
394 81 : case 'D':
395 81 : opts->debug = 1;
396 81 : break;
397 0 : case 'h':
398 0 : print_usage(argv[0]);
399 0 : return 1;
400 6 : case 'J':
401 6 : opts->jsize = atoi(optarg);
402 6 : opts->got_jsize = 1;
403 6 : break;
404 3 : case 'j':
405 3 : opts->journals = atoi(optarg);
406 3 : opts->got_journals = 1;
407 3 : break;
408 0 : case 'K':
409 0 : opts->discard = 0;
410 0 : break;
411 96 : case 'O':
412 96 : opts->override = 1;
413 96 : break;
414 96 : case 'p':
415 96 : opts->lockproto = optarg;
416 96 : opts->got_lockproto = 1;
417 96 : break;
418 10 : case 't':
419 10 : opts->locktable = optarg;
420 10 : opts->got_locktable = 1;
421 10 : break;
422 0 : case 'q':
423 0 : opts->quiet = 1;
424 0 : break;
425 17 : case 'r':
426 17 : opts->rgsize = atoi(optarg);
427 17 : opts->got_rgsize = 1;
428 17 : break;
429 25 : case 'o':
430 25 : ret = opt_parse_extended(optarg, opts);
431 25 : if (ret != 0)
432 7 : return ret;
433 18 : break;
434 4 : case 'U':
435 4 : opts->uuid = optarg;
436 4 : opts->got_uuid = 1;
437 4 : break;
438 0 : case 'V':
439 0 : printf("mkfs.gfs2 %s (built %s %s)\n", VERSION,
440 : __DATE__, __TIME__);
441 0 : printf(REDHAT_COPYRIGHT "\n");
442 0 : return 1;
443 : break;
444 2 : case ':':
445 : case '?':
446 2 : fprintf(stderr, _("Please use '-h' for help.\n"));
447 2 : return -1;
448 : break;
449 96 : case 1:
450 96 : if (strcmp(optarg, "gfs2") == 0)
451 0 : continue;
452 96 : if (!opts->got_device) {
453 89 : opts->dev.path = optarg;
454 89 : opts->got_device = 1;
455 7 : } else if (!opts->got_fssize && isdigit(optarg[0])) {
456 7 : opts->fssize = atol(optarg);
457 7 : opts->got_fssize = 1;
458 : } else {
459 0 : fprintf(stderr, _("More than one device specified (try -h for help)\n"));
460 0 : return -1;
461 : }
462 96 : break;
463 0 : default:
464 0 : fprintf(stderr, _("Invalid option: %c\n"), c);
465 0 : return -1;
466 : };
467 : }
468 88 : return 0;
469 : }
470 :
471 : /**
472 : * Make sure the GFS2 is set up to use the right lock protocol
473 : * @lockproto: the lock protocol to mount
474 : * @locktable: the locktable name
475 : *
476 : */
477 :
478 88 : static int test_locking(struct mkfs_opts *opts)
479 : {
480 : const char *c;
481 : /* Translators: A lock table is a string identifying a gfs2 file system
482 : * in a cluster, e.g. cluster_name:fs_name */
483 88 : const char *errprefix = _("Invalid lock table:");
484 176 : int table_required = (strcmp(opts->lockproto, "lock_gulm") == 0)
485 88 : || (strcmp(opts->lockproto, "lock_dlm") == 0);
486 :
487 88 : if ((strcmp(opts->lockproto, "lock_nolock") != 0) && !table_required) {
488 1 : fprintf(stderr, _("Invalid lock protocol: %s\n"), opts->lockproto);
489 1 : return -1;
490 : }
491 : /* When lock_*lm is given as the lock protocol, require a lock table too */
492 87 : if (!opts->got_locktable) {
493 77 : if (table_required) {
494 0 : fprintf(stderr, _("No lock table specified.\n"));
495 0 : return -1;
496 : }
497 77 : return 0;
498 : }
499 : /* User gave a lock table option, validate it */
500 10 : if (*opts->locktable == '\0') {
501 2 : fprintf(stderr, _("Lock table is empty.\n"));
502 2 : return -1;
503 : }
504 337 : for (c = opts->locktable; *c; c++) {
505 329 : if (!isalnum(*c) && (*c != '-') && (*c != '_') && (*c != ':')) {
506 0 : fprintf(stderr, "%s %s '%c'\n", errprefix, _("invalid character"), *c);
507 0 : return -1;
508 : }
509 : }
510 8 : c = strstr(opts->locktable, ":");
511 8 : if (!c) {
512 0 : fprintf(stderr, "%s %s\n", errprefix, _("missing colon"));
513 0 : return -1;
514 : }
515 :
516 8 : if (c == opts->locktable) {
517 0 : fprintf(stderr, "%s %s\n", errprefix, _("cluster name is missing"));
518 0 : return -1;
519 : }
520 8 : if (c - opts->locktable > 32) {
521 2 : fprintf(stderr, "%s %s\n", errprefix, _("cluster name is too long"));
522 2 : return -1;
523 : }
524 :
525 6 : c++;
526 6 : if (strstr(c, ":")) {
527 0 : fprintf(stderr, "%s %s\n", errprefix, _("contains more than one colon"));
528 0 : return -1;
529 : }
530 6 : if (!strlen(c)) {
531 0 : fprintf(stderr, "%s %s\n", errprefix, _("file system name is missing"));
532 0 : return -1;
533 : }
534 6 : if (strlen(c) > 30) {
535 2 : fprintf(stderr, "%s %s\n", errprefix, _("file system name is too long"));
536 2 : return -1;
537 : }
538 4 : return 0;
539 : }
540 :
541 0 : static int are_you_sure(void)
542 : {
543 0 : while (1) {
544 0 : char *line = NULL;
545 0 : size_t len = 0;
546 : int ret;
547 : int res;
548 :
549 : /* Translators: We use rpmatch(3) to match the answers to y/n
550 : questions in the user's own language, so the [y/n] here must also be
551 : translated to match one of the letters in the pattern printed by
552 : `locale -k yesexpr` and one of the letters in the pattern printed by
553 : `locale -k noexpr` */
554 0 : printf( _("Are you sure you want to proceed? [y/n] "));
555 0 : ret = getline(&line, &len, stdin);
556 0 : if (ret < 0) {
557 0 : printf("\n");
558 0 : free(line);
559 0 : return 0;
560 : }
561 0 : res = rpmatch(line);
562 0 : free(line);
563 0 : if (ret == 0)
564 0 : continue;
565 0 : if (res == 1) /* Yes */
566 0 : return 1;
567 0 : if (res == 0) /* No */
568 0 : return 0;
569 : /* Unrecognized input; go again. */
570 : }
571 : }
572 :
573 75 : static int choose_blocksize(struct mkfs_opts *opts, unsigned *pbsize)
574 : {
575 : unsigned int x;
576 75 : unsigned int bsize = opts->bsize;
577 75 : struct mkfs_dev *dev = &opts->dev;
578 75 : int got_topol = (dev->got_topol || opts->got_topol);
579 :
580 75 : if (got_topol && opts->debug) {
581 8 : printf("alignment_offset: %lu\n", dev->alignment_offset);
582 8 : printf("logical_sector_size: %lu\n", dev->logical_sector_size);
583 8 : printf("minimum_io_size: %lu\n", dev->minimum_io_size);
584 8 : printf("optimal_io_size: %lu\n", dev->optimal_io_size);
585 8 : printf("physical_sector_size: %lu\n", dev->physical_sector_size);
586 : }
587 75 : if (got_topol && dev->alignment_offset != 0) {
588 2 : fprintf(stderr,
589 2 : _("Warning: device is not properly aligned. This may harm performance.\n"));
590 2 : dev->physical_sector_size = dev->logical_sector_size;
591 : }
592 75 : if (!opts->got_bsize && got_topol) {
593 7 : if (dev->optimal_io_size <= getpagesize() &&
594 1 : dev->optimal_io_size >= LGFS2_DEFAULT_BSIZE)
595 0 : bsize = dev->optimal_io_size;
596 7 : else if (dev->physical_sector_size <= getpagesize() &&
597 7 : dev->physical_sector_size >= LGFS2_DEFAULT_BSIZE)
598 0 : bsize = dev->physical_sector_size;
599 : }
600 : /* Block sizes must be a power of two from 512 to 65536 */
601 275 : for (x = 512; x; x <<= 1)
602 275 : if (x == bsize)
603 75 : break;
604 :
605 75 : if (!x || bsize > getpagesize()) {
606 0 : fprintf(stderr, _("Block size must be a power of two between 512 and %d\n"),
607 : getpagesize());
608 0 : return -1;
609 : }
610 75 : if (bsize < dev->logical_sector_size) {
611 0 : fprintf(stderr, _("Error: Block size %d is less than minimum logical "
612 : "block size (%lu).\n"), bsize, dev->logical_sector_size);
613 0 : return -1;
614 : }
615 75 : if (bsize < dev->physical_sector_size) {
616 0 : printf( _("Warning: Block size %d is inefficient because it "
617 : "is less than the physical block size (%lu).\n"),
618 : bsize, dev->physical_sector_size);
619 0 : opts->confirm = 1;
620 : }
621 75 : *pbsize = bsize;
622 75 : return 0;
623 : }
624 :
625 88 : static int opts_check(struct mkfs_opts *opts)
626 : {
627 88 : if (!opts->got_device) {
628 0 : fprintf(stderr, _("No device specified. Use -h for help\n"));
629 0 : return -1;
630 : }
631 :
632 88 : if (test_locking(opts) != 0)
633 7 : return -1;
634 :
635 81 : if (LGFS2_MIN_RGSIZE > opts->rgsize || opts->rgsize > LGFS2_MAX_RGSIZE) {
636 : /* Translators: gfs2 file systems are split into equal sized chunks called
637 : resource groups. We're checking that the user gave a valid size for them. */
638 2 : fprintf(stderr, _("Bad resource group size\n"));
639 2 : return -1;
640 : }
641 :
642 79 : if (!opts->journals) {
643 0 : fprintf(stderr, _("No journals specified\n"));
644 0 : return -1;
645 : }
646 79 : if (opts->journals < 0) {
647 0 : fprintf(stderr, _("Number of journals cannot be negative: %d\n"), opts->journals);
648 0 : return -1;
649 : }
650 79 : if (opts->jsize < LGFS2_MIN_JSIZE || opts->jsize > LGFS2_MAX_JSIZE) {
651 2 : fprintf(stderr, _("Bad journal size\n"));
652 2 : return -1;
653 : }
654 :
655 77 : if (!opts->qcsize || opts->qcsize > 64) {
656 2 : fprintf(stderr, _("Bad quota change size\n"));
657 2 : return -1;
658 : }
659 :
660 75 : if ((opts->got_sunit && !opts->got_swidth) || (!opts->got_sunit && opts->got_swidth)) {
661 0 : fprintf(stderr, _("Stripe unit and stripe width must be specified together\n"));
662 0 : return -1;
663 : }
664 75 : return 0;
665 : }
666 :
667 70 : static void print_results(struct lgfs2_sbd *sb, struct mkfs_opts *opts)
668 : {
669 : char readable_uuid[36+1];
670 :
671 70 : uuid_unparse(sb->sd_uuid, readable_uuid);
672 :
673 70 : printf("%-27s%s\n", _("Device:"), opts->dev.path);
674 70 : printf("%-27s%u\n", _("Block size:"), sb->sd_bsize);
675 70 : printf("%-27s%.2f %s (%"PRIu64" %s)\n", _("Device size:"),
676 : /* Translators: "GB" here means "gigabytes" */
677 70 : (opts->dev.size / ((float)(1 << 30))), _("GB"),
678 70 : (opts->dev.size / sb->sd_bsize), _("blocks"));
679 70 : printf("%-27s%.2f %s (%"PRIu64" %s)\n", _("Filesystem size:"),
680 70 : (sb->fssize / ((float)(1 << 30)) * sb->sd_bsize), _("GB"), sb->fssize, _("blocks"));
681 70 : printf("%-27s%u\n", _("Journals:"), opts->journals);
682 70 : printf("%-27s%uMB\n", _("Journal size:"), opts->jsize);
683 70 : printf("%-27s%"PRIu64"\n", _("Resource groups:"), nrgrp);
684 70 : printf("%-27s\"%s\"\n", _("Locking protocol:"), opts->lockproto);
685 70 : printf("%-27s\"%s\"\n", _("Lock table:"), opts->locktable);
686 : /* Translators: "UUID" = universally unique identifier. */
687 70 : printf("%-27s%s\n", _("UUID:"), readable_uuid);
688 70 : }
689 :
690 70 : static int warn_of_destruction(const char *path)
691 : {
692 : struct stat lnkstat;
693 70 : char *abspath = NULL;
694 :
695 70 : if (lstat(path, &lnkstat) == -1) {
696 0 : perror(_("Failed to lstat the device"));
697 0 : return -1;
698 : }
699 70 : if (S_ISLNK(lnkstat.st_mode)) {
700 : /* coverity[toctou:SUPPRESS] */
701 0 : abspath = realpath(path, NULL);
702 0 : if (abspath == NULL) {
703 0 : perror(_("Could not find the absolute path of the device"));
704 0 : return -1;
705 : }
706 : /* Translators: Example: "/dev/vg/lv is a symbolic link to /dev/dm-2" */
707 0 : printf( _("%s is a symbolic link to %s\n"), path, abspath);
708 0 : path = abspath;
709 : }
710 70 : printf(_("This will destroy any data on %s\n"), path);
711 70 : free(abspath);
712 70 : return 0;
713 : }
714 :
715 70 : static int build_per_node(struct lgfs2_sbd *sdp, struct mkfs_opts *opts)
716 : {
717 : struct lgfs2_inode *per_node;
718 : unsigned int j;
719 :
720 : /* coverity[identity_transfer:SUPPRESS] False positive */
721 70 : per_node = lgfs2_createi(sdp->master_dir, "per_node", S_IFDIR | 0700,
722 : GFS2_DIF_SYSTEM);
723 70 : if (per_node == NULL) {
724 0 : fprintf(stderr, _("Error building '%s': %s\n"), "per_node", strerror(errno));
725 0 : return -1;
726 : }
727 147 : for (j = 0; j < sdp->md.journals; j++) {
728 : struct lgfs2_inode *ip;
729 :
730 : /* coverity[identity_transfer:SUPPRESS] False positive */
731 77 : ip = lgfs2_build_inum_range(per_node, j);
732 77 : if (ip == NULL) {
733 0 : fprintf(stderr, _("Error building '%s': %s\n"), "inum_range",
734 0 : strerror(errno));
735 0 : lgfs2_inode_put(&per_node);
736 0 : return 1;
737 : }
738 77 : if (opts->debug) {
739 62 : printf("\nInum Range %u:\n", j);
740 62 : dinode_print(ip->i_bh->b_data);
741 : }
742 77 : lgfs2_inode_put(&ip);
743 :
744 : /* coverity[identity_transfer:SUPPRESS] False positive */
745 77 : ip = lgfs2_build_statfs_change(per_node, j);
746 77 : if (ip == NULL) {
747 0 : fprintf(stderr, _("Error building '%s': %s\n"), "statfs_change",
748 0 : strerror(errno));
749 0 : lgfs2_inode_put(&per_node);
750 0 : return 1;
751 : }
752 77 : if (opts->debug) {
753 62 : printf("\nStatFS Change %u:\n", j);
754 62 : dinode_print(ip->i_bh->b_data);
755 : }
756 77 : lgfs2_inode_put(&ip);
757 :
758 : /* coverity[identity_transfer:SUPPRESS] False positive */
759 77 : ip = lgfs2_build_quota_change(per_node, j);
760 77 : if (ip == NULL) {
761 0 : fprintf(stderr, _("Error building '%s': %s\n"), "quota_change",
762 0 : strerror(errno));
763 : /* coverity[deref_arg:SUPPRESS] */
764 0 : lgfs2_inode_put(&per_node);
765 0 : return 1;
766 : }
767 77 : if (opts->debug) {
768 62 : printf("\nQuota Change %u:\n", j);
769 62 : dinode_print(ip->i_bh->b_data);
770 : }
771 77 : lgfs2_inode_put(&ip);
772 : }
773 70 : if (opts->debug) {
774 55 : printf("\nper_node:\n");
775 55 : dinode_print(per_node->i_bh->b_data);
776 : }
777 70 : lgfs2_inode_put(&per_node);
778 70 : return 0;
779 : }
780 :
781 3800 : static int zero_gap(struct lgfs2_sbd *sdp, uint64_t addr, size_t blocks)
782 : {
783 : struct iovec *iov;
784 : char *zerobuf;
785 : ssize_t wrote;
786 : unsigned i;
787 :
788 3800 : if (blocks == 0)
789 0 : return 0;
790 3800 : iov = calloc(blocks, sizeof(*iov));
791 3800 : if (iov == NULL) {
792 0 : perror(_("Failed to zero blocks\n"));
793 0 : return 1;
794 : }
795 3800 : zerobuf = calloc(1, sdp->sd_bsize);
796 3800 : if (zerobuf == NULL) {
797 0 : perror(_("Failed to zero blocks\n"));
798 0 : free(iov);
799 0 : return 1;
800 : }
801 16273 : for (i = 0; i < blocks; i++) {
802 12473 : iov[i].iov_base = zerobuf;
803 12473 : iov[i].iov_len = sdp->sd_bsize;
804 : }
805 3800 : wrote = pwritev(sdp->device_fd, iov, blocks, addr * sdp->sd_bsize);
806 3800 : if (wrote != blocks * sdp->sd_bsize) {
807 0 : fprintf(stderr, _("Zeroing write failed at block %"PRIu64"\n"), addr);
808 0 : free(zerobuf);
809 0 : free(iov);
810 0 : return 1;
811 : }
812 3800 : free(zerobuf);
813 3800 : free(iov);
814 3800 : return 0;
815 : }
816 :
817 70 : static lgfs2_rgrps_t rgs_init(struct mkfs_opts *opts, struct lgfs2_sbd *sdp)
818 : {
819 : lgfs2_rgrps_t rgs;
820 70 : uint64_t al_base = 0;
821 70 : uint64_t al_off = 0;
822 :
823 70 : if (opts->align && opts->got_sunit) {
824 0 : if ((opts->sunit % sdp->sd_bsize) != 0) {
825 0 : fprintf(stderr, _("Stripe unit (%lu) must be a multiple of block size (%u)\n"),
826 : opts->sunit, sdp->sd_bsize);
827 0 : return NULL;
828 0 : } else if ((opts->swidth % opts->sunit) != 0) {
829 0 : fprintf(stderr, _("Stripe width (%lu) must be a multiple of stripe unit (%lu)\n"),
830 : opts->swidth, opts->sunit);
831 0 : return NULL;
832 : } else {
833 0 : al_base = opts->swidth / sdp->sd_bsize;
834 0 : al_off = opts->sunit / sdp->sd_bsize;
835 : }
836 70 : } else if (opts->align) {
837 69 : if (opts->dev.optimal_io_size <= opts->dev.physical_sector_size ||
838 7 : opts->dev.minimum_io_size <= opts->dev.physical_sector_size ||
839 6 : (opts->dev.optimal_io_size % opts->dev.minimum_io_size) != 0) {
840 : /* If optimal_io_size is not a multiple of minimum_io_size then
841 : the values are not reliable swidth and sunit values, so disable
842 : rgrp alignment */
843 64 : opts->align = 0;
844 : } else {
845 5 : al_base = opts->dev.optimal_io_size / sdp->sd_bsize;
846 5 : al_off = opts->dev.minimum_io_size / sdp->sd_bsize;
847 : }
848 : }
849 :
850 70 : rgs = lgfs2_rgrps_init(sdp, al_base, al_off);
851 70 : if (rgs == NULL) {
852 0 : perror(_("Could not initialise resource groups"));
853 0 : return NULL;
854 : }
855 :
856 70 : if (opts->debug) {
857 55 : printf(" rgrp align = ");
858 55 : if (opts->align)
859 5 : printf("%"PRIu64"+%"PRIu64" blocks\n", al_base, al_off);
860 : else
861 50 : printf("(disabled)\n");
862 : }
863 :
864 70 : return rgs;
865 : }
866 :
867 6429 : static int place_rgrp(struct lgfs2_sbd *sdp, lgfs2_rgrp_t rg, int debug)
868 : {
869 6429 : uint64_t prev_end = (GFS2_SB_ADDR * GFS2_BASIC_BLOCK / sdp->sd_bsize) + 1;
870 6429 : lgfs2_rgrp_t prev = lgfs2_rgrp_prev(rg);
871 : struct gfs2_rindex ri;
872 : uint64_t addr;
873 6429 : int err = 0;
874 :
875 6429 : if (prev != NULL) {
876 6359 : lgfs2_rindex_out(prev, &ri);
877 6359 : prev_end = be64_to_cpu(ri.ri_data0) + be32_to_cpu(ri.ri_data);
878 : }
879 :
880 6429 : lgfs2_rindex_out(rg, &ri);
881 6429 : addr = be64_to_cpu(ri.ri_addr);
882 :
883 10229 : while (prev_end < addr) {
884 3800 : size_t gap_len = addr - prev_end;
885 :
886 3800 : if (gap_len > IOV_MAX)
887 3 : gap_len = IOV_MAX;
888 3800 : err = zero_gap(sdp, prev_end, gap_len);
889 3800 : if (err != 0)
890 0 : return -1;
891 3800 : prev_end += gap_len;
892 : }
893 6429 : err = lgfs2_rgrp_write(sdp->device_fd, rg);
894 6429 : if (err != 0) {
895 0 : perror(_("Failed to write resource group"));
896 0 : return -1;
897 : }
898 6429 : if (debug) {
899 5354 : rindex_print(&ri);
900 5354 : printf("\n");
901 : }
902 6429 : sdp->blks_total += be32_to_cpu(ri.ri_data);
903 6429 : sdp->fssize = be64_to_cpu(ri.ri_data0) + be32_to_cpu(ri.ri_data);
904 6429 : nrgrp++;
905 6429 : return 0;
906 : }
907 :
908 6499 : static int add_rgrp(lgfs2_rgrps_t rgs, uint64_t *addr, uint32_t len, lgfs2_rgrp_t *rg)
909 : {
910 : struct gfs2_rindex ri;
911 : uint64_t nextaddr;
912 :
913 : /* When we get to the end of the device, it's only an error if we have
914 : more structures left to write, i.e. when len is != 0. */
915 6499 : nextaddr = lgfs2_rindex_entry_new(rgs, &ri, *addr, len);
916 6499 : if (nextaddr == 0) {
917 70 : if (len != 0) {
918 0 : perror(_("Failed to create resource group index entry"));
919 0 : return -1;
920 : } else {
921 70 : return 1;
922 : }
923 : }
924 6429 : *rg = lgfs2_rgrps_append(rgs, &ri, nextaddr - *addr);
925 6429 : if (*rg == NULL) {
926 0 : perror(_("Failed to create resource group"));
927 0 : return -1;
928 : }
929 6429 : *addr = nextaddr;
930 6429 : return 0;
931 : }
932 :
933 70 : static int place_journals(struct lgfs2_sbd *sdp, lgfs2_rgrps_t rgs, struct mkfs_opts *opts, uint64_t *rgaddr)
934 : {
935 : struct gfs2_progress_bar progress;
936 70 : uint64_t jfsize = lgfs2_space_for_data(sdp, sdp->sd_bsize, opts->jsize << 20);
937 70 : uint32_t rgsize = lgfs2_rgsize_for_data(jfsize, sdp->sd_bsize);
938 : unsigned j;
939 :
940 70 : gfs2_progress_init(&progress, opts->journals, _("Adding journals: "), opts->quiet);
941 :
942 : /* We'll build the jindex later so remember where we put the journals */
943 70 : mkfs_journals = calloc(opts->journals, sizeof(*mkfs_journals));
944 70 : if (mkfs_journals == NULL)
945 0 : return 1;
946 70 : *rgaddr = lgfs2_rgrp_align_addr(rgs, LGFS2_SB_ADDR(sdp) + 1);
947 70 : rgsize = lgfs2_rgrp_align_len(rgs, rgsize);
948 :
949 147 : for (j = 0; j < opts->journals; j++) {
950 : int result;
951 : lgfs2_rgrp_t rg;
952 77 : struct lgfs2_inode in = {0};
953 : struct gfs2_rindex ri;
954 :
955 77 : gfs2_progress_update(&progress, (j + 1));
956 :
957 77 : if (opts->debug)
958 62 : printf(_("Placing resource group for journal%u\n"), j);
959 :
960 77 : result = add_rgrp(rgs, rgaddr, rgsize, &rg);
961 77 : if (result > 0)
962 0 : break;
963 77 : else if (result < 0)
964 0 : return result;
965 :
966 77 : result = lgfs2_rgrp_bitbuf_alloc(rg);
967 77 : if (result != 0) {
968 0 : perror(_("Failed to allocate space for bitmap buffer"));
969 0 : return result;
970 : }
971 : /* Allocate at the beginning of the rgrp, bypassing extent search */
972 77 : lgfs2_rindex_out(rg, &ri);
973 77 : in.i_num.in_addr = be64_to_cpu(ri.ri_data0);
974 : /* In order to keep writes sequential here, we have to allocate
975 : the journal, then write the rgrp header (which is now in its
976 : final form) and then write the journal out */
977 77 : result = lgfs2_file_alloc(rg, opts->jsize << 20, &in, GFS2_DIF_SYSTEM, S_IFREG | 0600);
978 77 : if (result != 0) {
979 0 : fprintf(stderr, _("Failed to allocate space for journal %u\n"), j);
980 0 : return result;
981 : }
982 :
983 77 : result = place_rgrp(sdp, rg, opts->debug);
984 77 : if (result != 0)
985 0 : return result;
986 :
987 77 : lgfs2_rgrp_bitbuf_free(rg);
988 :
989 77 : result = lgfs2_write_filemeta(&in);
990 77 : if (result != 0) {
991 0 : fprintf(stderr, _("Failed to write journal %u: %s\n"),
992 0 : j, strerror(errno));
993 0 : return result;
994 : }
995 :
996 77 : result = lgfs2_write_journal_data(&in);
997 77 : if (result != 0) {
998 0 : fprintf(stderr, _("Failed to write data blocks for journal %u: %s\n"),
999 0 : j, strerror(errno));
1000 0 : return result;
1001 : }
1002 77 : mkfs_journals[j] = in.i_num;
1003 : }
1004 70 : gfs2_progress_close(&progress, _("Done\n"));
1005 :
1006 70 : return 0;
1007 : }
1008 :
1009 70 : static int place_rgrps(struct lgfs2_sbd *sdp, lgfs2_rgrps_t rgs, uint64_t *rgaddr, struct mkfs_opts *opts)
1010 : {
1011 : struct gfs2_progress_bar progress;
1012 70 : uint32_t rgblks = ((opts->rgsize << 20) / sdp->sd_bsize);
1013 : uint32_t rgnum;
1014 : int result;
1015 :
1016 70 : rgnum = lgfs2_rgrps_plan(rgs, sdp->device.length - *rgaddr, rgblks);
1017 70 : gfs2_progress_init(&progress, (rgnum + opts->journals), _("Building resource groups: "), opts->quiet);
1018 :
1019 6352 : while (1) {
1020 : lgfs2_rgrp_t rg;
1021 6422 : result = add_rgrp(rgs, rgaddr, 0, &rg);
1022 6422 : if (result > 0)
1023 70 : break;
1024 6352 : else if (result < 0)
1025 0 : return result;
1026 :
1027 6352 : result = place_rgrp(sdp, rg, opts->debug);
1028 6352 : if (result != 0) {
1029 0 : fprintf(stderr, _("Failed to build resource groups\n"));
1030 0 : return result;
1031 : }
1032 6352 : gfs2_progress_update(&progress, nrgrp);
1033 : }
1034 70 : if (lgfs2_rgrps_write_final(sdp->device_fd, rgs) != 0) {
1035 0 : perror(_("Failed to write final resource group"));
1036 0 : return 0;
1037 : }
1038 70 : gfs2_progress_close(&progress, _("Done\n"));
1039 :
1040 70 : return 0;
1041 : }
1042 :
1043 70 : static int create_jindex(struct lgfs2_sbd *sdp, struct mkfs_opts *opts, struct lgfs2_inum *jnls)
1044 : {
1045 : struct lgfs2_inode *jindex;
1046 :
1047 70 : jindex = lgfs2_build_jindex(sdp->master_dir, jnls, opts->journals);
1048 70 : if (jindex == NULL) {
1049 0 : fprintf(stderr, _("Error building '%s': %s\n"), "jindex", strerror(errno));
1050 0 : return 1;
1051 : }
1052 70 : if (opts->debug) {
1053 55 : printf("Jindex:\n");
1054 55 : dinode_print(jindex->i_bh->b_data);
1055 : }
1056 70 : lgfs2_inode_put(&jindex);
1057 70 : return 0;
1058 : }
1059 :
1060 :
1061 : /*
1062 : * Find a reasonable journal file size (in blocks) given the number of blocks
1063 : * in the filesystem. For very small filesystems, it is not reasonable to
1064 : * have a journal that fills more than half of the filesystem.
1065 : *
1066 : * n.b. comments assume 4k blocks
1067 : *
1068 : * This was copied and adapted from e2fsprogs.
1069 : */
1070 66 : static int default_journal_size(unsigned bsize, uint64_t num_blocks)
1071 : {
1072 66 : int min_blocks = (LGFS2_MIN_JSIZE << 20) / bsize;
1073 :
1074 66 : if (num_blocks < 2 * min_blocks)
1075 0 : return -1;
1076 66 : if (num_blocks < 131072) /* 512 MB */
1077 2 : return min_blocks; /* 8 MB */
1078 64 : if (num_blocks < 512*1024) /* 2 GB */
1079 1 : return (4096); /* 16 MB */
1080 63 : if (num_blocks < 2048*1024) /* 8 GB */
1081 0 : return (8192); /* 32 MB */
1082 63 : if (num_blocks < 4096*1024) /* 16 GB */
1083 2 : return (16384); /* 64 MB */
1084 61 : if (num_blocks < 262144*1024) /* 1 TB */
1085 61 : return (32768); /* 128 MB */
1086 0 : if (num_blocks < 2621440UL*1024) /* 10 TB */
1087 0 : return (131072); /* 512 MB */
1088 0 : return 262144; /* 1 GB */
1089 : }
1090 :
1091 75 : static int sbd_init(struct lgfs2_sbd *sdp, struct mkfs_opts *opts, unsigned bsize)
1092 : {
1093 75 : memset(sdp, 0, sizeof(struct lgfs2_sbd));
1094 75 : sdp->sd_time = time(NULL);
1095 75 : sdp->rgtree.osi_node = NULL;
1096 75 : sdp->rgsize = opts->rgsize;
1097 75 : sdp->qcsize = opts->qcsize;
1098 75 : sdp->jsize = opts->jsize;
1099 75 : sdp->md.journals = opts->journals;
1100 75 : sdp->device_fd = opts->dev.fd;
1101 75 : sdp->sd_bsize = bsize;
1102 75 : sdp->sd_fs_format = opts->format;
1103 75 : sdp->sd_multihost_format = GFS2_FORMAT_MULTI;
1104 75 : sdp->sd_bsize = bsize;
1105 75 : sdp->sd_bsize_shift = ffs(bsize) - 1;
1106 :
1107 75 : if (opts->got_uuid) {
1108 4 : int err = uuid_parse(opts->uuid, sdp->sd_uuid);
1109 4 : if (err != 0) {
1110 3 : fprintf(stderr, _("Failed to parse UUID option."));
1111 3 : return -1;
1112 : }
1113 : } else
1114 71 : uuid_generate(sdp->sd_uuid);
1115 :
1116 72 : if (lgfs2_compute_constants(sdp)) {
1117 0 : perror(_("Failed to compute file system constants"));
1118 0 : return -1;
1119 : }
1120 72 : sdp->device.length = opts->dev.size / sdp->sd_bsize;
1121 72 : if (opts->got_fssize) {
1122 7 : if (opts->fssize > sdp->device.length) {
1123 2 : fprintf(stderr, _("Specified size is bigger than the device."));
1124 2 : fprintf(stderr, "%s %.2f %s (%"PRIu64" %s)\n", _("Device size:"),
1125 2 : opts->dev.size / ((float)(1 << 30)), _("GB"),
1126 2 : opts->dev.size / sdp->sd_bsize, _("blocks"));
1127 2 : return -1;
1128 : }
1129 5 : sdp->device.length = opts->fssize;
1130 : }
1131 : /* opts->jsize has already been max/min checked but we need to check it
1132 : makes sense for the device size, or set a sensible default, if one
1133 : will fit. For user-provided journal sizes, limit it to half of the fs. */
1134 70 : if (!opts->got_jsize) {
1135 66 : int default_jsize = default_journal_size(sdp->sd_bsize, sdp->device.length / opts->journals);
1136 : unsigned jsize_mb;
1137 :
1138 66 : if (default_jsize < 0) {
1139 0 : fprintf(stderr, _("gfs2 will not fit on this device.\n"));
1140 0 : return -1;
1141 : }
1142 66 : jsize_mb = (default_jsize * sdp->sd_bsize) >> 20;
1143 66 : if (jsize_mb < LGFS2_MIN_JSIZE)
1144 1 : opts->jsize = LGFS2_MIN_JSIZE;
1145 : else
1146 65 : opts->jsize = jsize_mb;
1147 4 : } else if ((((opts->jsize * opts->journals) << 20) / sdp->sd_bsize) > (sdp->device.length / 2)) {
1148 0 : unsigned max_jsize = (sdp->device.length / 2 * sdp->sd_bsize / opts->journals) >> 20;
1149 :
1150 0 : fprintf(stderr, _("gfs2 will not fit on this device.\n"));
1151 0 : if (max_jsize >= LGFS2_MIN_JSIZE)
1152 0 : fprintf(stderr, _("Maximum size for %u journals on this device is %uMB.\n"),
1153 : opts->journals, max_jsize);
1154 0 : return -1;
1155 : }
1156 70 : sdp->jsize = opts->jsize;
1157 70 : return 0;
1158 : }
1159 :
1160 67 : static int probe_contents(struct mkfs_dev *dev)
1161 : {
1162 : int ret;
1163 : const char *contents;
1164 67 : blkid_probe pr = blkid_new_probe();
1165 67 : if (pr == NULL || blkid_probe_set_device(pr, dev->fd, 0, 0) != 0
1166 67 : || blkid_probe_enable_superblocks(pr, 1) != 0
1167 67 : || blkid_probe_enable_partitions(pr, 1) != 0) {
1168 0 : fprintf(stderr, _("Failed to create probe\n"));
1169 0 : return -1;
1170 : }
1171 :
1172 67 : if (!S_ISREG(dev->stat.st_mode) && blkid_probe_enable_topology(pr, 1) != 0) {
1173 0 : fprintf(stderr, _("Failed to create probe\n"));
1174 0 : return -1;
1175 : }
1176 :
1177 67 : ret = blkid_do_fullprobe(pr);
1178 67 : if (ret == -1) {
1179 0 : fprintf(stderr, _("Failed to probe device\n"));
1180 0 : return -1;
1181 : }
1182 :
1183 67 : if (ret == 1)
1184 54 : return 0;
1185 :
1186 13 : if (!blkid_probe_lookup_value(pr, "TYPE", &contents, NULL)) {
1187 13 : printf(_("It appears to contain an existing filesystem (%s)\n"), contents);
1188 0 : } else if (!blkid_probe_lookup_value(pr, "PTTYPE", &contents, NULL)) {
1189 0 : printf(_("It appears to contain a partition table (%s).\n"), contents);
1190 : }
1191 :
1192 13 : if (!S_ISREG(dev->stat.st_mode)) {
1193 0 : blkid_topology tp = blkid_probe_get_topology(pr);
1194 0 : if (tp != NULL) {
1195 0 : dev->alignment_offset = blkid_topology_get_alignment_offset(tp);
1196 0 : dev->logical_sector_size = blkid_topology_get_logical_sector_size(tp);
1197 0 : dev->minimum_io_size = blkid_topology_get_minimum_io_size(tp);
1198 0 : dev->optimal_io_size = blkid_topology_get_optimal_io_size(tp);
1199 0 : dev->physical_sector_size = blkid_topology_get_physical_sector_size(tp);
1200 0 : dev->got_topol = (dev->logical_sector_size != 0 &&
1201 0 : dev->physical_sector_size != 0);
1202 : }
1203 : }
1204 :
1205 13 : blkid_free_probe(pr);
1206 13 : return 0;
1207 : }
1208 :
1209 75 : static int open_dev(struct mkfs_dev *dev, int withprobe)
1210 : {
1211 : int error;
1212 :
1213 75 : dev->fd = open(dev->path, O_RDWR|O_CLOEXEC|O_EXCL);
1214 75 : if (dev->fd < 0) {
1215 0 : perror(dev->path);
1216 0 : return 1;
1217 : }
1218 :
1219 : /* Freshen up the cache */
1220 75 : (void)posix_fadvise(dev->fd, 0, 0, POSIX_FADV_DONTNEED);
1221 :
1222 75 : error = fstat(dev->fd, &dev->stat);
1223 75 : if (error < 0) {
1224 0 : perror(dev->path);
1225 0 : return 1;
1226 : }
1227 :
1228 75 : if (S_ISREG(dev->stat.st_mode)) {
1229 75 : dev->size = dev->stat.st_size;
1230 0 : } else if (S_ISBLK(dev->stat.st_mode)) {
1231 0 : dev->size = lseek(dev->fd, 0, SEEK_END);
1232 0 : if (dev->size < 1) {
1233 0 : fprintf(stderr, _("Device '%s' is too small\n"), dev->path);
1234 0 : return 1;
1235 : }
1236 : } else {
1237 0 : fprintf(stderr, _("'%s' is not a block device or regular file\n"), dev->path);
1238 0 : return 1;
1239 : }
1240 75 : if (withprobe && (probe_contents(dev) != 0))
1241 0 : return 1;
1242 75 : return 0;
1243 : }
1244 :
1245 : #ifndef UNITTESTS
1246 97 : int main(int argc, char *argv[])
1247 : {
1248 : struct gfs2_statfs_change sc;
1249 : struct lgfs2_sbd sbd;
1250 : struct mkfs_opts opts;
1251 : struct lgfs2_inode *ip;
1252 : lgfs2_rgrps_t rgs;
1253 : uint64_t rgaddr;
1254 : int error;
1255 : unsigned bsize;
1256 :
1257 97 : setlocale(LC_ALL, "");
1258 97 : textdomain("gfs2-utils");
1259 97 : srandom(time(NULL) ^ getpid());
1260 :
1261 97 : opts_init(&opts);
1262 97 : error = opts_get(argc, argv, &opts);
1263 97 : if (error == 1)
1264 0 : exit(0);
1265 97 : if (error != 0)
1266 9 : exit(-1);
1267 88 : error = opts_check(&opts);
1268 88 : if (error != 0)
1269 13 : exit(error);
1270 :
1271 75 : error = open_dev(&opts.dev, !opts.got_topol);
1272 75 : if (error != 0)
1273 0 : exit(error);
1274 75 : error = choose_blocksize(&opts, &bsize);
1275 75 : if (error != 0)
1276 0 : exit(-1);
1277 :
1278 75 : if (S_ISREG(opts.dev.stat.st_mode)) {
1279 75 : opts.got_bsize = 1; /* Use default block size for regular files */
1280 : }
1281 75 : if (sbd_init(&sbd, &opts, bsize) != 0)
1282 5 : exit(-1);
1283 70 : if (opts.debug) {
1284 55 : printf(_("File system options:\n"));
1285 55 : printf(" bsize = %u\n", sbd.sd_bsize);
1286 55 : printf(" qcsize = %u\n", sbd.qcsize);
1287 55 : printf(" jsize = %u\n", sbd.jsize);
1288 55 : printf(" journals = %u\n", sbd.md.journals);
1289 55 : printf(" proto = %s\n", opts.lockproto);
1290 55 : printf(" table = %s\n", opts.locktable);
1291 55 : printf(" rgsize = %u\n", sbd.rgsize);
1292 55 : printf(" fssize = %"PRIu64"\n", opts.fssize);
1293 55 : printf(" sunit = %lu\n", opts.sunit);
1294 55 : printf(" swidth = %lu\n", opts.swidth);
1295 55 : printf(" format = %u\n", opts.format);
1296 : }
1297 70 : rgs = rgs_init(&opts, &sbd);
1298 70 : if (rgs == NULL)
1299 0 : exit(-1);
1300 70 : if (warn_of_destruction(opts.dev.path) != 0)
1301 0 : exit(-1);
1302 :
1303 70 : if (opts.confirm && !opts.override)
1304 0 : if (!are_you_sure())
1305 0 : exit(-1);
1306 :
1307 70 : if (!S_ISREG(opts.dev.stat.st_mode) && opts.discard) {
1308 0 : if (!opts.quiet) {
1309 0 : printf("%s", _("Discarding device contents (may take a while on large devices): "));
1310 0 : fflush(stdout);
1311 : }
1312 0 : discard_blocks(opts.dev.fd, opts.dev.size, opts.debug);
1313 :
1314 0 : if (!opts.quiet)
1315 0 : printf("%s", _("Done\n"));
1316 : }
1317 70 : rgaddr = lgfs2_rgrp_align_addr(rgs, LGFS2_SB_ADDR(&sbd) + 1);
1318 70 : error = place_journals(&sbd, rgs, &opts, &rgaddr);
1319 70 : if (error != 0) {
1320 0 : fprintf(stderr, _("Failed to create journals\n"));
1321 0 : exit(1);
1322 : }
1323 70 : error = place_rgrps(&sbd, rgs, &rgaddr, &opts);
1324 70 : if (error) {
1325 0 : fprintf(stderr, _("Failed to build resource groups\n"));
1326 0 : exit(1);
1327 : }
1328 70 : lgfs2_attach_rgrps(&sbd, rgs); // Temporary
1329 :
1330 70 : error = lgfs2_build_master(&sbd);
1331 70 : if (error) {
1332 0 : fprintf(stderr, _("Error building '%s': %s\n"), "master", strerror(errno));
1333 0 : exit(EXIT_FAILURE);
1334 : }
1335 70 : if (opts.debug) {
1336 55 : printf("Metafs inode:\n");
1337 55 : dinode_print(sbd.master_dir->i_bh->b_data);
1338 : }
1339 70 : sbd.sd_meta_dir = sbd.master_dir->i_num;
1340 :
1341 70 : error = create_jindex(&sbd, &opts, mkfs_journals);
1342 70 : free(mkfs_journals);
1343 70 : if (error != 0)
1344 0 : exit(1);
1345 :
1346 70 : error = build_per_node(&sbd, &opts);
1347 70 : if (error != 0)
1348 0 : exit(1);
1349 :
1350 70 : sbd.md.inum = lgfs2_build_inum(&sbd);
1351 70 : if (sbd.md.inum == NULL) {
1352 0 : fprintf(stderr, _("Error building '%s': %s\n"), "inum", strerror(errno));
1353 0 : exit(EXIT_FAILURE);
1354 : }
1355 70 : if (opts.debug) {
1356 55 : printf("\nInum Inode:\n");
1357 55 : dinode_print(sbd.md.inum->i_bh->b_data);
1358 : }
1359 70 : sbd.md.statfs = lgfs2_build_statfs(&sbd);
1360 70 : if (sbd.md.statfs == NULL) {
1361 0 : fprintf(stderr, _("Error building '%s': %s\n"), "statfs", strerror(errno));
1362 0 : exit(EXIT_FAILURE);
1363 : }
1364 70 : if (opts.debug) {
1365 55 : printf("\nStatFS Inode:\n");
1366 55 : dinode_print(sbd.md.statfs->i_bh->b_data);
1367 : }
1368 70 : ip = lgfs2_build_rindex(&sbd);
1369 70 : if (ip == NULL) {
1370 0 : fprintf(stderr, _("Error building '%s': %s\n"), "rindex", strerror(errno));
1371 0 : exit(EXIT_FAILURE);
1372 : }
1373 70 : if (opts.debug) {
1374 55 : printf("\nResource Index:\n");
1375 55 : dinode_print(ip->i_bh->b_data);
1376 : }
1377 70 : lgfs2_inode_put(&ip);
1378 70 : if (!opts.quiet) {
1379 70 : printf("%s", _("Creating quota file: "));
1380 70 : fflush(stdout);
1381 : }
1382 70 : ip = lgfs2_build_quota(&sbd);
1383 70 : if (ip == NULL) {
1384 0 : fprintf(stderr, _("Error building '%s': %s\n"), "quota", strerror(errno));
1385 0 : exit(EXIT_FAILURE);
1386 : }
1387 70 : if (opts.debug) {
1388 55 : printf("\nQuota:\n");
1389 55 : dinode_print(ip->i_bh->b_data);
1390 : }
1391 70 : lgfs2_inode_put(&ip);
1392 70 : if (!opts.quiet)
1393 70 : printf("%s", _("Done\n"));
1394 :
1395 70 : lgfs2_build_root(&sbd);
1396 70 : if (opts.root_inherit_jd) {
1397 2 : sbd.md.rooti->i_flags |= GFS2_DIF_INHERIT_JDATA;
1398 2 : lgfs2_dinode_out(sbd.md.rooti, sbd.md.rooti->i_bh->b_data);
1399 : }
1400 70 : if (opts.debug) {
1401 55 : printf("\nRoot directory:\n");
1402 55 : dinode_print(sbd.md.rooti->i_bh->b_data);
1403 : }
1404 70 : sbd.sd_root_dir = sbd.md.rooti->i_num;
1405 :
1406 70 : strncpy(sbd.sd_lockproto, opts.lockproto, GFS2_LOCKNAME_LEN - 1);
1407 70 : strncpy(sbd.sd_locktable, opts.locktable, GFS2_LOCKNAME_LEN - 1);
1408 70 : sbd.sd_lockproto[GFS2_LOCKNAME_LEN - 1] = '\0';
1409 70 : sbd.sd_locktable[GFS2_LOCKNAME_LEN - 1] = '\0';
1410 :
1411 70 : lgfs2_init_inum(&sbd);
1412 70 : if (opts.debug)
1413 55 : printf("\nNext Inum: %"PRIu64"\n", sbd.md.next_inum);
1414 :
1415 70 : lgfs2_init_statfs(&sbd, &sc);
1416 70 : if (opts.debug) {
1417 55 : printf("\nStatfs:\n");
1418 55 : statfs_change_print(&sc);
1419 : }
1420 70 : lgfs2_inode_put(&sbd.md.rooti);
1421 70 : lgfs2_inode_put(&sbd.master_dir);
1422 70 : lgfs2_inode_put(&sbd.md.inum);
1423 70 : lgfs2_inode_put(&sbd.md.statfs);
1424 :
1425 70 : lgfs2_rgrps_free(&rgs);
1426 :
1427 70 : if (!opts.quiet) {
1428 70 : printf("%s", _("Writing superblock and syncing: "));
1429 70 : fflush(stdout);
1430 : }
1431 :
1432 70 : error = lgfs2_sb_write(&sbd, opts.dev.fd);
1433 70 : if (error) {
1434 0 : perror(_("Failed to write superblock\n"));
1435 0 : exit(EXIT_FAILURE);
1436 : }
1437 :
1438 70 : error = fsync(opts.dev.fd);
1439 70 : if (error){
1440 0 : perror(opts.dev.path);
1441 0 : exit(EXIT_FAILURE);
1442 : }
1443 70 : error = close(opts.dev.fd);
1444 70 : if (error){
1445 0 : perror(opts.dev.path);
1446 0 : exit(EXIT_FAILURE);
1447 : }
1448 :
1449 70 : if (!opts.quiet) {
1450 70 : printf("%s", _("Done\n"));
1451 70 : print_results(&sbd, &opts);
1452 : }
1453 70 : return 0;
1454 : }
1455 : #endif /* UNITTESTS */
|