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