mkfs.c revision 94112
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 34#ifndef lint 35#if 0 36static char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95"; 37#endif 38static const char rcsid[] = 39 "$FreeBSD: head/sbin/newfs/mkfs.c 94112 2002-04-07 14:57:57Z phk $"; 40#endif /* not lint */ 41 42#include <err.h> 43#include <signal.h> 44#include <stdlib.h> 45#include <string.h> 46#include <stdio.h> 47#include <unistd.h> 48#include <sys/param.h> 49#include <sys/time.h> 50#include <sys/types.h> 51#include <sys/wait.h> 52#include <sys/resource.h> 53#include <sys/stat.h> 54#include <ufs/ufs/dinode.h> 55#include <ufs/ufs/dir.h> 56#include <ufs/ffs/fs.h> 57#include <sys/disklabel.h> 58#include <sys/file.h> 59#include <sys/mman.h> 60#include <sys/ioctl.h> 61#include "newfs.h" 62 63/* 64 * make file system for cylinder-group style file systems 65 */ 66 67/* 68 * We limit the size of the inode map to be no more than a 69 * third of the cylinder group space, since we must leave at 70 * least an equal amount of space for the block map. 71 * 72 * N.B.: MAXIPG must be a multiple of INOPB(fs). 73 */ 74#define MAXIPG(fs) roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs)) 75 76#define UMASK 0755 77#define MAXINOPB (MAXBSIZE / sizeof(struct dinode)) 78#define POWEROF2(num) (((num) & ((num) - 1)) == 0) 79 80static union { 81 struct fs fs; 82 char pad[SBSIZE]; 83} fsun; 84#define sblock fsun.fs 85static struct csum *fscs; 86 87static union { 88 struct cg cg; 89 char pad[MAXBSIZE]; 90} cgun; 91#define acg cgun.cg 92 93static struct dinode zino[MAXBSIZE / sizeof(struct dinode)]; 94 95static int fsi, fso; 96static int randinit; 97static daddr_t alloc(int size, int mode); 98static long calcipg(long lcpg, long bpcg, off_t *usedbp); 99static int charsperline(void); 100static void clrblock(struct fs *, unsigned char *, int); 101static void fsinit(time_t); 102static int ilog2(int); 103static void initcg(int, time_t); 104static int isblock(struct fs *, unsigned char *, int); 105static void iput(struct dinode *, ino_t); 106static int makedir(struct direct *, int); 107static void rdfs(daddr_t, int, char *); 108static void setblock(struct fs *, unsigned char *, int); 109static void wtfs(daddr_t, int, char *); 110static void wtfsflush(void); 111 112void 113mkfs(struct partition *pp, char *fsys, int fi, int fo) 114{ 115 long i, mincpc, mincpg, inospercg; 116 long cylno, j, lwarn = 0; 117 long used, mincpgcnt, bpcg; 118 off_t usedb; 119 long mapcramped, inodecramped; 120 time_t utime; 121 quad_t sizepb; 122 int width; 123 char tmpbuf[100]; /* XXX this will break in about 2,500 years */ 124 125 if (Rflag) 126 utime = 1000000000; 127 else 128 time(&utime); 129 if (!Rflag && !randinit) { 130 randinit = 1; 131 srandomdev(); 132 } 133 fsi = fi; 134 fso = fo; 135 sblock.fs_inodefmt = FS_44INODEFMT; 136 sblock.fs_maxsymlinklen = MAXSYMLINKLEN; 137 if (Uflag) 138 sblock.fs_flags |= FS_DOSOFTDEP; 139 /* 140 * Validate the given file system size. 141 * Verify that its last block can actually be accessed. 142 */ 143 if (fssize <= 0) 144 printf("preposterous size %d\n", fssize), exit(13); 145 wtfs(fssize - (realsectorsize / DEV_BSIZE), realsectorsize, 146 (char *)&sblock); 147 /* 148 * collect and verify the sector and track info 149 */ 150 sblock.fs_nsect = secpercyl; 151 sblock.fs_ntrak = 1; 152 if (sblock.fs_nsect <= 0) 153 printf("preposterous nsect %d\n", sblock.fs_nsect), exit(15); 154 /* 155 * collect and verify the filesystem density info 156 */ 157 sblock.fs_avgfilesize = avgfilesize; 158 sblock.fs_avgfpdir = avgfilesperdir; 159 if (sblock.fs_avgfilesize <= 0) 160 printf("illegal expected average file size %d\n", 161 sblock.fs_avgfilesize), exit(14); 162 if (sblock.fs_avgfpdir <= 0) 163 printf("illegal expected number of files per directory %d\n", 164 sblock.fs_avgfpdir), exit(15); 165 /* 166 * collect and verify the block and fragment sizes 167 */ 168 sblock.fs_bsize = bsize; 169 sblock.fs_fsize = fsize; 170 if (!POWEROF2(sblock.fs_bsize)) { 171 printf("block size must be a power of 2, not %d\n", 172 sblock.fs_bsize); 173 exit(16); 174 } 175 if (!POWEROF2(sblock.fs_fsize)) { 176 printf("fragment size must be a power of 2, not %d\n", 177 sblock.fs_fsize); 178 exit(17); 179 } 180 if (sblock.fs_fsize < sectorsize) { 181 printf("increasing fragment size from %d to sector size (%d)\n", 182 sblock.fs_fsize, sectorsize); 183 sblock.fs_fsize = sectorsize; 184 } 185 if (sblock.fs_bsize < MINBSIZE) { 186 printf("increasing block size from %d to minimum (%d)\n", 187 sblock.fs_bsize, MINBSIZE); 188 sblock.fs_bsize = MINBSIZE; 189 } 190 if (sblock.fs_bsize < sblock.fs_fsize) { 191 printf("increasing block size from %d to fragment size (%d)\n", 192 sblock.fs_bsize, sblock.fs_fsize); 193 sblock.fs_bsize = sblock.fs_fsize; 194 } 195 if (sblock.fs_fsize * MAXFRAG < sblock.fs_bsize) { 196 printf( 197 "increasing fragment size from %d to block size / %d (%d)\n", 198 sblock.fs_fsize, MAXFRAG, sblock.fs_bsize / MAXFRAG); 199 sblock.fs_fsize = sblock.fs_bsize / MAXFRAG; 200 } 201 sblock.fs_bmask = ~(sblock.fs_bsize - 1); 202 sblock.fs_fmask = ~(sblock.fs_fsize - 1); 203 sblock.fs_qbmask = ~sblock.fs_bmask; 204 sblock.fs_qfmask = ~sblock.fs_fmask; 205 sblock.fs_bshift = ilog2(sblock.fs_bsize); 206 sblock.fs_fshift = ilog2(sblock.fs_fsize); 207 sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize); 208 sblock.fs_fragshift = ilog2(sblock.fs_frag); 209 if (sblock.fs_frag > MAXFRAG) { 210 printf("fragment size %d is still too small (can't happen)\n", 211 sblock.fs_bsize / MAXFRAG); 212 exit(21); 213 } 214 sblock.fs_nrpos = 1; 215 sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t); 216 sblock.fs_inopb = sblock.fs_bsize / sizeof(struct dinode); 217 sblock.fs_nspf = sblock.fs_fsize / sectorsize; 218 sblock.fs_fsbtodb = ilog2(NSPF(&sblock)); 219 sblock.fs_sblkno = 220 roundup(howmany(BBSIZE + SBSIZE, sblock.fs_fsize), sblock.fs_frag); 221 sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno + 222 roundup(howmany(SBSIZE, sblock.fs_fsize), sblock.fs_frag)); 223 sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag; 224 sblock.fs_cgoffset = 225 roundup(howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag); 226 sblock.fs_cgmask = 0xffffffff; 227 sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1; 228 for (sizepb = sblock.fs_bsize, i = 0; i < NIADDR; i++) { 229 sizepb *= NINDIR(&sblock); 230 sblock.fs_maxfilesize += sizepb; 231 } 232 /* 233 * Validate specified/determined secpercyl 234 * and calculate minimum cylinders per group. 235 */ 236 sblock.fs_spc = secpercyl; 237 for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc; 238 sblock.fs_cpc > 1 && (i & 1) == 0; 239 sblock.fs_cpc >>= 1, i >>= 1) 240 /* void */; 241 mincpc = sblock.fs_cpc; 242 bpcg = sblock.fs_spc * sectorsize; 243 inospercg = roundup(bpcg / sizeof(struct dinode), INOPB(&sblock)); 244 if (inospercg > MAXIPG(&sblock)) 245 inospercg = MAXIPG(&sblock); 246 used = (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock); 247 mincpgcnt = howmany(sblock.fs_cgoffset * (~sblock.fs_cgmask) + used, 248 sblock.fs_spc); 249 mincpg = roundup(mincpgcnt, mincpc); 250 /* 251 * Ensure that cylinder group with mincpg has enough space 252 * for block maps. 253 */ 254 sblock.fs_cpg = mincpg; 255 sblock.fs_ipg = inospercg; 256 if (maxcontig > 1) 257 sblock.fs_contigsumsize = MIN(maxcontig, FS_MAXCONTIG); 258 mapcramped = 0; 259 while (CGSIZE(&sblock) > sblock.fs_bsize) { 260 mapcramped = 1; 261 if (sblock.fs_bsize < MAXBSIZE) { 262 sblock.fs_bsize <<= 1; 263 if ((i & 1) == 0) 264 i >>= 1; 265 else { 266 sblock.fs_cpc <<= 1; 267 mincpc <<= 1; 268 mincpg = roundup(mincpgcnt, mincpc); 269 sblock.fs_cpg = mincpg; 270 } 271 sblock.fs_frag <<= 1; 272 sblock.fs_fragshift += 1; 273 if (sblock.fs_frag <= MAXFRAG) 274 continue; 275 } 276 if (sblock.fs_fsize == sblock.fs_bsize) { 277 printf("There is no block size that"); 278 printf(" can support this disk\n"); 279 exit(22); 280 } 281 sblock.fs_frag >>= 1; 282 sblock.fs_fragshift -= 1; 283 sblock.fs_fsize <<= 1; 284 sblock.fs_nspf <<= 1; 285 } 286 /* 287 * Ensure that cylinder group with mincpg has enough space for inodes. 288 */ 289 inodecramped = 0; 290 inospercg = calcipg(mincpg, bpcg, &usedb); 291 sblock.fs_ipg = inospercg; 292 while (inospercg > MAXIPG(&sblock)) { 293 inodecramped = 1; 294 if (mincpc == 1 || sblock.fs_frag == 1 || 295 sblock.fs_bsize == MINBSIZE) 296 break; 297 printf("With a block size of %d %s %d\n", sblock.fs_bsize, 298 "minimum bytes per inode is", 299 (int)((mincpg * (off_t)bpcg - usedb) / 300 MAXIPG(&sblock) + 1)); 301 sblock.fs_bsize >>= 1; 302 sblock.fs_frag >>= 1; 303 sblock.fs_fragshift -= 1; 304 mincpc >>= 1; 305 sblock.fs_cpg = roundup(mincpgcnt, mincpc); 306 if (CGSIZE(&sblock) > sblock.fs_bsize) { 307 sblock.fs_bsize <<= 1; 308 break; 309 } 310 mincpg = sblock.fs_cpg; 311 inospercg = calcipg(mincpg, bpcg, &usedb); 312 sblock.fs_ipg = inospercg; 313 } 314 if (inodecramped) { 315 if (inospercg > MAXIPG(&sblock)) { 316 printf("Minimum bytes per inode is %d\n", 317 (int)((mincpg * (off_t)bpcg - usedb) / 318 MAXIPG(&sblock) + 1)); 319 } else if (!mapcramped) { 320 printf("With %d bytes per inode, ", density); 321 printf("minimum cylinders per group is %ld\n", mincpg); 322 } 323 } 324 if (mapcramped) { 325 printf("With %d sectors per cylinder, ", sblock.fs_spc); 326 printf("minimum cylinders per group is %ld\n", mincpg); 327 } 328 if (inodecramped || mapcramped) { 329 if (sblock.fs_bsize != bsize) 330 printf("%s to be changed from %d to %d\n", 331 "This requires the block size", 332 bsize, sblock.fs_bsize); 333 if (sblock.fs_fsize != fsize) 334 printf("\t%s to be changed from %d to %d\n", 335 "and the fragment size", fsize, sblock.fs_fsize); 336 exit(23); 337 } 338 /* 339 * Calculate the number of cylinders per group 340 */ 341 sblock.fs_cpg = cpg; 342 if (sblock.fs_cpg % mincpc != 0) { 343 printf("%s groups must have a multiple of %ld cylinders\n", 344 cpgflg ? "Cylinder" : "Warning: cylinder", mincpc); 345 sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc); 346 if (!cpgflg) 347 cpg = sblock.fs_cpg; 348 } 349 /* 350 * Must ensure there is enough space for inodes. 351 */ 352 sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb); 353 while (sblock.fs_ipg > MAXIPG(&sblock)) { 354 inodecramped = 1; 355 sblock.fs_cpg -= mincpc; 356 sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb); 357 } 358 /* 359 * Must ensure there is enough space to hold block map. 360 */ 361 while (CGSIZE(&sblock) > sblock.fs_bsize) { 362 mapcramped = 1; 363 sblock.fs_cpg -= mincpc; 364 sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb); 365 } 366 sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 367 if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) { 368 printf("panic (fs_cpg * fs_spc) %% NSPF != 0"); 369 exit(24); 370 } 371 if (sblock.fs_cpg < mincpg) { 372 printf("cylinder groups must have at least %ld cylinders\n", 373 mincpg); 374 exit(25); 375 } else if (sblock.fs_cpg != cpg) { 376 if (!cpgflg) 377 printf("Warning: "); 378 else if (!mapcramped && !inodecramped) 379 exit(26); 380 if (mapcramped && inodecramped) 381 printf("Block size and bytes per inode restrict"); 382 else if (mapcramped) 383 printf("Block size restricts"); 384 else 385 printf("Bytes per inode restrict"); 386 printf(" cylinders per group to %d.\n", sblock.fs_cpg); 387 if (cpgflg) 388 exit(27); 389 } 390 sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock)); 391 /* 392 * Now have size for file system and nsect and ntrak. 393 * Determine number of cylinders and blocks in the file system. 394 */ 395 sblock.fs_size = fssize = dbtofsb(&sblock, fssize); 396 sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc; 397 if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) { 398 sblock.fs_ncyl++; 399 lwarn = 1; 400 } 401 if (sblock.fs_ncyl < 1) { 402 printf("file systems must have at least one cylinder\n"); 403 exit(28); 404 } 405 /* 406 * Determine feasability/values of rotational layout tables. 407 * 408 * The size of the rotational layout tables is limited by the 409 * size of the superblock, SBSIZE. The amount of space available 410 * for tables is calculated as (SBSIZE - sizeof (struct fs)). 411 * The size of these tables is inversely proportional to the block 412 * size of the file system. The size increases if sectors per track 413 * are not powers of two, because more cylinders must be described 414 * by the tables before the rotational pattern repeats (fs_cpc). 415 */ 416 sblock.fs_interleave = 1; 417 sblock.fs_trackskew = 0; 418 sblock.fs_npsect = secpercyl; 419 sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT; 420 sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs)); 421 if (sblock.fs_sbsize > SBSIZE) 422 sblock.fs_sbsize = SBSIZE; 423 sblock.fs_cpc = 0; 424 /* 425 * Compute/validate number of cylinder groups. 426 */ 427 sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; 428 if (sblock.fs_ncyl % sblock.fs_cpg) 429 sblock.fs_ncg++; 430 sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock); 431 i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1); 432 if (cgdmin(&sblock, i) - cgbase(&sblock, i) >= sblock.fs_fpg) { 433 printf("inode blocks/cyl group (%ld) >= data blocks (%ld)\n", 434 cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag, 435 (long)(sblock.fs_fpg / sblock.fs_frag)); 436 printf("number of cylinders per cylinder group (%d) %s.\n", 437 sblock.fs_cpg, "must be increased"); 438 exit(29); 439 } 440 j = sblock.fs_ncg - 1; 441 if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg && 442 cgdmin(&sblock, j) - cgbase(&sblock, j) > i) { 443 if (j == 0) { 444 printf("Filesystem must have at least %d sectors\n", 445 NSPF(&sblock) * 446 (cgdmin(&sblock, 0) + 3 * sblock.fs_frag)); 447 exit(30); 448 } 449 printf( 450"Warning: inode blocks/cyl group (%ld) >= data blocks (%ld) in last\n", 451 (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag, 452 i / sblock.fs_frag); 453 printf( 454" cylinder group. This implies %ld sector(s) cannot be allocated.\n", 455 i * NSPF(&sblock)); 456 sblock.fs_ncg--; 457 sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg; 458 sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc / 459 NSPF(&sblock); 460 lwarn = 0; 461 } 462 if (lwarn) { 463 printf("Warning: %d sector(s) in last cylinder unallocated\n", 464 sblock.fs_spc - 465 (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1) * 466 sblock.fs_spc)); 467 } 468 /* 469 * fill in remaining fields of the super block 470 */ 471 sblock.fs_csaddr = cgdmin(&sblock, 0); 472 sblock.fs_cssize = 473 fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); 474 /* 475 * The superblock fields 'fs_csmask' and 'fs_csshift' are no 476 * longer used. However, we still initialise them so that the 477 * filesystem remains compatible with old kernels. 478 */ 479 i = sblock.fs_bsize / sizeof(struct csum); 480 sblock.fs_csmask = ~(i - 1); 481 sblock.fs_csshift = ilog2(i); 482 fscs = (struct csum *)calloc(1, sblock.fs_cssize); 483 if (fscs == NULL) 484 errx(31, "calloc failed"); 485 sblock.fs_magic = FS_MAGIC; 486 sblock.fs_rotdelay = 0; 487 sblock.fs_minfree = minfree; 488 sblock.fs_maxcontig = maxcontig; 489 sblock.fs_maxbpg = maxbpg; 490 sblock.fs_rps = 60; 491 sblock.fs_optim = opt; 492 sblock.fs_cgrotor = 0; 493 sblock.fs_cstotal.cs_ndir = 0; 494 sblock.fs_cstotal.cs_nbfree = 0; 495 sblock.fs_cstotal.cs_nifree = 0; 496 sblock.fs_cstotal.cs_nffree = 0; 497 sblock.fs_fmod = 0; 498 sblock.fs_ronly = 0; 499 sblock.fs_clean = 1; 500 sblock.fs_id[0] = (long)utime; 501 sblock.fs_id[1] = random(); 502 503 /* 504 * Dump out summary information about file system. 505 */ 506 printf("%s:\t%d sectors in %d %s of %d tracks, %d sectors\n", 507 fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl, 508 "cylinders", sblock.fs_ntrak, sblock.fs_nsect); 509#define B2MBFACTOR (1 / (1024.0 * 1024.0)) 510 printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)%s\n", 511 (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR, 512 sblock.fs_ncg, sblock.fs_cpg, 513 (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, 514 sblock.fs_ipg, 515 sblock.fs_flags & FS_DOSOFTDEP ? " SOFTUPDATES" : ""); 516#undef B2MBFACTOR 517 /* 518 * Now build the cylinders group blocks and 519 * then print out indices of cylinder groups. 520 */ 521 printf("super-block backups (for fsck -b #) at:\n"); 522 i = 0; 523 width = charsperline(); 524 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { 525 initcg(cylno, utime); 526 j = snprintf(tmpbuf, sizeof(tmpbuf), " %ld%s", 527 fsbtodb(&sblock, cgsblock(&sblock, cylno)), 528 cylno < (sblock.fs_ncg-1) ? "," : ""); 529 if (j < 0) 530 tmpbuf[j = 0] = '\0'; 531 if (i + j >= width) { 532 printf("\n"); 533 i = 0; 534 } 535 i += j; 536 printf("%s", tmpbuf); 537 fflush(stdout); 538 } 539 printf("\n"); 540 if (Nflag) 541 exit(0); 542 /* 543 * Now construct the initial file system, 544 * then write out the super-block. 545 */ 546 fsinit(utime); 547 sblock.fs_time = utime; 548 wtfs((int)SBOFF / sectorsize, SBSIZE, (char *)&sblock); 549 for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) 550 wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), 551 sblock.fs_cssize - i < sblock.fs_bsize ? 552 sblock.fs_cssize - i : sblock.fs_bsize, 553 ((char *)fscs) + i); 554 /* 555 * Write out the duplicate super blocks 556 */ 557 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) 558 wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), 559 SBSIZE, (char *)&sblock); 560 wtfsflush(); 561 /* 562 * Update information about this partion in pack 563 * label, to that it may be updated on disk. 564 */ 565 pp->p_fstype = FS_BSDFFS; 566 pp->p_fsize = sblock.fs_fsize; 567 pp->p_frag = sblock.fs_frag; 568 pp->p_cpg = sblock.fs_cpg; 569} 570 571/* 572 * Initialize a cylinder group. 573 */ 574void 575initcg(int cylno, time_t utime) 576{ 577 daddr_t cbase, d, dlower, dupper, dmax, blkno; 578 struct csum *cs; 579 long i, j; 580 581 /* 582 * Determine block bounds for cylinder group. 583 * Allow space for super block summary information in first 584 * cylinder group. 585 */ 586 cbase = cgbase(&sblock, cylno); 587 dmax = cbase + sblock.fs_fpg; 588 if (dmax > sblock.fs_size) 589 dmax = sblock.fs_size; 590 dlower = cgsblock(&sblock, cylno) - cbase; 591 dupper = cgdmin(&sblock, cylno) - cbase; 592 if (cylno == 0) 593 dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); 594 cs = fscs + cylno; 595 memset(&acg, 0, sblock.fs_cgsize); 596 acg.cg_time = utime; 597 acg.cg_magic = CG_MAGIC; 598 acg.cg_cgx = cylno; 599 if (cylno == sblock.fs_ncg - 1) 600 acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; 601 else 602 acg.cg_ncyl = sblock.fs_cpg; 603 acg.cg_niblk = sblock.fs_ipg; 604 acg.cg_ndblk = dmax - cbase; 605 if (sblock.fs_contigsumsize > 0) 606 acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag; 607 acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield); 608 acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(int32_t); 609 acg.cg_iusedoff = acg.cg_boff + 610 sblock.fs_cpg * sizeof(u_int16_t); 611 acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY); 612 if (sblock.fs_contigsumsize <= 0) { 613 acg.cg_nextfreeoff = acg.cg_freeoff + 614 howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), 615 NBBY); 616 } else { 617 acg.cg_clustersumoff = acg.cg_freeoff + howmany 618 (sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY) - 619 sizeof(u_int32_t); 620 acg.cg_clustersumoff = 621 roundup(acg.cg_clustersumoff, sizeof(u_int32_t)); 622 acg.cg_clusteroff = acg.cg_clustersumoff + 623 (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t); 624 acg.cg_nextfreeoff = acg.cg_clusteroff + howmany 625 (sblock.fs_cpg * sblock.fs_spc / NSPB(&sblock), NBBY); 626 } 627 if (acg.cg_nextfreeoff - (long)(&acg.cg_firstfield) > 628 sblock.fs_cgsize) { 629 printf("Panic: cylinder group too big\n"); 630 exit(37); 631 } 632 acg.cg_cs.cs_nifree += sblock.fs_ipg; 633 if (cylno == 0) 634 for (i = 0; i < ROOTINO; i++) { 635 setbit(cg_inosused(&acg), i); 636 acg.cg_cs.cs_nifree--; 637 } 638 for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) { 639 for (j = 0; j < sblock.fs_bsize / sizeof(struct dinode); j++) 640 zino[j].di_gen = random(); 641 wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), 642 sblock.fs_bsize, (char *)zino); 643 } 644 if (cylno > 0) { 645 /* 646 * In cylno 0, beginning space is reserved 647 * for boot and super blocks. 648 */ 649 for (d = 0; d < dlower; d += sblock.fs_frag) { 650 blkno = d / sblock.fs_frag; 651 setblock(&sblock, cg_blksfree(&acg), blkno); 652 if (sblock.fs_contigsumsize > 0) 653 setbit(cg_clustersfree(&acg), blkno); 654 acg.cg_cs.cs_nbfree++; 655 cg_blktot(&acg)[cbtocylno(&sblock, d)]++; 656 cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) 657 [cbtorpos(&sblock, d)]++; 658 } 659 sblock.fs_dsize += dlower; 660 } 661 sblock.fs_dsize += acg.cg_ndblk - dupper; 662 if ((i = dupper % sblock.fs_frag)) { 663 acg.cg_frsum[sblock.fs_frag - i]++; 664 for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) { 665 setbit(cg_blksfree(&acg), dupper); 666 acg.cg_cs.cs_nffree++; 667 } 668 } 669 for (d = dupper; d + sblock.fs_frag <= dmax - cbase;) { 670 blkno = d / sblock.fs_frag; 671 setblock(&sblock, cg_blksfree(&acg), blkno); 672 if (sblock.fs_contigsumsize > 0) 673 setbit(cg_clustersfree(&acg), blkno); 674 acg.cg_cs.cs_nbfree++; 675 cg_blktot(&acg)[cbtocylno(&sblock, d)]++; 676 cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) 677 [cbtorpos(&sblock, d)]++; 678 d += sblock.fs_frag; 679 } 680 if (d < dmax - cbase) { 681 acg.cg_frsum[dmax - cbase - d]++; 682 for (; d < dmax - cbase; d++) { 683 setbit(cg_blksfree(&acg), d); 684 acg.cg_cs.cs_nffree++; 685 } 686 } 687 if (sblock.fs_contigsumsize > 0) { 688 int32_t *sump = cg_clustersum(&acg); 689 u_char *mapp = cg_clustersfree(&acg); 690 int map = *mapp++; 691 int bit = 1; 692 int run = 0; 693 694 for (i = 0; i < acg.cg_nclusterblks; i++) { 695 if ((map & bit) != 0) 696 run++; 697 else if (run != 0) { 698 if (run > sblock.fs_contigsumsize) 699 run = sblock.fs_contigsumsize; 700 sump[run]++; 701 run = 0; 702 } 703 if ((i & (NBBY - 1)) != NBBY - 1) 704 bit <<= 1; 705 else { 706 map = *mapp++; 707 bit = 1; 708 } 709 } 710 if (run != 0) { 711 if (run > sblock.fs_contigsumsize) 712 run = sblock.fs_contigsumsize; 713 sump[run]++; 714 } 715 } 716 sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; 717 sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; 718 sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; 719 sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; 720 *cs = acg.cg_cs; 721 wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), 722 sblock.fs_bsize, (char *)&acg); 723} 724 725/* 726 * initialize the file system 727 */ 728struct dinode node; 729 730#define PREDEFDIR 2 731 732struct direct root_dir[] = { 733 { ROOTINO, sizeof(struct direct), DT_DIR, 1, "." }, 734 { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, 735}; 736struct odirect { 737 u_long d_ino; 738 u_short d_reclen; 739 u_short d_namlen; 740 u_char d_name[MAXNAMLEN + 1]; 741} oroot_dir[] = { 742 { ROOTINO, sizeof(struct direct), 1, "." }, 743 { ROOTINO, sizeof(struct direct), 2, ".." }, 744}; 745char buf[MAXBSIZE]; 746 747void 748fsinit(time_t utime) 749{ 750 751 /* 752 * initialize the node 753 */ 754 node.di_atime = utime; 755 node.di_mtime = utime; 756 node.di_ctime = utime; 757 /* 758 * create the root directory 759 */ 760 node.di_mode = IFDIR | UMASK; 761 node.di_nlink = PREDEFDIR; 762 node.di_size = makedir(root_dir, PREDEFDIR); 763 node.di_db[0] = alloc(sblock.fs_fsize, node.di_mode); 764 node.di_blocks = btodb(fragroundup(&sblock, node.di_size)); 765 wtfs(fsbtodb(&sblock, node.di_db[0]), sblock.fs_fsize, buf); 766 iput(&node, ROOTINO); 767} 768 769/* 770 * construct a set of directory entries in "buf". 771 * return size of directory. 772 */ 773int 774makedir(struct direct *protodir, int entries) 775{ 776 char *cp; 777 int i, spcleft; 778 779 spcleft = DIRBLKSIZ; 780 for (cp = buf, i = 0; i < entries - 1; i++) { 781 protodir[i].d_reclen = DIRSIZ(0, &protodir[i]); 782 memmove(cp, &protodir[i], protodir[i].d_reclen); 783 cp += protodir[i].d_reclen; 784 spcleft -= protodir[i].d_reclen; 785 } 786 protodir[i].d_reclen = spcleft; 787 memmove(cp, &protodir[i], DIRSIZ(0, &protodir[i])); 788 return (DIRBLKSIZ); 789} 790 791/* 792 * allocate a block or frag 793 */ 794daddr_t 795alloc(int size, int mode) 796{ 797 int i, frag; 798 daddr_t d, blkno; 799 800 rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 801 (char *)&acg); 802 if (acg.cg_magic != CG_MAGIC) { 803 printf("cg 0: bad magic number\n"); 804 return (0); 805 } 806 if (acg.cg_cs.cs_nbfree == 0) { 807 printf("first cylinder group ran out of space\n"); 808 return (0); 809 } 810 for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) 811 if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag)) 812 goto goth; 813 printf("internal error: can't find block in cyl 0\n"); 814 return (0); 815goth: 816 blkno = fragstoblks(&sblock, d); 817 clrblock(&sblock, cg_blksfree(&acg), blkno); 818 if (sblock.fs_contigsumsize > 0) 819 clrbit(cg_clustersfree(&acg), blkno); 820 acg.cg_cs.cs_nbfree--; 821 sblock.fs_cstotal.cs_nbfree--; 822 fscs[0].cs_nbfree--; 823 if (mode & IFDIR) { 824 acg.cg_cs.cs_ndir++; 825 sblock.fs_cstotal.cs_ndir++; 826 fscs[0].cs_ndir++; 827 } 828 cg_blktot(&acg)[cbtocylno(&sblock, d)]--; 829 cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--; 830 if (size != sblock.fs_bsize) { 831 frag = howmany(size, sblock.fs_fsize); 832 fscs[0].cs_nffree += sblock.fs_frag - frag; 833 sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; 834 acg.cg_cs.cs_nffree += sblock.fs_frag - frag; 835 acg.cg_frsum[sblock.fs_frag - frag]++; 836 for (i = frag; i < sblock.fs_frag; i++) 837 setbit(cg_blksfree(&acg), d + i); 838 } 839 wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 840 (char *)&acg); 841 return (d); 842} 843 844/* 845 * Calculate number of inodes per group. 846 */ 847long 848calcipg(long lcpg, long bpcg, off_t *usedbp) 849{ 850 int i; 851 long ipg, new_ipg, ncg, ncyl; 852 off_t usedb; 853 854 /* 855 * Prepare to scale by fssize / (number of sectors in cylinder groups). 856 * Note that fssize is still in sectors, not filesystem blocks. 857 */ 858 ncyl = howmany(fssize, (u_int)secpercyl); 859 ncg = howmany(ncyl, lcpg); 860 /* 861 * Iterate a few times to allow for ipg depending on itself. 862 */ 863 ipg = 0; 864 for (i = 0; i < 10; i++) { 865 usedb = (sblock.fs_iblkno + ipg / INOPF(&sblock)) * 866 NSPF(&sblock) * (off_t)sectorsize; 867 new_ipg = (lcpg * (quad_t)bpcg - usedb) / density * 868 fssize / ncg / secpercyl / lcpg; 869 new_ipg = roundup(new_ipg, INOPB(&sblock)); 870 if (new_ipg == ipg) 871 break; 872 ipg = new_ipg; 873 } 874 *usedbp = usedb; 875 return (ipg); 876} 877 878/* 879 * Allocate an inode on the disk 880 */ 881void 882iput(struct dinode *ip, ino_t ino) 883{ 884 struct dinode lbuf[MAXINOPB]; 885 daddr_t d; 886 int c; 887 888 ip->di_gen = random(); 889 c = ino_to_cg(&sblock, ino); 890 rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 891 (char *)&acg); 892 if (acg.cg_magic != CG_MAGIC) { 893 printf("cg 0: bad magic number\n"); 894 exit(31); 895 } 896 acg.cg_cs.cs_nifree--; 897 setbit(cg_inosused(&acg), ino); 898 wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 899 (char *)&acg); 900 sblock.fs_cstotal.cs_nifree--; 901 fscs[0].cs_nifree--; 902 if (ino >= sblock.fs_ipg * sblock.fs_ncg) { 903 printf("fsinit: inode value out of range (%d).\n", ino); 904 exit(32); 905 } 906 d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino)); 907 rdfs(d, sblock.fs_bsize, (char *)lbuf); 908 lbuf[ino_to_fsbo(&sblock, ino)] = *ip; 909 wtfs(d, sblock.fs_bsize, (char *)lbuf); 910} 911 912/* 913 * read a block from the file system 914 */ 915void 916rdfs(daddr_t bno, int size, char *bf) 917{ 918 int n; 919 920 wtfsflush(); 921 if (lseek(fsi, (off_t)bno * sectorsize, 0) < 0) { 922 printf("seek error: %ld\n", (long)bno); 923 err(33, "rdfs"); 924 } 925 n = read(fsi, bf, size); 926 if (n != size) { 927 printf("read error: %ld\n", (long)bno); 928 err(34, "rdfs"); 929 } 930} 931 932#define WCSIZE (128 * 1024) 933daddr_t wc_sect; /* units of sectorsize */ 934int wc_end; /* bytes */ 935static char wc[WCSIZE]; /* bytes */ 936 937/* 938 * Flush dirty write behind buffer. 939 */ 940static void 941wtfsflush() 942{ 943 int n; 944 if (wc_end) { 945 if (lseek(fso, (off_t)wc_sect * sectorsize, SEEK_SET) < 0) { 946 printf("seek error: %ld\n", (long)wc_sect); 947 err(35, "wtfs - writecombine"); 948 } 949 n = write(fso, wc, wc_end); 950 if (n != wc_end) { 951 printf("write error: %ld\n", (long)wc_sect); 952 err(36, "wtfs - writecombine"); 953 } 954 wc_end = 0; 955 } 956} 957 958/* 959 * write a block to the file system 960 */ 961static void 962wtfs(daddr_t bno, int size, char *bf) 963{ 964 int done, n; 965 966 if (Nflag) 967 return; 968 done = 0; 969 if (wc_end == 0 && size <= WCSIZE) { 970 wc_sect = bno; 971 bcopy(bf, wc, size); 972 wc_end = size; 973 if (wc_end < WCSIZE) 974 return; 975 done = 1; 976 } 977 if ((off_t)wc_sect * sectorsize + wc_end == (off_t)bno * sectorsize && 978 wc_end + size <= WCSIZE) { 979 bcopy(bf, wc + wc_end, size); 980 wc_end += size; 981 if (wc_end < WCSIZE) 982 return; 983 done = 1; 984 } 985 wtfsflush(); 986 if (done) 987 return; 988 if (lseek(fso, (off_t)bno * sectorsize, SEEK_SET) < 0) { 989 printf("seek error: %ld\n", (long)bno); 990 err(35, "wtfs"); 991 } 992 n = write(fso, bf, size); 993 if (n != size) { 994 printf("write error: %ld\n", (long)bno); 995 err(36, "wtfs"); 996 } 997} 998 999/* 1000 * check if a block is available 1001 */ 1002static int 1003isblock(struct fs *fs, unsigned char *cp, int h) 1004{ 1005 unsigned char mask; 1006 1007 switch (fs->fs_frag) { 1008 case 8: 1009 return (cp[h] == 0xff); 1010 case 4: 1011 mask = 0x0f << ((h & 0x1) << 2); 1012 return ((cp[h >> 1] & mask) == mask); 1013 case 2: 1014 mask = 0x03 << ((h & 0x3) << 1); 1015 return ((cp[h >> 2] & mask) == mask); 1016 case 1: 1017 mask = 0x01 << (h & 0x7); 1018 return ((cp[h >> 3] & mask) == mask); 1019 default: 1020 fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 1021 return (0); 1022 } 1023} 1024 1025/* 1026 * take a block out of the map 1027 */ 1028static void 1029clrblock(struct fs *fs, unsigned char *cp, int h) 1030{ 1031 switch ((fs)->fs_frag) { 1032 case 8: 1033 cp[h] = 0; 1034 return; 1035 case 4: 1036 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 1037 return; 1038 case 2: 1039 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 1040 return; 1041 case 1: 1042 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 1043 return; 1044 default: 1045 fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag); 1046 return; 1047 } 1048} 1049 1050/* 1051 * put a block into the map 1052 */ 1053static void 1054setblock(struct fs *fs, unsigned char *cp, int h) 1055{ 1056 switch (fs->fs_frag) { 1057 case 8: 1058 cp[h] = 0xff; 1059 return; 1060 case 4: 1061 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 1062 return; 1063 case 2: 1064 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 1065 return; 1066 case 1: 1067 cp[h >> 3] |= (0x01 << (h & 0x7)); 1068 return; 1069 default: 1070 fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); 1071 return; 1072 } 1073} 1074 1075/* 1076 * Determine the number of characters in a 1077 * single line. 1078 */ 1079 1080static int 1081charsperline(void) 1082{ 1083 int columns; 1084 char *cp; 1085 struct winsize ws; 1086 1087 columns = 0; 1088 if (ioctl(0, TIOCGWINSZ, &ws) != -1) 1089 columns = ws.ws_col; 1090 if (columns == 0 && (cp = getenv("COLUMNS"))) 1091 columns = atoi(cp); 1092 if (columns == 0) 1093 columns = 80; /* last resort */ 1094 return (columns); 1095} 1096 1097static int 1098ilog2(int val) 1099{ 1100 u_int n; 1101 1102 for (n = 0; n < sizeof(n) * NBBY; n++) 1103 if (1 << n == val) 1104 return (n); 1105 errx(1, "ilog2: %d is not a power of 2\n", val); 1106} 1107