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