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