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