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