]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - mkfs/xfs_mkfs.c
Sort out cosmetic differences between user and kernel copies of some sources.
[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
NS
17 */
18
1d7e80ee
NS
19#include <xfs/libxfs.h>
20#include <disk/fstyp.h>
21#include <disk/volume.h>
9e017777 22#include <ctype.h>
2bd0ea18 23#include "xfs_mkfs.h"
156fafc9 24
2bd0ea18
NS
25/*
26 * Prototypes for internal functions.
27 */
28static void conflict(char opt, char *tab[], int oldidx, int newidx);
29static void illegal(char *value, char *opt);
30static void reqval(char opt, char *tab[], int idx);
31static void respec(char opt, char *tab[], int idx);
32static void unknown(char opt, char *s);
33static int ispow2(unsigned int i);
2bd0ea18
NS
34
35/*
36 * option tables for getsubopt calls
37 */
9440d84d 38char *bopts[] = {
2bd0ea18
NS
39#define B_LOG 0
40 "log",
41#define B_SIZE 1
42 "size",
43 NULL
44};
45
46char *dopts[] = {
47#define D_AGCOUNT 0
48 "agcount",
49#define D_FILE 1
50 "file",
51#define D_NAME 2
52 "name",
53#define D_SIZE 3
54 "size",
55#define D_SUNIT 4
56 "sunit",
57#define D_SWIDTH 5
58 "swidth",
59#define D_UNWRITTEN 6
60 "unwritten",
3fbc9137
NS
61#define D_AGSIZE 7
62 "agsize",
63#define D_SU 8
64 "su",
65#define D_SW 9
66 "sw",
1cba5ede
NS
67#define D_SECTLOG 10
68 "sectlog",
69#define D_SECTSIZE 11
70 "sectsize",
63a63844
NS
71#define D_NOALIGN 12
72 "noalign",
9f064b7e
NS
73#define D_RTINHERIT 13
74 "rtinherit",
75#define D_PROJINHERIT 14
76 "projinherit",
77#define D_EXTSZINHERIT 15
78 "extszinherit",
2bd0ea18
NS
79 NULL
80};
81
82char *iopts[] = {
83#define I_ALIGN 0
84 "align",
85#define I_LOG 1
86 "log",
87#define I_MAXPCT 2
88 "maxpct",
89#define I_PERBLOCK 3
90 "perblock",
91#define I_SIZE 4
92 "size",
e78b9efb
NS
93#define I_ATTR 5
94 "attr",
2bd0ea18
NS
95 NULL
96};
97
98char *lopts[] = {
99#define L_AGNUM 0
100 "agnum",
101#define L_INTERNAL 1
102 "internal",
103#define L_SIZE 2
104 "size",
73bf5988
SL
105#define L_VERSION 3
106 "version",
9e017777 107#define L_SUNIT 4
73bf5988 108 "sunit",
9e017777
ES
109#define L_SU 5
110 "su",
111#define L_DEV 6
2bd0ea18 112 "logdev",
9440d84d
NS
113#define L_SECTLOG 7
114 "sectlog",
115#define L_SECTSIZE 8
116 "sectsize",
9440d84d 117#define L_FILE 9
2bd0ea18 118 "file",
9440d84d 119#define L_NAME 10
2bd0ea18 120 "name",
2bd0ea18
NS
121 NULL
122};
123
124char *nopts[] = {
125#define N_LOG 0
126 "log",
127#define N_SIZE 1
128 "size",
129#define N_VERSION 2
130 "version",
131 NULL,
132};
133
134char *ropts[] = {
135#define R_EXTSIZE 0
136 "extsize",
137#define R_SIZE 1
138 "size",
139#define R_DEV 2
140 "rtdev",
2bd0ea18
NS
141#define R_FILE 3
142 "file",
143#define R_NAME 4
144 "name",
63a63844
NS
145#define R_NOALIGN 5
146 "noalign",
2bd0ea18
NS
147 NULL
148};
149
9440d84d
NS
150char *sopts[] = {
151#define S_LOG 0
152 "log",
153#define S_SECTLOG 1
154 "sectlog",
155#define S_SIZE 2
156 "size",
157#define S_SECTSIZE 3
158 "sectsize",
159 NULL
2bd0ea18
NS
160};
161
1f1b8be7
NS
162#define TERABYTES(count, blog) ((__uint64_t)(count) << (40 - (blog)))
163#define GIGABYTES(count, blog) ((__uint64_t)(count) << (30 - (blog)))
164#define MEGABYTES(count, blog) ((__uint64_t)(count) << (20 - (blog)))
165
2bd0ea18 166/*
9440d84d 167 * Use this macro before we have superblock and mount structure
2bd0ea18
NS
168 */
169#define DTOBT(d) ((xfs_drfsbno_t)((d) >> (blocklog - BBSHIFT)))
170
171/*
172 * Use this for block reservations needed for mkfs's conditions
173 * (basically no fragmentation).
174 */
175#define MKFS_BLOCKRES_INODE \
176 ((uint)(XFS_IALLOC_BLOCKS(mp) + (XFS_IN_MAXLEVELS(mp) - 1)))
177#define MKFS_BLOCKRES(rb) \
178 ((uint)(MKFS_BLOCKRES_INODE + XFS_DA_NODE_MAXDEPTH + \
179 (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1) + (rb)))
180
5c617c87
ES
181/* amount (in bytes) we zero at the beginning and end of the device to
182 * remove traces of other filesystems, raid superblocks, etc.
183 */
184#define WHACK_SIZE (128 * 1024)
185
3fbc9137 186static void
9440d84d
NS
187calc_stripe_factors(
188 int dsu,
189 int dsw,
190 int dsectsz,
191 int lsu,
192 int lsectsz,
193 int *dsunit,
194 int *dswidth,
195 int *lsunit)
3fbc9137 196{
9e017777 197 /* Handle data sunit/swidth options */
3fbc9137
NS
198 if (*dsunit || *dswidth) {
199 if (dsu || dsw) {
200 fprintf(stderr,
9440d84d
NS
201 _("data su/sw must not be used in "
202 "conjunction with data sunit/swidth\n"));
3fbc9137
NS
203 usage();
204 }
205
206 if ((*dsunit && !*dswidth) || (!*dsunit && *dswidth)) {
207 fprintf(stderr,
9440d84d
NS
208 _("both data sunit and data swidth options "
209 "must be specified\n"));
3fbc9137
NS
210 usage();
211 }
212 }
213
214 if (dsu || dsw) {
215 if (*dsunit || *dswidth) {
216 fprintf(stderr,
9440d84d
NS
217 _("data sunit/swidth must not be used in "
218 "conjunction with data su/sw\n"));
3fbc9137
NS
219 usage();
220 }
221
222 if ((dsu && !dsw) || (!dsu && dsw)) {
223 fprintf(stderr,
9440d84d
NS
224 _("both data su and data sw options "
225 "must be specified\n"));
3fbc9137
NS
226 usage();
227 }
228
9440d84d
NS
229 if (dsu % dsectsz) {
230 fprintf(stderr,
231 _("data su must be a multiple of the "
232 "sector size (%d)\n"), dsectsz);
3fbc9137
NS
233 usage();
234 }
235
236 *dsunit = (int)BTOBBT(dsu);
237 *dswidth = *dsunit * dsw;
238 }
239
240 if (*dsunit && (*dswidth % *dsunit != 0)) {
241 fprintf(stderr,
9440d84d
NS
242 _("data stripe width (%d) must be a multiple of the "
243 "data stripe unit (%d)\n"), *dswidth, *dsunit);
3fbc9137
NS
244 usage();
245 }
9e017777
ES
246
247 /* Handle log sunit options */
248
249 if (*lsunit) {
250 if (lsu) {
251 fprintf(stderr,
9440d84d
NS
252 _("log su should not be used in "
253 "conjunction with log sunit\n"));
9e017777
ES
254 usage();
255 }
256 }
257
258 if (lsu) {
259 if (*lsunit) {
260 fprintf(stderr,
9440d84d
NS
261 _("log sunit should not be used in "
262 "conjunction with log su\n"));
9e017777
ES
263 usage();
264 }
9440d84d 265 *lsunit = (int)BTOBBT(lsu);
9e017777 266 }
3fbc9137
NS
267}
268
f937adac 269static int
9440d84d
NS
270check_overwrite(
271 char *device)
f937adac 272{
9440d84d 273 char *type;
f937adac
NS
274
275 if (device && *device) {
276 if ((type = fstype(device)) != NULL) {
277 fprintf(stderr,
9440d84d
NS
278 _("%s: %s appears to contain an existing "
279 "filesystem (%s).\n"), progname, device, type);
f937adac
NS
280 return 1;
281 }
282 if ((type = pttype(device)) != NULL) {
283 fprintf(stderr,
9440d84d
NS
284 _("%s: %s appears to contain a partition "
285 "table (%s).\n"), progname, device, type);
f937adac
NS
286 return 1;
287 }
288 }
289 return 0;
290}
291
72e527e7
NS
292static void
293fixup_log_stripe_unit(
73bf5988 294 int lsflag,
73bf5988
SL
295 int sunit,
296 xfs_drfsbno_t *logblocks,
72e527e7 297 int blocklog)
73bf5988
SL
298{
299 __uint64_t tmp_logblocks;
300
72e527e7
NS
301 /*
302 * Make sure that the log size is a multiple of the stripe unit
73bf5988
SL
303 */
304 if ((*logblocks % sunit) != 0) {
305 if (!lsflag) {
306 tmp_logblocks = ((*logblocks + (sunit - 1))
307 / sunit) * sunit;
308 /*
309 * If the log is too large, round down
310 * instead of round up
311 */
312 if ((tmp_logblocks > XFS_MAX_LOG_BLOCKS) ||
313 ((tmp_logblocks << blocklog) > XFS_MAX_LOG_BYTES)) {
314 tmp_logblocks = (*logblocks / sunit) * sunit;
315 }
316 *logblocks = tmp_logblocks;
317 } else {
72e527e7
NS
318 fprintf(stderr, _("log size %lld is not a multiple "
319 "of the log stripe unit %d\n"),
9440d84d 320 (long long) *logblocks, sunit);
73bf5988
SL
321 usage();
322 }
323 }
72e527e7
NS
324}
325
326static xfs_dfsbno_t
327fixup_internal_log_stripe(
328 xfs_mount_t *mp,
329 int lsflag,
330 xfs_dfsbno_t logstart,
331 __uint64_t agsize,
332 int sunit,
333 xfs_drfsbno_t *logblocks,
334 int blocklog,
335 int *lalign)
336{
337 if ((logstart % sunit) != 0) {
338 logstart = ((logstart + (sunit - 1))/sunit) * sunit;
339 *lalign = 1;
340 }
341
342 fixup_log_stripe_unit(lsflag, sunit, logblocks, blocklog);
73bf5988 343
9440d84d 344 if (*logblocks > agsize - XFS_FSB_TO_AGBNO(mp, logstart)) {
73bf5988 345 fprintf(stderr,
9440d84d
NS
346 _("Due to stripe alignment, the internal log size "
347 "(%lld) is too large.\n"), (long long) *logblocks);
348 fprintf(stderr, _("Must fit within an allocation group.\n"));
73bf5988
SL
349 usage();
350 }
351 return logstart;
352}
2bd0ea18 353
cfd4ac07
NS
354void
355validate_log_size(__uint64_t logblocks, int blocklog, int min_logblocks)
356{
357 if (logblocks < min_logblocks) {
358 fprintf(stderr,
359 _("log size %lld blocks too small, minimum size is %d blocks\n"),
360 (long long)logblocks, min_logblocks);
361 usage();
362 }
363 if (logblocks > XFS_MAX_LOG_BLOCKS) {
364 fprintf(stderr,
365 _("log size %lld blocks too large, maximum size is %d blocks\n"),
366 (long long)logblocks, XFS_MAX_LOG_BLOCKS);
367 usage();
368 }
369 if ((logblocks << blocklog) > XFS_MAX_LOG_BYTES) {
370 fprintf(stderr,
371 _("log size %lld bytes too large, maximum size is %d bytes\n"),
372 (long long)(logblocks << blocklog), XFS_MAX_LOG_BYTES);
373 usage();
374 }
375}
376
1f1b8be7
NS
377void
378calc_default_ag_geometry(
379 int blocklog,
380 __uint64_t dblocks,
381 __uint64_t *agsize,
382 __uint64_t *agcount)
383{
384 __uint64_t blocks;
385 __uint64_t count = 0;
386 int shift = 0;
387
388 /*
389 * First handle the extremes - the points at which we will
390 * always use the maximum AG size, the points at which we
391 * always use the minimum, and a "small-step" for 16-128Mb.
392 */
67256a79 393 if (dblocks >= TERABYTES(32, blocklog)) {
1f1b8be7
NS
394 blocks = XFS_AG_MAX_BLOCKS(blocklog);
395 goto done;
396 } else if (dblocks < MEGABYTES(16, blocklog)) {
397 blocks = dblocks;
398 count = 1;
399 goto done;
400 } else if (dblocks < MEGABYTES(128, blocklog)) {
401 blocks = MEGABYTES(16, blocklog);
402 goto done;
403 }
404
405 /*
406 * For the remainder we choose an AG size based on the
407 * number of data blocks available, trying to keep the
408 * number of AGs relatively small (especially compared
409 * to the original algorithm). AG count is calculated
410 * based on the prefered AG size, not vice-versa - the
411 * count can be increased by growfs, so prefer to use
412 * smaller counts at mkfs time.
413 *
414 * This scales us up smoothly between min/max AG sizes.
415 */
416 if (dblocks > GIGABYTES(512, blocklog))
417 shift = 5;
418 else if (dblocks > GIGABYTES(8, blocklog))
419 shift = 4;
420 else if (dblocks >= MEGABYTES(128, blocklog))
421 shift = 3;
422 else
423 ASSERT(0);
424 blocks = dblocks >> shift;
425
426done:
427 if (!count)
428 count = dblocks / blocks + (dblocks % blocks != 0);
429 *agsize = blocks;
430 *agcount = count;
431}
432
433static void
434validate_ag_geometry(
435 int blocklog,
436 __uint64_t dblocks,
437 __uint64_t agsize,
438 __uint64_t agcount)
439{
440 if (agsize < XFS_AG_MIN_BLOCKS(blocklog)) {
441 fprintf(stderr,
442 _("agsize (%lldb) too small, need at least %lld blocks\n"),
443 (long long)agsize,
444 (long long)XFS_AG_MIN_BLOCKS(blocklog));
445 usage();
446 }
447
448 if (agsize > XFS_AG_MAX_BLOCKS(blocklog)) {
449 fprintf(stderr,
450 _("agsize (%lldb) too big, maximum is %lld blocks\n"),
451 (long long)agsize,
452 (long long)XFS_AG_MAX_BLOCKS(blocklog));
453 usage();
454 }
455
456 if (agsize > dblocks) {
457 fprintf(stderr,
458 _("agsize (%lldb) too big, data area is %lld blocks\n"),
459 (long long)agsize, (long long)dblocks);
460 usage();
461 }
462
463 if (agsize < XFS_AG_MIN_BLOCKS(blocklog)) {
464 fprintf(stderr,
465 _("too many allocation groups for size = %lld\n"),
466 (long long)agsize);
467 fprintf(stderr, _("need at most %lld allocation groups\n"),
468 (long long)(dblocks / XFS_AG_MIN_BLOCKS(blocklog) +
469 (dblocks % XFS_AG_MIN_BLOCKS(blocklog) != 0)));
470 usage();
471 }
472
473 if (agsize > XFS_AG_MAX_BLOCKS(blocklog)) {
474 fprintf(stderr,
475 _("too few allocation groups for size = %lld\n"), (long long)agsize);
476 fprintf(stderr,
477 _("need at least %lld allocation groups\n"),
478 (long long)(dblocks / XFS_AG_MAX_BLOCKS(blocklog) +
479 (dblocks % XFS_AG_MAX_BLOCKS(blocklog) != 0)));
480 usage();
481 }
482
483 /*
484 * If the last AG is too small, reduce the filesystem size
485 * and drop the blocks.
486 */
487 if ( dblocks % agsize != 0 &&
488 (dblocks % agsize < XFS_AG_MIN_BLOCKS(blocklog))) {
489 fprintf(stderr,
490 _("last AG size %lld blocks too small, minimum size is %lld blocks\n"),
491 (long long)(dblocks % agsize),
492 (long long)XFS_AG_MIN_BLOCKS(blocklog));
493 usage();
494 }
495
496 /*
497 * If agcount is too large, make it smaller.
498 */
499 if (agcount > XFS_MAX_AGNUMBER + 1) {
500 fprintf(stderr,
501 _("%lld allocation groups is too many, maximum is %lld\n"),
502 (long long)agcount, (long long)XFS_MAX_AGNUMBER + 1);
503 usage();
504 }
505}
506
2bd0ea18 507int
9440d84d
NS
508main(
509 int argc,
510 char **argv)
2bd0ea18
NS
511{
512 __uint64_t agcount;
513 xfs_agf_t *agf;
514 xfs_agi_t *agi;
515 xfs_agnumber_t agno;
516 __uint64_t agsize;
517 xfs_alloc_rec_t *arec;
e78b9efb 518 int attrversion;
2bd0ea18
NS
519 xfs_btree_sblock_t *block;
520 int blflag;
521 int blocklog;
cb7ba2b0 522 unsigned int blocksize;
2bd0ea18
NS
523 int bsflag;
524 int bsize;
525 xfs_buf_t *buf;
526 int c;
527 int daflag;
3fbc9137 528 int dasize;
2bd0ea18
NS
529 xfs_drfsbno_t dblocks;
530 char *dfile;
531 int dirblocklog;
532 int dirblocksize;
533 int dirversion;
2bd0ea18 534 char *dsize;
3fbc9137
NS
535 int dsu;
536 int dsw;
2bd0ea18
NS
537 int dsunit;
538 int dswidth;
539 int extent_flagging;
f937adac 540 int force_overwrite;
9f064b7e 541 struct fsxattr fsx;
2bd0ea18
NS
542 int iaflag;
543 int ilflag;
544 int imaxpct;
545 int imflag;
546 int inodelog;
547 int inopblock;
548 int ipflag;
549 int isflag;
550 int isize;
979f7189 551 char *label = NULL;
2bd0ea18
NS
552 int laflag;
553 int lalign;
554 int ldflag;
555 int liflag;
556 xfs_agnumber_t logagno;
557 xfs_drfsbno_t logblocks;
558 char *logfile;
559 int loginternal;
560 char *logsize;
561 xfs_dfsbno_t logstart;
73bf5988
SL
562 int logversion;
563 int lvflag;
2bd0ea18 564 int lsflag;
9440d84d
NS
565 int lsectorlog;
566 int lsectorsize;
1cba5ede
NS
567 int lslflag;
568 int lssflag;
9e017777 569 int lsu;
73bf5988 570 int lsunit;
cfd4ac07 571 int max_tr_res;
2bd0ea18 572 int min_logblocks;
2bd0ea18
NS
573 xfs_mount_t *mp;
574 xfs_mount_t mbuf;
575 xfs_extlen_t nbmblocks;
576 int nlflag;
577 int nodsflag;
63a63844 578 int norsflag;
2bd0ea18
NS
579 xfs_alloc_rec_t *nrec;
580 int nsflag;
581 int nvflag;
33a12367 582 int Nflag;
2bd0ea18
NS
583 char *p;
584 char *protofile;
585 char *protostring;
586 int qflag;
587 xfs_drfsbno_t rtblocks;
588 xfs_extlen_t rtextblocks;
589 xfs_drtbno_t rtextents;
590 char *rtextsize;
591 char *rtfile;
592 char *rtsize;
593 xfs_sb_t *sbp;
c22b5fdf 594 int sectoralign;
9440d84d 595 int sectorlog;
cb7ba2b0 596 unsigned int sectorsize;
9440d84d
NS
597 int slflag;
598 int ssflag;
2bd0ea18
NS
599 __uint64_t tmp_agsize;
600 uuid_t uuid;
601 int worst_freelist;
602 libxfs_init_t xi;
603 int xlv_dsunit;
604 int xlv_dswidth;
605
606 progname = basename(argv[0]);
9440d84d
NS
607 setlocale(LC_ALL, "");
608 bindtextdomain(PACKAGE, LOCALEDIR);
609 textdomain(PACKAGE);
610
e78b9efb 611 attrversion = 0;
1cba5ede 612 blflag = bsflag = slflag = ssflag = lslflag = lssflag = 0;
836f654f 613 blocklog = blocksize = 0;
1cba5ede
NS
614 sectorlog = lsectorlog = XFS_MIN_SECTORSIZE_LOG;
615 sectorsize = lsectorsize = XFS_MIN_SECTORSIZE;
9440d84d 616 agsize = daflag = dasize = dblocks = 0;
2bd0ea18 617 ilflag = imflag = ipflag = isflag = 0;
73bf5988 618 liflag = laflag = lsflag = ldflag = lvflag = 0;
2bd0ea18 619 loginternal = 1;
73bf5988 620 logversion = 1;
2bd0ea18 621 logagno = logblocks = rtblocks = 0;
33a12367 622 Nflag = nlflag = nsflag = nvflag = 0;
2bd0ea18
NS
623 dirblocklog = dirblocksize = dirversion = 0;
624 qflag = 0;
625 imaxpct = inodelog = inopblock = isize = 0;
626 iaflag = XFS_IFLAG_ALIGN;
2bd0ea18 627 dfile = logfile = rtfile = NULL;
9e017777 628 dsize = logsize = rtsize = rtextsize = protofile = NULL;
63a63844
NS
629 dsu = dsw = dsunit = dswidth = lalign = lsu = lsunit = 0;
630 nodsflag = norsflag = 0;
4ca431fc 631 extent_flagging = 1;
f937adac 632 force_overwrite = 0;
2bd0ea18 633 worst_freelist = 0;
9f064b7e 634 bzero(&fsx, sizeof(fsx));
2bd0ea18 635
9440d84d
NS
636 bzero(&xi, sizeof(xi));
637 xi.notvolok = 1;
638 xi.setblksize = 1;
7eb6693f 639 xi.isreadonly = LIBXFS_EXCLUSIVELY;
9440d84d
NS
640
641 while ((c = getopt(argc, argv, "b:d:i:l:L:n:Np:qr:s:CfV")) != EOF) {
2bd0ea18
NS
642 switch (c) {
643 case 'C':
2bd0ea18 644 case 'f':
f937adac 645 force_overwrite = 1;
2bd0ea18
NS
646 break;
647 case 'b':
648 p = optarg;
649 while (*p != '\0') {
650 char *value;
651
652 switch (getsubopt(&p, (constpp)bopts, &value)) {
653 case B_LOG:
654 if (!value)
655 reqval('b', bopts, B_LOG);
656 if (blflag)
657 respec('b', bopts, B_LOG);
658 if (bsflag)
659 conflict('b', bopts, B_SIZE,
660 B_LOG);
661 blocklog = atoi(value);
662 if (blocklog <= 0)
663 illegal(value, "b log");
664 blocksize = 1 << blocklog;
665 blflag = 1;
666 break;
667 case B_SIZE:
668 if (!value)
669 reqval('b', bopts, B_SIZE);
670 if (bsflag)
671 respec('b', bopts, B_SIZE);
672 if (blflag)
673 conflict('b', bopts, B_LOG,
674 B_SIZE);
9440d84d
NS
675 blocksize = cvtnum(
676 blocksize, sectorsize, value);
2bd0ea18
NS
677 if (blocksize <= 0 ||
678 !ispow2(blocksize))
679 illegal(value, "b size");
680 blocklog = libxfs_highbit32(blocksize);
681 bsflag = 1;
682 break;
683 default:
684 unknown('b', value);
685 }
686 }
687 break;
688 case 'd':
689 p = optarg;
690 while (*p != '\0') {
691 char *value;
692
693 switch (getsubopt(&p, (constpp)dopts, &value)) {
694 case D_AGCOUNT:
695 if (!value)
696 reqval('d', dopts, D_AGCOUNT);
697 if (daflag)
698 respec('d', dopts, D_AGCOUNT);
33a12367
NS
699 agcount = (__uint64_t)
700 strtoul(value, NULL, 10);
2bd0ea18
NS
701 if ((__int64_t)agcount <= 0)
702 illegal(value, "d agcount");
703 daflag = 1;
704 break;
3fbc9137
NS
705 case D_AGSIZE:
706 if (!value)
707 reqval('d', dopts, D_AGSIZE);
708 if (dasize)
709 respec('d', dopts, D_AGSIZE);
9440d84d
NS
710 agsize = cvtnum(
711 blocksize, sectorsize, value);
3fbc9137
NS
712 dasize = 1;
713 break;
2bd0ea18
NS
714 case D_FILE:
715 if (!value)
716 value = "1";
717 xi.disfile = atoi(value);
718 if (xi.disfile < 0 || xi.disfile > 1)
719 illegal(value, "d file");
720 if (xi.disfile)
721 xi.dcreat = 1;
722 break;
723 case D_NAME:
724 if (!value)
725 reqval('d', dopts, D_NAME);
726 if (xi.dname)
727 respec('d', dopts, D_NAME);
728 xi.dname = value;
729 break;
730 case D_SIZE:
731 if (!value)
732 reqval('d', dopts, D_SIZE);
733 if (dsize)
734 respec('d', dopts, D_SIZE);
735 dsize = value;
736 break;
737 case D_SUNIT:
738 if (!value)
739 reqval('d', dopts, D_SUNIT);
740 if (dsunit)
741 respec('d', dopts, D_SUNIT);
63a63844
NS
742 if (nodsflag)
743 conflict('d', dopts, D_NOALIGN,
744 D_SUNIT);
9e017777
ES
745 if (!isdigits(value)) {
746 fprintf(stderr,
9440d84d 747 _("%s: Specify data sunit in 512-byte blocks, no unit suffix\n"),
9e017777
ES
748 progname);
749 exit(1);
750 }
9440d84d 751 dsunit = cvtnum(0, 0, value);
2bd0ea18
NS
752 break;
753 case D_SWIDTH:
754 if (!value)
755 reqval('d', dopts, D_SWIDTH);
756 if (dswidth)
757 respec('d', dopts, D_SWIDTH);
63a63844
NS
758 if (nodsflag)
759 conflict('d', dopts, D_NOALIGN,
760 D_SWIDTH);
9e017777
ES
761 if (!isdigits(value)) {
762 fprintf(stderr,
9440d84d 763 _("%s: Specify data swidth in 512-byte blocks, no unit suffix\n"),
9e017777
ES
764 progname);
765 exit(1);
766 }
9440d84d 767 dswidth = cvtnum(0, 0, value);
3fbc9137
NS
768 break;
769 case D_SU:
770 if (!value)
771 reqval('d', dopts, D_SU);
772 if (dsu)
773 respec('d', dopts, D_SU);
63a63844
NS
774 if (nodsflag)
775 conflict('d', dopts, D_NOALIGN,
776 D_SU);
9440d84d
NS
777 dsu = cvtnum(
778 blocksize, sectorsize, value);
3fbc9137
NS
779 break;
780 case D_SW:
781 if (!value)
782 reqval('d', dopts, D_SW);
783 if (dsw)
784 respec('d', dopts, D_SW);
63a63844
NS
785 if (nodsflag)
786 conflict('d', dopts, D_NOALIGN,
787 D_SW);
9e017777
ES
788 if (!isdigits(value)) {
789 fprintf(stderr,
9440d84d 790 _("%s: Specify data sw as multiple of su, no unit suffix\n"),
9e017777
ES
791 progname);
792 exit(1);
793 }
9440d84d 794 dsw = cvtnum(0, 0, value);
2bd0ea18 795 break;
63a63844
NS
796 case D_NOALIGN:
797 if (dsu)
798 conflict('d', dopts, D_SU,
799 D_NOALIGN);
800 if (dsunit)
801 conflict('d', dopts, D_SUNIT,
802 D_NOALIGN);
803 if (dsw)
804 conflict('d', dopts, D_SW,
805 D_NOALIGN);
806 if (dswidth)
807 conflict('d', dopts, D_SWIDTH,
808 D_NOALIGN);
809 nodsflag = 1;
810 break;
2bd0ea18
NS
811 case D_UNWRITTEN:
812 if (!value)
1cba5ede 813 reqval('d', dopts, D_UNWRITTEN);
cfd4ac07
NS
814 c = atoi(value);
815 if (c < 0 || c > 1)
1cba5ede 816 illegal(value, "d unwritten");
cfd4ac07 817 extent_flagging = c;
2bd0ea18 818 break;
1cba5ede
NS
819 case D_SECTLOG:
820 if (!value)
821 reqval('d', dopts, D_SECTLOG);
822 if (slflag)
823 respec('d', dopts, D_SECTLOG);
824 if (ssflag)
825 conflict('d', dopts, D_SECTSIZE,
826 D_SECTLOG);
827 sectorlog = atoi(value);
828 if (sectorlog <= 0)
829 illegal(value, "d sectlog");
830 sectorsize = 1 << sectorlog;
831 slflag = 1;
832 break;
833 case D_SECTSIZE:
834 if (!value)
835 reqval('d', dopts, D_SECTSIZE);
836 if (ssflag)
837 respec('d', dopts, D_SECTSIZE);
838 if (slflag)
839 conflict('d', dopts, D_SECTLOG,
840 D_SECTSIZE);
841 sectorsize = cvtnum(
842 blocksize, sectorsize, value);
843 if (sectorsize <= 0 ||
844 !ispow2(sectorsize))
845 illegal(value, "d sectsize");
846 sectorlog =
847 libxfs_highbit32(sectorsize);
848 ssflag = 1;
849 break;
9f064b7e
NS
850 case D_RTINHERIT:
851 fsx.fsx_xflags |= \
852 XFS_DIFLAG_RTINHERIT;
853 break;
854 case D_PROJINHERIT:
855 if (!value)
856 reqval('d', dopts, D_PROJINHERIT);
857 fsx.fsx_projid = atoi(value);
858 fsx.fsx_xflags |= \
859 XFS_DIFLAG_PROJINHERIT;
860 break;
861 case D_EXTSZINHERIT:
862 if (!value)
863 reqval('d', dopts, D_EXTSZINHERIT);
864 fsx.fsx_extsize = atoi(value);
865 fsx.fsx_xflags |= \
866 XFS_DIFLAG_EXTSZINHERIT;
867 break;
2bd0ea18
NS
868 default:
869 unknown('d', value);
870 }
871 }
872 break;
873 case 'i':
874 p = optarg;
875 while (*p != '\0') {
876 char *value;
877
878 switch (getsubopt(&p, (constpp)iopts, &value)) {
879 case I_ALIGN:
880 if (!value)
881 value = "1";
882 iaflag = atoi(value);
883 if (iaflag < 0 || iaflag > 1)
884 illegal(value, "i align");
885 break;
886 case I_LOG:
887 if (!value)
888 reqval('i', iopts, I_LOG);
889 if (ilflag)
890 respec('i', iopts, I_LOG);
891 if (ipflag)
892 conflict('i', iopts, I_PERBLOCK,
893 I_LOG);
894 if (isflag)
895 conflict('i', iopts, I_SIZE,
896 I_LOG);
897 inodelog = atoi(value);
898 if (inodelog <= 0)
899 illegal(value, "i log");
900 isize = 1 << inodelog;
901 ilflag = 1;
902 break;
903 case I_MAXPCT:
904 if (!value)
905 reqval('i', iopts, I_MAXPCT);
906 if (imflag)
907 respec('i', iopts, I_MAXPCT);
908 imaxpct = atoi(value);
909 if (imaxpct < 0 || imaxpct > 100)
910 illegal(value, "i maxpct");
911 imflag = 1;
912 break;
913 case I_PERBLOCK:
914 if (!value)
915 reqval('i', iopts, I_PERBLOCK);
916 if (ilflag)
917 conflict('i', iopts, I_LOG,
918 I_PERBLOCK);
919 if (ipflag)
920 respec('i', iopts, I_PERBLOCK);
921 if (isflag)
922 conflict('i', iopts, I_SIZE,
923 I_PERBLOCK);
924 inopblock = atoi(value);
925 if (inopblock <
926 XFS_MIN_INODE_PERBLOCK ||
927 !ispow2(inopblock))
928 illegal(value, "i perblock");
929 ipflag = 1;
930 break;
931 case I_SIZE:
932 if (!value)
933 reqval('i', iopts, I_SIZE);
934 if (ilflag)
935 conflict('i', iopts, I_LOG,
936 I_SIZE);
937 if (ipflag)
938 conflict('i', iopts, I_PERBLOCK,
939 I_SIZE);
940 if (isflag)
941 respec('i', iopts, I_SIZE);
9440d84d 942 isize = cvtnum(0, 0, value);
2bd0ea18
NS
943 if (isize <= 0 || !ispow2(isize))
944 illegal(value, "i size");
945 inodelog = libxfs_highbit32(isize);
946 isflag = 1;
947 break;
e78b9efb
NS
948 case I_ATTR:
949 if (!value)
950 reqval('i', iopts, I_ATTR);
951 c = atoi(value);
952 if (c < 0 || c > 2)
953 illegal(value, "i attr");
954 attrversion = c;
955 break;
2bd0ea18
NS
956 default:
957 unknown('i', value);
958 }
959 }
960 break;
961 case 'l':
962 p = optarg;
963 while (*p != '\0') {
964 char *value;
965
966 switch (getsubopt(&p, (constpp)lopts, &value)) {
967 case L_AGNUM:
968 if (laflag)
969 respec('l', lopts, L_AGNUM);
970
971 if (ldflag)
972 conflict('l', lopts, L_AGNUM, L_DEV);
973
974 logagno = atoi(value);
975 laflag = 1;
976 break;
977 case L_DEV:
978 if (!value) {
9440d84d
NS
979 fprintf(stderr,
980 _("Must specify log device\n"));
2bd0ea18
NS
981 usage();
982 }
983
984 if (laflag)
985 conflict('l', lopts, L_AGNUM, L_DEV);
986
987 if (liflag)
988 conflict('l', lopts, L_INTERNAL, L_DEV);
989
990 ldflag = 1;
991 loginternal = 0;
992 logfile = value;
993 xi.logname = value;
994 break;
995#ifdef HAVE_VOLUME_MANAGER
996 case L_FILE:
997 if (!value)
998 value = "1";
999 if (loginternal)
1000 conflict('l', lopts, L_INTERNAL,
1001 L_FILE);
1002 xi.lisfile = atoi(value);
1003 if (xi.lisfile < 0 || xi.lisfile > 1)
1004 illegal(value, "l file");
1005 if (xi.lisfile)
1006 xi.lcreat = 1;
1007 break;
1008#endif
1009 case L_INTERNAL:
1010 if (!value)
1011 value = "1";
1012
1013 if (ldflag)
1014 conflict('l', lopts, L_INTERNAL, L_DEV);
1015#ifdef HAVE_VOLUME_MANAGER
1016 if (xi.logname)
1017 conflict('l', lopts, L_NAME,
1018 L_INTERNAL);
1019 if (xi.lisfile)
1020 conflict('l', lopts, L_FILE,
1021 L_INTERNAL);
1022#endif
1023 if (liflag)
1024 respec('l', lopts, L_INTERNAL);
1025 loginternal = atoi(value);
1026 if (loginternal < 0 || loginternal > 1)
1027 illegal(value, "l internal");
1028 liflag = 1;
1029 break;
9e017777 1030 case L_SU:
73bf5988 1031 if (!value)
9e017777
ES
1032 reqval('l', lopts, L_SU);
1033 if (lsu)
1034 respec('l', lopts, L_SU);
9440d84d
NS
1035 lsu = cvtnum(
1036 blocksize, sectorsize, value);
9e017777
ES
1037 break;
1038 case L_SUNIT:
1039 if (!value)
1040 reqval('l', lopts, L_SUNIT);
1041 if (lsunit)
1042 respec('l', lopts, L_SUNIT);
1043 if (!isdigits(value)) {
1044 fprintf(stderr,
9440d84d 1045 _("Specify log sunit in 512-byte blocks, no size suffix\n"));
9e017777
ES
1046 usage();
1047 }
9440d84d 1048 lsunit = cvtnum(0, 0, value);
73bf5988 1049 break;
2bd0ea18
NS
1050#ifdef HAVE_VOLUME_MANAGER
1051 case L_NAME:
1052 if (!value)
1053 reqval('l', lopts, L_NAME);
1054 if (loginternal)
1055 conflict('l', lopts, L_INTERNAL,
1056 L_NAME);
1057 if (xi.logname)
1058 respec('l', lopts, L_NAME);
1059 xi.logname = value;
1060 break;
1061#endif
73bf5988
SL
1062 case L_VERSION:
1063 if (!value)
1cba5ede 1064 reqval('l', lopts, L_VERSION);
73bf5988 1065 if (lvflag)
1cba5ede 1066 respec('l', lopts, L_VERSION);
73bf5988
SL
1067 logversion = atoi(value);
1068 if (logversion < 1 || logversion > 2)
1069 illegal(value, "l version");
1070 lvflag = 1;
1071 break;
2bd0ea18
NS
1072 case L_SIZE:
1073 if (!value)
1074 reqval('l', lopts, L_SIZE);
1075 if (logsize)
1076 respec('l', lopts, L_SIZE);
1077 logsize = value;
1078 lsflag = 1;
1079 break;
9440d84d
NS
1080 case L_SECTLOG:
1081 if (!value)
1cba5ede
NS
1082 reqval('l', lopts, L_SECTLOG);
1083 if (lslflag)
1084 respec('l', lopts, L_SECTLOG);
1085 if (lssflag)
1086 conflict('l', lopts, L_SECTSIZE,
1087 L_SECTLOG);
9440d84d
NS
1088 lsectorlog = atoi(value);
1089 if (lsectorlog <= 0)
1090 illegal(value, "l sectlog");
1091 lsectorsize = 1 << lsectorlog;
1cba5ede 1092 lslflag = 1;
9440d84d
NS
1093 break;
1094 case L_SECTSIZE:
1095 if (!value)
1096 reqval('l', lopts, L_SECTSIZE);
1cba5ede 1097 if (lssflag)
9440d84d 1098 respec('l', lopts, L_SECTSIZE);
1cba5ede
NS
1099 if (lslflag)
1100 conflict('l', lopts, L_SECTLOG,
1101 L_SECTSIZE);
9440d84d
NS
1102 lsectorsize = cvtnum(
1103 blocksize, sectorsize, value);
1104 if (lsectorsize <= 0 ||
1105 !ispow2(lsectorsize))
1106 illegal(value, "l sectsize");
1107 lsectorlog =
1108 libxfs_highbit32(lsectorsize);
1cba5ede 1109 lssflag = 1;
9440d84d 1110 break;
2bd0ea18
NS
1111 default:
1112 unknown('l', value);
1113 }
1114 }
1115 break;
979f7189
NS
1116 case 'L':
1117 if (strlen(optarg) > sizeof(sbp->sb_fname))
1118 illegal(optarg, "L");
1119 label = optarg;
1120 break;
2bd0ea18
NS
1121 case 'n':
1122 p = optarg;
1123 while (*p != '\0') {
1124 char *value;
1125
1126 switch (getsubopt(&p, (constpp)nopts, &value)) {
1127 case N_LOG:
1128 if (!value)
1129 reqval('n', nopts, N_LOG);
1130 if (nlflag)
1131 respec('n', nopts, N_LOG);
1132 if (nsflag)
1133 conflict('n', nopts, N_SIZE,
1134 N_LOG);
1135 dirblocklog = atoi(value);
1136 if (dirblocklog <= 0)
1137 illegal(value, "n log");
1138 dirblocksize = 1 << dirblocklog;
1139 nlflag = 1;
1140 break;
1141 case N_SIZE:
1142 if (!value)
1143 reqval('n', nopts, N_SIZE);
1144 if (nsflag)
1145 respec('n', nopts, N_SIZE);
1146 if (nlflag)
1147 conflict('n', nopts, N_LOG,
1148 N_SIZE);
9440d84d
NS
1149 dirblocksize = cvtnum(
1150 blocksize, sectorsize, value);
2bd0ea18
NS
1151 if (dirblocksize <= 0 ||
1152 !ispow2(dirblocksize))
1153 illegal(value, "n size");
1154 dirblocklog =
1155 libxfs_highbit32(dirblocksize);
1156 nsflag = 1;
1157 break;
1158 case N_VERSION:
1159 if (!value)
1160 reqval('n', nopts, N_VERSION);
1161 if (nvflag)
1162 respec('n', nopts, N_VERSION);
1163 dirversion = atoi(value);
1164 if (dirversion < 1 || dirversion > 2)
1165 illegal(value, "n version");
1166 nvflag = 1;
1167 break;
1168 default:
1169 unknown('n', value);
1170 }
1171 }
1172 break;
33a12367
NS
1173 case 'N':
1174 Nflag = 1;
1175 break;
2bd0ea18
NS
1176 case 'p':
1177 if (protofile)
1178 respec('p', 0, 0);
1179 protofile = optarg;
1180 break;
1181 case 'q':
1182 qflag = 1;
1183 break;
1184 case 'r':
1185 p = optarg;
1186 while (*p != '\0') {
1187 char *value;
1188
1189 switch (getsubopt(&p, (constpp)ropts, &value)) {
1190 case R_EXTSIZE:
1191 if (!value)
1192 reqval('r', ropts, R_EXTSIZE);
1193 if (rtextsize)
1194 respec('r', ropts, R_EXTSIZE);
1195 rtextsize = value;
1196 break;
1197 case R_DEV:
1198 if (!value)
1199 reqval('r', ropts, R_DEV);
1200 xi.rtname = value;
1201 break;
1202#ifdef HAVE_VOLUME_MANAGER
1203 case R_FILE:
1204 if (!value)
1205 value = "1";
1206 xi.risfile = atoi(value);
1207 if (xi.risfile < 0 || xi.risfile > 1)
1208 illegal(value, "r file");
1209 if (xi.risfile)
1210 xi.rcreat = 1;
1211 break;
1212 case R_NAME:
1213 if (!value)
1214 reqval('r', ropts, R_NAME);
1215 if (xi.rtname)
1216 respec('r', ropts, R_NAME);
1217 xi.rtname = value;
1218 break;
1219#endif
1220 case R_SIZE:
1221 if (!value)
1222 reqval('r', ropts, R_SIZE);
1223 if (rtsize)
1224 respec('r', ropts, R_SIZE);
1225 rtsize = value;
1226 break;
63a63844
NS
1227 case R_NOALIGN:
1228 norsflag = 1;
1229 break;
2bd0ea18
NS
1230 default:
1231 unknown('r', value);
1232 }
1233 }
1234 break;
9440d84d
NS
1235 case 's':
1236 p = optarg;
1237 while (*p != '\0') {
1238 char *value;
1239
1240 switch (getsubopt(&p, (constpp)sopts, &value)) {
1241 case S_LOG:
1242 case S_SECTLOG:
1243 if (!value)
1cba5ede
NS
1244 reqval('s', sopts, S_SECTLOG);
1245 if (slflag || lslflag)
1246 respec('s', sopts, S_SECTLOG);
1247 if (ssflag || lssflag)
1248 conflict('s', sopts, S_SECTSIZE,
1249 S_SECTLOG);
9440d84d
NS
1250 sectorlog = atoi(value);
1251 if (sectorlog <= 0)
1cba5ede
NS
1252 illegal(value, "s sectlog");
1253 lsectorlog = sectorlog;
9440d84d 1254 sectorsize = 1 << sectorlog;
1cba5ede
NS
1255 lsectorsize = sectorsize;
1256 lslflag = slflag = 1;
9440d84d
NS
1257 break;
1258 case S_SIZE:
1259 case S_SECTSIZE:
1260 if (!value)
1cba5ede
NS
1261 reqval('s', sopts, S_SECTSIZE);
1262 if (ssflag || lssflag)
1263 respec('s', sopts, S_SECTSIZE);
1264 if (slflag || lslflag)
1265 conflict('s', sopts, S_SECTLOG,
1266 S_SECTSIZE);
9440d84d
NS
1267 sectorsize = cvtnum(
1268 blocksize, sectorsize, value);
1269 if (sectorsize <= 0 ||
1270 !ispow2(sectorsize))
1cba5ede
NS
1271 illegal(value, "s sectsize");
1272 lsectorsize = sectorsize;
9440d84d
NS
1273 sectorlog =
1274 libxfs_highbit32(sectorsize);
1cba5ede
NS
1275 lsectorlog = sectorlog;
1276 lssflag = ssflag = 1;
9440d84d
NS
1277 break;
1278 default:
1279 unknown('s', value);
1280 }
1281 }
1282 break;
2bd0ea18 1283 case 'V':
9440d84d 1284 printf(_("%s version %s\n"), progname, VERSION);
3d98fe63 1285 exit(0);
2bd0ea18
NS
1286 case '?':
1287 unknown(optopt, "");
1288 }
1289 }
1290 if (argc - optind > 1) {
9440d84d 1291 fprintf(stderr, _("extra arguments\n"));
2bd0ea18
NS
1292 usage();
1293 } else if (argc - optind == 1) {
1294 dfile = xi.volname = argv[optind];
1295 if (xi.dname) {
1296 fprintf(stderr,
9440d84d 1297 _("cannot specify both %s and -d name=%s\n"),
2bd0ea18
NS
1298 xi.volname, xi.dname);
1299 usage();
1300 }
1301 } else
1302 dfile = xi.dname;
9440d84d 1303
836f654f 1304 /*
9440d84d 1305 * Blocksize and sectorsize first, other things depend on them
c22b5fdf
NS
1306 * For RAID4/5/6 we want to align sector size and block size,
1307 * so we need to start with the device geometry extraction too.
836f654f
NS
1308 */
1309 if (!blflag && !bsflag) {
1310 blocklog = XFS_DFL_BLOCKSIZE_LOG;
1311 blocksize = 1 << XFS_DFL_BLOCKSIZE_LOG;
1312 }
2bd0ea18 1313 if (blocksize < XFS_MIN_BLOCKSIZE || blocksize > XFS_MAX_BLOCKSIZE) {
9440d84d
NS
1314 fprintf(stderr, _("illegal block size %d\n"), blocksize);
1315 usage();
1316 }
c22b5fdf
NS
1317
1318 sectoralign = 0;
1319 xlv_dsunit = xlv_dswidth = 0;
1320 if (!nodsflag && !xi.disfile)
1321 get_subvol_stripe_wrapper(dfile, SVTYPE_DATA,
1322 &xlv_dsunit, &xlv_dswidth, &sectoralign);
1323 if (sectoralign) {
1324 sectorsize = blocksize;
1325 sectorlog = libxfs_highbit32(sectorsize);
1326 if (loginternal) {
1327 lsectorsize = sectorsize;
1328 lsectorlog = sectorlog;
1329 }
1330 }
9440d84d
NS
1331 if (sectorsize < XFS_MIN_SECTORSIZE ||
1332 sectorsize > XFS_MAX_SECTORSIZE || sectorsize > blocksize) {
1333 fprintf(stderr, _("illegal sector size %d\n"), sectorsize);
1334 usage();
1335 }
1cba5ede
NS
1336 if (lsectorsize < XFS_MIN_SECTORSIZE ||
1337 lsectorsize > XFS_MAX_SECTORSIZE || lsectorsize > blocksize) {
1338 fprintf(stderr, _("illegal log sector size %d\n"), lsectorsize);
1339 usage();
1340 } else if (lsectorsize > XFS_MIN_SECTORSIZE && !lsu && !lsunit) {
1341 lsu = blocksize;
1342 logversion = 2;
1343 }
9440d84d 1344
2bd0ea18
NS
1345 if (!nvflag)
1346 dirversion = (nsflag || nlflag) ? 2 : XFS_DFL_DIR_VERSION;
1347 switch (dirversion) {
1348 case 1:
1349 if ((nsflag || nlflag) && dirblocklog != blocklog) {
9440d84d 1350 fprintf(stderr, _("illegal directory block size %d\n"),
2bd0ea18
NS
1351 dirblocksize);
1352 usage();
1353 }
1354 break;
1355 case 2:
1356 if (nsflag || nlflag) {
1357 if (dirblocksize < blocksize ||
1358 dirblocksize > XFS_MAX_BLOCKSIZE) {
1359 fprintf(stderr,
9440d84d 1360 _("illegal directory block size %d\n"),
2bd0ea18
NS
1361 dirblocksize);
1362 usage();
1363 }
1364 } else {
1365 if (blocksize < (1 << XFS_MIN_REC_DIRSIZE))
1366 dirblocklog = XFS_MIN_REC_DIRSIZE;
1367 else
1368 dirblocklog = blocklog;
1369 dirblocksize = 1 << dirblocklog;
1370 }
1371 break;
1372 }
3fbc9137
NS
1373
1374 if (daflag && dasize) {
1375 fprintf(stderr,
9440d84d 1376 _("both -d agcount= and agsize= specified, use one or the other\n"));
3fbc9137
NS
1377 usage();
1378 }
1379
2bd0ea18
NS
1380 if (xi.disfile && (!dsize || !xi.dname)) {
1381 fprintf(stderr,
9440d84d 1382 _("if -d file then -d name and -d size are required\n"));
2bd0ea18
NS
1383 usage();
1384 }
1385 if (dsize) {
1386 __uint64_t dbytes;
1387
9440d84d 1388 dbytes = cvtnum(blocksize, sectorsize, dsize);
2bd0ea18
NS
1389 if (dbytes % XFS_MIN_BLOCKSIZE) {
1390 fprintf(stderr,
9440d84d 1391 _("illegal data length %lld, not a multiple of %d\n"),
5b64e00a 1392 (long long)dbytes, XFS_MIN_BLOCKSIZE);
2bd0ea18
NS
1393 usage();
1394 }
1395 dblocks = (xfs_drfsbno_t)(dbytes >> blocklog);
1396 if (dbytes % blocksize)
9440d84d
NS
1397 fprintf(stderr, _("warning: "
1398 "data length %lld not a multiple of %d, truncated to %lld\n"),
5b64e00a
NS
1399 (long long)dbytes, blocksize,
1400 (long long)(dblocks << blocklog));
2bd0ea18
NS
1401 }
1402 if (ipflag) {
1403 inodelog = blocklog - libxfs_highbit32(inopblock);
1404 isize = 1 << inodelog;
1405 } else if (!ilflag && !isflag) {
1406 inodelog = XFS_DINODE_DFL_LOG;
1407 isize = 1 << inodelog;
1408 }
1409#ifdef HAVE_VOLUME_MANAGER
1410 if (xi.lisfile && (!logsize || !xi.logname)) {
1411 fprintf(stderr,
9440d84d 1412 _("if -l file then -l name and -l size are required\n"));
2bd0ea18
NS
1413 usage();
1414 }
1415#endif
1416 if (logsize) {
1417 __uint64_t logbytes;
1418
9440d84d 1419 logbytes = cvtnum(blocksize, sectorsize, logsize);
2bd0ea18
NS
1420 if (logbytes % XFS_MIN_BLOCKSIZE) {
1421 fprintf(stderr,
9440d84d 1422 _("illegal log length %lld, not a multiple of %d\n"),
5b64e00a 1423 (long long)logbytes, XFS_MIN_BLOCKSIZE);
2bd0ea18
NS
1424 usage();
1425 }
1426 logblocks = (xfs_drfsbno_t)(logbytes >> blocklog);
1427 if (logbytes % blocksize)
1428 fprintf(stderr,
9440d84d 1429 _("warning: log length %lld not a multiple of %d, truncated to %lld\n"),
5b64e00a
NS
1430 (long long)logbytes, blocksize,
1431 (long long)(logblocks << blocklog));
2bd0ea18
NS
1432 }
1433#ifdef HAVE_VOLUME_MANAGER
1434 if (xi.risfile && (!rtsize || !xi.rtname)) {
1435 fprintf(stderr,
9440d84d 1436 _("if -r file then -r name and -r size are required\n"));
2bd0ea18
NS
1437 usage();
1438 }
1439#endif
1440 if (rtsize) {
1441 __uint64_t rtbytes;
1442
9440d84d 1443 rtbytes = cvtnum(blocksize, sectorsize, rtsize);
2bd0ea18
NS
1444 if (rtbytes % XFS_MIN_BLOCKSIZE) {
1445 fprintf(stderr,
9440d84d 1446 _("illegal rt length %lld, not a multiple of %d\n"),
5b64e00a 1447 (long long)rtbytes, XFS_MIN_BLOCKSIZE);
2bd0ea18
NS
1448 usage();
1449 }
1450 rtblocks = (xfs_drfsbno_t)(rtbytes >> blocklog);
1451 if (rtbytes % blocksize)
1452 fprintf(stderr,
9440d84d 1453 _("warning: rt length %lld not a multiple of %d, truncated to %lld\n"),
5b64e00a
NS
1454 (long long)rtbytes, blocksize,
1455 (long long)(rtblocks << blocklog));
2bd0ea18
NS
1456 }
1457 /*
1458 * If specified, check rt extent size against its constraints.
1459 */
1460 if (rtextsize) {
1461 __uint64_t rtextbytes;
1462
9440d84d 1463 rtextbytes = cvtnum(blocksize, sectorsize, rtextsize);
2bd0ea18
NS
1464 if (rtextbytes % blocksize) {
1465 fprintf(stderr,
9440d84d 1466 _("illegal rt extent size %lld, not a multiple of %d\n"),
5b64e00a 1467 (long long)rtextbytes, blocksize);
2bd0ea18
NS
1468 usage();
1469 }
1470 if (rtextbytes > XFS_MAX_RTEXTSIZE) {
1471 fprintf(stderr,
9440d84d 1472 _("rt extent size %s too large, maximum %d\n"),
2bd0ea18
NS
1473 rtextsize, XFS_MAX_RTEXTSIZE);
1474 usage();
1475 }
1476 if (rtextbytes < XFS_MIN_RTEXTSIZE) {
1477 fprintf(stderr,
9440d84d 1478 _("rt extent size %s too small, minimum %d\n"),
2bd0ea18
NS
1479 rtextsize, XFS_MIN_RTEXTSIZE);
1480 usage();
1481 }
1482 rtextblocks = (xfs_extlen_t)(rtextbytes >> blocklog);
1483 } else {
1484 /*
1485 * If realtime extsize has not been specified by the user,
1486 * and the underlying volume is striped, then set rtextblocks
1487 * to the stripe width.
1488 */
9440d84d
NS
1489 int dummy1, rswidth;
1490 __uint64_t rtextbytes;
1491
2bd0ea18 1492 dummy1 = rswidth = 0;
1cba5ede 1493
7dc01804 1494 if (!norsflag && !xi.risfile && !(!rtsize && xi.disfile))
c22b5fdf
NS
1495 get_subvol_stripe_wrapper(dfile, SVTYPE_RT, &dummy1,
1496 &rswidth, &dummy1);
2bd0ea18
NS
1497
1498 /* check that rswidth is a multiple of fs blocksize */
63a63844 1499 if (!norsflag && rswidth && !(BBTOB(rswidth) % blocksize)) {
2bd0ea18
NS
1500 rswidth = DTOBT(rswidth);
1501 rtextbytes = rswidth << blocklog;
1502 if (XFS_MIN_RTEXTSIZE <= rtextbytes &&
1cba5ede
NS
1503 (rtextbytes <= XFS_MAX_RTEXTSIZE)) {
1504 rtextblocks = rswidth;
2bd0ea18
NS
1505 } else {
1506 rtextblocks = XFS_DFL_RTEXTSIZE >> blocklog;
1507 }
1508 } else
1509 rtextblocks = XFS_DFL_RTEXTSIZE >> blocklog;
1510 }
1511
1512 /*
1513 * Check some argument sizes against mins, maxes.
1514 */
1515 if (isize > blocksize / XFS_MIN_INODE_PERBLOCK ||
1516 isize < XFS_DINODE_MIN_SIZE ||
1517 isize > XFS_DINODE_MAX_SIZE) {
1518 int maxsz;
1519
9440d84d 1520 fprintf(stderr, _("illegal inode size %d\n"), isize);
2bd0ea18
NS
1521 maxsz = MIN(blocksize / XFS_MIN_INODE_PERBLOCK,
1522 XFS_DINODE_MAX_SIZE);
1523 if (XFS_DINODE_MIN_SIZE == maxsz)
1524 fprintf(stderr,
9440d84d 1525 _("allowable inode size with %d byte blocks is %d\n"),
2bd0ea18
NS
1526 blocksize, XFS_DINODE_MIN_SIZE);
1527 else
1528 fprintf(stderr,
9440d84d 1529 _("allowable inode size with %d byte blocks is between %d and %d\n"),
2bd0ea18
NS
1530 blocksize, XFS_DINODE_MIN_SIZE, maxsz);
1531 usage();
1532 }
1533
b2a8226a 1534 /* if lsu or lsunit was specified, automatically use v2 logs */
9d77aadd 1535 if ((lsu || lsunit) && logversion == 1) {
9440d84d
NS
1536 fprintf(stderr,
1537 _("log stripe unit specified, using v2 logs\n"));
b2a8226a
ES
1538 logversion = 2;
1539 }
1540
9440d84d
NS
1541 calc_stripe_factors(dsu, dsw, sectorsize, lsu, lsectorsize,
1542 &dsunit, &dswidth, &lsunit);
2bd0ea18
NS
1543
1544 /*
1545 * Initialize. This will open the log and rt devices as well.
1546 */
1547 if (!libxfs_init(&xi))
1548 usage();
1549 if (!xi.ddev) {
9440d84d 1550 fprintf(stderr, _("no device name given in argument list\n"));
2bd0ea18
NS
1551 usage();
1552 }
1553
b7abc846
ES
1554 /*
1555 * Ok, Linux only has a 1024-byte resolution on device _size_,
1556 * and the sizes below are in basic 512-byte blocks,
1557 * so if we have (size % 2), on any partition, we can't get
1558 * to the last 512 bytes. Just chop it down by a block.
1559 */
1560
1561 xi.dsize -= (xi.dsize % 2);
1562 xi.rtsize -= (xi.rtsize % 2);
1563 xi.logBBsize -= (xi.logBBsize % 2);
1564
f937adac
NS
1565 if (!force_overwrite) {
1566 if (check_overwrite(dfile) ||
1567 check_overwrite(logfile) ||
1568 check_overwrite(xi.rtname)) {
9440d84d
NS
1569 fprintf(stderr,
1570 _("%s: Use the -f option to force overwrite.\n"),
2bd0ea18
NS
1571 progname);
1572 exit(1);
1573 }
1574 }
1575
2bd0ea18
NS
1576 if (!liflag && !ldflag)
1577 loginternal = xi.logdev == 0;
1578 if (xi.logname)
1579 logfile = xi.logname;
1580 else if (loginternal)
9440d84d 1581 logfile = _("internal log");
2bd0ea18 1582 else if (xi.volname && xi.logdev)
9440d84d 1583 logfile = _("volume log");
2bd0ea18 1584 else if (!ldflag) {
9440d84d 1585 fprintf(stderr, _("no log subvolume or internal log\n"));
2bd0ea18
NS
1586 usage();
1587 }
1588 if (xi.rtname)
1589 rtfile = xi.rtname;
1590 else
1591 if (xi.volname && xi.rtdev)
9440d84d 1592 rtfile = _("volume rt");
2bd0ea18 1593 else if (!xi.rtdev)
9440d84d 1594 rtfile = _("none");
2bd0ea18
NS
1595 if (dsize && xi.dsize > 0 && dblocks > DTOBT(xi.dsize)) {
1596 fprintf(stderr,
9440d84d
NS
1597 _("size %s specified for data subvolume is too large, "
1598 "maximum is %lld blocks\n"),
5b64e00a 1599 dsize, (long long)DTOBT(xi.dsize));
2bd0ea18
NS
1600 usage();
1601 } else if (!dsize && xi.dsize > 0)
1602 dblocks = DTOBT(xi.dsize);
1603 else if (!dsize) {
9440d84d 1604 fprintf(stderr, _("can't get size of data subvolume\n"));
2bd0ea18
NS
1605 usage();
1606 }
1607 if (dblocks < XFS_MIN_DATA_BLOCKS) {
1608 fprintf(stderr,
9440d84d 1609 _("size %lld of data subvolume is too small, minimum %d blocks\n"),
5b64e00a 1610 (long long)dblocks, XFS_MIN_DATA_BLOCKS);
2bd0ea18
NS
1611 usage();
1612 }
74668075 1613
9440d84d
NS
1614 if (loginternal && xi.logdev) {
1615 fprintf(stderr,
1616 _("can't have both external and internal logs\n"));
1617 usage();
1618 } else if (loginternal && sectorsize != lsectorsize) {
1619 fprintf(stderr,
1620 _("data and log sector sizes must be equal for internal logs\n"));
2bd0ea18
NS
1621 usage();
1622 }
74668075
NS
1623
1624 if (xi.dbsize > sectorsize) {
1625 fprintf(stderr, _(
1626"Warning: the data subvolume sector size %u is less than the sector size \n\
1627reported by the device (%u).\n"),
1628 sectorsize, xi.dbsize);
1629 }
1630 if (!loginternal && xi.lbsize > lsectorsize) {
1631 fprintf(stderr, _(
1632"Warning: the log subvolume sector size %u is less than the sector size\n\
1633reported by the device (%u).\n"),
1634 lsectorsize, xi.lbsize);
1635 }
1636 if (rtsize && xi.rtsize > 0 && xi.rtbsize > sectorsize) {
1637 fprintf(stderr, _(
1638"Warning: the realtime subvolume sector size %u is less than the sector size\n\
1639reported by the device (%u).\n"),
1640 sectorsize, xi.rtbsize);
1641 }
1642
cfd4ac07
NS
1643 max_tr_res = max_trans_res(dirversion,
1644 sectorlog, blocklog, inodelog, dirblocklog);
1645 ASSERT(max_tr_res);
1646 min_logblocks = max_tr_res * XFS_MIN_LOG_FACTOR;
1647 min_logblocks = MAX(XFS_MIN_LOG_BLOCKS, min_logblocks);
3cc4d0db
NS
1648 if (!logsize && dblocks >= (1024*1024*1024) >> blocklog)
1649 min_logblocks = MAX(min_logblocks, (10*1024*1024)>>blocklog);
2bd0ea18
NS
1650 if (logsize && xi.logBBsize > 0 && logblocks > DTOBT(xi.logBBsize)) {
1651 fprintf(stderr,
9440d84d 1652_("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
5b64e00a 1653 logsize, (long long)DTOBT(xi.logBBsize));
2bd0ea18 1654 usage();
cfd4ac07 1655 } else if (!logsize && xi.logBBsize > 0) {
2bd0ea18 1656 logblocks = DTOBT(xi.logBBsize);
cfd4ac07 1657 } else if (logsize && !xi.logdev && !loginternal) {
2bd0ea18 1658 fprintf(stderr,
9440d84d 1659 _("size specified for non-existent log subvolume\n"));
2bd0ea18
NS
1660 usage();
1661 } else if (loginternal && logsize && logblocks >= dblocks) {
9440d84d 1662 fprintf(stderr, _("size %lld too large for internal log\n"),
5b64e00a 1663 (long long)logblocks);
2bd0ea18 1664 usage();
cfd4ac07 1665 } else if (!loginternal && !xi.logdev) {
2bd0ea18 1666 logblocks = 0;
cfd4ac07 1667 } else if (loginternal && !logsize) {
3fbc9137
NS
1668 /*
1669 * logblocks grows from min_logblocks to XFS_MAX_LOG_BLOCKS
3cc4d0db 1670 * at 128GB
3fbc9137 1671 *
3cc4d0db 1672 * 2048 = 128GB / MAX_LOG_BYTES
3fbc9137 1673 */
3cc4d0db 1674 logblocks = (dblocks << blocklog) / 2048;
3fbc9137
NS
1675 logblocks = logblocks >> blocklog;
1676 logblocks = MAX(min_logblocks, logblocks);
1cba5ede 1677 logblocks = MAX(logblocks,
cfd4ac07
NS
1678 MAX(XFS_DFL_LOG_SIZE,
1679 max_tr_res * XFS_DFL_LOG_FACTOR));
1cba5ede 1680 logblocks = MIN(logblocks, XFS_MAX_LOG_BLOCKS);
3fbc9137
NS
1681 if ((logblocks << blocklog) > XFS_MAX_LOG_BYTES) {
1682 logblocks = XFS_MAX_LOG_BYTES >> blocklog;
1683 }
2bd0ea18 1684 }
cfd4ac07
NS
1685 validate_log_size(logblocks, blocklog, min_logblocks);
1686
2bd0ea18
NS
1687 if (rtsize && xi.rtsize > 0 && rtblocks > DTOBT(xi.rtsize)) {
1688 fprintf(stderr,
9440d84d
NS
1689 _("size %s specified for rt subvolume is too large, "
1690 "maximum is %lld blocks\n"),
5b64e00a 1691 rtsize, (long long)DTOBT(xi.rtsize));
2bd0ea18
NS
1692 usage();
1693 } else if (!rtsize && xi.rtsize > 0)
1694 rtblocks = DTOBT(xi.rtsize);
1695 else if (rtsize && !xi.rtdev) {
1696 fprintf(stderr,
9440d84d 1697 _("size specified for non-existent rt subvolume\n"));
2bd0ea18
NS
1698 usage();
1699 }
1700 if (xi.rtdev) {
1701 rtextents = rtblocks / rtextblocks;
1702 nbmblocks = (xfs_extlen_t)howmany(rtextents, NBBY * blocksize);
1703 } else {
1704 rtextents = rtblocks = 0;
1705 nbmblocks = 0;
1706 }
3fbc9137 1707
1f1b8be7 1708 if (dasize) { /* User-specified AG size */
3fbc9137 1709 /*
1f1b8be7 1710 * Check specified agsize is a multiple of blocksize.
3fbc9137
NS
1711 */
1712 if (agsize % blocksize) {
1713 fprintf(stderr,
9440d84d 1714 _("agsize (%lld) not a multiple of fs blk size (%d)\n"),
3fbc9137
NS
1715 (long long)agsize, blocksize);
1716 usage();
1717 }
3fbc9137 1718 agsize /= blocksize;
3fbc9137 1719 agcount = dblocks / agsize + (dblocks % agsize != 0);
2bd0ea18 1720
1f1b8be7
NS
1721 } else if (daflag) /* User-specified AG size */
1722 agsize = dblocks / agcount + (dblocks % agcount != 0);
1723 else
1724 calc_default_ag_geometry(blocklog, dblocks, &agsize, &agcount);
a6cae4ff
NS
1725
1726 /*
28eb0070
ES
1727 * If the last AG is too small, reduce the filesystem size
1728 * and drop the blocks.
a6cae4ff 1729 */
28eb0070
ES
1730 if ( dblocks % agsize != 0 &&
1731 (dblocks % agsize < XFS_AG_MIN_BLOCKS(blocklog))) {
1732 dblocks = (xfs_drfsbno_t)((agcount - 1) * agsize);
a212110f 1733 agcount--;
28eb0070 1734 ASSERT(agcount != 0);
a6cae4ff
NS
1735 }
1736
1f1b8be7 1737 validate_ag_geometry(blocklog, dblocks, agsize, agcount);
2bd0ea18 1738
63a63844 1739 if (!nodsflag && dsunit) {
2bd0ea18 1740 if (xlv_dsunit && xlv_dsunit != dsunit) {
9440d84d
NS
1741 fprintf(stderr,
1742 _("%s: Specified data stripe unit %d is not "
1743 "the same as the volume stripe unit %d\n"),
2bd0ea18 1744 progname, dsunit, xlv_dsunit);
2bd0ea18
NS
1745 }
1746 if (xlv_dswidth && xlv_dswidth != dswidth) {
9440d84d
NS
1747 fprintf(stderr,
1748 _("%s: Specified data stripe width %d is not "
1749 "the same as the volume stripe width %d\n"),
2bd0ea18 1750 progname, dswidth, xlv_dswidth);
2bd0ea18
NS
1751 }
1752 } else {
1753 dsunit = xlv_dsunit;
1754 dswidth = xlv_dswidth;
1755 nodsflag = 1;
1756 }
1757
1758 /*
1759 * If dsunit is a multiple of fs blocksize, then check that is a
1760 * multiple of the agsize too
1761 */
1762 if (dsunit && !(BBTOB(dsunit) % blocksize) &&
1763 dswidth && !(BBTOB(dswidth) % blocksize)) {
1764
1765 /* convert from 512 byte blocks to fs blocksize */
1766 dsunit = DTOBT(dsunit);
1767 dswidth = DTOBT(dswidth);
1768
1769 /*
1770 * agsize is not a multiple of dsunit
1771 */
1772 if ((agsize % dsunit) != 0) {
1cba5ede
NS
1773 /*
1774 * Round up to stripe unit boundary. Also make sure
2bd0ea18
NS
1775 * that agsize is still larger than
1776 * XFS_AG_MIN_BLOCKS(blocklog)
1777 */
1cba5ede 1778 tmp_agsize = ((agsize + (dsunit - 1))/ dsunit) * dsunit;
3fbc9137
NS
1779 /*
1780 * Round down to stripe unit boundary if rounding up
1781 * created an AG size that is larger than the AG max.
1782 */
1783 if (tmp_agsize > XFS_AG_MAX_BLOCKS(blocklog))
1784 tmp_agsize = ((agsize) / dsunit) * dsunit;
5b5df80a 1785 if ((tmp_agsize >= XFS_AG_MIN_BLOCKS(blocklog)) &&
2bd0ea18
NS
1786 (tmp_agsize <= XFS_AG_MAX_BLOCKS(blocklog)) &&
1787 !daflag) {
1788 agsize = tmp_agsize;
1789 agcount = dblocks/agsize +
1790 (dblocks % agsize != 0);
3fbc9137
NS
1791 if (dasize || daflag)
1792 fprintf(stderr,
9440d84d 1793 _("agsize rounded to %lld, swidth = %d\n"),
3fbc9137 1794 (long long)agsize, dswidth);
1cba5ede 1795 } else {
3fbc9137 1796 if (nodsflag) {
2bd0ea18 1797 dsunit = dswidth = 0;
3fbc9137 1798 } else {
2bd0ea18 1799 fprintf(stderr,
9440d84d 1800_("Allocation group size (%lld) is not a multiple of the stripe unit (%d)\n"),
5b64e00a 1801 (long long)agsize, dsunit);
2bd0ea18
NS
1802 exit(1);
1803 }
1cba5ede 1804 }
2bd0ea18 1805 }
5b5df80a 1806 if (dswidth && ((agsize % dswidth) == 0) && (agcount > 1)) {
a212110f 1807 /* This is a non-optimal configuration because all AGs
0640ee14 1808 * start on the same disk in the stripe. Changing
a212110f 1809 * the AG size by one sunit will guarantee that this
0640ee14 1810 * does not happen.
a212110f
ES
1811 */
1812 tmp_agsize = agsize - dsunit;
0640ee14 1813 if (tmp_agsize < XFS_AG_MIN_BLOCKS(blocklog)) {
a212110f 1814 tmp_agsize = agsize + dsunit;
0640ee14
ES
1815 if (dblocks < agsize) {
1816 /* oh well, nothing to do */
1817 tmp_agsize = agsize;
1818 }
1819 }
a212110f 1820 if (daflag || dasize) {
9440d84d 1821 fprintf(stderr, _(
3c925401
NS
1822"Warning: AG size is a multiple of stripe width. This can cause performance\n\
1823problems by aligning all AGs on the same disk. To avoid this, run mkfs with\n\
9440d84d 1824an AG size that is one stripe unit smaller, for example %llu.\n"),
3c925401 1825 (unsigned long long)tmp_agsize);
a212110f
ES
1826 } else {
1827 agsize = tmp_agsize;
1828 agcount = dblocks/agsize + (dblocks % agsize != 0);
02e85e7f
GO
1829 /*
1830 * If the last AG is too small, reduce the
1831 * filesystem size and drop the blocks.
1832 */
1833 if ( dblocks % agsize != 0 &&
1834 (dblocks % agsize <
1835 XFS_AG_MIN_BLOCKS(blocklog))) {
1836 dblocks = (xfs_drfsbno_t)((agcount - 1) * agsize);
1837 agcount--;
1838 ASSERT(agcount != 0);
1839 }
a212110f
ES
1840 }
1841 }
2bd0ea18
NS
1842 } else {
1843 if (nodsflag)
1844 dsunit = dswidth = 0;
1845 else {
9440d84d
NS
1846 fprintf(stderr,
1847 _("%s: Stripe unit(%d) or stripe width(%d) is "
1848 "not a multiple of the block size(%d)\n"),
9e017777
ES
1849 progname, BBTOB(dsunit), BBTOB(dswidth),
1850 blocksize);
2bd0ea18
NS
1851 exit(1);
1852 }
1853 }
1854
73bf5988
SL
1855 /*
1856 * check that log sunit is modulo fsblksize or default it to dsunit.
1857 */
1858
1859 if (lsunit) {
9e017777 1860 if ((BBTOB(lsunit) % blocksize != 0)) {
73bf5988 1861 fprintf(stderr,
9440d84d 1862 _("log stripe unit (%d) must be a multiple of the block size (%d)\n"),
9e017777 1863 BBTOB(lsunit), blocksize);
73bf5988
SL
1864 exit(1);
1865 }
9e017777
ES
1866 /* convert from 512 byte blocks to fs blocks */
1867 lsunit = DTOBT(lsunit);
4d762552 1868 } else if (logversion == 2 && loginternal && dsunit) {
9e017777
ES
1869 /* lsunit and dsunit now in fs blocks */
1870 lsunit = dsunit;
73bf5988
SL
1871 }
1872
4d762552 1873 if (logversion == 2 && (lsunit * blocksize) > 256 * 1024) {
73bf5988 1874 fprintf(stderr,
b50e4c6e 1875 _("log stripe unit (%d bytes) is too large (maximum is 256KiB)\n"),
9e017777 1876 (lsunit * blocksize));
b51d0582 1877 lsunit = (32 * 1024) >> blocklog;
b50e4c6e 1878 fprintf(stderr, _("log stripe unit adjusted to 32KiB\n"));
73bf5988
SL
1879 }
1880
2bd0ea18
NS
1881 protostring = setup_proto(protofile);
1882 bsize = 1 << (blocklog - BBSHIFT);
2bd0ea18
NS
1883 mp = &mbuf;
1884 sbp = &mp->m_sb;
1885 bzero(mp, sizeof(xfs_mount_t));
1886 sbp->sb_blocklog = (__uint8_t)blocklog;
9440d84d 1887 sbp->sb_sectlog = (__uint8_t)sectorlog;
2bd0ea18
NS
1888 sbp->sb_agblklog = (__uint8_t)libxfs_log2_roundup((unsigned int)agsize);
1889 mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT;
9440d84d
NS
1890 mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT;
1891
2bd0ea18 1892 if (loginternal) {
a212110f
ES
1893 /*
1894 * Readjust the log size to fit within an AG if it was sized
1895 * automaticly.
1896 */
1897 if (!logsize) {
1898 logblocks = MIN(logblocks,
1899 agsize - XFS_PREALLOC_BLOCKS(mp));
1900 }
2bd0ea18
NS
1901 if (logblocks > agsize - XFS_PREALLOC_BLOCKS(mp)) {
1902 fprintf(stderr,
9440d84d 1903 _("internal log size %lld too large, must fit in allocation group\n"),
5b64e00a 1904 (long long)logblocks);
2bd0ea18
NS
1905 usage();
1906 }
1907 if (laflag) {
1908 if (logagno >= agcount) {
1909 fprintf(stderr,
9440d84d 1910 _("log ag number %d too large, must be less than %lld\n"),
5b64e00a 1911 logagno, (long long)agcount);
2bd0ea18
NS
1912 usage();
1913 }
1914 } else
1915 logagno = (xfs_agnumber_t)(agcount / 2);
1916
1917 logstart = XFS_AGB_TO_FSB(mp, logagno, XFS_PREALLOC_BLOCKS(mp));
1918 /*
1919 * Align the logstart at stripe unit boundary.
1920 */
575fec4c 1921 if (lsunit) {
72e527e7
NS
1922 logstart = fixup_internal_log_stripe(mp,
1923 lsflag, logstart, agsize, lsunit,
1924 &logblocks, blocklog, &lalign);
575fec4c 1925 } else if (dsunit) {
72e527e7
NS
1926 logstart = fixup_internal_log_stripe(mp,
1927 lsflag, logstart, agsize, dsunit,
1928 &logblocks, blocklog, &lalign);
2bd0ea18 1929 }
72e527e7 1930 } else {
2bd0ea18 1931 logstart = 0;
72e527e7
NS
1932 if (lsunit)
1933 fixup_log_stripe_unit(lsflag, lsunit,
1934 &logblocks, blocklog);
1935 }
1936 validate_log_size(logblocks, blocklog, min_logblocks);
3fbc9137 1937
9440d84d
NS
1938 if (!qflag || Nflag) {
1939 printf(_(
1940 "meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n"
e78b9efb 1941 " =%-22s sectsz=%-5u attr=%u\n"
9440d84d
NS
1942 "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n"
1943 " =%-22s sunit=%-6u swidth=%u blks, unwritten=%u\n"
1944 "naming =version %-14u bsize=%-6u\n"
1945 "log =%-22s bsize=%-6d blocks=%lld, version=%d\n"
1946 " =%-22s sectsz=%-5u sunit=%d blks\n"
1947 "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n"),
1948 dfile, isize, (long long)agcount, (long long)agsize,
e78b9efb 1949 "", sectorsize, attrversion,
0a80baf7
ES
1950 "", blocksize, (long long)dblocks,
1951 imflag ? imaxpct : XFS_DFL_IMAXIMUM_PCT,
9440d84d
NS
1952 "", dsunit, dswidth, extent_flagging,
1953 dirversion, dirversion == 1 ? blocksize : dirblocksize,
1954 logfile, 1 << blocklog, (long long)logblocks,
1955 logversion, "", lsectorsize, lsunit,
1956 rtfile, rtextblocks << blocklog,
1957 (long long)rtblocks, (long long)rtextents);
1958 if (Nflag)
1959 exit(0);
1960 }
1961
979f7189
NS
1962 if (label)
1963 strncpy(sbp->sb_fname, label, sizeof(sbp->sb_fname));
2bd0ea18
NS
1964 sbp->sb_magicnum = XFS_SB_MAGIC;
1965 sbp->sb_blocksize = blocksize;
1966 sbp->sb_dblocks = dblocks;
1967 sbp->sb_rblocks = rtblocks;
1968 sbp->sb_rextents = rtextents;
1969 uuid_generate(uuid);
1970 uuid_copy(sbp->sb_uuid, uuid);
1971 sbp->sb_logstart = logstart;
1972 sbp->sb_rootino = sbp->sb_rbmino = sbp->sb_rsumino = NULLFSINO;
1973 sbp->sb_rextsize = rtextblocks;
1974 sbp->sb_agblocks = (xfs_agblock_t)agsize;
1975 sbp->sb_agcount = (xfs_agnumber_t)agcount;
1976 sbp->sb_rbmblocks = nbmblocks;
1977 sbp->sb_logblocks = (xfs_extlen_t)logblocks;
9440d84d 1978 sbp->sb_sectsize = (__uint16_t)sectorsize;
2bd0ea18
NS
1979 sbp->sb_inodesize = (__uint16_t)isize;
1980 sbp->sb_inopblock = (__uint16_t)(blocksize / isize);
9440d84d 1981 sbp->sb_sectlog = (__uint8_t)sectorlog;
2bd0ea18
NS
1982 sbp->sb_inodelog = (__uint8_t)inodelog;
1983 sbp->sb_inopblog = (__uint8_t)(blocklog - inodelog);
1984 sbp->sb_rextslog =
1985 (__uint8_t)(rtextents ?
1986 libxfs_highbit32((unsigned int)rtextents) : 0);
1987 sbp->sb_inprogress = 1; /* mkfs is in progress */
1988 sbp->sb_imax_pct = imflag ? imaxpct : XFS_DFL_IMAXIMUM_PCT;
1989 sbp->sb_icount = 0;
1990 sbp->sb_ifree = 0;
1991 sbp->sb_fdblocks = dblocks - agcount * XFS_PREALLOC_BLOCKS(mp) -
1992 (loginternal ? logblocks : 0);
1993 sbp->sb_frextents = 0; /* will do a free later */
b36eef04 1994 sbp->sb_uquotino = sbp->sb_gquotino = 0;
2bd0ea18
NS
1995 sbp->sb_qflags = 0;
1996 sbp->sb_unit = dsunit;
1997 sbp->sb_width = dswidth;
1998 if (dirversion == 2)
1999 sbp->sb_dirblklog = dirblocklog - blocklog;
3168bd4e
NS
2000 if (logversion == 2) { /* This is stored in bytes */
2001 lsunit = (lsunit == 0) ? 1 : XFS_FSB_TO_B(mp, lsunit);
2002 sbp->sb_logsunit = lsunit;
2003 } else
73bf5988 2004 sbp->sb_logsunit = 0;
2bd0ea18
NS
2005 if (iaflag) {
2006 sbp->sb_inoalignmt = XFS_INODE_BIG_CLUSTER_SIZE >> blocklog;
2007 iaflag = sbp->sb_inoalignmt != 0;
2008 } else
2009 sbp->sb_inoalignmt = 0;
9440d84d
NS
2010 if (lsectorsize != BBSIZE || sectorsize != BBSIZE) {
2011 sbp->sb_logsectlog = (__uint8_t)lsectorlog;
2012 sbp->sb_logsectsize = (__uint16_t)lsectorsize;
2013 } else {
2014 sbp->sb_logsectlog = 0;
2015 sbp->sb_logsectsize = 0;
2016 }
6e3140c7
NS
2017 sbp->sb_features2 = XFS_SB_VERSION2_MKFS(0, attrversion == 2, 0);
2018 sbp->sb_versionnum = XFS_SB_VERSION_MKFS(
2019 iaflag, dsunit != 0, extent_flagging,
e78b9efb 2020 dirversion == 2, logversion == 2, attrversion == 1,
46eca962 2021 (sectorsize != BBSIZE || lsectorsize != BBSIZE),
6e3140c7 2022 sbp->sb_features2 != 0);
46eca962 2023
2f012bf9 2024 /*
46eca962
NS
2025 * Zero out the beginning of the device, to obliterate any old
2026 * filesystem signatures out there. This should take care of
2027 * swap (somewhere around the page size), jfs (32k),
9440d84d 2028 * ext[2,3] and reiserfs (64k) - and hopefully all else.
2f012bf9 2029 */
5c617c87
ES
2030 buf = libxfs_getbuf(xi.ddev, 0, BTOBB(WHACK_SIZE));
2031 bzero(XFS_BUF_PTR(buf), WHACK_SIZE);
9440d84d 2032 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2f012bf9
ES
2033
2034 /* OK, now write the superblock */
9440d84d
NS
2035 buf = libxfs_getbuf(xi.ddev, XFS_SB_DADDR, XFS_FSS_TO_BB(mp, 1));
2036 bzero(XFS_BUF_PTR(buf), sectorsize);
46eca962 2037 libxfs_xlate_sb(XFS_BUF_PTR(buf), sbp, -1, XFS_SB_ALL_BITS);
9440d84d 2038 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2bd0ea18 2039
2bd0ea18
NS
2040 /*
2041 * If the data area is a file, then grow it out to its final size
2042 * so that the reads for the end of the device in the mount code
2043 * will succeed.
2044 */
2045 if (xi.disfile && ftruncate64(xi.dfd, dblocks * blocksize) < 0) {
2c794e6e 2046 fprintf(stderr, _("%s: Growing the data section failed\n"),
2bd0ea18
NS
2047 progname);
2048 exit(1);
2049 }
2f012bf9
ES
2050
2051 /*
5c617c87 2052 * Zero out the end of the device, to obliterate any
9ea254da 2053 * old MD RAID (or other) metadata at the end of the device.
5c617c87 2054 * (MD sb is ~64k from the end, take out a wider swath to be sure)
2f012bf9 2055 */
9ea254da 2056 if (!xi.disfile) {
5c617c87
ES
2057 buf = libxfs_getbuf(xi.ddev, (xi.dsize - BTOBB(WHACK_SIZE)),
2058 BTOBB(WHACK_SIZE));
2059 bzero(XFS_BUF_PTR(buf), WHACK_SIZE);
9440d84d 2060 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
9ea254da 2061 }
2f012bf9 2062
2bd0ea18
NS
2063 /*
2064 * Zero the log if there is one.
2065 */
2066 if (loginternal)
2067 xi.logdev = xi.ddev;
2068 if (xi.logdev)
9440d84d
NS
2069 libxfs_log_clear(xi.logdev, XFS_FSB_TO_DADDR(mp, logstart),
2070 (xfs_extlen_t)XFS_FSB_TO_BB(mp, logblocks),
2071 &sbp->sb_uuid, logversion, lsunit, XLOG_FMT);
2bd0ea18
NS
2072
2073 mp = libxfs_mount(mp, sbp, xi.ddev, xi.logdev, xi.rtdev, 1);
02e85e7f 2074 if (mp == NULL) {
9440d84d
NS
2075 fprintf(stderr, _("%s: filesystem failed to initialize\n"),
2076 progname);
2bd0ea18
NS
2077 exit(1);
2078 }
2bd0ea18
NS
2079
2080 for (agno = 0; agno < agcount; agno++) {
2081 /*
2082 * Superblock.
2083 */
2084 buf = libxfs_getbuf(xi.ddev,
9440d84d
NS
2085 XFS_AG_DADDR(mp, agno, XFS_SB_DADDR),
2086 XFS_FSS_TO_BB(mp, 1));
2087 bzero(XFS_BUF_PTR(buf), sectorsize);
46eca962 2088 libxfs_xlate_sb(XFS_BUF_PTR(buf), sbp, -1, XFS_SB_ALL_BITS);
9440d84d 2089 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2bd0ea18
NS
2090
2091 /*
2092 * AG header block: freespace
2093 */
2094 buf = libxfs_getbuf(mp->m_dev,
9440d84d
NS
2095 XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
2096 XFS_FSS_TO_BB(mp, 1));
2bd0ea18 2097 agf = XFS_BUF_TO_AGF(buf);
9440d84d 2098 bzero(agf, sectorsize);
2bd0ea18
NS
2099 if (agno == agcount - 1)
2100 agsize = dblocks - (xfs_drfsbno_t)(agno * agsize);
2101 INT_SET(agf->agf_magicnum, ARCH_CONVERT, XFS_AGF_MAGIC);
2102 INT_SET(agf->agf_versionnum, ARCH_CONVERT, XFS_AGF_VERSION);
2103 INT_SET(agf->agf_seqno, ARCH_CONVERT, agno);
2104 INT_SET(agf->agf_length, ARCH_CONVERT, (xfs_agblock_t)agsize);
2105 INT_SET(agf->agf_roots[XFS_BTNUM_BNOi], ARCH_CONVERT,
2106 XFS_BNO_BLOCK(mp));
2107 INT_SET(agf->agf_roots[XFS_BTNUM_CNTi], ARCH_CONVERT,
2108 XFS_CNT_BLOCK(mp));
2109 INT_SET(agf->agf_levels[XFS_BTNUM_BNOi], ARCH_CONVERT, 1);
2110 INT_SET(agf->agf_levels[XFS_BTNUM_CNTi], ARCH_CONVERT, 1);
2111 INT_SET(agf->agf_flfirst, ARCH_CONVERT, 0);
9440d84d 2112 INT_SET(agf->agf_fllast, ARCH_CONVERT, XFS_AGFL_SIZE(mp) - 1);
2bd0ea18
NS
2113 INT_SET(agf->agf_flcount, ARCH_CONVERT, 0);
2114 nbmblocks = (xfs_extlen_t)(agsize - XFS_PREALLOC_BLOCKS(mp));
2115 INT_SET(agf->agf_freeblks, ARCH_CONVERT, nbmblocks);
2116 INT_SET(agf->agf_longest, ARCH_CONVERT, nbmblocks);
2117 if (loginternal && agno == logagno) {
2118 INT_MOD(agf->agf_freeblks, ARCH_CONVERT, -logblocks);
2119 INT_SET(agf->agf_longest, ARCH_CONVERT, agsize -
2120 XFS_FSB_TO_AGBNO(mp, logstart) - logblocks);
2121 }
2122 if (XFS_MIN_FREELIST(agf, mp) > worst_freelist)
2123 worst_freelist = XFS_MIN_FREELIST(agf, mp);
9440d84d 2124 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2bd0ea18
NS
2125
2126 /*
2127 * AG header block: inodes
2128 */
2129 buf = libxfs_getbuf(mp->m_dev,
9440d84d
NS
2130 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
2131 XFS_FSS_TO_BB(mp, 1));
2bd0ea18 2132 agi = XFS_BUF_TO_AGI(buf);
9440d84d 2133 bzero(agi, sectorsize);
2bd0ea18
NS
2134 INT_SET(agi->agi_magicnum, ARCH_CONVERT, XFS_AGI_MAGIC);
2135 INT_SET(agi->agi_versionnum, ARCH_CONVERT, XFS_AGI_VERSION);
2136 INT_SET(agi->agi_seqno, ARCH_CONVERT, agno);
2137 INT_SET(agi->agi_length, ARCH_CONVERT, (xfs_agblock_t)agsize);
2138 INT_SET(agi->agi_count, ARCH_CONVERT, 0);
2139 INT_SET(agi->agi_root, ARCH_CONVERT, XFS_IBT_BLOCK(mp));
2140 INT_SET(agi->agi_level, ARCH_CONVERT, 1);
2141 INT_SET(agi->agi_freecount, ARCH_CONVERT, 0);
2142 INT_SET(agi->agi_newino, ARCH_CONVERT, NULLAGINO);
2143 INT_SET(agi->agi_dirino, ARCH_CONVERT, NULLAGINO);
cfd4ac07
NS
2144 for (c = 0; c < XFS_AGI_UNLINKED_BUCKETS; c++)
2145 INT_SET(agi->agi_unlinked[c], ARCH_CONVERT, NULLAGINO);
9440d84d 2146 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2bd0ea18
NS
2147
2148 /*
2149 * BNO btree root block
2150 */
2151 buf = libxfs_getbuf(mp->m_dev,
2152 XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)),
2153 bsize);
2154 block = XFS_BUF_TO_SBLOCK(buf);
2155 bzero(block, blocksize);
2156 INT_SET(block->bb_magic, ARCH_CONVERT, XFS_ABTB_MAGIC);
2157 INT_SET(block->bb_level, ARCH_CONVERT, 0);
2158 INT_SET(block->bb_numrecs, ARCH_CONVERT, 1);
2159 INT_SET(block->bb_leftsib, ARCH_CONVERT, NULLAGBLOCK);
2160 INT_SET(block->bb_rightsib, ARCH_CONVERT, NULLAGBLOCK);
2161 arec = XFS_BTREE_REC_ADDR(blocksize, xfs_alloc, block, 1,
2162 XFS_BTREE_BLOCK_MAXRECS(blocksize, xfs_alloc, 1));
2163 INT_SET(arec->ar_startblock, ARCH_CONVERT,
2164 XFS_PREALLOC_BLOCKS(mp));
2165 if (loginternal && agno == logagno) {
2166 if (lalign) {
2167 /*
2168 * Have to insert two records
575fec4c 2169 * Insert pad record for stripe align of log
2bd0ea18
NS
2170 */
2171 INT_SET(arec->ar_blockcount, ARCH_CONVERT,
2172 (xfs_extlen_t)(XFS_FSB_TO_AGBNO(
2173 mp, logstart)
2174 - (INT_GET(arec->ar_startblock,
2175 ARCH_CONVERT))));
2176 nrec = arec + 1;
575fec4c 2177 /*
2178 * Insert record at start of internal log
2179 */
2bd0ea18
NS
2180 INT_SET(nrec->ar_startblock, ARCH_CONVERT,
2181 INT_GET(arec->ar_startblock,
2182 ARCH_CONVERT) +
2183 INT_GET(arec->ar_blockcount,
2184 ARCH_CONVERT));
2185 arec = nrec;
2186 INT_MOD(block->bb_numrecs, ARCH_CONVERT, 1);
2187 }
575fec4c 2188 /*
2189 * Change record start to after the internal log
2190 */
2bd0ea18
NS
2191 INT_MOD(arec->ar_startblock, ARCH_CONVERT, logblocks);
2192 }
2193 INT_SET(arec->ar_blockcount, ARCH_CONVERT,
2194 (xfs_extlen_t)(agsize -
2195 INT_GET(arec->ar_startblock, ARCH_CONVERT)));
9440d84d 2196 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2bd0ea18
NS
2197
2198 /*
2199 * CNT btree root block
2200 */
2201 buf = libxfs_getbuf(mp->m_dev,
2202 XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)),
2203 bsize);
2204 block = XFS_BUF_TO_SBLOCK(buf);
2205 bzero(block, blocksize);
2206 INT_SET(block->bb_magic, ARCH_CONVERT, XFS_ABTC_MAGIC);
2207 INT_SET(block->bb_level, ARCH_CONVERT, 0);
2208 INT_SET(block->bb_numrecs, ARCH_CONVERT, 1);
2209 INT_SET(block->bb_leftsib, ARCH_CONVERT, NULLAGBLOCK);
2210 INT_SET(block->bb_rightsib, ARCH_CONVERT, NULLAGBLOCK);
2211 arec = XFS_BTREE_REC_ADDR(blocksize, xfs_alloc, block, 1,
2212 XFS_BTREE_BLOCK_MAXRECS(blocksize, xfs_alloc, 1));
2213 INT_SET(arec->ar_startblock, ARCH_CONVERT,
2214 XFS_PREALLOC_BLOCKS(mp));
2215 if (loginternal && agno == logagno) {
2216 if (lalign) {
2217 INT_SET(arec->ar_blockcount, ARCH_CONVERT,
2218 (xfs_extlen_t)( XFS_FSB_TO_AGBNO(
2219 mp, logstart) - (INT_GET(
2220 arec->ar_startblock, ARCH_CONVERT)) )
2221 );
2222 nrec = arec + 1;
2223 INT_SET(nrec->ar_startblock, ARCH_CONVERT,
2224 INT_GET(arec->ar_startblock, ARCH_CONVERT) +
2225 INT_GET(arec->ar_blockcount, ARCH_CONVERT));
2226 arec = nrec;
2227 INT_MOD(block->bb_numrecs, ARCH_CONVERT, 1);
2228 }
2229 INT_MOD(arec->ar_startblock, ARCH_CONVERT, logblocks);
2230 }
2231 INT_SET(arec->ar_blockcount, ARCH_CONVERT, (xfs_extlen_t)
2232 (agsize - INT_GET(arec->ar_startblock, ARCH_CONVERT)));
9440d84d
NS
2233 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2234
2bd0ea18
NS
2235 /*
2236 * INO btree root block
2237 */
2238 buf = libxfs_getbuf(mp->m_dev,
2239 XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)),
2240 bsize);
2241 block = XFS_BUF_TO_SBLOCK(buf);
2242 bzero(block, blocksize);
2243 INT_SET(block->bb_magic, ARCH_CONVERT, XFS_IBT_MAGIC);
2244 INT_SET(block->bb_level, ARCH_CONVERT, 0);
2245 INT_SET(block->bb_numrecs, ARCH_CONVERT, 0);
2246 INT_SET(block->bb_leftsib, ARCH_CONVERT, NULLAGBLOCK);
2247 INT_SET(block->bb_rightsib, ARCH_CONVERT, NULLAGBLOCK);
9440d84d 2248 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2bd0ea18
NS
2249 }
2250
2251 /*
2252 * Touch last block, make fs the right size if it's a file.
2253 */
2254 buf = libxfs_getbuf(mp->m_dev,
2255 (xfs_daddr_t)XFS_FSB_TO_BB(mp, dblocks - 1LL), bsize);
2256 bzero(XFS_BUF_PTR(buf), blocksize);
9440d84d 2257 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2bd0ea18
NS
2258
2259 /*
2260 * Make sure we can write the last block in the realtime area.
2261 */
2262 if (mp->m_rtdev && rtblocks > 0) {
2263 buf = libxfs_getbuf(mp->m_rtdev,
2264 XFS_FSB_TO_BB(mp, rtblocks - 1LL), bsize);
2265 bzero(XFS_BUF_PTR(buf), blocksize);
9440d84d 2266 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2bd0ea18 2267 }
9440d84d 2268
2bd0ea18
NS
2269 /*
2270 * BNO, CNT free block list
2271 */
2272 for (agno = 0; agno < agcount; agno++) {
2273 xfs_alloc_arg_t args;
2274 xfs_trans_t *tp;
2275
2276 bzero(&args, sizeof(args));
2277 args.tp = tp = libxfs_trans_alloc(mp, 0);
2278 args.mp = mp;
2279 args.agno = agno;
2280 args.alignment = 1;
2bd0ea18 2281 args.pag = &mp->m_perag[agno];
cfd4ac07
NS
2282 if ((c = libxfs_trans_reserve(tp, worst_freelist, 0, 0, 0, 0)))
2283 res_failed(c);
2bd0ea18
NS
2284 libxfs_alloc_fix_freelist(&args, 0);
2285 libxfs_trans_commit(tp, 0, NULL);
2286 }
9440d84d 2287
2bd0ea18
NS
2288 /*
2289 * Allocate the root inode and anything else in the proto file.
2290 */
2291 mp->m_rootip = NULL;
9f064b7e 2292 parse_proto(mp, &fsx, &protostring);
2bd0ea18
NS
2293
2294 /*
9440d84d 2295 * Protect ourselves against possible stupidity
2bd0ea18
NS
2296 */
2297 if (XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino) != 0) {
9440d84d
NS
2298 fprintf(stderr,
2299 _("%s: root inode created in AG %u, not AG 0\n"),
2bd0ea18
NS
2300 progname, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino));
2301 exit(1);
2302 }
2303
2304 /*
9440d84d 2305 * Write out multiple secondary superblocks with rootinode field set
2bd0ea18
NS
2306 */
2307 if (mp->m_sb.sb_agcount > 1) {
2308 /*
2309 * the last superblock
2310 */
2311 buf = libxfs_readbuf(mp->m_dev,
2312 XFS_AGB_TO_DADDR(mp, mp->m_sb.sb_agcount-1,
2313 XFS_SB_DADDR),
9440d84d
NS
2314 XFS_FSS_TO_BB(mp, 1),
2315 LIBXFS_EXIT_ON_FAILURE);
2bd0ea18
NS
2316 INT_SET((XFS_BUF_TO_SBP(buf))->sb_rootino,
2317 ARCH_CONVERT, mp->m_sb.sb_rootino);
9440d84d 2318 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2bd0ea18
NS
2319 /*
2320 * and one in the middle for luck
2321 */
2322 if (mp->m_sb.sb_agcount > 2) {
2323 buf = libxfs_readbuf(mp->m_dev,
2324 XFS_AGB_TO_DADDR(mp, (mp->m_sb.sb_agcount-1)/2,
2325 XFS_SB_DADDR),
9440d84d
NS
2326 XFS_FSS_TO_BB(mp, 1),
2327 LIBXFS_EXIT_ON_FAILURE);
2bd0ea18
NS
2328 INT_SET((XFS_BUF_TO_SBP(buf))->sb_rootino,
2329 ARCH_CONVERT, mp->m_sb.sb_rootino);
9440d84d 2330 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2bd0ea18
NS
2331 }
2332 }
2333
2334 /*
2335 * Mark the filesystem ok.
2336 */
9440d84d 2337 buf = libxfs_getsb(mp, LIBXFS_EXIT_ON_FAILURE);
2bd0ea18 2338 (XFS_BUF_TO_SBP(buf))->sb_inprogress = 0;
9440d84d 2339 libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
2bd0ea18
NS
2340
2341 libxfs_umount(mp);
2342 if (xi.rtdev)
2343 libxfs_device_close(xi.rtdev);
2344 if (xi.logdev && xi.logdev != xi.ddev)
2345 libxfs_device_close(xi.logdev);
2346 libxfs_device_close(xi.ddev);
2347
2348 return 0;
2349}
2350
2351static void
2352conflict(
9440d84d
NS
2353 char opt,
2354 char *tab[],
2355 int oldidx,
2356 int newidx)
2bd0ea18 2357{
9440d84d 2358 fprintf(stderr, _("Cannot specify both -%c %s and -%c %s\n"),
2bd0ea18
NS
2359 opt, tab[oldidx], opt, tab[newidx]);
2360 usage();
2361}
2362
2363
2364static void
2365illegal(
9440d84d
NS
2366 char *value,
2367 char *opt)
2bd0ea18 2368{
9440d84d 2369 fprintf(stderr, _("Illegal value %s for -%s option\n"), value, opt);
2bd0ea18
NS
2370 usage();
2371}
2372
2373static int
2374ispow2(
2375 unsigned int i)
2376{
2377 return (i & (i - 1)) == 0;
2378}
2379
2380static void
2381reqval(
9440d84d
NS
2382 char opt,
2383 char *tab[],
2384 int idx)
2bd0ea18 2385{
9440d84d 2386 fprintf(stderr, _("-%c %s option requires a value\n"), opt, tab[idx]);
2bd0ea18
NS
2387 usage();
2388}
2389
2390static void
2391respec(
9440d84d
NS
2392 char opt,
2393 char *tab[],
2394 int idx)
2bd0ea18
NS
2395{
2396 fprintf(stderr, "-%c ", opt);
2397 if (tab)
2398 fprintf(stderr, "%s ", tab[idx]);
9440d84d 2399 fprintf(stderr, _("option respecified\n"));
2bd0ea18
NS
2400 usage();
2401}
2402
2403static void
2404unknown(
9440d84d
NS
2405 char opt,
2406 char *s)
2bd0ea18 2407{
9440d84d 2408 fprintf(stderr, _("unknown option -%c %s\n"), opt, s);
2bd0ea18
NS
2409 usage();
2410}
2411
9440d84d
NS
2412/*
2413 * isdigits -- returns 1 if string contains nothing but [0-9], 0 otherwise
2414 */
9e017777 2415int
9440d84d
NS
2416isdigits(
2417 char *str)
9e017777 2418{
9440d84d
NS
2419 int i;
2420 int n = strlen(str);
9e017777
ES
2421
2422 for (i = 0; i < n; i++) {
93d9f139 2423 if (!isdigit((int)str[i]))
9e017777
ES
2424 return 0;
2425 }
2426 return 1;
2427}
2428
2bd0ea18
NS
2429long long
2430cvtnum(
cb7ba2b0
CH
2431 unsigned int blocksize,
2432 unsigned int sectorsize,
2bd0ea18
NS
2433 char *s)
2434{
2435 long long i;
2436 char *sp;
2bd0ea18
NS
2437
2438 i = strtoll(s, &sp, 0);
2439 if (i == 0 && sp == s)
2440 return -1LL;
2441 if (*sp == '\0')
2442 return i;
2443
2444 if (*sp == 'b' && sp[1] == '\0') {
2445 if (blocksize)
2446 return i * blocksize;
9440d84d 2447 fprintf(stderr, _("blocksize not available yet.\n"));
2bd0ea18
NS
2448 usage();
2449 }
9440d84d
NS
2450 if (*sp == 's' && sp[1] == '\0') {
2451 if (sectorsize)
2452 return i * sectorsize;
2453 return i * BBSIZE;
2454 }
2bd0ea18
NS
2455 if (*sp == 'k' && sp[1] == '\0')
2456 return 1024LL * i;
2457 if (*sp == 'm' && sp[1] == '\0')
2458 return 1024LL * 1024LL * i;
2459 if (*sp == 'g' && sp[1] == '\0')
2460 return 1024LL * 1024LL * 1024LL * i;
638473d8
NS
2461 if (*sp == 't' && sp[1] == '\0')
2462 return 1024LL * 1024LL * 1024LL * 1024LL * i;
2463 if (*sp == 'p' && sp[1] == '\0')
2464 return 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * i;
062998e3
NS
2465 if (*sp == 'e' && sp[1] == '\0')
2466 return 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * i;
2bd0ea18
NS
2467 return -1LL;
2468}
2469
2470void
9440d84d 2471usage( void )
2bd0ea18 2472{
9440d84d 2473 fprintf(stderr, _("Usage: %s\n\
2bd0ea18
NS
2474/* blocksize */ [-b log=n|size=num]\n\
2475/* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\
9e017777 2476 (sunit=value,swidth=value|su=num,sw=num),\n\
1cba5ede 2477 sectlog=n|sectsize=num,unwritten=0|1]\n\
aceaedc4 2478/* inode size */ [-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2]\n\
1cba5ede
NS
2479/* log subvol */ [-l agnum=n,internal,size=num,logdev=xxx,version=n\n\
2480 sunit=value|su=num,sectlog=n|sectsize=num]\n\
979f7189 2481/* label */ [-L label (maximum 12 characters)]\n\
9440d84d 2482/* naming */ [-n log=n|size=num,version=n]\n\
2bd0ea18
NS
2483/* prototype file */ [-p fname]\n\
2484/* quiet */ [-q]\n\
2bd0ea18 2485/* realtime subvol */ [-r extsize=num,size=num,rtdev=xxx]\n\
9440d84d
NS
2486/* sectorsize */ [-s log=n|size=num]\n\
2487/* version */ [-V]\n\
2bd0ea18 2488 devicename\n\
3fbc9137 2489<devicename> is required unless -d name=xxx is given.\n\
638473d8
NS
2490<num> is xxx (bytes), xxxs (sectors), xxxb (fs blocks), xxxk (xxx KiB),\n\
2491 xxxm (xxx MiB), xxxg (xxx GiB), xxxt (xxx TiB) or xxxp (xxx PiB).\n\
2492<value> is xxx (512 byte blocks).\n"),
2bd0ea18
NS
2493 progname);
2494 exit(1);
2495}