1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 /* 30 * University Copyright- Copyright (c) 1982, 1986, 1988 31 * The Regents of the University of California 32 * All Rights Reserved 33 * 34 * University Acknowledgment- Portions of this document are derived from 35 * software developed by the University of California, Berkeley, and its 36 * contributors. 37 */ 38 39 /* 40 * Copyright (c) 2018, Joyent, Inc. 41 */ 42 43 /* 44 * The maximum supported file system size (in sectors) is the 45 * number of frags that can be represented in an int32_t field 46 * (INT_MAX) times the maximum number of sectors per frag. Since 47 * the maximum frag size is MAXBSIZE, the maximum number of sectors 48 * per frag is MAXBSIZE/DEV_BSIZE. 49 */ 50 #define FS_MAX (((diskaddr_t)INT_MAX) * (MAXBSIZE/DEV_BSIZE)) 51 52 /* 53 * make file system for cylinder-group style file systems 54 * 55 * usage: 56 * 57 * mkfs [-F FSType] [-V] [-G [-P]] [-M dirname] [-m] [options] 58 * [-o specific_options] special size 59 * [nsect ntrack bsize fsize cpg minfree rps nbpi opt apc rotdelay 60 * 2 3 4 5 6 7 8 9 10 11 12 61 * nrpos maxcontig mtb] 62 * 13 14 15 63 * 64 * where specific_options are: 65 * N - no create 66 * nsect - The number of sectors per track 67 * ntrack - The number of tracks per cylinder 68 * bsize - block size 69 * fragsize - fragment size 70 * cgsize - The number of disk cylinders per cylinder group. 71 * free - minimum free space 72 * rps - rotational speed (rev/sec). 73 * nbpi - number of data bytes per allocated inode 74 * opt - optimization (space, time) 75 * apc - number of alternates 76 * gap - gap size 77 * nrpos - number of rotational positions 78 * maxcontig - maximum number of logical blocks that will be 79 * allocated contiguously before inserting rotational delay 80 * mtb - if "y", set up file system for eventual growth to over a 81 * a terabyte 82 * -P Do not grow the file system, but print on stdout the maximal 83 * size in sectors to which the file system can be increased. The calculated 84 * size is limited by the value provided by the operand size. 85 * 86 * Note that -P is a project-private interface and together with -G intended 87 * to be used only by the growfs script. It is therefore purposely not 88 * documented in the man page. 89 * The -P option is covered by PSARC case 2003/422. 90 */ 91 92 /* 93 * The following constants set the defaults used for the number 94 * of sectors/track (fs_nsect), and number of tracks/cyl (fs_ntrak). 95 * 96 * NSECT NTRAK 97 * 72MB CDC 18 9 98 * 30MB CDC 18 5 99 * 720KB Diskette 9 2 100 * 101 * However the defaults will be different for disks larger than CHSLIMIT. 102 */ 103 104 #define DFLNSECT 32 105 #define DFLNTRAK 16 106 107 /* 108 * The following default sectors and tracks values are used for 109 * non-efi disks that are larger than the CHS addressing limit. The 110 * existing default cpg of 16 (DESCPG) holds good for larger disks too. 111 */ 112 #define DEF_SECTORS_EFI 128 113 #define DEF_TRACKS_EFI 48 114 115 /* 116 * The maximum number of cylinders in a group depends upon how much 117 * information can be stored on a single cylinder. The default is to 118 * use 16 cylinders per group. This is effectively tradition - it was 119 * the largest value acceptable under SunOs 4.1 120 */ 121 #define DESCPG 16 /* desired fs_cpg */ 122 123 /* 124 * The following two constants set the default block and fragment sizes. 125 * Both constants must be a power of 2 and meet the following constraints: 126 * MINBSIZE <= DESBLKSIZE <= MAXBSIZE 127 * DEV_BSIZE <= DESFRAGSIZE <= DESBLKSIZE 128 * DESBLKSIZE / DESFRAGSIZE <= 8 129 */ 130 #define DESBLKSIZE 8192 131 #define DESFRAGSIZE 1024 132 133 /* 134 * MINFREE gives the minimum acceptable percentage of file system 135 * blocks which may be free. If the freelist drops below this level 136 * only the superuser may continue to allocate blocks. This may 137 * be set to 0 if no reserve of free blocks is deemed necessary, 138 * however throughput drops by fifty percent if the file system 139 * is run at between 90% and 100% full; thus the default value of 140 * fs_minfree is 10%. With 10% free space, fragmentation is not a 141 * problem, so we choose to optimize for time. 142 */ 143 #define MINFREE 10 144 #define DEFAULTOPT FS_OPTTIME 145 146 /* 147 * ROTDELAY gives the minimum number of milliseconds to initiate 148 * another disk transfer on the same cylinder. It is no longer used 149 * and will always default to 0. 150 */ 151 #define ROTDELAY 0 152 153 /* 154 * MAXBLKPG determines the maximum number of data blocks which are 155 * placed in a single cylinder group. The default is one indirect 156 * block worth of data blocks. 157 */ 158 #define MAXBLKPG(bsize) ((bsize) / sizeof (daddr32_t)) 159 160 /* 161 * Each file system has a number of inodes statically allocated. 162 * We allocate one inode slot per NBPI bytes, expecting this 163 * to be far more than we will ever need. 164 */ 165 #define NBPI 2048 /* Number Bytes Per Inode */ 166 #define MTB_NBPI (MB) /* Number Bytes Per Inode for multi-terabyte */ 167 168 /* 169 * Disks are assumed to rotate at 60HZ, unless otherwise specified. 170 */ 171 #define DEFHZ 60 172 173 /* 174 * Cylinder group related limits. 175 * 176 * For each cylinder we keep track of the availability of blocks at different 177 * rotational positions, so that we can lay out the data to be picked 178 * up with minimum rotational latency. NRPOS is the number of rotational 179 * positions which we distinguish. With NRPOS 8 the resolution of our 180 * summary information is 2ms for a typical 3600 rpm drive. 181 */ 182 #define NRPOS 8 /* number distinct rotational positions */ 183 184 #ifdef DEBUG 185 #define dprintf(x) printf x 186 #else 187 #define dprintf(x) 188 #endif 189 190 /* 191 * For the -N option, when calculating the backup superblocks, do not print 192 * them if we are not really sure. We may have to try an alternate method of 193 * arriving at the superblocks. So defer printing till a handful of superblocks 194 * look good. 195 */ 196 #define tprintf(x) if (Nflag && retry) \ 197 (void) strncat(tmpbuf, x, strlen(x)); \ 198 else \ 199 (void) fprintf(stderr, x); 200 201 #define ALTSB 32 /* Location of first backup superblock */ 202 203 /* 204 * range_check "user_supplied" flag values. 205 */ 206 #define RC_DEFAULT 0 207 #define RC_KEYWORD 1 208 #define RC_POSITIONAL 2 209 210 /* 211 * ufs hole 212 */ 213 #define UFS_HOLE -1 214 215 #ifndef STANDALONE 216 #include <stdio.h> 217 #include <sys/mnttab.h> 218 #endif 219 220 #include <stdlib.h> 221 #include <unistd.h> 222 #include <malloc.h> 223 #include <string.h> 224 #include <strings.h> 225 #include <ctype.h> 226 #include <errno.h> 227 #include <sys/param.h> 228 #include <time.h> 229 #include <sys/types.h> 230 #include <sys/sysmacros.h> 231 #include <sys/vnode.h> 232 #include <sys/fs/ufs_fsdir.h> 233 #include <sys/fs/ufs_inode.h> 234 #include <sys/fs/ufs_fs.h> 235 #include <sys/fs/ufs_log.h> 236 #include <sys/mntent.h> 237 #include <sys/filio.h> 238 #include <limits.h> 239 #include <sys/int_const.h> 240 #include <signal.h> 241 #include <sys/efi_partition.h> 242 #include <fslib.h> 243 #include "roll_log.h" 244 245 #define bcopy(f, t, n) (void) memcpy(t, f, n) 246 #define bzero(s, n) (void) memset(s, 0, n) 247 #define bcmp(s, d, n) memcmp(s, d, n) 248 249 #define index(s, r) strchr(s, r) 250 #define rindex(s, r) strrchr(s, r) 251 252 #include <sys/stat.h> 253 #include <sys/statvfs.h> 254 #include <locale.h> 255 #include <fcntl.h> 256 #include <sys/isa_defs.h> /* for ENDIAN defines */ 257 #include <sys/vtoc.h> 258 259 #include <sys/dkio.h> 260 #include <sys/asynch.h> 261 262 extern offset_t llseek(); 263 extern char *getfullblkname(); 264 extern long lrand48(); 265 266 extern int optind; 267 extern char *optarg; 268 269 270 /* 271 * The size of a cylinder group is calculated by CGSIZE. The maximum size 272 * is limited by the fact that cylinder groups are at most one block. 273 * Its size is derived from the size of the maps maintained in the 274 * cylinder group and the (struct cg) size. 275 */ 276 #define CGSIZE(fs) \ 277 /* base cg */ (sizeof (struct cg) + \ 278 /* blktot size */ (fs)->fs_cpg * sizeof (long) + \ 279 /* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof (short) + \ 280 /* inode map */ howmany((fs)->fs_ipg, NBBY) + \ 281 /* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY)) 282 283 /* 284 * We limit the size of the inode map to be no more than a 285 * third of the cylinder group space, since we must leave at 286 * least an equal amount of space for the block map. 287 * 288 * N.B.: MAXIpG must be a multiple of INOPB(fs). 289 */ 290 #define MAXIpG(fs) roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs)) 291 292 /* 293 * Same as MAXIpG, but parameterized by the block size (b) and the 294 * cylinder group divisor (d), which is the reciprocal of the fraction of the 295 * cylinder group overhead block that is used for the inode map. So for 296 * example, if d = 5, the macro's computation assumes that 1/5 of the 297 * cylinder group overhead block can be dedicated to the inode map. 298 */ 299 #define MAXIpG_B(b, d) roundup((b) * NBBY / (d), (b) / sizeof (struct dinode)) 300 301 #define UMASK 0755 302 #define MAXINOPB (MAXBSIZE / sizeof (struct dinode)) 303 #define POWEROF2(num) (((num) & ((num) - 1)) == 0) 304 #define MB (1024*1024) 305 #define BETWEEN(x, l, h) ((x) >= (l) && (x) <= (h)) 306 307 /* 308 * Used to set the inode generation number. Since both inodes and dinodes 309 * are dealt with, we really need a pointer to an icommon here. 310 */ 311 #define IRANDOMIZE(icp) (icp)->ic_gen = lrand48(); 312 313 /* 314 * Flags for number() 315 */ 316 #define ALLOW_PERCENT 0x01 /* allow trailing `%' on number */ 317 #define ALLOW_MS1 0x02 /* allow trailing `ms', state 1 */ 318 #define ALLOW_MS2 0x04 /* allow trailing `ms', state 2 */ 319 #define ALLOW_END_ONLY 0x08 /* must be at end of number & suffixes */ 320 321 #define MAXAIO 1000 /* maximum number of outstanding I/O's we'll manage */ 322 #define BLOCK 1 /* block in aiowait */ 323 #define NOBLOCK 0 /* don't block in aiowait */ 324 325 #define RELEASE 1 /* free an aio buffer after use */ 326 #define SAVE 0 /* don't free the buffer */ 327 328 typedef struct aio_trans { 329 aio_result_t resultbuf; 330 diskaddr_t bno; 331 char *buffer; 332 int size; 333 int release; 334 struct aio_trans *next; 335 } aio_trans; 336 337 typedef struct aio_results { 338 int max; 339 int outstanding; 340 int maxpend; 341 aio_trans *trans; 342 } aio_results; 343 344 int aio_inited = 0; 345 aio_results results; 346 347 /* 348 * Allow up to MAXBUF aio requests that each have a unique buffer. 349 * More aio's might be done, but not using memory through the getbuf() 350 * interface. This can be raised, but you run into the potential of 351 * using more memory than is physically available on the machine, 352 * and if you start swapping, you can forget about performance. 353 * To prevent this, we also limit the total memory used for a given 354 * type of buffer to MAXBUFMEM. 355 * 356 * Tests indicate a cylinder group's worth of inodes takes: 357 * 358 * NBPI Size of Inode Buffer 359 * 2k 1688k 360 * 8k 424k 361 * 362 * initcg() stores all the inodes for a cylinder group in one buffer, 363 * so allowing 20 buffers could take 32 MB if not limited by MAXBUFMEM. 364 */ 365 #define MAXBUF 20 366 #define MAXBUFMEM (8 * 1024 * 1024) 367 368 /* 369 * header information for buffers managed by getbuf() and freebuf() 370 */ 371 typedef struct bufhdr { 372 struct bufhdr *head; 373 struct bufhdr *next; 374 } bufhdr; 375 376 int bufhdrsize; 377 378 bufhdr inodebuf = { NULL, NULL }; 379 bufhdr cgsumbuf = { NULL, NULL }; 380 381 #define SECTORS_PER_TERABYTE (1LL << 31) 382 /* 383 * The following constant specifies an upper limit for file system size 384 * that is actually a lot bigger than we expect to support with UFS. (Since 385 * it's specified in sectors, the file system size would be 2**44 * 512, 386 * which is 2**53, which is 8192 Terabytes.) However, it's useful 387 * for checking the basic sanity of a size value that is input on the 388 * command line. 389 */ 390 #define FS_SIZE_UPPER_LIMIT 0x100000000000LL 391 392 /* 393 * Forward declarations 394 */ 395 static char *getbuf(bufhdr *bufhead, int size); 396 static void freebuf(char *buf); 397 static void freetrans(aio_trans *transp); 398 static aio_trans *get_aiop(); 399 static aio_trans *wait_for_write(int block); 400 static void initcg(int cylno); 401 static void fsinit(); 402 static int makedir(struct direct *protodir, int entries); 403 static void iput(struct inode *ip); 404 static void rdfs(diskaddr_t bno, int size, char *bf); 405 static void wtfs(diskaddr_t bno, int size, char *bf); 406 static void awtfs(diskaddr_t bno, int size, char *bf, int release); 407 static void wtfs_breakup(diskaddr_t bno, int size, char *bf); 408 static int isblock(struct fs *fs, unsigned char *cp, int h); 409 static void clrblock(struct fs *fs, unsigned char *cp, int h); 410 static void setblock(struct fs *fs, unsigned char *cp, int h); 411 static void usage(void) __NORETURN; 412 static void dump_fscmd(char *fsys, int fsi); 413 static uint64_t number(uint64_t d_value, char *param, int flags); 414 static int match(char *s); 415 static char checkopt(char *optim); 416 static char checkmtb(char *mtbarg); 417 static void range_check(long *varp, char *name, long minimum, 418 long maximum, long def_val, int user_supplied); 419 static void range_check_64(uint64_t *varp, char *name, uint64_t minimum, 420 uint64_t maximum, uint64_t def_val, int user_supplied); 421 static daddr32_t alloc(int size, int mode); 422 static diskaddr_t get_max_size(int fd); 423 static long get_max_track_size(int fd); 424 static void block_sigint(sigset_t *old_mask); 425 static void unblock_sigint(sigset_t *old_mask); 426 static void recover_from_sigint(int signum); 427 static int confirm_abort(void); 428 static int getaline(FILE *fp, char *loc, int maxlen); 429 static void flush_writes(void); 430 static long compute_maxcpg(long, long, long, long, long); 431 static int in_64bit_mode(void); 432 static int validate_size(int fd, diskaddr_t size); 433 static void dump_sblock(void); 434 435 /* 436 * Workaround for mkfs to function properly on disks attached to XMIT 2.X 437 * controller. If the address is not aligned at 8 byte boundary, mkfs on 438 * disks attached to XMIT 2.X controller exhibts un-predictable behaviour. 439 */ 440 #define XMIT_2_X_ALIGN 8 441 #pragma align XMIT_2_X_ALIGN(fsun, altfsun, cgun) 442 443 union { 444 struct fs fs; 445 char pad[SBSIZE]; 446 } fsun, altfsun; 447 #define sblock fsun.fs 448 #define altsblock altfsun.fs 449 450 struct csum *fscs; 451 452 union cgun { 453 struct cg cg; 454 char pad[MAXBSIZE]; 455 } cgun; 456 457 #define acg cgun.cg 458 /* 459 * Size of screen in cols in which to fit output 460 */ 461 #define WIDTH 80 462 463 struct dinode zino[MAXBSIZE / sizeof (struct dinode)]; 464 465 /* 466 * file descriptors used for rdfs(fsi) and wtfs(fso). 467 * Initialized to an illegal file descriptor number. 468 */ 469 int fsi = -1; 470 int fso = -1; 471 472 /* 473 * The BIG parameter is machine dependent. It should be a longlong integer 474 * constant that can be used by the number parser to check the validity 475 * of numeric parameters. 476 */ 477 478 #define BIG 0x7fffffffffffffffLL 479 480 /* Used to indicate to number() that a bogus value should cause us to exit */ 481 #define NO_DEFAULT LONG_MIN 482 483 /* 484 * INVALIDSBLIMIT is the number of bad backup superblocks that will be 485 * tolerated before we decide to try arriving at a different set of them 486 * using a different logic. This is applicable for non-EFI disks only. 487 */ 488 #define INVALIDSBLIMIT 10 489 490 /* 491 * The *_flag variables are used to indicate that the user specified 492 * the values, rather than that we made them up ourselves. We can 493 * complain about the user giving us bogus values. 494 */ 495 496 /* semi-constants */ 497 long sectorsize = DEV_BSIZE; /* bytes/sector from param.h */ 498 long bbsize = BBSIZE; /* boot block size */ 499 long sbsize = SBSIZE; /* superblock size */ 500 501 /* parameters */ 502 diskaddr_t fssize_db; /* file system size in disk blocks */ 503 diskaddr_t fssize_frag; /* file system size in frags */ 504 long cpg; /* cylinders/cylinder group */ 505 int cpg_flag = RC_DEFAULT; 506 long rotdelay = -1; /* rotational delay between blocks */ 507 int rotdelay_flag = RC_DEFAULT; 508 long maxcontig; /* max contiguous blocks to allocate */ 509 int maxcontig_flag = RC_DEFAULT; 510 long nsect = DFLNSECT; /* sectors per track */ 511 int nsect_flag = RC_DEFAULT; 512 long ntrack = DFLNTRAK; /* tracks per cylinder group */ 513 int ntrack_flag = RC_DEFAULT; 514 long bsize = DESBLKSIZE; /* filesystem block size */ 515 int bsize_flag = RC_DEFAULT; 516 long fragsize = DESFRAGSIZE; /* filesystem fragment size */ 517 int fragsize_flag = RC_DEFAULT; 518 long minfree = MINFREE; /* fs_minfree */ 519 int minfree_flag = RC_DEFAULT; 520 long rps = DEFHZ; /* revolutions/second of drive */ 521 int rps_flag = RC_DEFAULT; 522 long nbpi = NBPI; /* number of bytes per inode */ 523 int nbpi_flag = RC_DEFAULT; 524 long nrpos = NRPOS; /* number of rotational positions */ 525 int nrpos_flag = RC_DEFAULT; 526 long apc = 0; /* alternate sectors per cylinder */ 527 int apc_flag = RC_DEFAULT; 528 char opt = 't'; /* optimization style, `t' or `s' */ 529 char mtb = 'n'; /* multi-terabyte format, 'y' or 'n' */ 530 #define DEFAULT_SECT_TRAK_CPG (nsect_flag == RC_DEFAULT && \ 531 ntrack_flag == RC_DEFAULT && \ 532 cpg_flag == RC_DEFAULT) 533 534 long debug = 0; /* enable debugging output */ 535 536 int spc_flag = 0; /* alternate sectors specified or */ 537 /* found */ 538 539 /* global state */ 540 int Nflag; /* do not write to disk */ 541 int mflag; /* return the command line used to create this FS */ 542 int rflag; /* report the superblock in an easily-parsed form */ 543 int Rflag; /* dump the superblock in binary */ 544 char *fsys; 545 time_t mkfstime; 546 char *string; 547 int label_type; 548 549 /* 550 * logging support 551 */ 552 int islog; /* true if ufs logging is enabled */ 553 int islogok; /* true if ufs log state is good */ 554 int waslog; /* true when ufs logging disabled during grow */ 555 556 /* 557 * growfs defines, globals, and forward references 558 */ 559 #define NOTENOUGHSPACE 33 560 int grow; 561 #define GROW_WITH_DEFAULT_TRAK (grow && ntrack_flag == RC_DEFAULT) 562 563 static int Pflag; /* probe to which size the fs can be grown */ 564 int ismounted; 565 char *directory; 566 diskaddr_t grow_fssize; 567 long grow_fs_size; 568 long grow_fs_ncg; 569 diskaddr_t grow_fs_csaddr; 570 long grow_fs_cssize; 571 int grow_fs_clean; 572 struct csum *grow_fscs; 573 diskaddr_t grow_sifrag; 574 int test; 575 int testforce; 576 diskaddr_t testfrags; 577 int inlockexit; 578 int isbad; 579 580 void lockexit(int) __NORETURN; 581 void randomgeneration(void); 582 void checksummarysize(void); 583 int checksblock(struct fs, int); 584 void growinit(char *); 585 void checkdev(char *, char *); 586 void checkmount(struct mnttab *, char *); 587 struct dinode *gdinode(ino_t); 588 int csfraginrange(daddr32_t); 589 struct csfrag *findcsfrag(daddr32_t, struct csfrag **); 590 void checkindirect(ino_t, daddr32_t *, daddr32_t, int); 591 void addcsfrag(ino_t, daddr32_t, struct csfrag **); 592 void delcsfrag(daddr32_t, struct csfrag **); 593 void checkdirect(ino_t, daddr32_t *, daddr32_t *, int); 594 void findcsfragino(void); 595 void fixindirect(daddr32_t, int); 596 void fixdirect(caddr_t, daddr32_t, daddr32_t *, int); 597 void fixcsfragino(void); 598 void extendsummaryinfo(void); 599 int notenoughspace(void); 600 void unalloccsfragino(void); 601 void unalloccsfragfree(void); 602 void findcsfragfree(void); 603 void copycsfragino(void); 604 void rdcg(long); 605 void wtcg(void); 606 void flcg(void); 607 void allocfrags(long, daddr32_t *, long *); 608 void alloccsfragino(void); 609 void alloccsfragfree(void); 610 void freefrags(daddr32_t, long, long); 611 int findfreerange(long *, long *); 612 void resetallocinfo(void); 613 void extendcg(long); 614 void ulockfs(void); 615 void wlockfs(void); 616 void clockfs(void); 617 void wtsb(void); 618 static int64_t checkfragallocated(daddr32_t); 619 static struct csum *read_summaryinfo(struct fs *); 620 static diskaddr_t probe_summaryinfo(); 621 622 int 623 main(int argc, char *argv[]) 624 { 625 long i, mincpc, mincpg, ibpcl; 626 long cylno, rpos, blk, j, warn = 0; 627 long mincpgcnt, maxcpg; 628 uint64_t used, bpcg, inospercg; 629 long mapcramped, inodecramped; 630 long postblsize, rotblsize, totalsbsize; 631 FILE *mnttab; 632 struct mnttab mntp; 633 char *special; 634 struct statvfs64 fs; 635 struct dk_geom dkg; 636 struct dk_minfo dkminfo; 637 char pbuf[sizeof (uint64_t) * 3 + 1]; 638 char *tmpbuf; 639 int width, plen; 640 uint64_t num; 641 int c, saverr; 642 diskaddr_t max_fssize; 643 long tmpmaxcontig = -1; 644 struct sigaction sigact; 645 uint64_t nbytes64; 646 int remaining_cg; 647 int do_dot = 0; 648 int use_efi_dflts = 0, retry = 0, isremovable = 0, ishotpluggable = 0; 649 int invalid_sb_cnt, ret, skip_this_sb, cg_too_small; 650 int geom_nsect, geom_ntrack, geom_cpg; 651 652 (void) setlocale(LC_ALL, ""); 653 654 #if !defined(TEXT_DOMAIN) 655 #define TEXT_DOMAIN "SYS_TEST" 656 #endif 657 (void) textdomain(TEXT_DOMAIN); 658 659 while ((c = getopt(argc, argv, "F:bmo:VPGM:T:t:")) != EOF) { 660 switch (c) { 661 662 case 'F': 663 string = optarg; 664 if (strcmp(string, "ufs") != 0) 665 usage(); 666 break; 667 668 case 'm': /* return command line used to create this FS */ 669 mflag++; 670 break; 671 672 case 'o': 673 /* 674 * ufs specific options. 675 */ 676 string = optarg; 677 while (*string != '\0') { 678 if (match("nsect=")) { 679 nsect = number(DFLNSECT, "nsect", 0); 680 nsect_flag = RC_KEYWORD; 681 } else if (match("ntrack=")) { 682 ntrack = number(DFLNTRAK, "ntrack", 0); 683 ntrack_flag = RC_KEYWORD; 684 } else if (match("bsize=")) { 685 bsize = number(DESBLKSIZE, "bsize", 0); 686 bsize_flag = RC_KEYWORD; 687 } else if (match("fragsize=")) { 688 fragsize = number(DESFRAGSIZE, 689 "fragsize", 0); 690 fragsize_flag = RC_KEYWORD; 691 } else if (match("cgsize=")) { 692 cpg = number(DESCPG, "cgsize", 0); 693 cpg_flag = RC_KEYWORD; 694 } else if (match("free=")) { 695 minfree = number(MINFREE, "free", 696 ALLOW_PERCENT); 697 minfree_flag = RC_KEYWORD; 698 } else if (match("maxcontig=")) { 699 tmpmaxcontig = 700 number(-1, "maxcontig", 0); 701 maxcontig_flag = RC_KEYWORD; 702 } else if (match("nrpos=")) { 703 nrpos = number(NRPOS, "nrpos", 0); 704 nrpos_flag = RC_KEYWORD; 705 } else if (match("rps=")) { 706 rps = number(DEFHZ, "rps", 0); 707 rps_flag = RC_KEYWORD; 708 } else if (match("nbpi=")) { 709 nbpi = number(NBPI, "nbpi", 0); 710 nbpi_flag = RC_KEYWORD; 711 } else if (match("opt=")) { 712 opt = checkopt(string); 713 } else if (match("mtb=")) { 714 mtb = checkmtb(string); 715 } else if (match("apc=")) { 716 apc = number(0, "apc", 0); 717 apc_flag = RC_KEYWORD; 718 } else if (match("gap=")) { 719 (void) number(0, "gap", ALLOW_MS1); 720 rotdelay = ROTDELAY; 721 rotdelay_flag = RC_DEFAULT; 722 } else if (match("debug=")) { 723 debug = number(0, "debug", 0); 724 } else if (match("N")) { 725 Nflag++; 726 } else if (match("calcsb")) { 727 rflag++; 728 Nflag++; 729 } else if (match("calcbinsb")) { 730 rflag++; 731 Rflag++; 732 Nflag++; 733 } else if (*string == '\0') { 734 break; 735 } else { 736 (void) fprintf(stderr, gettext( 737 "illegal option: %s\n"), string); 738 usage(); 739 } 740 741 if (*string == ',') string++; 742 if (*string == ' ') string++; 743 } 744 break; 745 746 case 'V': 747 { 748 char *opt_text; 749 int opt_count; 750 751 (void) fprintf(stdout, gettext("mkfs -F ufs ")); 752 for (opt_count = 1; opt_count < argc; 753 opt_count++) { 754 opt_text = argv[opt_count]; 755 if (opt_text) 756 (void) fprintf(stdout, " %s ", 757 opt_text); 758 } 759 (void) fprintf(stdout, "\n"); 760 } 761 break; 762 763 case 'b': /* do nothing for this */ 764 break; 765 766 case 'M': /* grow the mounted file system */ 767 directory = optarg; 768 769 /* FALLTHROUGH */ 770 case 'G': /* grow the file system */ 771 grow = 1; 772 break; 773 case 'P': /* probe the file system growing size */ 774 Pflag = 1; 775 grow = 1; /* probe mode implies fs growing */ 776 break; 777 case 'T': /* For testing */ 778 testforce = 1; 779 780 /* FALLTHROUGH */ 781 case 't': 782 test = 1; 783 string = optarg; 784 testfrags = number(NO_DEFAULT, "testfrags", 0); 785 break; 786 787 case '?': 788 usage(); 789 break; 790 } 791 } 792 #ifdef MKFS_DEBUG 793 /* 794 * Turning on MKFS_DEBUG causes mkfs to produce a filesystem 795 * that can be reproduced by setting the time to 0 and seeding 796 * the random number generator to a constant. 797 */ 798 mkfstime = 0; /* reproducible results */ 799 #else 800 (void) time(&mkfstime); 801 #endif 802 803 if (optind >= (argc - 1)) { 804 if (optind > (argc - 1)) { 805 (void) fprintf(stderr, 806 gettext("special not specified\n")); 807 usage(); 808 } else if (mflag == 0) { 809 (void) fprintf(stderr, 810 gettext("size not specified\n")); 811 usage(); 812 } 813 } 814 argc -= optind; 815 argv = &argv[optind]; 816 817 fsys = argv[0]; 818 fsi = open64(fsys, O_RDONLY); 819 if (fsi < 0) { 820 (void) fprintf(stderr, gettext("%s: cannot open\n"), fsys); 821 lockexit(32); 822 } 823 824 if (mflag) { 825 dump_fscmd(fsys, fsi); 826 lockexit(0); 827 } 828 829 /* 830 * The task of setting all of the configuration parameters for a 831 * UFS file system is basically a matter of solving n equations 832 * in m variables. Typically, m is greater than n, so there is 833 * usually more than one valid solution. Since this is usually 834 * an under-constrained problem, it's not always obvious what the 835 * "best" configuration is. 836 * 837 * In general, the approach is to 838 * 1. Determine the values for the file system parameters 839 * that are externally contrained and therefore not adjustable 840 * by mkfs (such as the device's size and maxtransfer size). 841 * 2. Acquire the user's requested setting for all configuration 842 * values that can be set on the command line. 843 * 3. Determine the final value of all configuration values, by 844 * the following approach: 845 * - set the file system block size (fs_bsize). Although 846 * this could be regarded as an adjustable parameter, in 847 * fact, it's pretty much a constant. At this time, it's 848 * generally set to 8k (with older hardware, it can 849 * sometimes make sense to set it to 4k, but those 850 * situations are pretty rare now). 851 * - re-adjust the maximum file system size based on the 852 * value of the file system block size. Since the 853 * frag size can't be any larger than a file system 854 * block, and the number of frags in the file system 855 * has to fit into 31 bits, the file system block size 856 * affects the maximum file system size. 857 * - now that the real maximum file system is known, set the 858 * actual size of the file system to be created to 859 * MIN(requested size, maximum file system size). 860 * - now validate, and if necessary, adjust the following 861 * values: 862 * rotdelay 863 * nsect 864 * maxcontig 865 * apc 866 * frag_size 867 * rps 868 * minfree 869 * nrpos 870 * nrack 871 * nbpi 872 * - calculate maxcpg (the maximum value of the cylinders-per- 873 * cylinder-group configuration parameters). There are two 874 * algorithms for calculating maxcpg: an old one, which is 875 * used for file systems of less than 1 terabyte, and a 876 * new one, implemented in the function compute_maxcpg(), 877 * which is used for file systems of greater than 1 TB. 878 * The difference between them is that compute_maxcpg() 879 * really tries to maximize the cpg value. The old 880 * algorithm fails to take advantage of smaller frags and 881 * lower inode density when determining the maximum cpg, 882 * and thus comes up with much lower numbers in some 883 * configurations. At some point, we might use the 884 * new algorithm for determining maxcpg for all file 885 * systems, but at this time, the changes implemented for 886 * multi-terabyte UFS are NOT being automatically applied 887 * to UFS file systems of less than a terabyte (in the 888 * interest of not changing existing UFS policy too much 889 * until the ramifications of the changes are well-understood 890 * and have been evaluated for their effects on performance.) 891 * - check the current values of the configuration parameters 892 * against the various constraints imposed by UFS. These 893 * include: 894 * * There must be at least one inode in each 895 * cylinder group. 896 * * The cylinder group overhead block, which 897 * contains the inode and frag bigmaps, must fit 898 * within one file system block. 899 * * The space required for inode maps should 900 * occupy no more than a third of the cylinder 901 * group overhead block. 902 * * The rotational position tables have to fit 903 * within the available space in the super block. 904 * Adjust the configuration values that can be adjusted 905 * so that these constraints are satisfied. The 906 * configuration values that are adjustable are: 907 * * frag size 908 * * cylinders per group 909 * * inode density (can be increased) 910 * * number of rotational positions (the rotational 911 * position tables are eliminated altogether if 912 * there isn't enough room for them.) 913 * 4. Set the values for all the dependent configuration 914 * values (those that aren't settable on the command 915 * line and which are completely dependent on the 916 * adjustable parameters). This include cpc (cycles 917 * per cylinder, spc (sectors-per-cylinder), and many others. 918 */ 919 920 /* 921 * Figure out the partition size and initialize the label_type. 922 */ 923 max_fssize = get_max_size(fsi); 924 925 /* 926 * Get and check positional arguments, if any. 927 */ 928 switch (argc - 1) { 929 default: 930 usage(); 931 /*NOTREACHED*/ 932 case 15: 933 mtb = checkmtb(argv[15]); 934 /* FALLTHROUGH */ 935 case 14: 936 string = argv[14]; 937 tmpmaxcontig = number(-1, "maxcontig", 0); 938 maxcontig_flag = RC_POSITIONAL; 939 /* FALLTHROUGH */ 940 case 13: 941 string = argv[13]; 942 nrpos = number(NRPOS, "nrpos", 0); 943 nrpos_flag = RC_POSITIONAL; 944 /* FALLTHROUGH */ 945 case 12: 946 string = argv[12]; 947 rotdelay = ROTDELAY; 948 rotdelay_flag = RC_DEFAULT; 949 /* FALLTHROUGH */ 950 case 11: 951 string = argv[11]; 952 apc = number(0, "apc", 0); 953 apc_flag = RC_POSITIONAL; 954 /* FALLTHROUGH */ 955 case 10: 956 opt = checkopt(argv[10]); 957 /* FALLTHROUGH */ 958 case 9: 959 string = argv[9]; 960 nbpi = number(NBPI, "nbpi", 0); 961 nbpi_flag = RC_POSITIONAL; 962 /* FALLTHROUGH */ 963 case 8: 964 string = argv[8]; 965 rps = number(DEFHZ, "rps", 0); 966 rps_flag = RC_POSITIONAL; 967 /* FALLTHROUGH */ 968 case 7: 969 string = argv[7]; 970 minfree = number(MINFREE, "free", ALLOW_PERCENT); 971 minfree_flag = RC_POSITIONAL; 972 /* FALLTHROUGH */ 973 case 6: 974 string = argv[6]; 975 cpg = number(DESCPG, "cgsize", 0); 976 cpg_flag = RC_POSITIONAL; 977 /* FALLTHROUGH */ 978 case 5: 979 string = argv[5]; 980 fragsize = number(DESFRAGSIZE, "fragsize", 0); 981 fragsize_flag = RC_POSITIONAL; 982 /* FALLTHROUGH */ 983 case 4: 984 string = argv[4]; 985 bsize = number(DESBLKSIZE, "bsize", 0); 986 bsize_flag = RC_POSITIONAL; 987 /* FALLTHROUGH */ 988 case 3: 989 string = argv[3]; 990 ntrack = number(DFLNTRAK, "ntrack", 0); 991 ntrack_flag = RC_POSITIONAL; 992 /* FALLTHROUGH */ 993 case 2: 994 string = argv[2]; 995 nsect = number(DFLNSECT, "nsect", 0); 996 nsect_flag = RC_POSITIONAL; 997 /* FALLTHROUGH */ 998 case 1: 999 string = argv[1]; 1000 fssize_db = number(max_fssize, "size", 0); 1001 } 1002 1003 /* 1004 * Initialize the parameters in the same way as newfs so that 1005 * newfs and mkfs would result in the same file system layout 1006 * for EFI labelled disks. Do this only in the absence of user 1007 * specified values for these parameters. 1008 */ 1009 if (label_type == LABEL_TYPE_EFI) { 1010 if (apc_flag == RC_DEFAULT) apc = 0; 1011 if (nrpos_flag == RC_DEFAULT) nrpos = 1; 1012 if (ntrack_flag == RC_DEFAULT) ntrack = DEF_TRACKS_EFI; 1013 if (rps_flag == RC_DEFAULT) rps = DEFHZ; 1014 if (nsect_flag == RC_DEFAULT) nsect = DEF_SECTORS_EFI; 1015 } 1016 1017 if ((maxcontig_flag == RC_DEFAULT) || (tmpmaxcontig == -1) || 1018 (maxcontig == -1)) { 1019 long maxtrax = get_max_track_size(fsi); 1020 maxcontig = maxtrax / bsize; 1021 1022 } else { 1023 maxcontig = tmpmaxcontig; 1024 } 1025 dprintf(("DeBuG maxcontig : %ld\n", maxcontig)); 1026 1027 if (rotdelay == -1) { /* default by newfs and mkfs */ 1028 rotdelay = ROTDELAY; 1029 } 1030 1031 if (cpg_flag == RC_DEFAULT) { /* If not explicity set, use default */ 1032 cpg = DESCPG; 1033 } 1034 dprintf(("DeBuG cpg : %ld\n", cpg)); 1035 1036 /* 1037 * Now that we have the semi-sane args, either positional, via -o, 1038 * or by defaulting, handle inter-dependencies and range checks. 1039 */ 1040 1041 /* 1042 * Settle the file system block size first, since it's a fixed 1043 * parameter once set and so many other parameters, including 1044 * max_fssize, depend on it. 1045 */ 1046 range_check(&bsize, "bsize", MINBSIZE, MAXBSIZE, DESBLKSIZE, 1047 bsize_flag); 1048 1049 if (!POWEROF2(bsize)) { 1050 (void) fprintf(stderr, 1051 gettext("block size must be a power of 2, not %ld\n"), 1052 bsize); 1053 bsize = DESBLKSIZE; 1054 (void) fprintf(stderr, 1055 gettext("mkfs: bsize reset to default %ld\n"), 1056 bsize); 1057 } 1058 1059 if (fssize_db > max_fssize && validate_size(fsi, fssize_db)) { 1060 (void) fprintf(stderr, gettext( 1061 "Warning: the requested size of this file system\n" 1062 "(%lld sectors) is greater than the size of the\n" 1063 "device reported by the driver (%lld sectors).\n" 1064 "However, a read of the device at the requested size\n" 1065 "does succeed, so the requested size will be used.\n"), 1066 fssize_db, max_fssize); 1067 max_fssize = fssize_db; 1068 } 1069 /* 1070 * Since the maximum allocatable unit (the frag) must be less than 1071 * or equal to bsize, and the number of frags must be less than or 1072 * equal to INT_MAX, the total size of the file system (in 1073 * bytes) must be less than or equal to bsize * INT_MAX. 1074 */ 1075 1076 if (max_fssize > ((diskaddr_t)bsize/DEV_BSIZE) * INT_MAX) 1077 max_fssize = ((diskaddr_t)bsize/DEV_BSIZE) * INT_MAX; 1078 1079 range_check_64(&fssize_db, "size", 1024LL, max_fssize, max_fssize, 1); 1080 1081 if (fssize_db >= SECTORS_PER_TERABYTE) { 1082 mtb = 'y'; 1083 if (!in_64bit_mode()) { 1084 (void) fprintf(stderr, gettext( 1085 "mkfs: Warning: Creating a file system greater than 1 terabyte on a\n" 1086 " system running a 32-bit kernel. This file system will not be\n" 1087 " accessible until the system is rebooted with a 64-bit kernel.\n")); 1088 } 1089 } 1090 dprintf(("DeBuG mtb : %c\n", mtb)); 1091 1092 /* 1093 * With newer and much larger disks, the newfs(1M) and mkfs_ufs(1M) 1094 * commands had problems in correctly handling the "native" geometries 1095 * for various storage devices. 1096 * 1097 * To handle the new age disks, mkfs_ufs(1M) will use the EFI style 1098 * for non-EFI disks that are larger than the CHS addressing limit 1099 * ( > 8GB approx ) and ignore the disk geometry information for 1100 * these drives. This is what is currently done for multi-terrabyte 1101 * filesystems on EFI disks. 1102 * 1103 * However if the user asked for a specific layout by supplying values 1104 * for even one of the three parameters (nsect, ntrack, cpg), honour 1105 * the user supplied parameters. 1106 * 1107 * Choosing EFI style or native geometry style can make a lot of 1108 * difference, because the size of a cylinder group is dependent on 1109 * this choice. This in turn means that the position of alternate 1110 * superblocks varies depending on the style chosen. It is not 1111 * necessary that all disks of size > CHSLIMIT have EFI style layout. 1112 * There can be disks which are > CHSLIMIT size, but have native 1113 * geometry style layout, thereby warranting the need for alternate 1114 * logic in superblock detection. 1115 */ 1116 if (mtb != 'y' && (ntrack == -1 || GROW_WITH_DEFAULT_TRAK || 1117 DEFAULT_SECT_TRAK_CPG)) { 1118 /* 1119 * "-1" indicates that we were called from newfs and ntracks 1120 * was not specified in newfs command line. Calculate nsect 1121 * and ntrack in the same manner as newfs. 1122 * 1123 * This is required because, the defaults for nsect and ntrack 1124 * is hardcoded in mkfs, whereas to generate the alternate 1125 * superblock locations for the -N option, there is a need for 1126 * the geometry based values that newfs would have arrived at. 1127 * Newfs would have arrived at these values as below. 1128 */ 1129 if (label_type == LABEL_TYPE_EFI || 1130 label_type == LABEL_TYPE_OTHER) { 1131 use_efi_dflts = 1; 1132 retry = 1; 1133 } else if (ioctl(fsi, DKIOCGGEOM, &dkg)) { 1134 dprintf(("%s: Unable to read Disk geometry", fsys)); 1135 perror(gettext("Unable to read Disk geometry")); 1136 lockexit(32); 1137 } else { 1138 nsect = dkg.dkg_nsect; 1139 ntrack = dkg.dkg_nhead; 1140 #ifdef i386 /* Bug 1170182 */ 1141 if (ntrack > 32 && (ntrack % 16) != 0) { 1142 ntrack -= (ntrack % 16); 1143 } 1144 #endif 1145 if (ioctl(fsi, DKIOCREMOVABLE, &isremovable)) { 1146 dprintf(("DeBuG Unable to determine if %s is" 1147 " Removable Media. Proceeding with system" 1148 " determined parameters.\n", fsys)); 1149 isremovable = 0; 1150 } 1151 if (ioctl(fsi, DKIOCHOTPLUGGABLE, &ishotpluggable)) { 1152 dprintf(("DeBuG Unable to determine if %s is" 1153 " Hotpluggable Media. Proceeding with " 1154 "system determined parameters.\n", fsys)); 1155 ishotpluggable = 0; 1156 } 1157 if ((((diskaddr_t)dkg.dkg_ncyl * dkg.dkg_nhead * 1158 dkg.dkg_nsect) > CHSLIMIT) || isremovable || 1159 ishotpluggable) { 1160 use_efi_dflts = 1; 1161 retry = 1; 1162 } 1163 } 1164 } 1165 dprintf(("DeBuG CHSLIMIT = %d geom = %llu\n", CHSLIMIT, 1166 (diskaddr_t)dkg.dkg_ncyl * dkg.dkg_nhead * dkg.dkg_nsect)); 1167 dprintf(("DeBuG label_type = %d isremovable = %d ishotpluggable = %d " 1168 "use_efi_dflts = %d\n", label_type, isremovable, ishotpluggable, 1169 use_efi_dflts)); 1170 1171 /* 1172 * For the newfs -N case, even if the disksize is > CHSLIMIT, do not 1173 * blindly follow EFI style. If the fs_version indicates a geometry 1174 * based layout, try that one first. If it fails we can always try the 1175 * other logic. 1176 * 1177 * If we were called from growfs, we will have a problem if we mix 1178 * and match the filesystem creation and growth styles. For example, 1179 * if we create using EFI style, we have to also grow using EFI 1180 * style. So follow the style indicated by the fs_version. 1181 * 1182 * Read and verify the primary superblock. If it looks sane, use the 1183 * fs_version from the superblock. If the primary superblock does 1184 * not look good, read and verify the first alternate superblock at 1185 * ALTSB. Use the fs_version to decide whether to use the 1186 * EFI style logic or the old geometry based logic to calculate 1187 * the alternate superblock locations. 1188 */ 1189 if ((Nflag && use_efi_dflts) || (grow)) { 1190 if (grow && ntrack_flag != RC_DEFAULT) 1191 goto start_fs_creation; 1192 rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, 1193 (char *)&altsblock); 1194 ret = checksblock(altsblock, 1); 1195 1196 if (!ret) { 1197 if (altsblock.fs_magic == MTB_UFS_MAGIC) { 1198 mtb = 'y'; 1199 goto start_fs_creation; 1200 } 1201 use_efi_dflts = (altsblock.fs_version == 1202 UFS_EFISTYLE4NONEFI_VERSION_2) ? 1 : 0; 1203 } else { 1204 /* 1205 * The primary superblock didn't help in determining 1206 * the fs_version. Try the first alternate superblock. 1207 */ 1208 dprintf(("DeBuG checksblock() failed - error : %d" 1209 " for sb : %d\n", ret, SBOFF/sectorsize)); 1210 rdfs((diskaddr_t)ALTSB, (int)sbsize, 1211 (char *)&altsblock); 1212 ret = checksblock(altsblock, 1); 1213 1214 if (!ret) { 1215 if (altsblock.fs_magic == MTB_UFS_MAGIC) { 1216 mtb = 'y'; 1217 goto start_fs_creation; 1218 } 1219 use_efi_dflts = (altsblock.fs_version == 1220 UFS_EFISTYLE4NONEFI_VERSION_2) ? 1 : 0; 1221 } 1222 dprintf(("DeBuG checksblock() returned : %d" 1223 " for sb : %d\n", ret, ALTSB)); 1224 } 1225 } 1226 1227 geom_nsect = nsect; 1228 geom_ntrack = ntrack; 1229 geom_cpg = cpg; 1230 dprintf(("DeBuG geom_nsect=%d, geom_ntrack=%d, geom_cpg=%d\n", 1231 geom_nsect, geom_ntrack, geom_cpg)); 1232 1233 start_fs_creation: 1234 retry_alternate_logic: 1235 invalid_sb_cnt = 0; 1236 cg_too_small = 0; 1237 if (use_efi_dflts) { 1238 nsect = DEF_SECTORS_EFI; 1239 ntrack = DEF_TRACKS_EFI; 1240 cpg = DESCPG; 1241 dprintf(("\nDeBuG Using EFI defaults\n")); 1242 } else { 1243 nsect = geom_nsect; 1244 ntrack = geom_ntrack; 1245 cpg = geom_cpg; 1246 dprintf(("\nDeBuG Using Geometry\n")); 1247 /* 1248 * 32K based on max block size of 64K, and rotational layout 1249 * test of nsect <= (256 * sectors/block). Current block size 1250 * limit is not 64K, but it's growing soon. 1251 */ 1252 range_check(&nsect, "nsect", 1, 32768, DFLNSECT, nsect_flag); 1253 /* 1254 * ntrack is the number of tracks per cylinder. 1255 * The ntrack value must be between 1 and the total number of 1256 * sectors in the file system. 1257 */ 1258 range_check(&ntrack, "ntrack", 1, 1259 fssize_db > INT_MAX ? INT_MAX : (uint32_t)fssize_db, 1260 DFLNTRAK, ntrack_flag); 1261 } 1262 1263 range_check(&apc, "apc", 0, nsect - 1, 0, apc_flag); 1264 1265 if (mtb == 'y') 1266 fragsize = bsize; 1267 1268 range_check(&fragsize, "fragsize", sectorsize, bsize, 1269 MAX(bsize / MAXFRAG, MIN(DESFRAGSIZE, bsize)), fragsize_flag); 1270 1271 if ((bsize / MAXFRAG) > fragsize) { 1272 (void) fprintf(stderr, gettext( 1273 "fragment size %ld is too small, minimum with block size %ld is %ld\n"), 1274 fragsize, bsize, bsize / MAXFRAG); 1275 (void) fprintf(stderr, 1276 gettext("mkfs: fragsize reset to minimum %ld\n"), 1277 bsize / MAXFRAG); 1278 fragsize = bsize / MAXFRAG; 1279 } 1280 1281 if (!POWEROF2(fragsize)) { 1282 (void) fprintf(stderr, 1283 gettext("fragment size must be a power of 2, not %ld\n"), 1284 fragsize); 1285 fragsize = MAX(bsize / MAXFRAG, MIN(DESFRAGSIZE, bsize)); 1286 (void) fprintf(stderr, 1287 gettext("mkfs: fragsize reset to %ld\n"), 1288 fragsize); 1289 } 1290 1291 /* At this point, bsize must be >= fragsize, so no need to check it */ 1292 1293 if (bsize < PAGESIZE) { 1294 (void) fprintf(stderr, gettext( 1295 "WARNING: filesystem block size (%ld) is smaller than " 1296 "memory page size (%ld).\nResulting filesystem can not be " 1297 "mounted on this system.\n\n"), 1298 bsize, (long)PAGESIZE); 1299 } 1300 1301 range_check(&rps, "rps", 1, 1000, DEFHZ, rps_flag); 1302 range_check(&minfree, "free", 0, 99, MINFREE, minfree_flag); 1303 range_check(&nrpos, "nrpos", 1, nsect, MIN(nsect, NRPOS), nrpos_flag); 1304 1305 /* 1306 * nbpi is variable, but 2MB seems a reasonable upper limit, 1307 * as 4MB tends to cause problems (using otherwise-default 1308 * parameters). The true limit is where we end up with one 1309 * inode per cylinder group. If this file system is being 1310 * configured for multi-terabyte access, nbpi must be at least 1MB. 1311 */ 1312 if (mtb == 'y' && nbpi < MTB_NBPI) { 1313 if (nbpi_flag != RC_DEFAULT) 1314 (void) fprintf(stderr, gettext("mkfs: bad value for " 1315 "nbpi: must be at least 1048576 for multi-terabyte," 1316 " nbpi reset to default 1048576\n")); 1317 nbpi = MTB_NBPI; 1318 } 1319 1320 if (mtb == 'y') 1321 range_check(&nbpi, "nbpi", MTB_NBPI, 2 * MB, MTB_NBPI, 1322 nbpi_flag); 1323 else 1324 range_check(&nbpi, "nbpi", DEV_BSIZE, 2 * MB, NBPI, nbpi_flag); 1325 1326 /* 1327 * maxcpg is another variably-limited parameter. Calculate 1328 * the limit based on what we've got for its dependent 1329 * variables. Effectively, it's how much space is left in the 1330 * superblock after all the other bits are accounted for. We 1331 * only fill in sblock fields so we can use MAXIpG. 1332 * 1333 * If the calculation of maxcpg below (for the mtb == 'n' 1334 * case) is changed, update newfs as well. 1335 * 1336 * For old-style, non-MTB format file systems, use the old 1337 * algorithm for calculating the maximum cylinder group size, 1338 * even though it limits the cylinder group more than necessary. 1339 * Since layout can affect performance, we don't want to change 1340 * the default layout for non-MTB file systems at this time. 1341 * However, for MTB file systems, use the new maxcpg calculation, 1342 * which really maxes out the cylinder group size. 1343 */ 1344 1345 sblock.fs_bsize = bsize; 1346 sblock.fs_inopb = sblock.fs_bsize / sizeof (struct dinode); 1347 1348 if (mtb == 'n') { 1349 maxcpg = (bsize - sizeof (struct cg) - 1350 howmany(MAXIpG(&sblock), NBBY)) / 1351 (sizeof (long) + nrpos * sizeof (short) + 1352 nsect / (MAXFRAG * NBBY)); 1353 } else { 1354 maxcpg = compute_maxcpg(bsize, fragsize, nbpi, nrpos, 1355 nsect * ntrack); 1356 } 1357 1358 dprintf(("DeBuG cpg : %ld\n", cpg)); 1359 /* 1360 * Increase the cpg to maxcpg if either newfs was invoked 1361 * with -T option or if mkfs wants to create a mtb file system 1362 * and if the user has not specified the cpg. 1363 */ 1364 if (cpg == -1 || (mtb == 'y' && cpg_flag == RC_DEFAULT)) 1365 cpg = maxcpg; 1366 dprintf(("DeBuG cpg : %ld\n", cpg)); 1367 1368 /* 1369 * mincpg is variable in complex ways, so we really can't 1370 * do a sane lower-end limit check at this point. 1371 */ 1372 range_check(&cpg, "cgsize", 1, maxcpg, MIN(maxcpg, DESCPG), cpg_flag); 1373 1374 /* 1375 * get the controller info 1376 */ 1377 islog = 0; 1378 islogok = 0; 1379 waslog = 0; 1380 1381 /* 1382 * Do not grow the file system, but print on stdout the maximum 1383 * size in sectors to which the file system can be increased. 1384 * The calculated size is limited by fssize_db. 1385 * Note that we don't lock the filesystem and therefore under rare 1386 * conditions (the filesystem is mounted, the free block count is 1387 * almost zero, and the superuser is still changing it) the calculated 1388 * size can be imprecise. 1389 */ 1390 if (Pflag) { 1391 (void) printf("%llu\n", probe_summaryinfo()); 1392 exit(0); 1393 } 1394 1395 /* 1396 * If we're growing an existing filesystem, then we're about 1397 * to start doing things that can require recovery efforts if 1398 * we get interrupted, so make sure we get a chance to do so. 1399 */ 1400 if (grow) { 1401 sigact.sa_handler = recover_from_sigint; 1402 sigemptyset(&sigact.sa_mask); 1403 sigact.sa_flags = SA_RESTART; 1404 1405 if (sigaction(SIGINT, &sigact, (struct sigaction *)NULL) < 0) { 1406 perror(gettext("Could not register SIGINT handler")); 1407 lockexit(3); 1408 } 1409 } 1410 1411 if (!Nflag) { 1412 /* 1413 * Check if MNTTAB is trustable 1414 */ 1415 if (statvfs64(MNTTAB, &fs) < 0) { 1416 (void) fprintf(stderr, gettext("can't statvfs %s\n"), 1417 MNTTAB); 1418 exit(32); 1419 } 1420 1421 if (strcmp(MNTTYPE_MNTFS, fs.f_basetype) != 0) { 1422 (void) fprintf(stderr, gettext( 1423 "%s file system type is not %s, can't mkfs\n"), 1424 MNTTAB, MNTTYPE_MNTFS); 1425 exit(32); 1426 } 1427 1428 special = getfullblkname(fsys); 1429 checkdev(fsys, special); 1430 1431 /* 1432 * If we found the block device name, 1433 * then check the mount table. 1434 * if mounted, and growing write lock the file system 1435 * 1436 */ 1437 if ((special != NULL) && (*special != '\0')) { 1438 if ((mnttab = fopen(MNTTAB, "r")) == NULL) { 1439 (void) fprintf(stderr, gettext( 1440 "can't open %s\n"), MNTTAB); 1441 exit(32); 1442 } 1443 while ((getmntent(mnttab, &mntp)) == 0) { 1444 if (grow) { 1445 checkmount(&mntp, special); 1446 continue; 1447 } 1448 if (strcmp(special, mntp.mnt_special) == 0) { 1449 (void) fprintf(stderr, gettext( 1450 "%s is mounted, can't mkfs\n"), 1451 special); 1452 exit(32); 1453 } 1454 } 1455 (void) fclose(mnttab); 1456 } 1457 1458 if (directory && (ismounted == 0)) { 1459 (void) fprintf(stderr, gettext("%s is not mounted\n"), 1460 special); 1461 lockexit(32); 1462 } 1463 1464 fso = (grow) ? open64(fsys, O_WRONLY) : creat64(fsys, 0666); 1465 if (fso < 0) { 1466 saverr = errno; 1467 (void) fprintf(stderr, 1468 gettext("%s: cannot create: %s\n"), 1469 fsys, strerror(saverr)); 1470 lockexit(32); 1471 } 1472 1473 } else { 1474 1475 /* 1476 * For the -N case, a file descriptor is needed for the llseek() 1477 * in wtfs(). See the comment in wtfs() for more information. 1478 * 1479 * Get a file descriptor that's read-only so that this code 1480 * doesn't accidentally write to the file. 1481 */ 1482 fso = open64(fsys, O_RDONLY); 1483 if (fso < 0) { 1484 saverr = errno; 1485 (void) fprintf(stderr, gettext("%s: cannot open: %s\n"), 1486 fsys, strerror(saverr)); 1487 lockexit(32); 1488 } 1489 } 1490 1491 /* 1492 * Check the media sector size 1493 */ 1494 if (ioctl(fso, DKIOCGMEDIAINFO, &dkminfo) != -1) { 1495 if (dkminfo.dki_lbsize != 0 && 1496 POWEROF2(dkminfo.dki_lbsize / DEV_BSIZE) && 1497 dkminfo.dki_lbsize != DEV_BSIZE) { 1498 fprintf(stderr, 1499 gettext("The device sector size %u is not " 1500 "supported by ufs!\n"), dkminfo.dki_lbsize); 1501 (void) close(fso); 1502 exit(1); 1503 } 1504 } 1505 1506 /* 1507 * seed random # generator (for ic_generation) 1508 */ 1509 #ifdef MKFS_DEBUG 1510 srand48(12962); /* reproducible results */ 1511 #else 1512 srand48((long)(time((time_t *)NULL) + getpid())); 1513 #endif 1514 1515 if (grow) { 1516 growinit(fsys); 1517 goto grow00; 1518 } 1519 1520 /* 1521 * Validate the given file system size. 1522 * Verify that its last block can actually be accessed. 1523 * 1524 * Note: it's ok to use sblock as a buffer because it is immediately 1525 * overwritten by the rdfs() of the superblock in the next line. 1526 * 1527 * ToDo: Because the size checking is done in rdfs()/wtfs(), the 1528 * error message for specifying an illegal size is very unfriendly. 1529 * In the future, one could replace the rdfs()/wtfs() calls 1530 * below with in-line calls to read() or write(). This allows better 1531 * error messages to be put in place. 1532 */ 1533 rdfs(fssize_db - 1, (int)sectorsize, (char *)&sblock); 1534 1535 /* 1536 * make the fs unmountable 1537 */ 1538 rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock); 1539 sblock.fs_magic = -1; 1540 sblock.fs_clean = FSBAD; 1541 sblock.fs_state = FSOKAY - sblock.fs_time; 1542 wtfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock); 1543 bzero(&sblock, (size_t)sbsize); 1544 1545 sblock.fs_nsect = nsect; 1546 sblock.fs_ntrak = ntrack; 1547 1548 /* 1549 * Validate specified/determined spc 1550 * and calculate minimum cylinders per group. 1551 */ 1552 1553 /* 1554 * sectors/cyl = tracks/cyl * sectors/track 1555 */ 1556 sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect; 1557 1558 grow00: 1559 if (apc_flag) { 1560 sblock.fs_spc -= apc; 1561 } 1562 /* 1563 * Have to test for this separately from apc_flag, due to 1564 * the growfs case.... 1565 */ 1566 if (sblock.fs_spc != sblock.fs_ntrak * sblock.fs_nsect) { 1567 spc_flag = 1; 1568 } 1569 if (grow) 1570 goto grow10; 1571 1572 sblock.fs_nrpos = nrpos; 1573 sblock.fs_bsize = bsize; 1574 sblock.fs_fsize = fragsize; 1575 sblock.fs_minfree = minfree; 1576 1577 grow10: 1578 if (nbpi < sblock.fs_fsize) { 1579 (void) fprintf(stderr, gettext( 1580 "warning: wasteful data byte allocation / inode (nbpi):\n")); 1581 (void) fprintf(stderr, gettext( 1582 "%ld smaller than allocatable fragment size of %d\n"), 1583 nbpi, sblock.fs_fsize); 1584 } 1585 if (grow) 1586 goto grow20; 1587 1588 if (opt == 's') 1589 sblock.fs_optim = FS_OPTSPACE; 1590 else 1591 sblock.fs_optim = FS_OPTTIME; 1592 1593 sblock.fs_bmask = ~(sblock.fs_bsize - 1); 1594 sblock.fs_fmask = ~(sblock.fs_fsize - 1); 1595 /* 1596 * Planning now for future expansion. 1597 */ 1598 #if defined(_BIG_ENDIAN) 1599 sblock.fs_qbmask.val[0] = 0; 1600 sblock.fs_qbmask.val[1] = ~sblock.fs_bmask; 1601 sblock.fs_qfmask.val[0] = 0; 1602 sblock.fs_qfmask.val[1] = ~sblock.fs_fmask; 1603 #endif 1604 #if defined(_LITTLE_ENDIAN) 1605 sblock.fs_qbmask.val[0] = ~sblock.fs_bmask; 1606 sblock.fs_qbmask.val[1] = 0; 1607 sblock.fs_qfmask.val[0] = ~sblock.fs_fmask; 1608 sblock.fs_qfmask.val[1] = 0; 1609 #endif 1610 for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1) 1611 sblock.fs_bshift++; 1612 for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1) 1613 sblock.fs_fshift++; 1614 sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize); 1615 for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1) 1616 sblock.fs_fragshift++; 1617 if (sblock.fs_frag > MAXFRAG) { 1618 (void) fprintf(stderr, gettext( 1619 "fragment size %d is too small, minimum with block size %d is %d\n"), 1620 sblock.fs_fsize, sblock.fs_bsize, 1621 sblock.fs_bsize / MAXFRAG); 1622 lockexit(32); 1623 } 1624 sblock.fs_nindir = sblock.fs_bsize / sizeof (daddr32_t); 1625 sblock.fs_inopb = sblock.fs_bsize / sizeof (struct dinode); 1626 sblock.fs_nspf = sblock.fs_fsize / sectorsize; 1627 for (sblock.fs_fsbtodb = 0, i = NSPF(&sblock); i > 1; i >>= 1) 1628 sblock.fs_fsbtodb++; 1629 1630 /* 1631 * Compute the super-block, cylinder group, and inode blocks. 1632 * Note that these "blkno" are really fragment addresses. 1633 * For example, on an 8K/1K (block/fragment) system, fs_sblkno is 16, 1634 * fs_cblkno is 24, and fs_iblkno is 32. This is why CGSIZE is so 1635 * important: only 1 FS block is allocated for the cg struct (fragment 1636 * numbers 24 through 31). 1637 */ 1638 sblock.fs_sblkno = 1639 roundup(howmany(bbsize + sbsize, sblock.fs_fsize), sblock.fs_frag); 1640 sblock.fs_cblkno = (daddr32_t)(sblock.fs_sblkno + 1641 roundup(howmany(sbsize, sblock.fs_fsize), sblock.fs_frag)); 1642 sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag; 1643 1644 sblock.fs_cgoffset = roundup( 1645 howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag); 1646 for (sblock.fs_cgmask = -1, i = sblock.fs_ntrak; i > 1; i >>= 1) 1647 sblock.fs_cgmask <<= 1; 1648 if (!POWEROF2(sblock.fs_ntrak)) 1649 sblock.fs_cgmask <<= 1; 1650 /* 1651 * Validate specified/determined spc 1652 * and calculate minimum cylinders per group. 1653 */ 1654 1655 for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc; 1656 sblock.fs_cpc > 1 && (i & 1) == 0; 1657 sblock.fs_cpc >>= 1, i >>= 1) 1658 /* void */; 1659 mincpc = sblock.fs_cpc; 1660 1661 /* if these calculations are changed, check dump_fscmd also */ 1662 bpcg = (uint64_t)sblock.fs_spc * sectorsize; 1663 inospercg = (uint64_t)roundup(bpcg / sizeof (struct dinode), 1664 INOPB(&sblock)); 1665 if (inospercg > MAXIpG(&sblock)) 1666 inospercg = MAXIpG(&sblock); 1667 used = (uint64_t)(sblock.fs_iblkno + inospercg / 1668 INOPF(&sblock)) * NSPF(&sblock); 1669 mincpgcnt = (long)howmany((uint64_t)sblock.fs_cgoffset * 1670 (~sblock.fs_cgmask) + used, sblock.fs_spc); 1671 mincpg = roundup(mincpgcnt, mincpc); 1672 /* 1673 * Insure that cylinder group with mincpg has enough space 1674 * for block maps 1675 */ 1676 sblock.fs_cpg = mincpg; 1677 sblock.fs_ipg = (int32_t)inospercg; 1678 mapcramped = 0; 1679 1680 /* 1681 * Make sure the cg struct fits within the file system block. 1682 * Use larger block sizes until it fits 1683 */ 1684 while (CGSIZE(&sblock) > sblock.fs_bsize) { 1685 mapcramped = 1; 1686 if (sblock.fs_bsize < MAXBSIZE) { 1687 sblock.fs_bsize <<= 1; 1688 if ((i & 1) == 0) { 1689 i >>= 1; 1690 } else { 1691 sblock.fs_cpc <<= 1; 1692 mincpc <<= 1; 1693 mincpg = roundup(mincpgcnt, mincpc); 1694 sblock.fs_cpg = mincpg; 1695 } 1696 sblock.fs_frag <<= 1; 1697 sblock.fs_fragshift += 1; 1698 if (sblock.fs_frag <= MAXFRAG) 1699 continue; 1700 } 1701 1702 /* 1703 * Looped far enough. The fragment is now as large as the 1704 * filesystem block! 1705 */ 1706 if (sblock.fs_fsize == sblock.fs_bsize) { 1707 (void) fprintf(stderr, gettext( 1708 "There is no block size that can support this disk\n")); 1709 lockexit(32); 1710 } 1711 1712 /* 1713 * Try a larger fragment. Double the fragment size. 1714 */ 1715 sblock.fs_frag >>= 1; 1716 sblock.fs_fragshift -= 1; 1717 sblock.fs_fsize <<= 1; 1718 sblock.fs_nspf <<= 1; 1719 } 1720 /* 1721 * Insure that cylinder group with mincpg has enough space for inodes 1722 */ 1723 inodecramped = 0; 1724 used *= sectorsize; 1725 nbytes64 = (uint64_t)mincpg * bpcg - used; 1726 inospercg = (uint64_t)roundup((nbytes64 / nbpi), INOPB(&sblock)); 1727 sblock.fs_ipg = (int32_t)inospercg; 1728 while (inospercg > MAXIpG(&sblock)) { 1729 inodecramped = 1; 1730 if (mincpc == 1 || sblock.fs_frag == 1 || 1731 sblock.fs_bsize == MINBSIZE) 1732 break; 1733 nbytes64 = (uint64_t)mincpg * bpcg - used; 1734 (void) fprintf(stderr, 1735 gettext("With a block size of %d %s %lu\n"), 1736 sblock.fs_bsize, gettext("minimum bytes per inode is"), 1737 (uint32_t)(nbytes64 / MAXIpG(&sblock) + 1)); 1738 sblock.fs_bsize >>= 1; 1739 sblock.fs_frag >>= 1; 1740 sblock.fs_fragshift -= 1; 1741 mincpc >>= 1; 1742 sblock.fs_cpg = roundup(mincpgcnt, mincpc); 1743 if (CGSIZE(&sblock) > sblock.fs_bsize) { 1744 sblock.fs_bsize <<= 1; 1745 break; 1746 } 1747 mincpg = sblock.fs_cpg; 1748 nbytes64 = (uint64_t)mincpg * bpcg - used; 1749 inospercg = (uint64_t)roundup((nbytes64 / nbpi), 1750 INOPB(&sblock)); 1751 sblock.fs_ipg = (int32_t)inospercg; 1752 } 1753 if (inodecramped) { 1754 if (inospercg > MAXIpG(&sblock)) { 1755 nbytes64 = (uint64_t)mincpg * bpcg - used; 1756 (void) fprintf(stderr, gettext( 1757 "Minimum bytes per inode is %d\n"), 1758 (uint32_t)(nbytes64 / MAXIpG(&sblock) + 1)); 1759 } else if (!mapcramped) { 1760 (void) fprintf(stderr, gettext( 1761 "With %ld bytes per inode, minimum cylinders per group is %ld\n"), 1762 nbpi, mincpg); 1763 } 1764 } 1765 if (mapcramped) { 1766 (void) fprintf(stderr, gettext( 1767 "With %d sectors per cylinder, minimum cylinders " 1768 "per group is %ld\n"), 1769 sblock.fs_spc, mincpg); 1770 } 1771 if (inodecramped || mapcramped) { 1772 /* 1773 * To make this at least somewhat comprehensible in 1774 * the world of i18n, figure out what we're going to 1775 * say and then say it all at one time. The days of 1776 * needing to scrimp on string space are behind us.... 1777 */ 1778 if ((sblock.fs_bsize != bsize) && 1779 (sblock.fs_fsize != fragsize)) { 1780 (void) fprintf(stderr, gettext( 1781 "This requires the block size to be changed from %ld to %d\n" 1782 "and the fragment size to be changed from %ld to %d\n"), 1783 bsize, sblock.fs_bsize, 1784 fragsize, sblock.fs_fsize); 1785 } else if (sblock.fs_bsize != bsize) { 1786 (void) fprintf(stderr, gettext( 1787 "This requires the block size to be changed from %ld to %d\n"), 1788 bsize, sblock.fs_bsize); 1789 } else if (sblock.fs_fsize != fragsize) { 1790 (void) fprintf(stderr, gettext( 1791 "This requires the fragment size to be changed from %ld to %d\n"), 1792 fragsize, sblock.fs_fsize); 1793 } else { 1794 (void) fprintf(stderr, gettext( 1795 "Unable to make filesystem fit with the given constraints\n")); 1796 } 1797 (void) fprintf(stderr, gettext( 1798 "Please re-run mkfs with corrected parameters\n")); 1799 lockexit(32); 1800 } 1801 /* 1802 * Calculate the number of cylinders per group 1803 */ 1804 sblock.fs_cpg = cpg; 1805 if (sblock.fs_cpg % mincpc != 0) { 1806 (void) fprintf(stderr, gettext( 1807 "Warning: cylinder groups must have a multiple " 1808 "of %ld cylinders with the given\n parameters\n"), 1809 mincpc); 1810 sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc); 1811 (void) fprintf(stderr, gettext("Rounded cgsize up to %d\n"), 1812 sblock.fs_cpg); 1813 } 1814 /* 1815 * Must insure there is enough space for inodes 1816 */ 1817 /* if these calculations are changed, check dump_fscmd also */ 1818 nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used; 1819 sblock.fs_ipg = roundup((uint32_t)(nbytes64 / nbpi), INOPB(&sblock)); 1820 1821 /* 1822 * Slim down cylinders per group, until the inodes can fit. 1823 */ 1824 while (sblock.fs_ipg > MAXIpG(&sblock)) { 1825 inodecramped = 1; 1826 sblock.fs_cpg -= mincpc; 1827 nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used; 1828 sblock.fs_ipg = roundup((uint32_t)(nbytes64 / nbpi), 1829 INOPB(&sblock)); 1830 } 1831 /* 1832 * Must insure there is enough space to hold block map. 1833 * Cut down on cylinders per group, until the cg struct fits in a 1834 * filesystem block. 1835 */ 1836 while (CGSIZE(&sblock) > sblock.fs_bsize) { 1837 mapcramped = 1; 1838 sblock.fs_cpg -= mincpc; 1839 nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used; 1840 sblock.fs_ipg = roundup((uint32_t)(nbytes64 / nbpi), 1841 INOPB(&sblock)); 1842 } 1843 sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 1844 if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) { 1845 (void) fprintf(stderr, 1846 gettext("newfs: panic (fs_cpg * fs_spc) %% NSPF != 0\n")); 1847 lockexit(32); 1848 } 1849 if (sblock.fs_cpg < mincpg) { 1850 (void) fprintf(stderr, gettext( 1851 "With the given parameters, cgsize must be at least %ld; please re-run mkfs\n"), 1852 mincpg); 1853 lockexit(32); 1854 } 1855 sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock)); 1856 grow20: 1857 /* 1858 * Now have size for file system and nsect and ntrak. 1859 * Determine number of cylinders and blocks in the file system. 1860 */ 1861 fssize_frag = (int64_t)dbtofsb(&sblock, fssize_db); 1862 if (fssize_frag > INT_MAX) { 1863 (void) fprintf(stderr, gettext( 1864 "There are too many fragments in the system, increase fragment size\n"), 1865 mincpg); 1866 lockexit(32); 1867 } 1868 sblock.fs_size = (int32_t)fssize_frag; 1869 sblock.fs_ncyl = (int32_t)(fssize_frag * NSPF(&sblock) / sblock.fs_spc); 1870 if (fssize_frag * NSPF(&sblock) > 1871 (uint64_t)sblock.fs_ncyl * sblock.fs_spc) { 1872 sblock.fs_ncyl++; 1873 warn = 1; 1874 } 1875 if (sblock.fs_ncyl < 1) { 1876 (void) fprintf(stderr, gettext( 1877 "file systems must have at least one cylinder\n")); 1878 lockexit(32); 1879 } 1880 if (grow) 1881 goto grow30; 1882 /* 1883 * Determine feasability/values of rotational layout tables. 1884 * 1885 * The size of the rotational layout tables is limited by the size 1886 * of the file system block, fs_bsize. The amount of space 1887 * available for tables is calculated as (fs_bsize - sizeof (struct 1888 * fs)). The size of these tables is inversely proportional to the 1889 * block size of the file system. The size increases if sectors per 1890 * track are not powers of two, because more cylinders must be 1891 * described by the tables before the rotational pattern repeats 1892 * (fs_cpc). 1893 */ 1894 sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT; 1895 sblock.fs_sbsize = fragroundup(&sblock, sizeof (struct fs)); 1896 sblock.fs_npsect = sblock.fs_nsect; 1897 if (sblock.fs_ntrak == 1) { 1898 sblock.fs_cpc = 0; 1899 goto next; 1900 } 1901 postblsize = sblock.fs_nrpos * sblock.fs_cpc * sizeof (short); 1902 rotblsize = sblock.fs_cpc * sblock.fs_spc / NSPB(&sblock); 1903 totalsbsize = sizeof (struct fs) + rotblsize; 1904 1905 /* do static allocation if nrpos == 8 and fs_cpc == 16 */ 1906 if (sblock.fs_nrpos == 8 && sblock.fs_cpc <= 16) { 1907 /* use old static table space */ 1908 sblock.fs_postbloff = (char *)(&sblock.fs_opostbl[0][0]) - 1909 (char *)(&sblock.fs_link); 1910 sblock.fs_rotbloff = &sblock.fs_space[0] - 1911 (uchar_t *)(&sblock.fs_link); 1912 } else { 1913 /* use 4.3 dynamic table space */ 1914 sblock.fs_postbloff = &sblock.fs_space[0] - 1915 (uchar_t *)(&sblock.fs_link); 1916 sblock.fs_rotbloff = sblock.fs_postbloff + postblsize; 1917 totalsbsize += postblsize; 1918 } 1919 if (totalsbsize > sblock.fs_bsize || 1920 sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) { 1921 (void) fprintf(stderr, gettext( 1922 "Warning: insufficient space in super block for\n" 1923 "rotational layout tables with nsect %d, ntrack %d, " 1924 "and nrpos %d.\nOmitting tables - file system " 1925 "performance may be impaired.\n"), 1926 sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_nrpos); 1927 1928 /* 1929 * Setting fs_cpc to 0 tells alloccgblk() in ufs_alloc.c to 1930 * ignore the positional layout table and rotational 1931 * position table. 1932 */ 1933 sblock.fs_cpc = 0; 1934 goto next; 1935 } 1936 sblock.fs_sbsize = fragroundup(&sblock, totalsbsize); 1937 1938 1939 /* 1940 * calculate the available blocks for each rotational position 1941 */ 1942 for (cylno = 0; cylno < sblock.fs_cpc; cylno++) 1943 for (rpos = 0; rpos < sblock.fs_nrpos; rpos++) 1944 fs_postbl(&sblock, cylno)[rpos] = -1; 1945 for (i = (rotblsize - 1) * sblock.fs_frag; 1946 i >= 0; i -= sblock.fs_frag) { 1947 cylno = cbtocylno(&sblock, i); 1948 rpos = cbtorpos(&sblock, i); 1949 blk = fragstoblks(&sblock, i); 1950 if (fs_postbl(&sblock, cylno)[rpos] == -1) 1951 fs_rotbl(&sblock)[blk] = 0; 1952 else 1953 fs_rotbl(&sblock)[blk] = 1954 fs_postbl(&sblock, cylno)[rpos] - blk; 1955 fs_postbl(&sblock, cylno)[rpos] = blk; 1956 } 1957 next: 1958 grow30: 1959 /* 1960 * Compute/validate number of cylinder groups. 1961 * Note that if an excessively large filesystem is specified 1962 * (e.g., more than 16384 cylinders for an 8K filesystem block), it 1963 * does not get detected until checksummarysize() 1964 */ 1965 sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; 1966 if (sblock.fs_ncyl % sblock.fs_cpg) 1967 sblock.fs_ncg++; 1968 sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock); 1969 i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1); 1970 ibpcl = cgdmin(&sblock, i) - cgbase(&sblock, i); 1971 if (ibpcl >= sblock.fs_fpg) { 1972 (void) fprintf(stderr, gettext( 1973 "inode blocks/cyl group (%d) >= data blocks (%d)\n"), 1974 cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag, 1975 sblock.fs_fpg / sblock.fs_frag); 1976 if ((ibpcl < 0) || (sblock.fs_fpg < 0)) { 1977 (void) fprintf(stderr, gettext( 1978 "number of cylinders per cylinder group (%d) must be decreased.\n"), 1979 sblock.fs_cpg); 1980 } else { 1981 (void) fprintf(stderr, gettext( 1982 "number of cylinders per cylinder group (%d) must be increased.\n"), 1983 sblock.fs_cpg); 1984 } 1985 (void) fprintf(stderr, gettext( 1986 "Note that cgsize may have been adjusted to allow struct cg to fit.\n")); 1987 lockexit(32); 1988 } 1989 j = sblock.fs_ncg - 1; 1990 if ((i = fssize_frag - j * sblock.fs_fpg) < sblock.fs_fpg && 1991 cgdmin(&sblock, j) - cgbase(&sblock, j) > i) { 1992 (void) fprintf(stderr, gettext( 1993 "Warning: inode blocks/cyl group (%d) >= data " 1994 "blocks (%ld) in last\n cylinder group. This " 1995 "implies %ld sector(s) cannot be allocated.\n"), 1996 (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag, 1997 i / sblock.fs_frag, i * NSPF(&sblock)); 1998 /* 1999 * If there is only one cylinder group and that is not even 2000 * big enough to hold the inodes, exit. 2001 */ 2002 if (sblock.fs_ncg == 1) 2003 cg_too_small = 1; 2004 sblock.fs_ncg--; 2005 sblock.fs_ncyl = sblock.fs_ncg * sblock.fs_cpg; 2006 sblock.fs_size = fssize_frag = 2007 (int64_t)sblock.fs_ncyl * (int64_t)sblock.fs_spc / 2008 (int64_t)NSPF(&sblock); 2009 warn = 0; 2010 } 2011 if (warn && !spc_flag) { 2012 (void) fprintf(stderr, gettext( 2013 "Warning: %d sector(s) in last cylinder unallocated\n"), 2014 sblock.fs_spc - (uint32_t)(fssize_frag * NSPF(&sblock) - 2015 (uint64_t)(sblock.fs_ncyl - 1) * sblock.fs_spc)); 2016 } 2017 /* 2018 * fill in remaining fields of the super block 2019 */ 2020 2021 /* 2022 * The csum records are stored in cylinder group 0, starting at 2023 * cgdmin, the first data block. 2024 */ 2025 sblock.fs_csaddr = cgdmin(&sblock, 0); 2026 sblock.fs_cssize = 2027 fragroundup(&sblock, sblock.fs_ncg * sizeof (struct csum)); 2028 i = sblock.fs_bsize / sizeof (struct csum); 2029 sblock.fs_csmask = ~(i - 1); 2030 for (sblock.fs_csshift = 0; i > 1; i >>= 1) 2031 sblock.fs_csshift++; 2032 fscs = (struct csum *)calloc(1, sblock.fs_cssize); 2033 2034 checksummarysize(); 2035 if (mtb == 'y') { 2036 sblock.fs_magic = MTB_UFS_MAGIC; 2037 sblock.fs_version = MTB_UFS_VERSION_1; 2038 } else { 2039 sblock.fs_magic = FS_MAGIC; 2040 if (use_efi_dflts) 2041 sblock.fs_version = UFS_EFISTYLE4NONEFI_VERSION_2; 2042 else 2043 sblock.fs_version = UFS_VERSION_MIN; 2044 } 2045 2046 if (grow) { 2047 bcopy((caddr_t)grow_fscs, (caddr_t)fscs, (int)grow_fs_cssize); 2048 extendsummaryinfo(); 2049 goto grow40; 2050 } 2051 sblock.fs_rotdelay = rotdelay; 2052 sblock.fs_maxcontig = maxcontig; 2053 sblock.fs_maxbpg = MAXBLKPG(sblock.fs_bsize); 2054 2055 sblock.fs_rps = rps; 2056 sblock.fs_cgrotor = 0; 2057 sblock.fs_cstotal.cs_ndir = 0; 2058 sblock.fs_cstotal.cs_nbfree = 0; 2059 sblock.fs_cstotal.cs_nifree = 0; 2060 sblock.fs_cstotal.cs_nffree = 0; 2061 sblock.fs_fmod = 0; 2062 sblock.fs_ronly = 0; 2063 sblock.fs_time = mkfstime; 2064 sblock.fs_state = FSOKAY - sblock.fs_time; 2065 sblock.fs_clean = FSCLEAN; 2066 grow40: 2067 2068 /* 2069 * If all that's needed is a dump of the superblock we 2070 * would use by default, we've got it now. So, splat it 2071 * out and leave. 2072 */ 2073 if (rflag) { 2074 dump_sblock(); 2075 lockexit(0); 2076 } 2077 /* 2078 * Dump out summary information about file system. 2079 */ 2080 (void) fprintf(stderr, gettext( 2081 "%s:\t%lld sectors in %d cylinders of %d tracks, %d sectors\n"), 2082 fsys, (uint64_t)sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl, 2083 sblock.fs_ntrak, sblock.fs_nsect); 2084 (void) fprintf(stderr, gettext( 2085 "\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n"), 2086 (float)sblock.fs_size * sblock.fs_fsize / MB, sblock.fs_ncg, 2087 sblock.fs_cpg, (float)sblock.fs_fpg * sblock.fs_fsize / MB, 2088 sblock.fs_ipg); 2089 2090 tmpbuf = calloc(sblock.fs_ncg / 50 + 500, 1); 2091 if (tmpbuf == NULL) { 2092 perror("calloc"); 2093 lockexit(32); 2094 } 2095 if (cg_too_small) { 2096 (void) fprintf(stderr, gettext("File system creation failed. " 2097 "There is only one cylinder group and\nthat is " 2098 "not even big enough to hold the inodes.\n")); 2099 lockexit(32); 2100 } 2101 /* 2102 * Now build the cylinders group blocks and 2103 * then print out indices of cylinder groups. 2104 */ 2105 tprintf(gettext( 2106 "super-block backups (for fsck -F ufs -o b=#) at:\n")); 2107 for (width = cylno = 0; cylno < sblock.fs_ncg && cylno < 10; cylno++) { 2108 if ((grow == 0) || (cylno >= grow_fs_ncg)) 2109 initcg(cylno); 2110 num = fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno)); 2111 /* 2112 * If Nflag and if the disk is larger than the CHSLIMIT, 2113 * then sanity test the superblocks before reporting. If there 2114 * are too many superblocks which look insane, we have 2115 * to retry with alternate logic. If both methods have 2116 * failed, then our efforts to arrive at alternate 2117 * superblocks failed, so complain and exit. 2118 */ 2119 if (Nflag && retry) { 2120 skip_this_sb = 0; 2121 rdfs((diskaddr_t)num, sbsize, (char *)&altsblock); 2122 ret = checksblock(altsblock, 1); 2123 if (ret) { 2124 skip_this_sb = 1; 2125 invalid_sb_cnt++; 2126 dprintf(("DeBuG checksblock() failed - error :" 2127 " %d for sb : %llu invalid_sb_cnt : %d\n", 2128 ret, num, invalid_sb_cnt)); 2129 } else { 2130 /* 2131 * Though the superblock looks sane, verify if 2132 * the fs_version in the superblock and the 2133 * logic that we are using to arrive at the 2134 * superblocks match. 2135 */ 2136 if (use_efi_dflts && altsblock.fs_version 2137 != UFS_EFISTYLE4NONEFI_VERSION_2) { 2138 skip_this_sb = 1; 2139 invalid_sb_cnt++; 2140 } 2141 } 2142 if (invalid_sb_cnt >= INVALIDSBLIMIT) { 2143 if (retry > 1) { 2144 (void) fprintf(stderr, gettext( 2145 "Error determining alternate " 2146 "superblock locations\n")); 2147 free(tmpbuf); 2148 lockexit(32); 2149 } 2150 retry++; 2151 use_efi_dflts = !use_efi_dflts; 2152 free(tmpbuf); 2153 goto retry_alternate_logic; 2154 } 2155 if (skip_this_sb) 2156 continue; 2157 } 2158 (void) sprintf(pbuf, " %llu,", num); 2159 plen = strlen(pbuf); 2160 if ((width + plen) > (WIDTH - 1)) { 2161 width = plen; 2162 tprintf("\n"); 2163 } else { 2164 width += plen; 2165 } 2166 if (Nflag && retry) 2167 (void) strncat(tmpbuf, pbuf, strlen(pbuf)); 2168 else 2169 (void) fprintf(stderr, "%s", pbuf); 2170 } 2171 tprintf("\n"); 2172 2173 remaining_cg = sblock.fs_ncg - cylno; 2174 2175 /* 2176 * If there are more than 300 cylinder groups still to be 2177 * initialized, print a "." for every 50 cylinder groups. 2178 */ 2179 if (remaining_cg > 300) { 2180 tprintf(gettext("Initializing cylinder groups:\n")); 2181 do_dot = 1; 2182 } 2183 2184 /* 2185 * Now initialize all cylinder groups between the first ten 2186 * and the last ten. 2187 * 2188 * If the number of cylinder groups was less than 10, all of the 2189 * cylinder group offsets would have printed in the last loop 2190 * and cylno will already be equal to sblock.fs_ncg and so this 2191 * loop will not be entered. If there are less than 20 cylinder 2192 * groups, cylno is already less than fs_ncg - 10, so this loop 2193 * won't be entered in that case either. 2194 */ 2195 2196 i = 0; 2197 for (; cylno < sblock.fs_ncg - 10; cylno++) { 2198 if ((grow == 0) || (cylno >= grow_fs_ncg)) 2199 initcg(cylno); 2200 if (do_dot && cylno % 50 == 0) { 2201 tprintf("."); 2202 i++; 2203 if (i == WIDTH - 1) { 2204 tprintf("\n"); 2205 i = 0; 2206 } 2207 } 2208 } 2209 2210 /* 2211 * Now print the cylinder group offsets for the last 10 2212 * cylinder groups, if any are left. 2213 */ 2214 2215 if (do_dot) { 2216 tprintf(gettext( 2217 "\nsuper-block backups for last 10 cylinder groups at:\n")); 2218 } 2219 for (width = 0; cylno < sblock.fs_ncg; cylno++) { 2220 if ((grow == 0) || (cylno >= grow_fs_ncg)) 2221 initcg(cylno); 2222 num = fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno)); 2223 if (Nflag && retry) { 2224 skip_this_sb = 0; 2225 rdfs((diskaddr_t)num, sbsize, (char *)&altsblock); 2226 ret = checksblock(altsblock, 1); 2227 if (ret) { 2228 skip_this_sb = 1; 2229 invalid_sb_cnt++; 2230 dprintf(("DeBuG checksblock() failed - error :" 2231 " %d for sb : %llu invalid_sb_cnt : %d\n", 2232 ret, num, invalid_sb_cnt)); 2233 } else { 2234 /* 2235 * Though the superblock looks sane, verify if 2236 * the fs_version in the superblock and the 2237 * logic that we are using to arrive at the 2238 * superblocks match. 2239 */ 2240 if (use_efi_dflts && altsblock.fs_version 2241 != UFS_EFISTYLE4NONEFI_VERSION_2) { 2242 skip_this_sb = 1; 2243 invalid_sb_cnt++; 2244 } 2245 } 2246 if (invalid_sb_cnt >= INVALIDSBLIMIT) { 2247 if (retry > 1) { 2248 (void) fprintf(stderr, gettext( 2249 "Error determining alternate " 2250 "superblock locations\n")); 2251 free(tmpbuf); 2252 lockexit(32); 2253 } 2254 retry++; 2255 use_efi_dflts = !use_efi_dflts; 2256 free(tmpbuf); 2257 goto retry_alternate_logic; 2258 } 2259 if (skip_this_sb) 2260 continue; 2261 } 2262 /* Don't print ',' for the last superblock */ 2263 if (cylno == sblock.fs_ncg-1) 2264 (void) sprintf(pbuf, " %llu", num); 2265 else 2266 (void) sprintf(pbuf, " %llu,", num); 2267 plen = strlen(pbuf); 2268 if ((width + plen) > (WIDTH - 1)) { 2269 width = plen; 2270 tprintf("\n"); 2271 } else { 2272 width += plen; 2273 } 2274 if (Nflag && retry) 2275 (void) strncat(tmpbuf, pbuf, strlen(pbuf)); 2276 else 2277 (void) fprintf(stderr, "%s", pbuf); 2278 } 2279 tprintf("\n"); 2280 if (Nflag) { 2281 if (retry) 2282 (void) fprintf(stderr, "%s", tmpbuf); 2283 free(tmpbuf); 2284 lockexit(0); 2285 } 2286 2287 free(tmpbuf); 2288 if (grow) 2289 goto grow50; 2290 2291 /* 2292 * Now construct the initial file system, 2293 * then write out the super-block. 2294 */ 2295 fsinit(); 2296 grow50: 2297 /* 2298 * write the superblock and csum information 2299 */ 2300 wtsb(); 2301 2302 /* 2303 * extend the last cylinder group in the original file system 2304 */ 2305 if (grow) { 2306 extendcg(grow_fs_ncg-1); 2307 wtsb(); 2308 } 2309 2310 /* 2311 * Write out the duplicate super blocks to the first 10 2312 * cylinder groups (or fewer, if there are fewer than 10 2313 * cylinder groups). 2314 */ 2315 for (cylno = 0; cylno < sblock.fs_ncg && cylno < 10; cylno++) 2316 awtfs(fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno)), 2317 (int)sbsize, (char *)&sblock, SAVE); 2318 2319 /* 2320 * Now write out duplicate super blocks to the remaining 2321 * cylinder groups. In the case of multi-terabyte file 2322 * systems, just write out the super block to the last ten 2323 * cylinder groups (or however many are left). 2324 */ 2325 if (mtb == 'y') { 2326 if (sblock.fs_ncg <= 10) 2327 cylno = sblock.fs_ncg; 2328 else if (sblock.fs_ncg <= 20) 2329 cylno = 10; 2330 else 2331 cylno = sblock.fs_ncg - 10; 2332 } 2333 2334 for (; cylno < sblock.fs_ncg; cylno++) 2335 awtfs(fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno)), 2336 (int)sbsize, (char *)&sblock, SAVE); 2337 2338 /* 2339 * Flush out all the AIO writes we've done. It's not 2340 * necessary to do this explicitly, but it's the only 2341 * way to report any errors from those writes. 2342 */ 2343 flush_writes(); 2344 2345 /* 2346 * set clean flag 2347 */ 2348 if (grow) 2349 sblock.fs_clean = grow_fs_clean; 2350 else 2351 sblock.fs_clean = FSCLEAN; 2352 sblock.fs_time = mkfstime; 2353 sblock.fs_state = FSOKAY - sblock.fs_time; 2354 wtfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock); 2355 isbad = 0; 2356 2357 if (fsync(fso) == -1) { 2358 saverr = errno; 2359 (void) fprintf(stderr, 2360 gettext("mkfs: fsync failed on write disk: %s\n"), 2361 strerror(saverr)); 2362 /* we're just cleaning up, so keep going */ 2363 } 2364 if (close(fsi) == -1) { 2365 saverr = errno; 2366 (void) fprintf(stderr, 2367 gettext("mkfs: close failed on read disk: %s\n"), 2368 strerror(saverr)); 2369 /* we're just cleaning up, so keep going */ 2370 } 2371 if (close(fso) == -1) { 2372 saverr = errno; 2373 (void) fprintf(stderr, 2374 gettext("mkfs: close failed on write disk: %s\n"), 2375 strerror(saverr)); 2376 /* we're just cleaning up, so keep going */ 2377 } 2378 fsi = fso = -1; 2379 2380 #ifndef STANDALONE 2381 lockexit(0); 2382 #endif 2383 2384 return (0); 2385 } 2386 2387 static diskaddr_t 2388 get_device_size(int fd) 2389 { 2390 struct dk_minfo disk_info; 2391 2392 if ((ioctl(fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info)) == -1) 2393 return (0); 2394 2395 return (disk_info.dki_capacity); 2396 } 2397 2398 /* 2399 * Figure out how big the partition we're dealing with is. 2400 * The value returned is in disk blocks (sectors); 2401 */ 2402 static diskaddr_t 2403 get_max_size(int fd) 2404 { 2405 struct extvtoc vtoc; 2406 dk_gpt_t *efi_vtoc; 2407 diskaddr_t slicesize; 2408 2409 int index = read_extvtoc(fd, &vtoc); 2410 2411 if (index >= 0) { 2412 label_type = LABEL_TYPE_VTOC; 2413 } else { 2414 if (index == VT_ENOTSUP || index == VT_ERROR) { 2415 /* it might be an EFI label */ 2416 index = efi_alloc_and_read(fd, &efi_vtoc); 2417 label_type = LABEL_TYPE_EFI; 2418 } 2419 } 2420 2421 if (index < 0) { 2422 /* 2423 * Since both attempts to read the label failed, we're 2424 * going to use DKIOCGMEDIAINFO to get device size. 2425 */ 2426 2427 label_type = LABEL_TYPE_OTHER; 2428 slicesize = get_device_size(fd); 2429 if (slicesize == 0) { 2430 switch (index) { 2431 case VT_ERROR: 2432 break; 2433 case VT_EIO: 2434 errno = EIO; 2435 break; 2436 case VT_EINVAL: 2437 errno = EINVAL; 2438 } 2439 perror(gettext("Can not determine partition size")); 2440 lockexit(32); 2441 } 2442 } 2443 2444 if (label_type == LABEL_TYPE_EFI) { 2445 slicesize = efi_vtoc->efi_parts[index].p_size; 2446 efi_free(efi_vtoc); 2447 } else if (label_type == LABEL_TYPE_VTOC) { 2448 /* 2449 * In the vtoc struct, p_size is a 32-bit signed quantity. 2450 * In the dk_gpt struct (efi's version of the vtoc), p_size 2451 * is an unsigned 64-bit quantity. By casting the vtoc's 2452 * psize to an unsigned 32-bit quantity, it will be copied 2453 * to 'slicesize' (an unsigned 64-bit diskaddr_t) without 2454 * sign extension. 2455 */ 2456 2457 slicesize = (uint32_t)vtoc.v_part[index].p_size; 2458 } 2459 2460 dprintf(("DeBuG get_max_size index = %d, p_size = %lld, dolimit = %d\n", 2461 index, slicesize, (slicesize > FS_MAX))); 2462 2463 /* 2464 * The next line limits a UFS file system to the maximum 2465 * supported size. 2466 */ 2467 2468 if (slicesize > FS_MAX) 2469 return (FS_MAX); 2470 return (slicesize); 2471 } 2472 2473 static long 2474 get_max_track_size(int fd) 2475 { 2476 struct dk_cinfo ci; 2477 long track_size = -1; 2478 2479 if (ioctl(fd, DKIOCINFO, &ci) == 0) { 2480 track_size = ci.dki_maxtransfer * DEV_BSIZE; 2481 } 2482 2483 if ((track_size < 0)) { 2484 int error = 0; 2485 int maxphys; 2486 int gotit = 0; 2487 2488 gotit = fsgetmaxphys(&maxphys, &error); 2489 if (gotit) { 2490 track_size = MIN(MB, maxphys); 2491 } else { 2492 (void) fprintf(stderr, gettext( 2493 "Warning: Could not get system value for maxphys. The value for\n" 2494 "maxcontig will default to 1MB.\n")); 2495 track_size = MB; 2496 } 2497 } 2498 return (track_size); 2499 } 2500 2501 /* 2502 * Initialize a cylinder group. 2503 */ 2504 static void 2505 initcg(int cylno) 2506 { 2507 diskaddr_t cbase, d; 2508 diskaddr_t dlower; /* last data block before cg metadata */ 2509 diskaddr_t dupper; /* first data block after cg metadata */ 2510 diskaddr_t dmax; 2511 int64_t i; 2512 struct csum *cs; 2513 struct dinode *inode_buffer; 2514 int size; 2515 2516 /* 2517 * Variables used to store intermediate results as a part of 2518 * the internal implementation of the cbtocylno() macros. 2519 */ 2520 diskaddr_t bno; /* UFS block number (not sector number) */ 2521 int cbcylno; /* current cylinder number */ 2522 int cbcylno_sect; /* sector offset within cylinder */ 2523 int cbsect_incr; /* amount to increment sector offset */ 2524 2525 /* 2526 * Variables used to store intermediate results as a part of 2527 * the internal implementation of the cbtorpos() macros. 2528 */ 2529 short *cgblks; /* pointer to array of free blocks in cg */ 2530 int trackrpos; /* tmp variable for rotation position */ 2531 int trackoff; /* offset within a track */ 2532 int trackoff_incr; /* amount to increment trackoff */ 2533 int rpos; /* rotation position of current block */ 2534 int rpos_incr; /* amount to increment rpos per block */ 2535 2536 union cgun *icgun; /* local pointer to a cg summary block */ 2537 #define icg (icgun->cg) 2538 2539 icgun = (union cgun *)getbuf(&cgsumbuf, sizeof (union cgun)); 2540 2541 /* 2542 * Determine block bounds for cylinder group. 2543 * Allow space for super block summary information in first 2544 * cylinder group. 2545 */ 2546 cbase = cgbase(&sblock, cylno); 2547 dmax = cbase + sblock.fs_fpg; 2548 if (dmax > sblock.fs_size) /* last cg may be smaller than normal */ 2549 dmax = sblock.fs_size; 2550 dlower = cgsblock(&sblock, cylno) - cbase; 2551 dupper = cgdmin(&sblock, cylno) - cbase; 2552 if (cylno == 0) 2553 dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); 2554 cs = fscs + cylno; 2555 icg.cg_time = mkfstime; 2556 icg.cg_magic = CG_MAGIC; 2557 icg.cg_cgx = cylno; 2558 /* last one gets whatever's left */ 2559 if (cylno == sblock.fs_ncg - 1) 2560 icg.cg_ncyl = sblock.fs_ncyl - (sblock.fs_cpg * cylno); 2561 else 2562 icg.cg_ncyl = sblock.fs_cpg; 2563 icg.cg_niblk = sblock.fs_ipg; 2564 icg.cg_ndblk = dmax - cbase; 2565 icg.cg_cs.cs_ndir = 0; 2566 icg.cg_cs.cs_nffree = 0; 2567 icg.cg_cs.cs_nbfree = 0; 2568 icg.cg_cs.cs_nifree = 0; 2569 icg.cg_rotor = 0; 2570 icg.cg_frotor = 0; 2571 icg.cg_irotor = 0; 2572 icg.cg_btotoff = &icg.cg_space[0] - (uchar_t *)(&icg.cg_link); 2573 icg.cg_boff = icg.cg_btotoff + sblock.fs_cpg * sizeof (long); 2574 icg.cg_iusedoff = icg.cg_boff + 2575 sblock.fs_cpg * sblock.fs_nrpos * sizeof (short); 2576 icg.cg_freeoff = icg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY); 2577 icg.cg_nextfreeoff = icg.cg_freeoff + 2578 howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY); 2579 for (i = 0; i < sblock.fs_frag; i++) { 2580 icg.cg_frsum[i] = 0; 2581 } 2582 bzero((caddr_t)cg_inosused(&icg), icg.cg_freeoff - icg.cg_iusedoff); 2583 icg.cg_cs.cs_nifree += sblock.fs_ipg; 2584 if (cylno == 0) 2585 for (i = 0; i < UFSROOTINO; i++) { 2586 setbit(cg_inosused(&icg), i); 2587 icg.cg_cs.cs_nifree--; 2588 } 2589 2590 /* 2591 * Initialize all the inodes in the cylinder group using 2592 * random numbers. 2593 */ 2594 size = sblock.fs_ipg * sizeof (struct dinode); 2595 inode_buffer = (struct dinode *)getbuf(&inodebuf, size); 2596 2597 for (i = 0; i < sblock.fs_ipg; i++) { 2598 IRANDOMIZE(&(inode_buffer[i].di_ic)); 2599 } 2600 2601 /* 2602 * Write all inodes in a single write for performance. 2603 */ 2604 awtfs(fsbtodb(&sblock, (uint64_t)cgimin(&sblock, cylno)), (int)size, 2605 (char *)inode_buffer, RELEASE); 2606 2607 bzero((caddr_t)cg_blktot(&icg), icg.cg_boff - icg.cg_btotoff); 2608 bzero((caddr_t)cg_blks(&sblock, &icg, 0), 2609 icg.cg_iusedoff - icg.cg_boff); 2610 bzero((caddr_t)cg_blksfree(&icg), icg.cg_nextfreeoff - icg.cg_freeoff); 2611 2612 if (cylno > 0) { 2613 for (d = 0; d < dlower; d += sblock.fs_frag) { 2614 setblock(&sblock, cg_blksfree(&icg), d/sblock.fs_frag); 2615 icg.cg_cs.cs_nbfree++; 2616 cg_blktot(&icg)[cbtocylno(&sblock, d)]++; 2617 cg_blks(&sblock, &icg, cbtocylno(&sblock, d)) 2618 [cbtorpos(&sblock, d)]++; 2619 } 2620 sblock.fs_dsize += dlower; 2621 } 2622 sblock.fs_dsize += icg.cg_ndblk - dupper; 2623 if ((i = dupper % sblock.fs_frag) != 0) { 2624 icg.cg_frsum[sblock.fs_frag - i]++; 2625 for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) { 2626 setbit(cg_blksfree(&icg), dupper); 2627 icg.cg_cs.cs_nffree++; 2628 } 2629 } 2630 2631 /* 2632 * WARNING: The following code is somewhat confusing, but 2633 * results in a substantial performance improvement in mkfs. 2634 * 2635 * Instead of using cbtocylno() and cbtorpos() macros, we 2636 * keep track of all the intermediate state of those macros 2637 * in some variables. This allows simple addition to be 2638 * done to calculate the results as we step through the 2639 * blocks in an orderly fashion instead of the slower 2640 * multiplication and division the macros are forced to 2641 * used so they can support random input. (Multiplication, 2642 * division, and remainder operations typically take about 2643 * 10x as many processor cycles as other operations.) 2644 * 2645 * The basic idea is to take code: 2646 * 2647 * for (x = starting_x; x < max; x++) 2648 * y = (x * c) / z 2649 * 2650 * and rewrite it to take advantage of the fact that 2651 * the variable x is incrementing in an orderly way: 2652 * 2653 * intermediate = starting_x * c 2654 * yval = intermediate / z 2655 * for (x = starting_x; x < max; x++) { 2656 * y = yval; 2657 * intermediate += c 2658 * if (intermediate > z) { 2659 * yval++; 2660 * intermediate -= z 2661 * } 2662 * } 2663 * 2664 * Performance has improved as much as 4X using this code. 2665 */ 2666 2667 /* 2668 * Initialize the starting points for all the cbtocylno() 2669 * macro variables and figure out the increments needed each 2670 * time through the loop. 2671 */ 2672 cbcylno_sect = dupper * NSPF(&sblock); 2673 cbsect_incr = sblock.fs_frag * NSPF(&sblock); 2674 cbcylno = cbcylno_sect / sblock.fs_spc; 2675 cbcylno_sect %= sblock.fs_spc; 2676 cgblks = cg_blks(&sblock, &icg, cbcylno); 2677 bno = dupper / sblock.fs_frag; 2678 2679 /* 2680 * Initialize the starting points for all the cbtorpos() 2681 * macro variables and figure out the increments needed each 2682 * time through the loop. 2683 * 2684 * It's harder to simplify the cbtorpos() macro if there were 2685 * alternate sectors specified (or if they previously existed 2686 * in the growfs case). Since this is rare, we just revert to 2687 * using the macros in this case and skip the variable setup. 2688 */ 2689 if (!spc_flag) { 2690 trackrpos = (cbcylno_sect % sblock.fs_nsect) * sblock.fs_nrpos; 2691 rpos = trackrpos / sblock.fs_nsect; 2692 trackoff = trackrpos % sblock.fs_nsect; 2693 trackoff_incr = cbsect_incr * sblock.fs_nrpos; 2694 rpos_incr = (trackoff_incr / sblock.fs_nsect) % sblock.fs_nrpos; 2695 trackoff_incr = trackoff_incr % sblock.fs_nsect; 2696 } 2697 2698 /* 2699 * Loop through all the blocks, marking them free and 2700 * updating totals kept in the superblock and cg summary. 2701 */ 2702 for (d = dupper; d + sblock.fs_frag <= dmax - cbase; ) { 2703 setblock(&sblock, cg_blksfree(&icg), bno); 2704 icg.cg_cs.cs_nbfree++; 2705 2706 cg_blktot(&icg)[cbcylno]++; 2707 2708 if (!spc_flag) 2709 cgblks[rpos]++; 2710 else 2711 cg_blks(&sblock, &icg, cbtocylno(&sblock, d)) 2712 [cbtorpos(&sblock, d)]++; 2713 2714 d += sblock.fs_frag; 2715 bno++; 2716 2717 /* 2718 * Increment the sector offset within the cylinder 2719 * for the cbtocylno() macro reimplementation. If 2720 * we're beyond the end of the cylinder, update the 2721 * cylinder number, calculate the offset in the 2722 * new cylinder, and update the cgblks pointer 2723 * to the next rotational position. 2724 */ 2725 cbcylno_sect += cbsect_incr; 2726 if (cbcylno_sect >= sblock.fs_spc) { 2727 cbcylno++; 2728 cbcylno_sect -= sblock.fs_spc; 2729 cgblks += sblock.fs_nrpos; 2730 } 2731 2732 /* 2733 * If there aren't alternate sectors, increment the 2734 * rotational position variables for the cbtorpos() 2735 * reimplementation. Note that we potentially 2736 * increment rpos twice. Once by rpos_incr, and one 2737 * more time when we wrap to a new track because 2738 * trackoff >= fs_nsect. 2739 */ 2740 if (!spc_flag) { 2741 trackoff += trackoff_incr; 2742 rpos += rpos_incr; 2743 if (trackoff >= sblock.fs_nsect) { 2744 trackoff -= sblock.fs_nsect; 2745 rpos++; 2746 } 2747 if (rpos >= sblock.fs_nrpos) 2748 rpos -= sblock.fs_nrpos; 2749 } 2750 } 2751 2752 if (d < dmax - cbase) { 2753 icg.cg_frsum[dmax - cbase - d]++; 2754 for (; d < dmax - cbase; d++) { 2755 setbit(cg_blksfree(&icg), d); 2756 icg.cg_cs.cs_nffree++; 2757 } 2758 } 2759 sblock.fs_cstotal.cs_ndir += icg.cg_cs.cs_ndir; 2760 sblock.fs_cstotal.cs_nffree += icg.cg_cs.cs_nffree; 2761 sblock.fs_cstotal.cs_nbfree += icg.cg_cs.cs_nbfree; 2762 sblock.fs_cstotal.cs_nifree += icg.cg_cs.cs_nifree; 2763 *cs = icg.cg_cs; 2764 awtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, cylno)), 2765 sblock.fs_bsize, (char *)&icg, RELEASE); 2766 } 2767 2768 /* 2769 * initialize the file system 2770 */ 2771 struct inode node; 2772 2773 #define LOSTDIR 2774 #ifdef LOSTDIR 2775 #define PREDEFDIR 3 2776 #else 2777 #define PREDEFDIR 2 2778 #endif 2779 2780 struct direct root_dir[] = { 2781 { UFSROOTINO, sizeof (struct direct), 1, "." }, 2782 { UFSROOTINO, sizeof (struct direct), 2, ".." }, 2783 #ifdef LOSTDIR 2784 { LOSTFOUNDINO, sizeof (struct direct), 10, "lost+found" }, 2785 #endif 2786 }; 2787 #ifdef LOSTDIR 2788 struct direct lost_found_dir[] = { 2789 { LOSTFOUNDINO, sizeof (struct direct), 1, "." }, 2790 { UFSROOTINO, sizeof (struct direct), 2, ".." }, 2791 { 0, DIRBLKSIZ, 0, 0 }, 2792 }; 2793 #endif 2794 char buf[MAXBSIZE]; 2795 2796 static void 2797 fsinit() 2798 { 2799 int i; 2800 2801 2802 /* 2803 * initialize the node 2804 */ 2805 node.i_atime = mkfstime; 2806 node.i_mtime = mkfstime; 2807 node.i_ctime = mkfstime; 2808 #ifdef LOSTDIR 2809 /* 2810 * create the lost+found directory 2811 */ 2812 (void) makedir(lost_found_dir, 2); 2813 for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) { 2814 bcopy(&lost_found_dir[2], &buf[i], DIRSIZ(&lost_found_dir[2])); 2815 } 2816 node.i_number = LOSTFOUNDINO; 2817 node.i_smode = IFDIR | 0700; 2818 node.i_nlink = 2; 2819 node.i_size = sblock.fs_bsize; 2820 node.i_db[0] = alloc((int)node.i_size, node.i_mode); 2821 node.i_blocks = btodb(fragroundup(&sblock, (int)node.i_size)); 2822 IRANDOMIZE(&node.i_ic); 2823 wtfs(fsbtodb(&sblock, (uint64_t)node.i_db[0]), (int)node.i_size, buf); 2824 iput(&node); 2825 #endif 2826 /* 2827 * create the root directory 2828 */ 2829 node.i_number = UFSROOTINO; 2830 node.i_mode = IFDIR | UMASK; 2831 node.i_nlink = PREDEFDIR; 2832 node.i_size = makedir(root_dir, PREDEFDIR); 2833 node.i_db[0] = alloc(sblock.fs_fsize, node.i_mode); 2834 /* i_size < 2GB because we are initializing the file system */ 2835 node.i_blocks = btodb(fragroundup(&sblock, (int)node.i_size)); 2836 IRANDOMIZE(&node.i_ic); 2837 wtfs(fsbtodb(&sblock, (uint64_t)node.i_db[0]), sblock.fs_fsize, buf); 2838 iput(&node); 2839 } 2840 2841 /* 2842 * construct a set of directory entries in "buf". 2843 * return size of directory. 2844 */ 2845 static int 2846 makedir(struct direct *protodir, int entries) 2847 { 2848 char *cp; 2849 int i; 2850 ushort_t spcleft; 2851 2852 spcleft = DIRBLKSIZ; 2853 for (cp = buf, i = 0; i < entries - 1; i++) { 2854 protodir[i].d_reclen = DIRSIZ(&protodir[i]); 2855 bcopy(&protodir[i], cp, protodir[i].d_reclen); 2856 cp += protodir[i].d_reclen; 2857 spcleft -= protodir[i].d_reclen; 2858 } 2859 protodir[i].d_reclen = spcleft; 2860 bcopy(&protodir[i], cp, DIRSIZ(&protodir[i])); 2861 return (DIRBLKSIZ); 2862 } 2863 2864 /* 2865 * allocate a block or frag 2866 */ 2867 static daddr32_t 2868 alloc(int size, int mode) 2869 { 2870 int i, frag; 2871 daddr32_t d; 2872 2873 rdfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize, 2874 (char *)&acg); 2875 if (acg.cg_magic != CG_MAGIC) { 2876 (void) fprintf(stderr, gettext("cg 0: bad magic number\n")); 2877 lockexit(32); 2878 } 2879 if (acg.cg_cs.cs_nbfree == 0) { 2880 (void) fprintf(stderr, 2881 gettext("first cylinder group ran out of space\n")); 2882 lockexit(32); 2883 } 2884 for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) 2885 if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag)) 2886 goto goth; 2887 (void) fprintf(stderr, 2888 gettext("internal error: can't find block in cyl 0\n")); 2889 lockexit(32); 2890 goth: 2891 clrblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag); 2892 acg.cg_cs.cs_nbfree--; 2893 sblock.fs_cstotal.cs_nbfree--; 2894 fscs[0].cs_nbfree--; 2895 if (mode & IFDIR) { 2896 acg.cg_cs.cs_ndir++; 2897 sblock.fs_cstotal.cs_ndir++; 2898 fscs[0].cs_ndir++; 2899 } 2900 cg_blktot(&acg)[cbtocylno(&sblock, d)]--; 2901 cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--; 2902 if (size != sblock.fs_bsize) { 2903 frag = howmany(size, sblock.fs_fsize); 2904 fscs[0].cs_nffree += sblock.fs_frag - frag; 2905 sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; 2906 acg.cg_cs.cs_nffree += sblock.fs_frag - frag; 2907 acg.cg_frsum[sblock.fs_frag - frag]++; 2908 for (i = frag; i < sblock.fs_frag; i++) 2909 setbit(cg_blksfree(&acg), d + i); 2910 } 2911 wtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize, 2912 (char *)&acg); 2913 return (d); 2914 } 2915 2916 /* 2917 * Allocate an inode on the disk 2918 */ 2919 static void 2920 iput(struct inode *ip) 2921 { 2922 struct dinode buf[MAXINOPB]; 2923 diskaddr_t d; 2924 2925 rdfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize, 2926 (char *)&acg); 2927 if (acg.cg_magic != CG_MAGIC) { 2928 (void) fprintf(stderr, gettext("cg 0: bad magic number\n")); 2929 lockexit(32); 2930 } 2931 acg.cg_cs.cs_nifree--; 2932 setbit(cg_inosused(&acg), ip->i_number); 2933 wtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize, 2934 (char *)&acg); 2935 sblock.fs_cstotal.cs_nifree--; 2936 fscs[0].cs_nifree--; 2937 if ((int)ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) { 2938 (void) fprintf(stderr, 2939 gettext("fsinit: inode value out of range (%d).\n"), 2940 ip->i_number); 2941 lockexit(32); 2942 } 2943 d = fsbtodb(&sblock, (uint64_t)itod(&sblock, (int)ip->i_number)); 2944 rdfs(d, sblock.fs_bsize, (char *)buf); 2945 buf[itoo(&sblock, (int)ip->i_number)].di_ic = ip->i_ic; 2946 wtfs(d, sblock.fs_bsize, (char *)buf); 2947 } 2948 2949 /* 2950 * getbuf() -- Get a buffer for use in an AIO operation. Buffer 2951 * is zero'd the first time returned, left with whatever 2952 * was in memory after that. This function actually gets 2953 * enough memory the first time it's called to support 2954 * MAXBUF buffers like a slab allocator. When all the 2955 * buffers are in use, it waits for an aio to complete 2956 * and make a buffer available. 2957 * 2958 * Never returns an error. Either succeeds or exits. 2959 */ 2960 static char * 2961 getbuf(bufhdr *bufhead, int size) 2962 { 2963 bufhdr *pbuf; 2964 bufhdr *prev; 2965 int i; 2966 int buf_size, max_bufs; 2967 2968 /* 2969 * Initialize all the buffers 2970 */ 2971 if (bufhead->head == NULL) { 2972 /* 2973 * round up the size of our buffer header to a 2974 * 16 byte boundary so the address we return to 2975 * the caller is "suitably aligned". 2976 */ 2977 bufhdrsize = (sizeof (bufhdr) + 15) & ~15; 2978 2979 /* 2980 * Add in our header to the buffer and round it all up to 2981 * a 16 byte boundry so each member of the slab is aligned. 2982 */ 2983 buf_size = (size + bufhdrsize + 15) & ~15; 2984 2985 /* 2986 * Limit number of buffers to lesser of MAXBUFMEM's worth 2987 * or MAXBUF, whichever is less. 2988 */ 2989 max_bufs = MAXBUFMEM / buf_size; 2990 if (max_bufs > MAXBUF) 2991 max_bufs = MAXBUF; 2992 2993 pbuf = (bufhdr *)calloc(max_bufs, buf_size); 2994 if (pbuf == NULL) { 2995 perror("calloc"); 2996 lockexit(32); 2997 } 2998 2999 bufhead->head = bufhead; 3000 prev = bufhead; 3001 for (i = 0; i < max_bufs; i++) { 3002 pbuf->head = bufhead; 3003 prev->next = pbuf; 3004 prev = pbuf; 3005 pbuf = (bufhdr *)((char *)pbuf + buf_size); 3006 } 3007 } 3008 3009 /* 3010 * Get an available buffer, waiting for I/O if necessary 3011 */ 3012 wait_for_write(NOBLOCK); 3013 while (bufhead->next == NULL) 3014 wait_for_write(BLOCK); 3015 3016 /* 3017 * Take the buffer off the list 3018 */ 3019 pbuf = bufhead->next; 3020 bufhead->next = pbuf->next; 3021 pbuf->next = NULL; 3022 3023 /* 3024 * return the empty buffer space just past the header 3025 */ 3026 return ((char *)pbuf + bufhdrsize); 3027 } 3028 3029 /* 3030 * freebuf() -- Free a buffer gotten previously through getbuf. 3031 * Puts the buffer back on the appropriate list for 3032 * later use. Never calls free(). 3033 * 3034 * Assumes that SIGINT is blocked. 3035 */ 3036 static void 3037 freebuf(char *buf) 3038 { 3039 bufhdr *pbuf; 3040 bufhdr *bufhead; 3041 3042 /* 3043 * get the header for this buffer 3044 */ 3045 pbuf = (bufhdr *)(buf - bufhdrsize); 3046 3047 /* 3048 * Put it back on the list of available buffers 3049 */ 3050 bufhead = pbuf->head; 3051 pbuf->next = bufhead->next; 3052 bufhead->next = pbuf; 3053 } 3054 3055 /* 3056 * freetrans() -- Free a transaction gotten previously through getaiop. 3057 * Puts the transaction struct back on the appropriate list for 3058 * later use. Never calls free(). 3059 * 3060 * Assumes that SIGINT is blocked. 3061 */ 3062 static void 3063 freetrans(aio_trans *transp) 3064 { 3065 /* 3066 * free the buffer associated with this AIO if needed 3067 */ 3068 if (transp->release == RELEASE) 3069 freebuf(transp->buffer); 3070 3071 /* 3072 * Put transaction on the free list 3073 */ 3074 transp->next = results.trans; 3075 results.trans = transp; 3076 } 3077 3078 /* 3079 * wait_for_write() -- Wait for an aio write to complete. Return 3080 * the transaction structure for that write. 3081 * 3082 * Blocks SIGINT if necessary. 3083 */ 3084 aio_trans * 3085 wait_for_write(int block) 3086 { 3087 aio_trans *transp; 3088 aio_result_t *resultp; 3089 static struct timeval zero_wait = { 0, 0 }; 3090 sigset_t old_mask; 3091 3092 /* 3093 * If we know there aren't any outstanding transactions, just return 3094 */ 3095 if (results.outstanding == 0) 3096 return ((aio_trans *) 0); 3097 3098 block_sigint(&old_mask); 3099 3100 resultp = aiowait(block ? NULL : &zero_wait); 3101 if (resultp == NULL || 3102 (resultp == (aio_result_t *)-1 && errno == EINVAL)) { 3103 unblock_sigint(&old_mask); 3104 return ((aio_trans *) 0); 3105 } 3106 3107 results.outstanding--; 3108 transp = (aio_trans *)resultp; 3109 3110 if (resultp->aio_return != transp->size) { 3111 if (resultp->aio_return == -1) { 3112 /* 3113 * The aiowrite() may have failed because the 3114 * kernel didn't have enough memory to do the job. 3115 * Flush all pending writes and try a normal 3116 * write(). wtfs_breakup() will call exit if it 3117 * fails, so we don't worry about errors here. 3118 */ 3119 flush_writes(); 3120 wtfs_breakup(transp->bno, transp->size, transp->buffer); 3121 } else { 3122 (void) fprintf(stderr, gettext( 3123 "short write (%d of %d bytes) on sector %lld\n"), 3124 resultp->aio_return, transp->size, 3125 transp->bno); 3126 /* 3127 * Don't unblock SIGINT, to avoid potential 3128 * looping due to queued interrupts and 3129 * error handling. 3130 */ 3131 lockexit(32); 3132 } 3133 } 3134 3135 resultp->aio_return = 0; 3136 freetrans(transp); 3137 unblock_sigint(&old_mask); 3138 return (transp); 3139 } 3140 3141 /* 3142 * flush_writes() -- flush all the outstanding aio writes. 3143 */ 3144 static void 3145 flush_writes(void) 3146 { 3147 while (wait_for_write(BLOCK)) 3148 ; 3149 } 3150 3151 /* 3152 * get_aiop() -- find and return an aio_trans structure on which a new 3153 * aio can be done. Blocks on aiowait() if needed. Reaps 3154 * all outstanding completed aio's. 3155 * 3156 * Assumes that SIGINT is blocked. 3157 */ 3158 aio_trans * 3159 get_aiop() 3160 { 3161 int i; 3162 aio_trans *transp; 3163 aio_trans *prev; 3164 3165 /* 3166 * initialize aio stuff 3167 */ 3168 if (!aio_inited) { 3169 aio_inited = 1; 3170 3171 results.maxpend = 0; 3172 results.outstanding = 0; 3173 results.max = MAXAIO; 3174 3175 results.trans = (aio_trans *)calloc(results.max, 3176 sizeof (aio_trans)); 3177 if (results.trans == NULL) { 3178 perror("calloc"); 3179 lockexit(32); 3180 } 3181 3182 /* 3183 * Initialize the linked list of aio transaction 3184 * structures. Note that the final "next" pointer 3185 * will be NULL since we got the buffer from calloc(). 3186 */ 3187 prev = results.trans; 3188 for (i = 1; i < results.max; i++) { 3189 prev->next = &(results.trans[i]); 3190 prev = prev->next; 3191 } 3192 } 3193 3194 wait_for_write(NOBLOCK); 3195 while (results.trans == NULL) 3196 wait_for_write(BLOCK); 3197 transp = results.trans; 3198 results.trans = results.trans->next; 3199 3200 transp->next = 0; 3201 transp->resultbuf.aio_return = AIO_INPROGRESS; 3202 return (transp); 3203 } 3204 3205 /* 3206 * read a block from the file system 3207 */ 3208 static void 3209 rdfs(diskaddr_t bno, int size, char *bf) 3210 { 3211 int n, saverr; 3212 3213 /* 3214 * In case we need any data that's pending in an aiowrite(), 3215 * we wait for them all to complete before doing a read. 3216 */ 3217 flush_writes(); 3218 3219 /* 3220 * Note: the llseek() can succeed, even if the offset is out of range. 3221 * It's not until the file i/o operation (the read()) that one knows 3222 * for sure if the raw device can handle the offset. 3223 */ 3224 if (llseek(fsi, (offset_t)bno * sectorsize, 0) < 0) { 3225 saverr = errno; 3226 (void) fprintf(stderr, 3227 gettext("seek error on sector %lld: %s\n"), 3228 bno, strerror(saverr)); 3229 lockexit(32); 3230 } 3231 n = read(fsi, bf, size); 3232 if (n != size) { 3233 saverr = errno; 3234 if (n == -1) 3235 (void) fprintf(stderr, 3236 gettext("read error on sector %lld: %s\n"), 3237 bno, strerror(saverr)); 3238 else 3239 (void) fprintf(stderr, gettext( 3240 "short read (%d of %d bytes) on sector %lld\n"), 3241 n, size, bno); 3242 lockexit(32); 3243 } 3244 } 3245 3246 /* 3247 * write a block to the file system 3248 */ 3249 static void 3250 wtfs(diskaddr_t bno, int size, char *bf) 3251 { 3252 int n, saverr; 3253 3254 if (fso == -1) 3255 return; 3256 3257 /* 3258 * Note: the llseek() can succeed, even if the offset is out of range. 3259 * It's not until the file i/o operation (the write()) that one knows 3260 * for sure if the raw device can handle the offset. 3261 */ 3262 if (llseek(fso, (offset_t)bno * sectorsize, 0) < 0) { 3263 saverr = errno; 3264 (void) fprintf(stderr, 3265 gettext("seek error on sector %lld: %s\n"), 3266 bno, strerror(saverr)); 3267 lockexit(32); 3268 } 3269 if (Nflag) 3270 return; 3271 n = write(fso, bf, size); 3272 if (n != size) { 3273 saverr = errno; 3274 if (n == -1) 3275 (void) fprintf(stderr, 3276 gettext("write error on sector %lld: %s\n"), 3277 bno, strerror(saverr)); 3278 else 3279 (void) fprintf(stderr, gettext( 3280 "short write (%d of %d bytes) on sector %lld\n"), 3281 n, size, bno); 3282 lockexit(32); 3283 } 3284 } 3285 3286 /* 3287 * write a block to the file system -- buffered with aio 3288 */ 3289 static void 3290 awtfs(diskaddr_t bno, int size, char *bf, int release) 3291 { 3292 int n; 3293 aio_trans *transp; 3294 sigset_t old_mask; 3295 3296 if (fso == -1) 3297 return; 3298 3299 /* 3300 * We need to keep things consistent if we get interrupted, 3301 * so defer any expected interrupts for the time being. 3302 */ 3303 block_sigint(&old_mask); 3304 3305 if (Nflag) { 3306 if (release == RELEASE) 3307 freebuf(bf); 3308 } else { 3309 transp = get_aiop(); 3310 transp->bno = bno; 3311 transp->buffer = bf; 3312 transp->size = size; 3313 transp->release = release; 3314 3315 n = aiowrite(fso, bf, size, (off_t)bno * sectorsize, 3316 SEEK_SET, &transp->resultbuf); 3317 3318 if (n < 0) { 3319 /* 3320 * The aiowrite() may have failed because the 3321 * kernel didn't have enough memory to do the job. 3322 * Flush all pending writes and try a normal 3323 * write(). wtfs_breakup() will call exit if it 3324 * fails, so we don't worry about errors here. 3325 */ 3326 flush_writes(); 3327 wtfs_breakup(transp->bno, transp->size, transp->buffer); 3328 freetrans(transp); 3329 } else { 3330 /* 3331 * Keep track of our pending writes. 3332 */ 3333 results.outstanding++; 3334 if (results.outstanding > results.maxpend) 3335 results.maxpend = results.outstanding; 3336 } 3337 } 3338 3339 unblock_sigint(&old_mask); 3340 } 3341 3342 3343 /* 3344 * write a block to the file system, but break it up into sbsize 3345 * chunks to avoid forcing a large amount of memory to be locked down. 3346 * Only used as a fallback when an aio write has failed. 3347 */ 3348 static void 3349 wtfs_breakup(diskaddr_t bno, int size, char *bf) 3350 { 3351 int n, saverr; 3352 int wsize; 3353 int block_incr = sbsize / sectorsize; 3354 3355 if (size < sbsize) 3356 wsize = size; 3357 else 3358 wsize = sbsize; 3359 3360 n = 0; 3361 while (size) { 3362 /* 3363 * Note: the llseek() can succeed, even if the offset is 3364 * out of range. It's not until the file i/o operation 3365 * (the write()) that one knows for sure if the raw device 3366 * can handle the offset. 3367 */ 3368 if (llseek(fso, (offset_t)bno * sectorsize, 0) < 0) { 3369 saverr = errno; 3370 (void) fprintf(stderr, 3371 gettext("seek error on sector %lld: %s\n"), 3372 bno, strerror(saverr)); 3373 lockexit(32); 3374 } 3375 3376 n = write(fso, bf, wsize); 3377 if (n == -1) { 3378 saverr = errno; 3379 (void) fprintf(stderr, 3380 gettext("write error on sector %lld: %s\n"), 3381 bno, strerror(saverr)); 3382 lockexit(32); 3383 } 3384 if (n != wsize) { 3385 saverr = errno; 3386 (void) fprintf(stderr, gettext( 3387 "short write (%d of %d bytes) on sector %lld\n"), 3388 n, size, bno); 3389 lockexit(32); 3390 } 3391 3392 bno += block_incr; 3393 bf += wsize; 3394 size -= wsize; 3395 if (size < wsize) 3396 wsize = size; 3397 } 3398 } 3399 3400 3401 /* 3402 * check if a block is available 3403 */ 3404 static int 3405 isblock(struct fs *fs, unsigned char *cp, int h) 3406 { 3407 unsigned char mask; 3408 3409 switch (fs->fs_frag) { 3410 case 8: 3411 return (cp[h] == 0xff); 3412 case 4: 3413 mask = 0x0f << ((h & 0x1) << 2); 3414 return ((cp[h >> 1] & mask) == mask); 3415 case 2: 3416 mask = 0x03 << ((h & 0x3) << 1); 3417 return ((cp[h >> 2] & mask) == mask); 3418 case 1: 3419 mask = 0x01 << (h & 0x7); 3420 return ((cp[h >> 3] & mask) == mask); 3421 default: 3422 (void) fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 3423 return (0); 3424 } 3425 } 3426 3427 /* 3428 * take a block out of the map 3429 */ 3430 static void 3431 clrblock(struct fs *fs, unsigned char *cp, int h) 3432 { 3433 switch ((fs)->fs_frag) { 3434 case 8: 3435 cp[h] = 0; 3436 return; 3437 case 4: 3438 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 3439 return; 3440 case 2: 3441 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 3442 return; 3443 case 1: 3444 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 3445 return; 3446 default: 3447 (void) fprintf(stderr, 3448 gettext("clrblock: bad fs_frag value %d\n"), fs->fs_frag); 3449 return; 3450 } 3451 } 3452 3453 /* 3454 * put a block into the map 3455 */ 3456 static void 3457 setblock(struct fs *fs, unsigned char *cp, int h) 3458 { 3459 switch (fs->fs_frag) { 3460 case 8: 3461 cp[h] = 0xff; 3462 return; 3463 case 4: 3464 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 3465 return; 3466 case 2: 3467 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 3468 return; 3469 case 1: 3470 cp[h >> 3] |= (0x01 << (h & 0x7)); 3471 return; 3472 default: 3473 (void) fprintf(stderr, 3474 gettext("setblock: bad fs_frag value %d\n"), fs->fs_frag); 3475 return; 3476 } 3477 } 3478 3479 static void 3480 usage(void) 3481 { 3482 (void) fprintf(stderr, 3483 gettext("ufs usage: mkfs [-F FSType] [-V] [-m] [-o options] " 3484 "special " /* param 0 */ 3485 "size(sectors) \\ \n")); /* param 1 */ 3486 (void) fprintf(stderr, 3487 "[nsect " /* param 2 */ 3488 "ntrack " /* param 3 */ 3489 "bsize " /* param 4 */ 3490 "fragsize " /* param 5 */ 3491 "cpg " /* param 6 */ 3492 "free " /* param 7 */ 3493 "rps " /* param 8 */ 3494 "nbpi " /* param 9 */ 3495 "opt " /* param 10 */ 3496 "apc " /* param 11 */ 3497 "gap " /* param 12 */ 3498 "nrpos " /* param 13 */ 3499 "maxcontig " /* param 14 */ 3500 "mtb]\n"); /* param 15 */ 3501 (void) fprintf(stderr, 3502 gettext(" -m : dump fs cmd line used to make this partition\n" 3503 " -V :print this command line and return\n" 3504 " -o :ufs options: :nsect=%d,ntrack=%d,bsize=%d,fragsize=%d\n" 3505 " -o :ufs options: :cgsize=%d,free=%d,rps=%d,nbpi=%d,opt=%c\n" 3506 " -o :ufs options: :apc=%d,gap=%d,nrpos=%d,maxcontig=%d\n" 3507 " -o :ufs options: :mtb=%c,calcsb,calcbinsb\n" 3508 "NOTE that all -o suboptions: must be separated only by commas so as to\n" 3509 "be parsed as a single argument\n"), 3510 nsect, ntrack, bsize, fragsize, cpg, sblock.fs_minfree, rps, 3511 nbpi, opt, apc, (rotdelay == -1) ? 0 : rotdelay, 3512 sblock.fs_nrpos, maxcontig, mtb); 3513 lockexit(32); 3514 } 3515 3516 /*ARGSUSED*/ 3517 static void 3518 dump_fscmd(char *fsys, int fsi) 3519 { 3520 int64_t used, bpcg, inospercg; 3521 int64_t nbpi; 3522 uint64_t nbytes64; 3523 3524 bzero((char *)&sblock, sizeof (sblock)); 3525 rdfs((diskaddr_t)SBLOCK, SBSIZE, (char *)&sblock); 3526 3527 /* 3528 * ensure a valid file system and if not, exit with error or else 3529 * we will end up computing block numbers etc and dividing by zero 3530 * which will cause floating point errors in this routine. 3531 */ 3532 3533 if ((sblock.fs_magic != FS_MAGIC) && 3534 (sblock.fs_magic != MTB_UFS_MAGIC)) { 3535 (void) fprintf(stderr, gettext( 3536 "[not currently a valid file system - bad superblock]\n")); 3537 lockexit(32); 3538 } 3539 3540 if (sblock.fs_magic == FS_MAGIC && 3541 (sblock.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 && 3542 sblock.fs_version != UFS_VERSION_MIN)) { 3543 (void) fprintf(stderr, gettext( 3544 "Unknown version of UFS format: %d\n"), sblock.fs_version); 3545 lockexit(32); 3546 } 3547 3548 if (sblock.fs_magic == MTB_UFS_MAGIC && 3549 (sblock.fs_version > MTB_UFS_VERSION_1 || 3550 sblock.fs_version < MTB_UFS_VERSION_MIN)) { 3551 (void) fprintf(stderr, gettext( 3552 "Unknown version of UFS format: %d\n"), sblock.fs_version); 3553 lockexit(32); 3554 } 3555 3556 /* 3557 * Compute a reasonable nbpi value. 3558 * The algorithm for "used" is copied from code 3559 * in main() verbatim. 3560 * The nbpi equation is taken from main where the 3561 * fs_ipg value is set for the last time. The INOPB(...) - 1 3562 * is used to account for the roundup. 3563 * The problem is that a range of nbpi values map to 3564 * the same file system layout. So it is not possible 3565 * to calculate the exact value specified when the file 3566 * system was created. So instead we determine the top 3567 * end of the range of values. 3568 */ 3569 bpcg = sblock.fs_spc * sectorsize; 3570 inospercg = (int64_t)roundup(bpcg / sizeof (struct dinode), 3571 INOPB(&sblock)); 3572 if (inospercg > MAXIpG(&sblock)) 3573 inospercg = MAXIpG(&sblock); 3574 used = (int64_t) 3575 (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock); 3576 used *= sectorsize; 3577 nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used; 3578 3579 /* 3580 * The top end of the range of values for nbpi may not be 3581 * a valid command line value for mkfs. Report the bottom 3582 * end instead. 3583 */ 3584 nbpi = (int64_t)(nbytes64 / (sblock.fs_ipg)); 3585 3586 (void) fprintf(stdout, gettext("mkfs -F ufs -o "), fsys); 3587 (void) fprintf(stdout, "nsect=%d,ntrack=%d,", 3588 sblock.fs_nsect, sblock.fs_ntrak); 3589 (void) fprintf(stdout, "bsize=%d,fragsize=%d,cgsize=%d,free=%d,", 3590 sblock.fs_bsize, sblock.fs_fsize, sblock.fs_cpg, sblock.fs_minfree); 3591 (void) fprintf(stdout, "rps=%d,nbpi=%lld,opt=%c,apc=%d,gap=%d,", 3592 sblock.fs_rps, nbpi, (sblock.fs_optim == FS_OPTSPACE) ? 's' : 't', 3593 (sblock.fs_ntrak * sblock.fs_nsect) - sblock.fs_spc, 3594 sblock.fs_rotdelay); 3595 (void) fprintf(stdout, "nrpos=%d,maxcontig=%d,mtb=%c ", 3596 sblock.fs_nrpos, sblock.fs_maxcontig, 3597 ((sblock.fs_magic == MTB_UFS_MAGIC) ? 'y' : 'n')); 3598 (void) fprintf(stdout, "%s %lld\n", fsys, 3599 fsbtodb(&sblock, sblock.fs_size)); 3600 3601 bzero((char *)&sblock, sizeof (sblock)); 3602 } 3603 3604 /* number ************************************************************* */ 3605 /* */ 3606 /* Convert a numeric string arg to binary */ 3607 /* */ 3608 /* Args: d_value - default value, if have parse error */ 3609 /* param - the name of the argument, for error messages */ 3610 /* flags - parser state and what's allowed in the arg */ 3611 /* Global arg: string - pointer to command arg */ 3612 /* */ 3613 /* Valid forms: 123 | 123k | 123*123 | 123x123 */ 3614 /* */ 3615 /* Return: converted number */ 3616 /* */ 3617 /* ******************************************************************** */ 3618 3619 static uint64_t 3620 number(uint64_t d_value, char *param, int flags) 3621 { 3622 char *cs; 3623 uint64_t n, t; 3624 uint64_t cut = BIG / 10; /* limit to avoid overflow */ 3625 int minus = 0; 3626 3627 cs = string; 3628 if (*cs == '-') { 3629 minus = 1; 3630 cs += 1; 3631 } 3632 if ((*cs < '0') || (*cs > '9')) { 3633 goto bail_out; 3634 } 3635 n = 0; 3636 while ((*cs >= '0') && (*cs <= '9') && (n <= cut)) { 3637 n = n*10 + *cs++ - '0'; 3638 } 3639 if (minus) 3640 n = -n; 3641 for (;;) { 3642 switch (*cs++) { 3643 case 'k': 3644 if (flags & ALLOW_END_ONLY) 3645 goto bail_out; 3646 if (n > (BIG / 1024)) 3647 goto overflow; 3648 n *= 1024; 3649 continue; 3650 3651 case '*': 3652 case 'x': 3653 if (flags & ALLOW_END_ONLY) 3654 goto bail_out; 3655 string = cs; 3656 t = number(d_value, param, flags); 3657 if (n > (BIG / t)) 3658 goto overflow; 3659 n *= t; 3660 cs = string + 1; /* adjust for -- below */ 3661 3662 /* recursion has read rest of expression */ 3663 /* FALLTHROUGH */ 3664 3665 case ',': 3666 case '\0': 3667 cs--; 3668 string = cs; 3669 return (n); 3670 3671 case '%': 3672 if (flags & ALLOW_END_ONLY) 3673 goto bail_out; 3674 if (flags & ALLOW_PERCENT) { 3675 flags &= ~ALLOW_PERCENT; 3676 flags |= ALLOW_END_ONLY; 3677 continue; 3678 } 3679 goto bail_out; 3680 3681 case 'm': 3682 if (flags & ALLOW_END_ONLY) 3683 goto bail_out; 3684 if (flags & ALLOW_MS1) { 3685 flags &= ~ALLOW_MS1; 3686 flags |= ALLOW_MS2; 3687 continue; 3688 } 3689 goto bail_out; 3690 3691 case 's': 3692 if (flags & ALLOW_END_ONLY) 3693 goto bail_out; 3694 if (flags & ALLOW_MS2) { 3695 flags &= ~ALLOW_MS2; 3696 flags |= ALLOW_END_ONLY; 3697 continue; 3698 } 3699 goto bail_out; 3700 3701 case '0': case '1': case '2': case '3': case '4': 3702 case '5': case '6': case '7': case '8': case '9': 3703 overflow: 3704 (void) fprintf(stderr, 3705 gettext("mkfs: value for %s overflowed\n"), 3706 param); 3707 while ((*cs != '\0') && (*cs != ',')) 3708 cs++; 3709 string = cs; 3710 return (BIG); 3711 3712 default: 3713 bail_out: 3714 (void) fprintf(stderr, gettext( 3715 "mkfs: bad numeric arg for %s: \"%s\"\n"), 3716 param, string); 3717 while ((*cs != '\0') && (*cs != ',')) 3718 cs++; 3719 string = cs; 3720 if (d_value != NO_DEFAULT) { 3721 (void) fprintf(stderr, 3722 gettext("mkfs: %s reset to default %lld\n"), 3723 param, d_value); 3724 return (d_value); 3725 } 3726 lockexit(2); 3727 3728 } 3729 } /* never gets here */ 3730 } 3731 3732 /* match ************************************************************** */ 3733 /* */ 3734 /* Compare two text strings for equality */ 3735 /* */ 3736 /* Arg: s - pointer to string to match with a command arg */ 3737 /* Global arg: string - pointer to command arg */ 3738 /* */ 3739 /* Return: 1 if match, 0 if no match */ 3740 /* If match, also reset `string' to point to the text */ 3741 /* that follows the matching text. */ 3742 /* */ 3743 /* ******************************************************************** */ 3744 3745 static int 3746 match(char *s) 3747 { 3748 char *cs; 3749 3750 cs = string; 3751 while (*cs++ == *s) { 3752 if (*s++ == '\0') { 3753 goto true; 3754 } 3755 } 3756 if (*s != '\0') { 3757 return (0); 3758 } 3759 3760 true: 3761 cs--; 3762 string = cs; 3763 return (1); 3764 } 3765 3766 /* 3767 * GROWFS ROUTINES 3768 */ 3769 3770 /* ARGSUSED */ 3771 void 3772 lockexit(int exitstatus) 3773 { 3774 if (Pflag) { 3775 /* the probe mode neither changes nor locks the filesystem */ 3776 exit(exitstatus); 3777 } 3778 3779 /* 3780 * flush the dirty cylinder group 3781 */ 3782 if (inlockexit == 0) { 3783 inlockexit = 1; 3784 flcg(); 3785 } 3786 3787 if (aio_inited) { 3788 flush_writes(); 3789 } 3790 3791 /* 3792 * make sure the file system is unlocked before exiting 3793 */ 3794 if ((inlockexit == 1) && (!isbad)) { 3795 inlockexit = 2; 3796 ulockfs(); 3797 /* 3798 * if logging was enabled, then re-enable it 3799 */ 3800 if (waslog) { 3801 if (rl_log_control(fsys, _FIOLOGENABLE) != RL_SUCCESS) { 3802 (void) fprintf(stderr, gettext( 3803 "failed to re-enable logging\n")); 3804 } 3805 } 3806 } else if (grow) { 3807 if (isbad) { 3808 (void) fprintf(stderr, gettext( 3809 "Filesystem is currently inconsistent. It " 3810 "must be repaired with fsck(1M)\nbefore being " 3811 "used. Use the following command to " 3812 "do this:\n\n\tfsck %s\n\n"), fsys); 3813 3814 if (ismounted) { 3815 (void) fprintf(stderr, gettext( 3816 "You will be told that the filesystem " 3817 "is already mounted, and asked if you\n" 3818 "wish to continue. Answer `yes' to " 3819 "this question.\n\n")); 3820 } 3821 3822 (void) fprintf(stderr, gettext( 3823 "One problem should be reported, that the summary " 3824 "information is bad.\nYou will then be asked if it " 3825 "should be salvaged. Answer `yes' to\nthis " 3826 "question.\n\n")); 3827 } 3828 3829 if (ismounted) { 3830 /* 3831 * In theory, there's no way to get here without 3832 * isbad also being set, but be robust in the 3833 * face of future code changes. 3834 */ 3835 (void) fprintf(stderr, gettext( 3836 "The filesystem is currently mounted " 3837 "read-only and write-locked. ")); 3838 if (isbad) { 3839 (void) fprintf(stderr, gettext( 3840 "After\nrunning fsck, unlock the " 3841 "filesystem and ")); 3842 } else { 3843 (void) fprintf(stderr, gettext( 3844 "Unlock the filesystem\nand ")); 3845 } 3846 3847 (void) fprintf(stderr, gettext( 3848 "re-enable writing with\nthe following " 3849 "command:\n\n\tlockfs -u %s\n\n"), directory); 3850 } 3851 } 3852 3853 exit(exitstatus); 3854 } 3855 3856 void 3857 randomgeneration() 3858 { 3859 int i; 3860 struct dinode *dp; 3861 3862 /* 3863 * always perform fsirand(1) function... newfs will notice that 3864 * the inodes have been randomized and will not call fsirand itself 3865 */ 3866 for (i = 0, dp = zino; i < sblock.fs_inopb; ++i, ++dp) 3867 IRANDOMIZE(&dp->di_ic); 3868 } 3869 3870 /* 3871 * Check the size of the summary information. 3872 * Fields in sblock are not changed in this function. 3873 * 3874 * For an 8K filesystem block, the maximum number of cylinder groups is 16384. 3875 * MAXCSBUFS {32} * 8K {FS block size} 3876 * divided by (sizeof csum) {16} 3877 * 3878 * Note that MAXCSBUFS is not used in the kernel; as of Solaris 2.6 build 32, 3879 * this is the only place where it's referenced. 3880 */ 3881 void 3882 checksummarysize() 3883 { 3884 diskaddr_t dmax; 3885 diskaddr_t dmin; 3886 int64_t cg0frags; 3887 int64_t cg0blocks; 3888 int64_t maxncg; 3889 int64_t maxfrags; 3890 uint64_t fs_size; 3891 uint64_t maxfs_blocks; /* filesystem blocks for max filesystem size */ 3892 3893 /* 3894 * compute the maximum summary info size 3895 */ 3896 dmin = cgdmin(&sblock, 0); 3897 dmax = cgbase(&sblock, 0) + sblock.fs_fpg; 3898 fs_size = (grow) ? grow_fs_size : sblock.fs_size; 3899 if (dmax > fs_size) 3900 dmax = fs_size; 3901 cg0frags = dmax - dmin; 3902 cg0blocks = cg0frags / sblock.fs_frag; 3903 cg0frags = cg0blocks * sblock.fs_frag; 3904 maxncg = (longlong_t)cg0blocks * 3905 (longlong_t)(sblock.fs_bsize / sizeof (struct csum)); 3906 3907 maxfs_blocks = FS_MAX; 3908 3909 if (maxncg > ((longlong_t)maxfs_blocks / (longlong_t)sblock.fs_fpg) + 1) 3910 maxncg = ((longlong_t)maxfs_blocks / 3911 (longlong_t)sblock.fs_fpg) + 1; 3912 3913 maxfrags = maxncg * (longlong_t)sblock.fs_fpg; 3914 3915 if (maxfrags > maxfs_blocks) 3916 maxfrags = maxfs_blocks; 3917 3918 3919 /* 3920 * remember for later processing in extendsummaryinfo() 3921 */ 3922 if (test) 3923 grow_sifrag = dmin + (cg0blocks * sblock.fs_frag); 3924 if (testfrags == 0) 3925 testfrags = cg0frags; 3926 if (testforce) 3927 if (testfrags > cg0frags) { 3928 (void) fprintf(stderr, 3929 gettext("Too many test frags (%lld); " 3930 "try %lld\n"), testfrags, cg0frags); 3931 lockexit(32); 3932 } 3933 3934 /* 3935 * if summary info is too large (too many cg's) tell the user and exit 3936 */ 3937 if ((longlong_t)sblock.fs_size > maxfrags) { 3938 (void) fprintf(stderr, gettext( 3939 "Too many cylinder groups with %llu sectors;\n try " 3940 "increasing cgsize, or decreasing fssize to %llu\n"), 3941 fsbtodb(&sblock, (uint64_t)sblock.fs_size), 3942 fsbtodb(&sblock, (uint64_t)maxfrags)); 3943 lockexit(32); 3944 } 3945 } 3946 3947 /* 3948 * checksblock() has two uses: 3949 * - One is to sanity test the superblock and is used when newfs(1M) 3950 * is invoked with the "-N" option. If any discrepancy was found, 3951 * just return whatever error was found and do not exit. 3952 * - the other use of it is in places where you expect the superblock 3953 * to be sane, and if it isn't, then we exit. 3954 * Which of the above two actions to take is indicated with the second argument. 3955 */ 3956 3957 int 3958 checksblock(struct fs sb, int proceed) 3959 { 3960 int err = 0; 3961 char *errmsg; 3962 3963 if ((sb.fs_magic != FS_MAGIC) && (sb.fs_magic != MTB_UFS_MAGIC)) { 3964 err = 1; 3965 errmsg = gettext("Bad superblock; magic number wrong\n"); 3966 } else if ((sb.fs_magic == FS_MAGIC && 3967 (sb.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 && 3968 sb.fs_version != UFS_VERSION_MIN)) || 3969 (sb.fs_magic == MTB_UFS_MAGIC && 3970 (sb.fs_version > MTB_UFS_VERSION_1 || 3971 sb.fs_version < MTB_UFS_VERSION_MIN))) { 3972 err = 2; 3973 errmsg = gettext("Unrecognized version of UFS\n"); 3974 } else if (sb.fs_ncg < 1) { 3975 err = 3; 3976 errmsg = gettext("Bad superblock; ncg out of range\n"); 3977 } else if (sb.fs_cpg < 1) { 3978 err = 4; 3979 errmsg = gettext("Bad superblock; cpg out of range\n"); 3980 } else if (sb.fs_ncg * sb.fs_cpg < sb.fs_ncyl || 3981 (sb.fs_ncg - 1) * sb.fs_cpg >= sb.fs_ncyl) { 3982 err = 5; 3983 errmsg = gettext("Bad superblock; ncyl out of range\n"); 3984 } else if (sb.fs_sbsize <= 0 || sb.fs_sbsize > sb.fs_bsize) { 3985 err = 6; 3986 errmsg = gettext("Bad superblock; superblock size out of " 3987 "range\n"); 3988 } 3989 3990 if (proceed) { 3991 if (err) dprintf(("%s", errmsg)); 3992 return (err); 3993 } 3994 3995 if (err) { 3996 fprintf(stderr, "%s", errmsg); 3997 lockexit(32); 3998 } 3999 return (32); 4000 } 4001 4002 /* 4003 * Roll the embedded log, if any, and set up the global variables 4004 * islog and islogok. 4005 */ 4006 static void 4007 logsetup(char *devstr) 4008 { 4009 void *buf, *ud_buf; 4010 extent_block_t *ebp; 4011 ml_unit_t *ul; 4012 ml_odunit_t *ud; 4013 4014 /* 4015 * Does the superblock indicate that we are supposed to have a log ? 4016 */ 4017 if (sblock.fs_logbno == 0) { 4018 /* 4019 * No log present, nothing to do. 4020 */ 4021 islog = 0; 4022 islogok = 0; 4023 return; 4024 } else { 4025 /* 4026 * There's a log in a yet unknown state, attempt to roll it. 4027 */ 4028 islogok = 0; 4029 4030 /* 4031 * We failed to roll the log, bail out. 4032 */ 4033 if (rl_roll_log(devstr) != RL_SUCCESS) 4034 return; 4035 4036 islog = 1; 4037 4038 /* log is not okay; check the fs */ 4039 if ((FSOKAY != (sblock.fs_state + sblock.fs_time)) || 4040 (sblock.fs_clean != FSLOG)) 4041 return; 4042 4043 /* get the log allocation block */ 4044 buf = (void *)malloc(DEV_BSIZE); 4045 if (buf == (void *) NULL) 4046 return; 4047 4048 ud_buf = (void *)malloc(DEV_BSIZE); 4049 if (ud_buf == (void *) NULL) { 4050 free(buf); 4051 return; 4052 } 4053 4054 rdfs((diskaddr_t)logbtodb(&sblock, sblock.fs_logbno), 4055 DEV_BSIZE, buf); 4056 ebp = (extent_block_t *)buf; 4057 4058 /* log allocation block is not okay; check the fs */ 4059 if (ebp->type != LUFS_EXTENTS) { 4060 free(buf); 4061 free(ud_buf); 4062 return; 4063 } 4064 4065 /* get the log state block(s) */ 4066 rdfs((diskaddr_t)logbtodb(&sblock, ebp->extents[0].pbno), 4067 DEV_BSIZE, ud_buf); 4068 ud = (ml_odunit_t *)ud_buf; 4069 ul = (ml_unit_t *)malloc(sizeof (*ul)); 4070 ul->un_ondisk = *ud; 4071 4072 /* log state is okay */ 4073 if ((ul->un_chksum == ul->un_head_ident + ul->un_tail_ident) && 4074 (ul->un_version == LUFS_VERSION_LATEST) && 4075 (ul->un_badlog == 0)) 4076 islogok = 1; 4077 free(ud_buf); 4078 free(buf); 4079 free(ul); 4080 } 4081 } 4082 4083 void 4084 growinit(char *devstr) 4085 { 4086 int i; 4087 char buf[DEV_BSIZE]; 4088 4089 /* 4090 * Read and verify the superblock 4091 */ 4092 rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock); 4093 (void) checksblock(sblock, 0); 4094 if (sblock.fs_postblformat != FS_DYNAMICPOSTBLFMT) { 4095 (void) fprintf(stderr, 4096 gettext("old file system format; can't growfs\n")); 4097 lockexit(32); 4098 } 4099 4100 /* 4101 * can't shrink a file system 4102 */ 4103 grow_fssize = fsbtodb(&sblock, (uint64_t)sblock.fs_size); 4104 if (fssize_db < grow_fssize) { 4105 (void) fprintf(stderr, 4106 gettext("%lld sectors < current size of %lld sectors\n"), 4107 fssize_db, grow_fssize); 4108 lockexit(32); 4109 } 4110 4111 /* 4112 * can't grow a system to over a terabyte unless it was set up 4113 * as an MTB UFS file system. 4114 */ 4115 if (mtb == 'y' && sblock.fs_magic != MTB_UFS_MAGIC) { 4116 if (fssize_db >= SECTORS_PER_TERABYTE) { 4117 (void) fprintf(stderr, gettext( 4118 "File system was not set up with the multi-terabyte format.\n")); 4119 (void) fprintf(stderr, gettext( 4120 "Its size cannot be increased to a terabyte or more.\n")); 4121 } else { 4122 (void) fprintf(stderr, gettext( 4123 "Cannot convert file system to multi-terabyte format.\n")); 4124 } 4125 lockexit(32); 4126 } 4127 4128 logsetup(devstr); 4129 4130 /* 4131 * can't growfs when logging device has errors 4132 */ 4133 if ((islog && !islogok) || 4134 ((FSOKAY == (sblock.fs_state + sblock.fs_time)) && 4135 (sblock.fs_clean == FSLOG && !islog))) { 4136 (void) fprintf(stderr, 4137 gettext("logging device has errors; can't growfs\n")); 4138 lockexit(32); 4139 } 4140 4141 /* 4142 * disable ufs logging for growing 4143 */ 4144 if (islog) { 4145 if (rl_log_control(devstr, _FIOLOGDISABLE) != RL_SUCCESS) { 4146 (void) fprintf(stderr, gettext( 4147 "failed to disable logging\n")); 4148 lockexit(32); 4149 } 4150 islog = 0; 4151 waslog = 1; 4152 } 4153 4154 /* 4155 * if mounted write lock the file system to be grown 4156 */ 4157 if (ismounted) 4158 wlockfs(); 4159 4160 /* 4161 * refresh dynamic superblock state - disabling logging will have 4162 * changed the amount of free space available in the file system 4163 */ 4164 rdfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock); 4165 4166 /* 4167 * make sure device is big enough 4168 */ 4169 rdfs((diskaddr_t)fssize_db - 1, DEV_BSIZE, buf); 4170 wtfs((diskaddr_t)fssize_db - 1, DEV_BSIZE, buf); 4171 4172 /* 4173 * read current summary information 4174 */ 4175 grow_fscs = read_summaryinfo(&sblock); 4176 4177 /* 4178 * save some current size related fields from the superblock 4179 * These are used in extendsummaryinfo() 4180 */ 4181 grow_fs_size = sblock.fs_size; 4182 grow_fs_ncg = sblock.fs_ncg; 4183 grow_fs_csaddr = (diskaddr_t)sblock.fs_csaddr; 4184 grow_fs_cssize = sblock.fs_cssize; 4185 4186 /* 4187 * save and reset the clean flag 4188 */ 4189 if (FSOKAY == (sblock.fs_state + sblock.fs_time)) 4190 grow_fs_clean = sblock.fs_clean; 4191 else 4192 grow_fs_clean = FSBAD; 4193 sblock.fs_clean = FSBAD; 4194 sblock.fs_state = FSOKAY - sblock.fs_time; 4195 isbad = 1; 4196 wtfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock); 4197 } 4198 4199 void 4200 checkdev(char *rdev, char *bdev) 4201 { 4202 struct stat64 statarea; 4203 4204 if (stat64(bdev, &statarea) < 0) { 4205 (void) fprintf(stderr, gettext("can't check mount point; ")); 4206 (void) fprintf(stderr, gettext("can't stat %s\n"), bdev); 4207 lockexit(32); 4208 } 4209 if ((statarea.st_mode & S_IFMT) != S_IFBLK) { 4210 (void) fprintf(stderr, gettext( 4211 "can't check mount point; %s is not a block device\n"), 4212 bdev); 4213 lockexit(32); 4214 } 4215 if (stat64(rdev, &statarea) < 0) { 4216 (void) fprintf(stderr, gettext("can't stat %s\n"), rdev); 4217 lockexit(32); 4218 } 4219 if ((statarea.st_mode & S_IFMT) != S_IFCHR) { 4220 (void) fprintf(stderr, 4221 gettext("%s is not a character device\n"), rdev); 4222 lockexit(32); 4223 } 4224 } 4225 4226 void 4227 checkmount(struct mnttab *mntp, char *bdevname) 4228 { 4229 struct stat64 statdir; 4230 struct stat64 statdev; 4231 4232 if (strcmp(bdevname, mntp->mnt_special) == 0) { 4233 if (stat64(mntp->mnt_mountp, &statdir) == -1) { 4234 (void) fprintf(stderr, gettext("can't stat %s\n"), 4235 mntp->mnt_mountp); 4236 lockexit(32); 4237 } 4238 if (stat64(mntp->mnt_special, &statdev) == -1) { 4239 (void) fprintf(stderr, gettext("can't stat %s\n"), 4240 mntp->mnt_special); 4241 lockexit(32); 4242 } 4243 if (statdir.st_dev != statdev.st_rdev) { 4244 (void) fprintf(stderr, gettext( 4245 "%s is not mounted on %s; mnttab(4) wrong\n"), 4246 mntp->mnt_special, mntp->mnt_mountp); 4247 lockexit(32); 4248 } 4249 ismounted = 1; 4250 if (directory) { 4251 if (strcmp(mntp->mnt_mountp, directory) != 0) { 4252 (void) fprintf(stderr, 4253 gettext("%s is mounted on %s, not %s\n"), 4254 bdevname, mntp->mnt_mountp, directory); 4255 lockexit(32); 4256 } 4257 } else { 4258 if (grow) 4259 (void) fprintf(stderr, gettext( 4260 "%s is mounted on %s; can't growfs\n"), 4261 bdevname, mntp->mnt_mountp); 4262 else 4263 (void) fprintf(stderr, 4264 gettext("%s is mounted, can't mkfs\n"), 4265 bdevname); 4266 lockexit(32); 4267 } 4268 } 4269 } 4270 4271 struct dinode *dibuf = 0; 4272 diskaddr_t difrag = 0; 4273 4274 struct dinode * 4275 gdinode(ino_t ino) 4276 { 4277 /* 4278 * read the block of inodes containing inode number ino 4279 */ 4280 if (dibuf == 0) 4281 dibuf = (struct dinode *)malloc((unsigned)sblock.fs_bsize); 4282 if (itod(&sblock, ino) != difrag) { 4283 difrag = itod(&sblock, ino); 4284 rdfs(fsbtodb(&sblock, (uint64_t)difrag), (int)sblock.fs_bsize, 4285 (char *)dibuf); 4286 } 4287 return (dibuf + (ino % INOPB(&sblock))); 4288 } 4289 4290 /* 4291 * structure that manages the frags we need for extended summary info 4292 * These frags can be: 4293 * free 4294 * data block 4295 * alloc block 4296 */ 4297 struct csfrag { 4298 struct csfrag *next; /* next entry */ 4299 daddr32_t ofrag; /* old frag */ 4300 daddr32_t nfrag; /* new frag */ 4301 long cylno; /* cylno of nfrag */ 4302 long frags; /* number of frags */ 4303 long size; /* size in bytes */ 4304 ino_t ino; /* inode number */ 4305 long fixed; /* Boolean - Already fixed? */ 4306 }; 4307 struct csfrag *csfrag; /* state unknown */ 4308 struct csfrag *csfragino; /* frags belonging to an inode */ 4309 struct csfrag *csfragfree; /* frags that are free */ 4310 4311 daddr32_t maxcsfrag = 0; /* maximum in range */ 4312 daddr32_t mincsfrag = 0x7fffffff; /* minimum in range */ 4313 4314 int 4315 csfraginrange(daddr32_t frag) 4316 { 4317 return ((frag >= mincsfrag) && (frag <= maxcsfrag)); 4318 } 4319 4320 struct csfrag * 4321 findcsfrag(daddr32_t frag, struct csfrag **cfap) 4322 { 4323 struct csfrag *cfp; 4324 4325 if (!csfraginrange(frag)) 4326 return (NULL); 4327 4328 for (cfp = *cfap; cfp; cfp = cfp->next) 4329 if (cfp->ofrag == frag) 4330 return (cfp); 4331 return (NULL); 4332 } 4333 4334 void 4335 checkindirect(ino_t ino, daddr32_t *fragsp, daddr32_t frag, int level) 4336 { 4337 int i; 4338 int ne = sblock.fs_bsize / sizeof (daddr32_t); 4339 daddr32_t fsb[MAXBSIZE / sizeof (daddr32_t)]; 4340 4341 if (frag == 0) 4342 return; 4343 4344 rdfs(fsbtodb(&sblock, frag), (int)sblock.fs_bsize, 4345 (char *)fsb); 4346 4347 checkdirect(ino, fragsp, fsb, sblock.fs_bsize / sizeof (daddr32_t)); 4348 4349 if (level) 4350 for (i = 0; i < ne && *fragsp; ++i) 4351 checkindirect(ino, fragsp, fsb[i], level-1); 4352 } 4353 4354 void 4355 addcsfrag(ino_t ino, daddr32_t frag, struct csfrag **cfap) 4356 { 4357 struct csfrag *cfp, *curr, *prev; 4358 4359 /* 4360 * establish a range for faster checking in csfraginrange() 4361 */ 4362 if (frag > maxcsfrag) 4363 maxcsfrag = frag; 4364 if (frag < mincsfrag) 4365 mincsfrag = frag; 4366 4367 /* 4368 * if this frag belongs to an inode and is not the start of a block 4369 * then see if it is part of a frag range for this inode 4370 */ 4371 if (ino && (frag % sblock.fs_frag)) 4372 for (cfp = *cfap; cfp; cfp = cfp->next) { 4373 if (ino != cfp->ino) 4374 continue; 4375 if (frag != cfp->ofrag + cfp->frags) 4376 continue; 4377 cfp->frags++; 4378 cfp->size += sblock.fs_fsize; 4379 return; 4380 } 4381 /* 4382 * allocate a csfrag entry and insert it in an increasing order into the 4383 * specified list 4384 */ 4385 cfp = (struct csfrag *)calloc(1, sizeof (struct csfrag)); 4386 cfp->ino = ino; 4387 cfp->ofrag = frag; 4388 cfp->frags = 1; 4389 cfp->size = sblock.fs_fsize; 4390 for (prev = NULL, curr = *cfap; curr != NULL; 4391 prev = curr, curr = curr->next) { 4392 if (frag < curr->ofrag) { 4393 cfp->next = curr; 4394 if (prev) 4395 prev->next = cfp; /* middle element */ 4396 else 4397 *cfap = cfp; /* first element */ 4398 break; 4399 } 4400 if (curr->next == NULL) { 4401 curr->next = cfp; /* last element */ 4402 break; 4403 } 4404 } 4405 if (*cfap == NULL) /* will happen only once */ 4406 *cfap = cfp; 4407 } 4408 4409 void 4410 delcsfrag(daddr32_t frag, struct csfrag **cfap) 4411 { 4412 struct csfrag *cfp; 4413 struct csfrag **cfpp; 4414 4415 /* 4416 * free up entry whose beginning frag matches 4417 */ 4418 for (cfpp = cfap; *cfpp; cfpp = &(*cfpp)->next) { 4419 if (frag == (*cfpp)->ofrag) { 4420 cfp = *cfpp; 4421 *cfpp = (*cfpp)->next; 4422 free((char *)cfp); 4423 return; 4424 } 4425 } 4426 } 4427 4428 /* 4429 * See whether any of the direct blocks in the array pointed by "db" and of 4430 * length "ne" are within the range of frags needed to extend the cylinder 4431 * summary. If so, remove those frags from the "as-yet-unclassified" list 4432 * (csfrag) and add them to the "owned-by-inode" list (csfragino). 4433 * For each such frag found, decrement the frag count pointed to by fragsp. 4434 * "ino" is the inode that contains (either directly or indirectly) the frags 4435 * being checked. 4436 */ 4437 void 4438 checkdirect(ino_t ino, daddr32_t *fragsp, daddr32_t *db, int ne) 4439 { 4440 int i; 4441 int j; 4442 int found; 4443 diskaddr_t frag; 4444 4445 /* 4446 * scan for allocation within the new summary info range 4447 */ 4448 for (i = 0; i < ne && *fragsp; ++i) { 4449 if ((frag = *db++) != 0) { 4450 found = 0; 4451 for (j = 0; j < sblock.fs_frag && *fragsp; ++j) { 4452 if (found || (found = csfraginrange(frag))) { 4453 addcsfrag(ino, frag, &csfragino); 4454 delcsfrag(frag, &csfrag); 4455 } 4456 ++frag; 4457 --(*fragsp); 4458 } 4459 } 4460 } 4461 } 4462 4463 void 4464 findcsfragino() 4465 { 4466 int i; 4467 int j; 4468 daddr32_t frags; 4469 struct dinode *dp; 4470 4471 /* 4472 * scan all old inodes looking for allocations in the new 4473 * summary info range. Move the affected frag from the 4474 * generic csfrag list onto the `owned-by-inode' list csfragino. 4475 */ 4476 for (i = UFSROOTINO; i < grow_fs_ncg*sblock.fs_ipg && csfrag; ++i) { 4477 dp = gdinode((ino_t)i); 4478 switch (dp->di_mode & IFMT) { 4479 case IFSHAD : 4480 case IFLNK : 4481 case IFDIR : 4482 case IFREG : break; 4483 default : continue; 4484 } 4485 4486 frags = dbtofsb(&sblock, dp->di_blocks); 4487 4488 checkdirect((ino_t)i, &frags, &dp->di_db[0], NDADDR+NIADDR); 4489 for (j = 0; j < NIADDR && frags; ++j) { 4490 /* Negate the block if its an fallocate'd block */ 4491 if (dp->di_ib[j] < 0 && dp->di_ib[j] != UFS_HOLE) 4492 checkindirect((ino_t)i, &frags, 4493 -(dp->di_ib[j]), j); 4494 else 4495 checkindirect((ino_t)i, &frags, 4496 dp->di_ib[j], j); 4497 } 4498 } 4499 } 4500 4501 void 4502 fixindirect(daddr32_t frag, int level) 4503 { 4504 int i; 4505 int ne = sblock.fs_bsize / sizeof (daddr32_t); 4506 daddr32_t fsb[MAXBSIZE / sizeof (daddr32_t)]; 4507 4508 if (frag == 0) 4509 return; 4510 4511 rdfs(fsbtodb(&sblock, (uint64_t)frag), (int)sblock.fs_bsize, 4512 (char *)fsb); 4513 4514 fixdirect((caddr_t)fsb, frag, fsb, ne); 4515 4516 if (level) 4517 for (i = 0; i < ne; ++i) 4518 fixindirect(fsb[i], level-1); 4519 } 4520 4521 void 4522 fixdirect(caddr_t bp, daddr32_t frag, daddr32_t *db, int ne) 4523 { 4524 int i; 4525 struct csfrag *cfp; 4526 4527 for (i = 0; i < ne; ++i, ++db) { 4528 if (*db == 0) 4529 continue; 4530 if ((cfp = findcsfrag(*db, &csfragino)) == NULL) 4531 continue; 4532 *db = cfp->nfrag; 4533 cfp->fixed = 1; 4534 wtfs(fsbtodb(&sblock, (uint64_t)frag), (int)sblock.fs_bsize, 4535 bp); 4536 } 4537 } 4538 4539 void 4540 fixcsfragino() 4541 { 4542 int i; 4543 struct dinode *dp; 4544 struct csfrag *cfp; 4545 4546 for (cfp = csfragino; cfp; cfp = cfp->next) { 4547 if (cfp->fixed) 4548 continue; 4549 dp = gdinode((ino_t)cfp->ino); 4550 fixdirect((caddr_t)dibuf, difrag, dp->di_db, NDADDR+NIADDR); 4551 for (i = 0; i < NIADDR; ++i) 4552 fixindirect(dp->di_ib[i], i); 4553 } 4554 } 4555 4556 /* 4557 * Read the cylinders summary information specified by settings in the 4558 * passed 'fs' structure into a new allocated array of csum structures. 4559 * The caller is responsible for freeing the returned array. 4560 * Return a pointer to an array of csum structures. 4561 */ 4562 static struct csum * 4563 read_summaryinfo(struct fs *fsp) 4564 { 4565 struct csum *csp; 4566 int i; 4567 4568 if ((csp = malloc((size_t)fsp->fs_cssize)) == NULL) { 4569 (void) fprintf(stderr, gettext("cannot create csum list," 4570 " not enough memory\n")); 4571 exit(32); 4572 } 4573 4574 for (i = 0; i < fsp->fs_cssize; i += fsp->fs_bsize) { 4575 rdfs(fsbtodb(fsp, 4576 (uint64_t)(fsp->fs_csaddr + numfrags(fsp, i))), 4577 (int)(fsp->fs_cssize - i < fsp->fs_bsize ? 4578 fsp->fs_cssize - i : fsp->fs_bsize), ((caddr_t)csp) + i); 4579 } 4580 4581 return (csp); 4582 } 4583 4584 /* 4585 * Check the allocation of fragments that are to be made part of a csum block. 4586 * A fragment is allocated if it is either in the csfragfree list or, it is 4587 * in the csfragino list and has new frags associated with it. 4588 * Return the number of allocated fragments. 4589 */ 4590 int64_t 4591 checkfragallocated(daddr32_t frag) 4592 { 4593 struct csfrag *cfp; 4594 /* 4595 * Since the lists are sorted we can break the search if the asked 4596 * frag is smaller then the one in the list. 4597 */ 4598 for (cfp = csfragfree; cfp != NULL && frag >= cfp->ofrag; 4599 cfp = cfp->next) { 4600 if (frag == cfp->ofrag) 4601 return (1); 4602 } 4603 for (cfp = csfragino; cfp != NULL && frag >= cfp->ofrag; 4604 cfp = cfp->next) { 4605 if (frag == cfp->ofrag && cfp->nfrag != 0) 4606 return (cfp->frags); 4607 } 4608 4609 return (0); 4610 } 4611 4612 /* 4613 * Figure out how much the filesystem can be grown. The limiting factor is 4614 * the available free space needed to extend the cg summary info block. 4615 * The free space is determined in three steps: 4616 * - Try to extend the cg summary block to the required size. 4617 * - Find free blocks in last cg. 4618 * - Find free space in the last already allocated fragment of the summary info 4619 * block, and use it for additional csum structures. 4620 * Return the maximum size of the new filesystem or 0 if it can't be grown. 4621 * Please note that this function leaves the global list pointers csfrag, 4622 * csfragfree, and csfragino initialized, and the caller is responsible for 4623 * freeing the lists. 4624 */ 4625 diskaddr_t 4626 probe_summaryinfo() 4627 { 4628 /* fragments by which the csum block can be extended. */ 4629 int64_t growth_csum_frags = 0; 4630 /* fragments by which the filesystem can be extended. */ 4631 int64_t growth_fs_frags = 0; 4632 int64_t new_fs_cssize; /* size of csum blk in the new FS */ 4633 int64_t new_fs_ncg; /* number of cg in the new FS */ 4634 int64_t spare_csum; 4635 daddr32_t oldfrag_daddr; 4636 daddr32_t newfrag_daddr; 4637 daddr32_t daddr; 4638 int i; 4639 4640 /* 4641 * read and verify the superblock 4642 */ 4643 rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock); 4644 (void) checksblock(sblock, 0); 4645 4646 /* 4647 * check how much we can extend the cg summary info block 4648 */ 4649 4650 /* 4651 * read current summary information 4652 */ 4653 fscs = read_summaryinfo(&sblock); 4654 4655 /* 4656 * build list of frags needed for cg summary info block extension 4657 */ 4658 oldfrag_daddr = howmany(sblock.fs_cssize, sblock.fs_fsize) + 4659 sblock.fs_csaddr; 4660 new_fs_ncg = howmany(dbtofsb(&sblock, fssize_db), sblock.fs_fpg); 4661 new_fs_cssize = fragroundup(&sblock, new_fs_ncg * sizeof (struct csum)); 4662 newfrag_daddr = howmany(new_fs_cssize, sblock.fs_fsize) + 4663 sblock.fs_csaddr; 4664 /* 4665 * add all of the frags that are required to grow the cyl summary to the 4666 * csfrag list, which is the generic/unknown list, since at this point 4667 * we don't yet know the state of those frags. 4668 */ 4669 for (daddr = oldfrag_daddr; daddr < newfrag_daddr; daddr++) 4670 addcsfrag((ino_t)0, daddr, &csfrag); 4671 4672 /* 4673 * filter free fragments and allocate them. Note that the free frags 4674 * must be allocated first otherwise they could be grabbed by 4675 * alloccsfragino() for data frags. 4676 */ 4677 findcsfragfree(); 4678 alloccsfragfree(); 4679 4680 /* 4681 * filter fragments owned by inodes and allocate them 4682 */ 4683 grow_fs_ncg = sblock.fs_ncg; /* findcsfragino() needs this glob. var. */ 4684 findcsfragino(); 4685 alloccsfragino(); 4686 4687 if (notenoughspace()) { 4688 /* 4689 * check how many consecutive fragments could be allocated 4690 * in both lists. 4691 */ 4692 int64_t tmp_frags; 4693 for (daddr = oldfrag_daddr; daddr < newfrag_daddr; 4694 daddr += tmp_frags) { 4695 if ((tmp_frags = checkfragallocated(daddr)) > 0) 4696 growth_csum_frags += tmp_frags; 4697 else 4698 break; 4699 } 4700 } else { 4701 /* 4702 * We have all we need for the new desired size, 4703 * so clean up and report back. 4704 */ 4705 return (fssize_db); 4706 } 4707 4708 /* 4709 * given the number of fragments by which the csum block can be grown 4710 * compute by how many new fragments the FS can be increased. 4711 * It is the number of csum instances per fragment multiplied by 4712 * `growth_csum_frags' and the number of fragments per cylinder group. 4713 */ 4714 growth_fs_frags = howmany(sblock.fs_fsize, sizeof (struct csum)) * 4715 growth_csum_frags * sblock.fs_fpg; 4716 4717 /* 4718 * compute free fragments in the last cylinder group 4719 */ 4720 rdcg(sblock.fs_ncg - 1); 4721 growth_fs_frags += sblock.fs_fpg - acg.cg_ndblk; 4722 4723 /* 4724 * compute how many csum instances are unused in the old csum block. 4725 * For each unused csum instance the FS can be grown by one cylinder 4726 * group without extending the csum block. 4727 */ 4728 spare_csum = howmany(sblock.fs_cssize, sizeof (struct csum)) - 4729 sblock.fs_ncg; 4730 if (spare_csum > 0) 4731 growth_fs_frags += spare_csum * sblock.fs_fpg; 4732 4733 /* 4734 * recalculate the new filesystem size in sectors, shorten it by 4735 * the requested size `fssize_db' if necessary. 4736 */ 4737 if (growth_fs_frags > 0) { 4738 diskaddr_t sect; 4739 sect = (sblock.fs_size + growth_fs_frags) * sblock.fs_nspf; 4740 return ((sect > fssize_db) ? fssize_db : sect); 4741 } 4742 4743 return (0); 4744 } 4745 4746 void 4747 extendsummaryinfo() 4748 { 4749 int64_t i; 4750 int localtest = test; 4751 int64_t frags; 4752 daddr32_t oldfrag; 4753 daddr32_t newfrag; 4754 4755 /* 4756 * if no-write (-N), don't bother 4757 */ 4758 if (Nflag) 4759 return; 4760 4761 again: 4762 flcg(); 4763 /* 4764 * summary info did not change size -- do nothing unless in test mode 4765 */ 4766 if (grow_fs_cssize == sblock.fs_cssize) 4767 if (!localtest) 4768 return; 4769 4770 /* 4771 * build list of frags needed for additional summary information 4772 */ 4773 oldfrag = howmany(grow_fs_cssize, sblock.fs_fsize) + grow_fs_csaddr; 4774 newfrag = howmany(sblock.fs_cssize, sblock.fs_fsize) + grow_fs_csaddr; 4775 /* 4776 * add all of the frags that are required to grow the cyl summary to the 4777 * csfrag list, which is the generic/unknown list, since at this point 4778 * we don't yet know the state of those frags. 4779 */ 4780 for (i = oldfrag, frags = 0; i < newfrag; ++i, ++frags) 4781 addcsfrag((ino_t)0, (diskaddr_t)i, &csfrag); 4782 /* 4783 * reduce the number of data blocks in the file system (fs_dsize) by 4784 * the number of frags that need to be added to the cyl summary 4785 */ 4786 sblock.fs_dsize -= (newfrag - oldfrag); 4787 4788 /* 4789 * In test mode, we move more data than necessary from 4790 * cylinder group 0. The lookup/allocate/move code can be 4791 * better stressed without having to create HUGE file systems. 4792 */ 4793 if (localtest) 4794 for (i = newfrag; i < grow_sifrag; ++i) { 4795 if (frags >= testfrags) 4796 break; 4797 frags++; 4798 addcsfrag((ino_t)0, (diskaddr_t)i, &csfrag); 4799 } 4800 4801 /* 4802 * move frags to free or inode lists, depending on owner 4803 */ 4804 findcsfragfree(); 4805 findcsfragino(); 4806 4807 /* 4808 * if not all frags can be located, file system must be inconsistent 4809 */ 4810 if (csfrag) { 4811 isbad = 1; /* should already be set, but make sure */ 4812 lockexit(32); 4813 } 4814 4815 /* 4816 * allocate the free frags. Note that the free frags must be allocated 4817 * first otherwise they could be grabbed by alloccsfragino() for data 4818 * frags. 4819 */ 4820 alloccsfragfree(); 4821 /* 4822 * allocate extra space for inode frags 4823 */ 4824 alloccsfragino(); 4825 4826 /* 4827 * not enough space 4828 */ 4829 if (notenoughspace()) { 4830 unalloccsfragfree(); 4831 unalloccsfragino(); 4832 if (localtest && !testforce) { 4833 localtest = 0; 4834 goto again; 4835 } 4836 (void) fprintf(stderr, gettext("Not enough free space\n")); 4837 lockexit(NOTENOUGHSPACE); 4838 } 4839 4840 /* 4841 * copy the data from old frags to new frags 4842 */ 4843 copycsfragino(); 4844 4845 /* 4846 * fix the inodes to point to the new frags 4847 */ 4848 fixcsfragino(); 4849 4850 /* 4851 * We may have moved more frags than we needed. Free them. 4852 */ 4853 rdcg((long)0); 4854 for (i = newfrag; i <= maxcsfrag; ++i) 4855 setbit(cg_blksfree(&acg), i-cgbase(&sblock, 0)); 4856 wtcg(); 4857 4858 flcg(); 4859 } 4860 4861 /* 4862 * Check if all fragments in the `csfragino' list were reallocated. 4863 */ 4864 int 4865 notenoughspace() 4866 { 4867 struct csfrag *cfp; 4868 4869 /* 4870 * If any element in the csfragino array has a "new frag location" 4871 * of 0, the allocfrags() function was unsuccessful in allocating 4872 * space for moving the frag represented by this array element. 4873 */ 4874 for (cfp = csfragino; cfp; cfp = cfp->next) 4875 if (cfp->nfrag == 0) 4876 return (1); 4877 return (0); 4878 } 4879 4880 void 4881 unalloccsfragino() 4882 { 4883 struct csfrag *cfp; 4884 4885 while ((cfp = csfragino) != NULL) { 4886 if (cfp->nfrag) 4887 freefrags(cfp->nfrag, cfp->frags, cfp->cylno); 4888 delcsfrag(cfp->ofrag, &csfragino); 4889 } 4890 } 4891 4892 void 4893 unalloccsfragfree() 4894 { 4895 struct csfrag *cfp; 4896 4897 while ((cfp = csfragfree) != NULL) { 4898 freefrags(cfp->ofrag, cfp->frags, cfp->cylno); 4899 delcsfrag(cfp->ofrag, &csfragfree); 4900 } 4901 } 4902 4903 /* 4904 * For each frag in the "as-yet-unclassified" list (csfrag), see if 4905 * it's free (i.e., its bit is set in the free frag bit map). If so, 4906 * move it from the "as-yet-unclassified" list to the csfragfree list. 4907 */ 4908 void 4909 findcsfragfree() 4910 { 4911 struct csfrag *cfp; 4912 struct csfrag *cfpnext; 4913 4914 /* 4915 * move free frags onto the free-frag list 4916 */ 4917 rdcg((long)0); 4918 for (cfp = csfrag; cfp; cfp = cfpnext) { 4919 cfpnext = cfp->next; 4920 if (isset(cg_blksfree(&acg), cfp->ofrag - cgbase(&sblock, 0))) { 4921 addcsfrag(cfp->ino, cfp->ofrag, &csfragfree); 4922 delcsfrag(cfp->ofrag, &csfrag); 4923 } 4924 } 4925 } 4926 4927 void 4928 copycsfragino() 4929 { 4930 struct csfrag *cfp; 4931 char buf[MAXBSIZE]; 4932 4933 /* 4934 * copy data from old frags to newly allocated frags 4935 */ 4936 for (cfp = csfragino; cfp; cfp = cfp->next) { 4937 rdfs(fsbtodb(&sblock, (uint64_t)cfp->ofrag), (int)cfp->size, 4938 buf); 4939 wtfs(fsbtodb(&sblock, (uint64_t)cfp->nfrag), (int)cfp->size, 4940 buf); 4941 } 4942 } 4943 4944 long curcylno = -1; 4945 int cylnodirty = 0; 4946 4947 void 4948 rdcg(long cylno) 4949 { 4950 if (cylno != curcylno) { 4951 flcg(); 4952 curcylno = cylno; 4953 rdfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, curcylno)), 4954 (int)sblock.fs_cgsize, (char *)&acg); 4955 } 4956 } 4957 4958 void 4959 flcg() 4960 { 4961 if (cylnodirty) { 4962 if (debug && Pflag) { 4963 (void) fprintf(stderr, 4964 "Assert: cylnodirty set in probe mode\n"); 4965 return; 4966 } 4967 resetallocinfo(); 4968 wtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, curcylno)), 4969 (int)sblock.fs_cgsize, (char *)&acg); 4970 cylnodirty = 0; 4971 } 4972 curcylno = -1; 4973 } 4974 4975 void 4976 wtcg() 4977 { 4978 if (!Pflag) { 4979 /* probe mode should never write to disk */ 4980 cylnodirty = 1; 4981 } 4982 } 4983 4984 void 4985 allocfrags(long frags, daddr32_t *fragp, long *cylnop) 4986 { 4987 int i; 4988 int j; 4989 long bits; 4990 long bit; 4991 4992 /* 4993 * Allocate a free-frag range in an old cylinder group 4994 */ 4995 for (i = 0, *fragp = 0; i < grow_fs_ncg; ++i) { 4996 if (((fscs+i)->cs_nffree < frags) && ((fscs+i)->cs_nbfree == 0)) 4997 continue; 4998 rdcg((long)i); 4999 bit = bits = 0; 5000 while (findfreerange(&bit, &bits)) { 5001 if (frags <= bits) { 5002 for (j = 0; j < frags; ++j) 5003 clrbit(cg_blksfree(&acg), bit+j); 5004 wtcg(); 5005 *cylnop = i; 5006 *fragp = bit + cgbase(&sblock, i); 5007 return; 5008 } 5009 bit += bits; 5010 } 5011 } 5012 } 5013 5014 /* 5015 * Allocate space for frags that need to be moved in order to free up space for 5016 * expanding the cylinder summary info. 5017 * For each frag that needs to be moved (each frag or range of frags in 5018 * the csfragino list), allocate a new location and store the frag number 5019 * of that new location in the nfrag field of the csfrag struct. 5020 * If a new frag can't be allocated for any element in the csfragino list, 5021 * set the new frag number for that element to 0 and return immediately. 5022 * The notenoughspace() function will detect this condition. 5023 */ 5024 void 5025 alloccsfragino() 5026 { 5027 struct csfrag *cfp; 5028 5029 /* 5030 * allocate space for inode frag ranges 5031 */ 5032 for (cfp = csfragino; cfp; cfp = cfp->next) { 5033 allocfrags(cfp->frags, &cfp->nfrag, &cfp->cylno); 5034 if (cfp->nfrag == 0) 5035 break; 5036 } 5037 } 5038 5039 void 5040 alloccsfragfree() 5041 { 5042 struct csfrag *cfp; 5043 5044 /* 5045 * allocate the free frags needed for extended summary info 5046 */ 5047 rdcg((long)0); 5048 5049 for (cfp = csfragfree; cfp; cfp = cfp->next) 5050 clrbit(cg_blksfree(&acg), cfp->ofrag - cgbase(&sblock, 0)); 5051 5052 wtcg(); 5053 } 5054 5055 void 5056 freefrags(daddr32_t frag, long frags, long cylno) 5057 { 5058 int i; 5059 5060 /* 5061 * free frags 5062 */ 5063 rdcg(cylno); 5064 for (i = 0; i < frags; ++i) { 5065 setbit(cg_blksfree(&acg), (frag+i) - cgbase(&sblock, cylno)); 5066 } 5067 wtcg(); 5068 } 5069 5070 int 5071 findfreerange(long *bitp, long *bitsp) 5072 { 5073 long bit; 5074 5075 /* 5076 * find a range of free bits in a cylinder group bit map 5077 */ 5078 for (bit = *bitp, *bitsp = 0; bit < acg.cg_ndblk; ++bit) 5079 if (isset(cg_blksfree(&acg), bit)) 5080 break; 5081 5082 if (bit >= acg.cg_ndblk) 5083 return (0); 5084 5085 *bitp = bit; 5086 *bitsp = 1; 5087 for (++bit; bit < acg.cg_ndblk; ++bit, ++(*bitsp)) { 5088 if ((bit % sblock.fs_frag) == 0) 5089 break; 5090 if (isclr(cg_blksfree(&acg), bit)) 5091 break; 5092 } 5093 return (1); 5094 } 5095 5096 void 5097 resetallocinfo() 5098 { 5099 long cno; 5100 long bit; 5101 long bits; 5102 5103 /* 5104 * Compute the free blocks/frags info and update the appropriate 5105 * inmemory superblock, summary info, and cylinder group fields 5106 */ 5107 sblock.fs_cstotal.cs_nffree -= acg.cg_cs.cs_nffree; 5108 sblock.fs_cstotal.cs_nbfree -= acg.cg_cs.cs_nbfree; 5109 5110 acg.cg_cs.cs_nffree = 0; 5111 acg.cg_cs.cs_nbfree = 0; 5112 5113 bzero((caddr_t)acg.cg_frsum, sizeof (acg.cg_frsum)); 5114 bzero((caddr_t)cg_blktot(&acg), (int)(acg.cg_iusedoff-acg.cg_btotoff)); 5115 5116 bit = bits = 0; 5117 while (findfreerange(&bit, &bits)) { 5118 if (bits == sblock.fs_frag) { 5119 acg.cg_cs.cs_nbfree++; 5120 cno = cbtocylno(&sblock, bit); 5121 cg_blktot(&acg)[cno]++; 5122 cg_blks(&sblock, &acg, cno)[cbtorpos(&sblock, bit)]++; 5123 } else { 5124 acg.cg_cs.cs_nffree += bits; 5125 acg.cg_frsum[bits]++; 5126 } 5127 bit += bits; 5128 } 5129 5130 *(fscs + acg.cg_cgx) = acg.cg_cs; 5131 5132 sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; 5133 sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; 5134 } 5135 5136 void 5137 extendcg(long cylno) 5138 { 5139 int i; 5140 diskaddr_t dupper; 5141 diskaddr_t cbase; 5142 diskaddr_t dmax; 5143 5144 /* 5145 * extend the cylinder group at the end of the old file system 5146 * if it was partially allocated becase of lack of space 5147 */ 5148 flcg(); 5149 rdcg(cylno); 5150 5151 dupper = acg.cg_ndblk; 5152 if (cylno == sblock.fs_ncg - 1) 5153 acg.cg_ncyl = sblock.fs_ncyl - (sblock.fs_cpg * cylno); 5154 else 5155 acg.cg_ncyl = sblock.fs_cpg; 5156 cbase = cgbase(&sblock, cylno); 5157 dmax = cbase + sblock.fs_fpg; 5158 if (dmax > sblock.fs_size) 5159 dmax = sblock.fs_size; 5160 acg.cg_ndblk = dmax - cbase; 5161 5162 for (i = dupper; i < acg.cg_ndblk; ++i) 5163 setbit(cg_blksfree(&acg), i); 5164 5165 sblock.fs_dsize += (acg.cg_ndblk - dupper); 5166 5167 wtcg(); 5168 flcg(); 5169 } 5170 5171 struct lockfs lockfs; 5172 int lockfd; 5173 int islocked; 5174 int lockfskey; 5175 char lockfscomment[128]; 5176 5177 void 5178 ulockfs() 5179 { 5180 /* 5181 * if the file system was locked, unlock it before exiting 5182 */ 5183 if (islocked == 0) 5184 return; 5185 5186 /* 5187 * first, check if the lock held 5188 */ 5189 lockfs.lf_flags = LOCKFS_MOD; 5190 if (ioctl(lockfd, _FIOLFSS, &lockfs) == -1) { 5191 perror(directory); 5192 lockexit(32); 5193 } 5194 5195 if (LOCKFS_IS_MOD(&lockfs)) { 5196 (void) fprintf(stderr, 5197 gettext("FILE SYSTEM CHANGED DURING GROWFS!\n")); 5198 (void) fprintf(stderr, 5199 gettext(" See lockfs(1), umount(1), and fsck(1)\n")); 5200 lockexit(32); 5201 } 5202 /* 5203 * unlock the file system 5204 */ 5205 lockfs.lf_lock = LOCKFS_ULOCK; 5206 lockfs.lf_flags = 0; 5207 lockfs.lf_key = lockfskey; 5208 clockfs(); 5209 if (ioctl(lockfd, _FIOLFS, &lockfs) == -1) { 5210 perror(directory); 5211 lockexit(32); 5212 } 5213 } 5214 5215 void 5216 wlockfs() 5217 { 5218 5219 /* 5220 * if no-write (-N), don't bother 5221 */ 5222 if (Nflag) 5223 return; 5224 /* 5225 * open the mountpoint, and write lock the file system 5226 */ 5227 if ((lockfd = open64(directory, O_RDONLY)) == -1) { 5228 perror(directory); 5229 lockexit(32); 5230 } 5231 5232 /* 5233 * check if it is already locked 5234 */ 5235 if (ioctl(lockfd, _FIOLFSS, &lockfs) == -1) { 5236 perror(directory); 5237 lockexit(32); 5238 } 5239 5240 if (lockfs.lf_lock != LOCKFS_WLOCK) { 5241 lockfs.lf_lock = LOCKFS_WLOCK; 5242 lockfs.lf_flags = 0; 5243 lockfs.lf_key = 0; 5244 clockfs(); 5245 if (ioctl(lockfd, _FIOLFS, &lockfs) == -1) { 5246 perror(directory); 5247 lockexit(32); 5248 } 5249 } 5250 islocked = 1; 5251 lockfskey = lockfs.lf_key; 5252 } 5253 5254 void 5255 clockfs() 5256 { 5257 time_t t; 5258 char *ct; 5259 5260 (void) time(&t); 5261 ct = ctime(&t); 5262 ct[strlen(ct)-1] = '\0'; 5263 5264 (void) sprintf(lockfscomment, "%s -- mkfs pid %d", ct, getpid()); 5265 lockfs.lf_comlen = strlen(lockfscomment)+1; 5266 lockfs.lf_comment = lockfscomment; 5267 } 5268 5269 /* 5270 * Write the csum records and the superblock 5271 */ 5272 void 5273 wtsb() 5274 { 5275 long i; 5276 5277 /* 5278 * write summary information 5279 */ 5280 for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) 5281 wtfs(fsbtodb(&sblock, (uint64_t)(sblock.fs_csaddr + 5282 numfrags(&sblock, i))), 5283 (int)(sblock.fs_cssize - i < sblock.fs_bsize ? 5284 sblock.fs_cssize - i : sblock.fs_bsize), 5285 ((char *)fscs) + i); 5286 5287 /* 5288 * write superblock 5289 */ 5290 sblock.fs_time = mkfstime; 5291 wtfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock); 5292 } 5293 5294 /* 5295 * Verify that the optimization selection is reasonable, and advance 5296 * the global "string" appropriately. 5297 */ 5298 static char 5299 checkopt(char *optim) 5300 { 5301 char opt; 5302 int limit = strcspn(optim, ","); 5303 5304 switch (limit) { 5305 case 0: /* missing indicator (have comma or nul) */ 5306 (void) fprintf(stderr, gettext( 5307 "mkfs: missing optimization flag reset to `t' (time)\n")); 5308 opt = 't'; 5309 break; 5310 5311 case 1: /* single-character indicator */ 5312 opt = *optim; 5313 if ((opt != 's') && (opt != 't')) { 5314 (void) fprintf(stderr, gettext( 5315 "mkfs: bad optimization value `%c' reset to `t' (time)\n"), 5316 opt); 5317 opt = 't'; 5318 } 5319 break; 5320 5321 default: /* multi-character indicator */ 5322 (void) fprintf(stderr, gettext( 5323 "mkfs: bad optimization value `%*.*s' reset to `t' (time)\n"), 5324 limit, limit, optim); 5325 opt = 't'; 5326 break; 5327 } 5328 5329 string += limit; 5330 5331 return (opt); 5332 } 5333 5334 /* 5335 * Verify that the mtb selection is reasonable, and advance 5336 * the global "string" appropriately. 5337 */ 5338 static char 5339 checkmtb(char *mtbarg) 5340 { 5341 char mtbc; 5342 int limit = strcspn(mtbarg, ","); 5343 5344 switch (limit) { 5345 case 0: /* missing indicator (have comma or nul) */ 5346 (void) fprintf(stderr, gettext( 5347 "mkfs: missing mtb flag reset to `n' (no mtb support)\n")); 5348 mtbc = 'n'; 5349 break; 5350 5351 case 1: /* single-character indicator */ 5352 mtbc = tolower(*mtbarg); 5353 if ((mtbc != 'y') && (mtbc != 'n')) { 5354 (void) fprintf(stderr, gettext( 5355 "mkfs: bad mtb value `%c' reset to `n' (no mtb support)\n"), 5356 mtbc); 5357 mtbc = 'n'; 5358 } 5359 break; 5360 5361 default: /* multi-character indicator */ 5362 (void) fprintf(stderr, gettext( 5363 "mkfs: bad mtb value `%*.*s' reset to `n' (no mtb support)\n"), 5364 limit, limit, mtbarg); 5365 opt = 'n'; 5366 break; 5367 } 5368 5369 string += limit; 5370 5371 return (mtbc); 5372 } 5373 5374 /* 5375 * Verify that a value is in a range. If it is not, resets it to 5376 * its default value if one is supplied, exits otherwise. 5377 * 5378 * When testing, can compare user_supplied to RC_KEYWORD or RC_POSITIONAL. 5379 */ 5380 static void 5381 range_check(long *varp, char *name, long minimum, long maximum, 5382 long def_val, int user_supplied) 5383 { 5384 dprintf(("DeBuG %s : %ld (%ld %ld %ld)\n", 5385 name, *varp, minimum, maximum, def_val)); 5386 5387 if ((*varp < minimum) || (*varp > maximum)) { 5388 if (user_supplied != RC_DEFAULT) { 5389 (void) fprintf(stderr, gettext( 5390 "mkfs: bad value for %s: %ld must be between %ld and %ld\n"), 5391 name, *varp, minimum, maximum); 5392 } 5393 if (def_val != NO_DEFAULT) { 5394 if (user_supplied) { 5395 (void) fprintf(stderr, 5396 gettext("mkfs: %s reset to default %ld\n"), 5397 name, def_val); 5398 } 5399 *varp = def_val; 5400 dprintf(("DeBuG %s : %ld\n", name, *varp)); 5401 return; 5402 } 5403 lockexit(2); 5404 /*NOTREACHED*/ 5405 } 5406 } 5407 5408 /* 5409 * Verify that a value is in a range. If it is not, resets it to 5410 * its default value if one is supplied, exits otherwise. 5411 * 5412 * When testing, can compare user_supplied to RC_KEYWORD or RC_POSITIONAL. 5413 */ 5414 static void 5415 range_check_64(uint64_t *varp, char *name, uint64_t minimum, uint64_t maximum, 5416 uint64_t def_val, int user_supplied) 5417 { 5418 if ((*varp < minimum) || (*varp > maximum)) { 5419 if (user_supplied != RC_DEFAULT) { 5420 (void) fprintf(stderr, gettext( 5421 "mkfs: bad value for %s: %lld must be between %lld and %lld\n"), 5422 name, *varp, minimum, maximum); 5423 } 5424 if (def_val != NO_DEFAULT) { 5425 if (user_supplied) { 5426 (void) fprintf(stderr, 5427 gettext("mkfs: %s reset to default %lld\n"), 5428 name, def_val); 5429 } 5430 *varp = def_val; 5431 return; 5432 } 5433 lockexit(2); 5434 /*NOTREACHED*/ 5435 } 5436 } 5437 5438 /* 5439 * Blocks SIGINT from delivery. Returns the previous mask in the 5440 * buffer provided, so that mask may be later restored. 5441 */ 5442 static void 5443 block_sigint(sigset_t *old_mask) 5444 { 5445 sigset_t block_mask; 5446 5447 if (sigemptyset(&block_mask) < 0) { 5448 fprintf(stderr, gettext("Could not clear signal mask\n")); 5449 lockexit(3); 5450 } 5451 if (sigaddset(&block_mask, SIGINT) < 0) { 5452 fprintf(stderr, gettext("Could not set signal mask\n")); 5453 lockexit(3); 5454 } 5455 if (sigprocmask(SIG_BLOCK, &block_mask, old_mask) < 0) { 5456 fprintf(stderr, gettext("Could not block SIGINT\n")); 5457 lockexit(3); 5458 } 5459 } 5460 5461 /* 5462 * Restores the signal mask that was in force before a call 5463 * to block_sigint(). This may actually still have SIGINT blocked, 5464 * if we've been recursively invoked. 5465 */ 5466 static void 5467 unblock_sigint(sigset_t *old_mask) 5468 { 5469 if (sigprocmask(SIG_UNBLOCK, old_mask, (sigset_t *)NULL) < 0) { 5470 fprintf(stderr, gettext("Could not restore signal mask\n")); 5471 lockexit(3); 5472 } 5473 } 5474 5475 /* 5476 * Attempt to be somewhat graceful about being interrupted, rather than 5477 * just silently leaving the filesystem in an unusable state. 5478 * 5479 * The kernel has blocked SIGINT upon entry, so we don't have to worry 5480 * about recursion if the user starts pounding on the keyboard. 5481 */ 5482 static void 5483 recover_from_sigint(int signum) 5484 { 5485 if (fso > -1) { 5486 if ((Nflag != 0) || confirm_abort()) { 5487 lockexit(4); 5488 } 5489 } 5490 } 5491 5492 static int 5493 confirm_abort(void) 5494 { 5495 char line[80]; 5496 5497 printf(gettext("\n\nAborting at this point will leave the filesystem " 5498 "in an inconsistent\nstate. If you do choose to stop, " 5499 "you will be given instructions on how to\nrecover " 5500 "the filesystem. Do you wish to cancel the filesystem " 5501 "grow\noperation (y/n)?")); 5502 if (getaline(stdin, line, sizeof (line)) == EOF) 5503 line[0] = 'y'; 5504 5505 printf("\n"); 5506 if (line[0] == 'y' || line[0] == 'Y') 5507 return (1); 5508 else { 5509 return (0); 5510 } 5511 } 5512 5513 static int 5514 getaline(FILE *fp, char *loc, int maxlen) 5515 { 5516 int n; 5517 char *p, *lastloc; 5518 5519 p = loc; 5520 lastloc = &p[maxlen-1]; 5521 while ((n = getc(fp)) != '\n') { 5522 if (n == EOF) 5523 return (EOF); 5524 if (!isspace(n) && p < lastloc) 5525 *p++ = n; 5526 } 5527 *p = 0; 5528 return (p - loc); 5529 } 5530 5531 /* 5532 * Calculate the maximum value of cylinders-per-group for a file 5533 * system with the characteristics: 5534 * 5535 * bsize - file system block size 5536 * fragsize - frag size 5537 * nbpi - number of bytes of disk space per inode 5538 * nrpos - number of rotational positions 5539 * spc - sectors per cylinder 5540 * 5541 * These five characteristic are not adjustable (by this function). 5542 * The only attribute of the file system which IS adjusted by this 5543 * function in order to maximize cylinders-per-group is the proportion 5544 * of the cylinder group overhead block used for the inode map. The 5545 * inode map cannot occupy more than one-third of the cylinder group 5546 * overhead block, but it's OK for it to occupy less than one-third 5547 * of the overhead block. 5548 * 5549 * The setting of nbpi determines one possible value for the maximum 5550 * size of a cylinder group. It does so because it determines the total 5551 * number of inodes in the file system (file system size is fixed, and 5552 * nbpi is fixed, so the total number of inodes is fixed too). The 5553 * cylinder group has to be small enough so that the number of inodes 5554 * in the cylinder group is less than or equal to the number of bits 5555 * in one-third (or whatever proportion is assumed) of a file system 5556 * block. The details of the calculation are: 5557 * 5558 * The macro MAXIpG_B(bsize, inode_divisor) determines the maximum 5559 * number of inodes that can be in a cylinder group, given the 5560 * proportion of the cylinder group overhead block used for the 5561 * inode bitmaps (an inode_divisor of 3 means that 1/3 of the 5562 * block is used for inode bitmaps; an inode_divisor of 12 means 5563 * that 1/12 of the block is used for inode bitmaps.) 5564 * 5565 * Once the number of inodes per cylinder group is known, the 5566 * maximum value of cylinders-per-group (determined by nbpi) 5567 * is calculated by the formula 5568 * 5569 * maxcpg_given_nbpi = (size of a cylinder group)/(size of a cylinder) 5570 * 5571 * = (inodes-per-cg * nbpi)/(spc * DEV_BSIZE) 5572 * 5573 * (Interestingly, the size of the file system never enters 5574 * into this calculation.) 5575 * 5576 * Another possible value for the maximum cylinder group size is determined 5577 * by frag_size and nrpos. The frags in the cylinder group must be 5578 * representable in the frag bitmaps in the cylinder overhead block and the 5579 * rotational positions for each cylinder must be represented in the 5580 * rotational position tables. The calculation of the maximum cpg 5581 * value, given the frag and nrpos vales, is: 5582 * 5583 * maxcpg_given_fragsize = 5584 * (available space in the overhead block) / (size of per-cylinder data) 5585 * 5586 * The available space in the overhead block = 5587 * bsize - sizeof (struct cg) - space_used_for_inode_bitmaps 5588 * 5589 * The size of the per-cylinder data is: 5590 * sizeof(long) # for the "blocks avail per cylinder" field 5591 * + nrpos * sizeof(short) # for the rotational position table entry 5592 * + frags-per-cylinder/NBBY # number of bytes to represent this 5593 * # cylinder in the frag bitmap 5594 * 5595 * The two calculated maximum values of cylinder-per-group will typically 5596 * turn out to be different, since they are derived from two different 5597 * constraints. Usually, maxcpg_given_nbpi is much bigger than 5598 * maxcpg_given_fragsize. But they can be brought together by 5599 * adjusting the proportion of the overhead block dedicated to 5600 * the inode bitmaps. Decreasing the proportion of the cylinder 5601 * group overhead block used for inode maps will decrease 5602 * maxcpg_given_nbpi and increase maxcpg_given_fragsize. 5603 * 5604 * This function calculates the initial values of maxcpg_given_nbpi 5605 * and maxcpg_given_fragsize assuming that 1/3 of the cg overhead 5606 * block is used for inode bitmaps. Then it decreases the proportion 5607 * of the cg overhead block used for inode bitmaps (by increasing 5608 * the value of inode_divisor) until maxcpg_given_nbpi and 5609 * maxcpg_given_fragsize are the same, or stop changing, or 5610 * maxcpg_given_nbpi is less than maxcpg_given_fragsize. 5611 * 5612 * The loop terminates when any of the following occur: 5613 * * maxcpg_given_fragsize is greater than or equal to 5614 * maxcpg_given_nbpi 5615 * * neither maxcpg_given_fragsize nor maxcpg_given_nbpi 5616 * change in the expected direction 5617 * 5618 * The loop is guaranteed to terminate because it only continues 5619 * while maxcpg_given_fragsize and maxcpg_given_nbpi are approaching 5620 * each other. As soon they cross each other, or neither one changes 5621 * in the direction of the other, or one of them moves in the wrong 5622 * direction, the loop completes. 5623 */ 5624 5625 static long 5626 compute_maxcpg(long bsize, long fragsize, long nbpi, long nrpos, long spc) 5627 { 5628 int maxcpg_given_nbpi; /* in cylinders */ 5629 int maxcpg_given_fragsize; /* in cylinders */ 5630 int spf; /* sectors per frag */ 5631 int inode_divisor; 5632 int old_max_given_frag = 0; 5633 int old_max_given_nbpi = INT_MAX; 5634 5635 spf = fragsize / DEV_BSIZE; 5636 inode_divisor = 3; 5637 5638 while (1) { 5639 maxcpg_given_nbpi = 5640 (((int64_t)(MAXIpG_B(bsize, inode_divisor))) * nbpi) / 5641 (DEV_BSIZE * ((int64_t)spc)); 5642 maxcpg_given_fragsize = 5643 (bsize - (sizeof (struct cg)) - (bsize / inode_divisor)) / 5644 (sizeof (long) + nrpos * sizeof (short) + 5645 (spc / spf) / NBBY); 5646 5647 if (maxcpg_given_fragsize >= maxcpg_given_nbpi) 5648 return (maxcpg_given_nbpi); 5649 5650 /* 5651 * If neither value moves toward the other, return the 5652 * least of the old values (we use the old instead of the 5653 * new because: if the old is the same as the new, it 5654 * doesn't matter which ones we use. If one of the 5655 * values changed, but in the wrong direction, the 5656 * new values are suspect. Better use the old. This 5657 * shouldn't happen, but it's best to check. 5658 */ 5659 5660 if (!(maxcpg_given_nbpi < old_max_given_nbpi) && 5661 !(maxcpg_given_fragsize > old_max_given_frag)) 5662 return (MIN(old_max_given_nbpi, old_max_given_frag)); 5663 5664 /* 5665 * This is probably impossible, but if one of the maxcpg 5666 * values moved in the "right" direction and one moved 5667 * in the "wrong" direction (that is, the two values moved 5668 * in the same direction), the previous conditional won't 5669 * recognize that the values aren't converging (since at 5670 * least one value moved in the "right" direction, the 5671 * last conditional says "keep going"). 5672 * 5673 * Just to make absolutely certain that the loop terminates, 5674 * check for one of the values moving in the "wrong" direction 5675 * and terminate the loop if it happens. 5676 */ 5677 5678 if (maxcpg_given_nbpi > old_max_given_nbpi || 5679 maxcpg_given_fragsize < old_max_given_frag) 5680 return (MIN(old_max_given_nbpi, old_max_given_frag)); 5681 5682 old_max_given_nbpi = maxcpg_given_nbpi; 5683 old_max_given_frag = maxcpg_given_fragsize; 5684 5685 inode_divisor++; 5686 } 5687 } 5688 5689 static int 5690 in_64bit_mode(void) 5691 { 5692 /* cmd must be an absolute path, for security */ 5693 char *cmd = "/usr/bin/isainfo -b"; 5694 char buf[BUFSIZ]; 5695 FILE *ptr; 5696 int retval = 0; 5697 5698 putenv("IFS= \t"); 5699 if ((ptr = popen(cmd, "r")) != NULL) { 5700 if (fgets(buf, BUFSIZ, ptr) != NULL && 5701 strncmp(buf, "64", 2) == 0) 5702 retval = 1; 5703 (void) pclose(ptr); 5704 } 5705 return (retval); 5706 } 5707 5708 /* 5709 * validate_size 5710 * 5711 * Return 1 if the device appears to be at least "size" sectors long. 5712 * Return 0 if it's shorter or we can't read it. 5713 */ 5714 5715 static int 5716 validate_size(int fd, diskaddr_t size) 5717 { 5718 char buf[DEV_BSIZE]; 5719 int rc; 5720 5721 if ((llseek(fd, (offset_t)((size - 1) * DEV_BSIZE), SEEK_SET) == -1) || 5722 (read(fd, buf, DEV_BSIZE)) != DEV_BSIZE) 5723 rc = 0; 5724 else 5725 rc = 1; 5726 return (rc); 5727 } 5728 5729 /* 5730 * Print every field of the calculated superblock, along with 5731 * its value. To make parsing easier on the caller, the value 5732 * is printed first, then the name. Additionally, there's only 5733 * one name/value pair per line. All values are reported in 5734 * hexadecimal (with the traditional 0x prefix), as that's slightly 5735 * easier for humans to read. Not that they're expected to, but 5736 * debugging happens. 5737 */ 5738 static void 5739 dump_sblock(void) 5740 { 5741 int row, column, pending, written; 5742 caddr_t source; 5743 5744 if (Rflag) { 5745 pending = sizeof (sblock); 5746 source = (caddr_t)&sblock; 5747 do { 5748 written = write(fileno(stdout), source, pending); 5749 pending -= written; 5750 source += written; 5751 } while ((pending > 0) && (written > 0)); 5752 5753 if (written < 0) { 5754 perror(gettext("Binary dump of superblock failed")); 5755 lockexit(1); 5756 } 5757 return; 5758 } else { 5759 printf("0x%x sblock.fs_link\n", sblock.fs_link); 5760 printf("0x%x sblock.fs_rolled\n", sblock.fs_rolled); 5761 printf("0x%x sblock.fs_sblkno\n", sblock.fs_sblkno); 5762 printf("0x%x sblock.fs_cblkno\n", sblock.fs_cblkno); 5763 printf("0x%x sblock.fs_iblkno\n", sblock.fs_iblkno); 5764 printf("0x%x sblock.fs_dblkno\n", sblock.fs_dblkno); 5765 printf("0x%x sblock.fs_cgoffset\n", sblock.fs_cgoffset); 5766 printf("0x%x sblock.fs_cgmask\n", sblock.fs_cgmask); 5767 printf("0x%x sblock.fs_time\n", sblock.fs_time); 5768 printf("0x%x sblock.fs_size\n", sblock.fs_size); 5769 printf("0x%x sblock.fs_dsize\n", sblock.fs_dsize); 5770 printf("0x%x sblock.fs_ncg\n", sblock.fs_ncg); 5771 printf("0x%x sblock.fs_bsize\n", sblock.fs_bsize); 5772 printf("0x%x sblock.fs_fsize\n", sblock.fs_fsize); 5773 printf("0x%x sblock.fs_frag\n", sblock.fs_frag); 5774 printf("0x%x sblock.fs_minfree\n", sblock.fs_minfree); 5775 printf("0x%x sblock.fs_rotdelay\n", sblock.fs_rotdelay); 5776 printf("0x%x sblock.fs_rps\n", sblock.fs_rps); 5777 printf("0x%x sblock.fs_bmask\n", sblock.fs_bmask); 5778 printf("0x%x sblock.fs_fmask\n", sblock.fs_fmask); 5779 printf("0x%x sblock.fs_bshift\n", sblock.fs_bshift); 5780 printf("0x%x sblock.fs_fshift\n", sblock.fs_fshift); 5781 printf("0x%x sblock.fs_maxcontig\n", sblock.fs_maxcontig); 5782 printf("0x%x sblock.fs_maxbpg\n", sblock.fs_maxbpg); 5783 printf("0x%x sblock.fs_fragshift\n", sblock.fs_fragshift); 5784 printf("0x%x sblock.fs_fsbtodb\n", sblock.fs_fsbtodb); 5785 printf("0x%x sblock.fs_sbsize\n", sblock.fs_sbsize); 5786 printf("0x%x sblock.fs_csmask\n", sblock.fs_csmask); 5787 printf("0x%x sblock.fs_csshift\n", sblock.fs_csshift); 5788 printf("0x%x sblock.fs_nindir\n", sblock.fs_nindir); 5789 printf("0x%x sblock.fs_inopb\n", sblock.fs_inopb); 5790 printf("0x%x sblock.fs_nspf\n", sblock.fs_nspf); 5791 printf("0x%x sblock.fs_optim\n", sblock.fs_optim); 5792 #ifdef _LITTLE_ENDIAN 5793 printf("0x%x sblock.fs_state\n", sblock.fs_state); 5794 #else 5795 printf("0x%x sblock.fs_npsect\n", sblock.fs_npsect); 5796 #endif 5797 printf("0x%x sblock.fs_si\n", sblock.fs_si); 5798 printf("0x%x sblock.fs_trackskew\n", sblock.fs_trackskew); 5799 printf("0x%x sblock.fs_id[0]\n", sblock.fs_id[0]); 5800 printf("0x%x sblock.fs_id[1]\n", sblock.fs_id[1]); 5801 printf("0x%x sblock.fs_csaddr\n", sblock.fs_csaddr); 5802 printf("0x%x sblock.fs_cssize\n", sblock.fs_cssize); 5803 printf("0x%x sblock.fs_cgsize\n", sblock.fs_cgsize); 5804 printf("0x%x sblock.fs_ntrak\n", sblock.fs_ntrak); 5805 printf("0x%x sblock.fs_nsect\n", sblock.fs_nsect); 5806 printf("0x%x sblock.fs_spc\n", sblock.fs_spc); 5807 printf("0x%x sblock.fs_ncyl\n", sblock.fs_ncyl); 5808 printf("0x%x sblock.fs_cpg\n", sblock.fs_cpg); 5809 printf("0x%x sblock.fs_ipg\n", sblock.fs_ipg); 5810 printf("0x%x sblock.fs_fpg\n", sblock.fs_fpg); 5811 printf("0x%x sblock.fs_cstotal\n", sblock.fs_cstotal); 5812 printf("0x%x sblock.fs_fmod\n", sblock.fs_fmod); 5813 printf("0x%x sblock.fs_clean\n", sblock.fs_clean); 5814 printf("0x%x sblock.fs_ronly\n", sblock.fs_ronly); 5815 printf("0x%x sblock.fs_flags\n", sblock.fs_flags); 5816 printf("0x%x sblock.fs_fsmnt\n", sblock.fs_fsmnt); 5817 printf("0x%x sblock.fs_cgrotor\n", sblock.fs_cgrotor); 5818 printf("0x%x sblock.fs_u.fs_csp\n", sblock.fs_u.fs_csp); 5819 printf("0x%x sblock.fs_cpc\n", sblock.fs_cpc); 5820 5821 /* 5822 * No macros are defined for the dimensions of the 5823 * opostbl array. 5824 */ 5825 for (row = 0; row < 16; row++) { 5826 for (column = 0; column < 8; column++) { 5827 printf("0x%x sblock.fs_opostbl[%d][%d]\n", 5828 sblock.fs_opostbl[row][column], 5829 row, column); 5830 } 5831 } 5832 5833 /* 5834 * Ditto the size of sparecon. 5835 */ 5836 for (row = 0; row < 51; row++) { 5837 printf("0x%x sblock.fs_sparecon[%d]\n", 5838 sblock.fs_sparecon[row], row); 5839 } 5840 5841 printf("0x%x sblock.fs_version\n", sblock.fs_version); 5842 printf("0x%x sblock.fs_logbno\n", sblock.fs_logbno); 5843 printf("0x%x sblock.fs_reclaim\n", sblock.fs_reclaim); 5844 printf("0x%x sblock.fs_sparecon2\n", sblock.fs_sparecon2); 5845 #ifdef _LITTLE_ENDIAN 5846 printf("0x%x sblock.fs_npsect\n", sblock.fs_npsect); 5847 #else 5848 printf("0x%x sblock.fs_state\n", sblock.fs_state); 5849 #endif 5850 printf("0x%llx sblock.fs_qbmask\n", sblock.fs_qbmask); 5851 printf("0x%llx sblock.fs_qfmask\n", sblock.fs_qfmask); 5852 printf("0x%x sblock.fs_postblformat\n", sblock.fs_postblformat); 5853 printf("0x%x sblock.fs_nrpos\n", sblock.fs_nrpos); 5854 printf("0x%x sblock.fs_postbloff\n", sblock.fs_postbloff); 5855 printf("0x%x sblock.fs_rotbloff\n", sblock.fs_rotbloff); 5856 printf("0x%x sblock.fs_magic\n", sblock.fs_magic); 5857 5858 /* 5859 * fs_space isn't of much use in this context, so we'll 5860 * just ignore it for now. 5861 */ 5862 } 5863 } 5864