2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
36 #include <mountinfo.h>
44 * Prototypes for internal functions.
46 static void conflict(char opt
, char *tab
[], int oldidx
, int newidx
);
47 static void illegal(char *value
, char *opt
);
48 static void reqval(char opt
, char *tab
[], int idx
);
49 static void respec(char opt
, char *tab
[], int idx
);
50 static void unknown(char opt
, char *s
);
51 static int ispow2(unsigned int i
);
52 static int max_trans_res(xfs_mount_t
*mp
);
55 * option tables for getsubopt calls
112 #ifdef MKFS_SIMULATION
138 #ifdef MKFS_SIMULATION
148 * max transaction reservation values
150 * first dimension log(blocksize) (base XFS_MIN_BLOCKSIZE_LOG)
151 * second dimension log(inodesize) (base XFS_DINODE_MIN_LOG)
153 * first dimension log(blocksize) (base XFS_MIN_BLOCKSIZE_LOG)
154 * second dimension log(inodesize) (base XFS_DINODE_MIN_LOG)
155 * third dimension log(dirblocksize) (base XFS_MIN_BLOCKSIZE_LOG)
157 #define DFL_B (XFS_MAX_BLOCKSIZE_LOG + 1 - XFS_MIN_BLOCKSIZE_LOG)
158 #define DFL_I (XFS_DINODE_MAX_LOG + 1 - XFS_DINODE_MIN_LOG)
159 #define DFL_D (XFS_MAX_BLOCKSIZE_LOG + 1 - XFS_MIN_BLOCKSIZE_LOG)
161 static const int max_trres_v1
[DFL_B
][DFL_I
] = {
162 { MAXTRRES_B9_I8_D9_V1
, 0, 0, 0 },
163 { MAXTRRES_B10_I8_D10_V1
, MAXTRRES_B10_I9_D10_V1
, 0, 0 },
164 { MAXTRRES_B11_I8_D11_V1
, MAXTRRES_B11_I9_D11_V1
,
165 MAXTRRES_B11_I10_D11_V1
, 0 },
166 { MAXTRRES_B12_I8_D12_V1
, MAXTRRES_B12_I9_D12_V1
,
167 MAXTRRES_B12_I10_D12_V1
, MAXTRRES_B12_I11_D12_V1
},
168 { MAXTRRES_B13_I8_D13_V1
, MAXTRRES_B13_I9_D13_V1
,
169 MAXTRRES_B13_I10_D13_V1
, MAXTRRES_B13_I11_D13_V1
},
170 { MAXTRRES_B14_I8_D14_V1
, MAXTRRES_B14_I9_D14_V1
,
171 MAXTRRES_B14_I10_D14_V1
, MAXTRRES_B14_I11_D14_V1
},
172 { MAXTRRES_B15_I8_D15_V1
, MAXTRRES_B15_I9_D15_V1
,
173 MAXTRRES_B15_I10_D15_V1
, MAXTRRES_B15_I11_D15_V1
},
174 { MAXTRRES_B16_I8_D16_V1
, MAXTRRES_B16_I9_D16_V1
,
175 MAXTRRES_B16_I10_D16_V1
, MAXTRRES_B16_I11_D16_V1
},
178 static const int max_trres_v2
[DFL_B
][DFL_I
][DFL_D
] = {
179 { { MAXTRRES_B9_I8_D9_V2
, MAXTRRES_B9_I8_D10_V2
, MAXTRRES_B9_I8_D11_V2
,
180 MAXTRRES_B9_I8_D12_V2
, MAXTRRES_B9_I8_D13_V2
, MAXTRRES_B9_I8_D14_V2
,
181 MAXTRRES_B9_I8_D15_V2
, MAXTRRES_B9_I8_D16_V2
},
182 { 0, 0, 0, 0, 0, 0, 0, 0 },
183 { 0, 0, 0, 0, 0, 0, 0, 0 },
184 { 0, 0, 0, 0, 0, 0, 0, 0 } },
185 { { 0, MAXTRRES_B10_I8_D10_V2
, MAXTRRES_B10_I8_D11_V2
,
186 MAXTRRES_B10_I8_D12_V2
, MAXTRRES_B10_I8_D13_V2
,
187 MAXTRRES_B10_I8_D14_V2
, MAXTRRES_B10_I8_D15_V2
,
188 MAXTRRES_B10_I8_D16_V2
},
189 { 0, MAXTRRES_B10_I9_D10_V2
, MAXTRRES_B10_I9_D11_V2
,
190 MAXTRRES_B10_I9_D12_V2
, MAXTRRES_B10_I9_D13_V2
,
191 MAXTRRES_B10_I9_D14_V2
, MAXTRRES_B10_I9_D15_V2
,
192 MAXTRRES_B10_I9_D16_V2
},
193 { 0, 0, 0, 0, 0, 0, 0, 0 },
194 { 0, 0, 0, 0, 0, 0, 0, 0 } },
195 { { 0, 0, MAXTRRES_B11_I8_D11_V2
, MAXTRRES_B11_I8_D12_V2
,
196 MAXTRRES_B11_I8_D13_V2
, MAXTRRES_B11_I8_D14_V2
,
197 MAXTRRES_B11_I8_D15_V2
, MAXTRRES_B11_I8_D16_V2
},
198 { 0, 0, MAXTRRES_B11_I9_D11_V2
, MAXTRRES_B11_I9_D12_V2
,
199 MAXTRRES_B11_I9_D13_V2
, MAXTRRES_B11_I9_D14_V2
,
200 MAXTRRES_B11_I9_D15_V2
, MAXTRRES_B11_I9_D16_V2
},
201 { 0, 0, MAXTRRES_B11_I10_D11_V2
, MAXTRRES_B11_I10_D12_V2
,
202 MAXTRRES_B11_I10_D13_V2
, MAXTRRES_B11_I10_D14_V2
,
203 MAXTRRES_B11_I10_D15_V2
, MAXTRRES_B11_I10_D16_V2
},
204 { 0, 0, 0, 0, 0, 0, 0, 0 } },
205 { { 0, 0, 0, MAXTRRES_B12_I8_D12_V2
, MAXTRRES_B12_I8_D13_V2
,
206 MAXTRRES_B12_I8_D14_V2
, MAXTRRES_B12_I8_D15_V2
,
207 MAXTRRES_B12_I8_D16_V2
},
208 { 0, 0, 0, MAXTRRES_B12_I9_D12_V2
, MAXTRRES_B12_I9_D13_V2
,
209 MAXTRRES_B12_I9_D14_V2
, MAXTRRES_B12_I9_D15_V2
,
210 MAXTRRES_B12_I9_D16_V2
},
211 { 0, 0, 0, MAXTRRES_B12_I10_D12_V2
, MAXTRRES_B12_I10_D13_V2
,
212 MAXTRRES_B12_I10_D14_V2
, MAXTRRES_B12_I10_D15_V2
,
213 MAXTRRES_B12_I10_D16_V2
},
214 { 0, 0, 0, MAXTRRES_B12_I11_D12_V2
, MAXTRRES_B12_I11_D13_V2
,
215 MAXTRRES_B12_I11_D14_V2
, MAXTRRES_B12_I11_D15_V2
,
216 MAXTRRES_B12_I11_D16_V2
} },
217 { { 0, 0, 0, 0, MAXTRRES_B13_I8_D13_V2
, MAXTRRES_B13_I8_D14_V2
,
218 MAXTRRES_B13_I8_D15_V2
, MAXTRRES_B13_I8_D16_V2
},
219 { 0, 0, 0, 0, MAXTRRES_B13_I9_D13_V2
, MAXTRRES_B13_I9_D14_V2
,
220 MAXTRRES_B13_I9_D15_V2
, MAXTRRES_B13_I9_D16_V2
},
221 { 0, 0, 0, 0, MAXTRRES_B13_I10_D13_V2
, MAXTRRES_B13_I10_D14_V2
,
222 MAXTRRES_B13_I10_D15_V2
, MAXTRRES_B13_I10_D16_V2
},
223 { 0, 0, 0, 0, MAXTRRES_B13_I11_D13_V2
, MAXTRRES_B13_I11_D14_V2
,
224 MAXTRRES_B13_I11_D15_V2
, MAXTRRES_B13_I11_D16_V2
} },
225 { { 0, 0, 0, 0, 0, MAXTRRES_B14_I8_D14_V2
, MAXTRRES_B14_I8_D15_V2
,
226 MAXTRRES_B14_I8_D16_V2
},
227 { 0, 0, 0, 0, 0, MAXTRRES_B14_I9_D14_V2
, MAXTRRES_B14_I9_D15_V2
,
228 MAXTRRES_B14_I9_D16_V2
},
229 { 0, 0, 0, 0, 0, MAXTRRES_B14_I10_D14_V2
, MAXTRRES_B14_I10_D15_V2
,
230 MAXTRRES_B14_I10_D16_V2
},
231 { 0, 0, 0, 0, 0, MAXTRRES_B14_I11_D14_V2
, MAXTRRES_B14_I11_D15_V2
,
232 MAXTRRES_B14_I11_D16_V2
} },
233 { { 0, 0, 0, 0, 0, 0, MAXTRRES_B15_I8_D15_V2
, MAXTRRES_B15_I8_D16_V2
},
234 { 0, 0, 0, 0, 0, 0, MAXTRRES_B15_I9_D15_V2
, MAXTRRES_B15_I9_D16_V2
},
235 { 0, 0, 0, 0, 0, 0, MAXTRRES_B15_I10_D15_V2
,
236 MAXTRRES_B15_I10_D16_V2
},
237 { 0, 0, 0, 0, 0, 0, MAXTRRES_B15_I11_D15_V2
,
238 MAXTRRES_B15_I11_D16_V2
} },
239 { { 0, 0, 0, 0, 0, 0, 0, MAXTRRES_B16_I8_D16_V2
},
240 { 0, 0, 0, 0, 0, 0, 0, MAXTRRES_B16_I9_D16_V2
},
241 { 0, 0, 0, 0, 0, 0, 0, MAXTRRES_B16_I10_D16_V2
},
242 { 0, 0, 0, 0, 0, 0, 0, MAXTRRES_B16_I11_D16_V2
, } },
246 * Use this before we have a superblock, else would use XFS_DTOBT
248 #define DTOBT(d) ((xfs_drfsbno_t)((d) >> (blocklog - BBSHIFT)))
251 * Use this for block reservations needed for mkfs's conditions
252 * (basically no fragmentation).
254 #define MKFS_BLOCKRES_INODE \
255 ((uint)(XFS_IALLOC_BLOCKS(mp) + (XFS_IN_MAXLEVELS(mp) - 1)))
256 #define MKFS_BLOCKRES(rb) \
257 ((uint)(MKFS_BLOCKRES_INODE + XFS_DA_NODE_MAXDEPTH + \
258 (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1) + (rb)))
261 calc_stripe_factors(int dsu
, int dsw
, int *dsunit
, int *dswidth
)
263 if (*dsunit
|| *dswidth
) {
266 "su/sw should not be used in conjunction with sunit/swidth\n");
270 if ((*dsunit
&& !*dswidth
) || (!*dsunit
&& *dswidth
)) {
272 "both sunit and swidth options have to be specified\n");
278 if (*dsunit
|| *dswidth
) {
280 "sunit/swidth should not be used in conjunction with su/sw\n");
284 if ((dsu
&& !dsw
) || (!dsu
&& dsw
)) {
286 "both su and sw options have to be specified\n");
291 fprintf(stderr
, "su must be a multiple of %d\n",
296 *dsunit
= (int)BTOBBT(dsu
);
297 *dswidth
= *dsunit
* dsw
;
300 if (*dsunit
&& (*dswidth
% *dsunit
!= 0)) {
302 "stripe width (%d) has to be a multiple of the stripe unit (%d)\n",
309 get_default_blocksize(void)
311 size_t pagesize
= getpagesize();
314 /* default is between 4K and 16K */
315 for (i
= 12; i
<= 16; i
++)
316 if ((1 << i
) == pagesize
)
318 return (1 << XFS_DFL_BLOCKSIZE_LOG
);
322 check_overwrite(char *device
)
326 if (device
&& *device
) {
327 if ((type
= fstype(device
)) != NULL
) {
329 "%s: %s appears to contain an existing filesystem (%s).\n",
330 progname
, device
, type
);
333 if ((type
= pttype(device
)) != NULL
) {
335 "%s: %s appears to contain a partition table (%s).\n",
336 progname
, device
, type
);
345 main(int argc
, char **argv
)
352 xfs_alloc_rec_t
*arec
;
353 xfs_btree_sblock_t
*block
;
363 xfs_drfsbno_t dblocks
;
368 int do_overlap_checks
;
392 xfs_agnumber_t logagno
;
393 xfs_drfsbno_t logblocks
;
397 xfs_dfsbno_t logstart
;
400 mnt_check_state_t
*mnt_check_state
;
401 int mnt_partition_count
;
404 xfs_extlen_t nbmblocks
;
407 xfs_alloc_rec_t
*nrec
;
414 xfs_drfsbno_t rtblocks
;
415 xfs_extlen_t rtextblocks
;
416 xfs_drtbno_t rtextents
;
422 __uint64_t tmp_agsize
;
423 __uint64_t tmp_logblocks
;
430 progname
= basename(argv
[0]);
434 blocksize
= get_default_blocksize();
435 blocklog
= libxfs_highbit32(blocksize
);
436 agsize
= daflag
= dblocks
= 0;
437 ilflag
= imflag
= ipflag
= isflag
= 0;
438 liflag
= laflag
= lsflag
= ldflag
= 0;
440 logagno
= logblocks
= rtblocks
= 0;
441 nlflag
= nsflag
= nvflag
= 0;
442 dirblocklog
= dirblocksize
= dirversion
= 0;
444 imaxpct
= inodelog
= inopblock
= isize
= 0;
445 iaflag
= XFS_IFLAG_ALIGN
;
446 bzero(&xi
, sizeof(xi
));
449 dfile
= logfile
= rtfile
= NULL
;
450 dsize
= logsize
= rtsize
= rtextsize
= protofile
= NULL
;
452 dsu
= dsw
= dsunit
= dswidth
= nodsflag
= lalign
= 0;
453 do_overlap_checks
= 1;
458 while ((c
= getopt(argc
, argv
, "b:d:i:l:L:n:p:qr:CfV")) != EOF
) {
461 do_overlap_checks
= 0;
471 switch (getsubopt(&p
, (constpp
)bopts
, &value
)) {
474 reqval('b', bopts
, B_LOG
);
476 respec('b', bopts
, B_LOG
);
478 conflict('b', bopts
, B_SIZE
,
480 blocklog
= atoi(value
);
482 illegal(value
, "b log");
483 blocksize
= 1 << blocklog
;
488 reqval('b', bopts
, B_SIZE
);
490 respec('b', bopts
, B_SIZE
);
492 conflict('b', bopts
, B_LOG
,
494 blocksize
= cvtnum(0, value
);
495 if (blocksize
<= 0 ||
497 illegal(value
, "b size");
498 blocklog
= libxfs_highbit32(blocksize
);
511 switch (getsubopt(&p
, (constpp
)dopts
, &value
)) {
514 reqval('d', dopts
, D_AGCOUNT
);
516 respec('d', dopts
, D_AGCOUNT
);
517 agcount
= (__uint64_t
)atoll(value
);
518 if ((__int64_t
)agcount
<= 0)
519 illegal(value
, "d agcount");
524 reqval('d', dopts
, D_AGSIZE
);
526 respec('d', dopts
, D_AGSIZE
);
527 if (blflag
|| bsflag
)
528 agsize
= cvtnum(blocksize
,
531 agsize
= cvtnum(0, value
);
537 xi
.disfile
= atoi(value
);
538 if (xi
.disfile
< 0 || xi
.disfile
> 1)
539 illegal(value
, "d file");
545 reqval('d', dopts
, D_NAME
);
547 respec('d', dopts
, D_NAME
);
552 reqval('d', dopts
, D_SIZE
);
554 respec('d', dopts
, D_SIZE
);
559 reqval('d', dopts
, D_SUNIT
);
561 respec('d', dopts
, D_SUNIT
);
562 if (blflag
|| bsflag
)
563 dsunit
= cvtnum(blocksize
,
566 dsunit
= cvtnum(0, value
);
570 reqval('d', dopts
, D_SWIDTH
);
572 respec('d', dopts
, D_SWIDTH
);
573 if (blflag
|| bsflag
)
574 dswidth
= cvtnum(blocksize
,
577 dswidth
= cvtnum(0, value
);
581 reqval('d', dopts
, D_SU
);
583 respec('d', dopts
, D_SU
);
584 dsu
= cvtnum(0, value
);
588 reqval('d', dopts
, D_SW
);
590 respec('d', dopts
, D_SW
);
591 dsw
= cvtnum(0, value
);
595 reqval('d', dopts
, D_UNWRITTEN
);
598 illegal(value
, "d unwritten");
611 switch (getsubopt(&p
, (constpp
)iopts
, &value
)) {
615 iaflag
= atoi(value
);
616 if (iaflag
< 0 || iaflag
> 1)
617 illegal(value
, "i align");
621 reqval('i', iopts
, I_LOG
);
623 respec('i', iopts
, I_LOG
);
625 conflict('i', iopts
, I_PERBLOCK
,
628 conflict('i', iopts
, I_SIZE
,
630 inodelog
= atoi(value
);
632 illegal(value
, "i log");
633 isize
= 1 << inodelog
;
638 reqval('i', iopts
, I_MAXPCT
);
640 respec('i', iopts
, I_MAXPCT
);
641 imaxpct
= atoi(value
);
642 if (imaxpct
< 0 || imaxpct
> 100)
643 illegal(value
, "i maxpct");
648 reqval('i', iopts
, I_PERBLOCK
);
650 conflict('i', iopts
, I_LOG
,
653 respec('i', iopts
, I_PERBLOCK
);
655 conflict('i', iopts
, I_SIZE
,
657 inopblock
= atoi(value
);
659 XFS_MIN_INODE_PERBLOCK
||
661 illegal(value
, "i perblock");
666 reqval('i', iopts
, I_SIZE
);
668 conflict('i', iopts
, I_LOG
,
671 conflict('i', iopts
, I_PERBLOCK
,
674 respec('i', iopts
, I_SIZE
);
675 isize
= cvtnum(0, value
);
676 if (isize
<= 0 || !ispow2(isize
))
677 illegal(value
, "i size");
678 inodelog
= libxfs_highbit32(isize
);
691 switch (getsubopt(&p
, (constpp
)lopts
, &value
)) {
694 respec('l', lopts
, L_AGNUM
);
697 conflict('l', lopts
, L_AGNUM
, L_DEV
);
699 logagno
= atoi(value
);
704 fprintf (stderr
, "Must specify log device\n");
709 conflict('l', lopts
, L_AGNUM
, L_DEV
);
712 conflict('l', lopts
, L_INTERNAL
, L_DEV
);
719 #ifdef HAVE_VOLUME_MANAGER
724 conflict('l', lopts
, L_INTERNAL
,
726 xi
.lisfile
= atoi(value
);
727 if (xi
.lisfile
< 0 || xi
.lisfile
> 1)
728 illegal(value
, "l file");
738 conflict('l', lopts
, L_INTERNAL
, L_DEV
);
739 #ifdef HAVE_VOLUME_MANAGER
741 conflict('l', lopts
, L_NAME
,
744 conflict('l', lopts
, L_FILE
,
748 respec('l', lopts
, L_INTERNAL
);
749 loginternal
= atoi(value
);
750 if (loginternal
< 0 || loginternal
> 1)
751 illegal(value
, "l internal");
754 #ifdef HAVE_VOLUME_MANAGER
757 reqval('l', lopts
, L_NAME
);
759 conflict('l', lopts
, L_INTERNAL
,
762 respec('l', lopts
, L_NAME
);
768 reqval('l', lopts
, L_SIZE
);
770 respec('l', lopts
, L_SIZE
);
780 if (strlen(optarg
) > sizeof(sbp
->sb_fname
))
781 illegal(optarg
, "L");
789 switch (getsubopt(&p
, (constpp
)nopts
, &value
)) {
792 reqval('n', nopts
, N_LOG
);
794 respec('n', nopts
, N_LOG
);
796 conflict('n', nopts
, N_SIZE
,
798 dirblocklog
= atoi(value
);
799 if (dirblocklog
<= 0)
800 illegal(value
, "n log");
801 dirblocksize
= 1 << dirblocklog
;
806 reqval('n', nopts
, N_SIZE
);
808 respec('n', nopts
, N_SIZE
);
810 conflict('n', nopts
, N_LOG
,
812 dirblocksize
= cvtnum(0, value
);
813 if (dirblocksize
<= 0 ||
814 !ispow2(dirblocksize
))
815 illegal(value
, "n size");
817 libxfs_highbit32(dirblocksize
);
822 reqval('n', nopts
, N_VERSION
);
824 respec('n', nopts
, N_VERSION
);
825 dirversion
= atoi(value
);
826 if (dirversion
< 1 || dirversion
> 2)
827 illegal(value
, "n version");
848 switch (getsubopt(&p
, (constpp
)ropts
, &value
)) {
851 reqval('r', ropts
, R_EXTSIZE
);
853 respec('r', ropts
, R_EXTSIZE
);
858 reqval('r', ropts
, R_DEV
);
861 #ifdef HAVE_VOLUME_MANAGER
865 xi
.risfile
= atoi(value
);
866 if (xi
.risfile
< 0 || xi
.risfile
> 1)
867 illegal(value
, "r file");
873 reqval('r', ropts
, R_NAME
);
875 respec('r', ropts
, R_NAME
);
881 reqval('r', ropts
, R_SIZE
);
883 respec('r', ropts
, R_SIZE
);
893 printf("%s version %s\n", progname
, VERSION
);
899 if (argc
- optind
> 1) {
900 fprintf(stderr
, "extra arguments\n");
902 } else if (argc
- optind
== 1) {
903 dfile
= xi
.volname
= argv
[optind
];
906 "cannot specify both %s and -d name=%s\n",
907 xi
.volname
, xi
.dname
);
912 /* option post-processing */
913 if (blocksize
< XFS_MIN_BLOCKSIZE
|| blocksize
> XFS_MAX_BLOCKSIZE
) {
914 fprintf(stderr
, "illegal block size %d\n", blocksize
);
918 dirversion
= (nsflag
|| nlflag
) ? 2 : XFS_DFL_DIR_VERSION
;
919 switch (dirversion
) {
921 if ((nsflag
|| nlflag
) && dirblocklog
!= blocklog
) {
922 fprintf(stderr
, "illegal directory block size %d\n",
928 if (nsflag
|| nlflag
) {
929 if (dirblocksize
< blocksize
||
930 dirblocksize
> XFS_MAX_BLOCKSIZE
) {
932 "illegal directory block size %d\n",
937 if (blocksize
< (1 << XFS_MIN_REC_DIRSIZE
))
938 dirblocklog
= XFS_MIN_REC_DIRSIZE
;
940 dirblocklog
= blocklog
;
941 dirblocksize
= 1 << dirblocklog
;
946 if (daflag
&& dasize
) {
948 "both -d agcount= and agsize= specified, use one or the other\n");
955 if (xi
.disfile
&& (!dsize
|| !xi
.dname
)) {
957 "if -d file then -d name and -d size are required\n");
963 dbytes
= cvtnum(blocksize
, dsize
);
964 if (dbytes
% XFS_MIN_BLOCKSIZE
) {
966 "illegal data length %lld, not a multiple of %d\n",
967 (long long)dbytes
, XFS_MIN_BLOCKSIZE
);
970 dblocks
= (xfs_drfsbno_t
)(dbytes
>> blocklog
);
971 if (dbytes
% blocksize
)
973 "warning: data length %lld not a multiple of %d, truncated to %lld\n",
974 (long long)dbytes
, blocksize
,
975 (long long)(dblocks
<< blocklog
));
978 inodelog
= blocklog
- libxfs_highbit32(inopblock
);
979 isize
= 1 << inodelog
;
980 } else if (!ilflag
&& !isflag
) {
981 inodelog
= XFS_DINODE_DFL_LOG
;
982 isize
= 1 << inodelog
;
984 #ifdef HAVE_VOLUME_MANAGER
985 if (xi
.lisfile
&& (!logsize
|| !xi
.logname
)) {
987 "if -l file then -l name and -l size are required\n");
994 logbytes
= cvtnum(blocksize
, logsize
);
995 if (logbytes
% XFS_MIN_BLOCKSIZE
) {
997 "illegal log length %lld, not a multiple of %d\n",
998 (long long)logbytes
, XFS_MIN_BLOCKSIZE
);
1001 logblocks
= (xfs_drfsbno_t
)(logbytes
>> blocklog
);
1002 if (logbytes
% blocksize
)
1004 "warning: log length %lld not a multiple of %d, truncated to %lld\n",
1005 (long long)logbytes
, blocksize
,
1006 (long long)(logblocks
<< blocklog
));
1008 #ifdef HAVE_VOLUME_MANAGER
1009 if (xi
.risfile
&& (!rtsize
|| !xi
.rtname
)) {
1011 "if -r file then -r name and -r size are required\n");
1018 rtbytes
= cvtnum(blocksize
, rtsize
);
1019 if (rtbytes
% XFS_MIN_BLOCKSIZE
) {
1021 "illegal rt length %lld, not a multiple of %d\n",
1022 (long long)rtbytes
, XFS_MIN_BLOCKSIZE
);
1025 rtblocks
= (xfs_drfsbno_t
)(rtbytes
>> blocklog
);
1026 if (rtbytes
% blocksize
)
1028 "warning: rt length %lld not a multiple of %d, truncated to %lld\n",
1029 (long long)rtbytes
, blocksize
,
1030 (long long)(rtblocks
<< blocklog
));
1033 * If specified, check rt extent size against its constraints.
1036 __uint64_t rtextbytes
;
1038 rtextbytes
= cvtnum(blocksize
, rtextsize
);
1039 if (rtextbytes
% blocksize
) {
1041 "illegal rt extent size %lld, not a multiple of %d\n",
1042 (long long)rtextbytes
, blocksize
);
1045 if (rtextbytes
> XFS_MAX_RTEXTSIZE
) {
1047 "rt extent size %s too large, maximum %d\n",
1048 rtextsize
, XFS_MAX_RTEXTSIZE
);
1051 if (rtextbytes
< XFS_MIN_RTEXTSIZE
) {
1053 "rt extent size %s too small, minimum %d\n",
1054 rtextsize
, XFS_MIN_RTEXTSIZE
);
1057 rtextblocks
= (xfs_extlen_t
)(rtextbytes
>> blocklog
);
1060 * If realtime extsize has not been specified by the user,
1061 * and the underlying volume is striped, then set rtextblocks
1062 * to the stripe width.
1064 int dummy1
, rswidth
;
1065 __uint64_t rtextbytes
;
1066 dummy1
= rswidth
= 0;
1069 get_subvol_stripe_wrapper(dfile
, SVTYPE_RT
, &dummy1
,
1072 /* check that rswidth is a multiple of fs blocksize */
1073 if (rswidth
&& !(BBTOB(rswidth
) % blocksize
)) {
1074 rswidth
= DTOBT(rswidth
);
1075 rtextbytes
= rswidth
<< blocklog
;
1076 if (XFS_MIN_RTEXTSIZE
<= rtextbytes
&&
1077 (rtextbytes
<= XFS_MAX_RTEXTSIZE
)) {
1078 rtextblocks
= rswidth
;
1080 rtextblocks
= XFS_DFL_RTEXTSIZE
>> blocklog
;
1083 rtextblocks
= XFS_DFL_RTEXTSIZE
>> blocklog
;
1087 * Check some argument sizes against mins, maxes.
1089 if (isize
> blocksize
/ XFS_MIN_INODE_PERBLOCK
||
1090 isize
< XFS_DINODE_MIN_SIZE
||
1091 isize
> XFS_DINODE_MAX_SIZE
) {
1094 fprintf(stderr
, "illegal inode size %d\n", isize
);
1095 maxsz
= MIN(blocksize
/ XFS_MIN_INODE_PERBLOCK
,
1096 XFS_DINODE_MAX_SIZE
);
1097 if (XFS_DINODE_MIN_SIZE
== maxsz
)
1099 "allowable inode size with %d byte blocks is %d\n",
1100 blocksize
, XFS_DINODE_MIN_SIZE
);
1103 "allowable inode size with %d byte blocks is between %d and %d\n",
1104 blocksize
, XFS_DINODE_MIN_SIZE
, maxsz
);
1108 calc_stripe_factors(dsu
, dsw
, &dsunit
, &dswidth
);
1110 /* other global variables */
1111 sectlog
= 9; /* i.e. 512 bytes */
1114 * Initialize. This will open the log and rt devices as well.
1116 if (!libxfs_init(&xi
))
1119 fprintf(stderr
, "no device name given in argument list\n");
1123 if (!force_overwrite
) {
1124 if (check_overwrite(dfile
) ||
1125 check_overwrite(logfile
) ||
1126 check_overwrite(xi
.rtname
)) {
1127 fprintf(stderr
, "%s: "
1128 "Use the -f option to force overwrite.\n",
1134 if (!xi
.disfile
&& do_overlap_checks
) {
1136 * do partition overlap check
1137 * If this is a straight file we assume that it's been created
1138 * before the call to mnt_check_init()
1141 if (mnt_check_init(&mnt_check_state
) == -1) {
1143 "unable to initialize mount checking "
1144 "routines, bypassing protection checks.\n");
1146 mnt_partition_count
= mnt_find_mount_conflicts(
1147 mnt_check_state
, dfile
);
1150 * ignore -1 return codes, since 3rd party devices
1151 * may not be part of hinv.
1153 if (mnt_partition_count
> 0) {
1154 if (mnt_causes_test(mnt_check_state
, MNT_CAUSE_MOUNTED
)) {
1155 fprintf(stderr
, "%s: "
1156 "%s is already in use.\n",
1158 } else if (mnt_causes_test(mnt_check_state
, MNT_CAUSE_OVERLAP
)) {
1159 fprintf(stderr
, "%s: "
1160 "%s overlaps partition(s) "
1161 "already in use.\n",
1164 mnt_causes_show(mnt_check_state
, stderr
, progname
);
1166 fprintf(stderr
, "\n");
1168 mnt_plist_show(mnt_check_state
, stderr
, progname
);
1169 fprintf(stderr
, "\n");
1171 mnt_check_end(mnt_check_state
);
1172 if (mnt_partition_count
> 0) {
1178 if (!liflag
&& !ldflag
)
1179 loginternal
= xi
.logdev
== 0;
1181 logfile
= xi
.logname
;
1182 else if (loginternal
)
1183 logfile
= "internal log";
1184 else if (xi
.volname
&& xi
.logdev
)
1185 logfile
= "volume log";
1187 fprintf(stderr
, "no log subvolume or internal log\n");
1193 if (xi
.volname
&& xi
.rtdev
)
1194 rtfile
= "volume rt";
1197 if (dsize
&& xi
.dsize
> 0 && dblocks
> DTOBT(xi
.dsize
)) {
1199 "size %s specified for data subvolume is too large, maximum is %lld blocks\n",
1200 dsize
, (long long)DTOBT(xi
.dsize
));
1202 } else if (!dsize
&& xi
.dsize
> 0)
1203 dblocks
= DTOBT(xi
.dsize
);
1205 fprintf(stderr
, "can't get size of data subvolume\n");
1208 if (dblocks
< XFS_MIN_DATA_BLOCKS
) {
1210 "size %lld of data subvolume is too small, minimum %d blocks\n",
1211 (long long)dblocks
, XFS_MIN_DATA_BLOCKS
);
1214 if (xi
.logdev
&& loginternal
) {
1215 fprintf(stderr
, "can't have both external and internal logs\n");
1218 if (dirversion
== 1)
1219 i
= max_trres_v1
[blocklog
- XFS_MIN_BLOCKSIZE_LOG
]
1220 [inodelog
- XFS_DINODE_MIN_LOG
];
1222 i
= max_trres_v2
[blocklog
- XFS_MIN_BLOCKSIZE_LOG
]
1223 [inodelog
- XFS_DINODE_MIN_LOG
]
1224 [dirblocklog
- XFS_MIN_BLOCKSIZE_LOG
];
1225 min_logblocks
= MAX(XFS_MIN_LOG_BLOCKS
, i
* XFS_MIN_LOG_FACTOR
);
1226 if (logsize
&& xi
.logBBsize
> 0 && logblocks
> DTOBT(xi
.logBBsize
)) {
1228 "size %s specified for log subvolume is too large, maximum is %lld blocks\n",
1229 logsize
, (long long)DTOBT(xi
.logBBsize
));
1231 } else if (!logsize
&& xi
.logBBsize
> 0)
1232 logblocks
= DTOBT(xi
.logBBsize
);
1233 else if (logsize
&& !xi
.logdev
&& !loginternal
) {
1235 "size specified for non-existent log subvolume\n");
1237 } else if (loginternal
&& logsize
&& logblocks
>= dblocks
) {
1238 fprintf(stderr
, "size %lld too large for internal log\n",
1239 (long long)logblocks
);
1241 } else if (!loginternal
&& !xi
.logdev
)
1243 else if (loginternal
&& !logsize
) {
1245 * logblocks grows from min_logblocks to XFS_MAX_LOG_BLOCKS
1248 * 8192 = 1TB / MAX_LOG_BYTES
1250 logblocks
= (dblocks
<< blocklog
) / 8192;
1251 logblocks
= logblocks
>> blocklog
;
1252 logblocks
= MAX(min_logblocks
, logblocks
);
1253 logblocks
= MAX(logblocks
,
1254 MAX(XFS_DFL_LOG_SIZE
, i
* XFS_DFL_LOG_FACTOR
));
1255 logblocks
= MIN(logblocks
, XFS_MAX_LOG_BLOCKS
);
1256 if ((logblocks
<< blocklog
) > XFS_MAX_LOG_BYTES
) {
1257 logblocks
= XFS_MAX_LOG_BYTES
>> blocklog
;
1260 if (logblocks
< min_logblocks
) {
1262 "log size %lld blocks too small, minimum size is %d blocks\n",
1263 (long long)logblocks
, min_logblocks
);
1266 if (logblocks
> XFS_MAX_LOG_BLOCKS
) {
1268 "log size %lld blocks too large, maximum size is %d blocks\n",
1269 (long long)logblocks
, XFS_MAX_LOG_BLOCKS
);
1272 if ((logblocks
<< blocklog
) > XFS_MAX_LOG_BYTES
) {
1274 "log size %lld bytes too large, maximum size is %d bytes\n",
1275 (long long)(logblocks
<< blocklog
), XFS_MAX_LOG_BYTES
);
1278 if (rtsize
&& xi
.rtsize
> 0 && rtblocks
> DTOBT(xi
.rtsize
)) {
1280 "size %s specified for rt subvolume is too large, maximum is %lld blocks\n",
1281 rtsize
, (long long)DTOBT(xi
.rtsize
));
1283 } else if (!rtsize
&& xi
.rtsize
> 0)
1284 rtblocks
= DTOBT(xi
.rtsize
);
1285 else if (rtsize
&& !xi
.rtdev
) {
1287 "size specified for non-existent rt subvolume\n");
1291 rtextents
= rtblocks
/ rtextblocks
;
1292 nbmblocks
= (xfs_extlen_t
)howmany(rtextents
, NBBY
* blocksize
);
1294 rtextents
= rtblocks
= 0;
1300 * If the specified agsize isn't a multiple of fs blks,
1303 if (agsize
% blocksize
) {
1305 "agsize (%lld) not a multiple of fs blk size (%d)\n",
1306 (long long)agsize
, blocksize
);
1310 agsize
/= blocksize
;
1313 * If the specified agsize is too small, or too large,
1316 if (agsize
< XFS_AG_MIN_BLOCKS(blocklog
)) {
1318 "agsize (%lldb) too small, need at least %lld blocks\n",
1320 (long long)XFS_AG_MIN_BLOCKS(blocklog
));
1324 if (agsize
> XFS_AG_MAX_BLOCKS(blocklog
)) {
1326 "agsize (%lldb) too big, maximum is %lld blocks\n",
1328 (long long)XFS_AG_MAX_BLOCKS(blocklog
));
1332 if (agsize
> dblocks
) {
1334 "agsize (%lldb) too big, data area is %lld blocks\n",
1335 (long long)agsize
, (long long)dblocks
);
1339 agcount
= dblocks
/ agsize
+ (dblocks
% agsize
!= 0);
1341 agsize
= dblocks
/ agcount
+ (dblocks
% agcount
!= 0);
1345 * If the ag size is too small, complain if agcount/agsize was
1346 * specified, and fix it otherwise.
1348 if (agsize
< XFS_AG_MIN_BLOCKS(blocklog
)) {
1349 if (daflag
|| dasize
) {
1351 "too many allocation groups for size = %lld\n",
1353 fprintf(stderr
, "need at most %lld allocation groups\n",
1355 (dblocks
/ XFS_AG_MIN_BLOCKS(blocklog
) +
1356 (dblocks
% XFS_AG_MIN_BLOCKS(blocklog
) != 0)));
1359 agsize
= XFS_AG_MIN_BLOCKS(blocklog
);
1360 if (dblocks
< agsize
)
1363 agcount
= dblocks
/ agsize
;
1365 agsize
= dblocks
/ agcount
+ (dblocks
% agcount
!= 0);
1369 * If the ag size is too large, complain if agcount/agsize was
1370 * specified, and fix it otherwise.
1372 else if (agsize
> XFS_AG_MAX_BLOCKS(blocklog
)) {
1373 if (daflag
|| dasize
) {
1374 fprintf(stderr
, "too few allocation groups for size = %lld\n",
1377 "need at least %lld allocation groups\n",
1379 (dblocks
/ XFS_AG_MAX_BLOCKS(blocklog
) +
1380 (dblocks
% XFS_AG_MAX_BLOCKS(blocklog
) != 0)));
1383 agsize
= XFS_AG_MAX_BLOCKS(blocklog
);
1384 agcount
= dblocks
/ agsize
+ (dblocks
% agsize
!= 0);
1388 * if user set the AG size, and if the last AG is too small,
1389 * reduce the filesystem size and drop the blocks.
1392 (dblocks
% agsize
< XFS_AG_MIN_BLOCKS(blocklog
))) {
1393 dblocks
-= dblocks
% agsize
;
1397 * If agcount was not specified, and agsize is larger than
1398 * we'd like, make it the size we want.
1400 if (!daflag
&& !dasize
&&
1401 (agsize
> XFS_AG_BEST_BLOCKS(blocklog
,dblocks
))) {
1402 agsize
= XFS_AG_BEST_BLOCKS(blocklog
,dblocks
);
1404 * If the last AG is too small, reduce the filesystem size
1405 * and drop the blocks.
1407 if (dblocks
% agsize
< XFS_AG_MIN_BLOCKS(blocklog
)) {
1408 dblocks
-= dblocks
% agsize
;
1410 agcount
= dblocks
/ agsize
+ (dblocks
% agsize
!= 0);
1414 * If agcount is too large, make it smaller.
1416 if (agcount
> XFS_MAX_AGNUMBER
+ 1) {
1417 agcount
= XFS_MAX_AGNUMBER
+ 1;
1418 agsize
= dblocks
/ agcount
+ (dblocks
% agcount
!= 0);
1420 if (dasize
|| daflag
)
1422 "agsize set to %lld, agcount %lld > max (%lld)\n",
1423 (long long)agsize
, (long long)agcount
,
1424 (long long)XFS_MAX_AGNUMBER
+1);
1426 if (agsize
> XFS_AG_MAX_BLOCKS(blocklog
)) {
1430 fprintf(stderr
, "%s: can't compute agsize/agcount\n",
1436 xlv_dsunit
= xlv_dswidth
= 0;
1438 get_subvol_stripe_wrapper(dfile
, SVTYPE_DATA
, &xlv_dsunit
,
1442 if (xlv_dsunit
&& xlv_dsunit
!= dsunit
) {
1443 fprintf(stderr
, "%s: "
1444 "Specified data stripe unit %d is not the same as the xlv stripe unit %d\n",
1445 progname
, dsunit
, xlv_dsunit
);
1448 if (xlv_dswidth
&& xlv_dswidth
!= dswidth
) {
1449 fprintf(stderr
, "%s: "
1450 "Specified data stripe width (%d) is not the same as the xlv stripe width (%d)\n",
1451 progname
, dswidth
, xlv_dswidth
);
1455 dsunit
= xlv_dsunit
;
1456 dswidth
= xlv_dswidth
;
1461 * If dsunit is a multiple of fs blocksize, then check that is a
1462 * multiple of the agsize too
1464 if (dsunit
&& !(BBTOB(dsunit
) % blocksize
) &&
1465 dswidth
&& !(BBTOB(dswidth
) % blocksize
)) {
1467 /* convert from 512 byte blocks to fs blocksize */
1468 dsunit
= DTOBT(dsunit
);
1469 dswidth
= DTOBT(dswidth
);
1472 * agsize is not a multiple of dsunit
1474 if ((agsize
% dsunit
) != 0) {
1476 * Round up to stripe unit boundary. Also make sure
1477 * that agsize is still larger than
1478 * XFS_AG_MIN_BLOCKS(blocklog)
1480 tmp_agsize
= ((agsize
+ (dsunit
- 1))/ dsunit
) * dsunit
;
1482 * Round down to stripe unit boundary if rounding up
1483 * created an AG size that is larger than the AG max.
1485 if (tmp_agsize
> XFS_AG_MAX_BLOCKS(blocklog
))
1486 tmp_agsize
= ((agsize
) / dsunit
) * dsunit
;
1487 if ((tmp_agsize
>= XFS_AG_MIN_BLOCKS(blocklog
)) &&
1488 (tmp_agsize
<= XFS_AG_MAX_BLOCKS(blocklog
)) &&
1490 agsize
= tmp_agsize
;
1491 agcount
= dblocks
/agsize
+
1492 (dblocks
% agsize
!= 0);
1493 if (dasize
|| daflag
)
1495 "agsize rounded to %lld, swidth = %d\n",
1496 (long long)agsize
, dswidth
);
1499 dsunit
= dswidth
= 0;
1502 "Allocation group size %lld is not a multiple of the stripe unit %d\n",
1503 (long long)agsize
, dsunit
);
1510 dsunit
= dswidth
= 0;
1512 fprintf(stderr
, "%s: "
1513 "Stripe unit(%d) or stripe width(%d) is not a multiple of the block size(%d)\n",
1514 progname
, dsunit
, dswidth
, blocksize
);
1521 * Check to see if inode number will be > 32 significant bits
1522 * Note that libxfs_highbitXX returns 0 -> XX-1,
1523 * so to get the bit count, add one to what we get.
1526 inodebits
= (libxfs_highbit32(blocksize
/isize
- 1) + 1)
1527 + (libxfs_highbit64(agsize
- 1) + 1)
1528 + (libxfs_highbit64(agcount
- 1) + 1);
1530 if (inodebits
> XFS_MAX_INODE_SIG_BITS
) {
1535 new_isize
= isize
<< (inodebits
- XFS_MAX_INODE_SIG_BITS
);
1537 new_isize_ok
= (new_isize
<= blocksize
/ XFS_MIN_INODE_PERBLOCK
1538 && new_isize
<= XFS_DINODE_MAX_SIZE
);
1540 if (ilflag
+ ipflag
+ isflag
== 0) {
1542 * If we didn't specify inode size, just bump it up
1543 * unless we can't go far enough.
1548 /* re-calc inodebits */
1549 inodebits
= (libxfs_highbit32(blocksize
/isize
- 1) + 1)
1550 + (libxfs_highbit64(agsize
- 1) + 1)
1551 + (libxfs_highbit64(agcount
- 1) + 1);
1552 inodelog
= libxfs_highbit32(isize
);
1553 /* Let's not get too chatty, no fprintf here */
1556 * Can't do nothin' for ya, man!
1557 * Don't bother changing isize at all,
1558 * one bit over is as bad as 20.
1561 "warning: inode numbers exceed %d "
1562 " significant bits (%d)\n",
1563 XFS_MAX_INODE_SIG_BITS
, inodebits
);
1566 /* if isize specified, just warn the user */
1568 "warning: inode numbers exceed %d "
1569 "significant bits (%d)\n",
1570 XFS_MAX_INODE_SIG_BITS
, inodebits
);
1573 " increase inode size to %d to "
1574 "avoid this\n", new_isize
);
1580 protostring
= setup_proto(protofile
);
1581 bsize
= 1 << (blocklog
- BBSHIFT
);
1582 buf
= libxfs_getbuf(xi
.ddev
, XFS_SB_DADDR
, 1);
1585 bzero(mp
, sizeof(xfs_mount_t
));
1586 sbp
->sb_blocklog
= (__uint8_t
)blocklog
;
1587 sbp
->sb_agblklog
= (__uint8_t
)libxfs_log2_roundup((unsigned int)agsize
);
1588 mp
->m_blkbb_log
= sbp
->sb_blocklog
- BBSHIFT
;
1590 if (logblocks
> agsize
- XFS_PREALLOC_BLOCKS(mp
)) {
1592 "internal log size %lld too large, must fit in allocation group\n",
1593 (long long)logblocks
);
1597 if (logagno
>= agcount
) {
1599 "log ag number %d too large, must be less than %lld\n",
1600 logagno
, (long long)agcount
);
1604 logagno
= (xfs_agnumber_t
)(agcount
/ 2);
1606 logstart
= XFS_AGB_TO_FSB(mp
, logagno
, XFS_PREALLOC_BLOCKS(mp
));
1608 * Align the logstart at stripe unit boundary.
1610 if (dsunit
&& ((logstart
% dsunit
) != 0)) {
1611 logstart
= ((logstart
+ (dsunit
- 1))/dsunit
) * dsunit
;
1613 * Make sure that the log size is a multiple of the
1616 if ((logblocks
% dsunit
) != 0) {
1618 tmp_logblocks
= ((logblocks
+ (dsunit
- 1))
1621 * If the log is too large, round down
1622 * instead of round up
1624 if ((tmp_logblocks
> XFS_MAX_LOG_BLOCKS
) ||
1625 ((tmp_logblocks
<< blocklog
) > XFS_MAX_LOG_BYTES
)) {
1626 tmp_logblocks
= (logblocks
/ dsunit
) * dsunit
;
1628 logblocks
= tmp_logblocks
;
1631 "internal log size %lld is not a multiple of the stripe unit %d\n",
1632 (long long)logblocks
, dsunit
);
1637 if (logblocks
> agsize
-XFS_FSB_TO_AGBNO(mp
,logstart
)) {
1639 "Due to stripe alignment, the internal log size %lld is too large.\n"
1640 "Must fit in allocation group\n",
1641 (long long)logblocks
);
1650 strncpy(sbp
->sb_fname
, label
, sizeof(sbp
->sb_fname
));
1651 sbp
->sb_magicnum
= XFS_SB_MAGIC
;
1652 sbp
->sb_blocksize
= blocksize
;
1653 sbp
->sb_dblocks
= dblocks
;
1654 sbp
->sb_rblocks
= rtblocks
;
1655 sbp
->sb_rextents
= rtextents
;
1656 uuid_generate(uuid
);
1657 uuid_copy(sbp
->sb_uuid
, uuid
);
1658 sbp
->sb_logstart
= logstart
;
1659 sbp
->sb_rootino
= sbp
->sb_rbmino
= sbp
->sb_rsumino
= NULLFSINO
;
1660 sbp
->sb_rextsize
= rtextblocks
;
1661 sbp
->sb_agblocks
= (xfs_agblock_t
)agsize
;
1662 sbp
->sb_agcount
= (xfs_agnumber_t
)agcount
;
1663 sbp
->sb_rbmblocks
= nbmblocks
;
1664 sbp
->sb_logblocks
= (xfs_extlen_t
)logblocks
;
1665 sbp
->sb_sectsize
= 1 << sectlog
;
1666 sbp
->sb_inodesize
= (__uint16_t
)isize
;
1667 sbp
->sb_inopblock
= (__uint16_t
)(blocksize
/ isize
);
1668 sbp
->sb_sectlog
= (__uint8_t
)sectlog
;
1669 sbp
->sb_inodelog
= (__uint8_t
)inodelog
;
1670 sbp
->sb_inopblog
= (__uint8_t
)(blocklog
- inodelog
);
1672 (__uint8_t
)(rtextents
?
1673 libxfs_highbit32((unsigned int)rtextents
) : 0);
1674 sbp
->sb_inprogress
= 1; /* mkfs is in progress */
1675 sbp
->sb_imax_pct
= imflag
? imaxpct
: XFS_DFL_IMAXIMUM_PCT
;
1678 sbp
->sb_fdblocks
= dblocks
- agcount
* XFS_PREALLOC_BLOCKS(mp
) -
1679 (loginternal
? logblocks
: 0);
1680 sbp
->sb_frextents
= 0; /* will do a free later */
1681 sbp
->sb_uquotino
= sbp
->sb_gquotino
= 0;
1683 sbp
->sb_unit
= dsunit
;
1684 sbp
->sb_width
= dswidth
;
1685 if (dirversion
== 2)
1686 sbp
->sb_dirblklog
= dirblocklog
- blocklog
;
1688 sbp
->sb_inoalignmt
= XFS_INODE_BIG_CLUSTER_SIZE
>> blocklog
;
1689 iaflag
= sbp
->sb_inoalignmt
!= 0;
1691 sbp
->sb_inoalignmt
= 0;
1692 sbp
->sb_versionnum
=
1693 XFS_SB_VERSION_MKFS(iaflag
, dsunit
!= 0, extent_flagging
,
1696 bzero(XFS_BUF_PTR(buf
), BBSIZE
);
1697 libxfs_xlate_sb(XFS_BUF_PTR(buf
), sbp
, -1, ARCH_CONVERT
,
1699 libxfs_writebuf(buf
, 1);
1703 "meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n"
1704 "data =%-22s bsize=%-6d blocks=%lld, imaxpct=%d\n"
1705 " =%-22s sunit=%-6d swidth=%d blks, unwritten=%d\n"
1706 " =%-22s imaxbits=%-6d\n"
1707 "naming =version %-14d bsize=%-6d\n"
1708 "log =%-22s bsize=%-6d blocks=%lld\n"
1709 "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n",
1710 dfile
, isize
, (long long)agcount
, (long long)agsize
,
1711 "", blocksize
, (long long)dblocks
, sbp
->sb_imax_pct
,
1712 "", dsunit
, dswidth
, extent_flagging
,
1714 dirversion
, dirversion
== 1 ? blocksize
: dirblocksize
,
1715 logfile
, 1 << blocklog
, (long long)logblocks
,
1716 rtfile
, rtextblocks
<< blocklog
,
1717 (long long)rtblocks
, (long long)rtextents
);
1719 * If the data area is a file, then grow it out to its final size
1720 * so that the reads for the end of the device in the mount code
1723 if (xi
.disfile
&& ftruncate64(xi
.dfd
, dblocks
* blocksize
) < 0) {
1724 fprintf(stderr
, "%s: Growing the data section file failed\n",
1729 * Zero the log if there is one.
1732 xi
.logdev
= xi
.ddev
;
1736 XFS_FSB_TO_DADDR(mp
, logstart
),
1737 (xfs_extlen_t
)XFS_FSB_TO_BB(mp
, logblocks
),
1741 mp
= libxfs_mount(mp
, sbp
, xi
.ddev
, xi
.logdev
, xi
.rtdev
, 1);
1743 fprintf(stderr
, "%s: mount initialization failed\n", progname
);
1747 XFS_FSB_TO_B(mp
, logblocks
) <
1748 XFS_MIN_LOG_FACTOR
* max_trans_res(mp
)) {
1749 fprintf(stderr
, "%s: log size (%lld) is too small for "
1750 "transaction reservations\n",
1751 progname
, (long long)logblocks
);
1755 for (agno
= 0; agno
< agcount
; agno
++) {
1759 buf
= libxfs_getbuf(xi
.ddev
,
1760 XFS_AG_DADDR(mp
, agno
, XFS_SB_DADDR
), 1);
1761 bzero(XFS_BUF_PTR(buf
), BBSIZE
);
1762 libxfs_xlate_sb(XFS_BUF_PTR(buf
), sbp
, -1, ARCH_CONVERT
,
1764 libxfs_writebuf(buf
, 1);
1767 * AG header block: freespace
1769 buf
= libxfs_getbuf(mp
->m_dev
,
1770 XFS_AG_DADDR(mp
, agno
, XFS_AGF_DADDR
), 1);
1771 agf
= XFS_BUF_TO_AGF(buf
);
1773 if (agno
== agcount
- 1)
1774 agsize
= dblocks
- (xfs_drfsbno_t
)(agno
* agsize
);
1775 INT_SET(agf
->agf_magicnum
, ARCH_CONVERT
, XFS_AGF_MAGIC
);
1776 INT_SET(agf
->agf_versionnum
, ARCH_CONVERT
, XFS_AGF_VERSION
);
1777 INT_SET(agf
->agf_seqno
, ARCH_CONVERT
, agno
);
1778 INT_SET(agf
->agf_length
, ARCH_CONVERT
, (xfs_agblock_t
)agsize
);
1779 INT_SET(agf
->agf_roots
[XFS_BTNUM_BNOi
], ARCH_CONVERT
,
1781 INT_SET(agf
->agf_roots
[XFS_BTNUM_CNTi
], ARCH_CONVERT
,
1783 INT_SET(agf
->agf_levels
[XFS_BTNUM_BNOi
], ARCH_CONVERT
, 1);
1784 INT_SET(agf
->agf_levels
[XFS_BTNUM_CNTi
], ARCH_CONVERT
, 1);
1785 INT_SET(agf
->agf_flfirst
, ARCH_CONVERT
, 0);
1786 INT_SET(agf
->agf_fllast
, ARCH_CONVERT
, XFS_AGFL_SIZE
- 1);
1787 INT_SET(agf
->agf_flcount
, ARCH_CONVERT
, 0);
1788 nbmblocks
= (xfs_extlen_t
)(agsize
- XFS_PREALLOC_BLOCKS(mp
));
1789 INT_SET(agf
->agf_freeblks
, ARCH_CONVERT
, nbmblocks
);
1790 INT_SET(agf
->agf_longest
, ARCH_CONVERT
, nbmblocks
);
1791 if (loginternal
&& agno
== logagno
) {
1792 INT_MOD(agf
->agf_freeblks
, ARCH_CONVERT
, -logblocks
);
1793 INT_SET(agf
->agf_longest
, ARCH_CONVERT
, agsize
-
1794 XFS_FSB_TO_AGBNO(mp
, logstart
) - logblocks
);
1796 if (XFS_MIN_FREELIST(agf
, mp
) > worst_freelist
)
1797 worst_freelist
= XFS_MIN_FREELIST(agf
, mp
);
1798 libxfs_writebuf(buf
, 1);
1801 * AG header block: inodes
1803 buf
= libxfs_getbuf(mp
->m_dev
,
1804 XFS_AG_DADDR(mp
, agno
, XFS_AGI_DADDR
), 1);
1805 agi
= XFS_BUF_TO_AGI(buf
);
1807 INT_SET(agi
->agi_magicnum
, ARCH_CONVERT
, XFS_AGI_MAGIC
);
1808 INT_SET(agi
->agi_versionnum
, ARCH_CONVERT
, XFS_AGI_VERSION
);
1809 INT_SET(agi
->agi_seqno
, ARCH_CONVERT
, agno
);
1810 INT_SET(agi
->agi_length
, ARCH_CONVERT
, (xfs_agblock_t
)agsize
);
1811 INT_SET(agi
->agi_count
, ARCH_CONVERT
, 0);
1812 INT_SET(agi
->agi_root
, ARCH_CONVERT
, XFS_IBT_BLOCK(mp
));
1813 INT_SET(agi
->agi_level
, ARCH_CONVERT
, 1);
1814 INT_SET(agi
->agi_freecount
, ARCH_CONVERT
, 0);
1815 INT_SET(agi
->agi_newino
, ARCH_CONVERT
, NULLAGINO
);
1816 INT_SET(agi
->agi_dirino
, ARCH_CONVERT
, NULLAGINO
);
1817 for (i
= 0; i
< XFS_AGI_UNLINKED_BUCKETS
; i
++)
1818 INT_SET(agi
->agi_unlinked
[i
], ARCH_CONVERT
, NULLAGINO
);
1819 libxfs_writebuf(buf
, 1);
1822 * BNO btree root block
1824 buf
= libxfs_getbuf(mp
->m_dev
,
1825 XFS_AGB_TO_DADDR(mp
, agno
, XFS_BNO_BLOCK(mp
)),
1827 block
= XFS_BUF_TO_SBLOCK(buf
);
1828 bzero(block
, blocksize
);
1829 INT_SET(block
->bb_magic
, ARCH_CONVERT
, XFS_ABTB_MAGIC
);
1830 INT_SET(block
->bb_level
, ARCH_CONVERT
, 0);
1831 INT_SET(block
->bb_numrecs
, ARCH_CONVERT
, 1);
1832 INT_SET(block
->bb_leftsib
, ARCH_CONVERT
, NULLAGBLOCK
);
1833 INT_SET(block
->bb_rightsib
, ARCH_CONVERT
, NULLAGBLOCK
);
1834 arec
= XFS_BTREE_REC_ADDR(blocksize
, xfs_alloc
, block
, 1,
1835 XFS_BTREE_BLOCK_MAXRECS(blocksize
, xfs_alloc
, 1));
1836 INT_SET(arec
->ar_startblock
, ARCH_CONVERT
,
1837 XFS_PREALLOC_BLOCKS(mp
));
1838 if (loginternal
&& agno
== logagno
) {
1841 * Have to insert two records
1843 INT_SET(arec
->ar_blockcount
, ARCH_CONVERT
,
1844 (xfs_extlen_t
)(XFS_FSB_TO_AGBNO(
1846 - (INT_GET(arec
->ar_startblock
,
1849 INT_SET(nrec
->ar_startblock
, ARCH_CONVERT
,
1850 INT_GET(arec
->ar_startblock
,
1852 INT_GET(arec
->ar_blockcount
,
1855 INT_MOD(block
->bb_numrecs
, ARCH_CONVERT
, 1);
1857 INT_MOD(arec
->ar_startblock
, ARCH_CONVERT
, logblocks
);
1859 INT_SET(arec
->ar_blockcount
, ARCH_CONVERT
,
1860 (xfs_extlen_t
)(agsize
-
1861 INT_GET(arec
->ar_startblock
, ARCH_CONVERT
)));
1862 libxfs_writebuf(buf
, 1);
1865 * CNT btree root block
1867 buf
= libxfs_getbuf(mp
->m_dev
,
1868 XFS_AGB_TO_DADDR(mp
, agno
, XFS_CNT_BLOCK(mp
)),
1870 block
= XFS_BUF_TO_SBLOCK(buf
);
1871 bzero(block
, blocksize
);
1872 INT_SET(block
->bb_magic
, ARCH_CONVERT
, XFS_ABTC_MAGIC
);
1873 INT_SET(block
->bb_level
, ARCH_CONVERT
, 0);
1874 INT_SET(block
->bb_numrecs
, ARCH_CONVERT
, 1);
1875 INT_SET(block
->bb_leftsib
, ARCH_CONVERT
, NULLAGBLOCK
);
1876 INT_SET(block
->bb_rightsib
, ARCH_CONVERT
, NULLAGBLOCK
);
1877 arec
= XFS_BTREE_REC_ADDR(blocksize
, xfs_alloc
, block
, 1,
1878 XFS_BTREE_BLOCK_MAXRECS(blocksize
, xfs_alloc
, 1));
1879 INT_SET(arec
->ar_startblock
, ARCH_CONVERT
,
1880 XFS_PREALLOC_BLOCKS(mp
));
1881 if (loginternal
&& agno
== logagno
) {
1883 INT_SET(arec
->ar_blockcount
, ARCH_CONVERT
,
1884 (xfs_extlen_t
)( XFS_FSB_TO_AGBNO(
1885 mp
, logstart
) - (INT_GET(
1886 arec
->ar_startblock
, ARCH_CONVERT
)) )
1889 INT_SET(nrec
->ar_startblock
, ARCH_CONVERT
,
1890 INT_GET(arec
->ar_startblock
, ARCH_CONVERT
) +
1891 INT_GET(arec
->ar_blockcount
, ARCH_CONVERT
));
1893 INT_MOD(block
->bb_numrecs
, ARCH_CONVERT
, 1);
1895 INT_MOD(arec
->ar_startblock
, ARCH_CONVERT
, logblocks
);
1897 INT_SET(arec
->ar_blockcount
, ARCH_CONVERT
, (xfs_extlen_t
)
1898 (agsize
- INT_GET(arec
->ar_startblock
, ARCH_CONVERT
)));
1899 libxfs_writebuf(buf
, 1);
1901 * INO btree root block
1903 buf
= libxfs_getbuf(mp
->m_dev
,
1904 XFS_AGB_TO_DADDR(mp
, agno
, XFS_IBT_BLOCK(mp
)),
1906 block
= XFS_BUF_TO_SBLOCK(buf
);
1907 bzero(block
, blocksize
);
1908 INT_SET(block
->bb_magic
, ARCH_CONVERT
, XFS_IBT_MAGIC
);
1909 INT_SET(block
->bb_level
, ARCH_CONVERT
, 0);
1910 INT_SET(block
->bb_numrecs
, ARCH_CONVERT
, 0);
1911 INT_SET(block
->bb_leftsib
, ARCH_CONVERT
, NULLAGBLOCK
);
1912 INT_SET(block
->bb_rightsib
, ARCH_CONVERT
, NULLAGBLOCK
);
1913 libxfs_writebuf(buf
, 1);
1917 * Touch last block, make fs the right size if it's a file.
1919 buf
= libxfs_getbuf(mp
->m_dev
,
1920 (xfs_daddr_t
)XFS_FSB_TO_BB(mp
, dblocks
- 1LL), bsize
);
1921 bzero(XFS_BUF_PTR(buf
), blocksize
);
1922 libxfs_writebuf(buf
, 1);
1925 * Make sure we can write the last block in the realtime area.
1927 if (mp
->m_rtdev
&& rtblocks
> 0) {
1928 buf
= libxfs_getbuf(mp
->m_rtdev
,
1929 XFS_FSB_TO_BB(mp
, rtblocks
- 1LL), bsize
);
1930 bzero(XFS_BUF_PTR(buf
), blocksize
);
1931 libxfs_writebuf(buf
, 1);
1934 * BNO, CNT free block list
1936 for (agno
= 0; agno
< agcount
; agno
++) {
1937 xfs_alloc_arg_t args
;
1940 bzero(&args
, sizeof(args
));
1941 args
.tp
= tp
= libxfs_trans_alloc(mp
, 0);
1945 args
.minalignslop
= UINT_MAX
;
1946 args
.pag
= &mp
->m_perag
[agno
];
1947 if ((i
= libxfs_trans_reserve(tp
, worst_freelist
, 0, 0, 0, 0)))
1949 libxfs_alloc_fix_freelist(&args
, 0);
1950 libxfs_trans_commit(tp
, 0, NULL
);
1953 * Allocate the root inode and anything else in the proto file.
1955 mp
->m_rootip
= NULL
;
1956 parseproto(mp
, NULL
, &protostring
, NULL
);
1959 * protect ourselves against possible stupidity
1961 if (XFS_INO_TO_AGNO(mp
, mp
->m_sb
.sb_rootino
) != 0) {
1962 fprintf(stderr
, "%s: root inode not created in AG 0, "
1964 progname
, XFS_INO_TO_AGNO(mp
, mp
->m_sb
.sb_rootino
));
1969 * write out multiple copies of superblocks with the rootinode field set
1971 if (mp
->m_sb
.sb_agcount
> 1) {
1973 * the last superblock
1975 buf
= libxfs_readbuf(mp
->m_dev
,
1976 XFS_AGB_TO_DADDR(mp
, mp
->m_sb
.sb_agcount
-1,
1978 BTOBB(mp
->m_sb
.sb_sectsize
), 1);
1979 INT_SET((XFS_BUF_TO_SBP(buf
))->sb_rootino
,
1980 ARCH_CONVERT
, mp
->m_sb
.sb_rootino
);
1981 libxfs_writebuf(buf
, 1);
1983 * and one in the middle for luck
1985 if (mp
->m_sb
.sb_agcount
> 2) {
1986 buf
= libxfs_readbuf(mp
->m_dev
,
1987 XFS_AGB_TO_DADDR(mp
, (mp
->m_sb
.sb_agcount
-1)/2,
1989 BTOBB(mp
->m_sb
.sb_sectsize
), 1);
1990 INT_SET((XFS_BUF_TO_SBP(buf
))->sb_rootino
,
1991 ARCH_CONVERT
, mp
->m_sb
.sb_rootino
);
1992 libxfs_writebuf(buf
, 1);
1997 * Mark the filesystem ok.
1999 buf
= libxfs_getsb(mp
, 1);
2000 (XFS_BUF_TO_SBP(buf
))->sb_inprogress
= 0;
2001 libxfs_writebuf(buf
, 1);
2005 libxfs_device_close(xi
.rtdev
);
2006 if (xi
.logdev
&& xi
.logdev
!= xi
.ddev
)
2007 libxfs_device_close(xi
.logdev
);
2008 libxfs_device_close(xi
.ddev
);
2020 fprintf(stderr
, "Cannot specify both -%c %s and -%c %s\n",
2021 opt
, tab
[oldidx
], opt
, tab
[newidx
]);
2031 fprintf(stderr
, "Illegal value %s for -%s option\n", value
, opt
);
2039 return (i
& (i
- 1)) == 0;
2048 fprintf(stderr
, "-%c %s option requires a value\n", opt
, tab
[idx
]);
2058 fprintf(stderr
, "-%c ", opt
);
2060 fprintf(stderr
, "%s ", tab
[idx
]);
2061 fprintf(stderr
, "option respecified\n");
2070 fprintf(stderr
, "unknown option -%c %s\n", opt
, s
);
2080 xfs_trans_reservations_t
*tr
;
2082 tr
= &mp
->m_reservations
;
2084 for (rval
= 0, p
= (uint
*)tr
; p
< (uint
*)(tr
+ 1); p
++) {
2098 extern void usage(void);
2100 i
= strtoll(s
, &sp
, 0);
2101 if (i
== 0 && sp
== s
)
2106 if (*sp
== 'b' && sp
[1] == '\0') {
2108 return i
* blocksize
;
2110 fprintf(stderr
, "blocksize not available yet.\n");
2114 if (*sp
== 'k' && sp
[1] == '\0')
2116 if (*sp
== 'm' && sp
[1] == '\0')
2117 return 1024LL * 1024LL * i
;
2118 if (*sp
== 'g' && sp
[1] == '\0')
2119 return 1024LL * 1024LL * 1024LL * i
;
2126 fprintf(stderr
, "Usage: %s\n\
2127 /* blocksize */ [-b log=n|size=num]\n\
2128 /* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\
2129 sunit=value,swidth=value,unwritten=0|1,\n\
2130 su=value,sw=value]\n\
2131 /* inode size */ [-i log=n|perblock=n|size=num,maxpct=n]\n\
2132 /* log subvol */ [-l agnum=n,internal,size=num,logdev=xxx]\n\
2133 /* naming */ [-n log=n|size=num|version=n]\n\
2134 /* label */ [-L label (maximum 12 characters)]\n\
2135 /* prototype file */ [-p fname]\n\
2137 /* version */ [-V]\n\
2138 /* realtime subvol */ [-r extsize=num,size=num,rtdev=xxx]\n\
2140 <devicename> is required unless -d name=xxx is given.\n\
2141 Internal log by default, size is scaled from 1,000 blocks to 32,768 blocks\n\
2142 based on the filesystem size. Default log reaches its largest size at 1TB.\n\
2143 This can be overridden with the -l options or using a volume manager with a\n\
2145 <num> is xxx (bytes), or xxxb (blocks), or xxxk (xxx KB), or xxxm (xxx MB)\n\
2146 <value> is xxx (512 blocks).\n",