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