1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 static char sccsid[] = "@(#)mkfs.c 6.9 (Berkeley) 07/08/88"; 9 #endif not lint 10 11 #ifndef STANDALONE 12 #include <stdio.h> 13 #include <a.out.h> 14 #endif 15 16 #include <sys/param.h> 17 #include <sys/inode.h> 18 #include <sys/fs.h> 19 #include <sys/dir.h> 20 #include <sys/disklabel.h> 21 #include <machine/endian.h> 22 23 /* 24 * make file system for cylinder-group style file systems 25 */ 26 27 /* 28 * The size of a cylinder group is calculated by CGSIZE. The maximum size 29 * is limited by the fact that cylinder groups are at most one block. 30 * Its size is derived from the size of the maps maintained in the 31 * cylinder group and the (struct cg) size. 32 */ 33 #define CGSIZE(fs) \ 34 /* base cg */ (sizeof(struct cg) + \ 35 /* blktot size */ (fs)->fs_cpg * sizeof(long) + \ 36 /* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(short) + \ 37 /* inode map */ howmany((fs)->fs_ipg, NBBY) + \ 38 /* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY)) 39 40 /* 41 * We limit the size of the inode map to be no more than a 42 * third of the cylinder group space, since we must leave at 43 * least an equal amount of space for the block map. 44 * 45 * N.B.: MAXIPG must be a multiple of INOPB(fs). 46 */ 47 #define MAXIPG(fs) roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs)) 48 49 #define UMASK 0755 50 #define MAXINOPB (MAXBSIZE / sizeof(struct dinode)) 51 #define POWEROF2(num) (((num) & ((num) - 1)) == 0) 52 53 /* 54 * variables set up by front end. 55 */ 56 extern int Nflag; /* run mkfs without writing file system */ 57 extern int fssize; /* file system size */ 58 extern int ntracks; /* # tracks/cylinder */ 59 extern int nsectors; /* # sectors/track */ 60 extern int nphyssectors; /* # sectors/track including spares */ 61 extern int secpercyl; /* sectors per cylinder */ 62 extern int sectorsize; /* bytes/sector */ 63 extern int rpm; /* revolutions/minute of drive */ 64 extern int interleave; /* hardware sector interleave */ 65 extern int trackskew; /* sector 0 skew, per track */ 66 extern int headswitch; /* head switch time, usec */ 67 extern int trackseek; /* track-to-track seek, usec */ 68 extern int fsize; /* fragment size */ 69 extern int bsize; /* block size */ 70 extern int cpg; /* cylinders/cylinder group */ 71 extern int cpgflg; /* cylinders/cylinder group flag was given */ 72 extern int minfree; /* free space threshold */ 73 extern int opt; /* optimization preference (space or time) */ 74 extern int density; /* number of bytes per inode */ 75 extern int maxcontig; /* max contiguous blocks to allocate */ 76 extern int rotdelay; /* rotational delay between blocks */ 77 extern int maxbpg; /* maximum blocks per file in a cyl group */ 78 extern int nrpos; /* # of distinguished rotational positions */ 79 extern int bbsize; /* boot block size */ 80 extern int sbsize; /* superblock size */ 81 82 union { 83 struct fs fs; 84 char pad[SBSIZE]; 85 } fsun; 86 #define sblock fsun.fs 87 struct csum *fscs; 88 89 union { 90 struct cg cg; 91 char pad[MAXBSIZE]; 92 } cgun; 93 #define acg cgun.cg 94 95 struct dinode zino[MAXBSIZE / sizeof(struct dinode)]; 96 97 int fsi, fso; 98 time_t utime; 99 daddr_t alloc(); 100 101 mkfs(pp, fsys, fi, fo) 102 struct partition *pp; 103 char *fsys; 104 int fi, fo; 105 { 106 register long i, mincpc, mincpg, inospercg; 107 long cylno, rpos, blk, j, warn = 0; 108 long used, mincpgcnt, bpcg; 109 long mapcramped, inodecramped; 110 long postblsize, rotblsize, totalsbsize; 111 112 #ifndef STANDALONE 113 time(&utime); 114 #endif 115 fsi = fi; 116 fso = fo; 117 /* 118 * Validate the given file system size. 119 * Verify that its last block can actually be accessed. 120 */ 121 if (fssize <= 0) 122 printf("preposterous size %d\n", fssize), exit(1); 123 wtfs(fssize - 1, sectorsize, (char *)&sblock); 124 /* 125 * collect and verify the sector and track info 126 */ 127 sblock.fs_nsect = nsectors; 128 sblock.fs_ntrak = ntracks; 129 if (sblock.fs_ntrak <= 0) 130 printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1); 131 if (sblock.fs_nsect <= 0) 132 printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1); 133 /* 134 * collect and verify the block and fragment sizes 135 */ 136 sblock.fs_bsize = bsize; 137 sblock.fs_fsize = fsize; 138 if (!POWEROF2(sblock.fs_bsize)) { 139 printf("block size must be a power of 2, not %d\n", 140 sblock.fs_bsize); 141 exit(1); 142 } 143 if (!POWEROF2(sblock.fs_fsize)) { 144 printf("fragment size must be a power of 2, not %d\n", 145 sblock.fs_fsize); 146 exit(1); 147 } 148 if (sblock.fs_fsize < sectorsize) { 149 printf("fragment size %d is too small, minimum is %d\n", 150 sblock.fs_fsize, sectorsize); 151 exit(1); 152 } 153 if (sblock.fs_bsize < MINBSIZE) { 154 printf("block size %d is too small, minimum is %d\n", 155 sblock.fs_bsize, MINBSIZE); 156 exit(1); 157 } 158 if (sblock.fs_bsize < sblock.fs_fsize) { 159 printf("block size (%d) cannot be smaller than fragment size (%d)\n", 160 sblock.fs_bsize, sblock.fs_fsize); 161 exit(1); 162 } 163 sblock.fs_bmask = ~(sblock.fs_bsize - 1); 164 sblock.fs_fmask = ~(sblock.fs_fsize - 1); 165 /* 166 * Planning now for future expansion. 167 */ 168 # if (BYTE_ORDER == BIG_ENDIAN) 169 sblock.fs_qbmask.val[0] = 0; 170 sblock.fs_qbmask.val[1] = ~sblock.fs_bmask; 171 sblock.fs_qfmask.val[0] = 0; 172 sblock.fs_qfmask.val[1] = ~sblock.fs_fmask; 173 # endif /* BIG_ENDIAN */ 174 # if (BYTE_ORDER == LITTLE_ENDIAN) 175 sblock.fs_qbmask.val[0] = ~sblock.fs_bmask; 176 sblock.fs_qbmask.val[1] = 0; 177 sblock.fs_qfmask.val[0] = ~sblock.fs_fmask; 178 sblock.fs_qfmask.val[1] = 0; 179 # endif /* LITTLE_ENDIAN */ 180 for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1) 181 sblock.fs_bshift++; 182 for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1) 183 sblock.fs_fshift++; 184 sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize); 185 for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1) 186 sblock.fs_fragshift++; 187 if (sblock.fs_frag > MAXFRAG) { 188 printf("fragment size %d is too small, minimum with block size %d is %d\n", 189 sblock.fs_fsize, sblock.fs_bsize, 190 sblock.fs_bsize / MAXFRAG); 191 exit(1); 192 } 193 sblock.fs_nrpos = nrpos; 194 sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t); 195 sblock.fs_inopb = sblock.fs_bsize / sizeof(struct dinode); 196 sblock.fs_nspf = sblock.fs_fsize / sectorsize; 197 for (sblock.fs_fsbtodb = 0, i = NSPF(&sblock); i > 1; i >>= 1) 198 sblock.fs_fsbtodb++; 199 sblock.fs_sblkno = 200 roundup(howmany(bbsize + sbsize, sblock.fs_fsize), sblock.fs_frag); 201 sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno + 202 roundup(howmany(sbsize, sblock.fs_fsize), sblock.fs_frag)); 203 sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag; 204 sblock.fs_cgoffset = roundup( 205 howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag); 206 for (sblock.fs_cgmask = 0xffffffff, i = sblock.fs_ntrak; i > 1; i >>= 1) 207 sblock.fs_cgmask <<= 1; 208 if (!POWEROF2(sblock.fs_ntrak)) 209 sblock.fs_cgmask <<= 1; 210 /* 211 * Validate specified/determined secpercyl 212 * and calculate minimum cylinders per group. 213 */ 214 sblock.fs_spc = secpercyl; 215 for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc; 216 sblock.fs_cpc > 1 && (i & 1) == 0; 217 sblock.fs_cpc >>= 1, i >>= 1) 218 /* void */; 219 mincpc = sblock.fs_cpc; 220 bpcg = sblock.fs_spc * sectorsize; 221 inospercg = roundup(bpcg / sizeof(struct dinode), INOPB(&sblock)); 222 if (inospercg > MAXIPG(&sblock)) 223 inospercg = MAXIPG(&sblock); 224 used = (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock); 225 mincpgcnt = howmany(sblock.fs_cgoffset * (~sblock.fs_cgmask) + used, 226 sblock.fs_spc); 227 mincpg = roundup(mincpgcnt, mincpc); 228 /* 229 * Insure that cylinder group with mincpg has enough space 230 * for block maps 231 */ 232 sblock.fs_cpg = mincpg; 233 sblock.fs_ipg = inospercg; 234 mapcramped = 0; 235 while (CGSIZE(&sblock) > sblock.fs_bsize) { 236 mapcramped = 1; 237 if (sblock.fs_bsize < MAXBSIZE) { 238 sblock.fs_bsize <<= 1; 239 if ((i & 1) == 0) { 240 i >>= 1; 241 } else { 242 sblock.fs_cpc <<= 1; 243 mincpc <<= 1; 244 mincpg = roundup(mincpgcnt, mincpc); 245 sblock.fs_cpg = mincpg; 246 } 247 sblock.fs_frag <<= 1; 248 sblock.fs_fragshift += 1; 249 if (sblock.fs_frag <= MAXFRAG) 250 continue; 251 } 252 if (sblock.fs_fsize == sblock.fs_bsize) { 253 printf("There is no block size that"); 254 printf(" can support this disk\n"); 255 exit(1); 256 } 257 sblock.fs_frag >>= 1; 258 sblock.fs_fragshift -= 1; 259 sblock.fs_fsize <<= 1; 260 sblock.fs_nspf <<= 1; 261 } 262 /* 263 * Insure that cylinder group with mincpg has enough space for inodes 264 */ 265 inodecramped = 0; 266 used *= sectorsize; 267 inospercg = roundup((mincpg * bpcg - used) / density, INOPB(&sblock)); 268 sblock.fs_ipg = inospercg; 269 while (inospercg > MAXIPG(&sblock)) { 270 inodecramped = 1; 271 if (mincpc == 1 || sblock.fs_frag == 1 || 272 sblock.fs_bsize == MINBSIZE) 273 break; 274 printf("With a block size of %d %s %d\n", sblock.fs_bsize, 275 "minimum bytes per inode is", 276 (mincpg * bpcg - used) / MAXIPG(&sblock) + 1); 277 sblock.fs_bsize >>= 1; 278 sblock.fs_frag >>= 1; 279 sblock.fs_fragshift -= 1; 280 mincpc >>= 1; 281 sblock.fs_cpg = roundup(mincpgcnt, mincpc); 282 if (CGSIZE(&sblock) > sblock.fs_bsize) { 283 sblock.fs_bsize <<= 1; 284 break; 285 } 286 mincpg = sblock.fs_cpg; 287 inospercg = 288 roundup((mincpg * bpcg - used) / density, INOPB(&sblock)); 289 sblock.fs_ipg = inospercg; 290 } 291 if (inodecramped) { 292 if (inospercg > MAXIPG(&sblock)) { 293 printf("Minimum bytes per inode is %d\n", 294 (mincpg * bpcg - used) / MAXIPG(&sblock) + 1); 295 } else if (!mapcramped) { 296 printf("With %d bytes per inode, ", density); 297 printf("minimum cylinders per group is %d\n", mincpg); 298 } 299 } 300 if (mapcramped) { 301 printf("With %d sectors per cylinder, ", sblock.fs_spc); 302 printf("minimum cylinders per group is %d\n", mincpg); 303 } 304 if (inodecramped || mapcramped) { 305 if (sblock.fs_bsize != bsize) 306 printf("%s to be changed from %d to %d\n", 307 "This requires the block size", 308 bsize, sblock.fs_bsize); 309 if (sblock.fs_fsize != fsize) 310 printf("\t%s to be changed from %d to %d\n", 311 "and the fragment size", 312 fsize, sblock.fs_fsize); 313 exit(1); 314 } 315 /* 316 * Calculate the number of cylinders per group 317 */ 318 sblock.fs_cpg = cpg; 319 if (sblock.fs_cpg % mincpc != 0) { 320 printf("%s groups must have a multiple of %d cylinders\n", 321 cpgflg ? "Cylinder" : "Warning: cylinder", mincpc); 322 sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc); 323 if (!cpgflg) 324 cpg = sblock.fs_cpg; 325 } 326 /* 327 * Must insure there is enough space for inodes 328 */ 329 sblock.fs_ipg = roundup((sblock.fs_cpg * bpcg - used) / density, 330 INOPB(&sblock)); 331 while (sblock.fs_ipg > MAXIPG(&sblock)) { 332 inodecramped = 1; 333 sblock.fs_cpg -= mincpc; 334 sblock.fs_ipg = roundup((sblock.fs_cpg * bpcg - used) / density, 335 INOPB(&sblock)); 336 } 337 /* 338 * Must insure there is enough space to hold block map 339 */ 340 while (CGSIZE(&sblock) > sblock.fs_bsize) { 341 mapcramped = 1; 342 sblock.fs_cpg -= mincpc; 343 sblock.fs_ipg = roundup((sblock.fs_cpg * bpcg - used) / density, 344 INOPB(&sblock)); 345 } 346 sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 347 if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) { 348 printf("newfs: panic (fs_cpg * fs_spc) % NSPF != 0"); 349 exit(2); 350 } 351 if (sblock.fs_cpg < mincpg) { 352 printf("cylinder groups must have at least %d cylinders\n", 353 mincpg); 354 exit(1); 355 } else if (sblock.fs_cpg != cpg) { 356 if (!cpgflg) 357 printf("Warning: "); 358 else if (!mapcramped && !inodecramped) 359 exit(1); 360 if (mapcramped && inodecramped) 361 printf("Block size and bytes per inode restrict"); 362 else if (mapcramped) 363 printf("Block size restricts"); 364 else 365 printf("Bytes per inode restrict"); 366 printf(" cylinders per group to %d.\n", sblock.fs_cpg); 367 if (cpgflg) 368 exit(1); 369 } 370 sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock)); 371 /* 372 * Now have size for file system and nsect and ntrak. 373 * Determine number of cylinders and blocks in the file system. 374 */ 375 sblock.fs_size = fssize = dbtofsb(&sblock, fssize); 376 sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc; 377 if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) { 378 sblock.fs_ncyl++; 379 warn = 1; 380 } 381 if (sblock.fs_ncyl < 1) { 382 printf("file systems must have at least one cylinder\n"); 383 exit(1); 384 } 385 /* 386 * Determine feasability/values of rotational layout tables. 387 * 388 * The size of the rotational layout tables is limited by the 389 * size of the superblock, SBSIZE. The amount of space available 390 * for tables is calculated as (SBSIZE - sizeof (struct fs)). 391 * The size of these tables is inversely proportional to the block 392 * size of the file system. The size increases if sectors per track 393 * are not powers of two, because more cylinders must be described 394 * by the tables before the rotational pattern repeats (fs_cpc). 395 */ 396 sblock.fs_interleave = interleave; 397 sblock.fs_trackskew = trackskew; 398 sblock.fs_npsect = nphyssectors; 399 sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT; 400 sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs)); 401 if (sblock.fs_ntrak == 1) { 402 sblock.fs_cpc = 0; 403 goto next; 404 } 405 postblsize = sblock.fs_nrpos * sblock.fs_cpc * sizeof(short); 406 rotblsize = sblock.fs_cpc * sblock.fs_spc / NSPB(&sblock); 407 totalsbsize = sizeof(struct fs) + rotblsize; 408 if (sblock.fs_nrpos == 8 && sblock.fs_cpc <= 16) { 409 /* use old static table space */ 410 sblock.fs_postbloff = (char *)(&sblock.fs_opostbl[0][0]) - 411 (char *)(&sblock.fs_link); 412 sblock.fs_rotbloff = &sblock.fs_space[0] - 413 (u_char *)(&sblock.fs_link); 414 } else { 415 /* use dynamic table space */ 416 sblock.fs_postbloff = &sblock.fs_space[0] - 417 (u_char *)(&sblock.fs_link); 418 sblock.fs_rotbloff = sblock.fs_postbloff + postblsize; 419 totalsbsize += postblsize; 420 } 421 if (totalsbsize > SBSIZE || 422 sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) { 423 printf("%s %s %d %s %d.%s", 424 "Warning: insufficient space in super block for\n", 425 "rotational layout tables with nsect", sblock.fs_nsect, 426 "and ntrak", sblock.fs_ntrak, 427 "\nFile system performance may be impaired.\n"); 428 sblock.fs_cpc = 0; 429 goto next; 430 } 431 sblock.fs_sbsize = fragroundup(&sblock, totalsbsize); 432 /* 433 * calculate the available blocks for each rotational position 434 */ 435 for (cylno = 0; cylno < sblock.fs_cpc; cylno++) 436 for (rpos = 0; rpos < sblock.fs_nrpos; rpos++) 437 fs_postbl(&sblock, cylno)[rpos] = -1; 438 for (i = (rotblsize - 1) * sblock.fs_frag; 439 i >= 0; i -= sblock.fs_frag) { 440 cylno = cbtocylno(&sblock, i); 441 rpos = cbtorpos(&sblock, i); 442 blk = fragstoblks(&sblock, i); 443 if (fs_postbl(&sblock, cylno)[rpos] == -1) 444 fs_rotbl(&sblock)[blk] = 0; 445 else 446 fs_rotbl(&sblock)[blk] = 447 fs_postbl(&sblock, cylno)[rpos] - blk; 448 fs_postbl(&sblock, cylno)[rpos] = blk; 449 } 450 next: 451 /* 452 * Compute/validate number of cylinder groups. 453 */ 454 sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; 455 if (sblock.fs_ncyl % sblock.fs_cpg) 456 sblock.fs_ncg++; 457 sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock); 458 i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1); 459 if (cgdmin(&sblock, i) - cgbase(&sblock, i) >= sblock.fs_fpg) { 460 printf("inode blocks/cyl group (%d) >= data blocks (%d)\n", 461 cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag, 462 sblock.fs_fpg / sblock.fs_frag); 463 printf("number of cylinders per cylinder group (%d) %s.\n", 464 sblock.fs_cpg, "must be increased"); 465 exit(1); 466 } 467 j = sblock.fs_ncg - 1; 468 if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg && 469 cgdmin(&sblock, j) - cgbase(&sblock, j) > i) { 470 printf("Warning: inode blocks/cyl group (%d) >= data blocks (%d) in last\n", 471 (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag, 472 i / sblock.fs_frag); 473 printf(" cylinder group. This implies %d sector(s) cannot be allocated.\n", 474 i * NSPF(&sblock)); 475 sblock.fs_ncg--; 476 sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg; 477 sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc / 478 NSPF(&sblock); 479 warn = 0; 480 } 481 if (warn) { 482 printf("Warning: %d sector(s) in last cylinder unallocated\n", 483 sblock.fs_spc - 484 (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1) 485 * sblock.fs_spc)); 486 } 487 /* 488 * fill in remaining fields of the super block 489 */ 490 sblock.fs_csaddr = cgdmin(&sblock, 0); 491 sblock.fs_cssize = 492 fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); 493 i = sblock.fs_bsize / sizeof(struct csum); 494 sblock.fs_csmask = ~(i - 1); 495 for (sblock.fs_csshift = 0; i > 1; i >>= 1) 496 sblock.fs_csshift++; 497 fscs = (struct csum *)calloc(1, sblock.fs_cssize); 498 sblock.fs_magic = FS_MAGIC; 499 sblock.fs_rotdelay = rotdelay; 500 sblock.fs_minfree = minfree; 501 sblock.fs_maxcontig = maxcontig; 502 sblock.fs_headswitch = headswitch; 503 sblock.fs_trkseek = trackseek; 504 sblock.fs_maxbpg = maxbpg; 505 sblock.fs_rps = rpm / 60; 506 sblock.fs_optim = opt; 507 sblock.fs_cgrotor = 0; 508 sblock.fs_cstotal.cs_ndir = 0; 509 sblock.fs_cstotal.cs_nbfree = 0; 510 sblock.fs_cstotal.cs_nifree = 0; 511 sblock.fs_cstotal.cs_nffree = 0; 512 sblock.fs_fmod = 0; 513 sblock.fs_ronly = 0; 514 /* 515 * Dump out summary information about file system. 516 */ 517 printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n", 518 fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl, 519 sblock.fs_ntrak, sblock.fs_nsect); 520 printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n", 521 (float)sblock.fs_size * sblock.fs_fsize * 1e-6, sblock.fs_ncg, 522 sblock.fs_cpg, (float)sblock.fs_fpg * sblock.fs_fsize * 1e-6, 523 sblock.fs_ipg); 524 /* 525 * Now build the cylinders group blocks and 526 * then print out indices of cylinder groups. 527 */ 528 printf("super-block backups (for fsck -b #) at:"); 529 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { 530 initcg(cylno); 531 if (cylno % 9 == 0) 532 printf("\n"); 533 printf(" %d,", fsbtodb(&sblock, cgsblock(&sblock, cylno))); 534 } 535 printf("\n"); 536 if (Nflag) 537 exit(0); 538 /* 539 * Now construct the initial file system, 540 * then write out the super-block. 541 */ 542 fsinit(); 543 sblock.fs_time = utime; 544 wtfs(SBOFF / sectorsize, sbsize, (char *)&sblock); 545 for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) 546 wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), 547 sblock.fs_cssize - i < sblock.fs_bsize ? 548 sblock.fs_cssize - i : sblock.fs_bsize, 549 ((char *)fscs) + i); 550 /* 551 * Write out the duplicate super blocks 552 */ 553 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) 554 wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), 555 sbsize, (char *)&sblock); 556 /* 557 * Update information about this partion in pack 558 * label, to that it may be updated on disk. 559 */ 560 pp->p_fstype = FS_BSDFFS; 561 pp->p_fsize = sblock.fs_fsize; 562 pp->p_frag = sblock.fs_frag; 563 pp->p_cpg = sblock.fs_cpg; 564 } 565 566 /* 567 * Initialize a cylinder group. 568 */ 569 initcg(cylno) 570 int cylno; 571 { 572 daddr_t cbase, d, dlower, dupper, dmax; 573 long i, j, s; 574 register struct csum *cs; 575 576 /* 577 * Determine block bounds for cylinder group. 578 * Allow space for super block summary information in first 579 * cylinder group. 580 */ 581 cbase = cgbase(&sblock, cylno); 582 dmax = cbase + sblock.fs_fpg; 583 if (dmax > sblock.fs_size) 584 dmax = sblock.fs_size; 585 dlower = cgsblock(&sblock, cylno) - cbase; 586 dupper = cgdmin(&sblock, cylno) - cbase; 587 if (cylno == 0) 588 dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); 589 cs = fscs + cylno; 590 acg.cg_time = utime; 591 acg.cg_magic = CG_MAGIC; 592 acg.cg_cgx = cylno; 593 if (cylno == sblock.fs_ncg - 1) 594 acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; 595 else 596 acg.cg_ncyl = sblock.fs_cpg; 597 acg.cg_niblk = sblock.fs_ipg; 598 acg.cg_ndblk = dmax - cbase; 599 acg.cg_cs.cs_ndir = 0; 600 acg.cg_cs.cs_nffree = 0; 601 acg.cg_cs.cs_nbfree = 0; 602 acg.cg_cs.cs_nifree = 0; 603 acg.cg_rotor = 0; 604 acg.cg_frotor = 0; 605 acg.cg_irotor = 0; 606 acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_link); 607 acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(long); 608 acg.cg_iusedoff = acg.cg_boff + 609 sblock.fs_cpg * sblock.fs_nrpos * sizeof(short); 610 acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY); 611 acg.cg_nextfreeoff = acg.cg_freeoff + 612 howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY); 613 for (i = 0; i < sblock.fs_frag; i++) { 614 acg.cg_frsum[i] = 0; 615 } 616 bzero((caddr_t)cg_inosused(&acg), acg.cg_freeoff - acg.cg_iusedoff); 617 acg.cg_cs.cs_nifree += sblock.fs_ipg; 618 if (cylno == 0) 619 for (i = 0; i < ROOTINO; i++) { 620 setbit(cg_inosused(&acg), i); 621 acg.cg_cs.cs_nifree--; 622 } 623 for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) 624 wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), 625 sblock.fs_bsize, (char *)zino); 626 bzero((caddr_t)cg_blktot(&acg), acg.cg_boff - acg.cg_btotoff); 627 bzero((caddr_t)cg_blks(&sblock, &acg, 0), 628 acg.cg_iusedoff - acg.cg_boff); 629 bzero((caddr_t)cg_blksfree(&acg), acg.cg_nextfreeoff - acg.cg_freeoff); 630 if (cylno > 0) { 631 /* 632 * In cylno 0, beginning space is reserved 633 * for boot and super blocks. 634 */ 635 for (d = 0; d < dlower; d += sblock.fs_frag) { 636 setblock(&sblock, cg_blksfree(&acg), d/sblock.fs_frag); 637 acg.cg_cs.cs_nbfree++; 638 cg_blktot(&acg)[cbtocylno(&sblock, d)]++; 639 cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) 640 [cbtorpos(&sblock, d)]++; 641 } 642 sblock.fs_dsize += dlower; 643 } 644 sblock.fs_dsize += acg.cg_ndblk - dupper; 645 if (i = dupper % sblock.fs_frag) { 646 acg.cg_frsum[sblock.fs_frag - i]++; 647 for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) { 648 setbit(cg_blksfree(&acg), dupper); 649 acg.cg_cs.cs_nffree++; 650 } 651 } 652 for (d = dupper; d + sblock.fs_frag <= dmax - cbase; ) { 653 setblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag); 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 d += sblock.fs_frag; 659 } 660 if (d < dmax - cbase) { 661 acg.cg_frsum[dmax - cbase - d]++; 662 for (; d < dmax - cbase; d++) { 663 setbit(cg_blksfree(&acg), d); 664 acg.cg_cs.cs_nffree++; 665 } 666 } 667 sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; 668 sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; 669 sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; 670 sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; 671 *cs = acg.cg_cs; 672 wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), 673 sblock.fs_bsize, (char *)&acg); 674 } 675 676 /* 677 * initialize the file system 678 */ 679 struct inode node; 680 681 #ifdef LOSTDIR 682 #define PREDEFDIR 3 683 #else 684 #define PREDEFDIR 2 685 #endif 686 687 struct direct root_dir[] = { 688 { ROOTINO, sizeof(struct direct), 1, "." }, 689 { ROOTINO, sizeof(struct direct), 2, ".." }, 690 #ifdef LOSTDIR 691 { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" }, 692 #endif 693 }; 694 #ifdef LOSTDIR 695 struct direct lost_found_dir[] = { 696 { LOSTFOUNDINO, sizeof(struct direct), 1, "." }, 697 { ROOTINO, sizeof(struct direct), 2, ".." }, 698 { 0, DIRBLKSIZ, 0, 0 }, 699 }; 700 #endif 701 char buf[MAXBSIZE]; 702 703 fsinit() 704 { 705 int i; 706 707 /* 708 * initialize the node 709 */ 710 node.i_atime = utime; 711 node.i_mtime = utime; 712 node.i_ctime = utime; 713 #ifdef LOSTDIR 714 /* 715 * create the lost+found directory 716 */ 717 (void)makedir(lost_found_dir, 2); 718 for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) 719 bcopy(&lost_found_dir[2], &buf[i], DIRSIZ(&lost_found_dir[2])); 720 node.i_number = LOSTFOUNDINO; 721 node.i_mode = IFDIR | UMASK; 722 node.i_nlink = 2; 723 node.i_size = sblock.fs_bsize; 724 node.i_db[0] = alloc(node.i_size, node.i_mode); 725 node.i_blocks = btodb(fragroundup(&sblock, node.i_size)); 726 wtfs(fsbtodb(&sblock, node.i_db[0]), node.i_size, buf); 727 iput(&node); 728 #endif 729 /* 730 * create the root directory 731 */ 732 node.i_number = ROOTINO; 733 node.i_mode = IFDIR | UMASK; 734 node.i_nlink = PREDEFDIR; 735 node.i_size = makedir(root_dir, PREDEFDIR); 736 node.i_db[0] = alloc(sblock.fs_fsize, node.i_mode); 737 node.i_blocks = btodb(fragroundup(&sblock, node.i_size)); 738 wtfs(fsbtodb(&sblock, node.i_db[0]), sblock.fs_fsize, buf); 739 iput(&node); 740 } 741 742 /* 743 * construct a set of directory entries in "buf". 744 * return size of directory. 745 */ 746 makedir(protodir, entries) 747 register struct direct *protodir; 748 int entries; 749 { 750 char *cp; 751 int i, spcleft; 752 753 spcleft = DIRBLKSIZ; 754 for (cp = buf, i = 0; i < entries - 1; i++) { 755 protodir[i].d_reclen = DIRSIZ(&protodir[i]); 756 bcopy(&protodir[i], cp, protodir[i].d_reclen); 757 cp += protodir[i].d_reclen; 758 spcleft -= protodir[i].d_reclen; 759 } 760 protodir[i].d_reclen = spcleft; 761 bcopy(&protodir[i], cp, DIRSIZ(&protodir[i])); 762 return (DIRBLKSIZ); 763 } 764 765 /* 766 * allocate a block or frag 767 */ 768 daddr_t 769 alloc(size, mode) 770 int size; 771 int mode; 772 { 773 int i, frag; 774 daddr_t d; 775 776 rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 777 (char *)&acg); 778 if (acg.cg_magic != CG_MAGIC) { 779 printf("cg 0: bad magic number\n"); 780 return (0); 781 } 782 if (acg.cg_cs.cs_nbfree == 0) { 783 printf("first cylinder group ran out of space\n"); 784 return (0); 785 } 786 for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) 787 if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag)) 788 goto goth; 789 printf("internal error: can't find block in cyl 0\n"); 790 return (0); 791 goth: 792 clrblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag); 793 acg.cg_cs.cs_nbfree--; 794 sblock.fs_cstotal.cs_nbfree--; 795 fscs[0].cs_nbfree--; 796 if (mode & IFDIR) { 797 acg.cg_cs.cs_ndir++; 798 sblock.fs_cstotal.cs_ndir++; 799 fscs[0].cs_ndir++; 800 } 801 cg_blktot(&acg)[cbtocylno(&sblock, d)]--; 802 cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--; 803 if (size != sblock.fs_bsize) { 804 frag = howmany(size, sblock.fs_fsize); 805 fscs[0].cs_nffree += sblock.fs_frag - frag; 806 sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; 807 acg.cg_cs.cs_nffree += sblock.fs_frag - frag; 808 acg.cg_frsum[sblock.fs_frag - frag]++; 809 for (i = frag; i < sblock.fs_frag; i++) 810 setbit(cg_blksfree(&acg), d + i); 811 } 812 wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 813 (char *)&acg); 814 return (d); 815 } 816 817 /* 818 * Allocate an inode on the disk 819 */ 820 iput(ip) 821 register struct inode *ip; 822 { 823 struct dinode buf[MAXINOPB]; 824 daddr_t d; 825 int c; 826 827 c = itog(&sblock, ip->i_number); 828 rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 829 (char *)&acg); 830 if (acg.cg_magic != CG_MAGIC) { 831 printf("cg 0: bad magic number\n"); 832 exit(1); 833 } 834 acg.cg_cs.cs_nifree--; 835 setbit(cg_inosused(&acg), ip->i_number); 836 wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 837 (char *)&acg); 838 sblock.fs_cstotal.cs_nifree--; 839 fscs[0].cs_nifree--; 840 if (ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) { 841 printf("fsinit: inode value out of range (%d).\n", 842 ip->i_number); 843 exit(1); 844 } 845 d = fsbtodb(&sblock, itod(&sblock, ip->i_number)); 846 rdfs(d, sblock.fs_bsize, buf); 847 buf[itoo(&sblock, ip->i_number)].di_ic = ip->i_ic; 848 wtfs(d, sblock.fs_bsize, buf); 849 } 850 851 /* 852 * read a block from the file system 853 */ 854 rdfs(bno, size, bf) 855 daddr_t bno; 856 int size; 857 char *bf; 858 { 859 int n; 860 861 if (lseek(fsi, bno * sectorsize, 0) < 0) { 862 printf("seek error: %ld\n", bno); 863 perror("rdfs"); 864 exit(1); 865 } 866 n = read(fsi, bf, size); 867 if(n != size) { 868 printf("read error: %ld\n", bno); 869 perror("rdfs"); 870 exit(1); 871 } 872 } 873 874 /* 875 * write a block to the file system 876 */ 877 wtfs(bno, size, bf) 878 daddr_t bno; 879 int size; 880 char *bf; 881 { 882 int n; 883 884 if (Nflag) 885 return; 886 if (lseek(fso, bno * sectorsize, 0) < 0) { 887 printf("seek error: %ld\n", bno); 888 perror("wtfs"); 889 exit(1); 890 } 891 n = write(fso, bf, size); 892 if(n != size) { 893 printf("write error: %ld\n", bno); 894 perror("wtfs"); 895 exit(1); 896 } 897 } 898 899 /* 900 * check if a block is available 901 */ 902 isblock(fs, cp, h) 903 struct fs *fs; 904 unsigned char *cp; 905 int h; 906 { 907 unsigned char mask; 908 909 switch (fs->fs_frag) { 910 case 8: 911 return (cp[h] == 0xff); 912 case 4: 913 mask = 0x0f << ((h & 0x1) << 2); 914 return ((cp[h >> 1] & mask) == mask); 915 case 2: 916 mask = 0x03 << ((h & 0x3) << 1); 917 return ((cp[h >> 2] & mask) == mask); 918 case 1: 919 mask = 0x01 << (h & 0x7); 920 return ((cp[h >> 3] & mask) == mask); 921 default: 922 #ifdef STANDALONE 923 printf("isblock bad fs_frag %d\n", fs->fs_frag); 924 #else 925 fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 926 #endif 927 return (0); 928 } 929 } 930 931 /* 932 * take a block out of the map 933 */ 934 clrblock(fs, cp, h) 935 struct fs *fs; 936 unsigned char *cp; 937 int h; 938 { 939 switch ((fs)->fs_frag) { 940 case 8: 941 cp[h] = 0; 942 return; 943 case 4: 944 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 945 return; 946 case 2: 947 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 948 return; 949 case 1: 950 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 951 return; 952 default: 953 #ifdef STANDALONE 954 printf("clrblock bad fs_frag %d\n", fs->fs_frag); 955 #else 956 fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag); 957 #endif 958 return; 959 } 960 } 961 962 /* 963 * put a block into the map 964 */ 965 setblock(fs, cp, h) 966 struct fs *fs; 967 unsigned char *cp; 968 int h; 969 { 970 switch (fs->fs_frag) { 971 case 8: 972 cp[h] = 0xff; 973 return; 974 case 4: 975 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 976 return; 977 case 2: 978 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 979 return; 980 case 1: 981 cp[h >> 3] |= (0x01 << (h & 0x7)); 982 return; 983 default: 984 #ifdef STANDALONE 985 printf("setblock bad fs_frag %d\n", fs->fs_frag); 986 #else 987 fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); 988 #endif 989 return; 990 } 991 } 992