]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - mkfs/xfs_mkfs.c
mkfs: factor writing AG headers
[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
14f8b681
DW
865#define TERABYTES(count, blog) ((uint64_t)(count) << (40 - (blog)))
866#define GIGABYTES(count, blog) ((uint64_t)(count) << (30 - (blog)))
867#define MEGABYTES(count, blog) ((uint64_t)(count) << (20 - (blog)))
1f1b8be7 868
2bd0ea18 869/*
9440d84d 870 * Use this macro before we have superblock and mount structure
2bd0ea18 871 */
5a35bf2c 872#define DTOBT(d) ((xfs_rfsblock_t)((d) >> (blocklog - BBSHIFT)))
2bd0ea18
NS
873
874/*
875 * Use this for block reservations needed for mkfs's conditions
876 * (basically no fragmentation).
877 */
878#define MKFS_BLOCKRES_INODE \
ff105f75 879 ((uint)(mp->m_ialloc_blks + (mp->m_in_maxlevels - 1)))
2bd0ea18
NS
880#define MKFS_BLOCKRES(rb) \
881 ((uint)(MKFS_BLOCKRES_INODE + XFS_DA_NODE_MAXDEPTH + \
882 (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1) + (rb)))
883
5c617c87
ES
884/* amount (in bytes) we zero at the beginning and end of the device to
885 * remove traces of other filesystems, raid superblocks, etc.
886 */
887#define WHACK_SIZE (128 * 1024)
888
587636b1
JT
889/*
890 * Convert lsu to lsunit for 512 bytes blocks and check validity of the values.
891 */
3fbc9137 892static void
9440d84d
NS
893calc_stripe_factors(
894 int dsu,
895 int dsw,
896 int dsectsz,
897 int lsu,
898 int lsectsz,
899 int *dsunit,
900 int *dswidth,
901 int *lsunit)
3fbc9137 902{
9e017777 903 /* Handle data sunit/swidth options */
3ec1956a
DC
904 if ((*dsunit && !*dswidth) || (!*dsunit && *dswidth)) {
905 fprintf(stderr,
906 _("both data sunit and data swidth options "
907 "must be specified\n"));
908 usage();
3fbc9137
NS
909 }
910
911 if (dsu || dsw) {
3fbc9137
NS
912 if ((dsu && !dsw) || (!dsu && dsw)) {
913 fprintf(stderr,
9440d84d
NS
914 _("both data su and data sw options "
915 "must be specified\n"));
3fbc9137
NS
916 usage();
917 }
918
9440d84d
NS
919 if (dsu % dsectsz) {
920 fprintf(stderr,
921 _("data su must be a multiple of the "
922 "sector size (%d)\n"), dsectsz);
3fbc9137
NS
923 usage();
924 }
925
926 *dsunit = (int)BTOBBT(dsu);
927 *dswidth = *dsunit * dsw;
928 }
929
930 if (*dsunit && (*dswidth % *dsunit != 0)) {
931 fprintf(stderr,
9440d84d
NS
932 _("data stripe width (%d) must be a multiple of the "
933 "data stripe unit (%d)\n"), *dswidth, *dsunit);
3fbc9137
NS
934 usage();
935 }
9e017777
ES
936
937 /* Handle log sunit options */
938
3ec1956a 939 if (lsu)
9440d84d 940 *lsunit = (int)BTOBBT(lsu);
587636b1
JT
941
942 /* verify if lsu/lsunit is a multiple block size */
943 if (lsu % blocksize != 0) {
944 fprintf(stderr,
945_("log stripe unit (%d) must be a multiple of the block size (%d)\n"),
946 lsu, blocksize);
947 exit(1);
948 }
949 if ((BBTOB(*lsunit) % blocksize != 0)) {
950 fprintf(stderr,
951_("log stripe unit (%d) must be a multiple of the block size (%d)\n"),
952 BBTOB(*lsunit), blocksize);
953 exit(1);
954 }
3fbc9137
NS
955}
956
06ac92fd
DC
957static void
958check_device_type(
959 const char *name,
960 int *isfile,
961 bool no_size,
962 bool no_name,
963 int *create,
964 bool force_overwrite,
965 const char *optname)
966{
f594a0d1 967 struct stat statbuf;
06ac92fd
DC
968
969 if (*isfile && (no_size || no_name)) {
970 fprintf(stderr,
971 _("if -%s file then -%s name and -%s size are required\n"),
972 optname, optname, optname);
973 usage();
974 }
975
976 if (!name) {
977 fprintf(stderr, _("No device name specified\n"));
978 usage();
979 }
980
f594a0d1 981 if (stat(name, &statbuf)) {
06ac92fd
DC
982 if (errno == ENOENT && *isfile) {
983 if (create)
984 *create = 1;
985 return;
986 }
987
988 fprintf(stderr,
989 _("Error accessing specified device %s: %s\n"),
990 name, strerror(errno));
991 usage();
992 return;
993 }
994
995 if (!force_overwrite && check_overwrite(name)) {
996 fprintf(stderr,
997 _("%s: Use the -f option to force overwrite.\n"),
998 progname);
999 exit(1);
1000 }
1001
1002 /*
1003 * We only want to completely truncate and recreate an existing file if
1004 * we were specifically told it was a file. Set the create flag only in
1005 * this case to trigger that behaviour.
1006 */
1007 if (S_ISREG(statbuf.st_mode)) {
1008 if (!*isfile)
1009 *isfile = 1;
1010 else if (create)
1011 *create = 1;
1012 return;
1013 }
1014
1015 if (S_ISBLK(statbuf.st_mode)) {
1016 if (*isfile) {
1017 fprintf(stderr,
1018 _("specified \"-%s file\" on a block device %s\n"),
1019 optname, name);
1020 usage();
1021 }
1022 return;
1023 }
1024
1025 fprintf(stderr,
1026 _("specified device %s not a file or block device\n"),
1027 name);
1028 usage();
1029}
1030
72e527e7
NS
1031static void
1032fixup_log_stripe_unit(
73bf5988 1033 int lsflag,
73bf5988 1034 int sunit,
5a35bf2c 1035 xfs_rfsblock_t *logblocks,
72e527e7 1036 int blocklog)
73bf5988 1037{
14f8b681 1038 uint64_t tmp_logblocks;
73bf5988 1039
72e527e7
NS
1040 /*
1041 * Make sure that the log size is a multiple of the stripe unit
73bf5988
SL
1042 */
1043 if ((*logblocks % sunit) != 0) {
1044 if (!lsflag) {
1045 tmp_logblocks = ((*logblocks + (sunit - 1))
1046 / sunit) * sunit;
1047 /*
1048 * If the log is too large, round down
1049 * instead of round up
1050 */
1051 if ((tmp_logblocks > XFS_MAX_LOG_BLOCKS) ||
1052 ((tmp_logblocks << blocklog) > XFS_MAX_LOG_BYTES)) {
1053 tmp_logblocks = (*logblocks / sunit) * sunit;
1054 }
1055 *logblocks = tmp_logblocks;
1056 } else {
72e527e7
NS
1057 fprintf(stderr, _("log size %lld is not a multiple "
1058 "of the log stripe unit %d\n"),
9440d84d 1059 (long long) *logblocks, sunit);
73bf5988
SL
1060 usage();
1061 }
1062 }
72e527e7
NS
1063}
1064
5a35bf2c 1065static xfs_fsblock_t
72e527e7
NS
1066fixup_internal_log_stripe(
1067 xfs_mount_t *mp,
1068 int lsflag,
5a35bf2c 1069 xfs_fsblock_t logstart,
14f8b681 1070 uint64_t agsize,
72e527e7 1071 int sunit,
5a35bf2c 1072 xfs_rfsblock_t *logblocks,
72e527e7
NS
1073 int blocklog,
1074 int *lalign)
1075{
1076 if ((logstart % sunit) != 0) {
1077 logstart = ((logstart + (sunit - 1))/sunit) * sunit;
1078 *lalign = 1;
1079 }
1080
1081 fixup_log_stripe_unit(lsflag, sunit, logblocks, blocklog);
73bf5988 1082
9440d84d 1083 if (*logblocks > agsize - XFS_FSB_TO_AGBNO(mp, logstart)) {
73bf5988 1084 fprintf(stderr,
9440d84d
NS
1085 _("Due to stripe alignment, the internal log size "
1086 "(%lld) is too large.\n"), (long long) *logblocks);
1087 fprintf(stderr, _("Must fit within an allocation group.\n"));
73bf5988
SL
1088 usage();
1089 }
1090 return logstart;
1091}
2bd0ea18 1092
cfd4ac07 1093void
14f8b681 1094validate_log_size(uint64_t logblocks, int blocklog, int min_logblocks)
cfd4ac07
NS
1095{
1096 if (logblocks < min_logblocks) {
1097 fprintf(stderr,
1098 _("log size %lld blocks too small, minimum size is %d blocks\n"),
1099 (long long)logblocks, min_logblocks);
1100 usage();
1101 }
1102 if (logblocks > XFS_MAX_LOG_BLOCKS) {
1103 fprintf(stderr,
a6634fba 1104 _("log size %lld blocks too large, maximum size is %lld blocks\n"),
cfd4ac07
NS
1105 (long long)logblocks, XFS_MAX_LOG_BLOCKS);
1106 usage();
1107 }
1108 if ((logblocks << blocklog) > XFS_MAX_LOG_BYTES) {
1109 fprintf(stderr,
a6634fba 1110 _("log size %lld bytes too large, maximum size is %lld bytes\n"),
cfd4ac07
NS
1111 (long long)(logblocks << blocklog), XFS_MAX_LOG_BYTES);
1112 usage();
1113 }
1114}
1115
8d537733
NS
1116static int
1117calc_default_imaxpct(
1118 int blocklog,
14f8b681 1119 uint64_t dblocks)
8d537733
NS
1120{
1121 /*
1122 * This returns the % of the disk space that is used for
1123 * inodes, it changes relatively to the FS size:
1124 * - over 50 TB, use 1%,
1125 * - 1TB - 50 TB, use 5%,
1126 * - under 1 TB, use XFS_DFL_IMAXIMUM_PCT (25%).
1127 */
1128
1129 if (dblocks < TERABYTES(1, blocklog)) {
1130 return XFS_DFL_IMAXIMUM_PCT;
1131 } else if (dblocks < TERABYTES(50, blocklog)) {
1132 return 5;
1133 }
1134
1135 return 1;
1136}
1137
1f1b8be7
NS
1138static void
1139validate_ag_geometry(
1140 int blocklog,
14f8b681
DW
1141 uint64_t dblocks,
1142 uint64_t agsize,
1143 uint64_t agcount)
1f1b8be7
NS
1144{
1145 if (agsize < XFS_AG_MIN_BLOCKS(blocklog)) {
1146 fprintf(stderr,
ddf12ea5 1147 _("agsize (%lld blocks) too small, need at least %lld blocks\n"),
1f1b8be7
NS
1148 (long long)agsize,
1149 (long long)XFS_AG_MIN_BLOCKS(blocklog));
1150 usage();
1151 }
1152
1153 if (agsize > XFS_AG_MAX_BLOCKS(blocklog)) {
1154 fprintf(stderr,
ddf12ea5 1155 _("agsize (%lld blocks) too big, maximum is %lld blocks\n"),
1f1b8be7
NS
1156 (long long)agsize,
1157 (long long)XFS_AG_MAX_BLOCKS(blocklog));
1158 usage();
1159 }
1160
1161 if (agsize > dblocks) {
1162 fprintf(stderr,
ddf12ea5 1163 _("agsize (%lld blocks) too big, data area is %lld blocks\n"),
1f1b8be7
NS
1164 (long long)agsize, (long long)dblocks);
1165 usage();
1166 }
1167
1168 if (agsize < XFS_AG_MIN_BLOCKS(blocklog)) {
1169 fprintf(stderr,
1170 _("too many allocation groups for size = %lld\n"),
1171 (long long)agsize);
1172 fprintf(stderr, _("need at most %lld allocation groups\n"),
1173 (long long)(dblocks / XFS_AG_MIN_BLOCKS(blocklog) +
1174 (dblocks % XFS_AG_MIN_BLOCKS(blocklog) != 0)));
1175 usage();
1176 }
1177
1178 if (agsize > XFS_AG_MAX_BLOCKS(blocklog)) {
1179 fprintf(stderr,
1180 _("too few allocation groups for size = %lld\n"), (long long)agsize);
1181 fprintf(stderr,
1182 _("need at least %lld allocation groups\n"),
1e945ba2 1183 (long long)(dblocks / XFS_AG_MAX_BLOCKS(blocklog) +
1f1b8be7
NS
1184 (dblocks % XFS_AG_MAX_BLOCKS(blocklog) != 0)));
1185 usage();
1186 }
1187
1188 /*
1189 * If the last AG is too small, reduce the filesystem size
1190 * and drop the blocks.
1191 */
1192 if ( dblocks % agsize != 0 &&
1193 (dblocks % agsize < XFS_AG_MIN_BLOCKS(blocklog))) {
1194 fprintf(stderr,
1195 _("last AG size %lld blocks too small, minimum size is %lld blocks\n"),
1196 (long long)(dblocks % agsize),
1197 (long long)XFS_AG_MIN_BLOCKS(blocklog));
1198 usage();
1199 }
1200
1201 /*
1202 * If agcount is too large, make it smaller.
1203 */
1204 if (agcount > XFS_MAX_AGNUMBER + 1) {
1205 fprintf(stderr,
1206 _("%lld allocation groups is too many, maximum is %lld\n"),
1207 (long long)agcount, (long long)XFS_MAX_AGNUMBER + 1);
1208 usage();
1209 }
1210}
1211
1e945ba2
BN
1212static void
1213zero_old_xfs_structures(
1214 libxfs_init_t *xi,
1215 xfs_sb_t *new_sb)
1216{
1217 void *buf;
1218 xfs_sb_t sb;
14f8b681 1219 uint32_t bsize;
1e945ba2
BN
1220 int i;
1221 xfs_off_t off;
31daa90b
BF
1222
1223 /*
1224 * We open regular files with O_TRUNC|O_CREAT. Nothing to do here...
1225 */
1226 if (xi->disfile && xi->dcreat)
1227 return;
1e945ba2
BN
1228
1229 /*
ff1f79a7 1230 * read in existing filesystem superblock, use its geometry
1e945ba2
BN
1231 * settings and zero the existing secondary superblocks.
1232 */
1233 buf = memalign(libxfs_device_alignment(), new_sb->sb_sectsize);
1234 if (!buf) {
1235 fprintf(stderr,
1236 _("error reading existing superblock -- failed to memalign buffer\n"));
1237 return;
1238 }
dab9b8d6 1239 memset(buf, 0, new_sb->sb_sectsize);
1e945ba2 1240
06ac92fd
DC
1241 /*
1242 * If we are creating an image file, it might be of zero length at this
1243 * point in time. Hence reading the existing superblock is going to
1244 * return zero bytes. It's not a failure we need to warn about in this
1245 * case.
1246 */
1247 off = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
1248 if (off != new_sb->sb_sectsize) {
1249 if (!xi->disfile)
1250 fprintf(stderr,
1251 _("error reading existing superblock: %s\n"),
1252 strerror(errno));
31daa90b 1253 goto done;
1e945ba2 1254 }
5e656dbb 1255 libxfs_sb_from_disk(&sb, buf);
1e945ba2
BN
1256
1257 /*
1258 * perform same basic superblock validation to make sure we
1259 * actually zero secondary blocks
1260 */
1261 if (sb.sb_magicnum != XFS_SB_MAGIC || sb.sb_blocksize == 0)
1262 goto done;
1263
1264 for (bsize = 1, i = 0; bsize < sb.sb_blocksize &&
1265 i < sizeof(sb.sb_blocksize) * NBBY; i++)
1266 bsize <<= 1;
1267
1268 if (i < XFS_MIN_BLOCKSIZE_LOG || i > XFS_MAX_BLOCKSIZE_LOG ||
1269 i != sb.sb_blocklog)
1270 goto done;
1271
14f8b681
DW
1272 if (sb.sb_dblocks > ((uint64_t)sb.sb_agcount * sb.sb_agblocks) ||
1273 sb.sb_dblocks < ((uint64_t)(sb.sb_agcount - 1) *
1e945ba2
BN
1274 sb.sb_agblocks + XFS_MIN_AG_BLOCKS))
1275 goto done;
1276
1277 /*
c93b0a22 1278 * block size and basic geometry seems alright, zero the secondaries.
1e945ba2 1279 */
dab9b8d6 1280 memset(buf, 0, new_sb->sb_sectsize);
1e945ba2
BN
1281 off = 0;
1282 for (i = 1; i < sb.sb_agcount; i++) {
1283 off += sb.sb_agblocks;
2f9a125c 1284 if (pwrite(xi->dfd, buf, new_sb->sb_sectsize,
1e945ba2
BN
1285 off << sb.sb_blocklog) == -1)
1286 break;
1287 }
1288done:
1289 free(buf);
1290}
1291
ad136b33 1292static void
14f8b681 1293discard_blocks(dev_t dev, uint64_t nsectors)
ad136b33
CH
1294{
1295 int fd;
1296
1297 /*
1298 * We intentionally ignore errors from the discard ioctl. It is
1299 * not necessary for the mkfs functionality but just an optimization.
1300 */
1301 fd = libxfs_device_to_fd(dev);
1302 if (fd > 0)
1303 platform_discard_blocks(fd, 0, nsectors << 9);
1304}
1305
5f1a2100
DC
1306static void
1307sb_set_features(
1308 struct xfs_sb *sbp,
1309 struct sb_feat_args *fp,
1310 int sectsize,
1311 int lsectsize,
1312 int dsunit)
1313{
1314
1315 sbp->sb_versionnum = XFS_DFL_SB_VERSION_BITS;
1316 if (fp->crcs_enabled)
1317 sbp->sb_versionnum |= XFS_SB_VERSION_5;
1318 else
1319 sbp->sb_versionnum |= XFS_SB_VERSION_4;
1320
1321 if (fp->inode_align)
1322 sbp->sb_versionnum |= XFS_SB_VERSION_ALIGNBIT;
1323 if (dsunit)
1324 sbp->sb_versionnum |= XFS_SB_VERSION_DALIGNBIT;
1325 if (fp->log_version == 2)
1326 sbp->sb_versionnum |= XFS_SB_VERSION_LOGV2BIT;
1327 if (fp->attr_version == 1)
1328 sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT;
1329 if (sectsize > BBSIZE || lsectsize > BBSIZE)
1330 sbp->sb_versionnum |= XFS_SB_VERSION_SECTORBIT;
1331 if (fp->nci)
1332 sbp->sb_versionnum |= XFS_SB_VERSION_BORGBIT;
1333
1334
1335 sbp->sb_features2 = 0;
1336 if (fp->lazy_sb_counters)
1337 sbp->sb_features2 |= XFS_SB_VERSION2_LAZYSBCOUNTBIT;
1338 if (!fp->projid16bit)
1339 sbp->sb_features2 |= XFS_SB_VERSION2_PROJID32BIT;
1340 if (fp->parent_pointers)
1341 sbp->sb_features2 |= XFS_SB_VERSION2_PARENTBIT;
1342 if (fp->crcs_enabled)
1343 sbp->sb_features2 |= XFS_SB_VERSION2_CRCBIT;
1344 if (fp->attr_version == 2)
1345 sbp->sb_features2 |= XFS_SB_VERSION2_ATTR2BIT;
1346
1347 /* v5 superblocks have their own feature bit for dirftype */
1348 if (fp->dirftype && !fp->crcs_enabled)
1349 sbp->sb_features2 |= XFS_SB_VERSION2_FTYPE;
1350
1351 /* update whether extended features are in use */
1352 if (sbp->sb_features2 != 0)
1353 sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT;
1354
1355 /*
1356 * Due to a structure alignment issue, sb_features2 ended up in one
1357 * of two locations, the second "incorrect" location represented by
1358 * the sb_bad_features2 field. To avoid older kernels mounting
1359 * filesystems they shouldn't, set both field to the same value.
1360 */
1361 sbp->sb_bad_features2 = sbp->sb_features2;
1362
1363 if (!fp->crcs_enabled)
1364 return;
1365
1366 /* default features for v5 filesystems */
1367 sbp->sb_features_compat = 0;
1368 sbp->sb_features_ro_compat = 0;
1369 sbp->sb_features_incompat = XFS_SB_FEAT_INCOMPAT_FTYPE;
1370 sbp->sb_features_log_incompat = 0;
1371
1372 if (fp->finobt)
1373 sbp->sb_features_ro_compat = XFS_SB_FEAT_RO_COMPAT_FINOBT;
c563396a
DW
1374 if (fp->rmapbt)
1375 sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_RMAPBT;
a5132d9b
DW
1376 if (fp->reflink)
1377 sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_REFLINK;
5f1a2100
DC
1378
1379 /*
1380 * Sparse inode chunk support has two main inode alignment requirements.
1381 * First, sparse chunk alignment must match the cluster size. Second,
1382 * full chunk alignment must match the inode chunk size.
1383 *
1384 * Copy the already calculated/scaled inoalignmt to spino_align and
1385 * update the former to the full inode chunk size.
1386 */
1387 if (fp->spinodes) {
1388 sbp->sb_spino_align = sbp->sb_inoalignmt;
1389 sbp->sb_inoalignmt = XFS_INODES_PER_CHUNK *
1390 sbp->sb_inodesize >> sbp->sb_blocklog;
1391 sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_SPINODES;
1392 }
1393
1394}
1395
a9dad670
DC
1396static __attribute__((noreturn)) void
1397illegal_option(
aa3034d4 1398 const char *value,
a9dad670 1399 struct opt_params *opts,
aa3034d4
JT
1400 int index,
1401 const char *reason)
a9dad670
DC
1402{
1403 fprintf(stderr,
aa3034d4
JT
1404 _("Illegal value %s for -%c %s option. %s\n"),
1405 value, opts->name, opts->subopts[index],
1406 reason ? reason : "");
a9dad670
DC
1407 usage();
1408}
1409
27ae3a59
DC
1410/*
1411 * Check for conflicts and option respecification.
1412 */
1413static void
1414check_opt(
a9dad670 1415 struct opt_params *opts,
27ae3a59
DC
1416 int index,
1417 bool str_seen)
147e0f31 1418{
27ae3a59
DC
1419 struct subopt_param *sp = &opts->subopt_params[index];
1420 int i;
147e0f31 1421
56e4d368
DC
1422 if (sp->index != index) {
1423 fprintf(stderr,
02c3e106 1424 _("Developer screwed up option parsing (%d/%d)! Please report!\n"),
56e4d368 1425 sp->index, index);
05abf43d 1426 reqval(opts->name, opts->subopts, index);
56e4d368
DC
1427 }
1428
27ae3a59
DC
1429 /*
1430 * Check for respecification of the option. This is more complex than it
1431 * seems because some options are parsed twice - once as a string during
1432 * input parsing, then later the string is passed to getnum for
1433 * conversion into a number and bounds checking. Hence the two variables
1434 * used to track the different uses based on the @str parameter passed
1435 * to us.
1436 */
1437 if (!str_seen) {
1438 if (sp->seen)
05abf43d 1439 respec(opts->name, opts->subopts, index);
27ae3a59
DC
1440 sp->seen = true;
1441 } else {
1442 if (sp->str_seen)
05abf43d 1443 respec(opts->name, opts->subopts, index);
27ae3a59
DC
1444 sp->str_seen = true;
1445 }
9090e187 1446
3ec1956a 1447 /* check for conflicts with the option */
27ae3a59
DC
1448 for (i = 0; i < MAX_CONFLICTS; i++) {
1449 int conflict_opt = sp->conflicts[i];
3ec1956a
DC
1450
1451 if (conflict_opt == LAST_CONFLICT)
1452 break;
27ae3a59
DC
1453 if (opts->subopt_params[conflict_opt].seen ||
1454 opts->subopt_params[conflict_opt].str_seen)
05abf43d 1455 conflict(opts->name, opts->subopts,
3ec1956a
DC
1456 conflict_opt, index);
1457 }
27ae3a59 1458}
3ec1956a 1459
27ae3a59
DC
1460static long long
1461getnum(
1462 const char *str,
1463 struct opt_params *opts,
1464 int index)
1465{
1466 struct subopt_param *sp = &opts->subopt_params[index];
1467 long long c;
1468
1469 check_opt(opts, index, false);
6c855628 1470 /* empty strings might just return a default value */
56e4d368
DC
1471 if (!str || *str == '\0') {
1472 if (sp->defaultval == SUBOPT_NEEDS_VAL)
05abf43d 1473 reqval(opts->name, opts->subopts, index);
56e4d368
DC
1474 return sp->defaultval;
1475 }
a9dad670 1476
56e4d368 1477 if (sp->minval == 0 && sp->maxval == 0) {
a9dad670
DC
1478 fprintf(stderr,
1479 _("Option -%c %s has undefined minval/maxval."
1480 "Can't verify value range. This is a bug.\n"),
1481 opts->name, opts->subopts[index]);
1482 exit(1);
1483 }
147e0f31 1484
6c855628
DC
1485 /*
1486 * Some values are pure numbers, others can have suffixes that define
1487 * the units of the number. Those get passed to cvtnum(), otherwise we
1488 * convert it ourselves to guarantee there is no trailing garbage in the
1489 * number.
1490 */
1491 if (sp->convert)
1492 c = cvtnum(blocksize, sectorsize, str);
1493 else {
1494 char *str_end;
1495
1496 c = strtoll(str, &str_end, 0);
1497 if (c == 0 && str_end == str)
aa3034d4 1498 illegal_option(str, opts, index, NULL);
6c855628 1499 if (*str_end != '\0')
aa3034d4 1500 illegal_option(str, opts, index, NULL);
6c855628
DC
1501 }
1502
1503 /* Validity check the result. */
aa3034d4
JT
1504 if (c < sp->minval)
1505 illegal_option(str, opts, index, _("value is too small"));
1506 else if (c > sp->maxval)
1507 illegal_option(str, opts, index, _("value is too large"));
627e74fd 1508 if (sp->is_power_2 && !ispow2(c))
aa3034d4 1509 illegal_option(str, opts, index, _("value must be a power of 2"));
147e0f31
DC
1510 return c;
1511}
1512
27ae3a59
DC
1513/*
1514 * Option is a string - do all the option table work, and check there
1515 * is actually an option string. Otherwise we don't do anything with the string
1516 * here - validation will be done later when the string is converted to a value
1517 * or used as a file/device path.
1518 */
1519static char *
1520getstr(
1521 char *str,
1522 struct opt_params *opts,
1523 int index)
1524{
1525 check_opt(opts, index, true);
1526
1527 /* empty strings for string options are not valid */
1528 if (!str || *str == '\0')
05abf43d 1529 reqval(opts->name, opts->subopts, index);
27ae3a59
DC
1530 return str;
1531}
1532
a350bbc1
DC
1533static int
1534block_opts_parser(
1535 struct opt_params *opts,
1536 int subopt,
1537 char *value,
1538 struct cli_params *cli)
1539{
85d6f03d
DC
1540 int blocklog;
1541
1542 switch (subopt) {
1543 case B_LOG:
1544 blocklog = getnum(value, opts, B_LOG);
1545 cli->blocksize = 1 << blocklog;
1546 break;
1547 case B_SIZE:
1548 cli->blocksize = getnum(value, opts, B_SIZE);
1549 break;
1550 default:
1551 return -EINVAL;
1552 }
a350bbc1
DC
1553 return 0;
1554}
1555
1556static int
1557data_opts_parser(
1558 struct opt_params *opts,
1559 int subopt,
1560 char *value,
1561 struct cli_params *cli)
1562{
a1273b7c
DC
1563 int sectorlog;
1564
1565 switch (subopt) {
1566 case D_AGCOUNT:
1567 cli->agcount = getnum(value, opts, D_AGCOUNT);
1568 break;
1569 case D_AGSIZE:
1570 cli->agsize = getstr(value, opts, D_AGSIZE);
1571 break;
1572 case D_FILE:
1573 cli->xi->disfile = getnum(value, opts, D_FILE);
1574 break;
1575 case D_NAME:
1576 cli->xi->dname = getstr(value, opts, D_NAME);
1577 break;
1578 case D_SIZE:
1579 cli->dsize = getstr(value, opts, D_SIZE);
1580 break;
1581 case D_SUNIT:
1582 cli->dsunit = getnum(value, opts, D_SUNIT);
1583 break;
1584 case D_SWIDTH:
1585 cli->dswidth = getnum(value, opts, D_SWIDTH);
1586 break;
1587 case D_SU:
1588 cli->dsu = getstr(value, opts, D_SU);
1589 break;
1590 case D_SW:
1591 cli->dsw = getnum(value, opts, D_SW);
1592 break;
1593 case D_NOALIGN:
1594 cli->sb_feat.nodalign = getnum(value, opts, D_NOALIGN);
1595 break;
1596 case D_SECTLOG:
1597 if (cli->sectorsize)
1598 conflict('d', opts->subopts, D_SECTSIZE, D_SECTLOG);
1599 sectorlog = getnum(value, opts, D_SECTLOG);
1600 cli->sectorsize = 1 << sectorlog;
1601 break;
1602 case D_SECTSIZE:
1603 if (cli->sectorsize)
1604 conflict('d', opts->subopts, D_SECTSIZE, D_SECTLOG);
1605 cli->sectorsize = getnum(value, opts, D_SECTSIZE);
1606 break;
1607 case D_RTINHERIT:
1608 if (getnum(value, opts, D_RTINHERIT))
1609 cli->fsx.fsx_xflags |= XFS_DIFLAG_RTINHERIT;
1610 break;
1611 case D_PROJINHERIT:
1612 cli->fsx.fsx_projid = getnum(value, opts, D_PROJINHERIT);
1613 cli->fsx.fsx_xflags |= XFS_DIFLAG_PROJINHERIT;
1614 break;
1615 case D_EXTSZINHERIT:
1616 cli->fsx.fsx_extsize = getnum(value, opts, D_EXTSZINHERIT);
1617 cli->fsx.fsx_xflags |= XFS_DIFLAG_EXTSZINHERIT;
1618 break;
1619 case D_COWEXTSIZE:
1620 cli->fsx.fsx_cowextsize = getnum(value, opts, D_COWEXTSIZE);
1621 cli->fsx.fsx_xflags |= FS_XFLAG_COWEXTSIZE;
1622 break;
1623 default:
1624 return -EINVAL;
1625 }
a350bbc1
DC
1626 return 0;
1627}
1628
1629static int
1630inode_opts_parser(
1631 struct opt_params *opts,
1632 int subopt,
1633 char *value,
1634 struct cli_params *cli)
1635{
a3ac5af1
DC
1636 int inodelog;
1637
1638 switch (subopt) {
1639 case I_ALIGN:
1640 cli->sb_feat.inode_align = getnum(value, &iopts, I_ALIGN);
1641 break;
1642 case I_LOG:
1643 inodelog = getnum(value, &iopts, I_LOG);
1644 cli->inodesize = 1 << inodelog;
1645 break;
1646 case I_MAXPCT:
1647 cli->imaxpct = getnum(value, &iopts, I_MAXPCT);
1648 break;
1649 case I_PERBLOCK:
1650 cli->inopblock = getnum(value, &iopts, I_PERBLOCK);
1651 break;
1652 case I_SIZE:
1653 cli->inodesize = getnum(value, &iopts, I_SIZE);
1654 break;
1655 case I_ATTR:
1656 cli->sb_feat.attr_version = getnum(value, &iopts, I_ATTR);
1657 break;
1658 case I_PROJID32BIT:
1659 cli->sb_feat.projid16bit = !getnum(value, &iopts, I_PROJID32BIT);
1660 break;
1661 case I_SPINODES:
1662 cli->sb_feat.spinodes = getnum(value, &iopts, I_SPINODES);
1663 break;
1664 default:
1665 return -EINVAL;
1666 }
a350bbc1
DC
1667 return 0;
1668}
1669
1670static int
1671log_opts_parser(
1672 struct opt_params *opts,
1673 int subopt,
1674 char *value,
1675 struct cli_params *cli)
1676{
f3bc91a4
DC
1677 int lsectorlog;
1678
1679 switch (subopt) {
1680 case L_AGNUM:
1681 cli->logagno = getnum(value, &lopts, L_AGNUM);
1682 break;
1683 case L_FILE:
1684 cli->xi->lisfile = getnum(value, &lopts, L_FILE);
1685 break;
1686 case L_INTERNAL:
1687 cli->loginternal = getnum(value, &lopts, L_INTERNAL);
1688 break;
1689 case L_SU:
1690 cli->lsu = getstr(value, &lopts, L_SU);
1691 break;
1692 case L_SUNIT:
1693 cli->lsunit = getnum(value, &lopts, L_SUNIT);
1694 break;
1695 case L_NAME:
1696 case L_DEV:
1697 cli->xi->logname = getstr(value, &lopts, L_NAME);
1698 cli->loginternal = 0;
1699 break;
1700 case L_VERSION:
1701 cli->sb_feat.log_version = getnum(value, &lopts, L_VERSION);
1702 break;
1703 case L_SIZE:
1704 cli->logsize = getstr(value, &lopts, L_SIZE);
1705 break;
1706 case L_SECTLOG:
1707 lsectorlog = getnum(value, &lopts, L_SECTLOG);
1708 cli->lsectorsize = 1 << lsectorlog;
1709 break;
1710 case L_SECTSIZE:
1711 cli->lsectorsize = getnum(value, &lopts, L_SECTSIZE);
1712 break;
1713 case L_LAZYSBCNTR:
1714 cli->sb_feat.lazy_sb_counters = getnum(value, &lopts, L_LAZYSBCNTR);
1715 break;
1716 default:
1717 return -EINVAL;
1718 }
a350bbc1
DC
1719 return 0;
1720}
1721
1722static int
1723meta_opts_parser(
1724 struct opt_params *opts,
1725 int subopt,
1726 char *value,
1727 struct cli_params *cli)
1728{
997136c6
DC
1729 switch (subopt) {
1730 case M_CRC:
1731 cli->sb_feat.crcs_enabled = getnum(value, &mopts, M_CRC);
1732 if (cli->sb_feat.crcs_enabled)
1733 cli->sb_feat.dirftype = true;
1734 break;
1735 case M_FINOBT:
1736 cli->sb_feat.finobt = getnum(value, &mopts, M_FINOBT);
1737 break;
1738 case M_UUID:
1739 if (!value || *value == '\0')
1740 reqval('m', opts->subopts, M_UUID);
1741 if (platform_uuid_parse(value, &cli->uuid))
1742 illegal(value, "m uuid");
1743 break;
1744 case M_RMAPBT:
1745 cli->sb_feat.rmapbt = getnum(value, &mopts, M_RMAPBT);
1746 break;
1747 case M_REFLINK:
1748 cli->sb_feat.reflink = getnum(value, &mopts, M_REFLINK);
1749 break;
1750 default:
1751 return -EINVAL;
1752 }
a350bbc1
DC
1753 return 0;
1754}
1755
1756static int
1757naming_opts_parser(
1758 struct opt_params *opts,
1759 int subopt,
1760 char *value,
1761 struct cli_params *cli)
1762{
98d40922
DC
1763 switch (subopt) {
1764 case N_LOG:
1765 cli->dirblocklog = getnum(value, opts, N_LOG);
1766 break;
1767 case N_SIZE:
1768 cli->dirblocksize = getstr(value, opts, N_SIZE);
1769 break;
1770 case N_VERSION:
1771 value = getstr(value, &nopts, N_VERSION);
1772 if (!strcasecmp(value, "ci")) {
1773 /* ASCII CI mode */
1774 cli->sb_feat.nci = true;
1775 } else {
1776 cli->sb_feat.dir_version = getnum(value, opts, N_VERSION);
1777 }
1778 break;
1779 case N_FTYPE:
1780 cli->sb_feat.dirftype = getnum(value, opts, N_FTYPE);
1781 break;
1782 default:
1783 return -EINVAL;
1784 }
a350bbc1
DC
1785 return 0;
1786}
1787
1788static int
1789rtdev_opts_parser(
1790 struct opt_params *opts,
1791 int subopt,
1792 char *value,
1793 struct cli_params *cli)
1794{
d145f69d
DC
1795 switch (subopt) {
1796 case R_EXTSIZE:
1797 cli->rtextsize = getstr(value, &ropts, R_EXTSIZE);
1798 break;
1799 case R_FILE:
1800 cli->xi->risfile = getnum(value, &ropts, R_FILE);
1801 break;
1802 case R_NAME:
1803 case R_DEV:
1804 cli->xi->rtname = getstr(value, &ropts, R_NAME);
1805 break;
1806 case R_SIZE:
1807 cli->rtsize = getstr(value, &ropts, R_SIZE);
1808 break;
1809 case R_NOALIGN:
1810 cli->sb_feat.nortalign = getnum(value, &ropts, R_NOALIGN);
1811 break;
1812 default:
1813 return -EINVAL;
1814 }
a350bbc1
DC
1815 return 0;
1816}
1817
1818static int
1819sector_opts_parser(
1820 struct opt_params *opts,
1821 int subopt,
1822 char *value,
1823 struct cli_params *cli)
1824{
f948f00a
DC
1825 int sectorlog;
1826
1827 switch (subopt) {
1828 case S_LOG:
1829 case S_SECTLOG:
1830 if (cli->sectorsize)
1831 conflict('s', opts->subopts, S_SECTSIZE, S_SECTLOG);
1832 sectorlog = getnum(value, &sopts, S_SECTLOG);
1833 cli->sectorsize = 1 << sectorlog;
1834 cli->lsectorsize = cli->sectorsize;
1835 break;
1836 case S_SIZE:
1837 case S_SECTSIZE:
1838 if (cli->sectorsize)
1839 conflict('s', opts->subopts, S_SECTLOG, S_SECTSIZE);
1840 cli->sectorsize = getnum(value, &sopts, S_SECTSIZE);
1841 cli->lsectorsize = cli->sectorsize;
1842 break;
1843 default:
1844 return -EINVAL;
1845 }
a350bbc1
DC
1846 return 0;
1847}
1848
1849struct subopts {
1850 char opt;
1851 struct opt_params *opts;
1852 int (*parser)();
1853} subopt_tab[] = {
1854 { 'b', &bopts, block_opts_parser },
1855 { 'd', &dopts, data_opts_parser },
1856 { 'i', &iopts, inode_opts_parser },
1857 { 'l', &lopts, log_opts_parser },
1858 { 'm', &mopts, meta_opts_parser },
1859 { 'n', &nopts, naming_opts_parser },
1860 { 'r', &ropts, rtdev_opts_parser },
1861 { 's', &sopts, sector_opts_parser },
1862 { '\0', NULL, NULL },
1863};
1864
1865static void
1866parse_subopts(
1867 char opt,
1868 char *arg,
1869 struct cli_params *cli)
1870{
1871 struct subopts *sop = &subopt_tab[0];
1872 char *p;
1873 int ret = 0;
1874
1875 while (sop->opts) {
1876 if (sop->opt == opt)
1877 break;
1878 sop++;
1879 }
1880
1881 /* should never happen */
1882 if (!sop->opts)
1883 return;
1884
1885 p = arg;
1886 while (*p != '\0') {
1887 char **subopts = (char **)sop->opts->subopts;
1888 char *value;
1889 int subopt;
1890
1891 subopt = getsubopt(&p, subopts, &value);
1892
1893 ret = (sop->parser)(sop->opts, subopt, value, cli);
1894 if (ret)
1895 unknown(opt, value);
1896 }
1897}
1898
d1138048
DC
1899static void
1900print_mkfs_cfg(
1901 struct mkfs_params *cfg,
1902 char *dfile,
1903 char *logfile,
1904 char *rtfile)
1905{
1906 struct sb_feat_args *fp = &cfg->sb_feat;
1907
1908 printf(_(
1909"meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n"
1910" =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n"
1911" =%-22s crc=%-8u finobt=%u, sparse=%u, rmapbt=%u, reflink=%u\n"
1912"data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n"
1913" =%-22s sunit=%-6u swidth=%u blks\n"
1914"naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n"
1915"log =%-22s bsize=%-6d blocks=%lld, version=%d\n"
1916" =%-22s sectsz=%-5u sunit=%d blks, lazy-count=%d\n"
1917"realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n"),
1918 dfile, cfg->inodesize, (long long)cfg->agcount,
1919 (long long)cfg->agsize,
1920 "", cfg->sectorsize, fp->attr_version, !fp->projid16bit,
1921 "", fp->crcs_enabled, fp->finobt, fp->spinodes, fp->rmapbt,
1922 fp->reflink,
1923 "", cfg->blocksize, (long long)cfg->dblocks, cfg->imaxpct,
1924 "", cfg->dsunit, cfg->dswidth,
1925 fp->dir_version, cfg->dirblocksize, fp->nci, fp->dirftype,
1926 logfile, cfg->blocksize, (long long)cfg->logblocks,
1927 fp->log_version,
1928 "", cfg->lsectorsize, cfg->lsunit, fp->lazy_sb_counters,
1929 rtfile, (int)cfg->rtextblocks << cfg->blocklog,
1930 (long long)cfg->rtblocks, (long long)cfg->rtextents);
1931}
1932
afda75a5
DC
1933/*
1934 * Format everything from the generated config into the superblock that
1935 * will be used to initialise the on-disk superblock. This is the in-memory
1936 * copy, so no need to care about endian swapping here.
1937 */
1938static void
1939setup_superblock(
1940 struct mkfs_params *cfg,
1941 struct xfs_mount *mp,
1942 struct xfs_sb *sbp)
1943{
1944 if (cfg->label)
1945 strncpy(sbp->sb_fname, cfg->label, sizeof(sbp->sb_fname));
1946
1947 sbp->sb_magicnum = XFS_SB_MAGIC;
1948 sbp->sb_blocksize = cfg->blocksize;
1949 sbp->sb_dblocks = cfg->dblocks;
1950 sbp->sb_rblocks = cfg->rtblocks;
1951 sbp->sb_rextents = cfg->rtextents;
1952 platform_uuid_copy(&sbp->sb_uuid, &cfg->uuid);
1953 /* Only in memory; libxfs expects this as if read from disk */
1954 platform_uuid_copy(&sbp->sb_meta_uuid, &cfg->uuid);
1955 sbp->sb_logstart = cfg->logstart;
1956 sbp->sb_rootino = sbp->sb_rbmino = sbp->sb_rsumino = NULLFSINO;
1957 sbp->sb_rextsize = cfg->rtextblocks;
1958 sbp->sb_agcount = (xfs_agnumber_t)cfg->agcount;
1959 sbp->sb_rbmblocks = cfg->rtbmblocks;
1960 sbp->sb_logblocks = (xfs_extlen_t)cfg->logblocks;
1961 sbp->sb_sectsize = (uint16_t)cfg->sectorsize;
1962 sbp->sb_inodesize = (uint16_t)cfg->inodesize;
1963 sbp->sb_inopblock = (uint16_t)(cfg->blocksize / cfg->inodesize);
1964 sbp->sb_sectlog = (uint8_t)cfg->sectorlog;
1965 sbp->sb_inodelog = (uint8_t)cfg->inodelog;
1966 sbp->sb_inopblog = (uint8_t)(cfg->blocklog - cfg->inodelog);
1967 sbp->sb_rextslog = (uint8_t)(cfg->rtextents ?
1968 libxfs_highbit32((unsigned int)cfg->rtextents) : 0);
1969 sbp->sb_inprogress = 1; /* mkfs is in progress */
1970 sbp->sb_imax_pct = cfg->imaxpct;
1971 sbp->sb_icount = 0;
1972 sbp->sb_ifree = 0;
1973 sbp->sb_fdblocks = cfg->dblocks -
1974 cfg->agcount * libxfs_prealloc_blocks(mp) -
1975 (cfg->loginternal ? cfg->logblocks : 0);
1976 sbp->sb_frextents = 0; /* will do a free later */
1977 sbp->sb_uquotino = sbp->sb_gquotino = sbp->sb_pquotino = 0;
1978 sbp->sb_qflags = 0;
1979 sbp->sb_unit = cfg->dsunit;
1980 sbp->sb_width = cfg->dswidth;
1981 sbp->sb_dirblklog = cfg->dirblocklog - cfg->blocklog;
1982
1983 /*
1984 * log stripe unit is stored in bytes on disk and cannot be zero
1985 * for v2 logs.
1986 */
1987 if (cfg->sb_feat.log_version == 2) {
1988 if (cfg->lsunit)
1989 sbp->sb_logsunit = XFS_FSB_TO_B(mp, cfg->lsunit);
1990 else
1991 sbp->sb_logsunit = 1;
1992 } else
1993 sbp->sb_logsunit = 0;
1994
1995 if (cfg->sb_feat.inode_align) {
1996 int cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
1997 if (cfg->sb_feat.crcs_enabled)
1998 cluster_size *= cfg->inodesize / XFS_DINODE_MIN_SIZE;
1999 sbp->sb_inoalignmt = cluster_size >> cfg->blocklog;
2000 } else
2001 sbp->sb_inoalignmt = 0;
2002
2003 if (cfg->lsectorsize != BBSIZE || cfg->sectorsize != BBSIZE) {
2004 sbp->sb_logsectlog = (uint8_t)cfg->lsectorlog;
2005 sbp->sb_logsectsize = (uint16_t)cfg->lsectorsize;
2006 } else {
2007 sbp->sb_logsectlog = 0;
2008 sbp->sb_logsectsize = 0;
2009 }
2010}
2011
e99bf83d
DC
2012/*
2013 * Sanitise the data and log devices and prepare them so libxfs can mount the
2014 * device successfully. Also check we can access the rt device if configured.
2015 */
2016static void
2017prepare_devices(
2018 struct mkfs_params *cfg,
2019 struct libxfs_xinit *xi,
2020 struct xfs_mount *mp,
2021 struct xfs_sb *sbp,
2022 bool clear_stale)
2023{
2024 struct xfs_buf *buf;
2025 int whack_blks = BTOBB(WHACK_SIZE);
2026 int lsunit;
2027
2028 /*
2029 * If there's an old XFS filesystem on the device with enough intact
2030 * information that we can parse the superblock, there's enough
2031 * information on disk to confuse a future xfs_repair call. To avoid
2032 * this, whack all the old secondary superblocks that we can find.
2033 */
2034 if (clear_stale)
2035 zero_old_xfs_structures(xi, sbp);
2036
2037 /*
2038 * If the data device is a file, grow out the file to its final size if
2039 * needed so that the reads for the end of the device in the mount code
2040 * will succeed.
2041 */
2042 if (xi->disfile &&
2043 xi->dsize * xi->dbsize < cfg->dblocks * cfg->blocksize) {
2044 if (ftruncate(xi->dfd, cfg->dblocks * cfg->blocksize) < 0) {
2045 fprintf(stderr,
2046 _("%s: Growing the data section failed\n"),
2047 progname);
2048 exit(1);
2049 }
2050
2051 /* update size to be able to whack blocks correctly */
2052 xi->dsize = BTOBB(cfg->dblocks * cfg->blocksize);
2053 }
2054
2055 /*
2056 * Zero out the end to obliterate any old MD RAID (or other) metadata at
2057 * the end of the device. (MD sb is ~64k from the end, take out a wider
2058 * swath to be sure)
2059 */
2060 buf = libxfs_getbuf(mp->m_ddev_targp, (xi->dsize - whack_blks),
2061 whack_blks);
2062 memset(XFS_BUF_PTR(buf), 0, WHACK_SIZE);
2063 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2064 libxfs_purgebuf(buf);
2065
2066 /*
2067 * Now zero out the beginning of the device, to obliterate any old
2068 * filesystem signatures out there. This should take care of
2069 * swap (somewhere around the page size), jfs (32k),
2070 * ext[2,3] and reiserfs (64k) - and hopefully all else.
2071 */
2072 buf = libxfs_getbuf(mp->m_ddev_targp, 0, whack_blks);
2073 memset(XFS_BUF_PTR(buf), 0, WHACK_SIZE);
2074 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2075 libxfs_purgebuf(buf);
2076
2077 /* OK, now write the superblock... */
2078 buf = libxfs_getbuf(mp->m_ddev_targp, XFS_SB_DADDR, XFS_FSS_TO_BB(mp, 1));
2079 buf->b_ops = &xfs_sb_buf_ops;
2080 memset(XFS_BUF_PTR(buf), 0, cfg->sectorsize);
2081 libxfs_sb_to_disk((void *)XFS_BUF_PTR(buf), sbp);
2082 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2083 libxfs_purgebuf(buf);
2084
2085 /* ...and zero the log.... */
2086 lsunit = sbp->sb_logsunit;
2087 if (lsunit == 1)
2088 lsunit = sbp->sb_logsectsize;
2089
2090 libxfs_log_clear(mp->m_logdev_targp, NULL,
2091 XFS_FSB_TO_DADDR(mp, cfg->logstart),
2092 (xfs_extlen_t)XFS_FSB_TO_BB(mp, cfg->logblocks),
2093 &sbp->sb_uuid, cfg->sb_feat.log_version,
2094 lsunit, XLOG_FMT, XLOG_INIT_CYCLE, false);
2095
2096 /* finally, check we can write the last block in the realtime area */
2097 if (mp->m_rtdev_targp->dev && cfg->rtblocks > 0) {
2098 buf = libxfs_getbuf(mp->m_rtdev_targp,
2099 XFS_FSB_TO_BB(mp, cfg->rtblocks - 1LL),
2100 BTOBB(cfg->blocksize));
2101 memset(XFS_BUF_PTR(buf), 0, cfg->blocksize);
2102 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2103 libxfs_purgebuf(buf);
2104 }
2105
2106}
2107
0ff1b0ed
DC
2108/*
2109 * XXX: this code is mostly common with the kernel growfs code.
2110 * These initialisations should be pulled into libxfs to keep the
2111 * kernel/userspace header initialisation code the same.
2112 */
2113static void
2114initialise_ag_headers(
2115 struct mkfs_params *cfg,
2116 struct xfs_mount *mp,
2117 struct xfs_sb *sbp,
2118 xfs_agnumber_t agno,
2119 int *worst_freelist)
2120{
2121 struct xfs_perag *pag = libxfs_perag_get(mp, agno);
2122 struct xfs_agfl *agfl;
2123 struct xfs_agf *agf;
2124 struct xfs_agi *agi;
2125 struct xfs_buf *buf;
2126 struct xfs_btree_block *block;
2127 struct xfs_alloc_rec *arec;
2128 struct xfs_alloc_rec *nrec;
2129 int bucket;
2130 uint64_t agsize = cfg->agsize;
2131 xfs_agblock_t agblocks;
2132 bool is_log_ag = false;
2133 int c;
2134
2135 if (cfg->loginternal && agno == cfg->logagno)
2136 is_log_ag = true;
2137
2138 /*
2139 * Superblock.
2140 */
2141 buf = libxfs_getbuf(mp->m_ddev_targp,
2142 XFS_AG_DADDR(mp, agno, XFS_SB_DADDR),
2143 XFS_FSS_TO_BB(mp, 1));
2144 buf->b_ops = &xfs_sb_buf_ops;
2145 memset(XFS_BUF_PTR(buf), 0, cfg->sectorsize);
2146 libxfs_sb_to_disk((void *)XFS_BUF_PTR(buf), sbp);
2147 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2148
2149 /*
2150 * AG header block: freespace
2151 */
2152 buf = libxfs_getbuf(mp->m_ddev_targp,
2153 XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
2154 XFS_FSS_TO_BB(mp, 1));
2155 buf->b_ops = &xfs_agf_buf_ops;
2156 agf = XFS_BUF_TO_AGF(buf);
2157 memset(agf, 0, cfg->sectorsize);
2158 if (agno == cfg->agcount - 1)
2159 agsize = cfg->dblocks - (xfs_rfsblock_t)(agno * agsize);
2160 agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
2161 agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
2162 agf->agf_seqno = cpu_to_be32(agno);
2163 agf->agf_length = cpu_to_be32(agsize);
2164 agf->agf_roots[XFS_BTNUM_BNOi] = cpu_to_be32(XFS_BNO_BLOCK(mp));
2165 agf->agf_roots[XFS_BTNUM_CNTi] = cpu_to_be32(XFS_CNT_BLOCK(mp));
2166 agf->agf_levels[XFS_BTNUM_BNOi] = cpu_to_be32(1);
2167 agf->agf_levels[XFS_BTNUM_CNTi] = cpu_to_be32(1);
2168 pag->pagf_levels[XFS_BTNUM_BNOi] = 1;
2169 pag->pagf_levels[XFS_BTNUM_CNTi] = 1;
2170
2171 if (xfs_sb_version_hasrmapbt(sbp)) {
2172 agf->agf_roots[XFS_BTNUM_RMAPi] = cpu_to_be32(XFS_RMAP_BLOCK(mp));
2173 agf->agf_levels[XFS_BTNUM_RMAPi] = cpu_to_be32(1);
2174 agf->agf_rmap_blocks = cpu_to_be32(1);
2175 }
2176
2177 if (xfs_sb_version_hasreflink(sbp)) {
2178 agf->agf_refcount_root = cpu_to_be32(libxfs_refc_block(mp));
2179 agf->agf_refcount_level = cpu_to_be32(1);
2180 agf->agf_refcount_blocks = cpu_to_be32(1);
2181 }
2182
2183 agf->agf_flfirst = 0;
2184 agf->agf_fllast = cpu_to_be32(XFS_AGFL_SIZE(mp) - 1);
2185 agf->agf_flcount = 0;
2186 agblocks = (xfs_agblock_t)(agsize - libxfs_prealloc_blocks(mp));
2187 agf->agf_freeblks = cpu_to_be32(agblocks);
2188 agf->agf_longest = cpu_to_be32(agblocks);
2189
2190 if (xfs_sb_version_hascrc(sbp))
2191 platform_uuid_copy(&agf->agf_uuid, &sbp->sb_uuid);
2192
2193 if (is_log_ag) {
2194 be32_add_cpu(&agf->agf_freeblks, -(int64_t)cfg->logblocks);
2195 agf->agf_longest = cpu_to_be32(agsize -
2196 XFS_FSB_TO_AGBNO(mp, cfg->logstart) - cfg->logblocks);
2197 }
2198 if (libxfs_alloc_min_freelist(mp, pag) > *worst_freelist)
2199 *worst_freelist = libxfs_alloc_min_freelist(mp, pag);
2200 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2201
2202 /*
2203 * AG freelist header block
2204 */
2205 buf = libxfs_getbuf(mp->m_ddev_targp,
2206 XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)),
2207 XFS_FSS_TO_BB(mp, 1));
2208 buf->b_ops = &xfs_agfl_buf_ops;
2209 agfl = XFS_BUF_TO_AGFL(buf);
2210 /* setting to 0xff results in initialisation to NULLAGBLOCK */
2211 memset(agfl, 0xff, cfg->sectorsize);
2212 if (xfs_sb_version_hascrc(sbp)) {
2213 agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC);
2214 agfl->agfl_seqno = cpu_to_be32(agno);
2215 platform_uuid_copy(&agfl->agfl_uuid, &sbp->sb_uuid);
2216 for (bucket = 0; bucket < XFS_AGFL_SIZE(mp); bucket++)
2217 agfl->agfl_bno[bucket] = cpu_to_be32(NULLAGBLOCK);
2218 }
2219
2220 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2221
2222 /*
2223 * AG header block: inodes
2224 */
2225 buf = libxfs_getbuf(mp->m_ddev_targp,
2226 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
2227 XFS_FSS_TO_BB(mp, 1));
2228 agi = XFS_BUF_TO_AGI(buf);
2229 buf->b_ops = &xfs_agi_buf_ops;
2230 memset(agi, 0, cfg->sectorsize);
2231 agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
2232 agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);
2233 agi->agi_seqno = cpu_to_be32(agno);
2234 agi->agi_length = cpu_to_be32(agsize);
2235 agi->agi_count = 0;
2236 agi->agi_root = cpu_to_be32(XFS_IBT_BLOCK(mp));
2237 agi->agi_level = cpu_to_be32(1);
2238 if (xfs_sb_version_hasfinobt(sbp)) {
2239 agi->agi_free_root = cpu_to_be32(XFS_FIBT_BLOCK(mp));
2240 agi->agi_free_level = cpu_to_be32(1);
2241 }
2242 agi->agi_freecount = 0;
2243 agi->agi_newino = cpu_to_be32(NULLAGINO);
2244 agi->agi_dirino = cpu_to_be32(NULLAGINO);
2245 if (xfs_sb_version_hascrc(sbp))
2246 platform_uuid_copy(&agi->agi_uuid, &sbp->sb_uuid);
2247 for (c = 0; c < XFS_AGI_UNLINKED_BUCKETS; c++)
2248 agi->agi_unlinked[c] = cpu_to_be32(NULLAGINO);
2249 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2250
2251 /*
2252 * BNO btree root block
2253 */
2254 buf = libxfs_getbuf(mp->m_ddev_targp,
2255 XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)),
2256 BTOBB(cfg->blocksize));
2257 buf->b_ops = &xfs_allocbt_buf_ops;
2258 block = XFS_BUF_TO_BLOCK(buf);
2259 memset(block, 0, cfg->blocksize);
2260 libxfs_btree_init_block(mp, buf, XFS_BTNUM_BNO, 0, 1, agno, 0);
2261
2262 arec = XFS_ALLOC_REC_ADDR(mp, block, 1);
2263 arec->ar_startblock = cpu_to_be32(libxfs_prealloc_blocks(mp));
2264 if (is_log_ag) {
2265 xfs_agblock_t start = XFS_FSB_TO_AGBNO(mp, cfg->logstart);
2266
2267 ASSERT(start >= libxfs_prealloc_blocks(mp));
2268 if (start != libxfs_prealloc_blocks(mp)) {
2269 /*
2270 * Modify first record to pad stripe align of log
2271 */
2272 arec->ar_blockcount = cpu_to_be32(start -
2273 libxfs_prealloc_blocks(mp));
2274 nrec = arec + 1;
2275 /*
2276 * Insert second record at start of internal log
2277 * which then gets trimmed.
2278 */
2279 nrec->ar_startblock = cpu_to_be32(
2280 be32_to_cpu(arec->ar_startblock) +
2281 be32_to_cpu(arec->ar_blockcount));
2282 arec = nrec;
2283 be16_add_cpu(&block->bb_numrecs, 1);
2284 }
2285 /*
2286 * Change record start to after the internal log
2287 */
2288 be32_add_cpu(&arec->ar_startblock, cfg->logblocks);
2289 }
2290 /*
2291 * Calculate the record block count and check for the case where
2292 * the log might have consumed all available space in the AG. If
2293 * so, reset the record count to 0 to avoid exposure of an invalid
2294 * record start block.
2295 */
2296 arec->ar_blockcount = cpu_to_be32(agsize -
2297 be32_to_cpu(arec->ar_startblock));
2298 if (!arec->ar_blockcount)
2299 block->bb_numrecs = 0;
2300
2301 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2302
2303 /*
2304 * CNT btree root block
2305 */
2306 buf = libxfs_getbuf(mp->m_ddev_targp,
2307 XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)),
2308 BTOBB(cfg->blocksize));
2309 buf->b_ops = &xfs_allocbt_buf_ops;
2310 block = XFS_BUF_TO_BLOCK(buf);
2311 memset(block, 0, cfg->blocksize);
2312 libxfs_btree_init_block(mp, buf, XFS_BTNUM_CNT, 0, 1, agno, 0);
2313
2314 arec = XFS_ALLOC_REC_ADDR(mp, block, 1);
2315 arec->ar_startblock = cpu_to_be32(libxfs_prealloc_blocks(mp));
2316 if (is_log_ag) {
2317 xfs_agblock_t start = XFS_FSB_TO_AGBNO(mp, cfg->logstart);
2318
2319 ASSERT(start >= libxfs_prealloc_blocks(mp));
2320 if (start != libxfs_prealloc_blocks(mp)) {
2321 arec->ar_blockcount = cpu_to_be32(start -
2322 libxfs_prealloc_blocks(mp));
2323 nrec = arec + 1;
2324 nrec->ar_startblock = cpu_to_be32(
2325 be32_to_cpu(arec->ar_startblock) +
2326 be32_to_cpu(arec->ar_blockcount));
2327 arec = nrec;
2328 be16_add_cpu(&block->bb_numrecs, 1);
2329 }
2330 be32_add_cpu(&arec->ar_startblock, cfg->logblocks);
2331 }
2332 /*
2333 * Calculate the record block count and check for the case where
2334 * the log might have consumed all available space in the AG. If
2335 * so, reset the record count to 0 to avoid exposure of an invalid
2336 * record start block.
2337 */
2338 arec->ar_blockcount = cpu_to_be32(agsize -
2339 be32_to_cpu(arec->ar_startblock));
2340 if (!arec->ar_blockcount)
2341 block->bb_numrecs = 0;
2342
2343 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2344
2345 /*
2346 * refcount btree root block
2347 */
2348 if (xfs_sb_version_hasreflink(sbp)) {
2349 buf = libxfs_getbuf(mp->m_ddev_targp,
2350 XFS_AGB_TO_DADDR(mp, agno, libxfs_refc_block(mp)),
2351 BTOBB(cfg->blocksize));
2352 buf->b_ops = &xfs_refcountbt_buf_ops;
2353
2354 block = XFS_BUF_TO_BLOCK(buf);
2355 memset(block, 0, cfg->blocksize);
2356 libxfs_btree_init_block(mp, buf, XFS_BTNUM_REFC, 0, 0, agno, 0);
2357 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2358 }
2359
2360 /*
2361 * INO btree root block
2362 */
2363 buf = libxfs_getbuf(mp->m_ddev_targp,
2364 XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)),
2365 BTOBB(cfg->blocksize));
2366 buf->b_ops = &xfs_inobt_buf_ops;
2367 block = XFS_BUF_TO_BLOCK(buf);
2368 memset(block, 0, cfg->blocksize);
2369 libxfs_btree_init_block(mp, buf, XFS_BTNUM_INO, 0, 0, agno, 0);
2370 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2371
2372 /*
2373 * Free INO btree root block
2374 */
2375 if (xfs_sb_version_hasfinobt(sbp)) {
2376 buf = libxfs_getbuf(mp->m_ddev_targp,
2377 XFS_AGB_TO_DADDR(mp, agno, XFS_FIBT_BLOCK(mp)),
2378 BTOBB(cfg->blocksize));
2379 buf->b_ops = &xfs_inobt_buf_ops;
2380 block = XFS_BUF_TO_BLOCK(buf);
2381 memset(block, 0, cfg->blocksize);
2382 libxfs_btree_init_block(mp, buf, XFS_BTNUM_FINO, 0, 0, agno, 0);
2383 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2384 }
2385
2386 /* RMAP btree root block */
2387 if (xfs_sb_version_hasrmapbt(sbp)) {
2388 struct xfs_rmap_rec *rrec;
2389
2390 buf = libxfs_getbuf(mp->m_ddev_targp,
2391 XFS_AGB_TO_DADDR(mp, agno, XFS_RMAP_BLOCK(mp)),
2392 BTOBB(cfg->blocksize));
2393 buf->b_ops = &xfs_rmapbt_buf_ops;
2394 block = XFS_BUF_TO_BLOCK(buf);
2395 memset(block, 0, cfg->blocksize);
2396
2397 libxfs_btree_init_block(mp, buf, XFS_BTNUM_RMAP, 0, 0, agno, 0);
2398
2399 /*
2400 * mark the AG header regions as static metadata
2401 * The BNO btree block is the first block after the
2402 * headers, so it's location defines the size of region
2403 * the static metadata consumes.
2404 */
2405 rrec = XFS_RMAP_REC_ADDR(block, 1);
2406 rrec->rm_startblock = 0;
2407 rrec->rm_blockcount = cpu_to_be32(XFS_BNO_BLOCK(mp));
2408 rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_FS);
2409 rrec->rm_offset = 0;
2410 be16_add_cpu(&block->bb_numrecs, 1);
2411
2412 /* account freespace btree root blocks */
2413 rrec = XFS_RMAP_REC_ADDR(block, 2);
2414 rrec->rm_startblock = cpu_to_be32(XFS_BNO_BLOCK(mp));
2415 rrec->rm_blockcount = cpu_to_be32(2);
2416 rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_AG);
2417 rrec->rm_offset = 0;
2418 be16_add_cpu(&block->bb_numrecs, 1);
2419
2420 /* account inode btree root blocks */
2421 rrec = XFS_RMAP_REC_ADDR(block, 3);
2422 rrec->rm_startblock = cpu_to_be32(XFS_IBT_BLOCK(mp));
2423 rrec->rm_blockcount = cpu_to_be32(XFS_RMAP_BLOCK(mp) -
2424 XFS_IBT_BLOCK(mp));
2425 rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_INOBT);
2426 rrec->rm_offset = 0;
2427 be16_add_cpu(&block->bb_numrecs, 1);
2428
2429 /* account for rmap btree root */
2430 rrec = XFS_RMAP_REC_ADDR(block, 4);
2431 rrec->rm_startblock = cpu_to_be32(XFS_RMAP_BLOCK(mp));
2432 rrec->rm_blockcount = cpu_to_be32(1);
2433 rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_AG);
2434 rrec->rm_offset = 0;
2435 be16_add_cpu(&block->bb_numrecs, 1);
2436
2437 /* account for refcount btree root */
2438 if (xfs_sb_version_hasreflink(sbp)) {
2439 rrec = XFS_RMAP_REC_ADDR(block, 5);
2440 rrec->rm_startblock = cpu_to_be32(libxfs_refc_block(mp));
2441 rrec->rm_blockcount = cpu_to_be32(1);
2442 rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_REFC);
2443 rrec->rm_offset = 0;
2444 be16_add_cpu(&block->bb_numrecs, 1);
2445 }
2446
2447 /* account for the log space */
2448 if (is_log_ag) {
2449 rrec = XFS_RMAP_REC_ADDR(block,
2450 be16_to_cpu(block->bb_numrecs) + 1);
2451 rrec->rm_startblock = cpu_to_be32(
2452 XFS_FSB_TO_AGBNO(mp, cfg->logstart));
2453 rrec->rm_blockcount = cpu_to_be32(cfg->logblocks);
2454 rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_LOG);
2455 rrec->rm_offset = 0;
2456 be16_add_cpu(&block->bb_numrecs, 1);
2457 }
2458
2459 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2460 }
2461
2462 libxfs_perag_put(pag);
2463}
2464
2465static void
2466initialise_ag_freespace(
2467 struct xfs_mount *mp,
2468 xfs_agnumber_t agno,
2469 int worst_freelist)
2470{
2471 struct xfs_alloc_arg args;
2472 struct xfs_trans *tp;
2473 struct xfs_trans_res tres = {0};
2474 int c;
2475
2476 c = libxfs_trans_alloc(mp, &tres, worst_freelist, 0, 0, &tp);
2477 if (c)
2478 res_failed(c);
2479
2480 memset(&args, 0, sizeof(args));
2481 args.tp = tp;
2482 args.mp = mp;
2483 args.agno = agno;
2484 args.alignment = 1;
2485 args.pag = libxfs_perag_get(mp, agno);
2486
2487 libxfs_alloc_fix_freelist(&args, 0);
2488 libxfs_perag_put(args.pag);
2489 libxfs_trans_commit(tp);
2490}
2491
2bd0ea18 2492int
9440d84d
NS
2493main(
2494 int argc,
2495 char **argv)
2bd0ea18 2496{
14f8b681 2497 uint64_t agcount;
2bd0ea18 2498 xfs_agnumber_t agno;
14f8b681 2499 uint64_t agsize;
2bd0ea18
NS
2500 int blflag;
2501 int blocklog;
2bd0ea18 2502 int bsflag;
2bd0ea18
NS
2503 xfs_buf_t *buf;
2504 int c;
2505 int daflag;
3fbc9137 2506 int dasize;
5a35bf2c 2507 xfs_rfsblock_t dblocks;
2bd0ea18
NS
2508 char *dfile;
2509 int dirblocklog;
2510 int dirblocksize;
2bd0ea18 2511 char *dsize;
3fbc9137
NS
2512 int dsu;
2513 int dsw;
2bd0ea18
NS
2514 int dsunit;
2515 int dswidth;
746d40a7 2516 int dsflag;
f937adac 2517 int force_overwrite;
9f064b7e 2518 struct fsxattr fsx;
2bd0ea18
NS
2519 int ilflag;
2520 int imaxpct;
2521 int imflag;
2522 int inodelog;
2523 int inopblock;
2524 int ipflag;
2525 int isflag;
2526 int isize;
979f7189 2527 char *label = NULL;
2bd0ea18
NS
2528 int laflag;
2529 int lalign;
2530 int ldflag;
2531 int liflag;
2532 xfs_agnumber_t logagno;
5a35bf2c 2533 xfs_rfsblock_t logblocks;
2bd0ea18
NS
2534 char *logfile;
2535 int loginternal;
2536 char *logsize;
5a35bf2c 2537 xfs_fsblock_t logstart;
73bf5988 2538 int lvflag;
2bd0ea18 2539 int lsflag;
392e896e
ES
2540 int lsuflag;
2541 int lsunitflag;
9440d84d
NS
2542 int lsectorlog;
2543 int lsectorsize;
1cba5ede
NS
2544 int lslflag;
2545 int lssflag;
9e017777 2546 int lsu;
73bf5988 2547 int lsunit;
2bd0ea18 2548 int min_logblocks;
2bd0ea18
NS
2549 xfs_mount_t *mp;
2550 xfs_mount_t mbuf;
2551 xfs_extlen_t nbmblocks;
2552 int nlflag;
2553 int nodsflag;
63a63844 2554 int norsflag;
2bd0ea18
NS
2555 int nsflag;
2556 int nvflag;
33a12367 2557 int Nflag;
ad136b33 2558 int discard = 1;
2bd0ea18
NS
2559 char *protofile;
2560 char *protostring;
2561 int qflag;
5a35bf2c 2562 xfs_rfsblock_t rtblocks;
2bd0ea18 2563 xfs_extlen_t rtextblocks;
5a35bf2c 2564 xfs_rtblock_t rtextents;
2bd0ea18
NS
2565 char *rtextsize;
2566 char *rtfile;
2567 char *rtsize;
2568 xfs_sb_t *sbp;
9440d84d 2569 int sectorlog;
14f8b681 2570 uint64_t sector_mask;
9440d84d
NS
2571 int slflag;
2572 int ssflag;
14f8b681 2573 uint64_t tmp_agsize;
2bd0ea18
NS
2574 uuid_t uuid;
2575 int worst_freelist;
2576 libxfs_init_t xi;
e4da9941 2577 struct fs_topology ft;
5f1a2100
DC
2578 struct sb_feat_args sb_feat = {
2579 .finobt = 1,
5f1a2100
DC
2580 .spinodes = 0,
2581 .log_version = 2,
2582 .attr_version = 2,
2583 .dir_version = XFS_DFL_DIR_VERSION,
2584 .inode_align = XFS_IFLAG_ALIGN,
2585 .nci = false,
2586 .lazy_sb_counters = true,
2587 .projid16bit = false,
2588 .crcs_enabled = true,
2589 .dirftype = true,
2590 .parent_pointers = false,
c563396a 2591 .rmapbt = false,
a5132d9b 2592 .reflink = false,
5f1a2100 2593 };
a1273b7c
DC
2594 struct cli_params cli = {
2595 .xi = &xi,
a3ac5af1 2596 .sb_feat = sb_feat,
a1273b7c 2597 };
4ab08e3b 2598 struct mkfs_params cfg = {};
2bd0ea18 2599
6af48b97 2600 platform_uuid_generate(&uuid);
2bd0ea18 2601 progname = basename(argv[0]);
9440d84d
NS
2602 setlocale(LC_ALL, "");
2603 bindtextdomain(PACKAGE, LOCALEDIR);
2604 textdomain(PACKAGE);
2605
1cba5ede 2606 blflag = bsflag = slflag = ssflag = lslflag = lssflag = 0;
836f654f 2607 blocklog = blocksize = 0;
a887c950
DC
2608 sectorlog = lsectorlog = 0;
2609 sectorsize = lsectorsize = 0;
9440d84d 2610 agsize = daflag = dasize = dblocks = 0;
2bd0ea18 2611 ilflag = imflag = ipflag = isflag = 0;
392e896e 2612 liflag = laflag = lsflag = lsuflag = lsunitflag = ldflag = lvflag = 0;
2bd0ea18 2613 loginternal = 1;
9b040c37 2614 logagno = logblocks = rtblocks = rtextblocks = 0;
5f1a2100 2615 Nflag = nlflag = nsflag = nvflag = 0;
51ca7008 2616 dirblocklog = dirblocksize = 0;
2bd0ea18
NS
2617 qflag = 0;
2618 imaxpct = inodelog = inopblock = isize = 0;
2bd0ea18 2619 dfile = logfile = rtfile = NULL;
9e017777 2620 dsize = logsize = rtsize = rtextsize = protofile = NULL;
63a63844 2621 dsu = dsw = dsunit = dswidth = lalign = lsu = lsunit = 0;
746d40a7 2622 dsflag = nodsflag = norsflag = 0;
f937adac 2623 force_overwrite = 0;
2bd0ea18 2624 worst_freelist = 0;
dab9b8d6 2625 memset(&fsx, 0, sizeof(fsx));
2bd0ea18 2626
dab9b8d6 2627 memset(&xi, 0, sizeof(xi));
b74a1f6a 2628 xi.isdirect = LIBXFS_DIRECT;
7eb6693f 2629 xi.isreadonly = LIBXFS_EXCLUSIVELY;
9440d84d 2630
f7b80291 2631 while ((c = getopt(argc, argv, "b:d:i:l:L:m:n:KNp:qr:s:CfV")) != EOF) {
2bd0ea18
NS
2632 switch (c) {
2633 case 'C':
2bd0ea18 2634 case 'f':
f937adac 2635 force_overwrite = 1;
2bd0ea18
NS
2636 break;
2637 case 'b':
85d6f03d
DC
2638 parse_subopts(c, optarg, &cli);
2639
2640 /* temp don't break code */
2641 blocksize = cli.blocksize;
2642 blocklog = libxfs_highbit32(blocksize);
2643 blflag = cli_opt_set(&bopts, B_LOG);
2644 bsflag = cli_opt_set(&bopts, B_SIZE);
2645 /* end temp don't break code */
2bd0ea18
NS
2646 break;
2647 case 'd':
a1273b7c 2648 parse_subopts(c, optarg, &cli);
2bd0ea18 2649
a1273b7c
DC
2650 /* temp don't break code */
2651 agcount = cli.agcount;
2652 if (cli_opt_set(&dopts, D_AGSIZE)) {
2653 agsize = getnum(cli.agsize, &dopts, D_AGSIZE);
2654 dasize = 1;
2bd0ea18 2655 }
a1273b7c
DC
2656 daflag = cli_opt_set(&dopts, D_AGCOUNT);
2657
2658 dsunit = cli.dsunit;
2659 dswidth = cli.dswidth;
2660 dsw = cli.dsw;
2661 if (cli_opt_set(&dopts, D_SU)) {
2662 dsu = getnum(cli.dsu, &dopts, D_SU);
2663 dsflag = 1;
2664 }
2665 dsflag |= cli_opt_set(&dopts, D_SW) ||
2666 cli_opt_set(&dopts, D_SUNIT) ||
2667 cli_opt_set(&dopts, D_SWIDTH);
2668 nodsflag = cli_opt_set(&dopts, D_NOALIGN);
2669
2670 sectorsize = cli.sectorsize;
2671 sectorlog = libxfs_highbit32(sectorsize);
2672 slflag = cli_opt_set(&dopts, D_SECTLOG);
2673 ssflag = cli_opt_set(&dopts, D_SECTSIZE);
2674
2675 fsx.fsx_xflags |= cli.fsx.fsx_xflags;
2676 fsx.fsx_projid = cli.fsx.fsx_projid;
2677 fsx.fsx_extsize = cli.fsx.fsx_extsize;
2678 /* end temp don't break code */
2bd0ea18
NS
2679 break;
2680 case 'i':
a3ac5af1 2681 parse_subopts(c, optarg, &cli);
2bd0ea18 2682
a3ac5af1
DC
2683 /* temp don't break code */
2684 isize = cli.inodesize;
2685 inodelog = libxfs_highbit32(isize);
2686 inopblock = cli.inopblock;
2687 ilflag = cli_opt_set(&iopts, I_LOG);
2688 isflag = cli_opt_set(&iopts, I_SIZE);
2689 ipflag = cli_opt_set(&iopts, I_PERBLOCK);
2690
2691 imaxpct = cli.imaxpct;
2692 imflag = cli_opt_set(&iopts, I_MAXPCT);
2693 /* end temp don't break code */
2bd0ea18
NS
2694 break;
2695 case 'l':
f3bc91a4
DC
2696 parse_subopts(c, optarg, &cli);
2697
2698 /* temp don't break code */
2699 logagno = cli.logagno;
2700 loginternal = cli.loginternal;
2701 logfile = xi.logname;
2702 logsize = cli.logsize;
2703 lsectorsize = cli.lsectorsize;
2704 lsectorlog = libxfs_highbit32(lsectorsize);
2705
2706 lsunit = cli.lsunit;
2707 lsunitflag = cli_opt_set(&lopts, L_SUNIT);
2708 if (cli_opt_set(&lopts, L_SU)) {
2709 lsu = getnum(cli.lsu, &lopts, L_SU);
2710 lsuflag = 1;
2bd0ea18 2711 }
f3bc91a4
DC
2712
2713 laflag = cli_opt_set(&lopts, L_AGNUM);
2714 liflag = cli_opt_set(&lopts, L_INTERNAL);
2715 ldflag = cli_opt_set(&lopts, L_NAME) ||
2716 cli_opt_set(&lopts, L_DEV);
2717 lvflag = cli_opt_set(&lopts, L_VERSION);
2718 lslflag = cli_opt_set(&lopts, L_SECTLOG);
2719 lssflag = cli_opt_set(&lopts, L_SECTSIZE);
2720 /* end temp don't break code */
2bd0ea18 2721 break;
979f7189
NS
2722 case 'L':
2723 if (strlen(optarg) > sizeof(sbp->sb_fname))
2724 illegal(optarg, "L");
2725 label = optarg;
2726 break;
f7b80291 2727 case 'm':
997136c6 2728 parse_subopts(c, optarg, &cli);
f7b80291 2729
997136c6
DC
2730 /* temp don't break code */
2731 platform_uuid_copy(&uuid, &cli.uuid);
2732 /* end temp don't break code */
f7b80291 2733 break;
2bd0ea18 2734 case 'n':
98d40922 2735 parse_subopts(c, optarg, &cli);
2bd0ea18 2736
98d40922
DC
2737 /* temp don't break code */
2738 if ((nsflag = cli_opt_set(&nopts, N_SIZE)))
2739 dirblocksize = getnum(cli.dirblocksize, &nopts, N_SIZE);
2740 dirblocklog = cli.dirblocklog;
2741
2742 nlflag = cli_opt_set(&nopts, N_LOG);
2743 /* end temp don't break code */
2bd0ea18 2744 break;
33a12367
NS
2745 case 'N':
2746 Nflag = 1;
2747 break;
ad136b33
CH
2748 case 'K':
2749 discard = 0;
2750 break;
2bd0ea18
NS
2751 case 'p':
2752 if (protofile)
5e656dbb 2753 respec('p', NULL, 0);
2bd0ea18
NS
2754 protofile = optarg;
2755 break;
2756 case 'q':
2757 qflag = 1;
2758 break;
2759 case 'r':
d145f69d 2760 parse_subopts(c, optarg, &cli);
2bd0ea18 2761
d145f69d
DC
2762 /* temp don't break code */
2763 rtextsize = cli.rtextsize;
2764 rtsize = cli.rtsize;
2765 norsflag = cli.sb_feat.nortalign;
2766 /* end temp don't break code */
2bd0ea18 2767 break;
9440d84d 2768 case 's':
f948f00a
DC
2769 parse_subopts(c, optarg, &cli);
2770
2771 /* temp don't break code */
2772 sectorsize = cli.sectorsize;
2773 lsectorlog = libxfs_highbit32(sectorsize);
2774 lsectorsize = cli.lsectorsize;
2775 lsectorlog = libxfs_highbit32(lsectorsize);
2776 lslflag = slflag = cli_opt_set(&sopts, S_LOG) ||
2777 cli_opt_set(&sopts, S_SECTLOG);
2778
2779 lssflag = ssflag = cli_opt_set(&sopts, S_SIZE) ||
2780 cli_opt_set(&sopts, S_SECTSIZE);
9440d84d 2781 break;
2bd0ea18 2782 case 'V':
9440d84d 2783 printf(_("%s version %s\n"), progname, VERSION);
3d98fe63 2784 exit(0);
2bd0ea18
NS
2785 case '?':
2786 unknown(optopt, "");
2787 }
2788 }
2789 if (argc - optind > 1) {
9440d84d 2790 fprintf(stderr, _("extra arguments\n"));
2bd0ea18
NS
2791 usage();
2792 } else if (argc - optind == 1) {
27ae3a59 2793 dfile = xi.volname = getstr(argv[optind], &dopts, D_NAME);
2bd0ea18
NS
2794 } else
2795 dfile = xi.dname;
9440d84d 2796
a3ac5af1
DC
2797 /* temp don't break code */
2798 sb_feat = cli.sb_feat;
2799 /* end temp don't break code */
2800
836f654f 2801 /*
9440d84d 2802 * Blocksize and sectorsize first, other things depend on them
c22b5fdf
NS
2803 * For RAID4/5/6 we want to align sector size and block size,
2804 * so we need to start with the device geometry extraction too.
836f654f
NS
2805 */
2806 if (!blflag && !bsflag) {
2807 blocklog = XFS_DFL_BLOCKSIZE_LOG;
2808 blocksize = 1 << XFS_DFL_BLOCKSIZE_LOG;
2809 }
2bd0ea18 2810 if (blocksize < XFS_MIN_BLOCKSIZE || blocksize > XFS_MAX_BLOCKSIZE) {
9440d84d
NS
2811 fprintf(stderr, _("illegal block size %d\n"), blocksize);
2812 usage();
2813 }
5f1a2100 2814 if (sb_feat.crcs_enabled && blocksize < XFS_MIN_CRC_BLOCKSIZE) {
e24ee60b
DC
2815 fprintf(stderr,
2816_("Minimum block size for CRC enabled filesystems is %d bytes.\n"),
2817 XFS_MIN_CRC_BLOCKSIZE);
2818 usage();
2819 }
5f1a2100 2820 if (sb_feat.crcs_enabled && !sb_feat.dirftype) {
b990de8b
ES
2821 fprintf(stderr, _("cannot disable ftype with crcs enabled\n"));
2822 usage();
2823 }
c22b5fdf 2824
a887c950
DC
2825 if (!slflag && !ssflag) {
2826 sectorlog = XFS_MIN_SECTORSIZE_LOG;
2827 sectorsize = XFS_MIN_SECTORSIZE;
2828 }
2829 if (!lslflag && !lssflag) {
2830 lsectorlog = sectorlog;
2831 lsectorsize = sectorsize;
2832 }
2833
06ac92fd
DC
2834 /*
2835 * Before anything else, verify that we are correctly operating on
2836 * files or block devices and set the control parameters correctly.
2837 * Explicitly disable direct IO for image files so we don't error out on
2838 * sector size mismatches between the new filesystem and the underlying
2839 * host filesystem.
2840 */
2841 check_device_type(dfile, &xi.disfile, !dsize, !dfile,
2842 Nflag ? NULL : &xi.dcreat, force_overwrite, "d");
2843 if (!loginternal)
2844 check_device_type(xi.logname, &xi.lisfile, !logsize, !xi.logname,
2845 Nflag ? NULL : &xi.lcreat,
2846 force_overwrite, "l");
2847 if (xi.rtname)
2848 check_device_type(xi.rtname, &xi.risfile, !rtsize, !xi.rtname,
2849 Nflag ? NULL : &xi.rcreat,
2850 force_overwrite, "r");
2851 if (xi.disfile || xi.lisfile || xi.risfile)
2852 xi.isdirect = 0;
2853
e4da9941 2854 memset(&ft, 0, sizeof(ft));
66bd6431 2855 get_topology(&xi, &ft, force_overwrite);
e4da9941 2856
2a3a4942 2857 if (!ssflag) {
fd5eda53
ES
2858 /*
2859 * Unless specified manually on the command line use the
287d168b
ES
2860 * advertised sector size of the device. We use the physical
2861 * sector size unless the requested block size is smaller
2862 * than that, then we can use logical, but warn about the
2863 * inefficiency.
fd5eda53 2864 */
287d168b
ES
2865
2866 /* Older kernels may not have physical/logical distinction */
2867 if (!ft.psectorsize)
2868 ft.psectorsize = ft.lsectorsize;
2869
2870 sectorsize = ft.psectorsize ? ft.psectorsize :
2871 XFS_MIN_SECTORSIZE;
2872
2873 if ((blocksize < sectorsize) && (blocksize >= ft.lsectorsize)) {
2874 fprintf(stderr,
2875_("specified blocksize %d is less than device physical sector size %d\n"),
2876 blocksize, ft.psectorsize);
2877 fprintf(stderr,
2878_("switching to logical sector size %d\n"),
2879 ft.lsectorsize);
2880 sectorsize = ft.lsectorsize ? ft.lsectorsize :
2881 XFS_MIN_SECTORSIZE;
2882 }
fd5eda53
ES
2883 }
2884
2a3a4942 2885 if (!ssflag) {
c22b5fdf
NS
2886 sectorlog = libxfs_highbit32(sectorsize);
2887 if (loginternal) {
2888 lsectorsize = sectorsize;
2889 lsectorlog = sectorlog;
2890 }
2891 }
fd5eda53 2892
9440d84d
NS
2893 if (sectorsize < XFS_MIN_SECTORSIZE ||
2894 sectorsize > XFS_MAX_SECTORSIZE || sectorsize > blocksize) {
287d168b
ES
2895 if (ssflag)
2896 fprintf(stderr, _("illegal sector size %d\n"), sectorsize);
2897 else
2898 fprintf(stderr,
2899_("block size %d cannot be smaller than logical sector size %d\n"),
2900 blocksize, ft.lsectorsize);
9440d84d
NS
2901 usage();
2902 }
287d168b 2903 if (sectorsize < ft.lsectorsize) {
fd5eda53 2904 fprintf(stderr, _("illegal sector size %d; hw sector is %d\n"),
287d168b 2905 sectorsize, ft.lsectorsize);
fd5eda53
ES
2906 usage();
2907 }
1cba5ede
NS
2908 if (lsectorsize < XFS_MIN_SECTORSIZE ||
2909 lsectorsize > XFS_MAX_SECTORSIZE || lsectorsize > blocksize) {
2910 fprintf(stderr, _("illegal log sector size %d\n"), lsectorsize);
2911 usage();
2912 } else if (lsectorsize > XFS_MIN_SECTORSIZE && !lsu && !lsunit) {
2913 lsu = blocksize;
5f1a2100 2914 sb_feat.log_version = 2;
1cba5ede 2915 }
9440d84d 2916
f3edb66a
DC
2917 /*
2918 * Now we have blocks and sector sizes set up, check parameters that are
2919 * no longer optional for CRC enabled filesystems. Catch them up front
2920 * here before doing anything else.
2921 */
5f1a2100 2922 if (sb_feat.crcs_enabled) {
f3edb66a
DC
2923 /* minimum inode size is 512 bytes, ipflag checked later */
2924 if ((isflag || ilflag) && inodelog < XFS_DINODE_DFL_CRC_LOG) {
2925 fprintf(stderr,
2926_("Minimum inode size for CRCs is %d bytes\n"),
2927 1 << XFS_DINODE_DFL_CRC_LOG);
2928 usage();
2929 }
2930
2931 /* inodes always aligned */
5f1a2100 2932 if (!sb_feat.inode_align) {
f3edb66a
DC
2933 fprintf(stderr,
2934_("Inodes always aligned for CRC enabled filesytems\n"));
2935 usage();
2936 }
2937
2938 /* lazy sb counters always on */
5f1a2100 2939 if (!sb_feat.lazy_sb_counters) {
f3edb66a
DC
2940 fprintf(stderr,
2941_("Lazy superblock counted always enabled for CRC enabled filesytems\n"));
2942 usage();
2943 }
2944
2945 /* version 2 logs always on */
5f1a2100 2946 if (sb_feat.log_version != 2) {
f3edb66a
DC
2947 fprintf(stderr,
2948_("V2 logs always enabled for CRC enabled filesytems\n"));
2949 usage();
2950 }
2951
2952 /* attr2 always on */
5f1a2100 2953 if (sb_feat.attr_version != 2) {
f3edb66a
DC
2954 fprintf(stderr,
2955_("V2 attribute format always enabled on CRC enabled filesytems\n"));
2956 usage();
2957 }
2958
2959 /* 32 bit project quota always on */
2960 /* attr2 always on */
5f1a2100 2961 if (sb_feat.projid16bit) {
f3edb66a
DC
2962 fprintf(stderr,
2963_("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
2964 usage();
2965 }
566ebd5a
DC
2966 } else {
2967 /*
2968 * The kernel doesn't currently support crc=0,finobt=1
2aca16d6
JT
2969 * filesystems. If crcs are not enabled and the user has not
2970 * explicitly turned finobt on, then silently turn it off to
2971 * avoid an unnecessary warning.
2972 * If the user explicitly tried to use crc=0,finobt=1,
2973 * then issue an error.
2974 * The same is also for sparse inodes.
566ebd5a 2975 */
9090e187 2976 if (sb_feat.finobt && mopts.subopt_params[M_FINOBT].seen) {
566ebd5a 2977 fprintf(stderr,
2aca16d6
JT
2978_("finobt not supported without CRC support\n"));
2979 usage();
566ebd5a 2980 }
5f1a2100 2981 sb_feat.finobt = 0;
f49c4e8d 2982
ddc3b2da
JT
2983 if (sb_feat.spinodes) {
2984 fprintf(stderr,
2aca16d6
JT
2985_("sparse inodes not supported without CRC support\n"));
2986 usage();
ddc3b2da 2987 }
5f1a2100 2988 sb_feat.spinodes = 0;
ddc3b2da 2989
c563396a
DW
2990 if (sb_feat.rmapbt) {
2991 fprintf(stderr,
2992_("rmapbt not supported without CRC support\n"));
2993 usage();
2994 }
2995 sb_feat.rmapbt = false;
a5132d9b
DW
2996
2997 if (sb_feat.reflink) {
2998 fprintf(stderr,
2999_("reflink not supported without CRC support\n"));
3000 usage();
3001 }
3002 sb_feat.reflink = false;
c563396a
DW
3003 }
3004
06b80354
DW
3005 if ((fsx.fsx_xflags & FS_XFLAG_COWEXTSIZE) && !sb_feat.reflink) {
3006 fprintf(stderr,
3007_("cowextsize not supported without reflink support\n"));
3008 usage();
3009 }
c563396a
DW
3010
3011 if (sb_feat.rmapbt && xi.rtname) {
3012 fprintf(stderr,
3013_("rmapbt not supported with realtime devices\n"));
3014 usage();
3015 sb_feat.rmapbt = false;
6003fd81
BF
3016 }
3017
51ca7008
BN
3018 if (nsflag || nlflag) {
3019 if (dirblocksize < blocksize ||
3020 dirblocksize > XFS_MAX_BLOCKSIZE) {
9440d84d 3021 fprintf(stderr, _("illegal directory block size %d\n"),
2bd0ea18
NS
3022 dirblocksize);
3023 usage();
3024 }
51ca7008
BN
3025 } else {
3026 if (blocksize < (1 << XFS_MIN_REC_DIRSIZE))
3027 dirblocklog = XFS_MIN_REC_DIRSIZE;
3028 else
3029 dirblocklog = blocklog;
3030 dirblocksize = 1 << dirblocklog;
2bd0ea18 3031 }
3fbc9137 3032
3fbc9137 3033
2bd0ea18 3034 if (dsize) {
14f8b681 3035 uint64_t dbytes;
2bd0ea18 3036
6c855628 3037 dbytes = getnum(dsize, &dopts, D_SIZE);
2bd0ea18
NS
3038 if (dbytes % XFS_MIN_BLOCKSIZE) {
3039 fprintf(stderr,
9440d84d 3040 _("illegal data length %lld, not a multiple of %d\n"),
5b64e00a 3041 (long long)dbytes, XFS_MIN_BLOCKSIZE);
2bd0ea18
NS
3042 usage();
3043 }
5a35bf2c 3044 dblocks = (xfs_rfsblock_t)(dbytes >> blocklog);
2bd0ea18 3045 if (dbytes % blocksize)
9440d84d
NS
3046 fprintf(stderr, _("warning: "
3047 "data length %lld not a multiple of %d, truncated to %lld\n"),
5b64e00a
NS
3048 (long long)dbytes, blocksize,
3049 (long long)(dblocks << blocklog));
2bd0ea18
NS
3050 }
3051 if (ipflag) {
3052 inodelog = blocklog - libxfs_highbit32(inopblock);
3053 isize = 1 << inodelog;
3054 } else if (!ilflag && !isflag) {
5f1a2100
DC
3055 inodelog = sb_feat.crcs_enabled ? XFS_DINODE_DFL_CRC_LOG
3056 : XFS_DINODE_DFL_LOG;
2bd0ea18
NS
3057 isize = 1 << inodelog;
3058 }
5f1a2100 3059 if (sb_feat.crcs_enabled && inodelog < XFS_DINODE_DFL_CRC_LOG) {
f7b80291
DC
3060 fprintf(stderr,
3061 _("Minimum inode size for CRCs is %d bytes\n"),
3062 1 << XFS_DINODE_DFL_CRC_LOG);
3063 usage();
3064 }
3065
2bd0ea18 3066 if (logsize) {
14f8b681 3067 uint64_t logbytes;
2bd0ea18 3068
6c855628 3069 logbytes = getnum(logsize, &lopts, L_SIZE);
2bd0ea18
NS
3070 if (logbytes % XFS_MIN_BLOCKSIZE) {
3071 fprintf(stderr,
9440d84d 3072 _("illegal log length %lld, not a multiple of %d\n"),
5b64e00a 3073 (long long)logbytes, XFS_MIN_BLOCKSIZE);
2bd0ea18
NS
3074 usage();
3075 }
5a35bf2c 3076 logblocks = (xfs_rfsblock_t)(logbytes >> blocklog);
2bd0ea18
NS
3077 if (logbytes % blocksize)
3078 fprintf(stderr,
9440d84d 3079 _("warning: log length %lld not a multiple of %d, truncated to %lld\n"),
5b64e00a
NS
3080 (long long)logbytes, blocksize,
3081 (long long)(logblocks << blocklog));
2bd0ea18 3082 }
2bd0ea18 3083 if (rtsize) {
14f8b681 3084 uint64_t rtbytes;
2bd0ea18 3085
6c855628 3086 rtbytes = getnum(rtsize, &ropts, R_SIZE);
2bd0ea18
NS
3087 if (rtbytes % XFS_MIN_BLOCKSIZE) {
3088 fprintf(stderr,
9440d84d 3089 _("illegal rt length %lld, not a multiple of %d\n"),
5b64e00a 3090 (long long)rtbytes, XFS_MIN_BLOCKSIZE);
2bd0ea18
NS
3091 usage();
3092 }
5a35bf2c 3093 rtblocks = (xfs_rfsblock_t)(rtbytes >> blocklog);
2bd0ea18
NS
3094 if (rtbytes % blocksize)
3095 fprintf(stderr,
9440d84d 3096 _("warning: rt length %lld not a multiple of %d, truncated to %lld\n"),
5b64e00a
NS
3097 (long long)rtbytes, blocksize,
3098 (long long)(rtblocks << blocklog));
2bd0ea18
NS
3099 }
3100 /*
3101 * If specified, check rt extent size against its constraints.
3102 */
3103 if (rtextsize) {
14f8b681 3104 uint64_t rtextbytes;
2bd0ea18 3105
6c855628 3106 rtextbytes = getnum(rtextsize, &ropts, R_EXTSIZE);
2bd0ea18
NS
3107 if (rtextbytes % blocksize) {
3108 fprintf(stderr,
9440d84d 3109 _("illegal rt extent size %lld, not a multiple of %d\n"),
5b64e00a 3110 (long long)rtextbytes, blocksize);
2bd0ea18
NS
3111 usage();
3112 }
2bd0ea18
NS
3113 rtextblocks = (xfs_extlen_t)(rtextbytes >> blocklog);
3114 } else {
3115 /*
3116 * If realtime extsize has not been specified by the user,
3117 * and the underlying volume is striped, then set rtextblocks
3118 * to the stripe width.
3119 */
14f8b681
DW
3120 uint64_t rswidth;
3121 uint64_t rtextbytes;
9440d84d 3122
7dc01804 3123 if (!norsflag && !xi.risfile && !(!rtsize && xi.disfile))
e4da9941
CH
3124 rswidth = ft.rtswidth;
3125 else
3126 rswidth = 0;
2bd0ea18
NS
3127
3128 /* check that rswidth is a multiple of fs blocksize */
63a63844 3129 if (!norsflag && rswidth && !(BBTOB(rswidth) % blocksize)) {
2bd0ea18
NS
3130 rswidth = DTOBT(rswidth);
3131 rtextbytes = rswidth << blocklog;
3132 if (XFS_MIN_RTEXTSIZE <= rtextbytes &&
1cba5ede
NS
3133 (rtextbytes <= XFS_MAX_RTEXTSIZE)) {
3134 rtextblocks = rswidth;
1e945ba2 3135 }
9b040c37
BN
3136 }
3137 if (!rtextblocks) {
3138 rtextblocks = (blocksize < XFS_MIN_RTEXTSIZE) ?
3139 XFS_MIN_RTEXTSIZE >> blocklog : 1;
3140 }
2bd0ea18 3141 }
9b040c37 3142 ASSERT(rtextblocks);
2bd0ea18
NS
3143
3144 /*
3145 * Check some argument sizes against mins, maxes.
3146 */
3147 if (isize > blocksize / XFS_MIN_INODE_PERBLOCK ||
3148 isize < XFS_DINODE_MIN_SIZE ||
3149 isize > XFS_DINODE_MAX_SIZE) {
3150 int maxsz;
3151
9440d84d 3152 fprintf(stderr, _("illegal inode size %d\n"), isize);
2bd0ea18
NS
3153 maxsz = MIN(blocksize / XFS_MIN_INODE_PERBLOCK,
3154 XFS_DINODE_MAX_SIZE);
3155 if (XFS_DINODE_MIN_SIZE == maxsz)
3156 fprintf(stderr,
9440d84d 3157 _("allowable inode size with %d byte blocks is %d\n"),
2bd0ea18
NS
3158 blocksize, XFS_DINODE_MIN_SIZE);
3159 else
3160 fprintf(stderr,
9440d84d 3161 _("allowable inode size with %d byte blocks is between %d and %d\n"),
2bd0ea18 3162 blocksize, XFS_DINODE_MIN_SIZE, maxsz);
8639eade 3163 exit(1);
2bd0ea18
NS
3164 }
3165
b2a8226a 3166 /* if lsu or lsunit was specified, automatically use v2 logs */
5f1a2100 3167 if ((lsu || lsunit) && sb_feat.log_version == 1) {
9440d84d
NS
3168 fprintf(stderr,
3169 _("log stripe unit specified, using v2 logs\n"));
5f1a2100 3170 sb_feat.log_version = 2;
b2a8226a
ES
3171 }
3172
9440d84d
NS
3173 calc_stripe_factors(dsu, dsw, sectorsize, lsu, lsectorsize,
3174 &dsunit, &dswidth, &lsunit);
2bd0ea18 3175
746d40a7
ES
3176 /* If sunit & swidth were manually specified as 0, same as noalign */
3177 if (dsflag && !dsunit && !dswidth)
3178 nodsflag = 1;
3179
fd5eda53 3180 xi.setblksize = sectorsize;
edd45774 3181
2bd0ea18
NS
3182 /*
3183 * Initialize. This will open the log and rt devices as well.
3184 */
3185 if (!libxfs_init(&xi))
3186 usage();
3187 if (!xi.ddev) {
9440d84d 3188 fprintf(stderr, _("no device name given in argument list\n"));
2bd0ea18
NS
3189 usage();
3190 }
3191
b7abc846
ES
3192 /*
3193 * Ok, Linux only has a 1024-byte resolution on device _size_,
3194 * and the sizes below are in basic 512-byte blocks,
3195 * so if we have (size % 2), on any partition, we can't get
22aa6603
BN
3196 * to the last 512 bytes. The same issue exists for larger
3197 * sector sizes - we cannot write past the last sector.
3198 *
3199 * So, we reduce the size (in basic blocks) to a perfect
3200 * multiple of the sector size, or 1024, whichever is larger.
b7abc846
ES
3201 */
3202
14f8b681 3203 sector_mask = (uint64_t)-1 << (MAX(sectorlog, 10) - BBSHIFT);
22aa6603
BN
3204 xi.dsize &= sector_mask;
3205 xi.rtsize &= sector_mask;
14f8b681 3206 xi.logBBsize &= (uint64_t)-1 << (MAX(lsectorlog, 10) - BBSHIFT);
b7abc846 3207
2bd0ea18 3208
06ac92fd 3209 /* don't do discards on print-only runs or on files */
de0918e6 3210 if (discard && !Nflag) {
06ac92fd
DC
3211 if (!xi.disfile)
3212 discard_blocks(xi.ddev, xi.dsize);
3213 if (xi.rtdev && !xi.risfile)
ad136b33 3214 discard_blocks(xi.rtdev, xi.rtsize);
06ac92fd 3215 if (xi.logdev && xi.logdev != xi.ddev && !xi.lisfile)
ad136b33
CH
3216 discard_blocks(xi.logdev, xi.logBBsize);
3217 }
3218
2bd0ea18
NS
3219 if (!liflag && !ldflag)
3220 loginternal = xi.logdev == 0;
3221 if (xi.logname)
3222 logfile = xi.logname;
3223 else if (loginternal)
9440d84d 3224 logfile = _("internal log");
2bd0ea18 3225 else if (xi.volname && xi.logdev)
9440d84d 3226 logfile = _("volume log");
2bd0ea18 3227 else if (!ldflag) {
9440d84d 3228 fprintf(stderr, _("no log subvolume or internal log\n"));
2bd0ea18
NS
3229 usage();
3230 }
3231 if (xi.rtname)
3232 rtfile = xi.rtname;
3233 else
3234 if (xi.volname && xi.rtdev)
9440d84d 3235 rtfile = _("volume rt");
2bd0ea18 3236 else if (!xi.rtdev)
9440d84d 3237 rtfile = _("none");
2bd0ea18
NS
3238 if (dsize && xi.dsize > 0 && dblocks > DTOBT(xi.dsize)) {
3239 fprintf(stderr,
9440d84d
NS
3240 _("size %s specified for data subvolume is too large, "
3241 "maximum is %lld blocks\n"),
5b64e00a 3242 dsize, (long long)DTOBT(xi.dsize));
2bd0ea18
NS
3243 usage();
3244 } else if (!dsize && xi.dsize > 0)
3245 dblocks = DTOBT(xi.dsize);
3246 else if (!dsize) {
9440d84d 3247 fprintf(stderr, _("can't get size of data subvolume\n"));
2bd0ea18 3248 usage();
1e945ba2 3249 }
2bd0ea18
NS
3250 if (dblocks < XFS_MIN_DATA_BLOCKS) {
3251 fprintf(stderr,
9440d84d 3252 _("size %lld of data subvolume is too small, minimum %d blocks\n"),
5b64e00a 3253 (long long)dblocks, XFS_MIN_DATA_BLOCKS);
2bd0ea18
NS
3254 usage();
3255 }
74668075 3256
9440d84d
NS
3257 if (loginternal && xi.logdev) {
3258 fprintf(stderr,
3259 _("can't have both external and internal logs\n"));
3260 usage();
3261 } else if (loginternal && sectorsize != lsectorsize) {
3262 fprintf(stderr,
3263 _("data and log sector sizes must be equal for internal logs\n"));
2bd0ea18
NS
3264 usage();
3265 }
74668075
NS
3266
3267 if (xi.dbsize > sectorsize) {
3268 fprintf(stderr, _(
3269"Warning: the data subvolume sector size %u is less than the sector size \n\
3270reported by the device (%u).\n"),
3271 sectorsize, xi.dbsize);
3272 }
3273 if (!loginternal && xi.lbsize > lsectorsize) {
3274 fprintf(stderr, _(
3275"Warning: the log subvolume sector size %u is less than the sector size\n\
3276reported by the device (%u).\n"),
3277 lsectorsize, xi.lbsize);
3278 }
3279 if (rtsize && xi.rtsize > 0 && xi.rtbsize > sectorsize) {
3280 fprintf(stderr, _(
3281"Warning: the realtime subvolume sector size %u is less than the sector size\n\
3282reported by the device (%u).\n"),
3283 sectorsize, xi.rtbsize);
3284 }
3285
2bd0ea18
NS
3286 if (rtsize && xi.rtsize > 0 && rtblocks > DTOBT(xi.rtsize)) {
3287 fprintf(stderr,
9440d84d
NS
3288 _("size %s specified for rt subvolume is too large, "
3289 "maximum is %lld blocks\n"),
5b64e00a 3290 rtsize, (long long)DTOBT(xi.rtsize));
2bd0ea18
NS
3291 usage();
3292 } else if (!rtsize && xi.rtsize > 0)
3293 rtblocks = DTOBT(xi.rtsize);
3294 else if (rtsize && !xi.rtdev) {
3295 fprintf(stderr,
9440d84d 3296 _("size specified for non-existent rt subvolume\n"));
2bd0ea18
NS
3297 usage();
3298 }
3299 if (xi.rtdev) {
3300 rtextents = rtblocks / rtextblocks;
3301 nbmblocks = (xfs_extlen_t)howmany(rtextents, NBBY * blocksize);
3302 } else {
3303 rtextents = rtblocks = 0;
3304 nbmblocks = 0;
3305 }
3fbc9137 3306
fd65a91c
BN
3307 if (!nodsflag) {
3308 if (dsunit) {
e4da9941 3309 if (ft.dsunit && ft.dsunit != dsunit) {
fd65a91c
BN
3310 fprintf(stderr,
3311 _("%s: Specified data stripe unit %d "
3312 "is not the same as the volume stripe "
3313 "unit %d\n"),
e4da9941 3314 progname, dsunit, ft.dsunit);
fd65a91c 3315 }
e4da9941 3316 if (ft.dswidth && ft.dswidth != dswidth) {
fd65a91c
BN
3317 fprintf(stderr,
3318 _("%s: Specified data stripe width %d "
3319 "is not the same as the volume stripe "
3320 "width %d\n"),
e4da9941 3321 progname, dswidth, ft.dswidth);
fd65a91c
BN
3322 }
3323 } else {
e4da9941
CH
3324 dsunit = ft.dsunit;
3325 dswidth = ft.dswidth;
fd65a91c 3326 nodsflag = 1;
2bd0ea18 3327 }
fd65a91c 3328 } /* else dsunit & dswidth can't be set if nodsflag is set */
2bd0ea18 3329
0cfda29e
ES
3330 if (dasize) { /* User-specified AG size */
3331 /*
3332 * Check specified agsize is a multiple of blocksize.
3333 */
3334 if (agsize % blocksize) {
3335 fprintf(stderr,
3336 _("agsize (%lld) not a multiple of fs blk size (%d)\n"),
3337 (long long)agsize, blocksize);
3338 usage();
3339 }
3340 agsize /= blocksize;
3341 agcount = dblocks / agsize + (dblocks % agsize != 0);
3342
3343 } else if (daflag) { /* User-specified AG count */
3344 agsize = dblocks / agcount + (dblocks % agcount != 0);
3345 } else {
3346 calc_default_ag_geometry(blocklog, dblocks,
3347 dsunit | dswidth, &agsize, &agcount);
3348 }
3349
2bd0ea18
NS
3350 /*
3351 * If dsunit is a multiple of fs blocksize, then check that is a
3352 * multiple of the agsize too
3353 */
1e945ba2 3354 if (dsunit && !(BBTOB(dsunit) % blocksize) &&
2bd0ea18
NS
3355 dswidth && !(BBTOB(dswidth) % blocksize)) {
3356
3357 /* convert from 512 byte blocks to fs blocksize */
3358 dsunit = DTOBT(dsunit);
3359 dswidth = DTOBT(dswidth);
3360
1e945ba2 3361 /*
2bd0ea18
NS
3362 * agsize is not a multiple of dsunit
3363 */
3364 if ((agsize % dsunit) != 0) {
1cba5ede 3365 /*
1e945ba2
BN
3366 * Round up to stripe unit boundary. Also make sure
3367 * that agsize is still larger than
2bd0ea18
NS
3368 * XFS_AG_MIN_BLOCKS(blocklog)
3369 */
1cba5ede 3370 tmp_agsize = ((agsize + (dsunit - 1))/ dsunit) * dsunit;
3fbc9137
NS
3371 /*
3372 * Round down to stripe unit boundary if rounding up
3373 * created an AG size that is larger than the AG max.
3374 */
3375 if (tmp_agsize > XFS_AG_MAX_BLOCKS(blocklog))
3376 tmp_agsize = ((agsize) / dsunit) * dsunit;
a780dc96 3377
5b5df80a 3378 if ((tmp_agsize >= XFS_AG_MIN_BLOCKS(blocklog)) &&
a780dc96 3379 (tmp_agsize <= XFS_AG_MAX_BLOCKS(blocklog))) {
2bd0ea18 3380 agsize = tmp_agsize;
a780dc96
BN
3381 if (!daflag)
3382 agcount = dblocks/agsize +
2bd0ea18 3383 (dblocks % agsize != 0);
a780dc96 3384 if (dasize)
3fbc9137 3385 fprintf(stderr,
9440d84d 3386 _("agsize rounded to %lld, swidth = %d\n"),
3fbc9137 3387 (long long)agsize, dswidth);
1cba5ede 3388 } else {
3fbc9137 3389 if (nodsflag) {
2bd0ea18 3390 dsunit = dswidth = 0;
1e945ba2 3391 } else {
ddf12ea5
ES
3392 /*
3393 * agsize is out of bounds, this will
3394 * print nice details & exit.
3395 */
3396 validate_ag_geometry(blocklog, dblocks,
3397 agsize, agcount);
2bd0ea18
NS
3398 exit(1);
3399 }
1cba5ede 3400 }
2bd0ea18 3401 }
9a106b5f
DD
3402 if (dswidth && ((agsize % dswidth) == 0)
3403 && (dswidth != dsunit)
3404 && (agcount > 1)) {
a212110f 3405 /* This is a non-optimal configuration because all AGs
1e945ba2 3406 * start on the same disk in the stripe. Changing
a212110f 3407 * the AG size by one sunit will guarantee that this
0640ee14 3408 * does not happen.
a212110f
ES
3409 */
3410 tmp_agsize = agsize - dsunit;
0640ee14 3411 if (tmp_agsize < XFS_AG_MIN_BLOCKS(blocklog)) {
a212110f 3412 tmp_agsize = agsize + dsunit;
0640ee14
ES
3413 if (dblocks < agsize) {
3414 /* oh well, nothing to do */
3415 tmp_agsize = agsize;
3416 }
3417 }
a212110f 3418 if (daflag || dasize) {
9440d84d 3419 fprintf(stderr, _(
3c925401
NS
3420"Warning: AG size is a multiple of stripe width. This can cause performance\n\
3421problems by aligning all AGs on the same disk. To avoid this, run mkfs with\n\
9440d84d 3422an AG size that is one stripe unit smaller, for example %llu.\n"),
3c925401 3423 (unsigned long long)tmp_agsize);
a212110f
ES
3424 } else {
3425 agsize = tmp_agsize;
3426 agcount = dblocks/agsize + (dblocks % agsize != 0);
02e85e7f
GO
3427 /*
3428 * If the last AG is too small, reduce the
3429 * filesystem size and drop the blocks.
3430 */
3431 if ( dblocks % agsize != 0 &&
3432 (dblocks % agsize <
3433 XFS_AG_MIN_BLOCKS(blocklog))) {
5a35bf2c 3434 dblocks = (xfs_rfsblock_t)((agcount - 1) * agsize);
02e85e7f
GO
3435 agcount--;
3436 ASSERT(agcount != 0);
3437 }
a212110f
ES
3438 }
3439 }
2bd0ea18
NS
3440 } else {
3441 if (nodsflag)
3442 dsunit = dswidth = 0;
1e945ba2 3443 else {
9440d84d
NS
3444 fprintf(stderr,
3445 _("%s: Stripe unit(%d) or stripe width(%d) is "
3446 "not a multiple of the block size(%d)\n"),
1e945ba2
BN
3447 progname, BBTOB(dsunit), BBTOB(dswidth),
3448 blocksize);
2bd0ea18
NS
3449 exit(1);
3450 }
3451 }
3452
a780dc96
BN
3453 /*
3454 * If the last AG is too small, reduce the filesystem size
3455 * and drop the blocks.
3456 */
3457 if ( dblocks % agsize != 0 &&
3458 (dblocks % agsize < XFS_AG_MIN_BLOCKS(blocklog))) {
3459 ASSERT(!daflag);
5a35bf2c 3460 dblocks = (xfs_rfsblock_t)((agcount - 1) * agsize);
a780dc96
BN
3461 agcount--;
3462 ASSERT(agcount != 0);
3463 }
3464
3465 validate_ag_geometry(blocklog, dblocks, agsize, agcount);
3466
3467 if (!imflag)
3468 imaxpct = calc_default_imaxpct(blocklog, dblocks);
3469
73bf5988
SL
3470 /*
3471 * check that log sunit is modulo fsblksize or default it to dsunit.
3472 */
3473
3474 if (lsunit) {
9e017777
ES
3475 /* convert from 512 byte blocks to fs blocks */
3476 lsunit = DTOBT(lsunit);
5f1a2100 3477 } else if (sb_feat.log_version == 2 && loginternal && dsunit) {
9e017777
ES
3478 /* lsunit and dsunit now in fs blocks */
3479 lsunit = dsunit;
73bf5988
SL
3480 }
3481
5f1a2100 3482 if (sb_feat.log_version == 2 && (lsunit * blocksize) > 256 * 1024) {
392e896e
ES
3483 /* Warn only if specified on commandline */
3484 if (lsuflag || lsunitflag) {
3485 fprintf(stderr,
b50e4c6e 3486 _("log stripe unit (%d bytes) is too large (maximum is 256KiB)\n"),
392e896e
ES
3487 (lsunit * blocksize));
3488 fprintf(stderr,
3489 _("log stripe unit adjusted to 32KiB\n"));
3490 }
b51d0582 3491 lsunit = (32 * 1024) >> blocklog;
73bf5988
SL
3492 }
3493
e5cc9d56
DW
3494 min_logblocks = max_trans_res(agsize,
3495 sb_feat.crcs_enabled, sb_feat.dir_version,
88cd79be 3496 sectorlog, blocklog, inodelog, dirblocklog,
c563396a 3497 sb_feat.log_version, lsunit, sb_feat.finobt,
2a3145a8
DW
3498 sb_feat.rmapbt, sb_feat.reflink,
3499 sb_feat.inode_align);
88cd79be
DC
3500 ASSERT(min_logblocks);
3501 min_logblocks = MAX(XFS_MIN_LOG_BLOCKS, min_logblocks);
3502 if (!logsize && dblocks >= (1024*1024*1024) >> blocklog)
3503 min_logblocks = MAX(min_logblocks, XFS_MIN_LOG_BYTES>>blocklog);
3504 if (logsize && xi.logBBsize > 0 && logblocks > DTOBT(xi.logBBsize)) {
3505 fprintf(stderr,
3506_("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
3507 logsize, (long long)DTOBT(xi.logBBsize));
3508 usage();
3509 } else if (!logsize && xi.logBBsize > 0) {
3510 logblocks = DTOBT(xi.logBBsize);
3511 } else if (logsize && !xi.logdev && !loginternal) {
3512 fprintf(stderr,
3513 _("size specified for non-existent log subvolume\n"));
3514 usage();
3515 } else if (loginternal && logsize && logblocks >= dblocks) {
3516 fprintf(stderr, _("size %lld too large for internal log\n"),
3517 (long long)logblocks);
3518 usage();
3519 } else if (!loginternal && !xi.logdev) {
3520 logblocks = 0;
3521 } else if (loginternal && !logsize) {
88cd79be 3522
9718fa20
DC
3523 if (dblocks < GIGABYTES(1, blocklog)) {
3524 /* tiny filesystems get minimum sized logs. */
88cd79be 3525 logblocks = min_logblocks;
9718fa20
DC
3526 } else if (dblocks < GIGABYTES(16, blocklog)) {
3527
3528 /*
3529 * For small filesystems, we want to use the
3530 * XFS_MIN_LOG_BYTES for filesystems smaller than 16G if
3531 * at all possible, ramping up to 128MB at 256GB.
3532 */
3533 logblocks = MIN(XFS_MIN_LOG_BYTES >> blocklog,
3534 min_logblocks * XFS_DFL_LOG_FACTOR);
88cd79be 3535 } else {
9718fa20
DC
3536 /*
3537 * With a 2GB max log size, default to maximum size
3538 * at 4TB. This keeps the same ratio from the older
3539 * max log size of 128M at 256GB fs size. IOWs,
3540 * the ratio of fs size to log size is 2048:1.
3541 */
3542 logblocks = (dblocks << blocklog) / 2048;
3543 logblocks = logblocks >> blocklog;
88cd79be 3544 }
9718fa20 3545
bd76b93e
DC
3546 /* Ensure the chosen size meets minimum log size requirements */
3547 logblocks = MAX(min_logblocks, logblocks);
3548
9718fa20
DC
3549 /* make sure the log fits wholly within an AG */
3550 if (logblocks >= agsize)
3551 logblocks = min_logblocks;
3552
3553 /* and now clamp the size to the maximum supported size */
88cd79be 3554 logblocks = MIN(logblocks, XFS_MAX_LOG_BLOCKS);
9718fa20 3555 if ((logblocks << blocklog) > XFS_MAX_LOG_BYTES)
88cd79be 3556 logblocks = XFS_MAX_LOG_BYTES >> blocklog;
9718fa20 3557
88cd79be
DC
3558 }
3559 validate_log_size(logblocks, blocklog, min_logblocks);
3560
2bd0ea18 3561 protostring = setup_proto(protofile);
2bd0ea18
NS
3562 mp = &mbuf;
3563 sbp = &mp->m_sb;
dab9b8d6 3564 memset(mp, 0, sizeof(xfs_mount_t));
14f8b681
DW
3565 sbp->sb_blocklog = (uint8_t)blocklog;
3566 sbp->sb_sectlog = (uint8_t)sectorlog;
24f4f998 3567 sbp->sb_agblklog = (uint8_t)log2_roundup((unsigned int)agsize);
88cd79be 3568 sbp->sb_agblocks = (xfs_agblock_t)agsize;
2bd0ea18 3569 mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT;
9440d84d
NS
3570 mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT;
3571
f49c4e8d 3572 /*
c563396a 3573 * sb_versionnum, finobt and rmapbt flags must be set before we use
e2f60652 3574 * libxfs_prealloc_blocks().
f49c4e8d 3575 */
5f1a2100 3576 sb_set_features(&mp->m_sb, &sb_feat, sectorsize, lsectorsize, dsunit);
f49c4e8d 3577
f49c4e8d 3578
2bd0ea18 3579 if (loginternal) {
a212110f
ES
3580 /*
3581 * Readjust the log size to fit within an AG if it was sized
ff1f79a7 3582 * automatically.
a212110f
ES
3583 */
3584 if (!logsize) {
3585 logblocks = MIN(logblocks,
e2f60652 3586 libxfs_alloc_ag_max_usable(mp));
88cd79be
DC
3587
3588 /* revalidate the log size is valid if we changed it */
3589 validate_log_size(logblocks, blocklog, min_logblocks);
a212110f 3590 }
e2f60652 3591 if (logblocks > agsize - libxfs_prealloc_blocks(mp)) {
2bd0ea18 3592 fprintf(stderr,
9440d84d 3593 _("internal log size %lld too large, must fit in allocation group\n"),
5b64e00a 3594 (long long)logblocks);
2bd0ea18
NS
3595 usage();
3596 }
88cd79be 3597
2bd0ea18
NS
3598 if (laflag) {
3599 if (logagno >= agcount) {
3600 fprintf(stderr,
9440d84d 3601 _("log ag number %d too large, must be less than %lld\n"),
5b64e00a 3602 logagno, (long long)agcount);
2bd0ea18
NS
3603 usage();
3604 }
3605 } else
3606 logagno = (xfs_agnumber_t)(agcount / 2);
3607
e2f60652 3608 logstart = XFS_AGB_TO_FSB(mp, logagno, libxfs_prealloc_blocks(mp));
2bd0ea18
NS
3609 /*
3610 * Align the logstart at stripe unit boundary.
3611 */
575fec4c 3612 if (lsunit) {
72e527e7
NS
3613 logstart = fixup_internal_log_stripe(mp,
3614 lsflag, logstart, agsize, lsunit,
3615 &logblocks, blocklog, &lalign);
575fec4c 3616 } else if (dsunit) {
72e527e7
NS
3617 logstart = fixup_internal_log_stripe(mp,
3618 lsflag, logstart, agsize, dsunit,
3619 &logblocks, blocklog, &lalign);
2bd0ea18 3620 }
72e527e7 3621 } else {
2bd0ea18 3622 logstart = 0;
72e527e7
NS
3623 if (lsunit)
3624 fixup_log_stripe_unit(lsflag, lsunit,
3625 &logblocks, blocklog);
3626 }
3627 validate_log_size(logblocks, blocklog, min_logblocks);
3fbc9137 3628
4ab08e3b
DC
3629 /* Temp support code to set up mkfs cfg parameters */
3630 cfg.blocksize = blocksize;
3631 cfg.blocklog = blocklog;
3632 cfg.sectorsize = sectorsize;
3633 cfg.sectorlog = sectorlog;
3634 cfg.lsectorsize = lsectorsize;
3635 cfg.lsectorlog = lsectorlog;
3636 cfg.dirblocksize = dirblocksize;
3637 cfg.dirblocklog = dirblocklog;
3638 cfg.inodesize = isize;
3639 cfg.inodelog = inodelog;
3640 cfg.inopblock = inopblock;
3641
3642 cfg.dblocks = dblocks;
3643 cfg.logblocks = logblocks;
3644 cfg.rtblocks = rtblocks;
3645 cfg.rtextblocks = rtextblocks;
3646 cfg.rtextents = rtextents;
3647 cfg.rtbmblocks = nbmblocks;
3648 cfg.dsunit = dsunit;
3649 cfg.dswidth = dswidth;
3650 cfg.lsunit = lsunit;
3651 cfg.agsize = agsize;
3652 cfg.agcount = agcount;
3653 cfg.imaxpct = imaxpct;
3654 cfg.loginternal = loginternal;
3655 cfg.logstart = logstart;
3656 cfg.logagno = logagno;
3657 cfg.label = label;
3658 platform_uuid_copy(&cfg.uuid, &uuid);
3659 memcpy(&cfg.sb_feat, &sb_feat, sizeof(sb_feat));
3660 /* end temp support code */
3661
9440d84d 3662 if (!qflag || Nflag) {
d1138048 3663 print_mkfs_cfg(&cfg, dfile, logfile, rtfile);
9440d84d
NS
3664 if (Nflag)
3665 exit(0);
3666 }
3667
afda75a5
DC
3668 /*
3669 * Finish setting up the superblock state ready for formatting.
3670 */
3671 setup_superblock(&cfg, mp, sbp);
6003fd81 3672
2f012bf9 3673 /*
e99bf83d 3674 * we need the libxfs buffer cache from here on in.
2f012bf9 3675 */
75c8b434 3676 libxfs_buftarg_init(mp, xi.ddev, xi.logdev, xi.rtdev);
2bd0ea18 3677
2bd0ea18 3678 /*
e99bf83d
DC
3679 * Before we mount the filesystem we need to make sure the devices have
3680 * enough of the filesystem structure on them that allows libxfs to
3681 * mount.
2bd0ea18 3682 */
e99bf83d 3683 prepare_devices(&cfg, &xi, mp, sbp, force_overwrite);
9aa57116 3684 mp = libxfs_mount(mp, sbp, xi.ddev, xi.logdev, xi.rtdev, 0);
02e85e7f 3685 if (mp == NULL) {
9440d84d
NS
3686 fprintf(stderr, _("%s: filesystem failed to initialize\n"),
3687 progname);
2bd0ea18
NS
3688 exit(1);
3689 }
2bd0ea18 3690
75c8b434 3691 /*
0ff1b0ed 3692 * Initialise all the static on disk metadata.
75c8b434 3693 */
0ff1b0ed
DC
3694 for (agno = 0; agno < cfg.agcount; agno++)
3695 initialise_ag_headers(&cfg, mp, sbp, agno, &worst_freelist);
2bd0ea18 3696
2bd0ea18 3697 /*
0ff1b0ed 3698 * Initialise the freespace freelists (i.e. AGFLs) in each AG.
2bd0ea18 3699 */
0ff1b0ed
DC
3700 for (agno = 0; agno < cfg.agcount; agno++)
3701 initialise_ag_freespace(mp, agno, worst_freelist);
9440d84d 3702
2bd0ea18
NS
3703 /*
3704 * Allocate the root inode and anything else in the proto file.
3705 */
9f064b7e 3706 parse_proto(mp, &fsx, &protostring);
2bd0ea18
NS
3707
3708 /*
9440d84d 3709 * Protect ourselves against possible stupidity
2bd0ea18
NS
3710 */
3711 if (XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino) != 0) {
9440d84d
NS
3712 fprintf(stderr,
3713 _("%s: root inode created in AG %u, not AG 0\n"),
2bd0ea18
NS
3714 progname, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino));
3715 exit(1);
3716 }
3717
3718 /*
9440d84d 3719 * Write out multiple secondary superblocks with rootinode field set
2bd0ea18
NS
3720 */
3721 if (mp->m_sb.sb_agcount > 1) {
3722 /*
3723 * the last superblock
3724 */
3725 buf = libxfs_readbuf(mp->m_dev,
3726 XFS_AGB_TO_DADDR(mp, mp->m_sb.sb_agcount-1,
3727 XFS_SB_DADDR),
9440d84d 3728 XFS_FSS_TO_BB(mp, 1),
75c8b434 3729 LIBXFS_EXIT_ON_FAILURE, &xfs_sb_buf_ops);
5e656dbb
BN
3730 XFS_BUF_TO_SBP(buf)->sb_rootino = cpu_to_be64(
3731 mp->m_sb.sb_rootino);
9440d84d 3732 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2bd0ea18
NS
3733 /*
3734 * and one in the middle for luck
3735 */
3736 if (mp->m_sb.sb_agcount > 2) {
3737 buf = libxfs_readbuf(mp->m_dev,
3738 XFS_AGB_TO_DADDR(mp, (mp->m_sb.sb_agcount-1)/2,
3739 XFS_SB_DADDR),
9440d84d 3740 XFS_FSS_TO_BB(mp, 1),
75c8b434 3741 LIBXFS_EXIT_ON_FAILURE, &xfs_sb_buf_ops);
5e656dbb
BN
3742 XFS_BUF_TO_SBP(buf)->sb_rootino = cpu_to_be64(
3743 mp->m_sb.sb_rootino);
9440d84d 3744 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2bd0ea18
NS
3745 }
3746 }
3747
f1b058f9
NS
3748 /*
3749 * Dump all inodes and buffers before marking us all done.
3750 * Need to drop references to inodes we still hold, first.
3751 */
3752 libxfs_rtmount_destroy(mp);
f1b058f9
NS
3753 libxfs_bcache_purge();
3754
2bd0ea18
NS
3755 /*
3756 * Mark the filesystem ok.
3757 */
9440d84d 3758 buf = libxfs_getsb(mp, LIBXFS_EXIT_ON_FAILURE);
2bd0ea18 3759 (XFS_BUF_TO_SBP(buf))->sb_inprogress = 0;
9440d84d 3760 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2bd0ea18
NS
3761
3762 libxfs_umount(mp);
3763 if (xi.rtdev)
3764 libxfs_device_close(xi.rtdev);
3765 if (xi.logdev && xi.logdev != xi.ddev)
3766 libxfs_device_close(xi.logdev);
3767 libxfs_device_close(xi.ddev);
3768
3769 return 0;
3770}
3771
3772static void
3773conflict(
9440d84d 3774 char opt,
05abf43d 3775 const char *tab[],
9440d84d
NS
3776 int oldidx,
3777 int newidx)
2bd0ea18 3778{
9440d84d 3779 fprintf(stderr, _("Cannot specify both -%c %s and -%c %s\n"),
2bd0ea18
NS
3780 opt, tab[oldidx], opt, tab[newidx]);
3781 usage();
3782}
3783
3784
3785static void
3786illegal(
c81c8460
DC
3787 const char *value,
3788 const char *opt)
2bd0ea18 3789{
9440d84d 3790 fprintf(stderr, _("Illegal value %s for -%s option\n"), value, opt);
2bd0ea18
NS
3791 usage();
3792}
3793
3794static int
3795ispow2(
3796 unsigned int i)
3797{
3798 return (i & (i - 1)) == 0;
3799}
3800
b1559967 3801static void __attribute__((noreturn))
2bd0ea18 3802reqval(
9440d84d 3803 char opt,
05abf43d 3804 const char *tab[],
9440d84d 3805 int idx)
2bd0ea18 3806{
9440d84d 3807 fprintf(stderr, _("-%c %s option requires a value\n"), opt, tab[idx]);
2bd0ea18
NS
3808 usage();
3809}
3810
3811static void
3812respec(
9440d84d 3813 char opt,
05abf43d 3814 const char *tab[],
9440d84d 3815 int idx)
2bd0ea18
NS
3816{
3817 fprintf(stderr, "-%c ", opt);
3818 if (tab)
3819 fprintf(stderr, "%s ", tab[idx]);
9440d84d 3820 fprintf(stderr, _("option respecified\n"));
2bd0ea18
NS
3821 usage();
3822}
3823
3824static void
3825unknown(
9440d84d
NS
3826 char opt,
3827 char *s)
2bd0ea18 3828{
9440d84d 3829 fprintf(stderr, _("unknown option -%c %s\n"), opt, s);
2bd0ea18
NS
3830 usage();
3831}
3832
2bd0ea18
NS
3833long long
3834cvtnum(
6c855628
DC
3835 unsigned int blksize,
3836 unsigned int sectsize,
a887c950 3837 const char *s)
2bd0ea18
NS
3838{
3839 long long i;
3840 char *sp;
6de2e6c0 3841 int c;
2bd0ea18
NS
3842
3843 i = strtoll(s, &sp, 0);
3844 if (i == 0 && sp == s)
3845 return -1LL;
3846 if (*sp == '\0')
3847 return i;
3848
6de2e6c0
JT
3849 if (sp[1] != '\0')
3850 return -1LL;
3851
ef92dd5a
JT
3852 if (*sp == 'b') {
3853 if (!blksize) {
3854 fprintf(stderr,
3855_("Blocksize must be provided prior to using 'b' suffix.\n"));
3856 usage();
3857 } else {
3858 return i * blksize;
3859 }
3860 }
3861 if (*sp == 's') {
3862 if (!sectsize) {
3863 fprintf(stderr,
3864_("Sectorsize must be specified prior to using 's' suffix.\n"));
3865 usage();
3866 } else {
3867 return i * sectsize;
3868 }
3869 }
a887c950 3870
6de2e6c0
JT
3871 c = tolower(*sp);
3872 switch (c) {
3873 case 'e':
3874 i *= 1024LL;
ce211a6c 3875 /* fall through */
6de2e6c0
JT
3876 case 'p':
3877 i *= 1024LL;
ce211a6c 3878 /* fall through */
6de2e6c0
JT
3879 case 't':
3880 i *= 1024LL;
ce211a6c 3881 /* fall through */
6de2e6c0
JT
3882 case 'g':
3883 i *= 1024LL;
ce211a6c 3884 /* fall through */
6de2e6c0
JT
3885 case 'm':
3886 i *= 1024LL;
ce211a6c 3887 /* fall through */
6de2e6c0
JT
3888 case 'k':
3889 return i * 1024LL;
3890 default:
3891 break;
3892 }
2bd0ea18
NS
3893 return -1LL;
3894}
3895
079afa09 3896static void __attribute__((noreturn))
9440d84d 3897usage( void )
2bd0ea18 3898{
9440d84d 3899 fprintf(stderr, _("Usage: %s\n\
2bd0ea18 3900/* blocksize */ [-b log=n|size=num]\n\
a5132d9b 3901/* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1]\n\
2bd0ea18 3902/* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\
91e684d1 3903 (sunit=value,swidth=value|su=num,sw=num|noalign),\n\
8d537733 3904 sectlog=n|sectsize=num\n\
30626ef6 3905/* force overwrite */ [-f]\n\
22bc10ed 3906/* inode size */ [-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2,\n\
6003fd81 3907 projid32bit=0|1,sparse=0|1]\n\
30626ef6 3908/* no discard */ [-K]\n\
1cba5ede 3909/* log subvol */ [-l agnum=n,internal,size=num,logdev=xxx,version=n\n\
cdded3d8
DC
3910 sunit=value|su=num,sectlog=n|sectsize=num,\n\
3911 lazy-count=0|1]\n\
979f7189 3912/* label */ [-L label (maximum 12 characters)]\n\
4eb02d95 3913/* naming */ [-n log=n|size=num,version=2|ci,ftype=0|1]\n\
30626ef6 3914/* no-op info only */ [-N]\n\
2bd0ea18
NS
3915/* prototype file */ [-p fname]\n\
3916/* quiet */ [-q]\n\
2bd0ea18 3917/* realtime subvol */ [-r extsize=num,size=num,rtdev=xxx]\n\
9440d84d
NS
3918/* sectorsize */ [-s log=n|size=num]\n\
3919/* version */ [-V]\n\
2bd0ea18 3920 devicename\n\
3fbc9137 3921<devicename> is required unless -d name=xxx is given.\n\
638473d8
NS
3922<num> is xxx (bytes), xxxs (sectors), xxxb (fs blocks), xxxk (xxx KiB),\n\
3923 xxxm (xxx MiB), xxxg (xxx GiB), xxxt (xxx TiB) or xxxp (xxx PiB).\n\
3924<value> is xxx (512 byte blocks).\n"),
2bd0ea18
NS
3925 progname);
3926 exit(1);
3927}