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