1 /* 2 * Copyright (c) 1980, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)mkfs.c 8.11 (Berkeley) 5/3/95 34 * $FreeBSD: src/sbin/newfs/mkfs.c,v 1.29.2.6 2001/09/21 19:15:21 dillon Exp $ 35 * $DragonFly: src/sbin/newfs/mkfs.c,v 1.14 2007/05/20 19:29:21 dillon Exp $ 36 */ 37 38 #include "defs.h" 39 40 #include <stdlib.h> 41 42 /* 43 * make file system for cylinder-group style file systems 44 */ 45 46 /* 47 * We limit the size of the inode map to be no more than a 48 * third of the cylinder group space, since we must leave at 49 * least an equal amount of space for the block map. 50 * 51 * N.B.: MAXIPG must be a multiple of INOPB(fs). 52 */ 53 #define MAXIPG(fs) roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs)) 54 55 #define UMASK 0755 56 #define MAXINOPB (MAXBSIZE / sizeof(struct ufs1_dinode)) 57 #define POWEROF2(num) (((num) & ((num) - 1)) == 0) 58 59 #ifdef STANDALONE 60 #error "mkfs.c: STANDALONE compilation no longer supported" 61 #endif 62 63 /* 64 * variables set up by front end. 65 */ 66 extern int mfs; /* run as the memory based filesystem */ 67 extern char *mfs_mtpt; /* mount point for mfs */ 68 extern struct stat mfs_mtstat; /* stat prior to mount */ 69 extern int Lflag; /* add a volume label */ 70 extern int Nflag; /* run mkfs without writing file system */ 71 extern int Oflag; /* format as an 4.3BSD file system */ 72 extern int Uflag; /* enable soft updates for file system */ 73 extern u_long fssize; /* file system size */ 74 extern int ntracks; /* # tracks/cylinder */ 75 extern int nsectors; /* # sectors/track */ 76 extern int nphyssectors; /* # sectors/track including spares */ 77 extern int secpercyl; /* sectors per cylinder */ 78 extern int sectorsize; /* bytes/sector */ 79 extern int realsectorsize; /* bytes/sector in hardware*/ 80 extern int rpm; /* revolutions/minute of drive */ 81 extern int interleave; /* hardware sector interleave */ 82 extern int trackskew; /* sector 0 skew, per track */ 83 extern int fsize; /* fragment size */ 84 extern int bsize; /* block size */ 85 extern int cpg; /* cylinders/cylinder group */ 86 extern int cpgflg; /* cylinders/cylinder group flag was given */ 87 extern int minfree; /* free space threshold */ 88 extern int opt; /* optimization preference (space or time) */ 89 extern int density; /* number of bytes per inode */ 90 extern int maxcontig; /* max contiguous blocks to allocate */ 91 extern int rotdelay; /* rotational delay between blocks */ 92 extern int maxbpg; /* maximum blocks per file in a cyl group */ 93 extern int nrpos; /* # of distinguished rotational positions */ 94 extern int bbsize; /* boot block size */ 95 extern int sbsize; /* superblock size */ 96 extern int avgfilesize; /* expected average file size */ 97 extern int avgfilesperdir; /* expected number of files per directory */ 98 extern caddr_t membase; /* start address of memory based filesystem */ 99 extern char * filename; 100 extern u_char *volumelabel; /* volume label for filesystem */ 101 extern struct disktab geom; 102 103 extern void fatal(const char *fmt, ...); 104 105 union { 106 struct fs fs; 107 char pad[SBSIZE]; 108 } fsun; 109 #define sblock fsun.fs 110 struct csum *fscs; 111 112 union { 113 struct cg cg; 114 char pad[MAXBSIZE]; 115 } cgun; 116 #define acg cgun.cg 117 118 struct ufs1_dinode zino[MAXBSIZE / sizeof(struct ufs1_dinode)]; 119 120 int fsi, fso; 121 static fsnode_t copyroot; 122 static fsnode_t copyhlinks; 123 #ifdef FSIRAND 124 int randinit; 125 #endif 126 daddr_t alloc(int, int); 127 long calcipg(long, long, off_t *); 128 static int charsperline(void); 129 void clrblock(struct fs *, unsigned char *, int); 130 void fsinit(time_t); 131 void initcg(int, time_t); 132 int isblock(struct fs *, unsigned char *, int); 133 void iput(struct ufs1_dinode *, ino_t); 134 int makedir(struct direct *, int); 135 void parentready(int); 136 void rdfs(daddr_t, int, char *); 137 void setblock(struct fs *, unsigned char *, int); 138 void started(int); 139 void wtfs(daddr_t, int, char *); 140 void wtfsflush(void); 141 142 int mfs_ppid = 0; 143 int parentready_signalled; 144 145 void 146 mkfs(char *fsys, int fi, int fo, const char *mfscopy) 147 { 148 long i, mincpc, mincpg, inospercg; 149 long cylno, rpos, blk, j, emitwarn = 0; 150 long used, mincpgcnt, bpcg; 151 off_t usedb; 152 long mapcramped, inodecramped; 153 long postblsize, rotblsize, totalsbsize; 154 int status, fd; 155 time_t utime; 156 quad_t sizepb; 157 int width; 158 char tmpbuf[100]; /* XXX this will break in about 2,500 years */ 159 160 time(&utime); 161 #ifdef FSIRAND 162 if (!randinit) { 163 randinit = 1; 164 srandomdev(); 165 } 166 #endif 167 if (mfs) { 168 int omask; 169 pid_t child; 170 171 mfs_ppid = getpid(); 172 signal(SIGUSR1, parentready); 173 if ((child = fork()) != 0) { 174 /* 175 * Parent 176 */ 177 if (child == -1) 178 err(10, "mfs"); 179 if (mfscopy) 180 copyroot = FSCopy(©hlinks, mfscopy); 181 signal(SIGUSR1, started); 182 kill(child, SIGUSR1); 183 while (waitpid(child, &status, 0) != child) 184 ; 185 exit(WEXITSTATUS(status)); 186 /* NOTREACHED */ 187 } 188 189 /* 190 * Child 191 */ 192 omask = sigblock(sigmask(SIGUSR1)); 193 while (parentready_signalled == 0) 194 sigpause(omask); 195 sigsetmask(omask); 196 if (filename != NULL) { 197 unsigned char buf[BUFSIZ]; 198 unsigned long l, l1; 199 ssize_t w; 200 201 fd = open(filename, O_RDWR|O_TRUNC|O_CREAT, 0644); 202 if(fd < 0) 203 err(12, "%s", filename); 204 l1 = fssize * sectorsize; 205 if (l1 > BUFSIZ) 206 l1 = BUFSIZ; 207 for (l = 0; l < fssize * (u_long)sectorsize; l += l1) { 208 w = write(fd, buf, l1); 209 if (w < 0 || (u_long)w != l1) 210 err(12, "%s", filename); 211 } 212 membase = mmap(NULL, fssize * sectorsize, 213 PROT_READ|PROT_WRITE, 214 MAP_SHARED, fd, 0); 215 if (membase == MAP_FAILED) 216 err(12, "mmap"); 217 close(fd); 218 } else { 219 membase = mmap(NULL, fssize * sectorsize, 220 PROT_READ|PROT_WRITE, 221 MAP_SHARED|MAP_ANON, -1, 0); 222 if (membase == MAP_FAILED) 223 errx(13, "mmap (anonymous memory) failed"); 224 } 225 } 226 fsi = fi; 227 fso = fo; 228 if (Oflag) { 229 sblock.fs_inodefmt = FS_42INODEFMT; 230 sblock.fs_maxsymlinklen = 0; 231 } else { 232 sblock.fs_inodefmt = FS_44INODEFMT; 233 sblock.fs_maxsymlinklen = MAXSYMLINKLEN; 234 } 235 if (Uflag) 236 sblock.fs_flags |= FS_DOSOFTDEP; 237 if (Lflag) 238 strlcpy(sblock.fs_volname, volumelabel, MAXVOLLEN); 239 /* 240 * Validate the given file system size. 241 * Verify that its last block can actually be accessed. 242 */ 243 if (fssize == 0) 244 printf("preposterous size %lu\n", fssize), exit(13); 245 wtfs(fssize - (realsectorsize / DEV_BSIZE), realsectorsize, 246 (char *)&sblock); 247 /* 248 * collect and verify the sector and track info 249 */ 250 sblock.fs_nsect = nsectors; 251 sblock.fs_ntrak = ntracks; 252 if (sblock.fs_ntrak <= 0) 253 printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(14); 254 if (sblock.fs_nsect <= 0) 255 printf("preposterous nsect %d\n", sblock.fs_nsect), exit(15); 256 /* 257 * collect and verify the filesystem density info 258 */ 259 sblock.fs_avgfilesize = avgfilesize; 260 sblock.fs_avgfpdir = avgfilesperdir; 261 if (sblock.fs_avgfilesize <= 0) 262 printf("illegal expected average file size %d\n", 263 sblock.fs_avgfilesize), exit(14); 264 if (sblock.fs_avgfpdir <= 0) 265 printf("illegal expected number of files per directory %d\n", 266 sblock.fs_avgfpdir), exit(15); 267 /* 268 * collect and verify the block and fragment sizes 269 */ 270 sblock.fs_bsize = bsize; 271 sblock.fs_fsize = fsize; 272 if (!POWEROF2(sblock.fs_bsize)) { 273 printf("block size must be a power of 2, not %d\n", 274 sblock.fs_bsize); 275 exit(16); 276 } 277 if (!POWEROF2(sblock.fs_fsize)) { 278 printf("fragment size must be a power of 2, not %d\n", 279 sblock.fs_fsize); 280 exit(17); 281 } 282 if (sblock.fs_fsize < sectorsize) { 283 printf("fragment size %d is too small, minimum is %d\n", 284 sblock.fs_fsize, sectorsize); 285 exit(18); 286 } 287 if (sblock.fs_bsize < MINBSIZE) { 288 printf("block size %d is too small, minimum is %d\n", 289 sblock.fs_bsize, MINBSIZE); 290 exit(19); 291 } 292 if (sblock.fs_bsize < sblock.fs_fsize) { 293 printf("block size (%d) cannot be smaller than fragment size (%d)\n", 294 sblock.fs_bsize, sblock.fs_fsize); 295 exit(20); 296 } 297 sblock.fs_bmask = ~(sblock.fs_bsize - 1); 298 sblock.fs_fmask = ~(sblock.fs_fsize - 1); 299 sblock.fs_qbmask = ~sblock.fs_bmask; 300 sblock.fs_qfmask = ~sblock.fs_fmask; 301 for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1) 302 sblock.fs_bshift++; 303 for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1) 304 sblock.fs_fshift++; 305 sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize); 306 for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1) 307 sblock.fs_fragshift++; 308 if (sblock.fs_frag > MAXFRAG) { 309 printf("fragment size %d is too small, minimum with block size %d is %d\n", 310 sblock.fs_fsize, sblock.fs_bsize, 311 sblock.fs_bsize / MAXFRAG); 312 exit(21); 313 } 314 sblock.fs_nrpos = nrpos; 315 sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t); 316 sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs1_dinode); 317 sblock.fs_nspf = sblock.fs_fsize / sectorsize; 318 for (sblock.fs_fsbtodb = 0, i = NSPF(&sblock); i > 1; i >>= 1) 319 sblock.fs_fsbtodb++; 320 sblock.fs_sblkno = 321 roundup(howmany(bbsize + sbsize, sblock.fs_fsize), sblock.fs_frag); 322 sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno + 323 roundup(howmany(sbsize, sblock.fs_fsize), sblock.fs_frag)); 324 sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag; 325 sblock.fs_cgoffset = roundup( 326 howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag); 327 for (sblock.fs_cgmask = 0xffffffff, i = sblock.fs_ntrak; i > 1; i >>= 1) 328 sblock.fs_cgmask <<= 1; 329 if (!POWEROF2(sblock.fs_ntrak)) 330 sblock.fs_cgmask <<= 1; 331 sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1; 332 for (sizepb = sblock.fs_bsize, i = 0; i < NIADDR; i++) { 333 sizepb *= NINDIR(&sblock); 334 sblock.fs_maxfilesize += sizepb; 335 } 336 /* 337 * Validate specified/determined secpercyl 338 * and calculate minimum cylinders per group. 339 */ 340 sblock.fs_spc = secpercyl; 341 for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc; 342 sblock.fs_cpc > 1 && (i & 1) == 0; 343 sblock.fs_cpc >>= 1, i >>= 1) 344 /* void */; 345 mincpc = sblock.fs_cpc; 346 bpcg = sblock.fs_spc * sectorsize; 347 inospercg = roundup(bpcg / sizeof(struct ufs1_dinode), INOPB(&sblock)); 348 if (inospercg > MAXIPG(&sblock)) 349 inospercg = MAXIPG(&sblock); 350 used = (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock); 351 mincpgcnt = howmany(sblock.fs_cgoffset * (~sblock.fs_cgmask) + used, 352 sblock.fs_spc); 353 mincpg = roundup(mincpgcnt, mincpc); 354 /* 355 * Ensure that cylinder group with mincpg has enough space 356 * for block maps. 357 */ 358 sblock.fs_cpg = mincpg; 359 sblock.fs_ipg = inospercg; 360 if (maxcontig > 1) 361 sblock.fs_contigsumsize = MIN(maxcontig, FS_MAXCONTIG); 362 mapcramped = 0; 363 while (CGSIZE(&sblock) > (uint32_t)sblock.fs_bsize) { 364 mapcramped = 1; 365 if (sblock.fs_bsize < MAXBSIZE) { 366 sblock.fs_bsize <<= 1; 367 if ((i & 1) == 0) { 368 i >>= 1; 369 } else { 370 sblock.fs_cpc <<= 1; 371 mincpc <<= 1; 372 mincpg = roundup(mincpgcnt, mincpc); 373 sblock.fs_cpg = mincpg; 374 } 375 sblock.fs_frag <<= 1; 376 sblock.fs_fragshift += 1; 377 if (sblock.fs_frag <= MAXFRAG) 378 continue; 379 } 380 if (sblock.fs_fsize == sblock.fs_bsize) { 381 printf("There is no block size that"); 382 printf(" can support this disk\n"); 383 exit(22); 384 } 385 sblock.fs_frag >>= 1; 386 sblock.fs_fragshift -= 1; 387 sblock.fs_fsize <<= 1; 388 sblock.fs_nspf <<= 1; 389 } 390 /* 391 * Ensure that cylinder group with mincpg has enough space for inodes. 392 */ 393 inodecramped = 0; 394 inospercg = calcipg(mincpg, bpcg, &usedb); 395 sblock.fs_ipg = inospercg; 396 while (inospercg > MAXIPG(&sblock)) { 397 inodecramped = 1; 398 if (mincpc == 1 || sblock.fs_frag == 1 || 399 sblock.fs_bsize == MINBSIZE) 400 break; 401 printf("With a block size of %d %s %d\n", sblock.fs_bsize, 402 "minimum bytes per inode is", 403 (int)((mincpg * (off_t)bpcg - usedb) 404 / MAXIPG(&sblock) + 1)); 405 sblock.fs_bsize >>= 1; 406 sblock.fs_frag >>= 1; 407 sblock.fs_fragshift -= 1; 408 mincpc >>= 1; 409 sblock.fs_cpg = roundup(mincpgcnt, mincpc); 410 if (CGSIZE(&sblock) > (uint32_t)sblock.fs_bsize) { 411 sblock.fs_bsize <<= 1; 412 break; 413 } 414 mincpg = sblock.fs_cpg; 415 inospercg = calcipg(mincpg, bpcg, &usedb); 416 sblock.fs_ipg = inospercg; 417 } 418 if (inodecramped) { 419 if (inospercg > MAXIPG(&sblock)) { 420 printf("Minimum bytes per inode is %d\n", 421 (int)((mincpg * (off_t)bpcg - usedb) 422 / MAXIPG(&sblock) + 1)); 423 } else if (!mapcramped) { 424 printf("With %d bytes per inode, ", density); 425 printf("minimum cylinders per group is %ld\n", mincpg); 426 } 427 } 428 if (mapcramped) { 429 printf("With %d sectors per cylinder, ", sblock.fs_spc); 430 printf("minimum cylinders per group is %ld\n", mincpg); 431 } 432 if (inodecramped || mapcramped) { 433 if (sblock.fs_bsize != bsize) 434 printf("%s to be changed from %d to %d\n", 435 "This requires the block size", 436 bsize, sblock.fs_bsize); 437 if (sblock.fs_fsize != fsize) 438 printf("\t%s to be changed from %d to %d\n", 439 "and the fragment size", 440 fsize, sblock.fs_fsize); 441 exit(23); 442 } 443 /* 444 * Calculate the number of cylinders per group 445 */ 446 sblock.fs_cpg = cpg; 447 if (sblock.fs_cpg % mincpc != 0) { 448 printf("%s groups must have a multiple of %ld cylinders\n", 449 cpgflg ? "Cylinder" : "Warning: cylinder", mincpc); 450 sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc); 451 if (!cpgflg) 452 cpg = sblock.fs_cpg; 453 } 454 /* 455 * Must ensure there is enough space for inodes. 456 */ 457 sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb); 458 while (sblock.fs_ipg > MAXIPG(&sblock)) { 459 inodecramped = 1; 460 sblock.fs_cpg -= mincpc; 461 sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb); 462 } 463 /* 464 * Must ensure there is enough space to hold block map. 465 */ 466 while (CGSIZE(&sblock) > (uint32_t)sblock.fs_bsize) { 467 mapcramped = 1; 468 sblock.fs_cpg -= mincpc; 469 sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb); 470 } 471 sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 472 if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) { 473 printf("panic (fs_cpg * fs_spc) %% NSPF != 0"); 474 exit(24); 475 } 476 if (sblock.fs_cpg < mincpg) { 477 printf("cylinder groups must have at least %ld cylinders\n", 478 mincpg); 479 exit(25); 480 } else if (sblock.fs_cpg != cpg) { 481 if (!cpgflg && !mfs) 482 printf("Warning: "); 483 else if (!mapcramped && !inodecramped) 484 exit(26); 485 if (!mfs) { 486 if (mapcramped && inodecramped) 487 printf("Block size and bytes per inode restrict"); 488 else if (mapcramped) 489 printf("Block size restricts"); 490 else 491 printf("Bytes per inode restrict"); 492 printf(" cylinders per group to %d.\n", sblock.fs_cpg); 493 } 494 if (cpgflg) 495 exit(27); 496 } 497 sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock)); 498 /* 499 * Now have size for file system and nsect and ntrak. 500 * Determine number of cylinders and blocks in the file system. 501 */ 502 sblock.fs_size = fssize = dbtofsb(&sblock, fssize); 503 sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc; 504 if ((long)fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) { 505 sblock.fs_ncyl++; 506 emitwarn = 1; 507 } 508 if (sblock.fs_ncyl < 1) { 509 printf("file systems must have at least one cylinder\n"); 510 exit(28); 511 } 512 /* 513 * Determine feasability/values of rotational layout tables. 514 * 515 * The size of the rotational layout tables is limited by the 516 * size of the superblock, SBSIZE. The amount of space available 517 * for tables is calculated as (SBSIZE - sizeof (struct fs)). 518 * The size of these tables is inversely proportional to the block 519 * size of the file system. The size increases if sectors per track 520 * are not powers of two, because more cylinders must be described 521 * by the tables before the rotational pattern repeats (fs_cpc). 522 */ 523 sblock.fs_interleave = interleave; 524 sblock.fs_trackskew = trackskew; 525 sblock.fs_npsect = nphyssectors; 526 sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT; 527 sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs)); 528 if (sblock.fs_sbsize > SBSIZE) 529 sblock.fs_sbsize = SBSIZE; 530 if (sblock.fs_ntrak == 1) { 531 sblock.fs_cpc = 0; 532 goto next; 533 } 534 postblsize = sblock.fs_nrpos * sblock.fs_cpc * sizeof(int16_t); 535 rotblsize = sblock.fs_cpc * sblock.fs_spc / NSPB(&sblock); 536 totalsbsize = sizeof(struct fs) + rotblsize; 537 if (sblock.fs_nrpos == 8 && sblock.fs_cpc <= 16) { 538 /* use old static table space */ 539 sblock.fs_postbloff = (char *)(&sblock.fs_opostbl[0][0]) - 540 (char *)(&sblock.fs_firstfield); 541 sblock.fs_rotbloff = &sblock.fs_space[0] - 542 (u_char *)(&sblock.fs_firstfield); 543 } else { 544 /* use dynamic table space */ 545 sblock.fs_postbloff = &sblock.fs_space[0] - 546 (u_char *)(&sblock.fs_firstfield); 547 sblock.fs_rotbloff = sblock.fs_postbloff + postblsize; 548 totalsbsize += postblsize; 549 } 550 if (totalsbsize > SBSIZE || 551 sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) { 552 printf("%s %s %d %s %d.%s", 553 "Warning: insufficient space in super block for\n", 554 "rotational layout tables with nsect", sblock.fs_nsect, 555 "and ntrak", sblock.fs_ntrak, 556 "\nFile system performance may be impaired.\n"); 557 sblock.fs_cpc = 0; 558 goto next; 559 } 560 sblock.fs_sbsize = fragroundup(&sblock, totalsbsize); 561 if (sblock.fs_sbsize > SBSIZE) 562 sblock.fs_sbsize = SBSIZE; 563 /* 564 * calculate the available blocks for each rotational position 565 */ 566 for (cylno = 0; cylno < sblock.fs_cpc; cylno++) 567 for (rpos = 0; rpos < sblock.fs_nrpos; rpos++) 568 fs_postbl(&sblock, cylno)[rpos] = -1; 569 for (i = (rotblsize - 1) * sblock.fs_frag; 570 i >= 0; i -= sblock.fs_frag) { 571 cylno = cbtocylno(&sblock, i); 572 rpos = cbtorpos(&sblock, i); 573 blk = fragstoblks(&sblock, i); 574 if (fs_postbl(&sblock, cylno)[rpos] == -1) 575 fs_rotbl(&sblock)[blk] = 0; 576 else 577 fs_rotbl(&sblock)[blk] = 578 fs_postbl(&sblock, cylno)[rpos] - blk; 579 fs_postbl(&sblock, cylno)[rpos] = blk; 580 } 581 next: 582 /* 583 * Compute/validate number of cylinder groups. 584 */ 585 sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; 586 if (sblock.fs_ncyl % sblock.fs_cpg) 587 sblock.fs_ncg++; 588 sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock); 589 i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1); 590 if (cgdmin(&sblock, i) - cgbase(&sblock, i) >= sblock.fs_fpg) { 591 printf("inode blocks/cyl group (%ld) >= data blocks (%ld)\n", 592 cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag, 593 (long)(sblock.fs_fpg / sblock.fs_frag)); 594 printf("number of cylinders per cylinder group (%d) %s.\n", 595 sblock.fs_cpg, "must be increased"); 596 exit(29); 597 } 598 j = sblock.fs_ncg - 1; 599 if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg && 600 cgdmin(&sblock, j) - cgbase(&sblock, j) > i) { 601 if (j == 0) { 602 printf("Filesystem must have at least %d sectors\n", 603 NSPF(&sblock) * 604 (cgdmin(&sblock, 0) + 3 * sblock.fs_frag)); 605 exit(30); 606 } 607 printf( 608 "Warning: inode blocks/cyl group (%ld) >= data blocks (%ld) in last\n", 609 (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag, 610 i / sblock.fs_frag); 611 printf( 612 " cylinder group. This implies %ld sector(s) cannot be allocated.\n", 613 i * NSPF(&sblock)); 614 sblock.fs_ncg--; 615 sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg; 616 sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc / 617 NSPF(&sblock); 618 emitwarn = 0; 619 } 620 if (emitwarn && !mfs) { 621 printf("Warning: %lu sector(s) in last cylinder unallocated\n", 622 sblock.fs_spc - 623 (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1) 624 * sblock.fs_spc)); 625 } 626 /* 627 * fill in remaining fields of the super block 628 */ 629 sblock.fs_csaddr = cgdmin(&sblock, 0); 630 sblock.fs_cssize = 631 fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); 632 /* 633 * The superblock fields 'fs_csmask' and 'fs_csshift' are no 634 * longer used. However, we still initialise them so that the 635 * filesystem remains compatible with old kernels. 636 */ 637 i = sblock.fs_bsize / sizeof(struct csum); 638 sblock.fs_csmask = ~(i - 1); 639 for (sblock.fs_csshift = 0; i > 1; i >>= 1) 640 sblock.fs_csshift++; 641 fscs = (struct csum *)calloc(1, sblock.fs_cssize); 642 if (fscs == NULL) 643 errx(31, "calloc failed"); 644 sblock.fs_magic = FS_MAGIC; 645 sblock.fs_rotdelay = rotdelay; 646 sblock.fs_minfree = minfree; 647 sblock.fs_maxcontig = maxcontig; 648 sblock.fs_maxbpg = maxbpg; 649 sblock.fs_rps = rpm / 60; 650 sblock.fs_optim = opt; 651 sblock.fs_cgrotor = 0; 652 sblock.fs_cstotal.cs_ndir = 0; 653 sblock.fs_cstotal.cs_nbfree = 0; 654 sblock.fs_cstotal.cs_nifree = 0; 655 sblock.fs_cstotal.cs_nffree = 0; 656 sblock.fs_fmod = 0; 657 sblock.fs_ronly = 0; 658 sblock.fs_clean = 1; 659 #ifdef FSIRAND 660 sblock.fs_id[0] = (long)utime; 661 sblock.fs_id[1] = random(); 662 #endif 663 664 /* 665 * Dump out summary information about file system. 666 */ 667 if (!mfs) { 668 printf("%s:\t%d sectors in %d %s of %d tracks, %d sectors\n", 669 fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl, 670 "cylinders", sblock.fs_ntrak, sblock.fs_nsect); 671 #define B2MBFACTOR (1 / (1024.0 * 1024.0)) 672 printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)%s\n", 673 (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR, 674 sblock.fs_ncg, sblock.fs_cpg, 675 (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, 676 sblock.fs_ipg, 677 sblock.fs_flags & FS_DOSOFTDEP ? " SOFTUPDATES" : ""); 678 #undef B2MBFACTOR 679 } 680 /* 681 * Now build the cylinders group blocks and 682 * then print out indices of cylinder groups. 683 */ 684 if (!mfs) 685 printf("super-block backups (for fsck -b #) at:\n"); 686 i = 0; 687 width = charsperline(); 688 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { 689 initcg(cylno, utime); 690 if (mfs) 691 continue; 692 j = snprintf(tmpbuf, sizeof(tmpbuf), " %ld%s", 693 fsbtodb(&sblock, cgsblock(&sblock, cylno)), 694 cylno < (sblock.fs_ncg-1) ? "," : "" ); 695 if (i + j >= width) { 696 printf("\n"); 697 i = 0; 698 } 699 i += j; 700 printf("%s", tmpbuf); 701 fflush(stdout); 702 } 703 if (!mfs) 704 printf("\n"); 705 if (Nflag && !mfs) 706 exit(0); 707 /* 708 * Now construct the initial file system, 709 * then write out the super-block. 710 */ 711 fsinit(utime); 712 sblock.fs_time = utime; 713 wtfs((int)SBOFF / sectorsize, sbsize, (char *)&sblock); 714 for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) 715 wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), 716 sblock.fs_cssize - i < sblock.fs_bsize ? 717 sblock.fs_cssize - i : sblock.fs_bsize, 718 ((char *)fscs) + i); 719 /* 720 * Write out the duplicate super blocks 721 */ 722 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) 723 wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), 724 sbsize, (char *)&sblock); 725 wtfsflush(); 726 727 /* 728 * NOTE: we no longer update information in the disklabel 729 */ 730 731 /* 732 * Notify parent process of success. 733 * Dissociate from session and tty. 734 * 735 * NOTE: We are the child and may receive a SIGINT due 736 * to losing the tty session? XXX 737 */ 738 if (mfs) { 739 /* YYY */ 740 kill(mfs_ppid, SIGUSR1); 741 setsid(); 742 close(0); 743 close(1); 744 close(2); 745 chdir("/"); 746 /* returns to mount_mfs (newfs) and issues the mount */ 747 } 748 } 749 750 /* 751 * Initialize a cylinder group. 752 */ 753 void 754 initcg(int cylno, time_t utime) 755 { 756 daddr_t cbase, d, dlower, dupper, dmax, blkno; 757 long i; 758 unsigned long k; 759 struct csum *cs; 760 #ifdef FSIRAND 761 uint32_t j; 762 #endif 763 764 /* 765 * Determine block bounds for cylinder group. 766 * Allow space for super block summary information in first 767 * cylinder group. 768 */ 769 cbase = cgbase(&sblock, cylno); 770 dmax = cbase + sblock.fs_fpg; 771 if (dmax > sblock.fs_size) 772 dmax = sblock.fs_size; 773 dlower = cgsblock(&sblock, cylno) - cbase; 774 dupper = cgdmin(&sblock, cylno) - cbase; 775 if (cylno == 0) 776 dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); 777 cs = fscs + cylno; 778 memset(&acg, 0, sblock.fs_cgsize); 779 acg.cg_time = utime; 780 acg.cg_magic = CG_MAGIC; 781 acg.cg_cgx = cylno; 782 if (cylno == sblock.fs_ncg - 1) 783 acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; 784 else 785 acg.cg_ncyl = sblock.fs_cpg; 786 acg.cg_niblk = sblock.fs_ipg; 787 acg.cg_ndblk = dmax - cbase; 788 if (sblock.fs_contigsumsize > 0) 789 acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag; 790 acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield); 791 acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(int32_t); 792 acg.cg_iusedoff = acg.cg_boff + 793 sblock.fs_cpg * sblock.fs_nrpos * sizeof(u_int16_t); 794 acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY); 795 if (sblock.fs_contigsumsize <= 0) { 796 acg.cg_nextfreeoff = acg.cg_freeoff + 797 howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY); 798 } else { 799 acg.cg_clustersumoff = acg.cg_freeoff + howmany 800 (sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY) - 801 sizeof(u_int32_t); 802 acg.cg_clustersumoff = 803 roundup(acg.cg_clustersumoff, sizeof(u_int32_t)); 804 acg.cg_clusteroff = acg.cg_clustersumoff + 805 (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t); 806 acg.cg_nextfreeoff = acg.cg_clusteroff + howmany 807 (sblock.fs_cpg * sblock.fs_spc / NSPB(&sblock), NBBY); 808 } 809 if (acg.cg_nextfreeoff - (long)(&acg.cg_firstfield) > sblock.fs_cgsize) { 810 printf("Panic: cylinder group too big\n"); 811 exit(37); 812 } 813 acg.cg_cs.cs_nifree += sblock.fs_ipg; 814 if (cylno == 0) { 815 for (k = 0; k < ROOTINO; k++) { 816 setbit(cg_inosused(&acg), k); 817 acg.cg_cs.cs_nifree--; 818 } 819 } 820 for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) { 821 #ifdef FSIRAND 822 for (j = 0; 823 j < sblock.fs_bsize / sizeof(struct ufs1_dinode); 824 j++) { 825 zino[j].di_gen = random(); 826 } 827 #endif 828 wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), 829 sblock.fs_bsize, (char *)zino); 830 } 831 if (cylno > 0) { 832 /* 833 * In cylno 0, beginning space is reserved 834 * for boot and super blocks. 835 */ 836 for (d = 0; d < dlower; d += sblock.fs_frag) { 837 blkno = d / sblock.fs_frag; 838 setblock(&sblock, cg_blksfree(&acg), blkno); 839 if (sblock.fs_contigsumsize > 0) 840 setbit(cg_clustersfree(&acg), blkno); 841 acg.cg_cs.cs_nbfree++; 842 cg_blktot(&acg)[cbtocylno(&sblock, d)]++; 843 cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) 844 [cbtorpos(&sblock, d)]++; 845 } 846 sblock.fs_dsize += dlower; 847 } 848 sblock.fs_dsize += acg.cg_ndblk - dupper; 849 if ((i = dupper % sblock.fs_frag)) { 850 acg.cg_frsum[sblock.fs_frag - i]++; 851 for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) { 852 setbit(cg_blksfree(&acg), dupper); 853 acg.cg_cs.cs_nffree++; 854 } 855 } 856 for (d = dupper; d + sblock.fs_frag <= dmax - cbase; ) { 857 blkno = d / sblock.fs_frag; 858 setblock(&sblock, cg_blksfree(&acg), blkno); 859 if (sblock.fs_contigsumsize > 0) 860 setbit(cg_clustersfree(&acg), blkno); 861 acg.cg_cs.cs_nbfree++; 862 cg_blktot(&acg)[cbtocylno(&sblock, d)]++; 863 cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) 864 [cbtorpos(&sblock, d)]++; 865 d += sblock.fs_frag; 866 } 867 if (d < dmax - cbase) { 868 acg.cg_frsum[dmax - cbase - d]++; 869 for (; d < dmax - cbase; d++) { 870 setbit(cg_blksfree(&acg), d); 871 acg.cg_cs.cs_nffree++; 872 } 873 } 874 if (sblock.fs_contigsumsize > 0) { 875 int32_t *sump = cg_clustersum(&acg); 876 u_char *mapp = cg_clustersfree(&acg); 877 int map = *mapp++; 878 int bit = 1; 879 int run = 0; 880 881 for (i = 0; i < acg.cg_nclusterblks; i++) { 882 if ((map & bit) != 0) { 883 run++; 884 } else if (run != 0) { 885 if (run > sblock.fs_contigsumsize) 886 run = sblock.fs_contigsumsize; 887 sump[run]++; 888 run = 0; 889 } 890 if ((i & (NBBY - 1)) != (NBBY - 1)) { 891 bit <<= 1; 892 } else { 893 map = *mapp++; 894 bit = 1; 895 } 896 } 897 if (run != 0) { 898 if (run > sblock.fs_contigsumsize) 899 run = sblock.fs_contigsumsize; 900 sump[run]++; 901 } 902 } 903 sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; 904 sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; 905 sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; 906 sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; 907 *cs = acg.cg_cs; 908 wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), 909 sblock.fs_bsize, (char *)&acg); 910 } 911 912 /* 913 * initialize the file system 914 */ 915 struct ufs1_dinode node; 916 917 #ifdef LOSTDIR 918 #define PREDEFDIR 3 919 #else 920 #define PREDEFDIR 2 921 #endif 922 923 struct direct root_dir[] = { 924 { ROOTINO, sizeof(struct direct), DT_DIR, 1, "." }, 925 { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, 926 #ifdef LOSTDIR 927 { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 10, "lost+found" }, 928 #endif 929 }; 930 struct odirect { 931 u_long d_ino; 932 u_short d_reclen; 933 u_short d_namlen; 934 u_char d_name[MAXNAMLEN + 1]; 935 } oroot_dir[] = { 936 { ROOTINO, sizeof(struct direct), 1, "." }, 937 { ROOTINO, sizeof(struct direct), 2, ".." }, 938 #ifdef LOSTDIR 939 { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" }, 940 #endif 941 }; 942 #ifdef LOSTDIR 943 struct direct lost_found_dir[] = { 944 { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 1, "." }, 945 { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, 946 { 0, DIRBLKSIZ, 0, 0, 0 }, 947 }; 948 struct odirect olost_found_dir[] = { 949 { LOSTFOUNDINO, sizeof(struct direct), 1, "." }, 950 { ROOTINO, sizeof(struct direct), 2, ".." }, 951 { 0, DIRBLKSIZ, 0, 0 }, 952 }; 953 #endif 954 char buf[MAXBSIZE]; 955 956 void 957 fsinit(time_t utime) 958 { 959 #ifdef LOSTDIR 960 int i; 961 #endif 962 963 /* 964 * initialize the node 965 */ 966 node.di_atime = utime; 967 node.di_mtime = utime; 968 node.di_ctime = utime; 969 #ifdef LOSTDIR 970 /* 971 * create the lost+found directory 972 */ 973 if (Oflag) { 974 makedir((struct direct *)olost_found_dir, 2); 975 for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) 976 memmove(&buf[i], &olost_found_dir[2], 977 DIRSIZ(0, &olost_found_dir[2])); 978 } else { 979 makedir(lost_found_dir, 2); 980 for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) 981 memmove(&buf[i], &lost_found_dir[2], 982 DIRSIZ(0, &lost_found_dir[2])); 983 } 984 node.di_mode = IFDIR | UMASK; 985 node.di_nlink = 2; 986 node.di_size = sblock.fs_bsize; 987 node.di_db[0] = alloc(node.di_size, node.di_mode); 988 node.di_blocks = btodb(fragroundup(&sblock, node.di_size)); 989 wtfs(fsbtodb(&sblock, node.di_db[0]), node.di_size, buf); 990 iput(&node, LOSTFOUNDINO); 991 #endif 992 /* 993 * create the root directory 994 */ 995 if (mfs) 996 node.di_mode = IFDIR | 01777; 997 else 998 node.di_mode = IFDIR | UMASK; 999 node.di_nlink = PREDEFDIR; 1000 if (Oflag) 1001 node.di_size = makedir((struct direct *)oroot_dir, PREDEFDIR); 1002 else 1003 node.di_size = makedir(root_dir, PREDEFDIR); 1004 node.di_db[0] = alloc(sblock.fs_fsize, node.di_mode); 1005 node.di_blocks = btodb(fragroundup(&sblock, node.di_size)); 1006 wtfs(fsbtodb(&sblock, node.di_db[0]), sblock.fs_fsize, buf); 1007 iput(&node, ROOTINO); 1008 } 1009 1010 /* 1011 * construct a set of directory entries in "buf". 1012 * return size of directory. 1013 */ 1014 int 1015 makedir(struct direct *protodir, int entries) 1016 { 1017 char *cp; 1018 int i, spcleft; 1019 1020 spcleft = DIRBLKSIZ; 1021 for (cp = buf, i = 0; i < entries - 1; i++) { 1022 protodir[i].d_reclen = DIRSIZ(0, &protodir[i]); 1023 memmove(cp, &protodir[i], protodir[i].d_reclen); 1024 cp += protodir[i].d_reclen; 1025 spcleft -= protodir[i].d_reclen; 1026 } 1027 protodir[i].d_reclen = spcleft; 1028 memmove(cp, &protodir[i], DIRSIZ(0, &protodir[i])); 1029 return (DIRBLKSIZ); 1030 } 1031 1032 /* 1033 * allocate a block or frag 1034 */ 1035 daddr_t 1036 alloc(int size, int mode) 1037 { 1038 int i, frag; 1039 daddr_t d, blkno; 1040 1041 rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 1042 (char *)&acg); 1043 if (acg.cg_magic != CG_MAGIC) { 1044 printf("cg 0: bad magic number\n"); 1045 return (0); 1046 } 1047 if (acg.cg_cs.cs_nbfree == 0) { 1048 printf("first cylinder group ran out of space\n"); 1049 return (0); 1050 } 1051 for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) 1052 if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag)) 1053 goto goth; 1054 printf("internal error: can't find block in cyl 0\n"); 1055 return (0); 1056 goth: 1057 blkno = fragstoblks(&sblock, d); 1058 clrblock(&sblock, cg_blksfree(&acg), blkno); 1059 if (sblock.fs_contigsumsize > 0) 1060 clrbit(cg_clustersfree(&acg), blkno); 1061 acg.cg_cs.cs_nbfree--; 1062 sblock.fs_cstotal.cs_nbfree--; 1063 fscs[0].cs_nbfree--; 1064 if (mode & IFDIR) { 1065 acg.cg_cs.cs_ndir++; 1066 sblock.fs_cstotal.cs_ndir++; 1067 fscs[0].cs_ndir++; 1068 } 1069 cg_blktot(&acg)[cbtocylno(&sblock, d)]--; 1070 cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--; 1071 if (size != sblock.fs_bsize) { 1072 frag = howmany(size, sblock.fs_fsize); 1073 fscs[0].cs_nffree += sblock.fs_frag - frag; 1074 sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; 1075 acg.cg_cs.cs_nffree += sblock.fs_frag - frag; 1076 acg.cg_frsum[sblock.fs_frag - frag]++; 1077 for (i = frag; i < sblock.fs_frag; i++) 1078 setbit(cg_blksfree(&acg), d + i); 1079 } 1080 wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 1081 (char *)&acg); 1082 return (d); 1083 } 1084 1085 /* 1086 * Calculate number of inodes per group. 1087 */ 1088 long 1089 calcipg(long cylspg, long bpcg, off_t *usedbp) 1090 { 1091 int i; 1092 long ipg, new_ipg, ncg, ncyl; 1093 off_t usedb; 1094 1095 /* 1096 * Prepare to scale by fssize / (number of sectors in cylinder groups). 1097 * Note that fssize is still in sectors, not filesystem blocks. 1098 */ 1099 ncyl = howmany(fssize, (u_int)secpercyl); 1100 ncg = howmany(ncyl, cylspg); 1101 /* 1102 * Iterate a few times to allow for ipg depending on itself. 1103 */ 1104 ipg = 0; 1105 for (i = 0; i < 10; i++) { 1106 usedb = (sblock.fs_iblkno + ipg / INOPF(&sblock)) 1107 * NSPF(&sblock) * (off_t)sectorsize; 1108 new_ipg = (cylspg * (quad_t)bpcg - usedb) / density * fssize 1109 / ncg / secpercyl / cylspg; 1110 new_ipg = roundup(new_ipg, INOPB(&sblock)); 1111 if (new_ipg == ipg) 1112 break; 1113 ipg = new_ipg; 1114 } 1115 *usedbp = usedb; 1116 return (ipg); 1117 } 1118 1119 /* 1120 * Allocate an inode on the disk 1121 */ 1122 void 1123 iput(struct ufs1_dinode *ip, ino_t ino) 1124 { 1125 struct ufs1_dinode inobuf[MAXINOPB]; 1126 daddr_t d; 1127 int c; 1128 1129 #ifdef FSIRAND 1130 ip->di_gen = random(); 1131 #endif 1132 c = ino_to_cg(&sblock, ino); 1133 rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 1134 (char *)&acg); 1135 if (acg.cg_magic != CG_MAGIC) { 1136 printf("cg 0: bad magic number\n"); 1137 exit(31); 1138 } 1139 acg.cg_cs.cs_nifree--; 1140 setbit(cg_inosused(&acg), ino); 1141 wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 1142 (char *)&acg); 1143 sblock.fs_cstotal.cs_nifree--; 1144 fscs[0].cs_nifree--; 1145 if (ino >= (uint32_t)sblock.fs_ipg * (uint32_t)sblock.fs_ncg) { 1146 printf("fsinit: inode value out of range (%ju).\n", 1147 (uintmax_t)ino); 1148 exit(32); 1149 } 1150 d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino)); 1151 rdfs(d, sblock.fs_bsize, (char *)inobuf); 1152 inobuf[ino_to_fsbo(&sblock, ino)] = *ip; 1153 wtfs(d, sblock.fs_bsize, (char *)inobuf); 1154 } 1155 1156 /* 1157 * Parent notifies child that it can proceed with the newfs and mount 1158 * operation (occurs after parent has copied the underlying filesystem 1159 * if the -C option was specified (for MFS), or immediately after the 1160 * parent forked the child otherwise). 1161 */ 1162 void 1163 parentready(__unused int signo) 1164 { 1165 parentready_signalled = 1; 1166 } 1167 1168 /* 1169 * Notify parent process that the filesystem has created itself successfully. 1170 * 1171 * We have to wait until the mount has actually completed! 1172 */ 1173 void 1174 started(__unused int signo) 1175 { 1176 int retry = 100; /* 10 seconds, 100ms */ 1177 1178 while (mfs_ppid && retry) { 1179 struct stat st; 1180 1181 if ( 1182 stat(mfs_mtpt, &st) < 0 || 1183 st.st_dev != mfs_mtstat.st_dev 1184 ) { 1185 break; 1186 } 1187 usleep(100*1000); 1188 --retry; 1189 } 1190 if (retry == 0) { 1191 fatal("mfs mount failed waiting for mount to go active"); 1192 } else if (copyroot) { 1193 FSPaste(mfs_mtpt, copyroot, copyhlinks); 1194 } 1195 exit(0); 1196 } 1197 1198 /* 1199 * read a block from the file system 1200 */ 1201 void 1202 rdfs(daddr_t bno, int size, char *bf) 1203 { 1204 int n; 1205 1206 wtfsflush(); 1207 if (mfs) { 1208 memmove(bf, membase + bno * sectorsize, size); 1209 return; 1210 } 1211 if (lseek(fsi, (off_t)bno * sectorsize, 0) < 0) { 1212 printf("seek error: %ld\n", (long)bno); 1213 err(33, "rdfs"); 1214 } 1215 n = read(fsi, bf, size); 1216 if (n != size) { 1217 printf("read error: %ld\n", (long)bno); 1218 err(34, "rdfs"); 1219 } 1220 } 1221 1222 #define WCSIZE (128 * 1024) 1223 daddr_t wc_sect; /* units of sectorsize */ 1224 int wc_end; /* bytes */ 1225 static char wc[WCSIZE]; /* bytes */ 1226 1227 /* 1228 * Flush dirty write behind buffer. 1229 */ 1230 void 1231 wtfsflush(void) 1232 { 1233 int n; 1234 if (wc_end) { 1235 if (lseek(fso, (off_t)wc_sect * sectorsize, SEEK_SET) < 0) { 1236 printf("seek error: %ld\n", (long)wc_sect); 1237 err(35, "wtfs - writecombine"); 1238 } 1239 n = write(fso, wc, wc_end); 1240 if (n != wc_end) { 1241 printf("write error: %ld\n", (long)wc_sect); 1242 err(36, "wtfs - writecombine"); 1243 } 1244 wc_end = 0; 1245 } 1246 } 1247 1248 /* 1249 * write a block to the file system 1250 */ 1251 void 1252 wtfs(daddr_t bno, int size, char *bf) 1253 { 1254 int n; 1255 int done; 1256 1257 if (mfs) { 1258 memmove(membase + bno * sectorsize, bf, size); 1259 return; 1260 } 1261 if (Nflag) 1262 return; 1263 done = 0; 1264 if (wc_end == 0 && size <= WCSIZE) { 1265 wc_sect = bno; 1266 bcopy(bf, wc, size); 1267 wc_end = size; 1268 if (wc_end < WCSIZE) 1269 return; 1270 done = 1; 1271 } 1272 if ((off_t)wc_sect * sectorsize + wc_end == (off_t)bno * sectorsize && 1273 wc_end + size <= WCSIZE) { 1274 bcopy(bf, wc + wc_end, size); 1275 wc_end += size; 1276 if (wc_end < WCSIZE) 1277 return; 1278 done = 1; 1279 } 1280 wtfsflush(); 1281 if (done) 1282 return; 1283 if (lseek(fso, (off_t)bno * sectorsize, SEEK_SET) < 0) { 1284 printf("seek error: %ld\n", (long)bno); 1285 err(35, "wtfs"); 1286 } 1287 n = write(fso, bf, size); 1288 if (n != size) { 1289 printf("write error: fso %d blk %ld %d/%d\n", 1290 fso, (long)bno, n, size); 1291 err(36, "wtfs"); 1292 } 1293 } 1294 1295 /* 1296 * check if a block is available 1297 */ 1298 int 1299 isblock(struct fs *fs, unsigned char *cp, int h) 1300 { 1301 unsigned char mask; 1302 1303 switch (fs->fs_frag) { 1304 case 8: 1305 return (cp[h] == 0xff); 1306 case 4: 1307 mask = 0x0f << ((h & 0x1) << 2); 1308 return ((cp[h >> 1] & mask) == mask); 1309 case 2: 1310 mask = 0x03 << ((h & 0x3) << 1); 1311 return ((cp[h >> 2] & mask) == mask); 1312 case 1: 1313 mask = 0x01 << (h & 0x7); 1314 return ((cp[h >> 3] & mask) == mask); 1315 default: 1316 fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 1317 return (0); 1318 } 1319 } 1320 1321 /* 1322 * take a block out of the map 1323 */ 1324 void 1325 clrblock(struct fs *fs, unsigned char *cp, int h) 1326 { 1327 switch ((fs)->fs_frag) { 1328 case 8: 1329 cp[h] = 0; 1330 return; 1331 case 4: 1332 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 1333 return; 1334 case 2: 1335 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 1336 return; 1337 case 1: 1338 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 1339 return; 1340 default: 1341 fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag); 1342 return; 1343 } 1344 } 1345 1346 /* 1347 * put a block into the map 1348 */ 1349 void 1350 setblock(struct fs *fs, unsigned char *cp, int h) 1351 { 1352 switch (fs->fs_frag) { 1353 case 8: 1354 cp[h] = 0xff; 1355 return; 1356 case 4: 1357 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 1358 return; 1359 case 2: 1360 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 1361 return; 1362 case 1: 1363 cp[h >> 3] |= (0x01 << (h & 0x7)); 1364 return; 1365 default: 1366 fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); 1367 return; 1368 } 1369 } 1370 1371 /* 1372 * Determine the number of characters in a 1373 * single line. 1374 */ 1375 1376 static int 1377 charsperline(void) 1378 { 1379 int columns; 1380 char *cp; 1381 struct winsize ws; 1382 1383 columns = 0; 1384 if (ioctl(0, TIOCGWINSZ, &ws) != -1) 1385 columns = ws.ws_col; 1386 if (columns == 0 && (cp = getenv("COLUMNS"))) 1387 columns = atoi(cp); 1388 if (columns == 0) 1389 columns = 80; /* last resort */ 1390 return columns; 1391 } 1392