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