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