]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - mkfs/xfs_mkfs.c
mkfs: factor sector subopts parser
[thirdparty/xfsprogs-dev.git] / mkfs / xfs_mkfs.c
1 /*
2 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 #include "libfrog.h"
19 #include "libxfs.h"
20 #include <ctype.h>
21 #include "xfs_multidisk.h"
22 #include "libxcmd.h"
23
24 /*
25 * Prototypes for internal functions.
26 */
27 static void conflict(char opt, const char *tab[], int oldidx, int newidx);
28 static void illegal(const char *value, const char *opt);
29 static __attribute__((noreturn)) void usage (void);
30 static __attribute__((noreturn)) void reqval(char opt, const char *tab[], int idx);
31 static void respec(char opt, const char *tab[], int idx);
32 static void unknown(char opt, char *s);
33 static int ispow2(unsigned int i);
34
35 /*
36 * The configured block and sector sizes are defined as global variables so
37 * that they don't need to be passed to functions that require them.
38 */
39 unsigned int blocksize;
40 unsigned int sectorsize;
41
42 #define MAX_SUBOPTS 17
43 #define SUBOPT_NEEDS_VAL (-1LL)
44 #define MAX_CONFLICTS 8
45 #define LAST_CONFLICT (-1)
46
47 /*
48 * Table for parsing mkfs parameters.
49 *
50 * Description of the structure members follows:
51 *
52 * name MANDATORY
53 * Name is a single char, e.g., for '-d file', name is 'd'.
54 *
55 * subopts MANDATORY
56 * Subopts is a list of strings naming suboptions. In the example above,
57 * it would contain "file". The last entry of this list has to be NULL.
58 *
59 * subopt_params MANDATORY
60 * This is a list of structs tied with subopts. For each entry in subopts,
61 * a corresponding entry has to be defined:
62 *
63 * subopt_params struct:
64 * index MANDATORY
65 * This number, starting from zero, denotes which item in subopt_params
66 * it is. The index has to be the same as is the order in subopts list,
67 * so we can access the right item both in subopt_param and subopts.
68 *
69 * seen INTERNAL
70 * Do not set this flag when definning a subopt. It is used to remeber that
71 * this subopt was already seen, for example for conflicts detection.
72 *
73 * str_seen INTERNAL
74 * Do not set. It is used internally for respecification, when some options
75 * has to be parsed twice - at first as a string, then later as a number.
76 *
77 * convert OPTIONAL
78 * A flag signalling whether the user-given value can use suffixes.
79 * If you want to allow the use of user-friendly values like 13k, 42G,
80 * set it to true.
81 *
82 * is_power_2 OPTIONAL
83 * An optional flag for subopts where the given value has to be a power
84 * of two.
85 *
86 * conflicts MANDATORY
87 * If your subopt is in a conflict with some other option, specify it.
88 * Accepts the .index values of the conflicting subopts and the last
89 * member of this list has to be LAST_CONFLICT.
90 *
91 * minval, maxval OPTIONAL
92 * These options are used for automatic range check and they have to be
93 * always used together in pair. If you don't want to limit the max value,
94 * use something like UINT_MAX. If no value is given, then you must either
95 * supply your own validation, or refuse any value in the 'case
96 * X_SOMETHING' block. If you forget to define the min and max value, but
97 * call a standard function for validating user's value, it will cause an
98 * error message notifying you about this issue.
99 *
100 * (Said in another way, you can't have minval and maxval both equal
101 * to zero. But if one value is different: minval=0 and maxval=1,
102 * then it is OK.)
103 *
104 * defaultval MANDATORY
105 * The value used if user specifies the subopt, but no value.
106 * If the subopt accepts some values (-d file=[1|0]), then this
107 * sets what is used with simple specifying the subopt (-d file).
108 * A special SUBOPT_NEEDS_VAL can be used to require a user-given
109 * value in any case.
110 */
111 struct opt_params {
112 const char name;
113 const char *subopts[MAX_SUBOPTS];
114
115 struct subopt_param {
116 int index;
117 bool seen;
118 bool str_seen;
119 bool convert;
120 bool is_power_2;
121 int conflicts[MAX_CONFLICTS];
122 long long minval;
123 long long maxval;
124 long long defaultval;
125 } subopt_params[MAX_SUBOPTS];
126 };
127
128 struct opt_params bopts = {
129 .name = 'b',
130 .subopts = {
131 #define B_LOG 0
132 "log",
133 #define B_SIZE 1
134 "size",
135 NULL
136 },
137 .subopt_params = {
138 { .index = B_LOG,
139 .conflicts = { B_SIZE,
140 LAST_CONFLICT },
141 .minval = XFS_MIN_BLOCKSIZE_LOG,
142 .maxval = XFS_MAX_BLOCKSIZE_LOG,
143 .defaultval = SUBOPT_NEEDS_VAL,
144 },
145 { .index = B_SIZE,
146 .convert = true,
147 .is_power_2 = true,
148 .conflicts = { B_LOG,
149 LAST_CONFLICT },
150 .minval = XFS_MIN_BLOCKSIZE,
151 .maxval = XFS_MAX_BLOCKSIZE,
152 .defaultval = SUBOPT_NEEDS_VAL,
153 },
154 },
155 };
156
157 struct opt_params dopts = {
158 .name = 'd',
159 .subopts = {
160 #define D_AGCOUNT 0
161 "agcount",
162 #define D_FILE 1
163 "file",
164 #define D_NAME 2
165 "name",
166 #define D_SIZE 3
167 "size",
168 #define D_SUNIT 4
169 "sunit",
170 #define D_SWIDTH 5
171 "swidth",
172 #define D_AGSIZE 6
173 "agsize",
174 #define D_SU 7
175 "su",
176 #define D_SW 8
177 "sw",
178 #define D_SECTLOG 9
179 "sectlog",
180 #define D_SECTSIZE 10
181 "sectsize",
182 #define D_NOALIGN 11
183 "noalign",
184 #define D_RTINHERIT 12
185 "rtinherit",
186 #define D_PROJINHERIT 13
187 "projinherit",
188 #define D_EXTSZINHERIT 14
189 "extszinherit",
190 #define D_COWEXTSIZE 15
191 "cowextsize",
192 NULL
193 },
194 .subopt_params = {
195 { .index = D_AGCOUNT,
196 .conflicts = { D_AGSIZE,
197 LAST_CONFLICT },
198 .minval = 1,
199 .maxval = XFS_MAX_AGNUMBER,
200 .defaultval = SUBOPT_NEEDS_VAL,
201 },
202 { .index = D_FILE,
203 .conflicts = { LAST_CONFLICT },
204 .minval = 0,
205 .maxval = 1,
206 .defaultval = 1,
207 },
208 { .index = D_NAME,
209 .conflicts = { LAST_CONFLICT },
210 .defaultval = SUBOPT_NEEDS_VAL,
211 },
212 { .index = D_SIZE,
213 .conflicts = { LAST_CONFLICT },
214 .convert = true,
215 .minval = XFS_AG_MIN_BYTES,
216 .maxval = LLONG_MAX,
217 .defaultval = SUBOPT_NEEDS_VAL,
218 },
219 { .index = D_SUNIT,
220 .conflicts = { D_NOALIGN,
221 D_SU,
222 D_SW,
223 LAST_CONFLICT },
224 .minval = 0,
225 .maxval = UINT_MAX,
226 .defaultval = SUBOPT_NEEDS_VAL,
227 },
228 { .index = D_SWIDTH,
229 .conflicts = { D_NOALIGN,
230 D_SU,
231 D_SW,
232 LAST_CONFLICT },
233 .minval = 0,
234 .maxval = UINT_MAX,
235 .defaultval = SUBOPT_NEEDS_VAL,
236 },
237 { .index = D_AGSIZE,
238 .conflicts = { D_AGCOUNT,
239 LAST_CONFLICT },
240 .convert = true,
241 .minval = XFS_AG_MIN_BYTES,
242 .maxval = XFS_AG_MAX_BYTES,
243 .defaultval = SUBOPT_NEEDS_VAL,
244 },
245 { .index = D_SU,
246 .conflicts = { D_NOALIGN,
247 D_SUNIT,
248 D_SWIDTH,
249 LAST_CONFLICT },
250 .convert = true,
251 .minval = 0,
252 .maxval = UINT_MAX,
253 .defaultval = SUBOPT_NEEDS_VAL,
254 },
255 { .index = D_SW,
256 .conflicts = { D_NOALIGN,
257 D_SUNIT,
258 D_SWIDTH,
259 LAST_CONFLICT },
260 .minval = 0,
261 .maxval = UINT_MAX,
262 .defaultval = SUBOPT_NEEDS_VAL,
263 },
264 { .index = D_SECTLOG,
265 .conflicts = { D_SECTSIZE,
266 LAST_CONFLICT },
267 .minval = XFS_MIN_SECTORSIZE_LOG,
268 .maxval = XFS_MAX_SECTORSIZE_LOG,
269 .defaultval = SUBOPT_NEEDS_VAL,
270 },
271 { .index = D_SECTSIZE,
272 .conflicts = { D_SECTLOG,
273 LAST_CONFLICT },
274 .convert = true,
275 .is_power_2 = true,
276 .minval = XFS_MIN_SECTORSIZE,
277 .maxval = XFS_MAX_SECTORSIZE,
278 .defaultval = SUBOPT_NEEDS_VAL,
279 },
280 { .index = D_NOALIGN,
281 .conflicts = { D_SU,
282 D_SW,
283 D_SUNIT,
284 D_SWIDTH,
285 LAST_CONFLICT },
286 .minval = 0,
287 .maxval = 1,
288 .defaultval = 1,
289 },
290 { .index = D_RTINHERIT,
291 .conflicts = { LAST_CONFLICT },
292 .minval = 1,
293 .maxval = 1,
294 .defaultval = 1,
295 },
296 { .index = D_PROJINHERIT,
297 .conflicts = { LAST_CONFLICT },
298 .minval = 0,
299 .maxval = UINT_MAX,
300 .defaultval = SUBOPT_NEEDS_VAL,
301 },
302 { .index = D_EXTSZINHERIT,
303 .conflicts = { LAST_CONFLICT },
304 .minval = 0,
305 .maxval = UINT_MAX,
306 .defaultval = SUBOPT_NEEDS_VAL,
307 },
308 { .index = D_COWEXTSIZE,
309 .conflicts = { LAST_CONFLICT },
310 .minval = 0,
311 .maxval = UINT_MAX,
312 .defaultval = SUBOPT_NEEDS_VAL,
313 },
314 },
315 };
316
317
318 struct opt_params iopts = {
319 .name = 'i',
320 .subopts = {
321 #define I_ALIGN 0
322 "align",
323 #define I_LOG 1
324 "log",
325 #define I_MAXPCT 2
326 "maxpct",
327 #define I_PERBLOCK 3
328 "perblock",
329 #define I_SIZE 4
330 "size",
331 #define I_ATTR 5
332 "attr",
333 #define I_PROJID32BIT 6
334 "projid32bit",
335 #define I_SPINODES 7
336 "sparse",
337 NULL
338 },
339 .subopt_params = {
340 { .index = I_ALIGN,
341 .conflicts = { LAST_CONFLICT },
342 .minval = 0,
343 .maxval = 1,
344 .defaultval = 1,
345 },
346 { .index = I_LOG,
347 .conflicts = { I_PERBLOCK,
348 I_SIZE,
349 LAST_CONFLICT },
350 .minval = XFS_DINODE_MIN_LOG,
351 .maxval = XFS_DINODE_MAX_LOG,
352 .defaultval = SUBOPT_NEEDS_VAL,
353 },
354 { .index = I_MAXPCT,
355 .conflicts = { LAST_CONFLICT },
356 .minval = 0,
357 .maxval = 100,
358 .defaultval = SUBOPT_NEEDS_VAL,
359 },
360 { .index = I_PERBLOCK,
361 .conflicts = { I_LOG,
362 I_SIZE,
363 LAST_CONFLICT },
364 .is_power_2 = true,
365 .minval = XFS_MIN_INODE_PERBLOCK,
366 .maxval = XFS_MAX_BLOCKSIZE / XFS_DINODE_MIN_SIZE,
367 .defaultval = SUBOPT_NEEDS_VAL,
368 },
369 { .index = I_SIZE,
370 .conflicts = { I_PERBLOCK,
371 I_LOG,
372 LAST_CONFLICT },
373 .is_power_2 = true,
374 .minval = XFS_DINODE_MIN_SIZE,
375 .maxval = XFS_DINODE_MAX_SIZE,
376 .defaultval = SUBOPT_NEEDS_VAL,
377 },
378 { .index = I_ATTR,
379 .conflicts = { LAST_CONFLICT },
380 .minval = 0,
381 .maxval = 2,
382 .defaultval = SUBOPT_NEEDS_VAL,
383 },
384 { .index = I_PROJID32BIT,
385 .conflicts = { LAST_CONFLICT },
386 .minval = 0,
387 .maxval = 1,
388 .defaultval = 1,
389 },
390 { .index = I_SPINODES,
391 .conflicts = { LAST_CONFLICT },
392 .minval = 0,
393 .maxval = 1,
394 .defaultval = 1,
395 },
396 },
397 };
398
399 struct opt_params lopts = {
400 .name = 'l',
401 .subopts = {
402 #define L_AGNUM 0
403 "agnum",
404 #define L_INTERNAL 1
405 "internal",
406 #define L_SIZE 2
407 "size",
408 #define L_VERSION 3
409 "version",
410 #define L_SUNIT 4
411 "sunit",
412 #define L_SU 5
413 "su",
414 #define L_DEV 6
415 "logdev",
416 #define L_SECTLOG 7
417 "sectlog",
418 #define L_SECTSIZE 8
419 "sectsize",
420 #define L_FILE 9
421 "file",
422 #define L_NAME 10
423 "name",
424 #define L_LAZYSBCNTR 11
425 "lazy-count",
426 NULL
427 },
428 .subopt_params = {
429 { .index = L_AGNUM,
430 .conflicts = { L_DEV,
431 LAST_CONFLICT },
432 .minval = 0,
433 .maxval = UINT_MAX,
434 .defaultval = SUBOPT_NEEDS_VAL,
435 },
436 { .index = L_INTERNAL,
437 .conflicts = { L_FILE,
438 L_DEV,
439 L_SECTLOG,
440 L_SECTSIZE,
441 LAST_CONFLICT },
442 .minval = 0,
443 .maxval = 1,
444 .defaultval = 1,
445 },
446 { .index = L_SIZE,
447 .conflicts = { LAST_CONFLICT },
448 .convert = true,
449 .minval = 2 * 1024 * 1024LL, /* XXX: XFS_MIN_LOG_BYTES */
450 .maxval = XFS_MAX_LOG_BYTES,
451 .defaultval = SUBOPT_NEEDS_VAL,
452 },
453 { .index = L_VERSION,
454 .conflicts = { LAST_CONFLICT },
455 .minval = 1,
456 .maxval = 2,
457 .defaultval = SUBOPT_NEEDS_VAL,
458 },
459 { .index = L_SUNIT,
460 .conflicts = { L_SU,
461 LAST_CONFLICT },
462 .minval = 1,
463 .maxval = BTOBB(XLOG_MAX_RECORD_BSIZE),
464 .defaultval = SUBOPT_NEEDS_VAL,
465 },
466 { .index = L_SU,
467 .conflicts = { L_SUNIT,
468 LAST_CONFLICT },
469 .convert = true,
470 .minval = BBTOB(1),
471 .maxval = XLOG_MAX_RECORD_BSIZE,
472 .defaultval = SUBOPT_NEEDS_VAL,
473 },
474 { .index = L_DEV,
475 .conflicts = { L_AGNUM,
476 L_INTERNAL,
477 LAST_CONFLICT },
478 .defaultval = SUBOPT_NEEDS_VAL,
479 },
480 { .index = L_SECTLOG,
481 .conflicts = { L_SECTSIZE,
482 L_INTERNAL,
483 LAST_CONFLICT },
484 .minval = XFS_MIN_SECTORSIZE_LOG,
485 .maxval = XFS_MAX_SECTORSIZE_LOG,
486 .defaultval = SUBOPT_NEEDS_VAL,
487 },
488 { .index = L_SECTSIZE,
489 .conflicts = { L_SECTLOG,
490 L_INTERNAL,
491 LAST_CONFLICT },
492 .convert = true,
493 .is_power_2 = true,
494 .minval = XFS_MIN_SECTORSIZE,
495 .maxval = XFS_MAX_SECTORSIZE,
496 .defaultval = SUBOPT_NEEDS_VAL,
497 },
498 { .index = L_FILE,
499 .conflicts = { L_INTERNAL,
500 LAST_CONFLICT },
501 .minval = 0,
502 .maxval = 1,
503 .defaultval = 1,
504 },
505 { .index = L_NAME,
506 .conflicts = { L_AGNUM,
507 L_INTERNAL,
508 LAST_CONFLICT },
509 .defaultval = SUBOPT_NEEDS_VAL,
510 },
511 { .index = L_LAZYSBCNTR,
512 .conflicts = { LAST_CONFLICT },
513 .minval = 0,
514 .maxval = 1,
515 .defaultval = 1,
516 },
517 },
518 };
519
520 struct opt_params nopts = {
521 .name = 'n',
522 .subopts = {
523 #define N_LOG 0
524 "log",
525 #define N_SIZE 1
526 "size",
527 #define N_VERSION 2
528 "version",
529 #define N_FTYPE 3
530 "ftype",
531 NULL,
532 },
533 .subopt_params = {
534 { .index = N_LOG,
535 .conflicts = { N_SIZE,
536 LAST_CONFLICT },
537 .minval = XFS_MIN_REC_DIRSIZE,
538 .maxval = XFS_MAX_BLOCKSIZE_LOG,
539 .defaultval = SUBOPT_NEEDS_VAL,
540 },
541 { .index = N_SIZE,
542 .conflicts = { N_LOG,
543 LAST_CONFLICT },
544 .convert = true,
545 .is_power_2 = true,
546 .minval = 1 << XFS_MIN_REC_DIRSIZE,
547 .maxval = XFS_MAX_BLOCKSIZE,
548 .defaultval = SUBOPT_NEEDS_VAL,
549 },
550 { .index = N_VERSION,
551 .conflicts = { LAST_CONFLICT },
552 .minval = 2,
553 .maxval = 2,
554 .defaultval = SUBOPT_NEEDS_VAL,
555 },
556 { .index = N_FTYPE,
557 .conflicts = { LAST_CONFLICT },
558 .minval = 0,
559 .maxval = 1,
560 .defaultval = 1,
561 },
562 },
563 };
564
565 struct opt_params ropts = {
566 .name = 'r',
567 .subopts = {
568 #define R_EXTSIZE 0
569 "extsize",
570 #define R_SIZE 1
571 "size",
572 #define R_DEV 2
573 "rtdev",
574 #define R_FILE 3
575 "file",
576 #define R_NAME 4
577 "name",
578 #define R_NOALIGN 5
579 "noalign",
580 NULL
581 },
582 .subopt_params = {
583 { .index = R_EXTSIZE,
584 .conflicts = { LAST_CONFLICT },
585 .convert = true,
586 .minval = XFS_MIN_RTEXTSIZE,
587 .maxval = XFS_MAX_RTEXTSIZE,
588 .defaultval = SUBOPT_NEEDS_VAL,
589 },
590 { .index = R_SIZE,
591 .conflicts = { LAST_CONFLICT },
592 .convert = true,
593 .minval = 0,
594 .maxval = LLONG_MAX,
595 .defaultval = SUBOPT_NEEDS_VAL,
596 },
597 { .index = R_DEV,
598 .conflicts = { LAST_CONFLICT },
599 .defaultval = SUBOPT_NEEDS_VAL,
600 },
601 { .index = R_FILE,
602 .minval = 0,
603 .maxval = 1,
604 .defaultval = 1,
605 .conflicts = { LAST_CONFLICT },
606 },
607 { .index = R_NAME,
608 .conflicts = { LAST_CONFLICT },
609 .defaultval = SUBOPT_NEEDS_VAL,
610 },
611 { .index = R_NOALIGN,
612 .minval = 0,
613 .maxval = 1,
614 .defaultval = 1,
615 .conflicts = { LAST_CONFLICT },
616 },
617 },
618 };
619
620 struct opt_params sopts = {
621 .name = 's',
622 .subopts = {
623 #define S_LOG 0
624 "log",
625 #define S_SECTLOG 1
626 "sectlog",
627 #define S_SIZE 2
628 "size",
629 #define S_SECTSIZE 3
630 "sectsize",
631 NULL
632 },
633 .subopt_params = {
634 { .index = S_LOG,
635 .conflicts = { S_SIZE,
636 S_SECTSIZE,
637 LAST_CONFLICT },
638 .minval = XFS_MIN_SECTORSIZE_LOG,
639 .maxval = XFS_MAX_SECTORSIZE_LOG,
640 .defaultval = SUBOPT_NEEDS_VAL,
641 },
642 { .index = S_SECTLOG,
643 .conflicts = { S_SIZE,
644 S_SECTSIZE,
645 LAST_CONFLICT },
646 .minval = XFS_MIN_SECTORSIZE_LOG,
647 .maxval = XFS_MAX_SECTORSIZE_LOG,
648 .defaultval = SUBOPT_NEEDS_VAL,
649 },
650 { .index = S_SIZE,
651 .conflicts = { S_LOG,
652 S_SECTLOG,
653 LAST_CONFLICT },
654 .convert = true,
655 .is_power_2 = true,
656 .minval = XFS_MIN_SECTORSIZE,
657 .maxval = XFS_MAX_SECTORSIZE,
658 .defaultval = SUBOPT_NEEDS_VAL,
659 },
660 { .index = S_SECTSIZE,
661 .conflicts = { S_LOG,
662 S_SECTLOG,
663 LAST_CONFLICT },
664 .convert = true,
665 .is_power_2 = true,
666 .minval = XFS_MIN_SECTORSIZE,
667 .maxval = XFS_MAX_SECTORSIZE,
668 .defaultval = SUBOPT_NEEDS_VAL,
669 },
670 },
671 };
672
673 struct opt_params mopts = {
674 .name = 'm',
675 .subopts = {
676 #define M_CRC 0
677 "crc",
678 #define M_FINOBT 1
679 "finobt",
680 #define M_UUID 2
681 "uuid",
682 #define M_RMAPBT 3
683 "rmapbt",
684 #define M_REFLINK 4
685 "reflink",
686 NULL
687 },
688 .subopt_params = {
689 { .index = M_CRC,
690 .conflicts = { LAST_CONFLICT },
691 .minval = 0,
692 .maxval = 1,
693 .defaultval = 1,
694 },
695 { .index = M_FINOBT,
696 .conflicts = { LAST_CONFLICT },
697 .minval = 0,
698 .maxval = 1,
699 .defaultval = 1,
700 },
701 { .index = M_UUID,
702 .conflicts = { LAST_CONFLICT },
703 .defaultval = SUBOPT_NEEDS_VAL,
704 },
705 { .index = M_RMAPBT,
706 .conflicts = { LAST_CONFLICT },
707 .minval = 0,
708 .maxval = 1,
709 .defaultval = 1,
710 },
711 { .index = M_REFLINK,
712 .conflicts = { LAST_CONFLICT },
713 .minval = 0,
714 .maxval = 1,
715 .defaultval = 1,
716 },
717 },
718 };
719
720 /* quick way of checking if a parameter was set on the CLI */
721 static bool
722 cli_opt_set(
723 struct opt_params *opts,
724 int subopt)
725 {
726 return opts->subopt_params[subopt].seen ||
727 opts->subopt_params[subopt].str_seen;
728 }
729
730 /*
731 * Options configured on the command line.
732 *
733 * This stores all the specific config parameters the user sets on the command
734 * line. We do not use these values directly - they are inputs to the mkfs
735 * geometry validation and override any default configuration value we have.
736 *
737 * We don't keep flags to indicate what parameters are set - if we need to check
738 * if an option was set on teh command line, we check the relevant entry in the
739 * option table which records whether it was specified in the .seen and
740 * .str_seen variables in the table.
741 *
742 * Some parameters are stored as strings for post-parsing after their dependent
743 * options have been resolved (e.g. block size and sector size have been parsed
744 * and validated).
745 *
746 * This allows us to check that values have been set without needing separate
747 * flags for each value, and hence avoids needing to record and check for each
748 * specific option that can set the value later on in the code. In the cases
749 * where we don't have a cli_params structure around, the above cli_opt_set()
750 * function can be used.
751 */
752 struct sb_feat_args {
753 int log_version;
754 int attr_version;
755 int dir_version;
756 bool inode_align;
757 bool nci;
758 bool lazy_sb_counters;
759 bool projid16bit;
760 bool crcs_enabled;
761 bool dirftype;
762 bool finobt;
763 bool spinodes;
764 bool rmapbt;
765 bool reflink;
766 bool parent_pointers;
767 bool nodalign;
768 bool nortalign;
769 uuid_t m_uuid;
770 };
771
772 struct cli_params {
773 int sectorsize;
774 int blocksize;
775
776 /* parameters that depend on sector/block size being validated. */
777 char *dsize;
778 char *agsize;
779 char *dsu;
780 char *dirblocksize;
781 char *logsize;
782 char *lsu;
783 char *rtextsize;
784 char *rtsize;
785
786 /* parameters where 0 is a valid CLI value */
787 int dsunit;
788 int dswidth;
789 int dsw;
790 int64_t logagno;
791 int loginternal;
792 int lsunit;
793
794 /* parameters where 0 is not a valid value */
795 int64_t agcount;
796 int dirblocklog;
797 int inodesize;
798 int inopblock;
799 int imaxpct;
800 int lsectorsize;
801 uuid_t uuid;
802
803 /* feature flags that are set */
804 struct sb_feat_args sb_feat;
805
806 /* root inode characteristics */
807 struct fsxattr fsx;
808
809 /* libxfs device setup */
810 struct libxfs_xinit *xi;
811 };
812
813 #define TERABYTES(count, blog) ((uint64_t)(count) << (40 - (blog)))
814 #define GIGABYTES(count, blog) ((uint64_t)(count) << (30 - (blog)))
815 #define MEGABYTES(count, blog) ((uint64_t)(count) << (20 - (blog)))
816
817 /*
818 * Use this macro before we have superblock and mount structure
819 */
820 #define DTOBT(d) ((xfs_rfsblock_t)((d) >> (blocklog - BBSHIFT)))
821
822 /*
823 * Use this for block reservations needed for mkfs's conditions
824 * (basically no fragmentation).
825 */
826 #define MKFS_BLOCKRES_INODE \
827 ((uint)(mp->m_ialloc_blks + (mp->m_in_maxlevels - 1)))
828 #define MKFS_BLOCKRES(rb) \
829 ((uint)(MKFS_BLOCKRES_INODE + XFS_DA_NODE_MAXDEPTH + \
830 (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1) + (rb)))
831
832 /* amount (in bytes) we zero at the beginning and end of the device to
833 * remove traces of other filesystems, raid superblocks, etc.
834 */
835 #define WHACK_SIZE (128 * 1024)
836
837 /*
838 * Convert lsu to lsunit for 512 bytes blocks and check validity of the values.
839 */
840 static void
841 calc_stripe_factors(
842 int dsu,
843 int dsw,
844 int dsectsz,
845 int lsu,
846 int lsectsz,
847 int *dsunit,
848 int *dswidth,
849 int *lsunit)
850 {
851 /* Handle data sunit/swidth options */
852 if ((*dsunit && !*dswidth) || (!*dsunit && *dswidth)) {
853 fprintf(stderr,
854 _("both data sunit and data swidth options "
855 "must be specified\n"));
856 usage();
857 }
858
859 if (dsu || dsw) {
860 if ((dsu && !dsw) || (!dsu && dsw)) {
861 fprintf(stderr,
862 _("both data su and data sw options "
863 "must be specified\n"));
864 usage();
865 }
866
867 if (dsu % dsectsz) {
868 fprintf(stderr,
869 _("data su must be a multiple of the "
870 "sector size (%d)\n"), dsectsz);
871 usage();
872 }
873
874 *dsunit = (int)BTOBBT(dsu);
875 *dswidth = *dsunit * dsw;
876 }
877
878 if (*dsunit && (*dswidth % *dsunit != 0)) {
879 fprintf(stderr,
880 _("data stripe width (%d) must be a multiple of the "
881 "data stripe unit (%d)\n"), *dswidth, *dsunit);
882 usage();
883 }
884
885 /* Handle log sunit options */
886
887 if (lsu)
888 *lsunit = (int)BTOBBT(lsu);
889
890 /* verify if lsu/lsunit is a multiple block size */
891 if (lsu % blocksize != 0) {
892 fprintf(stderr,
893 _("log stripe unit (%d) must be a multiple of the block size (%d)\n"),
894 lsu, blocksize);
895 exit(1);
896 }
897 if ((BBTOB(*lsunit) % blocksize != 0)) {
898 fprintf(stderr,
899 _("log stripe unit (%d) must be a multiple of the block size (%d)\n"),
900 BBTOB(*lsunit), blocksize);
901 exit(1);
902 }
903 }
904
905 static void
906 check_device_type(
907 const char *name,
908 int *isfile,
909 bool no_size,
910 bool no_name,
911 int *create,
912 bool force_overwrite,
913 const char *optname)
914 {
915 struct stat statbuf;
916
917 if (*isfile && (no_size || no_name)) {
918 fprintf(stderr,
919 _("if -%s file then -%s name and -%s size are required\n"),
920 optname, optname, optname);
921 usage();
922 }
923
924 if (!name) {
925 fprintf(stderr, _("No device name specified\n"));
926 usage();
927 }
928
929 if (stat(name, &statbuf)) {
930 if (errno == ENOENT && *isfile) {
931 if (create)
932 *create = 1;
933 return;
934 }
935
936 fprintf(stderr,
937 _("Error accessing specified device %s: %s\n"),
938 name, strerror(errno));
939 usage();
940 return;
941 }
942
943 if (!force_overwrite && check_overwrite(name)) {
944 fprintf(stderr,
945 _("%s: Use the -f option to force overwrite.\n"),
946 progname);
947 exit(1);
948 }
949
950 /*
951 * We only want to completely truncate and recreate an existing file if
952 * we were specifically told it was a file. Set the create flag only in
953 * this case to trigger that behaviour.
954 */
955 if (S_ISREG(statbuf.st_mode)) {
956 if (!*isfile)
957 *isfile = 1;
958 else if (create)
959 *create = 1;
960 return;
961 }
962
963 if (S_ISBLK(statbuf.st_mode)) {
964 if (*isfile) {
965 fprintf(stderr,
966 _("specified \"-%s file\" on a block device %s\n"),
967 optname, name);
968 usage();
969 }
970 return;
971 }
972
973 fprintf(stderr,
974 _("specified device %s not a file or block device\n"),
975 name);
976 usage();
977 }
978
979 static void
980 fixup_log_stripe_unit(
981 int lsflag,
982 int sunit,
983 xfs_rfsblock_t *logblocks,
984 int blocklog)
985 {
986 uint64_t tmp_logblocks;
987
988 /*
989 * Make sure that the log size is a multiple of the stripe unit
990 */
991 if ((*logblocks % sunit) != 0) {
992 if (!lsflag) {
993 tmp_logblocks = ((*logblocks + (sunit - 1))
994 / sunit) * sunit;
995 /*
996 * If the log is too large, round down
997 * instead of round up
998 */
999 if ((tmp_logblocks > XFS_MAX_LOG_BLOCKS) ||
1000 ((tmp_logblocks << blocklog) > XFS_MAX_LOG_BYTES)) {
1001 tmp_logblocks = (*logblocks / sunit) * sunit;
1002 }
1003 *logblocks = tmp_logblocks;
1004 } else {
1005 fprintf(stderr, _("log size %lld is not a multiple "
1006 "of the log stripe unit %d\n"),
1007 (long long) *logblocks, sunit);
1008 usage();
1009 }
1010 }
1011 }
1012
1013 static xfs_fsblock_t
1014 fixup_internal_log_stripe(
1015 xfs_mount_t *mp,
1016 int lsflag,
1017 xfs_fsblock_t logstart,
1018 uint64_t agsize,
1019 int sunit,
1020 xfs_rfsblock_t *logblocks,
1021 int blocklog,
1022 int *lalign)
1023 {
1024 if ((logstart % sunit) != 0) {
1025 logstart = ((logstart + (sunit - 1))/sunit) * sunit;
1026 *lalign = 1;
1027 }
1028
1029 fixup_log_stripe_unit(lsflag, sunit, logblocks, blocklog);
1030
1031 if (*logblocks > agsize - XFS_FSB_TO_AGBNO(mp, logstart)) {
1032 fprintf(stderr,
1033 _("Due to stripe alignment, the internal log size "
1034 "(%lld) is too large.\n"), (long long) *logblocks);
1035 fprintf(stderr, _("Must fit within an allocation group.\n"));
1036 usage();
1037 }
1038 return logstart;
1039 }
1040
1041 void
1042 validate_log_size(uint64_t logblocks, int blocklog, int min_logblocks)
1043 {
1044 if (logblocks < min_logblocks) {
1045 fprintf(stderr,
1046 _("log size %lld blocks too small, minimum size is %d blocks\n"),
1047 (long long)logblocks, min_logblocks);
1048 usage();
1049 }
1050 if (logblocks > XFS_MAX_LOG_BLOCKS) {
1051 fprintf(stderr,
1052 _("log size %lld blocks too large, maximum size is %lld blocks\n"),
1053 (long long)logblocks, XFS_MAX_LOG_BLOCKS);
1054 usage();
1055 }
1056 if ((logblocks << blocklog) > XFS_MAX_LOG_BYTES) {
1057 fprintf(stderr,
1058 _("log size %lld bytes too large, maximum size is %lld bytes\n"),
1059 (long long)(logblocks << blocklog), XFS_MAX_LOG_BYTES);
1060 usage();
1061 }
1062 }
1063
1064 static int
1065 calc_default_imaxpct(
1066 int blocklog,
1067 uint64_t dblocks)
1068 {
1069 /*
1070 * This returns the % of the disk space that is used for
1071 * inodes, it changes relatively to the FS size:
1072 * - over 50 TB, use 1%,
1073 * - 1TB - 50 TB, use 5%,
1074 * - under 1 TB, use XFS_DFL_IMAXIMUM_PCT (25%).
1075 */
1076
1077 if (dblocks < TERABYTES(1, blocklog)) {
1078 return XFS_DFL_IMAXIMUM_PCT;
1079 } else if (dblocks < TERABYTES(50, blocklog)) {
1080 return 5;
1081 }
1082
1083 return 1;
1084 }
1085
1086 static void
1087 validate_ag_geometry(
1088 int blocklog,
1089 uint64_t dblocks,
1090 uint64_t agsize,
1091 uint64_t agcount)
1092 {
1093 if (agsize < XFS_AG_MIN_BLOCKS(blocklog)) {
1094 fprintf(stderr,
1095 _("agsize (%lld blocks) too small, need at least %lld blocks\n"),
1096 (long long)agsize,
1097 (long long)XFS_AG_MIN_BLOCKS(blocklog));
1098 usage();
1099 }
1100
1101 if (agsize > XFS_AG_MAX_BLOCKS(blocklog)) {
1102 fprintf(stderr,
1103 _("agsize (%lld blocks) too big, maximum is %lld blocks\n"),
1104 (long long)agsize,
1105 (long long)XFS_AG_MAX_BLOCKS(blocklog));
1106 usage();
1107 }
1108
1109 if (agsize > dblocks) {
1110 fprintf(stderr,
1111 _("agsize (%lld blocks) too big, data area is %lld blocks\n"),
1112 (long long)agsize, (long long)dblocks);
1113 usage();
1114 }
1115
1116 if (agsize < XFS_AG_MIN_BLOCKS(blocklog)) {
1117 fprintf(stderr,
1118 _("too many allocation groups for size = %lld\n"),
1119 (long long)agsize);
1120 fprintf(stderr, _("need at most %lld allocation groups\n"),
1121 (long long)(dblocks / XFS_AG_MIN_BLOCKS(blocklog) +
1122 (dblocks % XFS_AG_MIN_BLOCKS(blocklog) != 0)));
1123 usage();
1124 }
1125
1126 if (agsize > XFS_AG_MAX_BLOCKS(blocklog)) {
1127 fprintf(stderr,
1128 _("too few allocation groups for size = %lld\n"), (long long)agsize);
1129 fprintf(stderr,
1130 _("need at least %lld allocation groups\n"),
1131 (long long)(dblocks / XFS_AG_MAX_BLOCKS(blocklog) +
1132 (dblocks % XFS_AG_MAX_BLOCKS(blocklog) != 0)));
1133 usage();
1134 }
1135
1136 /*
1137 * If the last AG is too small, reduce the filesystem size
1138 * and drop the blocks.
1139 */
1140 if ( dblocks % agsize != 0 &&
1141 (dblocks % agsize < XFS_AG_MIN_BLOCKS(blocklog))) {
1142 fprintf(stderr,
1143 _("last AG size %lld blocks too small, minimum size is %lld blocks\n"),
1144 (long long)(dblocks % agsize),
1145 (long long)XFS_AG_MIN_BLOCKS(blocklog));
1146 usage();
1147 }
1148
1149 /*
1150 * If agcount is too large, make it smaller.
1151 */
1152 if (agcount > XFS_MAX_AGNUMBER + 1) {
1153 fprintf(stderr,
1154 _("%lld allocation groups is too many, maximum is %lld\n"),
1155 (long long)agcount, (long long)XFS_MAX_AGNUMBER + 1);
1156 usage();
1157 }
1158 }
1159
1160 static void
1161 zero_old_xfs_structures(
1162 libxfs_init_t *xi,
1163 xfs_sb_t *new_sb)
1164 {
1165 void *buf;
1166 xfs_sb_t sb;
1167 uint32_t bsize;
1168 int i;
1169 xfs_off_t off;
1170
1171 /*
1172 * We open regular files with O_TRUNC|O_CREAT. Nothing to do here...
1173 */
1174 if (xi->disfile && xi->dcreat)
1175 return;
1176
1177 /*
1178 * read in existing filesystem superblock, use its geometry
1179 * settings and zero the existing secondary superblocks.
1180 */
1181 buf = memalign(libxfs_device_alignment(), new_sb->sb_sectsize);
1182 if (!buf) {
1183 fprintf(stderr,
1184 _("error reading existing superblock -- failed to memalign buffer\n"));
1185 return;
1186 }
1187 memset(buf, 0, new_sb->sb_sectsize);
1188
1189 /*
1190 * If we are creating an image file, it might be of zero length at this
1191 * point in time. Hence reading the existing superblock is going to
1192 * return zero bytes. It's not a failure we need to warn about in this
1193 * case.
1194 */
1195 off = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
1196 if (off != new_sb->sb_sectsize) {
1197 if (!xi->disfile)
1198 fprintf(stderr,
1199 _("error reading existing superblock: %s\n"),
1200 strerror(errno));
1201 goto done;
1202 }
1203 libxfs_sb_from_disk(&sb, buf);
1204
1205 /*
1206 * perform same basic superblock validation to make sure we
1207 * actually zero secondary blocks
1208 */
1209 if (sb.sb_magicnum != XFS_SB_MAGIC || sb.sb_blocksize == 0)
1210 goto done;
1211
1212 for (bsize = 1, i = 0; bsize < sb.sb_blocksize &&
1213 i < sizeof(sb.sb_blocksize) * NBBY; i++)
1214 bsize <<= 1;
1215
1216 if (i < XFS_MIN_BLOCKSIZE_LOG || i > XFS_MAX_BLOCKSIZE_LOG ||
1217 i != sb.sb_blocklog)
1218 goto done;
1219
1220 if (sb.sb_dblocks > ((uint64_t)sb.sb_agcount * sb.sb_agblocks) ||
1221 sb.sb_dblocks < ((uint64_t)(sb.sb_agcount - 1) *
1222 sb.sb_agblocks + XFS_MIN_AG_BLOCKS))
1223 goto done;
1224
1225 /*
1226 * block size and basic geometry seems alright, zero the secondaries.
1227 */
1228 memset(buf, 0, new_sb->sb_sectsize);
1229 off = 0;
1230 for (i = 1; i < sb.sb_agcount; i++) {
1231 off += sb.sb_agblocks;
1232 if (pwrite(xi->dfd, buf, new_sb->sb_sectsize,
1233 off << sb.sb_blocklog) == -1)
1234 break;
1235 }
1236 done:
1237 free(buf);
1238 }
1239
1240 static void
1241 discard_blocks(dev_t dev, uint64_t nsectors)
1242 {
1243 int fd;
1244
1245 /*
1246 * We intentionally ignore errors from the discard ioctl. It is
1247 * not necessary for the mkfs functionality but just an optimization.
1248 */
1249 fd = libxfs_device_to_fd(dev);
1250 if (fd > 0)
1251 platform_discard_blocks(fd, 0, nsectors << 9);
1252 }
1253
1254 static void
1255 sb_set_features(
1256 struct xfs_sb *sbp,
1257 struct sb_feat_args *fp,
1258 int sectsize,
1259 int lsectsize,
1260 int dsunit)
1261 {
1262
1263 sbp->sb_versionnum = XFS_DFL_SB_VERSION_BITS;
1264 if (fp->crcs_enabled)
1265 sbp->sb_versionnum |= XFS_SB_VERSION_5;
1266 else
1267 sbp->sb_versionnum |= XFS_SB_VERSION_4;
1268
1269 if (fp->inode_align)
1270 sbp->sb_versionnum |= XFS_SB_VERSION_ALIGNBIT;
1271 if (dsunit)
1272 sbp->sb_versionnum |= XFS_SB_VERSION_DALIGNBIT;
1273 if (fp->log_version == 2)
1274 sbp->sb_versionnum |= XFS_SB_VERSION_LOGV2BIT;
1275 if (fp->attr_version == 1)
1276 sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT;
1277 if (sectsize > BBSIZE || lsectsize > BBSIZE)
1278 sbp->sb_versionnum |= XFS_SB_VERSION_SECTORBIT;
1279 if (fp->nci)
1280 sbp->sb_versionnum |= XFS_SB_VERSION_BORGBIT;
1281
1282
1283 sbp->sb_features2 = 0;
1284 if (fp->lazy_sb_counters)
1285 sbp->sb_features2 |= XFS_SB_VERSION2_LAZYSBCOUNTBIT;
1286 if (!fp->projid16bit)
1287 sbp->sb_features2 |= XFS_SB_VERSION2_PROJID32BIT;
1288 if (fp->parent_pointers)
1289 sbp->sb_features2 |= XFS_SB_VERSION2_PARENTBIT;
1290 if (fp->crcs_enabled)
1291 sbp->sb_features2 |= XFS_SB_VERSION2_CRCBIT;
1292 if (fp->attr_version == 2)
1293 sbp->sb_features2 |= XFS_SB_VERSION2_ATTR2BIT;
1294
1295 /* v5 superblocks have their own feature bit for dirftype */
1296 if (fp->dirftype && !fp->crcs_enabled)
1297 sbp->sb_features2 |= XFS_SB_VERSION2_FTYPE;
1298
1299 /* update whether extended features are in use */
1300 if (sbp->sb_features2 != 0)
1301 sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT;
1302
1303 /*
1304 * Due to a structure alignment issue, sb_features2 ended up in one
1305 * of two locations, the second "incorrect" location represented by
1306 * the sb_bad_features2 field. To avoid older kernels mounting
1307 * filesystems they shouldn't, set both field to the same value.
1308 */
1309 sbp->sb_bad_features2 = sbp->sb_features2;
1310
1311 if (!fp->crcs_enabled)
1312 return;
1313
1314 /* default features for v5 filesystems */
1315 sbp->sb_features_compat = 0;
1316 sbp->sb_features_ro_compat = 0;
1317 sbp->sb_features_incompat = XFS_SB_FEAT_INCOMPAT_FTYPE;
1318 sbp->sb_features_log_incompat = 0;
1319
1320 if (fp->finobt)
1321 sbp->sb_features_ro_compat = XFS_SB_FEAT_RO_COMPAT_FINOBT;
1322 if (fp->rmapbt)
1323 sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_RMAPBT;
1324 if (fp->reflink)
1325 sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_REFLINK;
1326
1327 /*
1328 * Sparse inode chunk support has two main inode alignment requirements.
1329 * First, sparse chunk alignment must match the cluster size. Second,
1330 * full chunk alignment must match the inode chunk size.
1331 *
1332 * Copy the already calculated/scaled inoalignmt to spino_align and
1333 * update the former to the full inode chunk size.
1334 */
1335 if (fp->spinodes) {
1336 sbp->sb_spino_align = sbp->sb_inoalignmt;
1337 sbp->sb_inoalignmt = XFS_INODES_PER_CHUNK *
1338 sbp->sb_inodesize >> sbp->sb_blocklog;
1339 sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_SPINODES;
1340 }
1341
1342 }
1343
1344 static __attribute__((noreturn)) void
1345 illegal_option(
1346 const char *value,
1347 struct opt_params *opts,
1348 int index,
1349 const char *reason)
1350 {
1351 fprintf(stderr,
1352 _("Illegal value %s for -%c %s option. %s\n"),
1353 value, opts->name, opts->subopts[index],
1354 reason ? reason : "");
1355 usage();
1356 }
1357
1358 /*
1359 * Check for conflicts and option respecification.
1360 */
1361 static void
1362 check_opt(
1363 struct opt_params *opts,
1364 int index,
1365 bool str_seen)
1366 {
1367 struct subopt_param *sp = &opts->subopt_params[index];
1368 int i;
1369
1370 if (sp->index != index) {
1371 fprintf(stderr,
1372 _("Developer screwed up option parsing (%d/%d)! Please report!\n"),
1373 sp->index, index);
1374 reqval(opts->name, opts->subopts, index);
1375 }
1376
1377 /*
1378 * Check for respecification of the option. This is more complex than it
1379 * seems because some options are parsed twice - once as a string during
1380 * input parsing, then later the string is passed to getnum for
1381 * conversion into a number and bounds checking. Hence the two variables
1382 * used to track the different uses based on the @str parameter passed
1383 * to us.
1384 */
1385 if (!str_seen) {
1386 if (sp->seen)
1387 respec(opts->name, opts->subopts, index);
1388 sp->seen = true;
1389 } else {
1390 if (sp->str_seen)
1391 respec(opts->name, opts->subopts, index);
1392 sp->str_seen = true;
1393 }
1394
1395 /* check for conflicts with the option */
1396 for (i = 0; i < MAX_CONFLICTS; i++) {
1397 int conflict_opt = sp->conflicts[i];
1398
1399 if (conflict_opt == LAST_CONFLICT)
1400 break;
1401 if (opts->subopt_params[conflict_opt].seen ||
1402 opts->subopt_params[conflict_opt].str_seen)
1403 conflict(opts->name, opts->subopts,
1404 conflict_opt, index);
1405 }
1406 }
1407
1408 static long long
1409 getnum(
1410 const char *str,
1411 struct opt_params *opts,
1412 int index)
1413 {
1414 struct subopt_param *sp = &opts->subopt_params[index];
1415 long long c;
1416
1417 check_opt(opts, index, false);
1418 /* empty strings might just return a default value */
1419 if (!str || *str == '\0') {
1420 if (sp->defaultval == SUBOPT_NEEDS_VAL)
1421 reqval(opts->name, opts->subopts, index);
1422 return sp->defaultval;
1423 }
1424
1425 if (sp->minval == 0 && sp->maxval == 0) {
1426 fprintf(stderr,
1427 _("Option -%c %s has undefined minval/maxval."
1428 "Can't verify value range. This is a bug.\n"),
1429 opts->name, opts->subopts[index]);
1430 exit(1);
1431 }
1432
1433 /*
1434 * Some values are pure numbers, others can have suffixes that define
1435 * the units of the number. Those get passed to cvtnum(), otherwise we
1436 * convert it ourselves to guarantee there is no trailing garbage in the
1437 * number.
1438 */
1439 if (sp->convert)
1440 c = cvtnum(blocksize, sectorsize, str);
1441 else {
1442 char *str_end;
1443
1444 c = strtoll(str, &str_end, 0);
1445 if (c == 0 && str_end == str)
1446 illegal_option(str, opts, index, NULL);
1447 if (*str_end != '\0')
1448 illegal_option(str, opts, index, NULL);
1449 }
1450
1451 /* Validity check the result. */
1452 if (c < sp->minval)
1453 illegal_option(str, opts, index, _("value is too small"));
1454 else if (c > sp->maxval)
1455 illegal_option(str, opts, index, _("value is too large"));
1456 if (sp->is_power_2 && !ispow2(c))
1457 illegal_option(str, opts, index, _("value must be a power of 2"));
1458 return c;
1459 }
1460
1461 /*
1462 * Option is a string - do all the option table work, and check there
1463 * is actually an option string. Otherwise we don't do anything with the string
1464 * here - validation will be done later when the string is converted to a value
1465 * or used as a file/device path.
1466 */
1467 static char *
1468 getstr(
1469 char *str,
1470 struct opt_params *opts,
1471 int index)
1472 {
1473 check_opt(opts, index, true);
1474
1475 /* empty strings for string options are not valid */
1476 if (!str || *str == '\0')
1477 reqval(opts->name, opts->subopts, index);
1478 return str;
1479 }
1480
1481 static int
1482 block_opts_parser(
1483 struct opt_params *opts,
1484 int subopt,
1485 char *value,
1486 struct cli_params *cli)
1487 {
1488 int blocklog;
1489
1490 switch (subopt) {
1491 case B_LOG:
1492 blocklog = getnum(value, opts, B_LOG);
1493 cli->blocksize = 1 << blocklog;
1494 break;
1495 case B_SIZE:
1496 cli->blocksize = getnum(value, opts, B_SIZE);
1497 break;
1498 default:
1499 return -EINVAL;
1500 }
1501 return 0;
1502 }
1503
1504 static int
1505 data_opts_parser(
1506 struct opt_params *opts,
1507 int subopt,
1508 char *value,
1509 struct cli_params *cli)
1510 {
1511 int sectorlog;
1512
1513 switch (subopt) {
1514 case D_AGCOUNT:
1515 cli->agcount = getnum(value, opts, D_AGCOUNT);
1516 break;
1517 case D_AGSIZE:
1518 cli->agsize = getstr(value, opts, D_AGSIZE);
1519 break;
1520 case D_FILE:
1521 cli->xi->disfile = getnum(value, opts, D_FILE);
1522 break;
1523 case D_NAME:
1524 cli->xi->dname = getstr(value, opts, D_NAME);
1525 break;
1526 case D_SIZE:
1527 cli->dsize = getstr(value, opts, D_SIZE);
1528 break;
1529 case D_SUNIT:
1530 cli->dsunit = getnum(value, opts, D_SUNIT);
1531 break;
1532 case D_SWIDTH:
1533 cli->dswidth = getnum(value, opts, D_SWIDTH);
1534 break;
1535 case D_SU:
1536 cli->dsu = getstr(value, opts, D_SU);
1537 break;
1538 case D_SW:
1539 cli->dsw = getnum(value, opts, D_SW);
1540 break;
1541 case D_NOALIGN:
1542 cli->sb_feat.nodalign = getnum(value, opts, D_NOALIGN);
1543 break;
1544 case D_SECTLOG:
1545 if (cli->sectorsize)
1546 conflict('d', opts->subopts, D_SECTSIZE, D_SECTLOG);
1547 sectorlog = getnum(value, opts, D_SECTLOG);
1548 cli->sectorsize = 1 << sectorlog;
1549 break;
1550 case D_SECTSIZE:
1551 if (cli->sectorsize)
1552 conflict('d', opts->subopts, D_SECTSIZE, D_SECTLOG);
1553 cli->sectorsize = getnum(value, opts, D_SECTSIZE);
1554 break;
1555 case D_RTINHERIT:
1556 if (getnum(value, opts, D_RTINHERIT))
1557 cli->fsx.fsx_xflags |= XFS_DIFLAG_RTINHERIT;
1558 break;
1559 case D_PROJINHERIT:
1560 cli->fsx.fsx_projid = getnum(value, opts, D_PROJINHERIT);
1561 cli->fsx.fsx_xflags |= XFS_DIFLAG_PROJINHERIT;
1562 break;
1563 case D_EXTSZINHERIT:
1564 cli->fsx.fsx_extsize = getnum(value, opts, D_EXTSZINHERIT);
1565 cli->fsx.fsx_xflags |= XFS_DIFLAG_EXTSZINHERIT;
1566 break;
1567 case D_COWEXTSIZE:
1568 cli->fsx.fsx_cowextsize = getnum(value, opts, D_COWEXTSIZE);
1569 cli->fsx.fsx_xflags |= FS_XFLAG_COWEXTSIZE;
1570 break;
1571 default:
1572 return -EINVAL;
1573 }
1574 return 0;
1575 }
1576
1577 static int
1578 inode_opts_parser(
1579 struct opt_params *opts,
1580 int subopt,
1581 char *value,
1582 struct cli_params *cli)
1583 {
1584 int inodelog;
1585
1586 switch (subopt) {
1587 case I_ALIGN:
1588 cli->sb_feat.inode_align = getnum(value, &iopts, I_ALIGN);
1589 break;
1590 case I_LOG:
1591 inodelog = getnum(value, &iopts, I_LOG);
1592 cli->inodesize = 1 << inodelog;
1593 break;
1594 case I_MAXPCT:
1595 cli->imaxpct = getnum(value, &iopts, I_MAXPCT);
1596 break;
1597 case I_PERBLOCK:
1598 cli->inopblock = getnum(value, &iopts, I_PERBLOCK);
1599 break;
1600 case I_SIZE:
1601 cli->inodesize = getnum(value, &iopts, I_SIZE);
1602 break;
1603 case I_ATTR:
1604 cli->sb_feat.attr_version = getnum(value, &iopts, I_ATTR);
1605 break;
1606 case I_PROJID32BIT:
1607 cli->sb_feat.projid16bit = !getnum(value, &iopts, I_PROJID32BIT);
1608 break;
1609 case I_SPINODES:
1610 cli->sb_feat.spinodes = getnum(value, &iopts, I_SPINODES);
1611 break;
1612 default:
1613 return -EINVAL;
1614 }
1615 return 0;
1616 }
1617
1618 static int
1619 log_opts_parser(
1620 struct opt_params *opts,
1621 int subopt,
1622 char *value,
1623 struct cli_params *cli)
1624 {
1625 int lsectorlog;
1626
1627 switch (subopt) {
1628 case L_AGNUM:
1629 cli->logagno = getnum(value, &lopts, L_AGNUM);
1630 break;
1631 case L_FILE:
1632 cli->xi->lisfile = getnum(value, &lopts, L_FILE);
1633 break;
1634 case L_INTERNAL:
1635 cli->loginternal = getnum(value, &lopts, L_INTERNAL);
1636 break;
1637 case L_SU:
1638 cli->lsu = getstr(value, &lopts, L_SU);
1639 break;
1640 case L_SUNIT:
1641 cli->lsunit = getnum(value, &lopts, L_SUNIT);
1642 break;
1643 case L_NAME:
1644 case L_DEV:
1645 cli->xi->logname = getstr(value, &lopts, L_NAME);
1646 cli->loginternal = 0;
1647 break;
1648 case L_VERSION:
1649 cli->sb_feat.log_version = getnum(value, &lopts, L_VERSION);
1650 break;
1651 case L_SIZE:
1652 cli->logsize = getstr(value, &lopts, L_SIZE);
1653 break;
1654 case L_SECTLOG:
1655 lsectorlog = getnum(value, &lopts, L_SECTLOG);
1656 cli->lsectorsize = 1 << lsectorlog;
1657 break;
1658 case L_SECTSIZE:
1659 cli->lsectorsize = getnum(value, &lopts, L_SECTSIZE);
1660 break;
1661 case L_LAZYSBCNTR:
1662 cli->sb_feat.lazy_sb_counters = getnum(value, &lopts, L_LAZYSBCNTR);
1663 break;
1664 default:
1665 return -EINVAL;
1666 }
1667 return 0;
1668 }
1669
1670 static int
1671 meta_opts_parser(
1672 struct opt_params *opts,
1673 int subopt,
1674 char *value,
1675 struct cli_params *cli)
1676 {
1677 switch (subopt) {
1678 case M_CRC:
1679 cli->sb_feat.crcs_enabled = getnum(value, &mopts, M_CRC);
1680 if (cli->sb_feat.crcs_enabled)
1681 cli->sb_feat.dirftype = true;
1682 break;
1683 case M_FINOBT:
1684 cli->sb_feat.finobt = getnum(value, &mopts, M_FINOBT);
1685 break;
1686 case M_UUID:
1687 if (!value || *value == '\0')
1688 reqval('m', opts->subopts, M_UUID);
1689 if (platform_uuid_parse(value, &cli->uuid))
1690 illegal(value, "m uuid");
1691 break;
1692 case M_RMAPBT:
1693 cli->sb_feat.rmapbt = getnum(value, &mopts, M_RMAPBT);
1694 break;
1695 case M_REFLINK:
1696 cli->sb_feat.reflink = getnum(value, &mopts, M_REFLINK);
1697 break;
1698 default:
1699 return -EINVAL;
1700 }
1701 return 0;
1702 }
1703
1704 static int
1705 naming_opts_parser(
1706 struct opt_params *opts,
1707 int subopt,
1708 char *value,
1709 struct cli_params *cli)
1710 {
1711 switch (subopt) {
1712 case N_LOG:
1713 cli->dirblocklog = getnum(value, opts, N_LOG);
1714 break;
1715 case N_SIZE:
1716 cli->dirblocksize = getstr(value, opts, N_SIZE);
1717 break;
1718 case N_VERSION:
1719 value = getstr(value, &nopts, N_VERSION);
1720 if (!strcasecmp(value, "ci")) {
1721 /* ASCII CI mode */
1722 cli->sb_feat.nci = true;
1723 } else {
1724 cli->sb_feat.dir_version = getnum(value, opts, N_VERSION);
1725 }
1726 break;
1727 case N_FTYPE:
1728 cli->sb_feat.dirftype = getnum(value, opts, N_FTYPE);
1729 break;
1730 default:
1731 return -EINVAL;
1732 }
1733 return 0;
1734 }
1735
1736 static int
1737 rtdev_opts_parser(
1738 struct opt_params *opts,
1739 int subopt,
1740 char *value,
1741 struct cli_params *cli)
1742 {
1743 switch (subopt) {
1744 case R_EXTSIZE:
1745 cli->rtextsize = getstr(value, &ropts, R_EXTSIZE);
1746 break;
1747 case R_FILE:
1748 cli->xi->risfile = getnum(value, &ropts, R_FILE);
1749 break;
1750 case R_NAME:
1751 case R_DEV:
1752 cli->xi->rtname = getstr(value, &ropts, R_NAME);
1753 break;
1754 case R_SIZE:
1755 cli->rtsize = getstr(value, &ropts, R_SIZE);
1756 break;
1757 case R_NOALIGN:
1758 cli->sb_feat.nortalign = getnum(value, &ropts, R_NOALIGN);
1759 break;
1760 default:
1761 return -EINVAL;
1762 }
1763 return 0;
1764 }
1765
1766 static int
1767 sector_opts_parser(
1768 struct opt_params *opts,
1769 int subopt,
1770 char *value,
1771 struct cli_params *cli)
1772 {
1773 int sectorlog;
1774
1775 switch (subopt) {
1776 case S_LOG:
1777 case S_SECTLOG:
1778 if (cli->sectorsize)
1779 conflict('s', opts->subopts, S_SECTSIZE, S_SECTLOG);
1780 sectorlog = getnum(value, &sopts, S_SECTLOG);
1781 cli->sectorsize = 1 << sectorlog;
1782 cli->lsectorsize = cli->sectorsize;
1783 break;
1784 case S_SIZE:
1785 case S_SECTSIZE:
1786 if (cli->sectorsize)
1787 conflict('s', opts->subopts, S_SECTLOG, S_SECTSIZE);
1788 cli->sectorsize = getnum(value, &sopts, S_SECTSIZE);
1789 cli->lsectorsize = cli->sectorsize;
1790 break;
1791 default:
1792 return -EINVAL;
1793 }
1794 return 0;
1795 }
1796
1797 struct subopts {
1798 char opt;
1799 struct opt_params *opts;
1800 int (*parser)();
1801 } subopt_tab[] = {
1802 { 'b', &bopts, block_opts_parser },
1803 { 'd', &dopts, data_opts_parser },
1804 { 'i', &iopts, inode_opts_parser },
1805 { 'l', &lopts, log_opts_parser },
1806 { 'm', &mopts, meta_opts_parser },
1807 { 'n', &nopts, naming_opts_parser },
1808 { 'r', &ropts, rtdev_opts_parser },
1809 { 's', &sopts, sector_opts_parser },
1810 { '\0', NULL, NULL },
1811 };
1812
1813 static void
1814 parse_subopts(
1815 char opt,
1816 char *arg,
1817 struct cli_params *cli)
1818 {
1819 struct subopts *sop = &subopt_tab[0];
1820 char *p;
1821 int ret = 0;
1822
1823 while (sop->opts) {
1824 if (sop->opt == opt)
1825 break;
1826 sop++;
1827 }
1828
1829 /* should never happen */
1830 if (!sop->opts)
1831 return;
1832
1833 p = arg;
1834 while (*p != '\0') {
1835 char **subopts = (char **)sop->opts->subopts;
1836 char *value;
1837 int subopt;
1838
1839 subopt = getsubopt(&p, subopts, &value);
1840
1841 ret = (sop->parser)(sop->opts, subopt, value, cli);
1842 if (ret)
1843 unknown(opt, value);
1844 }
1845 }
1846
1847 int
1848 main(
1849 int argc,
1850 char **argv)
1851 {
1852 uint64_t agcount;
1853 xfs_agf_t *agf;
1854 xfs_agi_t *agi;
1855 xfs_agnumber_t agno;
1856 uint64_t agsize;
1857 xfs_alloc_rec_t *arec;
1858 struct xfs_btree_block *block;
1859 int blflag;
1860 int blocklog;
1861 int bsflag;
1862 int bsize;
1863 xfs_buf_t *buf;
1864 int c;
1865 int daflag;
1866 int dasize;
1867 xfs_rfsblock_t dblocks;
1868 char *dfile;
1869 int dirblocklog;
1870 int dirblocksize;
1871 char *dsize;
1872 int dsu;
1873 int dsw;
1874 int dsunit;
1875 int dswidth;
1876 int dsflag;
1877 int force_overwrite;
1878 struct fsxattr fsx;
1879 int ilflag;
1880 int imaxpct;
1881 int imflag;
1882 int inodelog;
1883 int inopblock;
1884 int ipflag;
1885 int isflag;
1886 int isize;
1887 char *label = NULL;
1888 int laflag;
1889 int lalign;
1890 int ldflag;
1891 int liflag;
1892 xfs_agnumber_t logagno;
1893 xfs_rfsblock_t logblocks;
1894 char *logfile;
1895 int loginternal;
1896 char *logsize;
1897 xfs_fsblock_t logstart;
1898 int lvflag;
1899 int lsflag;
1900 int lsuflag;
1901 int lsunitflag;
1902 int lsectorlog;
1903 int lsectorsize;
1904 int lslflag;
1905 int lssflag;
1906 int lsu;
1907 int lsunit;
1908 int min_logblocks;
1909 xfs_mount_t *mp;
1910 xfs_mount_t mbuf;
1911 xfs_extlen_t nbmblocks;
1912 int nlflag;
1913 int nodsflag;
1914 int norsflag;
1915 xfs_alloc_rec_t *nrec;
1916 int nsflag;
1917 int nvflag;
1918 int Nflag;
1919 int discard = 1;
1920 char *protofile;
1921 char *protostring;
1922 int qflag;
1923 xfs_rfsblock_t rtblocks;
1924 xfs_extlen_t rtextblocks;
1925 xfs_rtblock_t rtextents;
1926 char *rtextsize;
1927 char *rtfile;
1928 char *rtsize;
1929 xfs_sb_t *sbp;
1930 int sectorlog;
1931 uint64_t sector_mask;
1932 int slflag;
1933 int ssflag;
1934 uint64_t tmp_agsize;
1935 uuid_t uuid;
1936 int worst_freelist;
1937 libxfs_init_t xi;
1938 struct fs_topology ft;
1939 struct sb_feat_args sb_feat = {
1940 .finobt = 1,
1941 .spinodes = 0,
1942 .log_version = 2,
1943 .attr_version = 2,
1944 .dir_version = XFS_DFL_DIR_VERSION,
1945 .inode_align = XFS_IFLAG_ALIGN,
1946 .nci = false,
1947 .lazy_sb_counters = true,
1948 .projid16bit = false,
1949 .crcs_enabled = true,
1950 .dirftype = true,
1951 .parent_pointers = false,
1952 .rmapbt = false,
1953 .reflink = false,
1954 };
1955 struct cli_params cli = {
1956 .xi = &xi,
1957 .sb_feat = sb_feat,
1958 };
1959
1960 platform_uuid_generate(&uuid);
1961 progname = basename(argv[0]);
1962 setlocale(LC_ALL, "");
1963 bindtextdomain(PACKAGE, LOCALEDIR);
1964 textdomain(PACKAGE);
1965
1966 blflag = bsflag = slflag = ssflag = lslflag = lssflag = 0;
1967 blocklog = blocksize = 0;
1968 sectorlog = lsectorlog = 0;
1969 sectorsize = lsectorsize = 0;
1970 agsize = daflag = dasize = dblocks = 0;
1971 ilflag = imflag = ipflag = isflag = 0;
1972 liflag = laflag = lsflag = lsuflag = lsunitflag = ldflag = lvflag = 0;
1973 loginternal = 1;
1974 logagno = logblocks = rtblocks = rtextblocks = 0;
1975 Nflag = nlflag = nsflag = nvflag = 0;
1976 dirblocklog = dirblocksize = 0;
1977 qflag = 0;
1978 imaxpct = inodelog = inopblock = isize = 0;
1979 dfile = logfile = rtfile = NULL;
1980 dsize = logsize = rtsize = rtextsize = protofile = NULL;
1981 dsu = dsw = dsunit = dswidth = lalign = lsu = lsunit = 0;
1982 dsflag = nodsflag = norsflag = 0;
1983 force_overwrite = 0;
1984 worst_freelist = 0;
1985 memset(&fsx, 0, sizeof(fsx));
1986
1987 memset(&xi, 0, sizeof(xi));
1988 xi.isdirect = LIBXFS_DIRECT;
1989 xi.isreadonly = LIBXFS_EXCLUSIVELY;
1990
1991 while ((c = getopt(argc, argv, "b:d:i:l:L:m:n:KNp:qr:s:CfV")) != EOF) {
1992 switch (c) {
1993 case 'C':
1994 case 'f':
1995 force_overwrite = 1;
1996 break;
1997 case 'b':
1998 parse_subopts(c, optarg, &cli);
1999
2000 /* temp don't break code */
2001 blocksize = cli.blocksize;
2002 blocklog = libxfs_highbit32(blocksize);
2003 blflag = cli_opt_set(&bopts, B_LOG);
2004 bsflag = cli_opt_set(&bopts, B_SIZE);
2005 /* end temp don't break code */
2006 break;
2007 case 'd':
2008 parse_subopts(c, optarg, &cli);
2009
2010 /* temp don't break code */
2011 agcount = cli.agcount;
2012 if (cli_opt_set(&dopts, D_AGSIZE)) {
2013 agsize = getnum(cli.agsize, &dopts, D_AGSIZE);
2014 dasize = 1;
2015 }
2016 daflag = cli_opt_set(&dopts, D_AGCOUNT);
2017
2018 dsunit = cli.dsunit;
2019 dswidth = cli.dswidth;
2020 dsw = cli.dsw;
2021 if (cli_opt_set(&dopts, D_SU)) {
2022 dsu = getnum(cli.dsu, &dopts, D_SU);
2023 dsflag = 1;
2024 }
2025 dsflag |= cli_opt_set(&dopts, D_SW) ||
2026 cli_opt_set(&dopts, D_SUNIT) ||
2027 cli_opt_set(&dopts, D_SWIDTH);
2028 nodsflag = cli_opt_set(&dopts, D_NOALIGN);
2029
2030 sectorsize = cli.sectorsize;
2031 sectorlog = libxfs_highbit32(sectorsize);
2032 slflag = cli_opt_set(&dopts, D_SECTLOG);
2033 ssflag = cli_opt_set(&dopts, D_SECTSIZE);
2034
2035 fsx.fsx_xflags |= cli.fsx.fsx_xflags;
2036 fsx.fsx_projid = cli.fsx.fsx_projid;
2037 fsx.fsx_extsize = cli.fsx.fsx_extsize;
2038 /* end temp don't break code */
2039 break;
2040 case 'i':
2041 parse_subopts(c, optarg, &cli);
2042
2043 /* temp don't break code */
2044 isize = cli.inodesize;
2045 inodelog = libxfs_highbit32(isize);
2046 inopblock = cli.inopblock;
2047 ilflag = cli_opt_set(&iopts, I_LOG);
2048 isflag = cli_opt_set(&iopts, I_SIZE);
2049 ipflag = cli_opt_set(&iopts, I_PERBLOCK);
2050
2051 imaxpct = cli.imaxpct;
2052 imflag = cli_opt_set(&iopts, I_MAXPCT);
2053 /* end temp don't break code */
2054 break;
2055 case 'l':
2056 parse_subopts(c, optarg, &cli);
2057
2058 /* temp don't break code */
2059 logagno = cli.logagno;
2060 loginternal = cli.loginternal;
2061 logfile = xi.logname;
2062 logsize = cli.logsize;
2063 lsectorsize = cli.lsectorsize;
2064 lsectorlog = libxfs_highbit32(lsectorsize);
2065
2066 lsunit = cli.lsunit;
2067 lsunitflag = cli_opt_set(&lopts, L_SUNIT);
2068 if (cli_opt_set(&lopts, L_SU)) {
2069 lsu = getnum(cli.lsu, &lopts, L_SU);
2070 lsuflag = 1;
2071 }
2072
2073 laflag = cli_opt_set(&lopts, L_AGNUM);
2074 liflag = cli_opt_set(&lopts, L_INTERNAL);
2075 ldflag = cli_opt_set(&lopts, L_NAME) ||
2076 cli_opt_set(&lopts, L_DEV);
2077 lvflag = cli_opt_set(&lopts, L_VERSION);
2078 lslflag = cli_opt_set(&lopts, L_SECTLOG);
2079 lssflag = cli_opt_set(&lopts, L_SECTSIZE);
2080 /* end temp don't break code */
2081 break;
2082 case 'L':
2083 if (strlen(optarg) > sizeof(sbp->sb_fname))
2084 illegal(optarg, "L");
2085 label = optarg;
2086 break;
2087 case 'm':
2088 parse_subopts(c, optarg, &cli);
2089
2090 /* temp don't break code */
2091 platform_uuid_copy(&uuid, &cli.uuid);
2092 /* end temp don't break code */
2093 break;
2094 case 'n':
2095 parse_subopts(c, optarg, &cli);
2096
2097 /* temp don't break code */
2098 if ((nsflag = cli_opt_set(&nopts, N_SIZE)))
2099 dirblocksize = getnum(cli.dirblocksize, &nopts, N_SIZE);
2100 dirblocklog = cli.dirblocklog;
2101
2102 nlflag = cli_opt_set(&nopts, N_LOG);
2103 /* end temp don't break code */
2104 break;
2105 case 'N':
2106 Nflag = 1;
2107 break;
2108 case 'K':
2109 discard = 0;
2110 break;
2111 case 'p':
2112 if (protofile)
2113 respec('p', NULL, 0);
2114 protofile = optarg;
2115 break;
2116 case 'q':
2117 qflag = 1;
2118 break;
2119 case 'r':
2120 parse_subopts(c, optarg, &cli);
2121
2122 /* temp don't break code */
2123 rtextsize = cli.rtextsize;
2124 rtsize = cli.rtsize;
2125 norsflag = cli.sb_feat.nortalign;
2126 /* end temp don't break code */
2127 break;
2128 case 's':
2129 parse_subopts(c, optarg, &cli);
2130
2131 /* temp don't break code */
2132 sectorsize = cli.sectorsize;
2133 lsectorlog = libxfs_highbit32(sectorsize);
2134 lsectorsize = cli.lsectorsize;
2135 lsectorlog = libxfs_highbit32(lsectorsize);
2136 lslflag = slflag = cli_opt_set(&sopts, S_LOG) ||
2137 cli_opt_set(&sopts, S_SECTLOG);
2138
2139 lssflag = ssflag = cli_opt_set(&sopts, S_SIZE) ||
2140 cli_opt_set(&sopts, S_SECTSIZE);
2141 break;
2142 case 'V':
2143 printf(_("%s version %s\n"), progname, VERSION);
2144 exit(0);
2145 case '?':
2146 unknown(optopt, "");
2147 }
2148 }
2149 if (argc - optind > 1) {
2150 fprintf(stderr, _("extra arguments\n"));
2151 usage();
2152 } else if (argc - optind == 1) {
2153 dfile = xi.volname = getstr(argv[optind], &dopts, D_NAME);
2154 } else
2155 dfile = xi.dname;
2156
2157 /* temp don't break code */
2158 sb_feat = cli.sb_feat;
2159 /* end temp don't break code */
2160
2161 /*
2162 * Blocksize and sectorsize first, other things depend on them
2163 * For RAID4/5/6 we want to align sector size and block size,
2164 * so we need to start with the device geometry extraction too.
2165 */
2166 if (!blflag && !bsflag) {
2167 blocklog = XFS_DFL_BLOCKSIZE_LOG;
2168 blocksize = 1 << XFS_DFL_BLOCKSIZE_LOG;
2169 }
2170 if (blocksize < XFS_MIN_BLOCKSIZE || blocksize > XFS_MAX_BLOCKSIZE) {
2171 fprintf(stderr, _("illegal block size %d\n"), blocksize);
2172 usage();
2173 }
2174 if (sb_feat.crcs_enabled && blocksize < XFS_MIN_CRC_BLOCKSIZE) {
2175 fprintf(stderr,
2176 _("Minimum block size for CRC enabled filesystems is %d bytes.\n"),
2177 XFS_MIN_CRC_BLOCKSIZE);
2178 usage();
2179 }
2180 if (sb_feat.crcs_enabled && !sb_feat.dirftype) {
2181 fprintf(stderr, _("cannot disable ftype with crcs enabled\n"));
2182 usage();
2183 }
2184
2185 if (!slflag && !ssflag) {
2186 sectorlog = XFS_MIN_SECTORSIZE_LOG;
2187 sectorsize = XFS_MIN_SECTORSIZE;
2188 }
2189 if (!lslflag && !lssflag) {
2190 lsectorlog = sectorlog;
2191 lsectorsize = sectorsize;
2192 }
2193
2194 /*
2195 * Before anything else, verify that we are correctly operating on
2196 * files or block devices and set the control parameters correctly.
2197 * Explicitly disable direct IO for image files so we don't error out on
2198 * sector size mismatches between the new filesystem and the underlying
2199 * host filesystem.
2200 */
2201 check_device_type(dfile, &xi.disfile, !dsize, !dfile,
2202 Nflag ? NULL : &xi.dcreat, force_overwrite, "d");
2203 if (!loginternal)
2204 check_device_type(xi.logname, &xi.lisfile, !logsize, !xi.logname,
2205 Nflag ? NULL : &xi.lcreat,
2206 force_overwrite, "l");
2207 if (xi.rtname)
2208 check_device_type(xi.rtname, &xi.risfile, !rtsize, !xi.rtname,
2209 Nflag ? NULL : &xi.rcreat,
2210 force_overwrite, "r");
2211 if (xi.disfile || xi.lisfile || xi.risfile)
2212 xi.isdirect = 0;
2213
2214 memset(&ft, 0, sizeof(ft));
2215 get_topology(&xi, &ft, force_overwrite);
2216
2217 if (!ssflag) {
2218 /*
2219 * Unless specified manually on the command line use the
2220 * advertised sector size of the device. We use the physical
2221 * sector size unless the requested block size is smaller
2222 * than that, then we can use logical, but warn about the
2223 * inefficiency.
2224 */
2225
2226 /* Older kernels may not have physical/logical distinction */
2227 if (!ft.psectorsize)
2228 ft.psectorsize = ft.lsectorsize;
2229
2230 sectorsize = ft.psectorsize ? ft.psectorsize :
2231 XFS_MIN_SECTORSIZE;
2232
2233 if ((blocksize < sectorsize) && (blocksize >= ft.lsectorsize)) {
2234 fprintf(stderr,
2235 _("specified blocksize %d is less than device physical sector size %d\n"),
2236 blocksize, ft.psectorsize);
2237 fprintf(stderr,
2238 _("switching to logical sector size %d\n"),
2239 ft.lsectorsize);
2240 sectorsize = ft.lsectorsize ? ft.lsectorsize :
2241 XFS_MIN_SECTORSIZE;
2242 }
2243 }
2244
2245 if (!ssflag) {
2246 sectorlog = libxfs_highbit32(sectorsize);
2247 if (loginternal) {
2248 lsectorsize = sectorsize;
2249 lsectorlog = sectorlog;
2250 }
2251 }
2252
2253 if (sectorsize < XFS_MIN_SECTORSIZE ||
2254 sectorsize > XFS_MAX_SECTORSIZE || sectorsize > blocksize) {
2255 if (ssflag)
2256 fprintf(stderr, _("illegal sector size %d\n"), sectorsize);
2257 else
2258 fprintf(stderr,
2259 _("block size %d cannot be smaller than logical sector size %d\n"),
2260 blocksize, ft.lsectorsize);
2261 usage();
2262 }
2263 if (sectorsize < ft.lsectorsize) {
2264 fprintf(stderr, _("illegal sector size %d; hw sector is %d\n"),
2265 sectorsize, ft.lsectorsize);
2266 usage();
2267 }
2268 if (lsectorsize < XFS_MIN_SECTORSIZE ||
2269 lsectorsize > XFS_MAX_SECTORSIZE || lsectorsize > blocksize) {
2270 fprintf(stderr, _("illegal log sector size %d\n"), lsectorsize);
2271 usage();
2272 } else if (lsectorsize > XFS_MIN_SECTORSIZE && !lsu && !lsunit) {
2273 lsu = blocksize;
2274 sb_feat.log_version = 2;
2275 }
2276
2277 /*
2278 * Now we have blocks and sector sizes set up, check parameters that are
2279 * no longer optional for CRC enabled filesystems. Catch them up front
2280 * here before doing anything else.
2281 */
2282 if (sb_feat.crcs_enabled) {
2283 /* minimum inode size is 512 bytes, ipflag checked later */
2284 if ((isflag || ilflag) && inodelog < XFS_DINODE_DFL_CRC_LOG) {
2285 fprintf(stderr,
2286 _("Minimum inode size for CRCs is %d bytes\n"),
2287 1 << XFS_DINODE_DFL_CRC_LOG);
2288 usage();
2289 }
2290
2291 /* inodes always aligned */
2292 if (!sb_feat.inode_align) {
2293 fprintf(stderr,
2294 _("Inodes always aligned for CRC enabled filesytems\n"));
2295 usage();
2296 }
2297
2298 /* lazy sb counters always on */
2299 if (!sb_feat.lazy_sb_counters) {
2300 fprintf(stderr,
2301 _("Lazy superblock counted always enabled for CRC enabled filesytems\n"));
2302 usage();
2303 }
2304
2305 /* version 2 logs always on */
2306 if (sb_feat.log_version != 2) {
2307 fprintf(stderr,
2308 _("V2 logs always enabled for CRC enabled filesytems\n"));
2309 usage();
2310 }
2311
2312 /* attr2 always on */
2313 if (sb_feat.attr_version != 2) {
2314 fprintf(stderr,
2315 _("V2 attribute format always enabled on CRC enabled filesytems\n"));
2316 usage();
2317 }
2318
2319 /* 32 bit project quota always on */
2320 /* attr2 always on */
2321 if (sb_feat.projid16bit) {
2322 fprintf(stderr,
2323 _("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
2324 usage();
2325 }
2326 } else {
2327 /*
2328 * The kernel doesn't currently support crc=0,finobt=1
2329 * filesystems. If crcs are not enabled and the user has not
2330 * explicitly turned finobt on, then silently turn it off to
2331 * avoid an unnecessary warning.
2332 * If the user explicitly tried to use crc=0,finobt=1,
2333 * then issue an error.
2334 * The same is also for sparse inodes.
2335 */
2336 if (sb_feat.finobt && mopts.subopt_params[M_FINOBT].seen) {
2337 fprintf(stderr,
2338 _("finobt not supported without CRC support\n"));
2339 usage();
2340 }
2341 sb_feat.finobt = 0;
2342
2343 if (sb_feat.spinodes) {
2344 fprintf(stderr,
2345 _("sparse inodes not supported without CRC support\n"));
2346 usage();
2347 }
2348 sb_feat.spinodes = 0;
2349
2350 if (sb_feat.rmapbt) {
2351 fprintf(stderr,
2352 _("rmapbt not supported without CRC support\n"));
2353 usage();
2354 }
2355 sb_feat.rmapbt = false;
2356
2357 if (sb_feat.reflink) {
2358 fprintf(stderr,
2359 _("reflink not supported without CRC support\n"));
2360 usage();
2361 }
2362 sb_feat.reflink = false;
2363 }
2364
2365 if ((fsx.fsx_xflags & FS_XFLAG_COWEXTSIZE) && !sb_feat.reflink) {
2366 fprintf(stderr,
2367 _("cowextsize not supported without reflink support\n"));
2368 usage();
2369 }
2370
2371 if (sb_feat.rmapbt && xi.rtname) {
2372 fprintf(stderr,
2373 _("rmapbt not supported with realtime devices\n"));
2374 usage();
2375 sb_feat.rmapbt = false;
2376 }
2377
2378 if (nsflag || nlflag) {
2379 if (dirblocksize < blocksize ||
2380 dirblocksize > XFS_MAX_BLOCKSIZE) {
2381 fprintf(stderr, _("illegal directory block size %d\n"),
2382 dirblocksize);
2383 usage();
2384 }
2385 } else {
2386 if (blocksize < (1 << XFS_MIN_REC_DIRSIZE))
2387 dirblocklog = XFS_MIN_REC_DIRSIZE;
2388 else
2389 dirblocklog = blocklog;
2390 dirblocksize = 1 << dirblocklog;
2391 }
2392
2393
2394 if (dsize) {
2395 uint64_t dbytes;
2396
2397 dbytes = getnum(dsize, &dopts, D_SIZE);
2398 if (dbytes % XFS_MIN_BLOCKSIZE) {
2399 fprintf(stderr,
2400 _("illegal data length %lld, not a multiple of %d\n"),
2401 (long long)dbytes, XFS_MIN_BLOCKSIZE);
2402 usage();
2403 }
2404 dblocks = (xfs_rfsblock_t)(dbytes >> blocklog);
2405 if (dbytes % blocksize)
2406 fprintf(stderr, _("warning: "
2407 "data length %lld not a multiple of %d, truncated to %lld\n"),
2408 (long long)dbytes, blocksize,
2409 (long long)(dblocks << blocklog));
2410 }
2411 if (ipflag) {
2412 inodelog = blocklog - libxfs_highbit32(inopblock);
2413 isize = 1 << inodelog;
2414 } else if (!ilflag && !isflag) {
2415 inodelog = sb_feat.crcs_enabled ? XFS_DINODE_DFL_CRC_LOG
2416 : XFS_DINODE_DFL_LOG;
2417 isize = 1 << inodelog;
2418 }
2419 if (sb_feat.crcs_enabled && inodelog < XFS_DINODE_DFL_CRC_LOG) {
2420 fprintf(stderr,
2421 _("Minimum inode size for CRCs is %d bytes\n"),
2422 1 << XFS_DINODE_DFL_CRC_LOG);
2423 usage();
2424 }
2425
2426 if (logsize) {
2427 uint64_t logbytes;
2428
2429 logbytes = getnum(logsize, &lopts, L_SIZE);
2430 if (logbytes % XFS_MIN_BLOCKSIZE) {
2431 fprintf(stderr,
2432 _("illegal log length %lld, not a multiple of %d\n"),
2433 (long long)logbytes, XFS_MIN_BLOCKSIZE);
2434 usage();
2435 }
2436 logblocks = (xfs_rfsblock_t)(logbytes >> blocklog);
2437 if (logbytes % blocksize)
2438 fprintf(stderr,
2439 _("warning: log length %lld not a multiple of %d, truncated to %lld\n"),
2440 (long long)logbytes, blocksize,
2441 (long long)(logblocks << blocklog));
2442 }
2443 if (rtsize) {
2444 uint64_t rtbytes;
2445
2446 rtbytes = getnum(rtsize, &ropts, R_SIZE);
2447 if (rtbytes % XFS_MIN_BLOCKSIZE) {
2448 fprintf(stderr,
2449 _("illegal rt length %lld, not a multiple of %d\n"),
2450 (long long)rtbytes, XFS_MIN_BLOCKSIZE);
2451 usage();
2452 }
2453 rtblocks = (xfs_rfsblock_t)(rtbytes >> blocklog);
2454 if (rtbytes % blocksize)
2455 fprintf(stderr,
2456 _("warning: rt length %lld not a multiple of %d, truncated to %lld\n"),
2457 (long long)rtbytes, blocksize,
2458 (long long)(rtblocks << blocklog));
2459 }
2460 /*
2461 * If specified, check rt extent size against its constraints.
2462 */
2463 if (rtextsize) {
2464 uint64_t rtextbytes;
2465
2466 rtextbytes = getnum(rtextsize, &ropts, R_EXTSIZE);
2467 if (rtextbytes % blocksize) {
2468 fprintf(stderr,
2469 _("illegal rt extent size %lld, not a multiple of %d\n"),
2470 (long long)rtextbytes, blocksize);
2471 usage();
2472 }
2473 rtextblocks = (xfs_extlen_t)(rtextbytes >> blocklog);
2474 } else {
2475 /*
2476 * If realtime extsize has not been specified by the user,
2477 * and the underlying volume is striped, then set rtextblocks
2478 * to the stripe width.
2479 */
2480 uint64_t rswidth;
2481 uint64_t rtextbytes;
2482
2483 if (!norsflag && !xi.risfile && !(!rtsize && xi.disfile))
2484 rswidth = ft.rtswidth;
2485 else
2486 rswidth = 0;
2487
2488 /* check that rswidth is a multiple of fs blocksize */
2489 if (!norsflag && rswidth && !(BBTOB(rswidth) % blocksize)) {
2490 rswidth = DTOBT(rswidth);
2491 rtextbytes = rswidth << blocklog;
2492 if (XFS_MIN_RTEXTSIZE <= rtextbytes &&
2493 (rtextbytes <= XFS_MAX_RTEXTSIZE)) {
2494 rtextblocks = rswidth;
2495 }
2496 }
2497 if (!rtextblocks) {
2498 rtextblocks = (blocksize < XFS_MIN_RTEXTSIZE) ?
2499 XFS_MIN_RTEXTSIZE >> blocklog : 1;
2500 }
2501 }
2502 ASSERT(rtextblocks);
2503
2504 /*
2505 * Check some argument sizes against mins, maxes.
2506 */
2507 if (isize > blocksize / XFS_MIN_INODE_PERBLOCK ||
2508 isize < XFS_DINODE_MIN_SIZE ||
2509 isize > XFS_DINODE_MAX_SIZE) {
2510 int maxsz;
2511
2512 fprintf(stderr, _("illegal inode size %d\n"), isize);
2513 maxsz = MIN(blocksize / XFS_MIN_INODE_PERBLOCK,
2514 XFS_DINODE_MAX_SIZE);
2515 if (XFS_DINODE_MIN_SIZE == maxsz)
2516 fprintf(stderr,
2517 _("allowable inode size with %d byte blocks is %d\n"),
2518 blocksize, XFS_DINODE_MIN_SIZE);
2519 else
2520 fprintf(stderr,
2521 _("allowable inode size with %d byte blocks is between %d and %d\n"),
2522 blocksize, XFS_DINODE_MIN_SIZE, maxsz);
2523 exit(1);
2524 }
2525
2526 /* if lsu or lsunit was specified, automatically use v2 logs */
2527 if ((lsu || lsunit) && sb_feat.log_version == 1) {
2528 fprintf(stderr,
2529 _("log stripe unit specified, using v2 logs\n"));
2530 sb_feat.log_version = 2;
2531 }
2532
2533 calc_stripe_factors(dsu, dsw, sectorsize, lsu, lsectorsize,
2534 &dsunit, &dswidth, &lsunit);
2535
2536 /* If sunit & swidth were manually specified as 0, same as noalign */
2537 if (dsflag && !dsunit && !dswidth)
2538 nodsflag = 1;
2539
2540 xi.setblksize = sectorsize;
2541
2542 /*
2543 * Initialize. This will open the log and rt devices as well.
2544 */
2545 if (!libxfs_init(&xi))
2546 usage();
2547 if (!xi.ddev) {
2548 fprintf(stderr, _("no device name given in argument list\n"));
2549 usage();
2550 }
2551
2552 /*
2553 * Ok, Linux only has a 1024-byte resolution on device _size_,
2554 * and the sizes below are in basic 512-byte blocks,
2555 * so if we have (size % 2), on any partition, we can't get
2556 * to the last 512 bytes. The same issue exists for larger
2557 * sector sizes - we cannot write past the last sector.
2558 *
2559 * So, we reduce the size (in basic blocks) to a perfect
2560 * multiple of the sector size, or 1024, whichever is larger.
2561 */
2562
2563 sector_mask = (uint64_t)-1 << (MAX(sectorlog, 10) - BBSHIFT);
2564 xi.dsize &= sector_mask;
2565 xi.rtsize &= sector_mask;
2566 xi.logBBsize &= (uint64_t)-1 << (MAX(lsectorlog, 10) - BBSHIFT);
2567
2568
2569 /* don't do discards on print-only runs or on files */
2570 if (discard && !Nflag) {
2571 if (!xi.disfile)
2572 discard_blocks(xi.ddev, xi.dsize);
2573 if (xi.rtdev && !xi.risfile)
2574 discard_blocks(xi.rtdev, xi.rtsize);
2575 if (xi.logdev && xi.logdev != xi.ddev && !xi.lisfile)
2576 discard_blocks(xi.logdev, xi.logBBsize);
2577 }
2578
2579 if (!liflag && !ldflag)
2580 loginternal = xi.logdev == 0;
2581 if (xi.logname)
2582 logfile = xi.logname;
2583 else if (loginternal)
2584 logfile = _("internal log");
2585 else if (xi.volname && xi.logdev)
2586 logfile = _("volume log");
2587 else if (!ldflag) {
2588 fprintf(stderr, _("no log subvolume or internal log\n"));
2589 usage();
2590 }
2591 if (xi.rtname)
2592 rtfile = xi.rtname;
2593 else
2594 if (xi.volname && xi.rtdev)
2595 rtfile = _("volume rt");
2596 else if (!xi.rtdev)
2597 rtfile = _("none");
2598 if (dsize && xi.dsize > 0 && dblocks > DTOBT(xi.dsize)) {
2599 fprintf(stderr,
2600 _("size %s specified for data subvolume is too large, "
2601 "maximum is %lld blocks\n"),
2602 dsize, (long long)DTOBT(xi.dsize));
2603 usage();
2604 } else if (!dsize && xi.dsize > 0)
2605 dblocks = DTOBT(xi.dsize);
2606 else if (!dsize) {
2607 fprintf(stderr, _("can't get size of data subvolume\n"));
2608 usage();
2609 }
2610 if (dblocks < XFS_MIN_DATA_BLOCKS) {
2611 fprintf(stderr,
2612 _("size %lld of data subvolume is too small, minimum %d blocks\n"),
2613 (long long)dblocks, XFS_MIN_DATA_BLOCKS);
2614 usage();
2615 }
2616
2617 if (loginternal && xi.logdev) {
2618 fprintf(stderr,
2619 _("can't have both external and internal logs\n"));
2620 usage();
2621 } else if (loginternal && sectorsize != lsectorsize) {
2622 fprintf(stderr,
2623 _("data and log sector sizes must be equal for internal logs\n"));
2624 usage();
2625 }
2626
2627 if (xi.dbsize > sectorsize) {
2628 fprintf(stderr, _(
2629 "Warning: the data subvolume sector size %u is less than the sector size \n\
2630 reported by the device (%u).\n"),
2631 sectorsize, xi.dbsize);
2632 }
2633 if (!loginternal && xi.lbsize > lsectorsize) {
2634 fprintf(stderr, _(
2635 "Warning: the log subvolume sector size %u is less than the sector size\n\
2636 reported by the device (%u).\n"),
2637 lsectorsize, xi.lbsize);
2638 }
2639 if (rtsize && xi.rtsize > 0 && xi.rtbsize > sectorsize) {
2640 fprintf(stderr, _(
2641 "Warning: the realtime subvolume sector size %u is less than the sector size\n\
2642 reported by the device (%u).\n"),
2643 sectorsize, xi.rtbsize);
2644 }
2645
2646 if (rtsize && xi.rtsize > 0 && rtblocks > DTOBT(xi.rtsize)) {
2647 fprintf(stderr,
2648 _("size %s specified for rt subvolume is too large, "
2649 "maximum is %lld blocks\n"),
2650 rtsize, (long long)DTOBT(xi.rtsize));
2651 usage();
2652 } else if (!rtsize && xi.rtsize > 0)
2653 rtblocks = DTOBT(xi.rtsize);
2654 else if (rtsize && !xi.rtdev) {
2655 fprintf(stderr,
2656 _("size specified for non-existent rt subvolume\n"));
2657 usage();
2658 }
2659 if (xi.rtdev) {
2660 rtextents = rtblocks / rtextblocks;
2661 nbmblocks = (xfs_extlen_t)howmany(rtextents, NBBY * blocksize);
2662 } else {
2663 rtextents = rtblocks = 0;
2664 nbmblocks = 0;
2665 }
2666
2667 if (!nodsflag) {
2668 if (dsunit) {
2669 if (ft.dsunit && ft.dsunit != dsunit) {
2670 fprintf(stderr,
2671 _("%s: Specified data stripe unit %d "
2672 "is not the same as the volume stripe "
2673 "unit %d\n"),
2674 progname, dsunit, ft.dsunit);
2675 }
2676 if (ft.dswidth && ft.dswidth != dswidth) {
2677 fprintf(stderr,
2678 _("%s: Specified data stripe width %d "
2679 "is not the same as the volume stripe "
2680 "width %d\n"),
2681 progname, dswidth, ft.dswidth);
2682 }
2683 } else {
2684 dsunit = ft.dsunit;
2685 dswidth = ft.dswidth;
2686 nodsflag = 1;
2687 }
2688 } /* else dsunit & dswidth can't be set if nodsflag is set */
2689
2690 if (dasize) { /* User-specified AG size */
2691 /*
2692 * Check specified agsize is a multiple of blocksize.
2693 */
2694 if (agsize % blocksize) {
2695 fprintf(stderr,
2696 _("agsize (%lld) not a multiple of fs blk size (%d)\n"),
2697 (long long)agsize, blocksize);
2698 usage();
2699 }
2700 agsize /= blocksize;
2701 agcount = dblocks / agsize + (dblocks % agsize != 0);
2702
2703 } else if (daflag) { /* User-specified AG count */
2704 agsize = dblocks / agcount + (dblocks % agcount != 0);
2705 } else {
2706 calc_default_ag_geometry(blocklog, dblocks,
2707 dsunit | dswidth, &agsize, &agcount);
2708 }
2709
2710 /*
2711 * If dsunit is a multiple of fs blocksize, then check that is a
2712 * multiple of the agsize too
2713 */
2714 if (dsunit && !(BBTOB(dsunit) % blocksize) &&
2715 dswidth && !(BBTOB(dswidth) % blocksize)) {
2716
2717 /* convert from 512 byte blocks to fs blocksize */
2718 dsunit = DTOBT(dsunit);
2719 dswidth = DTOBT(dswidth);
2720
2721 /*
2722 * agsize is not a multiple of dsunit
2723 */
2724 if ((agsize % dsunit) != 0) {
2725 /*
2726 * Round up to stripe unit boundary. Also make sure
2727 * that agsize is still larger than
2728 * XFS_AG_MIN_BLOCKS(blocklog)
2729 */
2730 tmp_agsize = ((agsize + (dsunit - 1))/ dsunit) * dsunit;
2731 /*
2732 * Round down to stripe unit boundary if rounding up
2733 * created an AG size that is larger than the AG max.
2734 */
2735 if (tmp_agsize > XFS_AG_MAX_BLOCKS(blocklog))
2736 tmp_agsize = ((agsize) / dsunit) * dsunit;
2737
2738 if ((tmp_agsize >= XFS_AG_MIN_BLOCKS(blocklog)) &&
2739 (tmp_agsize <= XFS_AG_MAX_BLOCKS(blocklog))) {
2740 agsize = tmp_agsize;
2741 if (!daflag)
2742 agcount = dblocks/agsize +
2743 (dblocks % agsize != 0);
2744 if (dasize)
2745 fprintf(stderr,
2746 _("agsize rounded to %lld, swidth = %d\n"),
2747 (long long)agsize, dswidth);
2748 } else {
2749 if (nodsflag) {
2750 dsunit = dswidth = 0;
2751 } else {
2752 /*
2753 * agsize is out of bounds, this will
2754 * print nice details & exit.
2755 */
2756 validate_ag_geometry(blocklog, dblocks,
2757 agsize, agcount);
2758 exit(1);
2759 }
2760 }
2761 }
2762 if (dswidth && ((agsize % dswidth) == 0)
2763 && (dswidth != dsunit)
2764 && (agcount > 1)) {
2765 /* This is a non-optimal configuration because all AGs
2766 * start on the same disk in the stripe. Changing
2767 * the AG size by one sunit will guarantee that this
2768 * does not happen.
2769 */
2770 tmp_agsize = agsize - dsunit;
2771 if (tmp_agsize < XFS_AG_MIN_BLOCKS(blocklog)) {
2772 tmp_agsize = agsize + dsunit;
2773 if (dblocks < agsize) {
2774 /* oh well, nothing to do */
2775 tmp_agsize = agsize;
2776 }
2777 }
2778 if (daflag || dasize) {
2779 fprintf(stderr, _(
2780 "Warning: AG size is a multiple of stripe width. This can cause performance\n\
2781 problems by aligning all AGs on the same disk. To avoid this, run mkfs with\n\
2782 an AG size that is one stripe unit smaller, for example %llu.\n"),
2783 (unsigned long long)tmp_agsize);
2784 } else {
2785 agsize = tmp_agsize;
2786 agcount = dblocks/agsize + (dblocks % agsize != 0);
2787 /*
2788 * If the last AG is too small, reduce the
2789 * filesystem size and drop the blocks.
2790 */
2791 if ( dblocks % agsize != 0 &&
2792 (dblocks % agsize <
2793 XFS_AG_MIN_BLOCKS(blocklog))) {
2794 dblocks = (xfs_rfsblock_t)((agcount - 1) * agsize);
2795 agcount--;
2796 ASSERT(agcount != 0);
2797 }
2798 }
2799 }
2800 } else {
2801 if (nodsflag)
2802 dsunit = dswidth = 0;
2803 else {
2804 fprintf(stderr,
2805 _("%s: Stripe unit(%d) or stripe width(%d) is "
2806 "not a multiple of the block size(%d)\n"),
2807 progname, BBTOB(dsunit), BBTOB(dswidth),
2808 blocksize);
2809 exit(1);
2810 }
2811 }
2812
2813 /*
2814 * If the last AG is too small, reduce the filesystem size
2815 * and drop the blocks.
2816 */
2817 if ( dblocks % agsize != 0 &&
2818 (dblocks % agsize < XFS_AG_MIN_BLOCKS(blocklog))) {
2819 ASSERT(!daflag);
2820 dblocks = (xfs_rfsblock_t)((agcount - 1) * agsize);
2821 agcount--;
2822 ASSERT(agcount != 0);
2823 }
2824
2825 validate_ag_geometry(blocklog, dblocks, agsize, agcount);
2826
2827 if (!imflag)
2828 imaxpct = calc_default_imaxpct(blocklog, dblocks);
2829
2830 /*
2831 * check that log sunit is modulo fsblksize or default it to dsunit.
2832 */
2833
2834 if (lsunit) {
2835 /* convert from 512 byte blocks to fs blocks */
2836 lsunit = DTOBT(lsunit);
2837 } else if (sb_feat.log_version == 2 && loginternal && dsunit) {
2838 /* lsunit and dsunit now in fs blocks */
2839 lsunit = dsunit;
2840 }
2841
2842 if (sb_feat.log_version == 2 && (lsunit * blocksize) > 256 * 1024) {
2843 /* Warn only if specified on commandline */
2844 if (lsuflag || lsunitflag) {
2845 fprintf(stderr,
2846 _("log stripe unit (%d bytes) is too large (maximum is 256KiB)\n"),
2847 (lsunit * blocksize));
2848 fprintf(stderr,
2849 _("log stripe unit adjusted to 32KiB\n"));
2850 }
2851 lsunit = (32 * 1024) >> blocklog;
2852 }
2853
2854 min_logblocks = max_trans_res(agsize,
2855 sb_feat.crcs_enabled, sb_feat.dir_version,
2856 sectorlog, blocklog, inodelog, dirblocklog,
2857 sb_feat.log_version, lsunit, sb_feat.finobt,
2858 sb_feat.rmapbt, sb_feat.reflink,
2859 sb_feat.inode_align);
2860 ASSERT(min_logblocks);
2861 min_logblocks = MAX(XFS_MIN_LOG_BLOCKS, min_logblocks);
2862 if (!logsize && dblocks >= (1024*1024*1024) >> blocklog)
2863 min_logblocks = MAX(min_logblocks, XFS_MIN_LOG_BYTES>>blocklog);
2864 if (logsize && xi.logBBsize > 0 && logblocks > DTOBT(xi.logBBsize)) {
2865 fprintf(stderr,
2866 _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
2867 logsize, (long long)DTOBT(xi.logBBsize));
2868 usage();
2869 } else if (!logsize && xi.logBBsize > 0) {
2870 logblocks = DTOBT(xi.logBBsize);
2871 } else if (logsize && !xi.logdev && !loginternal) {
2872 fprintf(stderr,
2873 _("size specified for non-existent log subvolume\n"));
2874 usage();
2875 } else if (loginternal && logsize && logblocks >= dblocks) {
2876 fprintf(stderr, _("size %lld too large for internal log\n"),
2877 (long long)logblocks);
2878 usage();
2879 } else if (!loginternal && !xi.logdev) {
2880 logblocks = 0;
2881 } else if (loginternal && !logsize) {
2882
2883 if (dblocks < GIGABYTES(1, blocklog)) {
2884 /* tiny filesystems get minimum sized logs. */
2885 logblocks = min_logblocks;
2886 } else if (dblocks < GIGABYTES(16, blocklog)) {
2887
2888 /*
2889 * For small filesystems, we want to use the
2890 * XFS_MIN_LOG_BYTES for filesystems smaller than 16G if
2891 * at all possible, ramping up to 128MB at 256GB.
2892 */
2893 logblocks = MIN(XFS_MIN_LOG_BYTES >> blocklog,
2894 min_logblocks * XFS_DFL_LOG_FACTOR);
2895 } else {
2896 /*
2897 * With a 2GB max log size, default to maximum size
2898 * at 4TB. This keeps the same ratio from the older
2899 * max log size of 128M at 256GB fs size. IOWs,
2900 * the ratio of fs size to log size is 2048:1.
2901 */
2902 logblocks = (dblocks << blocklog) / 2048;
2903 logblocks = logblocks >> blocklog;
2904 }
2905
2906 /* Ensure the chosen size meets minimum log size requirements */
2907 logblocks = MAX(min_logblocks, logblocks);
2908
2909 /* make sure the log fits wholly within an AG */
2910 if (logblocks >= agsize)
2911 logblocks = min_logblocks;
2912
2913 /* and now clamp the size to the maximum supported size */
2914 logblocks = MIN(logblocks, XFS_MAX_LOG_BLOCKS);
2915 if ((logblocks << blocklog) > XFS_MAX_LOG_BYTES)
2916 logblocks = XFS_MAX_LOG_BYTES >> blocklog;
2917
2918 }
2919 validate_log_size(logblocks, blocklog, min_logblocks);
2920
2921 protostring = setup_proto(protofile);
2922 bsize = 1 << (blocklog - BBSHIFT);
2923 mp = &mbuf;
2924 sbp = &mp->m_sb;
2925 memset(mp, 0, sizeof(xfs_mount_t));
2926 sbp->sb_blocklog = (uint8_t)blocklog;
2927 sbp->sb_sectlog = (uint8_t)sectorlog;
2928 sbp->sb_agblklog = (uint8_t)log2_roundup((unsigned int)agsize);
2929 sbp->sb_agblocks = (xfs_agblock_t)agsize;
2930 mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT;
2931 mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT;
2932
2933 /*
2934 * sb_versionnum, finobt and rmapbt flags must be set before we use
2935 * libxfs_prealloc_blocks().
2936 */
2937 sb_set_features(&mp->m_sb, &sb_feat, sectorsize, lsectorsize, dsunit);
2938
2939
2940 if (loginternal) {
2941 /*
2942 * Readjust the log size to fit within an AG if it was sized
2943 * automatically.
2944 */
2945 if (!logsize) {
2946 logblocks = MIN(logblocks,
2947 libxfs_alloc_ag_max_usable(mp));
2948
2949 /* revalidate the log size is valid if we changed it */
2950 validate_log_size(logblocks, blocklog, min_logblocks);
2951 }
2952 if (logblocks > agsize - libxfs_prealloc_blocks(mp)) {
2953 fprintf(stderr,
2954 _("internal log size %lld too large, must fit in allocation group\n"),
2955 (long long)logblocks);
2956 usage();
2957 }
2958
2959 if (laflag) {
2960 if (logagno >= agcount) {
2961 fprintf(stderr,
2962 _("log ag number %d too large, must be less than %lld\n"),
2963 logagno, (long long)agcount);
2964 usage();
2965 }
2966 } else
2967 logagno = (xfs_agnumber_t)(agcount / 2);
2968
2969 logstart = XFS_AGB_TO_FSB(mp, logagno, libxfs_prealloc_blocks(mp));
2970 /*
2971 * Align the logstart at stripe unit boundary.
2972 */
2973 if (lsunit) {
2974 logstart = fixup_internal_log_stripe(mp,
2975 lsflag, logstart, agsize, lsunit,
2976 &logblocks, blocklog, &lalign);
2977 } else if (dsunit) {
2978 logstart = fixup_internal_log_stripe(mp,
2979 lsflag, logstart, agsize, dsunit,
2980 &logblocks, blocklog, &lalign);
2981 }
2982 } else {
2983 logstart = 0;
2984 if (lsunit)
2985 fixup_log_stripe_unit(lsflag, lsunit,
2986 &logblocks, blocklog);
2987 }
2988 validate_log_size(logblocks, blocklog, min_logblocks);
2989
2990 if (!qflag || Nflag) {
2991 printf(_(
2992 "meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n"
2993 " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n"
2994 " =%-22s crc=%-8u finobt=%u, sparse=%u, rmapbt=%u, reflink=%u\n"
2995 "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n"
2996 " =%-22s sunit=%-6u swidth=%u blks\n"
2997 "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n"
2998 "log =%-22s bsize=%-6d blocks=%lld, version=%d\n"
2999 " =%-22s sectsz=%-5u sunit=%d blks, lazy-count=%d\n"
3000 "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n"),
3001 dfile, isize, (long long)agcount, (long long)agsize,
3002 "", sectorsize, sb_feat.attr_version,
3003 !sb_feat.projid16bit,
3004 "", sb_feat.crcs_enabled, sb_feat.finobt, sb_feat.spinodes,
3005 sb_feat.rmapbt, sb_feat.reflink,
3006 "", blocksize, (long long)dblocks, imaxpct,
3007 "", dsunit, dswidth,
3008 sb_feat.dir_version, dirblocksize, sb_feat.nci,
3009 sb_feat.dirftype,
3010 logfile, 1 << blocklog, (long long)logblocks,
3011 sb_feat.log_version, "", lsectorsize, lsunit,
3012 sb_feat.lazy_sb_counters,
3013 rtfile, rtextblocks << blocklog,
3014 (long long)rtblocks, (long long)rtextents);
3015 if (Nflag)
3016 exit(0);
3017 }
3018
3019 if (label)
3020 strncpy(sbp->sb_fname, label, sizeof(sbp->sb_fname));
3021 sbp->sb_magicnum = XFS_SB_MAGIC;
3022 sbp->sb_blocksize = blocksize;
3023 sbp->sb_dblocks = dblocks;
3024 sbp->sb_rblocks = rtblocks;
3025 sbp->sb_rextents = rtextents;
3026 platform_uuid_copy(&sbp->sb_uuid, &uuid);
3027 /* Only in memory; libxfs expects this as if read from disk */
3028 platform_uuid_copy(&sbp->sb_meta_uuid, &uuid);
3029 sbp->sb_logstart = logstart;
3030 sbp->sb_rootino = sbp->sb_rbmino = sbp->sb_rsumino = NULLFSINO;
3031 sbp->sb_rextsize = rtextblocks;
3032 sbp->sb_agcount = (xfs_agnumber_t)agcount;
3033 sbp->sb_rbmblocks = nbmblocks;
3034 sbp->sb_logblocks = (xfs_extlen_t)logblocks;
3035 sbp->sb_sectsize = (uint16_t)sectorsize;
3036 sbp->sb_inodesize = (uint16_t)isize;
3037 sbp->sb_inopblock = (uint16_t)(blocksize / isize);
3038 sbp->sb_sectlog = (uint8_t)sectorlog;
3039 sbp->sb_inodelog = (uint8_t)inodelog;
3040 sbp->sb_inopblog = (uint8_t)(blocklog - inodelog);
3041 sbp->sb_rextslog =
3042 (uint8_t)(rtextents ?
3043 libxfs_highbit32((unsigned int)rtextents) : 0);
3044 sbp->sb_inprogress = 1; /* mkfs is in progress */
3045 sbp->sb_imax_pct = imaxpct;
3046 sbp->sb_icount = 0;
3047 sbp->sb_ifree = 0;
3048 sbp->sb_fdblocks = dblocks - agcount * libxfs_prealloc_blocks(mp) -
3049 (loginternal ? logblocks : 0);
3050 sbp->sb_frextents = 0; /* will do a free later */
3051 sbp->sb_uquotino = sbp->sb_gquotino = sbp->sb_pquotino = 0;
3052 sbp->sb_qflags = 0;
3053 sbp->sb_unit = dsunit;
3054 sbp->sb_width = dswidth;
3055 sbp->sb_dirblklog = dirblocklog - blocklog;
3056 if (sb_feat.log_version == 2) { /* This is stored in bytes */
3057 lsunit = (lsunit == 0) ? 1 : XFS_FSB_TO_B(mp, lsunit);
3058 sbp->sb_logsunit = lsunit;
3059 } else
3060 sbp->sb_logsunit = 0;
3061 if (sb_feat.inode_align) {
3062 int cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
3063 if (sb_feat.crcs_enabled)
3064 cluster_size *= isize / XFS_DINODE_MIN_SIZE;
3065 sbp->sb_inoalignmt = cluster_size >> blocklog;
3066 sb_feat.inode_align = sbp->sb_inoalignmt != 0;
3067 } else
3068 sbp->sb_inoalignmt = 0;
3069 if (lsectorsize != BBSIZE || sectorsize != BBSIZE) {
3070 sbp->sb_logsectlog = (uint8_t)lsectorlog;
3071 sbp->sb_logsectsize = (uint16_t)lsectorsize;
3072 } else {
3073 sbp->sb_logsectlog = 0;
3074 sbp->sb_logsectsize = 0;
3075 }
3076
3077 sb_set_features(&mp->m_sb, &sb_feat, sectorsize, lsectorsize, dsunit);
3078
3079 if (force_overwrite)
3080 zero_old_xfs_structures(&xi, sbp);
3081
3082 /*
3083 * Zero out the beginning of the device, to obliterate any old
3084 * filesystem signatures out there. This should take care of
3085 * swap (somewhere around the page size), jfs (32k),
3086 * ext[2,3] and reiserfs (64k) - and hopefully all else.
3087 */
3088 libxfs_buftarg_init(mp, xi.ddev, xi.logdev, xi.rtdev);
3089 buf = libxfs_getbuf(mp->m_ddev_targp, 0, BTOBB(WHACK_SIZE));
3090 memset(XFS_BUF_PTR(buf), 0, WHACK_SIZE);
3091 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
3092 libxfs_purgebuf(buf);
3093
3094 /* OK, now write the superblock */
3095 buf = libxfs_getbuf(mp->m_ddev_targp, XFS_SB_DADDR, XFS_FSS_TO_BB(mp, 1));
3096 buf->b_ops = &xfs_sb_buf_ops;
3097 memset(XFS_BUF_PTR(buf), 0, sectorsize);
3098 libxfs_sb_to_disk((void *)XFS_BUF_PTR(buf), sbp);
3099 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
3100 libxfs_purgebuf(buf);
3101
3102 /*
3103 * If the data area is a file, then grow it out to its final size
3104 * if needed so that the reads for the end of the device in the mount
3105 * code will succeed.
3106 */
3107 if (xi.disfile && xi.dsize * xi.dbsize < dblocks * blocksize) {
3108 if (ftruncate(xi.dfd, dblocks * blocksize) < 0) {
3109 fprintf(stderr,
3110 _("%s: Growing the data section failed\n"),
3111 progname);
3112 exit(1);
3113 }
3114 }
3115
3116 /*
3117 * Zero out the end of the device, to obliterate any
3118 * old MD RAID (or other) metadata at the end of the device.
3119 * (MD sb is ~64k from the end, take out a wider swath to be sure)
3120 */
3121 if (!xi.disfile) {
3122 buf = libxfs_getbuf(mp->m_ddev_targp,
3123 (xi.dsize - BTOBB(WHACK_SIZE)),
3124 BTOBB(WHACK_SIZE));
3125 memset(XFS_BUF_PTR(buf), 0, WHACK_SIZE);
3126 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
3127 libxfs_purgebuf(buf);
3128 }
3129
3130 /*
3131 * Zero the log....
3132 */
3133 libxfs_log_clear(mp->m_logdev_targp, NULL,
3134 XFS_FSB_TO_DADDR(mp, logstart),
3135 (xfs_extlen_t)XFS_FSB_TO_BB(mp, logblocks),
3136 &sbp->sb_uuid, sb_feat.log_version, lsunit, XLOG_FMT, XLOG_INIT_CYCLE, false);
3137
3138 mp = libxfs_mount(mp, sbp, xi.ddev, xi.logdev, xi.rtdev, 0);
3139 if (mp == NULL) {
3140 fprintf(stderr, _("%s: filesystem failed to initialize\n"),
3141 progname);
3142 exit(1);
3143 }
3144
3145 /*
3146 * XXX: this code is effectively shared with the kernel growfs code.
3147 * These initialisations should be pulled into libxfs to keep the
3148 * kernel/userspace header initialisation code the same.
3149 */
3150 for (agno = 0; agno < agcount; agno++) {
3151 struct xfs_agfl *agfl;
3152 int bucket;
3153 struct xfs_perag *pag = libxfs_perag_get(mp, agno);
3154
3155 /*
3156 * Superblock.
3157 */
3158 buf = libxfs_getbuf(mp->m_ddev_targp,
3159 XFS_AG_DADDR(mp, agno, XFS_SB_DADDR),
3160 XFS_FSS_TO_BB(mp, 1));
3161 buf->b_ops = &xfs_sb_buf_ops;
3162 memset(XFS_BUF_PTR(buf), 0, sectorsize);
3163 libxfs_sb_to_disk((void *)XFS_BUF_PTR(buf), sbp);
3164 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
3165
3166 /*
3167 * AG header block: freespace
3168 */
3169 buf = libxfs_getbuf(mp->m_ddev_targp,
3170 XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
3171 XFS_FSS_TO_BB(mp, 1));
3172 buf->b_ops = &xfs_agf_buf_ops;
3173 agf = XFS_BUF_TO_AGF(buf);
3174 memset(agf, 0, sectorsize);
3175 if (agno == agcount - 1)
3176 agsize = dblocks - (xfs_rfsblock_t)(agno * agsize);
3177 agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
3178 agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
3179 agf->agf_seqno = cpu_to_be32(agno);
3180 agf->agf_length = cpu_to_be32(agsize);
3181 agf->agf_roots[XFS_BTNUM_BNOi] = cpu_to_be32(XFS_BNO_BLOCK(mp));
3182 agf->agf_roots[XFS_BTNUM_CNTi] = cpu_to_be32(XFS_CNT_BLOCK(mp));
3183 agf->agf_levels[XFS_BTNUM_BNOi] = cpu_to_be32(1);
3184 agf->agf_levels[XFS_BTNUM_CNTi] = cpu_to_be32(1);
3185 pag->pagf_levels[XFS_BTNUM_BNOi] = 1;
3186 pag->pagf_levels[XFS_BTNUM_CNTi] = 1;
3187 if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
3188 agf->agf_roots[XFS_BTNUM_RMAPi] =
3189 cpu_to_be32(XFS_RMAP_BLOCK(mp));
3190 agf->agf_levels[XFS_BTNUM_RMAPi] = cpu_to_be32(1);
3191 agf->agf_rmap_blocks = cpu_to_be32(1);
3192 }
3193 if (xfs_sb_version_hasreflink(&mp->m_sb)) {
3194 agf->agf_refcount_root = cpu_to_be32(
3195 libxfs_refc_block(mp));
3196 agf->agf_refcount_level = cpu_to_be32(1);
3197 agf->agf_refcount_blocks = cpu_to_be32(1);
3198 }
3199 agf->agf_flfirst = 0;
3200 agf->agf_fllast = cpu_to_be32(XFS_AGFL_SIZE(mp) - 1);
3201 agf->agf_flcount = 0;
3202 nbmblocks = (xfs_extlen_t)(agsize - libxfs_prealloc_blocks(mp));
3203 agf->agf_freeblks = cpu_to_be32(nbmblocks);
3204 agf->agf_longest = cpu_to_be32(nbmblocks);
3205 if (xfs_sb_version_hascrc(&mp->m_sb))
3206 platform_uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_uuid);
3207
3208 if (loginternal && agno == logagno) {
3209 be32_add_cpu(&agf->agf_freeblks, -logblocks);
3210 agf->agf_longest = cpu_to_be32(agsize -
3211 XFS_FSB_TO_AGBNO(mp, logstart) - logblocks);
3212 }
3213 if (libxfs_alloc_min_freelist(mp, pag) > worst_freelist)
3214 worst_freelist = libxfs_alloc_min_freelist(mp, pag);
3215 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
3216
3217 /*
3218 * AG freelist header block
3219 */
3220 buf = libxfs_getbuf(mp->m_ddev_targp,
3221 XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)),
3222 XFS_FSS_TO_BB(mp, 1));
3223 buf->b_ops = &xfs_agfl_buf_ops;
3224 agfl = XFS_BUF_TO_AGFL(buf);
3225 /* setting to 0xff results in initialisation to NULLAGBLOCK */
3226 memset(agfl, 0xff, sectorsize);
3227 if (xfs_sb_version_hascrc(&mp->m_sb)) {
3228 agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC);
3229 agfl->agfl_seqno = cpu_to_be32(agno);
3230 platform_uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_uuid);
3231 for (bucket = 0; bucket < XFS_AGFL_SIZE(mp); bucket++)
3232 agfl->agfl_bno[bucket] = cpu_to_be32(NULLAGBLOCK);
3233 }
3234
3235 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
3236
3237 /*
3238 * AG header block: inodes
3239 */
3240 buf = libxfs_getbuf(mp->m_ddev_targp,
3241 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
3242 XFS_FSS_TO_BB(mp, 1));
3243 agi = XFS_BUF_TO_AGI(buf);
3244 buf->b_ops = &xfs_agi_buf_ops;
3245 memset(agi, 0, sectorsize);
3246 agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
3247 agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);
3248 agi->agi_seqno = cpu_to_be32(agno);
3249 agi->agi_length = cpu_to_be32((xfs_agblock_t)agsize);
3250 agi->agi_count = 0;
3251 agi->agi_root = cpu_to_be32(XFS_IBT_BLOCK(mp));
3252 agi->agi_level = cpu_to_be32(1);
3253 if (sb_feat.finobt) {
3254 agi->agi_free_root = cpu_to_be32(XFS_FIBT_BLOCK(mp));
3255 agi->agi_free_level = cpu_to_be32(1);
3256 }
3257 agi->agi_freecount = 0;
3258 agi->agi_newino = cpu_to_be32(NULLAGINO);
3259 agi->agi_dirino = cpu_to_be32(NULLAGINO);
3260 if (xfs_sb_version_hascrc(&mp->m_sb))
3261 platform_uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_uuid);
3262 for (c = 0; c < XFS_AGI_UNLINKED_BUCKETS; c++)
3263 agi->agi_unlinked[c] = cpu_to_be32(NULLAGINO);
3264 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
3265
3266 /*
3267 * BNO btree root block
3268 */
3269 buf = libxfs_getbuf(mp->m_ddev_targp,
3270 XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)),
3271 bsize);
3272 buf->b_ops = &xfs_allocbt_buf_ops;
3273 block = XFS_BUF_TO_BLOCK(buf);
3274 memset(block, 0, blocksize);
3275 libxfs_btree_init_block(mp, buf, XFS_BTNUM_BNO, 0, 1, agno, 0);
3276
3277 arec = XFS_ALLOC_REC_ADDR(mp, block, 1);
3278 arec->ar_startblock = cpu_to_be32(libxfs_prealloc_blocks(mp));
3279 if (loginternal && agno == logagno) {
3280 if (lalign) {
3281 /*
3282 * Have to insert two records
3283 * Insert pad record for stripe align of log
3284 */
3285 arec->ar_blockcount = cpu_to_be32(
3286 XFS_FSB_TO_AGBNO(mp, logstart) -
3287 be32_to_cpu(arec->ar_startblock));
3288 nrec = arec + 1;
3289 /*
3290 * Insert record at start of internal log
3291 */
3292 nrec->ar_startblock = cpu_to_be32(
3293 be32_to_cpu(arec->ar_startblock) +
3294 be32_to_cpu(arec->ar_blockcount));
3295 arec = nrec;
3296 be16_add_cpu(&block->bb_numrecs, 1);
3297 }
3298 /*
3299 * Change record start to after the internal log
3300 */
3301 be32_add_cpu(&arec->ar_startblock, logblocks);
3302 }
3303 /*
3304 * Calculate the record block count and check for the case where
3305 * the log might have consumed all available space in the AG. If
3306 * so, reset the record count to 0 to avoid exposure of an invalid
3307 * record start block.
3308 */
3309 arec->ar_blockcount = cpu_to_be32(agsize -
3310 be32_to_cpu(arec->ar_startblock));
3311 if (!arec->ar_blockcount)
3312 block->bb_numrecs = 0;
3313
3314 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
3315
3316 /*
3317 * CNT btree root block
3318 */
3319 buf = libxfs_getbuf(mp->m_ddev_targp,
3320 XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)),
3321 bsize);
3322 buf->b_ops = &xfs_allocbt_buf_ops;
3323 block = XFS_BUF_TO_BLOCK(buf);
3324 memset(block, 0, blocksize);
3325 libxfs_btree_init_block(mp, buf, XFS_BTNUM_CNT, 0, 1, agno, 0);
3326
3327 arec = XFS_ALLOC_REC_ADDR(mp, block, 1);
3328 arec->ar_startblock = cpu_to_be32(libxfs_prealloc_blocks(mp));
3329 if (loginternal && agno == logagno) {
3330 if (lalign) {
3331 arec->ar_blockcount = cpu_to_be32(
3332 XFS_FSB_TO_AGBNO(mp, logstart) -
3333 be32_to_cpu(arec->ar_startblock));
3334 nrec = arec + 1;
3335 nrec->ar_startblock = cpu_to_be32(
3336 be32_to_cpu(arec->ar_startblock) +
3337 be32_to_cpu(arec->ar_blockcount));
3338 arec = nrec;
3339 be16_add_cpu(&block->bb_numrecs, 1);
3340 }
3341 be32_add_cpu(&arec->ar_startblock, logblocks);
3342 }
3343 /*
3344 * Calculate the record block count and check for the case where
3345 * the log might have consumed all available space in the AG. If
3346 * so, reset the record count to 0 to avoid exposure of an invalid
3347 * record start block.
3348 */
3349 arec->ar_blockcount = cpu_to_be32(agsize -
3350 be32_to_cpu(arec->ar_startblock));
3351 if (!arec->ar_blockcount)
3352 block->bb_numrecs = 0;
3353
3354 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
3355
3356 /*
3357 * refcount btree root block
3358 */
3359 if (xfs_sb_version_hasreflink(&mp->m_sb)) {
3360 buf = libxfs_getbuf(mp->m_ddev_targp,
3361 XFS_AGB_TO_DADDR(mp, agno,
3362 libxfs_refc_block(mp)),
3363 bsize);
3364 buf->b_ops = &xfs_refcountbt_buf_ops;
3365
3366 block = XFS_BUF_TO_BLOCK(buf);
3367 memset(block, 0, blocksize);
3368 libxfs_btree_init_block(mp, buf, XFS_BTNUM_REFC, 0,
3369 0, agno, 0);
3370
3371 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
3372 }
3373
3374 /*
3375 * INO btree root block
3376 */
3377 buf = libxfs_getbuf(mp->m_ddev_targp,
3378 XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)),
3379 bsize);
3380 buf->b_ops = &xfs_inobt_buf_ops;
3381 block = XFS_BUF_TO_BLOCK(buf);
3382 memset(block, 0, blocksize);
3383 libxfs_btree_init_block(mp, buf, XFS_BTNUM_INO, 0, 0, agno, 0);
3384 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
3385
3386 /*
3387 * Free INO btree root block
3388 */
3389 if (sb_feat.finobt) {
3390 buf = libxfs_getbuf(mp->m_ddev_targp,
3391 XFS_AGB_TO_DADDR(mp, agno, XFS_FIBT_BLOCK(mp)),
3392 bsize);
3393 buf->b_ops = &xfs_inobt_buf_ops;
3394 block = XFS_BUF_TO_BLOCK(buf);
3395 memset(block, 0, blocksize);
3396 libxfs_btree_init_block(mp, buf, XFS_BTNUM_FINO, 0, 0, agno, 0);
3397 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
3398 }
3399
3400 /* RMAP btree root block */
3401 if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
3402 struct xfs_rmap_rec *rrec;
3403
3404 buf = libxfs_getbuf(mp->m_ddev_targp,
3405 XFS_AGB_TO_DADDR(mp, agno, XFS_RMAP_BLOCK(mp)),
3406 bsize);
3407 buf->b_ops = &xfs_rmapbt_buf_ops;
3408 block = XFS_BUF_TO_BLOCK(buf);
3409 memset(block, 0, blocksize);
3410
3411 libxfs_btree_init_block(mp, buf, XFS_BTNUM_RMAP, 0, 0, agno, 0);
3412
3413 /*
3414 * mark the AG header regions as static metadata
3415 * The BNO btree block is the first block after the
3416 * headers, so it's location defines the size of region
3417 * the static metadata consumes.
3418 */
3419 rrec = XFS_RMAP_REC_ADDR(block, 1);
3420 rrec->rm_startblock = 0;
3421 rrec->rm_blockcount = cpu_to_be32(XFS_BNO_BLOCK(mp));
3422 rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_FS);
3423 rrec->rm_offset = 0;
3424 be16_add_cpu(&block->bb_numrecs, 1);
3425
3426 /* account freespace btree root blocks */
3427 rrec = XFS_RMAP_REC_ADDR(block, 2);
3428 rrec->rm_startblock = cpu_to_be32(XFS_BNO_BLOCK(mp));
3429 rrec->rm_blockcount = cpu_to_be32(2);
3430 rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_AG);
3431 rrec->rm_offset = 0;
3432 be16_add_cpu(&block->bb_numrecs, 1);
3433
3434 /* account inode btree root blocks */
3435 rrec = XFS_RMAP_REC_ADDR(block, 3);
3436 rrec->rm_startblock = cpu_to_be32(XFS_IBT_BLOCK(mp));
3437 rrec->rm_blockcount = cpu_to_be32(XFS_RMAP_BLOCK(mp) -
3438 XFS_IBT_BLOCK(mp));
3439 rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_INOBT);
3440 rrec->rm_offset = 0;
3441 be16_add_cpu(&block->bb_numrecs, 1);
3442
3443 /* account for rmap btree root */
3444 rrec = XFS_RMAP_REC_ADDR(block, 4);
3445 rrec->rm_startblock = cpu_to_be32(XFS_RMAP_BLOCK(mp));
3446 rrec->rm_blockcount = cpu_to_be32(1);
3447 rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_AG);
3448 rrec->rm_offset = 0;
3449 be16_add_cpu(&block->bb_numrecs, 1);
3450
3451 /* account for refcount btree root */
3452 if (xfs_sb_version_hasreflink(&mp->m_sb)) {
3453 rrec = XFS_RMAP_REC_ADDR(block, 5);
3454 rrec->rm_startblock = cpu_to_be32(
3455 libxfs_refc_block(mp));
3456 rrec->rm_blockcount = cpu_to_be32(1);
3457 rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_REFC);
3458 rrec->rm_offset = 0;
3459 be16_add_cpu(&block->bb_numrecs, 1);
3460 }
3461
3462 /* account for the log space */
3463 if (loginternal && agno == logagno) {
3464 rrec = XFS_RMAP_REC_ADDR(block,
3465 be16_to_cpu(block->bb_numrecs) + 1);
3466 rrec->rm_startblock = cpu_to_be32(
3467 XFS_FSB_TO_AGBNO(mp, logstart));
3468 rrec->rm_blockcount = cpu_to_be32(logblocks);
3469 rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_LOG);
3470 rrec->rm_offset = 0;
3471 be16_add_cpu(&block->bb_numrecs, 1);
3472 }
3473
3474 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
3475 }
3476
3477 libxfs_perag_put(pag);
3478 }
3479
3480 /*
3481 * Touch last block, make fs the right size if it's a file.
3482 */
3483 buf = libxfs_getbuf(mp->m_ddev_targp,
3484 (xfs_daddr_t)XFS_FSB_TO_BB(mp, dblocks - 1LL), bsize);
3485 memset(XFS_BUF_PTR(buf), 0, blocksize);
3486 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
3487
3488 /*
3489 * Make sure we can write the last block in the realtime area.
3490 */
3491 if (mp->m_rtdev_targp->dev && rtblocks > 0) {
3492 buf = libxfs_getbuf(mp->m_rtdev_targp,
3493 XFS_FSB_TO_BB(mp, rtblocks - 1LL), bsize);
3494 memset(XFS_BUF_PTR(buf), 0, blocksize);
3495 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
3496 }
3497
3498 /*
3499 * BNO, CNT free block list
3500 */
3501 for (agno = 0; agno < agcount; agno++) {
3502 xfs_alloc_arg_t args;
3503 xfs_trans_t *tp;
3504 struct xfs_trans_res tres = {0};
3505
3506 c = libxfs_trans_alloc(mp, &tres, worst_freelist, 0, 0, &tp);
3507 if (c)
3508 res_failed(c);
3509
3510 memset(&args, 0, sizeof(args));
3511 args.tp = tp;
3512 args.mp = mp;
3513 args.agno = agno;
3514 args.alignment = 1;
3515 args.pag = libxfs_perag_get(mp,agno);
3516
3517 libxfs_alloc_fix_freelist(&args, 0);
3518 libxfs_perag_put(args.pag);
3519 libxfs_trans_commit(tp);
3520 }
3521
3522 /*
3523 * Allocate the root inode and anything else in the proto file.
3524 */
3525 parse_proto(mp, &fsx, &protostring);
3526
3527 /*
3528 * Protect ourselves against possible stupidity
3529 */
3530 if (XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino) != 0) {
3531 fprintf(stderr,
3532 _("%s: root inode created in AG %u, not AG 0\n"),
3533 progname, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino));
3534 exit(1);
3535 }
3536
3537 /*
3538 * Write out multiple secondary superblocks with rootinode field set
3539 */
3540 if (mp->m_sb.sb_agcount > 1) {
3541 /*
3542 * the last superblock
3543 */
3544 buf = libxfs_readbuf(mp->m_dev,
3545 XFS_AGB_TO_DADDR(mp, mp->m_sb.sb_agcount-1,
3546 XFS_SB_DADDR),
3547 XFS_FSS_TO_BB(mp, 1),
3548 LIBXFS_EXIT_ON_FAILURE, &xfs_sb_buf_ops);
3549 XFS_BUF_TO_SBP(buf)->sb_rootino = cpu_to_be64(
3550 mp->m_sb.sb_rootino);
3551 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
3552 /*
3553 * and one in the middle for luck
3554 */
3555 if (mp->m_sb.sb_agcount > 2) {
3556 buf = libxfs_readbuf(mp->m_dev,
3557 XFS_AGB_TO_DADDR(mp, (mp->m_sb.sb_agcount-1)/2,
3558 XFS_SB_DADDR),
3559 XFS_FSS_TO_BB(mp, 1),
3560 LIBXFS_EXIT_ON_FAILURE, &xfs_sb_buf_ops);
3561 XFS_BUF_TO_SBP(buf)->sb_rootino = cpu_to_be64(
3562 mp->m_sb.sb_rootino);
3563 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
3564 }
3565 }
3566
3567 /*
3568 * Dump all inodes and buffers before marking us all done.
3569 * Need to drop references to inodes we still hold, first.
3570 */
3571 libxfs_rtmount_destroy(mp);
3572 libxfs_bcache_purge();
3573
3574 /*
3575 * Mark the filesystem ok.
3576 */
3577 buf = libxfs_getsb(mp, LIBXFS_EXIT_ON_FAILURE);
3578 (XFS_BUF_TO_SBP(buf))->sb_inprogress = 0;
3579 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
3580
3581 libxfs_umount(mp);
3582 if (xi.rtdev)
3583 libxfs_device_close(xi.rtdev);
3584 if (xi.logdev && xi.logdev != xi.ddev)
3585 libxfs_device_close(xi.logdev);
3586 libxfs_device_close(xi.ddev);
3587
3588 return 0;
3589 }
3590
3591 static void
3592 conflict(
3593 char opt,
3594 const char *tab[],
3595 int oldidx,
3596 int newidx)
3597 {
3598 fprintf(stderr, _("Cannot specify both -%c %s and -%c %s\n"),
3599 opt, tab[oldidx], opt, tab[newidx]);
3600 usage();
3601 }
3602
3603
3604 static void
3605 illegal(
3606 const char *value,
3607 const char *opt)
3608 {
3609 fprintf(stderr, _("Illegal value %s for -%s option\n"), value, opt);
3610 usage();
3611 }
3612
3613 static int
3614 ispow2(
3615 unsigned int i)
3616 {
3617 return (i & (i - 1)) == 0;
3618 }
3619
3620 static void __attribute__((noreturn))
3621 reqval(
3622 char opt,
3623 const char *tab[],
3624 int idx)
3625 {
3626 fprintf(stderr, _("-%c %s option requires a value\n"), opt, tab[idx]);
3627 usage();
3628 }
3629
3630 static void
3631 respec(
3632 char opt,
3633 const char *tab[],
3634 int idx)
3635 {
3636 fprintf(stderr, "-%c ", opt);
3637 if (tab)
3638 fprintf(stderr, "%s ", tab[idx]);
3639 fprintf(stderr, _("option respecified\n"));
3640 usage();
3641 }
3642
3643 static void
3644 unknown(
3645 char opt,
3646 char *s)
3647 {
3648 fprintf(stderr, _("unknown option -%c %s\n"), opt, s);
3649 usage();
3650 }
3651
3652 long long
3653 cvtnum(
3654 unsigned int blksize,
3655 unsigned int sectsize,
3656 const char *s)
3657 {
3658 long long i;
3659 char *sp;
3660 int c;
3661
3662 i = strtoll(s, &sp, 0);
3663 if (i == 0 && sp == s)
3664 return -1LL;
3665 if (*sp == '\0')
3666 return i;
3667
3668 if (sp[1] != '\0')
3669 return -1LL;
3670
3671 if (*sp == 'b') {
3672 if (!blksize) {
3673 fprintf(stderr,
3674 _("Blocksize must be provided prior to using 'b' suffix.\n"));
3675 usage();
3676 } else {
3677 return i * blksize;
3678 }
3679 }
3680 if (*sp == 's') {
3681 if (!sectsize) {
3682 fprintf(stderr,
3683 _("Sectorsize must be specified prior to using 's' suffix.\n"));
3684 usage();
3685 } else {
3686 return i * sectsize;
3687 }
3688 }
3689
3690 c = tolower(*sp);
3691 switch (c) {
3692 case 'e':
3693 i *= 1024LL;
3694 /* fall through */
3695 case 'p':
3696 i *= 1024LL;
3697 /* fall through */
3698 case 't':
3699 i *= 1024LL;
3700 /* fall through */
3701 case 'g':
3702 i *= 1024LL;
3703 /* fall through */
3704 case 'm':
3705 i *= 1024LL;
3706 /* fall through */
3707 case 'k':
3708 return i * 1024LL;
3709 default:
3710 break;
3711 }
3712 return -1LL;
3713 }
3714
3715 static void __attribute__((noreturn))
3716 usage( void )
3717 {
3718 fprintf(stderr, _("Usage: %s\n\
3719 /* blocksize */ [-b log=n|size=num]\n\
3720 /* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1]\n\
3721 /* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\
3722 (sunit=value,swidth=value|su=num,sw=num|noalign),\n\
3723 sectlog=n|sectsize=num\n\
3724 /* force overwrite */ [-f]\n\
3725 /* inode size */ [-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2,\n\
3726 projid32bit=0|1,sparse=0|1]\n\
3727 /* no discard */ [-K]\n\
3728 /* log subvol */ [-l agnum=n,internal,size=num,logdev=xxx,version=n\n\
3729 sunit=value|su=num,sectlog=n|sectsize=num,\n\
3730 lazy-count=0|1]\n\
3731 /* label */ [-L label (maximum 12 characters)]\n\
3732 /* naming */ [-n log=n|size=num,version=2|ci,ftype=0|1]\n\
3733 /* no-op info only */ [-N]\n\
3734 /* prototype file */ [-p fname]\n\
3735 /* quiet */ [-q]\n\
3736 /* realtime subvol */ [-r extsize=num,size=num,rtdev=xxx]\n\
3737 /* sectorsize */ [-s log=n|size=num]\n\
3738 /* version */ [-V]\n\
3739 devicename\n\
3740 <devicename> is required unless -d name=xxx is given.\n\
3741 <num> is xxx (bytes), xxxs (sectors), xxxb (fs blocks), xxxk (xxx KiB),\n\
3742 xxxm (xxx MiB), xxxg (xxx GiB), xxxt (xxx TiB) or xxxp (xxx PiB).\n\
3743 <value> is xxx (512 byte blocks).\n"),
3744 progname);
3745 exit(1);
3746 }