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