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