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