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