]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - mkfs/xfs_mkfs.c
Comment out automatic inode size selection code in mkfs
[thirdparty/xfsprogs-dev.git] / mkfs / xfs_mkfs.c
1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 *
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.
7 *
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.
11 *
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.
18 *
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.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33 #include <fstyp.h>
34 #include <stdio.h>
35 #include <volume.h>
36 #include <mountinfo.h>
37 #include <libxfs.h>
38
39 #include "xfs_mkfs.h"
40 #include "maxtrres.h"
41 #include "proto.h"
42
43 /*
44 * Prototypes for internal functions.
45 */
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);
53
54 /*
55 * option tables for getsubopt calls
56 */
57 char *bopts[] = {
58 #define B_LOG 0
59 "log",
60 #define B_SIZE 1
61 "size",
62 NULL
63 };
64
65 char *dopts[] = {
66 #define D_AGCOUNT 0
67 "agcount",
68 #define D_FILE 1
69 "file",
70 #define D_NAME 2
71 "name",
72 #define D_SIZE 3
73 "size",
74 #define D_SUNIT 4
75 "sunit",
76 #define D_SWIDTH 5
77 "swidth",
78 #define D_UNWRITTEN 6
79 "unwritten",
80 #define D_AGSIZE 7
81 "agsize",
82 #define D_SU 8
83 "su",
84 #define D_SW 9
85 "sw",
86 NULL
87 };
88
89 char *iopts[] = {
90 #define I_ALIGN 0
91 "align",
92 #define I_LOG 1
93 "log",
94 #define I_MAXPCT 2
95 "maxpct",
96 #define I_PERBLOCK 3
97 "perblock",
98 #define I_SIZE 4
99 "size",
100 NULL
101 };
102
103 char *lopts[] = {
104 #define L_AGNUM 0
105 "agnum",
106 #define L_INTERNAL 1
107 "internal",
108 #define L_SIZE 2
109 "size",
110 #define L_DEV 3
111 "logdev",
112 #ifdef MKFS_SIMULATION
113 #define L_FILE 4
114 "file",
115 #define L_NAME 5
116 "name",
117 #endif
118 NULL
119 };
120
121 char *nopts[] = {
122 #define N_LOG 0
123 "log",
124 #define N_SIZE 1
125 "size",
126 #define N_VERSION 2
127 "version",
128 NULL,
129 };
130
131 char *ropts[] = {
132 #define R_EXTSIZE 0
133 "extsize",
134 #define R_SIZE 1
135 "size",
136 #define R_DEV 2
137 "rtdev",
138 #ifdef MKFS_SIMULATION
139 #define R_FILE 3
140 "file",
141 #define R_NAME 4
142 "name",
143 #endif
144 NULL
145 };
146
147 /*
148 * max transaction reservation values
149 * version 1:
150 * first dimension log(blocksize) (base XFS_MIN_BLOCKSIZE_LOG)
151 * second dimension log(inodesize) (base XFS_DINODE_MIN_LOG)
152 * version 2:
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)
156 */
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)
160
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 },
176 };
177
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, } },
243 };
244
245 /*
246 * Use this before we have a superblock, else would use XFS_DTOBT
247 */
248 #define DTOBT(d) ((xfs_drfsbno_t)((d) >> (blocklog - BBSHIFT)))
249
250 /*
251 * Use this for block reservations needed for mkfs's conditions
252 * (basically no fragmentation).
253 */
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)))
259
260 static void
261 calc_stripe_factors(int dsu, int dsw, int *dsunit, int *dswidth)
262 {
263 if (*dsunit || *dswidth) {
264 if (dsu || dsw) {
265 fprintf(stderr,
266 "su/sw should not be used in conjunction with sunit/swidth\n");
267 usage();
268 }
269
270 if ((*dsunit && !*dswidth) || (!*dsunit && *dswidth)) {
271 fprintf(stderr,
272 "both sunit and swidth options have to be specified\n");
273 usage();
274 }
275 }
276
277 if (dsu || dsw) {
278 if (*dsunit || *dswidth) {
279 fprintf(stderr,
280 "sunit/swidth should not be used in conjunction with su/sw\n");
281 usage();
282 }
283
284 if ((dsu && !dsw) || (!dsu && dsw)) {
285 fprintf(stderr,
286 "both su and sw options have to be specified\n");
287 usage();
288 }
289
290 if (dsu % BBSIZE) {
291 fprintf(stderr, "su must be a multiple of %d\n",
292 BBSIZE);
293 usage();
294 }
295
296 *dsunit = (int)BTOBBT(dsu);
297 *dswidth = *dsunit * dsw;
298 }
299
300 if (*dsunit && (*dswidth % *dsunit != 0)) {
301 fprintf(stderr,
302 "stripe width (%d) has to be a multiple of the stripe unit (%d)\n",
303 *dswidth, *dsunit);
304 usage();
305 }
306 }
307
308 static int
309 get_default_blocksize(void)
310 {
311 size_t pagesize = getpagesize();
312 int i;
313
314 /* default is between 4K and 16K */
315 for (i = 12; i <= 16; i++)
316 if ((1 << i) == pagesize)
317 return pagesize;
318 return (1 << XFS_DFL_BLOCKSIZE_LOG);
319 }
320
321 static int
322 check_overwrite(char *device)
323 {
324 char *type;
325
326 if (device && *device) {
327 if ((type = fstype(device)) != NULL) {
328 fprintf(stderr,
329 "%s: %s appears to contain an existing filesystem (%s).\n",
330 progname, device, type);
331 return 1;
332 }
333 if ((type = pttype(device)) != NULL) {
334 fprintf(stderr,
335 "%s: %s appears to contain a partition table (%s).\n",
336 progname, device, type);
337 return 1;
338 }
339 }
340 return 0;
341 }
342
343
344 int
345 main(int argc, char **argv)
346 {
347 __uint64_t agcount;
348 xfs_agf_t *agf;
349 xfs_agi_t *agi;
350 xfs_agnumber_t agno;
351 __uint64_t agsize;
352 xfs_alloc_rec_t *arec;
353 xfs_btree_sblock_t *block;
354 int blflag;
355 int blocklog;
356 int blocksize;
357 int bsflag;
358 int bsize;
359 xfs_buf_t *buf;
360 int c;
361 int daflag;
362 int dasize;
363 xfs_drfsbno_t dblocks;
364 char *dfile;
365 int dirblocklog;
366 int dirblocksize;
367 int dirversion;
368 int do_overlap_checks;
369 char *dsize;
370 int dsu;
371 int dsw;
372 int dsunit;
373 int dswidth;
374 int extent_flagging;
375 int force_overwrite;
376 int i;
377 int iaflag;
378 int ilflag;
379 int imaxpct;
380 int imflag;
381 int inodelog;
382 int inodebits;
383 int inopblock;
384 int ipflag;
385 int isflag;
386 int isize;
387 char *label = NULL;
388 int laflag;
389 int lalign;
390 int ldflag;
391 int liflag;
392 xfs_agnumber_t logagno;
393 xfs_drfsbno_t logblocks;
394 char *logfile;
395 int loginternal;
396 char *logsize;
397 xfs_dfsbno_t logstart;
398 int lsflag;
399 int min_logblocks;
400 mnt_check_state_t *mnt_check_state;
401 int mnt_partition_count;
402 xfs_mount_t *mp;
403 xfs_mount_t mbuf;
404 xfs_extlen_t nbmblocks;
405 int nlflag;
406 int nodsflag;
407 xfs_alloc_rec_t *nrec;
408 int nsflag;
409 int nvflag;
410 char *p;
411 char *protofile;
412 char *protostring;
413 int qflag;
414 xfs_drfsbno_t rtblocks;
415 xfs_extlen_t rtextblocks;
416 xfs_drtbno_t rtextents;
417 char *rtextsize;
418 char *rtfile;
419 char *rtsize;
420 xfs_sb_t *sbp;
421 int sectlog;
422 __uint64_t tmp_agsize;
423 __uint64_t tmp_logblocks;
424 uuid_t uuid;
425 int worst_freelist;
426 libxfs_init_t xi;
427 int xlv_dsunit;
428 int xlv_dswidth;
429
430 progname = basename(argv[0]);
431 agcount = 8;
432 blflag = bsflag = 0;
433 dasize = daflag = 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;
439 loginternal = 1;
440 logagno = logblocks = rtblocks = 0;
441 nlflag = nsflag = nvflag = 0;
442 dirblocklog = dirblocksize = dirversion = 0;
443 qflag = 0;
444 imaxpct = inodelog = inopblock = isize = 0;
445 iaflag = XFS_IFLAG_ALIGN;
446 bzero(&xi, sizeof(xi));
447 xi.notvolok = 1;
448 xi.setblksize = 1;
449 dfile = logfile = rtfile = NULL;
450 dsize = logsize = rtsize = rtextsize = protofile = NULL;
451 opterr = 0;
452 dsu = dsw = dsunit = dswidth = nodsflag = lalign = 0;
453 do_overlap_checks = 1;
454 extent_flagging = 0;
455 force_overwrite = 0;
456 worst_freelist = 0;
457
458 while ((c = getopt(argc, argv, "b:d:i:l:L:n:p:qr:CfV")) != EOF) {
459 switch (c) {
460 case 'C':
461 do_overlap_checks = 0;
462 break;
463 case 'f':
464 force_overwrite = 1;
465 break;
466 case 'b':
467 p = optarg;
468 while (*p != '\0') {
469 char *value;
470
471 switch (getsubopt(&p, (constpp)bopts, &value)) {
472 case B_LOG:
473 if (!value)
474 reqval('b', bopts, B_LOG);
475 if (blflag)
476 respec('b', bopts, B_LOG);
477 if (bsflag)
478 conflict('b', bopts, B_SIZE,
479 B_LOG);
480 blocklog = atoi(value);
481 if (blocklog <= 0)
482 illegal(value, "b log");
483 blocksize = 1 << blocklog;
484 blflag = 1;
485 break;
486 case B_SIZE:
487 if (!value)
488 reqval('b', bopts, B_SIZE);
489 if (bsflag)
490 respec('b', bopts, B_SIZE);
491 if (blflag)
492 conflict('b', bopts, B_LOG,
493 B_SIZE);
494 blocksize = cvtnum(0, value);
495 if (blocksize <= 0 ||
496 !ispow2(blocksize))
497 illegal(value, "b size");
498 blocklog = libxfs_highbit32(blocksize);
499 bsflag = 1;
500 break;
501 default:
502 unknown('b', value);
503 }
504 }
505 break;
506 case 'd':
507 p = optarg;
508 while (*p != '\0') {
509 char *value;
510
511 switch (getsubopt(&p, (constpp)dopts, &value)) {
512 case D_AGCOUNT:
513 if (!value)
514 reqval('d', dopts, D_AGCOUNT);
515 if (daflag)
516 respec('d', dopts, D_AGCOUNT);
517 agcount = (__uint64_t)atoll(value);
518 if ((__int64_t)agcount <= 0)
519 illegal(value, "d agcount");
520 daflag = 1;
521 break;
522 case D_AGSIZE:
523 if (!value)
524 reqval('d', dopts, D_AGSIZE);
525 if (dasize)
526 respec('d', dopts, D_AGSIZE);
527 if (blflag || bsflag)
528 agsize = cvtnum(blocksize,
529 value);
530 else
531 agsize = cvtnum(0, value);
532 dasize = 1;
533 break;
534 case D_FILE:
535 if (!value)
536 value = "1";
537 xi.disfile = atoi(value);
538 if (xi.disfile < 0 || xi.disfile > 1)
539 illegal(value, "d file");
540 if (xi.disfile)
541 xi.dcreat = 1;
542 break;
543 case D_NAME:
544 if (!value)
545 reqval('d', dopts, D_NAME);
546 if (xi.dname)
547 respec('d', dopts, D_NAME);
548 xi.dname = value;
549 break;
550 case D_SIZE:
551 if (!value)
552 reqval('d', dopts, D_SIZE);
553 if (dsize)
554 respec('d', dopts, D_SIZE);
555 dsize = value;
556 break;
557 case D_SUNIT:
558 if (!value)
559 reqval('d', dopts, D_SUNIT);
560 if (dsunit)
561 respec('d', dopts, D_SUNIT);
562 if (blflag || bsflag)
563 dsunit = cvtnum(blocksize,
564 value);
565 else
566 dsunit = cvtnum(0, value);
567 break;
568 case D_SWIDTH:
569 if (!value)
570 reqval('d', dopts, D_SWIDTH);
571 if (dswidth)
572 respec('d', dopts, D_SWIDTH);
573 if (blflag || bsflag)
574 dswidth = cvtnum(blocksize,
575 value);
576 else
577 dswidth = cvtnum(0, value);
578 break;
579 case D_SU:
580 if (!value)
581 reqval('d', dopts, D_SU);
582 if (dsu)
583 respec('d', dopts, D_SU);
584 dsu = cvtnum(0, value);
585 break;
586 case D_SW:
587 if (!value)
588 reqval('d', dopts, D_SW);
589 if (dsw)
590 respec('d', dopts, D_SW);
591 dsw = cvtnum(0, value);
592 break;
593 case D_UNWRITTEN:
594 if (!value)
595 reqval('d', dopts, D_UNWRITTEN);
596 i = atoi(value);
597 if (i < 0 || i > 1)
598 illegal(value, "d unwritten");
599 extent_flagging = i;
600 break;
601 default:
602 unknown('d', value);
603 }
604 }
605 break;
606 case 'i':
607 p = optarg;
608 while (*p != '\0') {
609 char *value;
610
611 switch (getsubopt(&p, (constpp)iopts, &value)) {
612 case I_ALIGN:
613 if (!value)
614 value = "1";
615 iaflag = atoi(value);
616 if (iaflag < 0 || iaflag > 1)
617 illegal(value, "i align");
618 break;
619 case I_LOG:
620 if (!value)
621 reqval('i', iopts, I_LOG);
622 if (ilflag)
623 respec('i', iopts, I_LOG);
624 if (ipflag)
625 conflict('i', iopts, I_PERBLOCK,
626 I_LOG);
627 if (isflag)
628 conflict('i', iopts, I_SIZE,
629 I_LOG);
630 inodelog = atoi(value);
631 if (inodelog <= 0)
632 illegal(value, "i log");
633 isize = 1 << inodelog;
634 ilflag = 1;
635 break;
636 case I_MAXPCT:
637 if (!value)
638 reqval('i', iopts, I_MAXPCT);
639 if (imflag)
640 respec('i', iopts, I_MAXPCT);
641 imaxpct = atoi(value);
642 if (imaxpct < 0 || imaxpct > 100)
643 illegal(value, "i maxpct");
644 imflag = 1;
645 break;
646 case I_PERBLOCK:
647 if (!value)
648 reqval('i', iopts, I_PERBLOCK);
649 if (ilflag)
650 conflict('i', iopts, I_LOG,
651 I_PERBLOCK);
652 if (ipflag)
653 respec('i', iopts, I_PERBLOCK);
654 if (isflag)
655 conflict('i', iopts, I_SIZE,
656 I_PERBLOCK);
657 inopblock = atoi(value);
658 if (inopblock <
659 XFS_MIN_INODE_PERBLOCK ||
660 !ispow2(inopblock))
661 illegal(value, "i perblock");
662 ipflag = 1;
663 break;
664 case I_SIZE:
665 if (!value)
666 reqval('i', iopts, I_SIZE);
667 if (ilflag)
668 conflict('i', iopts, I_LOG,
669 I_SIZE);
670 if (ipflag)
671 conflict('i', iopts, I_PERBLOCK,
672 I_SIZE);
673 if (isflag)
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);
679 isflag = 1;
680 break;
681 default:
682 unknown('i', value);
683 }
684 }
685 break;
686 case 'l':
687 p = optarg;
688 while (*p != '\0') {
689 char *value;
690
691 switch (getsubopt(&p, (constpp)lopts, &value)) {
692 case L_AGNUM:
693 if (laflag)
694 respec('l', lopts, L_AGNUM);
695
696 if (ldflag)
697 conflict('l', lopts, L_AGNUM, L_DEV);
698
699 logagno = atoi(value);
700 laflag = 1;
701 break;
702 case L_DEV:
703 if (!value) {
704 fprintf (stderr, "Must specify log device\n");
705 usage();
706 }
707
708 if (laflag)
709 conflict('l', lopts, L_AGNUM, L_DEV);
710
711 if (liflag)
712 conflict('l', lopts, L_INTERNAL, L_DEV);
713
714 ldflag = 1;
715 loginternal = 0;
716 logfile = value;
717 xi.logname = value;
718 break;
719 #ifdef HAVE_VOLUME_MANAGER
720 case L_FILE:
721 if (!value)
722 value = "1";
723 if (loginternal)
724 conflict('l', lopts, L_INTERNAL,
725 L_FILE);
726 xi.lisfile = atoi(value);
727 if (xi.lisfile < 0 || xi.lisfile > 1)
728 illegal(value, "l file");
729 if (xi.lisfile)
730 xi.lcreat = 1;
731 break;
732 #endif
733 case L_INTERNAL:
734 if (!value)
735 value = "1";
736
737 if (ldflag)
738 conflict('l', lopts, L_INTERNAL, L_DEV);
739 #ifdef HAVE_VOLUME_MANAGER
740 if (xi.logname)
741 conflict('l', lopts, L_NAME,
742 L_INTERNAL);
743 if (xi.lisfile)
744 conflict('l', lopts, L_FILE,
745 L_INTERNAL);
746 #endif
747 if (liflag)
748 respec('l', lopts, L_INTERNAL);
749 loginternal = atoi(value);
750 if (loginternal < 0 || loginternal > 1)
751 illegal(value, "l internal");
752 liflag = 1;
753 break;
754 #ifdef HAVE_VOLUME_MANAGER
755 case L_NAME:
756 if (!value)
757 reqval('l', lopts, L_NAME);
758 if (loginternal)
759 conflict('l', lopts, L_INTERNAL,
760 L_NAME);
761 if (xi.logname)
762 respec('l', lopts, L_NAME);
763 xi.logname = value;
764 break;
765 #endif
766 case L_SIZE:
767 if (!value)
768 reqval('l', lopts, L_SIZE);
769 if (logsize)
770 respec('l', lopts, L_SIZE);
771 logsize = value;
772 lsflag = 1;
773 break;
774 default:
775 unknown('l', value);
776 }
777 }
778 break;
779 case 'L':
780 if (strlen(optarg) > sizeof(sbp->sb_fname))
781 illegal(optarg, "L");
782 label = optarg;
783 break;
784 case 'n':
785 p = optarg;
786 while (*p != '\0') {
787 char *value;
788
789 switch (getsubopt(&p, (constpp)nopts, &value)) {
790 case N_LOG:
791 if (!value)
792 reqval('n', nopts, N_LOG);
793 if (nlflag)
794 respec('n', nopts, N_LOG);
795 if (nsflag)
796 conflict('n', nopts, N_SIZE,
797 N_LOG);
798 dirblocklog = atoi(value);
799 if (dirblocklog <= 0)
800 illegal(value, "n log");
801 dirblocksize = 1 << dirblocklog;
802 nlflag = 1;
803 break;
804 case N_SIZE:
805 if (!value)
806 reqval('n', nopts, N_SIZE);
807 if (nsflag)
808 respec('n', nopts, N_SIZE);
809 if (nlflag)
810 conflict('n', nopts, N_LOG,
811 N_SIZE);
812 dirblocksize = cvtnum(0, value);
813 if (dirblocksize <= 0 ||
814 !ispow2(dirblocksize))
815 illegal(value, "n size");
816 dirblocklog =
817 libxfs_highbit32(dirblocksize);
818 nsflag = 1;
819 break;
820 case N_VERSION:
821 if (!value)
822 reqval('n', nopts, N_VERSION);
823 if (nvflag)
824 respec('n', nopts, N_VERSION);
825 dirversion = atoi(value);
826 if (dirversion < 1 || dirversion > 2)
827 illegal(value, "n version");
828 nvflag = 1;
829 break;
830 default:
831 unknown('n', value);
832 }
833 }
834 break;
835 case 'p':
836 if (protofile)
837 respec('p', 0, 0);
838 protofile = optarg;
839 break;
840 case 'q':
841 qflag = 1;
842 break;
843 case 'r':
844 p = optarg;
845 while (*p != '\0') {
846 char *value;
847
848 switch (getsubopt(&p, (constpp)ropts, &value)) {
849 case R_EXTSIZE:
850 if (!value)
851 reqval('r', ropts, R_EXTSIZE);
852 if (rtextsize)
853 respec('r', ropts, R_EXTSIZE);
854 rtextsize = value;
855 break;
856 case R_DEV:
857 if (!value)
858 reqval('r', ropts, R_DEV);
859 xi.rtname = value;
860 break;
861 #ifdef HAVE_VOLUME_MANAGER
862 case R_FILE:
863 if (!value)
864 value = "1";
865 xi.risfile = atoi(value);
866 if (xi.risfile < 0 || xi.risfile > 1)
867 illegal(value, "r file");
868 if (xi.risfile)
869 xi.rcreat = 1;
870 break;
871 case R_NAME:
872 if (!value)
873 reqval('r', ropts, R_NAME);
874 if (xi.rtname)
875 respec('r', ropts, R_NAME);
876 xi.rtname = value;
877 break;
878 #endif
879 case R_SIZE:
880 if (!value)
881 reqval('r', ropts, R_SIZE);
882 if (rtsize)
883 respec('r', ropts, R_SIZE);
884 rtsize = value;
885 break;
886
887 default:
888 unknown('r', value);
889 }
890 }
891 break;
892 case 'V':
893 printf("%s version %s\n", progname, VERSION);
894 break;
895 case '?':
896 unknown(optopt, "");
897 }
898 }
899 if (argc - optind > 1) {
900 fprintf(stderr, "extra arguments\n");
901 usage();
902 } else if (argc - optind == 1) {
903 dfile = xi.volname = argv[optind];
904 if (xi.dname) {
905 fprintf(stderr,
906 "cannot specify both %s and -d name=%s\n",
907 xi.volname, xi.dname);
908 usage();
909 }
910 } else
911 dfile = 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);
915 usage();
916 }
917 if (!nvflag)
918 dirversion = (nsflag || nlflag) ? 2 : XFS_DFL_DIR_VERSION;
919 switch (dirversion) {
920 case 1:
921 if ((nsflag || nlflag) && dirblocklog != blocklog) {
922 fprintf(stderr, "illegal directory block size %d\n",
923 dirblocksize);
924 usage();
925 }
926 break;
927 case 2:
928 if (nsflag || nlflag) {
929 if (dirblocksize < blocksize ||
930 dirblocksize > XFS_MAX_BLOCKSIZE) {
931 fprintf(stderr,
932 "illegal directory block size %d\n",
933 dirblocksize);
934 usage();
935 }
936 } else {
937 if (blocksize < (1 << XFS_MIN_REC_DIRSIZE))
938 dirblocklog = XFS_MIN_REC_DIRSIZE;
939 else
940 dirblocklog = blocklog;
941 dirblocksize = 1 << dirblocklog;
942 }
943 break;
944 }
945
946 if (daflag && dasize) {
947 fprintf(stderr,
948 "both -d agcount= and agsize= specified, use one or the other\n");
949 usage();
950 }
951
952 if (!daflag)
953 agcount = 8;
954
955 if (xi.disfile && (!dsize || !xi.dname)) {
956 fprintf(stderr,
957 "if -d file then -d name and -d size are required\n");
958 usage();
959 }
960 if (dsize) {
961 __uint64_t dbytes;
962
963 dbytes = cvtnum(blocksize, dsize);
964 if (dbytes % XFS_MIN_BLOCKSIZE) {
965 fprintf(stderr,
966 "illegal data length %lld, not a multiple of %d\n",
967 (long long)dbytes, XFS_MIN_BLOCKSIZE);
968 usage();
969 }
970 dblocks = (xfs_drfsbno_t)(dbytes >> blocklog);
971 if (dbytes % blocksize)
972 fprintf(stderr,
973 "warning: data length %lld not a multiple of %d, truncated to %lld\n",
974 (long long)dbytes, blocksize,
975 (long long)(dblocks << blocklog));
976 }
977 if (ipflag) {
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;
983 }
984 #ifdef HAVE_VOLUME_MANAGER
985 if (xi.lisfile && (!logsize || !xi.logname)) {
986 fprintf(stderr,
987 "if -l file then -l name and -l size are required\n");
988 usage();
989 }
990 #endif
991 if (logsize) {
992 __uint64_t logbytes;
993
994 logbytes = cvtnum(blocksize, logsize);
995 if (logbytes % XFS_MIN_BLOCKSIZE) {
996 fprintf(stderr,
997 "illegal log length %lld, not a multiple of %d\n",
998 (long long)logbytes, XFS_MIN_BLOCKSIZE);
999 usage();
1000 }
1001 logblocks = (xfs_drfsbno_t)(logbytes >> blocklog);
1002 if (logbytes % blocksize)
1003 fprintf(stderr,
1004 "warning: log length %lld not a multiple of %d, truncated to %lld\n",
1005 (long long)logbytes, blocksize,
1006 (long long)(logblocks << blocklog));
1007 }
1008 #ifdef HAVE_VOLUME_MANAGER
1009 if (xi.risfile && (!rtsize || !xi.rtname)) {
1010 fprintf(stderr,
1011 "if -r file then -r name and -r size are required\n");
1012 usage();
1013 }
1014 #endif
1015 if (rtsize) {
1016 __uint64_t rtbytes;
1017
1018 rtbytes = cvtnum(blocksize, rtsize);
1019 if (rtbytes % XFS_MIN_BLOCKSIZE) {
1020 fprintf(stderr,
1021 "illegal rt length %lld, not a multiple of %d\n",
1022 (long long)rtbytes, XFS_MIN_BLOCKSIZE);
1023 usage();
1024 }
1025 rtblocks = (xfs_drfsbno_t)(rtbytes >> blocklog);
1026 if (rtbytes % blocksize)
1027 fprintf(stderr,
1028 "warning: rt length %lld not a multiple of %d, truncated to %lld\n",
1029 (long long)rtbytes, blocksize,
1030 (long long)(rtblocks << blocklog));
1031 }
1032 /*
1033 * If specified, check rt extent size against its constraints.
1034 */
1035 if (rtextsize) {
1036 __uint64_t rtextbytes;
1037
1038 rtextbytes = cvtnum(blocksize, rtextsize);
1039 if (rtextbytes % blocksize) {
1040 fprintf(stderr,
1041 "illegal rt extent size %lld, not a multiple of %d\n",
1042 (long long)rtextbytes, blocksize);
1043 usage();
1044 }
1045 if (rtextbytes > XFS_MAX_RTEXTSIZE) {
1046 fprintf(stderr,
1047 "rt extent size %s too large, maximum %d\n",
1048 rtextsize, XFS_MAX_RTEXTSIZE);
1049 usage();
1050 }
1051 if (rtextbytes < XFS_MIN_RTEXTSIZE) {
1052 fprintf(stderr,
1053 "rt extent size %s too small, minimum %d\n",
1054 rtextsize, XFS_MIN_RTEXTSIZE);
1055 usage();
1056 }
1057 rtextblocks = (xfs_extlen_t)(rtextbytes >> blocklog);
1058 } else {
1059 /*
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.
1063 */
1064 int dummy1, rswidth;
1065 __uint64_t rtextbytes;
1066 dummy1 = rswidth = 0;
1067
1068 if (!xi.disfile)
1069 get_subvol_stripe_wrapper(dfile, SVTYPE_RT, &dummy1,
1070 &rswidth);
1071
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;
1079 } else {
1080 rtextblocks = XFS_DFL_RTEXTSIZE >> blocklog;
1081 }
1082 } else
1083 rtextblocks = XFS_DFL_RTEXTSIZE >> blocklog;
1084 }
1085
1086 /*
1087 * Check some argument sizes against mins, maxes.
1088 */
1089 if (isize > blocksize / XFS_MIN_INODE_PERBLOCK ||
1090 isize < XFS_DINODE_MIN_SIZE ||
1091 isize > XFS_DINODE_MAX_SIZE) {
1092 int maxsz;
1093
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)
1098 fprintf(stderr,
1099 "allowable inode size with %d byte blocks is %d\n",
1100 blocksize, XFS_DINODE_MIN_SIZE);
1101 else
1102 fprintf(stderr,
1103 "allowable inode size with %d byte blocks is between %d and %d\n",
1104 blocksize, XFS_DINODE_MIN_SIZE, maxsz);
1105 usage();
1106 }
1107
1108 calc_stripe_factors(dsu, dsw, &dsunit, &dswidth);
1109
1110 /* other global variables */
1111 sectlog = 9; /* i.e. 512 bytes */
1112
1113 /*
1114 * Initialize. This will open the log and rt devices as well.
1115 */
1116 if (!libxfs_init(&xi))
1117 usage();
1118 if (!xi.ddev) {
1119 fprintf(stderr, "no device name given in argument list\n");
1120 usage();
1121 }
1122
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",
1129 progname);
1130 exit(1);
1131 }
1132 }
1133
1134 if (!xi.disfile && do_overlap_checks) {
1135 /*
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()
1139 */
1140
1141 if (mnt_check_init(&mnt_check_state) == -1) {
1142 fprintf(stderr,
1143 "unable to initialize mount checking "
1144 "routines, bypassing protection checks.\n");
1145 } else {
1146 mnt_partition_count = mnt_find_mount_conflicts(
1147 mnt_check_state, dfile);
1148
1149 /*
1150 * ignore -1 return codes, since 3rd party devices
1151 * may not be part of hinv.
1152 */
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",
1157 progname, dfile);
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",
1162 progname, dfile);
1163 } else {
1164 mnt_causes_show(mnt_check_state, stderr, progname);
1165 }
1166 fprintf(stderr, "\n");
1167 fflush(stderr);
1168 mnt_plist_show(mnt_check_state, stderr, progname);
1169 fprintf(stderr, "\n");
1170 }
1171 mnt_check_end(mnt_check_state);
1172 if (mnt_partition_count > 0) {
1173 usage();
1174 }
1175 }
1176 }
1177
1178 if (!liflag && !ldflag)
1179 loginternal = xi.logdev == 0;
1180 if (xi.logname)
1181 logfile = xi.logname;
1182 else if (loginternal)
1183 logfile = "internal log";
1184 else if (xi.volname && xi.logdev)
1185 logfile = "volume log";
1186 else if (!ldflag) {
1187 fprintf(stderr, "no log subvolume or internal log\n");
1188 usage();
1189 }
1190 if (xi.rtname)
1191 rtfile = xi.rtname;
1192 else
1193 if (xi.volname && xi.rtdev)
1194 rtfile = "volume rt";
1195 else if (!xi.rtdev)
1196 rtfile = "none";
1197 if (dsize && xi.dsize > 0 && dblocks > DTOBT(xi.dsize)) {
1198 fprintf(stderr,
1199 "size %s specified for data subvolume is too large, maximum is %lld blocks\n",
1200 dsize, (long long)DTOBT(xi.dsize));
1201 usage();
1202 } else if (!dsize && xi.dsize > 0)
1203 dblocks = DTOBT(xi.dsize);
1204 else if (!dsize) {
1205 fprintf(stderr, "can't get size of data subvolume\n");
1206 usage();
1207 }
1208 if (dblocks < XFS_MIN_DATA_BLOCKS) {
1209 fprintf(stderr,
1210 "size %lld of data subvolume is too small, minimum %d blocks\n",
1211 (long long)dblocks, XFS_MIN_DATA_BLOCKS);
1212 usage();
1213 }
1214 if (xi.logdev && loginternal) {
1215 fprintf(stderr, "can't have both external and internal logs\n");
1216 usage();
1217 }
1218 if (dirversion == 1)
1219 i = max_trres_v1[blocklog - XFS_MIN_BLOCKSIZE_LOG]
1220 [inodelog - XFS_DINODE_MIN_LOG];
1221 else
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)) {
1227 fprintf(stderr,
1228 "size %s specified for log subvolume is too large, maximum is %lld blocks\n",
1229 logsize, (long long)DTOBT(xi.logBBsize));
1230 usage();
1231 } else if (!logsize && xi.logBBsize > 0)
1232 logblocks = DTOBT(xi.logBBsize);
1233 else if (logsize && !xi.logdev && !loginternal) {
1234 fprintf(stderr,
1235 "size specified for non-existent log subvolume\n");
1236 usage();
1237 } else if (loginternal && logsize && logblocks >= dblocks) {
1238 fprintf(stderr, "size %lld too large for internal log\n",
1239 (long long)logblocks);
1240 usage();
1241 } else if (!loginternal && !xi.logdev)
1242 logblocks = 0;
1243 else if (loginternal && !logsize) {
1244 /*
1245 * logblocks grows from min_logblocks to XFS_MAX_LOG_BLOCKS
1246 * at 1TB
1247 *
1248 * 8192 = 1TB / MAX_LOG_BYTES
1249 */
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;
1258 }
1259 }
1260 if (logblocks < min_logblocks) {
1261 fprintf(stderr,
1262 "log size %lld blocks too small, minimum size is %d blocks\n",
1263 (long long)logblocks, min_logblocks);
1264 usage();
1265 }
1266 if (logblocks > XFS_MAX_LOG_BLOCKS) {
1267 fprintf(stderr,
1268 "log size %lld blocks too large, maximum size is %d blocks\n",
1269 (long long)logblocks, XFS_MAX_LOG_BLOCKS);
1270 usage();
1271 }
1272 if ((logblocks << blocklog) > XFS_MAX_LOG_BYTES) {
1273 fprintf(stderr,
1274 "log size %lld bytes too large, maximum size is %d bytes\n",
1275 (long long)(logblocks << blocklog), XFS_MAX_LOG_BYTES);
1276 usage();
1277 }
1278 if (rtsize && xi.rtsize > 0 && rtblocks > DTOBT(xi.rtsize)) {
1279 fprintf(stderr,
1280 "size %s specified for rt subvolume is too large, maximum is %lld blocks\n",
1281 rtsize, (long long)DTOBT(xi.rtsize));
1282 usage();
1283 } else if (!rtsize && xi.rtsize > 0)
1284 rtblocks = DTOBT(xi.rtsize);
1285 else if (rtsize && !xi.rtdev) {
1286 fprintf(stderr,
1287 "size specified for non-existent rt subvolume\n");
1288 usage();
1289 }
1290 if (xi.rtdev) {
1291 rtextents = rtblocks / rtextblocks;
1292 nbmblocks = (xfs_extlen_t)howmany(rtextents, NBBY * blocksize);
1293 } else {
1294 rtextents = rtblocks = 0;
1295 nbmblocks = 0;
1296 }
1297
1298 if (dasize) {
1299 /*
1300 * If the specified agsize isn't a multiple of fs blks,
1301 * complain.
1302 */
1303 if (agsize % blocksize) {
1304 fprintf(stderr,
1305 "agsize (%lld) not a multiple of fs blk size (%d)\n",
1306 (long long)agsize, blocksize);
1307 usage();
1308 }
1309
1310 agsize /= blocksize;
1311
1312 /*
1313 * If the specified agsize is too small, or too large,
1314 * complain.
1315 */
1316 if (agsize < XFS_AG_MIN_BLOCKS(blocklog)) {
1317 fprintf(stderr,
1318 "agsize (%lldb) too small, need at least %lld blocks\n",
1319 (long long)agsize,
1320 (long long)XFS_AG_MIN_BLOCKS(blocklog));
1321 usage();
1322 }
1323
1324 if (agsize > XFS_AG_MAX_BLOCKS(blocklog)) {
1325 fprintf(stderr,
1326 "agsize (%lldb) too big, maximum is %lld blocks\n",
1327 (long long)agsize,
1328 (long long)XFS_AG_MAX_BLOCKS(blocklog));
1329 usage();
1330 }
1331
1332 if (agsize > dblocks) {
1333 fprintf(stderr,
1334 "agsize (%lldb) too big, data area is %lld blocks\n",
1335 (long long)agsize, (long long)dblocks);
1336 usage();
1337 }
1338
1339 agcount = dblocks / agsize + (dblocks % agsize != 0);
1340 } else {
1341 agsize = dblocks / agcount + (dblocks % agcount != 0);
1342 }
1343
1344 /*
1345 * If the ag size is too small, complain if agcount/agsize was
1346 * specified, and fix it otherwise.
1347 */
1348 if (agsize < XFS_AG_MIN_BLOCKS(blocklog)) {
1349 if (daflag || dasize) {
1350 fprintf(stderr,
1351 "too many allocation groups for size = %lld\n",
1352 (long long)agsize);
1353 fprintf(stderr, "need at most %lld allocation groups\n",
1354 (long long)
1355 (dblocks / XFS_AG_MIN_BLOCKS(blocklog) +
1356 (dblocks % XFS_AG_MIN_BLOCKS(blocklog) != 0)));
1357 usage();
1358 }
1359 agsize = XFS_AG_MIN_BLOCKS(blocklog);
1360 if (dblocks < agsize)
1361 agcount = 1;
1362 else
1363 agcount = dblocks / agsize;
1364
1365 agsize = dblocks / agcount + (dblocks % agcount != 0);
1366 }
1367
1368 /*
1369 * If the ag size is too large, complain if agcount/agsize was
1370 * specified, and fix it otherwise.
1371 */
1372 else if (agsize > XFS_AG_MAX_BLOCKS(blocklog)) {
1373 if (daflag || dasize) {
1374 fprintf(stderr, "too few allocation groups for size = %lld\n",
1375 (long long)agsize);
1376 fprintf(stderr,
1377 "need at least %lld allocation groups\n",
1378 (long long)
1379 (dblocks / XFS_AG_MAX_BLOCKS(blocklog) +
1380 (dblocks % XFS_AG_MAX_BLOCKS(blocklog) != 0)));
1381 usage();
1382 }
1383 agsize = XFS_AG_MAX_BLOCKS(blocklog);
1384 agcount = dblocks / agsize + (dblocks % agsize != 0);
1385 }
1386
1387 /*
1388 * if user set the AG size, and if the last AG is too small,
1389 * reduce the filesystem size and drop the blocks.
1390 */
1391 if (!daflag &&
1392 (dblocks % agsize < XFS_AG_MIN_BLOCKS(blocklog))) {
1393 dblocks -= dblocks % agsize;
1394 }
1395
1396 /*
1397 * If agcount was not specified, and agsize is larger than
1398 * we'd like, make it the size we want.
1399 */
1400 if (!daflag && !dasize &&
1401 (agsize > XFS_AG_BEST_BLOCKS(blocklog,dblocks))) {
1402 agsize = XFS_AG_BEST_BLOCKS(blocklog,dblocks);
1403 /*
1404 * If the last AG is too small, reduce the filesystem size
1405 * and drop the blocks.
1406 */
1407 if (dblocks % agsize < XFS_AG_MIN_BLOCKS(blocklog)) {
1408 dblocks -= dblocks % agsize;
1409 }
1410 agcount = dblocks / agsize + (dblocks % agsize != 0);
1411 }
1412
1413 /*
1414 * If agcount is too large, make it smaller.
1415 */
1416 if (agcount > XFS_MAX_AGNUMBER + 1) {
1417 agcount = XFS_MAX_AGNUMBER + 1;
1418 agsize = dblocks / agcount + (dblocks % agcount != 0);
1419
1420 if (dasize || daflag)
1421 fprintf(stderr,
1422 "agsize set to %lld, agcount %lld > max (%lld)\n",
1423 (long long)agsize, (long long)agcount,
1424 (long long)XFS_MAX_AGNUMBER+1);
1425
1426 if (agsize > XFS_AG_MAX_BLOCKS(blocklog)) {
1427 /*
1428 * We're confused.
1429 */
1430 fprintf(stderr, "%s: can't compute agsize/agcount\n",
1431 progname);
1432 exit(1);
1433 }
1434 }
1435
1436 xlv_dsunit = xlv_dswidth = 0;
1437 if (!xi.disfile)
1438 get_subvol_stripe_wrapper(dfile, SVTYPE_DATA, &xlv_dsunit,
1439 &xlv_dswidth);
1440 if (dsunit) {
1441
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);
1446 exit(1);
1447 }
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);
1452 exit(1);
1453 }
1454 } else {
1455 dsunit = xlv_dsunit;
1456 dswidth = xlv_dswidth;
1457 nodsflag = 1;
1458 }
1459
1460 /*
1461 * If dsunit is a multiple of fs blocksize, then check that is a
1462 * multiple of the agsize too
1463 */
1464 if (dsunit && !(BBTOB(dsunit) % blocksize) &&
1465 dswidth && !(BBTOB(dswidth) % blocksize)) {
1466
1467 /* convert from 512 byte blocks to fs blocksize */
1468 dsunit = DTOBT(dsunit);
1469 dswidth = DTOBT(dswidth);
1470
1471 /*
1472 * agsize is not a multiple of dsunit
1473 */
1474 if ((agsize % dsunit) != 0) {
1475 /*
1476 * Round up to stripe unit boundary. Also make sure
1477 * that agsize is still larger than
1478 * XFS_AG_MIN_BLOCKS(blocklog)
1479 */
1480 tmp_agsize = ((agsize + (dsunit - 1))/ dsunit) * dsunit;
1481 /*
1482 * Round down to stripe unit boundary if rounding up
1483 * created an AG size that is larger than the AG max.
1484 */
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)) &&
1489 !daflag) {
1490 agsize = tmp_agsize;
1491 agcount = dblocks/agsize +
1492 (dblocks % agsize != 0);
1493 if (dasize || daflag)
1494 fprintf(stderr,
1495 "agsize rounded to %lld, swidth = %d\n",
1496 (long long)agsize, dswidth);
1497 } else {
1498 if (nodsflag) {
1499 dsunit = dswidth = 0;
1500 } else {
1501 fprintf(stderr,
1502 "Allocation group size %lld is not a multiple of the stripe unit %d\n",
1503 (long long)agsize, dsunit);
1504 exit(1);
1505 }
1506 }
1507 }
1508 } else {
1509 if (nodsflag)
1510 dsunit = dswidth = 0;
1511 else {
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);
1515 exit(1);
1516 }
1517 }
1518
1519 #if 0
1520 /*
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.
1524 */
1525
1526 inodebits = (libxfs_highbit32(blocksize/isize - 1) + 1)
1527 + (libxfs_highbit64(agsize - 1) + 1)
1528 + (libxfs_highbit64(agcount - 1) + 1);
1529
1530 if (inodebits > XFS_MAX_INODE_SIG_BITS) {
1531
1532 int new_isize;
1533 int new_isize_ok;
1534
1535 new_isize = isize << (inodebits - XFS_MAX_INODE_SIG_BITS);
1536
1537 new_isize_ok = (new_isize <= blocksize / XFS_MIN_INODE_PERBLOCK
1538 && new_isize <= XFS_DINODE_MAX_SIZE);
1539
1540 if (ilflag + ipflag + isflag == 0) {
1541 /*
1542 * If we didn't specify inode size, just bump it up
1543 * unless we can't go far enough.
1544 */
1545
1546 if (new_isize_ok) {
1547 isize = new_isize;
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 */
1554 } else {
1555 /*
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.
1559 */
1560 fprintf(stderr,
1561 "warning: inode numbers exceed %d "
1562 " significant bits (%d)\n",
1563 XFS_MAX_INODE_SIG_BITS, inodebits);
1564 }
1565 } else {
1566 /* if isize specified, just warn the user */
1567 fprintf(stderr,
1568 "warning: inode numbers exceed %d "
1569 "significant bits (%d)\n",
1570 XFS_MAX_INODE_SIG_BITS, inodebits);
1571 if (new_isize_ok) {
1572 fprintf(stderr,
1573 " increase inode size to %d to "
1574 "avoid this\n", new_isize);
1575 }
1576 }
1577 }
1578 #endif
1579
1580 protostring = setup_proto(protofile);
1581 bsize = 1 << (blocklog - BBSHIFT);
1582 buf = libxfs_getbuf(xi.ddev, XFS_SB_DADDR, 1);
1583 mp = &mbuf;
1584 sbp = &mp->m_sb;
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;
1589 if (loginternal) {
1590 if (logblocks > agsize - XFS_PREALLOC_BLOCKS(mp)) {
1591 fprintf(stderr,
1592 "internal log size %lld too large, must fit in allocation group\n",
1593 (long long)logblocks);
1594 usage();
1595 }
1596 if (laflag) {
1597 if (logagno >= agcount) {
1598 fprintf(stderr,
1599 "log ag number %d too large, must be less than %lld\n",
1600 logagno, (long long)agcount);
1601 usage();
1602 }
1603 } else
1604 logagno = (xfs_agnumber_t)(agcount / 2);
1605
1606 logstart = XFS_AGB_TO_FSB(mp, logagno, XFS_PREALLOC_BLOCKS(mp));
1607 /*
1608 * Align the logstart at stripe unit boundary.
1609 */
1610 if (dsunit && ((logstart % dsunit) != 0)) {
1611 logstart = ((logstart + (dsunit - 1))/dsunit) * dsunit;
1612 /*
1613 * Make sure that the log size is a multiple of the
1614 * stripe unit
1615 */
1616 if ((logblocks % dsunit) != 0) {
1617 if (!lsflag) {
1618 tmp_logblocks = ((logblocks + (dsunit - 1))
1619 / dsunit) * dsunit;
1620 /*
1621 * If the log is too large, round down
1622 * instead of round up
1623 */
1624 if ((tmp_logblocks > XFS_MAX_LOG_BLOCKS) ||
1625 ((tmp_logblocks << blocklog) > XFS_MAX_LOG_BYTES)) {
1626 tmp_logblocks = (logblocks / dsunit) * dsunit;
1627 }
1628 logblocks = tmp_logblocks;
1629 } else {
1630 fprintf(stderr,
1631 "internal log size %lld is not a multiple of the stripe unit %d\n",
1632 (long long)logblocks, dsunit);
1633 usage();
1634 }
1635 }
1636
1637 if (logblocks > agsize-XFS_FSB_TO_AGBNO(mp,logstart)) {
1638 fprintf(stderr,
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);
1642 usage();
1643 }
1644 lalign = 1;
1645 }
1646 } else
1647 logstart = 0;
1648
1649 if (label)
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);
1671 sbp->sb_rextslog =
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;
1676 sbp->sb_icount = 0;
1677 sbp->sb_ifree = 0;
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;
1682 sbp->sb_qflags = 0;
1683 sbp->sb_unit = dsunit;
1684 sbp->sb_width = dswidth;
1685 if (dirversion == 2)
1686 sbp->sb_dirblklog = dirblocklog - blocklog;
1687 if (iaflag) {
1688 sbp->sb_inoalignmt = XFS_INODE_BIG_CLUSTER_SIZE >> blocklog;
1689 iaflag = sbp->sb_inoalignmt != 0;
1690 } else
1691 sbp->sb_inoalignmt = 0;
1692 sbp->sb_versionnum =
1693 XFS_SB_VERSION_MKFS(iaflag, dsunit != 0, extent_flagging,
1694 dirversion == 2);
1695
1696 bzero(XFS_BUF_PTR(buf), BBSIZE);
1697 libxfs_xlate_sb(XFS_BUF_PTR(buf), sbp, -1, ARCH_CONVERT,
1698 XFS_SB_ALL_BITS);
1699 libxfs_writebuf(buf, 1);
1700
1701 if (!qflag)
1702 printf(
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,
1713 "", inodebits,
1714 dirversion, dirversion == 1 ? blocksize : dirblocksize,
1715 logfile, 1 << blocklog, (long long)logblocks,
1716 rtfile, rtextblocks << blocklog,
1717 (long long)rtblocks, (long long)rtextents);
1718 /*
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
1721 * will succeed.
1722 */
1723 if (xi.disfile && ftruncate64(xi.dfd, dblocks * blocksize) < 0) {
1724 fprintf(stderr, "%s: Growing the data section file failed\n",
1725 progname);
1726 exit(1);
1727 }
1728 /*
1729 * Zero the log if there is one.
1730 */
1731 if (loginternal)
1732 xi.logdev = xi.ddev;
1733 if (xi.logdev)
1734 libxfs_log_clear(
1735 xi.logdev,
1736 XFS_FSB_TO_DADDR(mp, logstart),
1737 (xfs_extlen_t)XFS_FSB_TO_BB(mp, logblocks),
1738 &sbp->sb_uuid,
1739 XLOG_FMT);
1740
1741 mp = libxfs_mount(mp, sbp, xi.ddev, xi.logdev, xi.rtdev, 1);
1742 if (!mp) {
1743 fprintf(stderr, "%s: mount initialization failed\n", progname);
1744 exit(1);
1745 }
1746 if (xi.logdev &&
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);
1752 exit(1);
1753 }
1754
1755 for (agno = 0; agno < agcount; agno++) {
1756 /*
1757 * Superblock.
1758 */
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,
1763 XFS_SB_ALL_BITS);
1764 libxfs_writebuf(buf, 1);
1765
1766 /*
1767 * AG header block: freespace
1768 */
1769 buf = libxfs_getbuf(mp->m_dev,
1770 XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR), 1);
1771 agf = XFS_BUF_TO_AGF(buf);
1772 bzero(agf, BBSIZE);
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,
1780 XFS_BNO_BLOCK(mp));
1781 INT_SET(agf->agf_roots[XFS_BTNUM_CNTi], ARCH_CONVERT,
1782 XFS_CNT_BLOCK(mp));
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);
1795 }
1796 if (XFS_MIN_FREELIST(agf, mp) > worst_freelist)
1797 worst_freelist = XFS_MIN_FREELIST(agf, mp);
1798 libxfs_writebuf(buf, 1);
1799
1800 /*
1801 * AG header block: inodes
1802 */
1803 buf = libxfs_getbuf(mp->m_dev,
1804 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR), 1);
1805 agi = XFS_BUF_TO_AGI(buf);
1806 bzero(agi, BBSIZE);
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);
1820
1821 /*
1822 * BNO btree root block
1823 */
1824 buf = libxfs_getbuf(mp->m_dev,
1825 XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)),
1826 bsize);
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) {
1839 if (lalign) {
1840 /*
1841 * Have to insert two records
1842 */
1843 INT_SET(arec->ar_blockcount, ARCH_CONVERT,
1844 (xfs_extlen_t)(XFS_FSB_TO_AGBNO(
1845 mp, logstart)
1846 - (INT_GET(arec->ar_startblock,
1847 ARCH_CONVERT))));
1848 nrec = arec + 1;
1849 INT_SET(nrec->ar_startblock, ARCH_CONVERT,
1850 INT_GET(arec->ar_startblock,
1851 ARCH_CONVERT) +
1852 INT_GET(arec->ar_blockcount,
1853 ARCH_CONVERT));
1854 arec = nrec;
1855 INT_MOD(block->bb_numrecs, ARCH_CONVERT, 1);
1856 }
1857 INT_MOD(arec->ar_startblock, ARCH_CONVERT, logblocks);
1858 }
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);
1863
1864 /*
1865 * CNT btree root block
1866 */
1867 buf = libxfs_getbuf(mp->m_dev,
1868 XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)),
1869 bsize);
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) {
1882 if (lalign) {
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)) )
1887 );
1888 nrec = arec + 1;
1889 INT_SET(nrec->ar_startblock, ARCH_CONVERT,
1890 INT_GET(arec->ar_startblock, ARCH_CONVERT) +
1891 INT_GET(arec->ar_blockcount, ARCH_CONVERT));
1892 arec = nrec;
1893 INT_MOD(block->bb_numrecs, ARCH_CONVERT, 1);
1894 }
1895 INT_MOD(arec->ar_startblock, ARCH_CONVERT, logblocks);
1896 }
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);
1900 /*
1901 * INO btree root block
1902 */
1903 buf = libxfs_getbuf(mp->m_dev,
1904 XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)),
1905 bsize);
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);
1914 }
1915
1916 /*
1917 * Touch last block, make fs the right size if it's a file.
1918 */
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);
1923
1924 /*
1925 * Make sure we can write the last block in the realtime area.
1926 */
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);
1932 }
1933 /*
1934 * BNO, CNT free block list
1935 */
1936 for (agno = 0; agno < agcount; agno++) {
1937 xfs_alloc_arg_t args;
1938 xfs_trans_t *tp;
1939
1940 bzero(&args, sizeof(args));
1941 args.tp = tp = libxfs_trans_alloc(mp, 0);
1942 args.mp = mp;
1943 args.agno = agno;
1944 args.alignment = 1;
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)))
1948 res_failed(i);
1949 libxfs_alloc_fix_freelist(&args, 0);
1950 libxfs_trans_commit(tp, 0, NULL);
1951 }
1952 /*
1953 * Allocate the root inode and anything else in the proto file.
1954 */
1955 mp->m_rootip = NULL;
1956 parseproto(mp, NULL, &protostring, NULL);
1957
1958 /*
1959 * protect ourselves against possible stupidity
1960 */
1961 if (XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino) != 0) {
1962 fprintf(stderr, "%s: root inode not created in AG 0, "
1963 "created in AG %u",
1964 progname, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino));
1965 exit(1);
1966 }
1967
1968 /*
1969 * write out multiple copies of superblocks with the rootinode field set
1970 */
1971 if (mp->m_sb.sb_agcount > 1) {
1972 /*
1973 * the last superblock
1974 */
1975 buf = libxfs_readbuf(mp->m_dev,
1976 XFS_AGB_TO_DADDR(mp, mp->m_sb.sb_agcount-1,
1977 XFS_SB_DADDR),
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);
1982 /*
1983 * and one in the middle for luck
1984 */
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,
1988 XFS_SB_DADDR),
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);
1993 }
1994 }
1995
1996 /*
1997 * Mark the filesystem ok.
1998 */
1999 buf = libxfs_getsb(mp, 1);
2000 (XFS_BUF_TO_SBP(buf))->sb_inprogress = 0;
2001 libxfs_writebuf(buf, 1);
2002
2003 libxfs_umount(mp);
2004 if (xi.rtdev)
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);
2009
2010 return 0;
2011 }
2012
2013 static void
2014 conflict(
2015 char opt,
2016 char *tab[],
2017 int oldidx,
2018 int newidx)
2019 {
2020 fprintf(stderr, "Cannot specify both -%c %s and -%c %s\n",
2021 opt, tab[oldidx], opt, tab[newidx]);
2022 usage();
2023 }
2024
2025
2026 static void
2027 illegal(
2028 char *value,
2029 char *opt)
2030 {
2031 fprintf(stderr, "Illegal value %s for -%s option\n", value, opt);
2032 usage();
2033 }
2034
2035 static int
2036 ispow2(
2037 unsigned int i)
2038 {
2039 return (i & (i - 1)) == 0;
2040 }
2041
2042 static void
2043 reqval(
2044 char opt,
2045 char *tab[],
2046 int idx)
2047 {
2048 fprintf(stderr, "-%c %s option requires a value\n", opt, tab[idx]);
2049 usage();
2050 }
2051
2052 static void
2053 respec(
2054 char opt,
2055 char *tab[],
2056 int idx)
2057 {
2058 fprintf(stderr, "-%c ", opt);
2059 if (tab)
2060 fprintf(stderr, "%s ", tab[idx]);
2061 fprintf(stderr, "option respecified\n");
2062 usage();
2063 }
2064
2065 static void
2066 unknown(
2067 char opt,
2068 char *s)
2069 {
2070 fprintf(stderr, "unknown option -%c %s\n", opt, s);
2071 usage();
2072 }
2073
2074 static int
2075 max_trans_res(
2076 xfs_mount_t *mp)
2077 {
2078 uint *p;
2079 int rval;
2080 xfs_trans_reservations_t *tr;
2081
2082 tr = &mp->m_reservations;
2083
2084 for (rval = 0, p = (uint *)tr; p < (uint *)(tr + 1); p++) {
2085 if ((int)*p > rval)
2086 rval = (int)*p;
2087 }
2088 return rval;
2089 }
2090
2091 long long
2092 cvtnum(
2093 int blocksize,
2094 char *s)
2095 {
2096 long long i;
2097 char *sp;
2098 extern void usage(void);
2099
2100 i = strtoll(s, &sp, 0);
2101 if (i == 0 && sp == s)
2102 return -1LL;
2103 if (*sp == '\0')
2104 return i;
2105
2106 if (*sp == 'b' && sp[1] == '\0') {
2107 if (blocksize)
2108 return i * blocksize;
2109
2110 fprintf(stderr, "blocksize not available yet.\n");
2111 usage();
2112 }
2113
2114 if (*sp == 'k' && sp[1] == '\0')
2115 return 1024LL * i;
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;
2120 return -1LL;
2121 }
2122
2123 void
2124 usage(void)
2125 {
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\
2136 /* quiet */ [-q]\n\
2137 /* version */ [-V]\n\
2138 /* realtime subvol */ [-r extsize=num,size=num,rtdev=xxx]\n\
2139 devicename\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\
2144 log subvolume.\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",
2147 progname);
2148 exit(1);
2149 }