fix rotational layout code to work with disks with nsect % bsize != 0
authorKirk McKusick <mckusic@ucbvax.Berkeley.EDU>
Mon, 11 Jan 1982 10:25:14 +0000 (02:25 -0800)
committerKirk McKusick <mckusic@ucbvax.Berkeley.EDU>
Mon, 11 Jan 1982 10:25:14 +0000 (02:25 -0800)
SCCS-vsn: sys/ufs/ffs/fs.h 1.11
SCCS-vsn: sys/ufs/ffs/ffs_alloc.c 1.13
SCCS-vsn: sys/ufs/lfs/lfs_alloc.c 1.13
SCCS-vsn: sbin/newfs/mkfs.c 1.13
SCCS-vsn: sbin/fsck/main.c 1.17
SCCS-vsn: sbin/icheck/icheck.c 1.13
SCCS-vsn: sbin/dumpfs/dumpfs.c 1.8

usr/src/sbin/dumpfs/dumpfs.c
usr/src/sbin/fsck/main.c
usr/src/sbin/icheck/icheck.c
usr/src/sbin/newfs/mkfs.c
usr/src/sys/ufs/ffs/ffs_alloc.c
usr/src/sys/ufs/ffs/fs.h
usr/src/sys/ufs/lfs/lfs_alloc.c

index 2470ae5..431e45d 100644 (file)
@@ -1,4 +1,4 @@
-static char *sccsid = "@(#)dumpfs.c    1.7 (Berkeley) %G%";
+static char *sccsid = "@(#)dumpfs.c    1.8 (Berkeley) %G%";
 
 #include "../h/param.h"
 #include "../h/fs.h"
 
 #include "../h/param.h"
 #include "../h/fs.h"
@@ -23,7 +23,7 @@ union {
 main(argc, argv)
        char **argv;
 {
 main(argc, argv)
        char **argv;
 {
-       int i, j, k;
+       int c, i, j, k;
 
        close(0);
        if (open(argv[1], 0) != 0)
 
        close(0);
        if (open(argv[1], 0) != 0)
@@ -32,7 +32,11 @@ main(argc, argv)
        if (read(0, &afs, SBSIZE) != SBSIZE)
                perror(argv[1]), exit(1);
        printf("magic\t%x\n", afs.fs_magic);
        if (read(0, &afs, SBSIZE) != SBSIZE)
                perror(argv[1]), exit(1);
        printf("magic\t%x\n", afs.fs_magic);
+       printf("bblkno\t%d\n", afs.fs_bblkno);
        printf("sblkno\t%d\n", afs.fs_sblkno);
        printf("sblkno\t%d\n", afs.fs_sblkno);
+       printf("cblkno\t%d\n", afs.fs_cblkno);
+       printf("iblkno\t%d\n", afs.fs_iblkno);
+       printf("dblkno\t%d\n", afs.fs_dblkno);
        printf("time\t%s", ctime(&afs.fs_time));
        printf("size\t%d\n", afs.fs_size);
        printf("blocks\t%d\n", afs.fs_dsize);
        printf("time\t%s", ctime(&afs.fs_time));
        printf("size\t%d\n", afs.fs_size);
        printf("blocks\t%d\n", afs.fs_dsize);
@@ -42,6 +46,7 @@ main(argc, argv)
        printf("frag\t%d\n", afs.fs_frag);
        printf("minfree\t%d%%\n", afs.fs_minfree);
        printf("rotdelay %dms\n", afs.fs_rotdelay);
        printf("frag\t%d\n", afs.fs_frag);
        printf("minfree\t%d%%\n", afs.fs_minfree);
        printf("rotdelay %dms\n", afs.fs_rotdelay);
+       printf("rps\t%d\n", afs.fs_rps);
        printf("csaddr\t%d\n", afs.fs_csaddr);
        printf("cssize\t%d\n", afs.fs_cssize);
        printf("cgsize\t%d\n", afs.fs_cgsize);
        printf("csaddr\t%d\n", afs.fs_csaddr);
        printf("cssize\t%d\n", afs.fs_cssize);
        printf("cgsize\t%d\n", afs.fs_cgsize);
@@ -54,15 +59,24 @@ main(argc, argv)
            afs.fs_cstotal.cs_nbfree, afs.fs_cstotal.cs_nifree);
        printf("cgrotor\t%d\nfmod\t%d\nronly\t%d\n",
            afs.fs_cgrotor, afs.fs_fmod, afs.fs_ronly);
            afs.fs_cstotal.cs_nbfree, afs.fs_cstotal.cs_nifree);
        printf("cgrotor\t%d\nfmod\t%d\nronly\t%d\n",
            afs.fs_cgrotor, afs.fs_fmod, afs.fs_ronly);
-       printf("blocks available in each rotational position");
-       for (i = 0; i < NRPOS; i++) {
-               if (afs.fs_postbl[i] > -1)
-                       printf("\nposition %d:\t", i);
-               for (j = afs.fs_postbl[i], k = 1; j > -1;
-                    j = afs.fs_rotbl[j], k++) {
-                       if (k % 15 == 0)
-                               printf("\n\t\t");
-                       printf("%4d", j);
+       if (afs.fs_cpc != 0)
+               printf("blocks available in each rotational position");
+       else
+               printf("insufficient space to maintain rotational tables\n");
+       for (c = 0; c < afs.fs_cpc; c++) {
+               printf("\ncylinder number %d:", c);
+               for (i = 0; i < NRPOS; i++) {
+                       if (afs.fs_postbl[c][i] == -1)
+                               continue;
+                       printf("\n   position %d:\t", i);
+                       for (j = afs.fs_postbl[c][i], k = 1; ;
+                            j += afs.fs_rotbl[j], k++) {
+                               printf("%5d", j);
+                               if (k % 12 == 0)
+                                       printf("\n\t\t");
+                               if (afs.fs_rotbl[j] == 0)
+                                       break;
+                       }
                }
        }
        printf("\ncs[].cs_(nbfree,ndir,nifree,nffree):\n\t");
                }
        }
        printf("\ncs[].cs_(nbfree,ndir,nifree,nffree):\n\t");
index 7430768..f3be519 100644 (file)
@@ -1,4 +1,4 @@
-static char *sccsid = "@(#)main.c      1.16 (Berkeley) %G%";
+static char *sccsid = "@(#)main.c      1.17 (Berkeley) %G%";
 
 #include <stdio.h>
 #include <ctype.h>
 
 #include <stdio.h>
 #include <ctype.h>
@@ -597,9 +597,8 @@ out1b:
                                /* this is clumsy ... */
                                n_ffree -= sblock.fs_frag;
                                n_bfree++;
                                /* this is clumsy ... */
                                n_ffree -= sblock.fs_frag;
                                n_bfree++;
-                               s = b * NSPF(&sblock);
-                               bo[s/sblock.fs_spc]
-                                   [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++;
+                               bo[cbtocylno(&sblock, b)]
+                                   [cbtorpos(&sblock, b)]++;
                        } else {
                                for (d = 0; d < sblock.fs_frag; d++)
                                        if (isset(cgrp.cg_free, b+d))
                        } else {
                                for (d = 0; d < sblock.fs_frag; d++)
                                        if (isset(cgrp.cg_free, b+d))
@@ -1197,6 +1196,9 @@ setup(dev)
                return (0);
        sblk.b_bno = super;
        sblk.b_size = SBSIZE;
                return (0);
        sblk.b_bno = super;
        sblk.b_size = SBSIZE;
+       /*
+        * run a few consistency checks of the super block
+        */
        if (sblock.fs_magic != FS_MAGIC)
                { badsb("MAGIC NUMBER WRONG"); return (0); }
        if (sblock.fs_ncg < 1)
        if (sblock.fs_magic != FS_MAGIC)
                { badsb("MAGIC NUMBER WRONG"); return (0); }
        if (sblock.fs_ncg < 1)
@@ -1207,28 +1209,33 @@ setup(dev)
                { badsb("NSECT < 1"); return (0); }
        if (sblock.fs_ntrak < 1)
                { badsb("NTRAK < 1"); return (0); }
                { badsb("NSECT < 1"); return (0); }
        if (sblock.fs_ntrak < 1)
                { badsb("NTRAK < 1"); return (0); }
-       if (sblock.fs_ipg*sblock.fs_ncg > 65535 || sblock.fs_ipg%INOPB(&sblock))
-               { badsb("TOO MANY INODES IMPLIED"); return (0); }
-       if (sblock.fs_ipg/INOPF(&sblock)+IBLOCK(&sblock) >=
-           sblock.fs_cpg*sblock.fs_nsect*sblock.fs_ntrak/NSPF(&sblock))
+       if (sblock.fs_spc != sblock.fs_nsect * sblock.fs_ntrak)
+               { badsb("SPC DOES NOT JIVE w/NTRAK*NSECT"); return (0); }
+       if (sblock.fs_ipg % INOPB(&sblock))
+               { badsb("INODES NOT MULTIPLE OF A BLOCK"); return (0); }
+       if (cgdmin(0, &sblock) >= sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock))
                { badsb("IMPLIES MORE INODE THAN DATA BLOCKS"); return (0); }
                { badsb("IMPLIES MORE INODE THAN DATA BLOCKS"); return (0); }
-/* THE FOLLOWING COULD BE CHECKED MORE CLOSELY... */
-       if ((sblock.fs_ncg + 1) * sblock.fs_cpg < sblock.fs_ncyl ||
-           (sblock.fs_ncg - 1) * sblock.fs_cpg > sblock.fs_ncyl)
+       if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl ||
+           (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl)
                { badsb("NCYL DOES NOT JIVE WITH NCG*CPG"); return (0); }
        if (sblock.fs_fpg != sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock))
                { badsb("FPG DOES NOT JIVE WITH CPG & SPC"); return (0); }
                { badsb("NCYL DOES NOT JIVE WITH NCG*CPG"); return (0); }
        if (sblock.fs_fpg != sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock))
                { badsb("FPG DOES NOT JIVE WITH CPG & SPC"); return (0); }
-       if (sblock.fs_size <=
-           (sblock.fs_ncg-1)*sblock.fs_fpg+IBLOCK(&sblock)+sblock.fs_ipg/INOPF(&sblock))
+       if (sblock.fs_size * NSPF(&sblock) <=
+           (sblock.fs_ncyl - 1) * sblock.fs_spc)
                { badsb("SIZE PREPOSTEROUSLY SMALL"); return (0); }
                { badsb("SIZE PREPOSTEROUSLY SMALL"); return (0); }
-       if (sblock.fs_size*NSPF(&sblock) >
-           (sblock.fs_ncg+2)*sblock.fs_cpg*sblock.fs_spc)
+       if (sblock.fs_size * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc)
                { badsb("SIZE PREPOSTEROUSLY LARGE"); return (0); }
        /* rest we COULD repair... */
        if (sblock.fs_sblkno != SBLOCK)
                { badsb("SIZE PREPOSTEROUSLY LARGE"); return (0); }
        /* rest we COULD repair... */
        if (sblock.fs_sblkno != SBLOCK)
-               { badsb("BLKNO CORRUPTED"); return (0); }
-       if (sblock.fs_spc != sblock.fs_nsect * sblock.fs_ntrak)
-               { badsb("SPC DOES NOT JIVE w/NTRAK*NSECT"); return (0); }
+               { badsb("SBLKNO CORRUPTED"); return (0); }
+       if (sblock.fs_cblkno !=
+           roundup(howmany(BBSIZE + SBSIZE, sblock.fs_fsize), sblock.fs_frag))
+               { badsb("CBLKNO CORRUPTED"); return (0); }
+       if (sblock.fs_iblkno != sblock.fs_cblkno + sblock.fs_frag)
+               { badsb("IBLKNO CORRUPTED"); return (0); }
+       if (sblock.fs_dblkno != 
+           sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock))
+               { badsb("DBLKNO CORRUPTED"); return (0); }
        if (sblock.fs_cgsize !=
            roundup(sizeof(struct cg) + howmany(sblock.fs_fpg, NBBY),
            sblock.fs_fsize))
        if (sblock.fs_cgsize !=
            roundup(sizeof(struct cg) + howmany(sblock.fs_fpg, NBBY),
            sblock.fs_fsize))
@@ -1237,7 +1244,9 @@ setup(dev)
                { badsb("CSSIZE INCORRECT"); return (0); }
        fmax = sblock.fs_size;
        imax = sblock.fs_ncg * sblock.fs_ipg;
                { badsb("CSSIZE INCORRECT"); return (0); }
        fmax = sblock.fs_size;
        imax = sblock.fs_ncg * sblock.fs_ipg;
-
+       /*
+        * allocate the necessary maps
+        */
        bmapsz = roundup(howmany(fmax, NBBY), sizeof(short));
        blkmap = (char *)calloc(bmapsz, sizeof (char));
        freemap = (char *)calloc(bmapsz, sizeof (char));
        bmapsz = roundup(howmany(fmax, NBBY), sizeof(short));
        blkmap = (char *)calloc(bmapsz, sizeof (char));
        freemap = (char *)calloc(bmapsz, sizeof (char));
@@ -1515,9 +1524,8 @@ makecg()
                        }
                        if (j == sblock.fs_frag) {
                                cgrp.cg_cs.cs_nbfree++;
                        }
                        if (j == sblock.fs_frag) {
                                cgrp.cg_cs.cs_nbfree++;
-                               s = d * NSPF(&sblock);
-                               cgrp.cg_b[s/sblock.fs_spc]
-                                 [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++;
+                               cgrp.cg_b[cbtocylno(&sblock, d)]
+                                   [cbtorpos(&sblock, d)]++;
                        } else if (j > 0) {
                                cgrp.cg_cs.cs_nffree += j;
                                blk = ((cgrp.cg_free[d / NBBY] >> (d % NBBY)) &
                        } else if (j > 0) {
                                cgrp.cg_cs.cs_nffree += j;
                                blk = ((cgrp.cg_free[d / NBBY] >> (d % NBBY)) &
index 5ba5e33..8bae8b2 100644 (file)
@@ -1,4 +1,4 @@
-static char *sccsid = "@(#)icheck.c    1.12 (Berkeley) %G%";
+static char *sccsid = "@(#)icheck.c    1.13 (Berkeley) %G%";
 
 /*
  * icheck
 
 /*
  * icheck
@@ -485,9 +485,8 @@ makecg()
                        }
                        if (j == sblock.fs_frag) {
                                cgrp.cg_cs.cs_nbfree++;
                        }
                        if (j == sblock.fs_frag) {
                                cgrp.cg_cs.cs_nbfree++;
-                               s = d * NSPF(&sblock);
-                               cgrp.cg_b[s/sblock.fs_spc]
-                                 [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++;
+                               cgrp.cg_b[cbtocylno(&sblock, d)]
+                                   [cbtorpos(&sblock, d)]++;
                        } else if (j > 0) {
                                cgrp.cg_cs.cs_nffree += j;
                                blk = ((cgrp.cg_free[d / NBBY] >> (d % NBBY)) &
                        } else if (j > 0) {
                                cgrp.cg_cs.cs_nffree += j;
                                blk = ((cgrp.cg_free[d / NBBY] >> (d % NBBY)) &
index 4198999..28c8f11 100644 (file)
@@ -1,4 +1,4 @@
-static char *sccsid = "@(#)mkfs.c      1.12 (Berkeley) %G%";
+static char *sccsid = "@(#)mkfs.c      1.13 (Berkeley) %G%";
 
 /*
  * make file system for cylinder-group style file systems
 
 /*
  * make file system for cylinder-group style file systems
@@ -46,7 +46,7 @@ main(argc, argv)
        int argc;
        char *argv[];
 {
        int argc;
        char *argv[];
 {
-       long c, i, inos, fssize;
+       long cylno, rpos, blk, i, inos, fssize;
 
 #ifndef STANDALONE
        argc--, argv++;
 
 #ifndef STANDALONE
        argc--, argv++;
@@ -145,6 +145,11 @@ main(argc, argv)
                    sblock.fs_bsize / MAXFRAG);
                exit(1);
        }
                    sblock.fs_bsize / MAXFRAG);
                exit(1);
        }
+       sblock.fs_bblkno = BBLOCK;
+       sblock.fs_sblkno = SBLOCK;
+       sblock.fs_cblkno = (daddr_t)
+           roundup(howmany(BBSIZE + SBSIZE, sblock.fs_fsize), sblock.fs_frag);
+       sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag;
        /* 
         * collect and verify the number of cylinders per group
         */
        /* 
         * collect and verify the number of cylinders per group
         */
@@ -174,15 +179,58 @@ main(argc, argv)
         */
        sblock.fs_size = fssize = dbtofsb(&sblock, fssize);
        sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc;
         */
        sblock.fs_size = fssize = dbtofsb(&sblock, fssize);
        sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc;
-       if (sblock.fs_spc > MAXBPC * NSPB(&sblock)) {
-               printf("too many sectors per cylinder (%d sectors)\n",
-                   sblock.fs_spc);
-               while (sblock.fs_spc > MAXBPC * NSPB(&sblock))
-                       sblock.fs_bsize <<= 1;
-               printf("nsect %d, and ntrak %d, requires block size of %d\n",
-                   sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_bsize);
+       if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) {
+               printf("Warning: %d sector(s) in last cylinder unallocated\n",
+                   sblock.fs_spc -
+                   (fssize * NSPF(&sblock) - sblock.fs_ncyl * sblock.fs_spc));
+               sblock.fs_ncyl++;
+       }
+       if (sblock.fs_ncyl < 1) {
+               printf("file systems must have at least one cylinder\n");
                exit(1);
        }
                exit(1);
        }
+       /*
+        * determine feasability/values of rotational layout tables
+        */
+       if (sblock.fs_ntrak == 1) {
+               sblock.fs_cpc = 0;
+               goto next;
+       }
+       for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc;
+            sblock.fs_cpc > 1 && (i & 1) == 0;
+            sblock.fs_cpc >>= 1, i >>= 1)
+               /* void */;
+       if (sblock.fs_spc * sblock.fs_cpc > MAXBPC * NSPB(&sblock) ||
+           sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) {
+               printf("%s %s %d %s %d.%s",
+                   "Warning: insufficient space in super block for\n",
+                   "rotational layout tables with nsect", sblock.fs_nsect,
+                   "and ntrak", sblock.fs_ntrak,
+                   "\nFile system performance may be impared.\n");
+               sblock.fs_cpc = 0;
+               goto next;
+       }
+       /*
+        * calculate the available blocks for each rotational position
+        */
+       for (cylno = 0; cylno < MAXCPG; cylno++)
+               for (rpos = 0; rpos < NRPOS; rpos++)
+                       sblock.fs_postbl[cylno][rpos] = -1;
+       blk = sblock.fs_spc * sblock.fs_cpc / NSPF(&sblock);
+       for (i = 0; i < blk; i += sblock.fs_frag)
+               /* void */;
+       for (i -= sblock.fs_frag; i >= 0; i -= sblock.fs_frag) {
+               cylno = cbtocylno(&sblock, i);
+               rpos = cbtorpos(&sblock, i);
+               blk = i / sblock.fs_frag;
+               if (sblock.fs_postbl[cylno][rpos] == -1)
+                       sblock.fs_rotbl[blk] = 0;
+               else
+                       sblock.fs_rotbl[blk] =
+                           sblock.fs_postbl[cylno][rpos] - blk;
+               sblock.fs_postbl[cylno][rpos] = blk;
+       }
+next:
        /*
         * Validate specified/determined cpg.
         */
        /*
         * Validate specified/determined cpg.
         */
@@ -204,7 +252,7 @@ main(argc, argv)
        if (sblock.fs_fpg > MAXBPG(&sblock) * sblock.fs_frag) {
                printf("cylinder group too large (%d cylinders); ",
                    sblock.fs_cpg);
        if (sblock.fs_fpg > MAXBPG(&sblock) * sblock.fs_frag) {
                printf("cylinder group too large (%d cylinders); ",
                    sblock.fs_cpg);
-               printf("max: %d cylinders\n",
+               printf("max: %d cylinders per group\n",
                    MAXBPG(&sblock) * sblock.fs_frag /
                    (sblock.fs_fpg / sblock.fs_cpg));
                exit(1);
                    MAXBPG(&sblock) * sblock.fs_frag /
                    (sblock.fs_fpg / sblock.fs_cpg));
                exit(1);
@@ -214,10 +262,6 @@ main(argc, argv)
        /*
         * Compute/validate number of cylinder groups.
         */
        /*
         * Compute/validate number of cylinder groups.
         */
-       if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) {
-               printf("%d sector(s) in last cylinder unused\n",
-                   fssize * NSPF(&sblock) - sblock.fs_ncyl * sblock.fs_spc);
-       }
        sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
        if (sblock.fs_ncyl % sblock.fs_cpg)
                sblock.fs_ncg++;
        sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
        if (sblock.fs_ncyl % sblock.fs_cpg)
                sblock.fs_ncg++;
@@ -228,20 +272,19 @@ main(argc, argv)
                printf("is not a multiple of %d; choke!\n", sblock.fs_fsize);
                exit(1);
        }
                printf("is not a multiple of %d; choke!\n", sblock.fs_fsize);
                exit(1);
        }
-       fscs = (struct csum *)
-           calloc(1, roundup(sblock.fs_ncg * sizeof (struct csum),
-               sblock.fs_bsize));
        /*
         * Compute number of inode blocks per cylinder group.
         * Start with one inode per NBPI bytes; adjust as necessary.
         */
        /*
         * Compute number of inode blocks per cylinder group.
         * Start with one inode per NBPI bytes; adjust as necessary.
         */
-       inos = ((fssize * sblock.fs_fsize) / MAX(NBPI, sblock.fs_fsize)) /
-           INOPB(&sblock);
+       i = sblock.fs_iblkno + MAXIPG / INOPF(&sblock);
+       inos = (fssize - sblock.fs_ncg * i) * sblock.fs_fsize /
+           MAX(NBPI, sblock.fs_fsize) / INOPB(&sblock);
        if (inos <= 0)
                inos = 1;
        sblock.fs_ipg = ((inos / sblock.fs_ncg) + 1) * INOPB(&sblock);
        if (sblock.fs_ipg > MAXIPG)
                sblock.fs_ipg = MAXIPG;
        if (inos <= 0)
                inos = 1;
        sblock.fs_ipg = ((inos / sblock.fs_ncg) + 1) * INOPB(&sblock);
        if (sblock.fs_ipg > MAXIPG)
                sblock.fs_ipg = MAXIPG;
+       sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock);
        if (cgdmin(0,&sblock) >= sblock.fs_fpg) {
                printf("inode blocks/cyl group (%d) >= data blocks (%d)\n",
                    cgdmin(0,&sblock) / sblock.fs_frag,
        if (cgdmin(0,&sblock) >= sblock.fs_fpg) {
                printf("inode blocks/cyl group (%d) >= data blocks (%d)\n",
                    cgdmin(0,&sblock) / sblock.fs_frag,
@@ -249,27 +292,17 @@ main(argc, argv)
                printf("number of cylinder per cylinder group must be increased\n");
                exit(1);
        }
                printf("number of cylinder per cylinder group must be increased\n");
                exit(1);
        }
-       /*
-        * calculate the available blocks for each rotational position
-        */
-       for (i = 0; i < NRPOS; i++)
-               sblock.fs_postbl[i] = -1;
-       for (i = 0; i < sblock.fs_spc; i += NSPB(&sblock))
-               /* void */;
-       for (i -= NSPB(&sblock); i >= 0; i -= NSPB(&sblock)) {
-               c = i % sblock.fs_nsect * NRPOS / sblock.fs_nsect;
-               sblock.fs_rotbl[i / NSPB(&sblock)] = sblock.fs_postbl[c];
-               sblock.fs_postbl[c] = i / NSPB(&sblock);
-       }
        /*
         * fill in remaining fields of the super block
         */
        sblock.fs_csaddr = cgdmin(0, &sblock);
        sblock.fs_cssize = sblock.fs_ncg * sizeof(struct csum);
        /*
         * fill in remaining fields of the super block
         */
        sblock.fs_csaddr = cgdmin(0, &sblock);
        sblock.fs_cssize = sblock.fs_ncg * sizeof(struct csum);
+       fscs = (struct csum *)
+           calloc(1, roundup(sblock.fs_cssize, sblock.fs_bsize));
+       sblock.fs_magic = FS_MAGIC;
        sblock.fs_rotdelay = ROTDELAY;
        sblock.fs_minfree = MINFREE;
        sblock.fs_rotdelay = ROTDELAY;
        sblock.fs_minfree = MINFREE;
-       sblock.fs_magic = FS_MAGIC;
-       sblock.fs_sblkno = SBLOCK;
+       sblock.fs_rps = HZ;     /* assume disk speed == HZ */
        sblock.fs_cgrotor = 0;
        sblock.fs_cstotal.cs_ndir = 0;
        sblock.fs_cstotal.cs_nbfree = 0;
        sblock.fs_cgrotor = 0;
        sblock.fs_cstotal.cs_ndir = 0;
        sblock.fs_cstotal.cs_nbfree = 0;
@@ -291,15 +324,14 @@ main(argc, argv)
         * Now build the cylinders group blocks and
         * then print out indices of cylinder groups.
         */
         * Now build the cylinders group blocks and
         * then print out indices of cylinder groups.
         */
-       for (c = 0; c < sblock.fs_ncg; c++)
-               initcg(c);
+       for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
+               initcg(cylno);
        if (sblock.fs_ncg == 1)
        if (sblock.fs_ncg == 1)
-               printf("Warning, no super-block backups with only one cylinder group\n");
+               printf("Warning: no super-block backups with only one cylinder group\n");
        else
                printf("\tsuper-block backups (for fsck -b#) at %d+k*%d (%d .. %d)\n",
        else
                printf("\tsuper-block backups (for fsck -b#) at %d+k*%d (%d .. %d)\n",
-                   SBLOCK, fsbtodb(&sblock, cgsblock(1, &sblock)) - SBLOCK,
-                   fsbtodb(&sblock, cgsblock(1, &sblock)),
-                   fsbtodb(&sblock, cgsblock(sblock.fs_ncg - 1, &sblock)));
+                   SBLOCK, cgsblock(1, &sblock) - SBLOCK, cgsblock(1, &sblock),
+                   cgsblock(sblock.fs_ncg - 1, &sblock));
        /*
         * Now construct the initial file system,
         * then write out the super-block.
        /*
         * Now construct the initial file system,
         * then write out the super-block.
@@ -313,9 +345,8 @@ main(argc, argv)
        /* 
         * Write out the duplicate super blocks
         */
        /* 
         * Write out the duplicate super blocks
         */
-       for (c = 1; c < sblock.fs_ncg; c++)
-               wtfs(fsbtodb(&sblock, cgsblock(c, &sblock)),
-                       SBSIZE, (char *)&sblock);
+       for (cylno = 1; cylno < sblock.fs_ncg; cylno++)
+               wtfs(cgsblock(cylno, &sblock), SBSIZE, (char *)&sblock);
 #ifndef STANDALONE
        exit(0);
 #endif
 #ifndef STANDALONE
        exit(0);
 #endif
@@ -324,8 +355,8 @@ main(argc, argv)
 /*
  * Initialize a cylinder group.
  */
 /*
  * Initialize a cylinder group.
  */
-initcg(c)
-       int c;
+initcg(cylno)
+       int cylno;
 {
        daddr_t cbase, d, dmin, dmax;
        long i, j, s;
 {
        daddr_t cbase, d, dmin, dmax;
        long i, j, s;
@@ -336,16 +367,16 @@ initcg(c)
         * Allow space for super block summary information in first
         * cylinder group.
         */
         * Allow space for super block summary information in first
         * cylinder group.
         */
-       cbase = cgbase(c,&sblock);
+       cbase = cgbase(cylno,&sblock);
        dmax = cbase + sblock.fs_fpg;
        if (dmax > sblock.fs_size)
                dmax = sblock.fs_size;
        dmax = cbase + sblock.fs_fpg;
        if (dmax > sblock.fs_size)
                dmax = sblock.fs_size;
-       dmin = cgdmin(c,&sblock) - cbase;
+       dmin = sblock.fs_dblkno;
        d = cbase;
        d = cbase;
-       cs = fscs+c;
+       cs = fscs + cylno;
        acg.cg_time = utime;
        acg.cg_magic = CG_MAGIC;
        acg.cg_time = utime;
        acg.cg_magic = CG_MAGIC;
-       acg.cg_cgx = c;
+       acg.cg_cgx = cylno;
        acg.cg_ncyl = sblock.fs_cpg;
        acg.cg_niblk = sblock.fs_ipg;
        acg.cg_ndblk = dmax - cbase;
        acg.cg_ncyl = sblock.fs_cpg;
        acg.cg_niblk = sblock.fs_ipg;
        acg.cg_ndblk = dmax - cbase;
@@ -366,7 +397,7 @@ initcg(c)
                }
                acg.cg_cs.cs_nifree += INOPB(&sblock);
        }
                }
                acg.cg_cs.cs_nifree += INOPB(&sblock);
        }
-       if (c == 0)
+       if (cylno == 0)
                for (i = 0; i < ROOTINO; i++) {
                        setbit(acg.cg_iused, i);
                        acg.cg_cs.cs_nifree--;
                for (i = 0; i < ROOTINO; i++) {
                        setbit(acg.cg_iused, i);
                        acg.cg_cs.cs_nifree--;
@@ -375,14 +406,14 @@ initcg(c)
                clrbit(acg.cg_iused, i);
                i++;
        }
                clrbit(acg.cg_iused, i);
                i++;
        }
-       lseek(fso, fsbtodb(&sblock, cgimin(c,&sblock)) * DEV_BSIZE, 0);
+       lseek(fso, fsbtodb(&sblock, cgimin(cylno,&sblock)) * DEV_BSIZE, 0);
        if (write(fso, (char *)zino, sblock.fs_ipg * sizeof (struct dinode)) !=
            sblock.fs_ipg * sizeof (struct dinode))
                printf("write error %D\n", tell(fso) / sblock.fs_bsize);
        for (i = 0; i < MAXCPG; i++)
                for (j = 0; j < NRPOS; j++)
                        acg.cg_b[i][j] = 0;
        if (write(fso, (char *)zino, sblock.fs_ipg * sizeof (struct dinode)) !=
            sblock.fs_ipg * sizeof (struct dinode))
                printf("write error %D\n", tell(fso) / sblock.fs_bsize);
        for (i = 0; i < MAXCPG; i++)
                for (j = 0; j < NRPOS; j++)
                        acg.cg_b[i][j] = 0;
-       if (c == 0) {
+       if (cylno == 0) {
                dmin += howmany(sblock.fs_cssize, sblock.fs_bsize) *
                        sblock.fs_frag;
        }
                dmin += howmany(sblock.fs_cssize, sblock.fs_bsize) *
                        sblock.fs_frag;
        }
@@ -391,12 +422,11 @@ initcg(c)
        while ((d+sblock.fs_frag) <= dmax - cbase) {
                setblock(&sblock, acg.cg_free, d/sblock.fs_frag);
                acg.cg_cs.cs_nbfree++;
        while ((d+sblock.fs_frag) <= dmax - cbase) {
                setblock(&sblock, acg.cg_free, d/sblock.fs_frag);
                acg.cg_cs.cs_nbfree++;
-               s = d * NSPF(&sblock);
-               acg.cg_b[s / sblock.fs_spc]
-                   [s % sblock.fs_nsect * NRPOS / sblock.fs_nsect]++;
+               acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]++;
                d += sblock.fs_frag;
        }
        if (d < dmax - cbase)
                d += sblock.fs_frag;
        }
        if (d < dmax - cbase)
+               acg.cg_frsum[dmax - cbase - d]++;
                for (; d < dmax - cbase; d++) {
                        setbit(acg.cg_free, d);
                        acg.cg_cs.cs_nffree++;
                for (; d < dmax - cbase; d++) {
                        setbit(acg.cg_free, d);
                        acg.cg_cs.cs_nffree++;
@@ -409,7 +439,7 @@ initcg(c)
        sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
        sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree;
        *cs = acg.cg_cs;
        sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
        sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree;
        *cs = acg.cg_cs;
-       wtfs(fsbtodb(&sblock, cgtod(c, &sblock)),
+       wtfs(fsbtodb(&sblock, cgtod(cylno, &sblock)),
                sblock.fs_bsize, (char *)&acg);
 }
 
                sblock.fs_bsize, (char *)&acg);
 }
 
@@ -466,10 +496,9 @@ alloc(size, mode)
        int size;
        int mode;
 {
        int size;
        int mode;
 {
-       int c, i, s, frag;
+       int i, frag;
        daddr_t d;
 
        daddr_t d;
 
-       c = 0;
        rdfs(fsbtodb(&sblock, cgtod(0,&sblock)),
                roundup(sblock.fs_cgsize, DEV_BSIZE), (char *)&acg);
        if (acg.cg_cs.cs_nbfree == 0) {
        rdfs(fsbtodb(&sblock, cgtod(0,&sblock)),
                roundup(sblock.fs_cgsize, DEV_BSIZE), (char *)&acg);
        if (acg.cg_cs.cs_nbfree == 0) {
@@ -491,9 +520,7 @@ goth:
                sblock.fs_cstotal.cs_ndir++;
                fscs[0].cs_ndir++;
        }
                sblock.fs_cstotal.cs_ndir++;
                fscs[0].cs_ndir++;
        }
-       s = d * NSPF(&sblock);
-       acg.cg_b[s / sblock.fs_spc]
-               [s % sblock.fs_nsect * NRPOS / sblock.fs_nsect]--;
+       acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]--;
        if (size != sblock.fs_bsize) {
                frag = howmany(size, sblock.fs_fsize);
                fscs[0].cs_nffree += sblock.fs_frag - frag;
        if (size != sblock.fs_bsize) {
                frag = howmany(size, sblock.fs_fsize);
                fscs[0].cs_nffree += sblock.fs_frag - frag;
index 280095f..e540928 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (c) 1981 Regents of the University of California */
 
 /* Copyright (c) 1981 Regents of the University of California */
 
-static char vers[] = "@(#)ffs_alloc.c 1.12 %G%";
+static char vers[] = "@(#)ffs_alloc.c 1.13 %G%";
 
 /*     alloc.c 4.8     81/03/08        */
 
 
 /*     alloc.c 4.8     81/03/08        */
 
@@ -91,6 +91,8 @@ realloccg(dev, bprev, bpref, osize, nsize)
        bno = fragextend(dev, fs, cg, (long)bprev, osize, nsize);
        if (bno != 0) {
                bp = bread(dev, fsbtodb(fs, bno), osize);
        bno = fragextend(dev, fs, cg, (long)bprev, osize, nsize);
        if (bno != 0) {
                bp = bread(dev, fsbtodb(fs, bno), osize);
+               if (bp->b_flags & B_ERROR)
+                       return (0);
                bp->b_bcount = nsize;
                blkclr(bp->b_un.b_addr + osize, nsize - osize);
                return (bp);
                bp->b_bcount = nsize;
                blkclr(bp->b_un.b_addr + osize, nsize - osize);
                return (bp);
@@ -103,6 +105,8 @@ realloccg(dev, bprev, bpref, osize, nsize)
                 * make a new copy
                 */
                obp = bread(dev, fsbtodb(fs, bprev), osize);
                 * make a new copy
                 */
                obp = bread(dev, fsbtodb(fs, bprev), osize);
+               if (obp->b_flags & B_ERROR)
+                       return (0);
                bp = getblk(dev, fsbtodb(fs, bno), nsize);
                cp = bp->b_un.b_addr;
                bp->b_un.b_addr = obp->b_un.b_addr;
                bp = getblk(dev, fsbtodb(fs, bno), nsize);
                cp = bp->b_un.b_addr;
                bp->b_un.b_addr = obp->b_un.b_addr;
@@ -275,35 +279,32 @@ fragextend(dev, fs, cg, bprev, osize, nsize)
                return (0);
        cgp = bp->b_un.b_cg;
        bno = bprev % fs->fs_fpg;
                return (0);
        cgp = bp->b_un.b_cg;
        bno = bprev % fs->fs_fpg;
-       for (i = osize / fs->fs_fsize; i < frags; i++) {
+       for (i = osize / fs->fs_fsize; i < frags; i++)
+               if (isclr(cgp->cg_free, bno + i)) {
+                       brelse(bp);
+                       return (0);
+               }
+       /*
+        * the current fragment can be extended
+        * deduct the count on fragment being extended into
+        * increase the count on the remaining fragment (if any)
+        * allocate the extended piece
+        */
+       for (i = frags; i < fs->fs_frag - bbase; i++)
                if (isclr(cgp->cg_free, bno + i))
                        break;
                if (isclr(cgp->cg_free, bno + i))
                        break;
+       cgp->cg_frsum[i - osize / fs->fs_fsize]--;
+       if (i != frags)
+               cgp->cg_frsum[i - frags]++;
+       for (i = osize / fs->fs_fsize; i < frags; i++) {
+               clrbit(cgp->cg_free, bno + i);
+               cgp->cg_cs.cs_nffree--;
+               fs->fs_cstotal.cs_nffree--;
+               fs->fs_cs(fs, cg).cs_nffree--;
        }
        }
-       if (i == frags) {
-               /*
-                * the current fragment can be extended
-                * deduct the count on fragment being extended into
-                * increase the count on the remaining fragment (if any)
-                * allocate the extended piece
-                */
-               for (i = frags; i < fs->fs_frag - bbase; i++)
-                       if (isclr(cgp->cg_free, bno + i))
-                               break;
-               cgp->cg_frsum[i - osize / fs->fs_fsize]--;
-               if (i != frags)
-                       cgp->cg_frsum[i - frags]++;
-               for (i = osize / fs->fs_fsize; i < frags; i++) {
-                       clrbit(cgp->cg_free, bno + i);
-                       cgp->cg_cs.cs_nffree--;
-                       fs->fs_cstotal.cs_nffree--;
-                       fs->fs_cs(fs, cg).cs_nffree--;
-               }
-               fs->fs_fmod++;
-               bdwrite(bp);
-               return (bprev);
-       }
-       brelse(bp);
-       return (0);
+       fs->fs_fmod++;
+       bdwrite(bp);
+       return (bprev);
 }
 
 daddr_t
 }
 
 daddr_t
@@ -385,48 +386,79 @@ alloccgblk(fs, cgp, bpref)
        daddr_t bno;
        int cylno, pos;
        short *cylbp;
        daddr_t bno;
        int cylno, pos;
        short *cylbp;
-       int i, j;
+       register int i;
 
        if (bpref == 0) {
                bpref = cgp->cg_rotor;
 
        if (bpref == 0) {
                bpref = cgp->cg_rotor;
+               goto norot;
+       }
+       bpref &= ~(fs->fs_frag - 1);
+       bpref %= fs->fs_fpg;
+       /*
+        * if the requested block is available, use it
+        */
+       if (isblock(fs, cgp->cg_free, bpref/fs->fs_frag)) {
+               bno = bpref;
+               goto gotit;
+       }
+       if (fs->fs_cpc == 0)
+               goto norot;
+       /*
+        * check for a block available on the same cylinder
+        * beginning with one which is rotationally optimal
+        */
+       cylno = cbtocylno(fs, bpref);
+       cylbp = cgp->cg_b[cylno];
+       if (fs->fs_rotdelay == 0) {
+               pos = cbtorpos(fs, bpref);
        } else {
        } else {
-               bpref &= ~(fs->fs_frag - 1);
-               bpref %= fs->fs_fpg;
-               /*
-                * if the requested block is available, use it
-                */
-               if (isblock(fs, cgp->cg_free, bpref/fs->fs_frag)) {
-                       bno = bpref;
-                       goto gotit;
-               }
                /*
                /*
-                * check for a block available on the same cylinder
-                * beginning with one which is rotationally optimal
+                * here we convert ms of delay to frags as:
+                * (frags) = (ms) * (rev/sec) * (sect/rev) /
+                *      ((sect/frag) * (ms/sec))
+                * then round up to the next rotational position
                 */
                 */
-               i = bpref * NSPF(fs);
-               cylno = i / fs->fs_spc;
-               cylbp = cgp->cg_b[cylno];
-               pos = (i + (fs->fs_rotdelay == 0) ? 0 :
-                      1 + fs->fs_rotdelay * HZ * fs->fs_nsect /
-                      (NSPF(fs) * 1000)) % fs->fs_nsect * NRPOS / fs->fs_nsect;
-               for (i = pos; i < NRPOS; i++)
+               bpref += fs->fs_rotdelay * fs->fs_rps * fs->fs_nsect /
+                   (NSPF(fs) * 1000);
+               pos = cbtorpos(fs, bpref);
+               pos = (pos + 1) % NRPOS;
+       }
+       /*
+        * check the summary information to see if a block is 
+        * available in the requested cylinder starting at the
+        * optimal rotational position and proceeding around.
+        */
+       for (i = pos; i < NRPOS; i++)
+               if (cylbp[i] > 0)
+                       break;
+       if (i == NRPOS)
+               for (i = 0; i < pos; i++)
                        if (cylbp[i] > 0)
                                break;
                        if (cylbp[i] > 0)
                                break;
-               if (i == NRPOS)
-                       for (i = 0; i < pos; i++)
-                               if (cylbp[i] > 0)
-                                       break;
-               if (cylbp[i] > 0) {
-                       bpref = cylno * fs->fs_spc / NSPB(fs);
-                       for (j = fs->fs_postbl[i]; j > -1; j = fs->fs_rotbl[j]) {
-                               if (isblock(fs, cgp->cg_free, bpref + j)) {
-                                       bno = (bpref + j) * fs->fs_frag;
-                                       goto gotit;
-                               }
+       if (cylbp[i] > 0) {
+               /*
+                * found a rotational position, now find the actual
+                * block. A panic if none is actually there.
+                */
+               pos = cylno % fs->fs_cpc;
+               bno = (cylno - pos) * fs->fs_spc / NSPB(fs);
+               if (fs->fs_postbl[pos][i] == -1)
+                       panic("alloccgblk: cyl groups corrupted");
+               for (i = fs->fs_postbl[pos][i]; ; i += fs->fs_rotbl[i]) {
+                       if (isblock(fs, cgp->cg_free, bno + i)) {
+                               bno = (bno + i) * fs->fs_frag;
+                               goto gotit;
                        }
                        }
-                       panic("alloccgblk: can't find blk in cyl");
+                       if (fs->fs_rotbl[i] == 0)
+                               break;
                }
                }
+               panic("alloccgblk: can't find blk in cyl");
        }
        }
+norot:
+       /*
+        * no blocks in the requested cylinder, so take next
+        * available one in this cylinder group.
+        */
        bno = mapsearch(fs, cgp, bpref, fs->fs_frag);
        if (bno == 0)
                return (0);
        bno = mapsearch(fs, cgp, bpref, fs->fs_frag);
        if (bno == 0)
                return (0);
@@ -436,8 +468,7 @@ gotit:
        cgp->cg_cs.cs_nbfree--;
        fs->fs_cstotal.cs_nbfree--;
        fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--;
        cgp->cg_cs.cs_nbfree--;
        fs->fs_cstotal.cs_nbfree--;
        fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--;
-       i = bno * NSPF(fs);
-       cgp->cg_b[i/fs->fs_spc][i%fs->fs_nsect*NRPOS/fs->fs_nsect]--;
+       cgp->cg_b[cbtocylno(fs, bno)][cbtorpos(fs, bno)]--;
        fs->fs_fmod++;
        return (cgp->cg_cgx * fs->fs_fpg + bno);
 }
        fs->fs_fmod++;
        return (cgp->cg_cgx * fs->fs_fpg + bno);
 }
@@ -521,8 +552,7 @@ fre(dev, bno, size)
                cgp->cg_cs.cs_nbfree++;
                fs->fs_cstotal.cs_nbfree++;
                fs->fs_cs(fs, cg).cs_nbfree++;
                cgp->cg_cs.cs_nbfree++;
                fs->fs_cstotal.cs_nbfree++;
                fs->fs_cs(fs, cg).cs_nbfree++;
-               i = bno * NSPF(fs);
-               cgp->cg_b[i/fs->fs_spc][i%fs->fs_nsect*NRPOS/fs->fs_nsect]++;
+               cgp->cg_b[cbtocylno(fs, bno)][cbtorpos(fs, bno)]++;
        } else {
                bbase = bno - (bno % fs->fs_frag);
                /*
        } else {
                bbase = bno - (bno % fs->fs_frag);
                /*
@@ -559,9 +589,7 @@ fre(dev, bno, size)
                        cgp->cg_cs.cs_nbfree++;
                        fs->fs_cstotal.cs_nbfree++;
                        fs->fs_cs(fs, cg).cs_nbfree++;
                        cgp->cg_cs.cs_nbfree++;
                        fs->fs_cstotal.cs_nbfree++;
                        fs->fs_cs(fs, cg).cs_nbfree++;
-                       i = bbase * NSPF(fs);
-                       cgp->cg_b[i / fs->fs_spc]
-                                [i % fs->fs_nsect * NRPOS / fs->fs_nsect]++;
+                       cgp->cg_b[cbtocylno(fs, bbase)][cbtorpos(fs, bbase)]++;
                }
        }
        fs->fs_fmod++;
                }
        }
        fs->fs_fmod++;
index 1bec71a..00107aa 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (c) 1981 Regents of the University of California */
 
 /* Copyright (c) 1981 Regents of the University of California */
 
-/*     fs.h    1.10    %G%     */
+/*     fs.h    1.11    %G%     */
 
 /*
  * Each disk drive contains some number of file systems.
 
 /*
  * Each disk drive contains some number of file systems.
  * super-block data does not change, so the copies need not be
  * referenced further unless disaster strikes.
  *
  * super-block data does not change, so the copies need not be
  * referenced further unless disaster strikes.
  *
- * For file system fs and a cylinder group number cg:
- *     [BBLOCK]        Boot sector
- *     [SBLOCK]        Super-block
- *     [CBLOCK(fs)]    Cylinder group block
- *     [IBLOCK(fs)..IBLOCK(fs)+fs.fs_ipg/INOPB(fs))
- *                     Inode blocks
- *     [IBLOCK(fs)+fs.fs_ipg/INOPB(fs)..fs.fs_fpg/fs.fs_frag)
- *                     Data blocks
- * The beginning of data blocks for cg in fs is also given by
- * the ``cgdmin(cg,fs)'' macro.
+ * For file system fs, the offsets of the various blocks of interest
+ * are given in the super block as:
+ *     [fs->fs_bblkno]         Boot sector
+ *     [fs->fs_sblkno]         Super-block
+ *     [fs->fs_cblkno]         Cylinder group block
+ *     [fs->fs_iblkno]         Inode blocks
+ *     [fs->fs_dblkno]         Data blocks
+ * The beginning of cylinder group cg in fs, is given by
+ * the ``cgbase(cg, fs)'' macro.
  *
  *
- * The boot and super blocks are given in absolute disk addresses.
+ * The first boot and super blocks are given in absolute disk addresses.
  */
 #define BBSIZE         1024
 #define SBSIZE         8192
 #define        BBLOCK          ((daddr_t)(0))
 #define        SBLOCK          ((daddr_t)(BBLOCK + BBSIZE / DEV_BSIZE))
  */
 #define BBSIZE         1024
 #define SBSIZE         8192
 #define        BBLOCK          ((daddr_t)(0))
 #define        SBLOCK          ((daddr_t)(BBLOCK + BBSIZE / DEV_BSIZE))
-/*
- * The cylinder group and inode blocks are given in file system
- * addresses, and hence must be converted to disk addresses by
- * the ``fsbtodb(fs, bno)'' macro.
- */
-#define        CBLOCK(fs) \
-  ((daddr_t)(roundup(howmany(BBSIZE + SBSIZE, (fs)->fs_fsize), (fs)->fs_frag)))
-#define        IBLOCK(fs)      ((daddr_t)(CBLOCK(fs) + (fs)->fs_frag))
 
 /*
  * Addresses stored in inodes are capable of addressing fragments
 
 /*
  * Addresses stored in inodes are capable of addressing fragments
@@ -165,16 +156,21 @@ struct csum {
 struct fs
 {
        long    fs_magic;               /* magic number */
 struct fs
 {
        long    fs_magic;               /* magic number */
-       daddr_t fs_sblkno;              /* offset of super-block in filesys */
+       daddr_t fs_bblkno;              /* abs addr of boot-block in filesys */
+       daddr_t fs_sblkno;              /* abs addr of super-block in filesys */
+       daddr_t fs_cblkno;              /* offset of cyl-block in filesys */
+       daddr_t fs_iblkno;              /* offset of inode-blocks in filesys */
+       daddr_t fs_dblkno;              /* offset of data-blocks in filesys */
        time_t  fs_time;                /* last time written */
        long    fs_size;                /* number of blocks in fs */
        long    fs_dsize;               /* number of data blocks in fs */
        long    fs_ncg;                 /* number of cylinder groups */
        long    fs_bsize;               /* size of basic blocks in fs */
        long    fs_fsize;               /* size of frag blocks in fs */
        time_t  fs_time;                /* last time written */
        long    fs_size;                /* number of blocks in fs */
        long    fs_dsize;               /* number of data blocks in fs */
        long    fs_ncg;                 /* number of cylinder groups */
        long    fs_bsize;               /* size of basic blocks in fs */
        long    fs_fsize;               /* size of frag blocks in fs */
-       long    fs_frag;                /* number of frags in a block in fs */
+       short   fs_frag;                /* number of frags in a block in fs */
        short   fs_minfree;             /* minimum percentage of free blocks */
        short   fs_rotdelay;            /* num of ms for optimal next block */
        short   fs_minfree;             /* minimum percentage of free blocks */
        short   fs_rotdelay;            /* num of ms for optimal next block */
+       short   fs_rps;                 /* disk revolutions per second */
 /* sizes determined by number of cylinder groups and their sizes */
        daddr_t fs_csaddr;              /* blk addr of cyl grp summary area */
        long    fs_cssize;              /* size of cyl grp summary area */
 /* sizes determined by number of cylinder groups and their sizes */
        daddr_t fs_csaddr;              /* blk addr of cyl grp summary area */
        long    fs_cssize;              /* size of cyl grp summary area */
@@ -198,8 +194,9 @@ struct      fs
 /* these fields retain the current block allocation info */
        long    fs_cgrotor;             /* last cg searched */
        struct  csum *fs_csp[NBUF];     /* list of fs_cs info buffers */
 /* these fields retain the current block allocation info */
        long    fs_cgrotor;             /* last cg searched */
        struct  csum *fs_csp[NBUF];     /* list of fs_cs info buffers */
-       short   fs_postbl[NRPOS];       /* head of blocks for each rotation */
-       short   fs_rotbl[1];            /* list of blocks for each rotation */
+       short   fs_cpc;                 /* cyl per cycle in postbl */
+       short   fs_postbl[MAXCPG][NRPOS];/* head of blocks for each rotation */
+       u_char  fs_rotbl[1];            /* list of blocks for each rotation */
 /* actually longer */
 };
 
 /* actually longer */
 };
 
@@ -213,12 +210,15 @@ struct    fs
        [(indx) % ((fs)->fs_bsize / sizeof(struct csum))]
 
 /*
        [(indx) % ((fs)->fs_bsize / sizeof(struct csum))]
 
 /*
- * MAXBPC bounds the number of blocks of data per cylinder,
- * and is limited by the fact that the super block is of size SBSIZE.
- * Its size is derived from the size of blocks and the (struct fs) size,
- * by the number of remaining bits.
+ * MAXBPC bounds the size of the rotational layout tables and
+ * is limited by the fact that the super block is of size SBSIZE.
+ * The size of these tables is INVERSELY proportional to the block
+ * size of the file system. It is aggravated by sector sizes that
+ * are not powers of two, as this increases the number of cylinders
+ * included before the rotational pattern repeats (fs_cpc).
+ * Its size is derived from the number of bytes remaining in (struct fs)
  */
  */
-#define        MAXBPC  ((SBSIZE - sizeof (struct fs)) / sizeof(short))
+#define        MAXBPC  (SBSIZE - sizeof (struct fs))
 
 /*
  * Cylinder group block for a file system.
 
 /*
  * Cylinder group block for a file system.
@@ -261,29 +261,33 @@ struct    cg {
 /*
  * Cylinder group macros to locate things in cylinder groups.
  *
 /*
  * Cylinder group macros to locate things in cylinder groups.
  *
- * cylinder group to disk block at very beginning
+ * cylinder group to disk block address of spare boot block
+ * and super block
+ * Note that these are in absolute addresses, and can NOT
+ * in general be expressable in terms of file system addresses.
  */
  */
-#define        cgbase(c,fs)    ((daddr_t)((fs)->fs_fpg * (c)))
+#define        cgbblock(c,fs)  (fsbtodb(fs, cgbase(c,fs)) + (fs)->fs_bblkno)
+#define        cgsblock(c,fs)  (fsbtodb(fs, cgbase(c,fs)) + (fs)->fs_sblkno)
 
 /*
 
 /*
- * cylinder group to spare super block address
+ * cylinder group to disk block at very beginning
  */
  */
-#define        cgsblock(c,fs)  (cgbase(c,fs) + dbtofsb(fs, SBLOCK))
+#define        cgbase(c,fs)    ((daddr_t)((fs)->fs_fpg * (c)))
 
 /*
  * convert cylinder group to index of its cg block
  */
 
 /*
  * convert cylinder group to index of its cg block
  */
-#define        cgtod(c,fs)     (cgbase(c,fs) + CBLOCK(fs))
+#define        cgtod(c,fs)     (cgbase(c,fs) + (fs)->fs_cblkno)
 
 /*
  * give address of first inode block in cylinder group
  */
 
 /*
  * give address of first inode block in cylinder group
  */
-#define        cgimin(c,fs)    (cgbase(c,fs) + IBLOCK(fs))
+#define        cgimin(c,fs)    (cgbase(c,fs) + (fs)->fs_iblkno)
 
 /*
  * give address of first data block in cylinder group
  */
 
 /*
  * give address of first data block in cylinder group
  */
-#define        cgdmin(c,fs)    (cgimin(c,fs) + (fs)->fs_ipg / INOPF(fs))
+#define        cgdmin(c,fs)    (cgbase(c,fs) + (fs)->fs_dblkno)
 
 /*
  * turn inode number into cylinder group number
 
 /*
  * turn inode number into cylinder group number
@@ -294,8 +298,8 @@ struct      cg {
  * turn inode number into file system block address
  */
 #define        itod(x,fs) \
  * turn inode number into file system block address
  */
 #define        itod(x,fs) \
-       ((daddr_t)(cgimin(itog(x,fs),fs) + (fs)->fs_frag * \
-       ((x) % (fs)->fs_ipg / INOPB(fs))))
+       ((daddr_t)(cgimin(itog(x,fs),fs) + \
+       (x) % (fs)->fs_ipg / INOPB(fs) * (fs)->fs_frag))
 
 /*
  * turn inode number into file system block offset
 
 /*
  * turn inode number into file system block offset
@@ -312,6 +316,14 @@ struct     cg {
  */
 #define        dtogd(d,fs)     ((d) % (fs)->fs_fpg)
 
  */
 #define        dtogd(d,fs)     ((d) % (fs)->fs_fpg)
 
+/*
+ * compute the cylinder and rotational position of a cyl block addr
+ */
+#define cbtocylno(fs, bno) \
+       ((bno) * NSPF(fs) / (fs)->fs_spc)
+#define cbtorpos(fs, bno) \
+       ((bno) * NSPF(fs) % (fs)->fs_nsect * NRPOS / (fs)->fs_nsect)
+
 /*
  * determining the size of a file block in the file system
  */
 /*
  * determining the size of a file block in the file system
  */
index 066dd11..2045e37 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (c) 1981 Regents of the University of California */
 
 /* Copyright (c) 1981 Regents of the University of California */
 
-static char vers[] = "@(#)lfs_alloc.c 1.12 %G%";
+static char vers[] = "@(#)lfs_alloc.c 1.13 %G%";
 
 /*     alloc.c 4.8     81/03/08        */
 
 
 /*     alloc.c 4.8     81/03/08        */
 
@@ -91,6 +91,8 @@ realloccg(dev, bprev, bpref, osize, nsize)
        bno = fragextend(dev, fs, cg, (long)bprev, osize, nsize);
        if (bno != 0) {
                bp = bread(dev, fsbtodb(fs, bno), osize);
        bno = fragextend(dev, fs, cg, (long)bprev, osize, nsize);
        if (bno != 0) {
                bp = bread(dev, fsbtodb(fs, bno), osize);
+               if (bp->b_flags & B_ERROR)
+                       return (0);
                bp->b_bcount = nsize;
                blkclr(bp->b_un.b_addr + osize, nsize - osize);
                return (bp);
                bp->b_bcount = nsize;
                blkclr(bp->b_un.b_addr + osize, nsize - osize);
                return (bp);
@@ -103,6 +105,8 @@ realloccg(dev, bprev, bpref, osize, nsize)
                 * make a new copy
                 */
                obp = bread(dev, fsbtodb(fs, bprev), osize);
                 * make a new copy
                 */
                obp = bread(dev, fsbtodb(fs, bprev), osize);
+               if (obp->b_flags & B_ERROR)
+                       return (0);
                bp = getblk(dev, fsbtodb(fs, bno), nsize);
                cp = bp->b_un.b_addr;
                bp->b_un.b_addr = obp->b_un.b_addr;
                bp = getblk(dev, fsbtodb(fs, bno), nsize);
                cp = bp->b_un.b_addr;
                bp->b_un.b_addr = obp->b_un.b_addr;
@@ -275,35 +279,32 @@ fragextend(dev, fs, cg, bprev, osize, nsize)
                return (0);
        cgp = bp->b_un.b_cg;
        bno = bprev % fs->fs_fpg;
                return (0);
        cgp = bp->b_un.b_cg;
        bno = bprev % fs->fs_fpg;
-       for (i = osize / fs->fs_fsize; i < frags; i++) {
+       for (i = osize / fs->fs_fsize; i < frags; i++)
+               if (isclr(cgp->cg_free, bno + i)) {
+                       brelse(bp);
+                       return (0);
+               }
+       /*
+        * the current fragment can be extended
+        * deduct the count on fragment being extended into
+        * increase the count on the remaining fragment (if any)
+        * allocate the extended piece
+        */
+       for (i = frags; i < fs->fs_frag - bbase; i++)
                if (isclr(cgp->cg_free, bno + i))
                        break;
                if (isclr(cgp->cg_free, bno + i))
                        break;
+       cgp->cg_frsum[i - osize / fs->fs_fsize]--;
+       if (i != frags)
+               cgp->cg_frsum[i - frags]++;
+       for (i = osize / fs->fs_fsize; i < frags; i++) {
+               clrbit(cgp->cg_free, bno + i);
+               cgp->cg_cs.cs_nffree--;
+               fs->fs_cstotal.cs_nffree--;
+               fs->fs_cs(fs, cg).cs_nffree--;
        }
        }
-       if (i == frags) {
-               /*
-                * the current fragment can be extended
-                * deduct the count on fragment being extended into
-                * increase the count on the remaining fragment (if any)
-                * allocate the extended piece
-                */
-               for (i = frags; i < fs->fs_frag - bbase; i++)
-                       if (isclr(cgp->cg_free, bno + i))
-                               break;
-               cgp->cg_frsum[i - osize / fs->fs_fsize]--;
-               if (i != frags)
-                       cgp->cg_frsum[i - frags]++;
-               for (i = osize / fs->fs_fsize; i < frags; i++) {
-                       clrbit(cgp->cg_free, bno + i);
-                       cgp->cg_cs.cs_nffree--;
-                       fs->fs_cstotal.cs_nffree--;
-                       fs->fs_cs(fs, cg).cs_nffree--;
-               }
-               fs->fs_fmod++;
-               bdwrite(bp);
-               return (bprev);
-       }
-       brelse(bp);
-       return (0);
+       fs->fs_fmod++;
+       bdwrite(bp);
+       return (bprev);
 }
 
 daddr_t
 }
 
 daddr_t
@@ -385,48 +386,79 @@ alloccgblk(fs, cgp, bpref)
        daddr_t bno;
        int cylno, pos;
        short *cylbp;
        daddr_t bno;
        int cylno, pos;
        short *cylbp;
-       int i, j;
+       register int i;
 
        if (bpref == 0) {
                bpref = cgp->cg_rotor;
 
        if (bpref == 0) {
                bpref = cgp->cg_rotor;
+               goto norot;
+       }
+       bpref &= ~(fs->fs_frag - 1);
+       bpref %= fs->fs_fpg;
+       /*
+        * if the requested block is available, use it
+        */
+       if (isblock(fs, cgp->cg_free, bpref/fs->fs_frag)) {
+               bno = bpref;
+               goto gotit;
+       }
+       if (fs->fs_cpc == 0)
+               goto norot;
+       /*
+        * check for a block available on the same cylinder
+        * beginning with one which is rotationally optimal
+        */
+       cylno = cbtocylno(fs, bpref);
+       cylbp = cgp->cg_b[cylno];
+       if (fs->fs_rotdelay == 0) {
+               pos = cbtorpos(fs, bpref);
        } else {
        } else {
-               bpref &= ~(fs->fs_frag - 1);
-               bpref %= fs->fs_fpg;
-               /*
-                * if the requested block is available, use it
-                */
-               if (isblock(fs, cgp->cg_free, bpref/fs->fs_frag)) {
-                       bno = bpref;
-                       goto gotit;
-               }
                /*
                /*
-                * check for a block available on the same cylinder
-                * beginning with one which is rotationally optimal
+                * here we convert ms of delay to frags as:
+                * (frags) = (ms) * (rev/sec) * (sect/rev) /
+                *      ((sect/frag) * (ms/sec))
+                * then round up to the next rotational position
                 */
                 */
-               i = bpref * NSPF(fs);
-               cylno = i / fs->fs_spc;
-               cylbp = cgp->cg_b[cylno];
-               pos = (i + (fs->fs_rotdelay == 0) ? 0 :
-                      1 + fs->fs_rotdelay * HZ * fs->fs_nsect /
-                      (NSPF(fs) * 1000)) % fs->fs_nsect * NRPOS / fs->fs_nsect;
-               for (i = pos; i < NRPOS; i++)
+               bpref += fs->fs_rotdelay * fs->fs_rps * fs->fs_nsect /
+                   (NSPF(fs) * 1000);
+               pos = cbtorpos(fs, bpref);
+               pos = (pos + 1) % NRPOS;
+       }
+       /*
+        * check the summary information to see if a block is 
+        * available in the requested cylinder starting at the
+        * optimal rotational position and proceeding around.
+        */
+       for (i = pos; i < NRPOS; i++)
+               if (cylbp[i] > 0)
+                       break;
+       if (i == NRPOS)
+               for (i = 0; i < pos; i++)
                        if (cylbp[i] > 0)
                                break;
                        if (cylbp[i] > 0)
                                break;
-               if (i == NRPOS)
-                       for (i = 0; i < pos; i++)
-                               if (cylbp[i] > 0)
-                                       break;
-               if (cylbp[i] > 0) {
-                       bpref = cylno * fs->fs_spc / NSPB(fs);
-                       for (j = fs->fs_postbl[i]; j > -1; j = fs->fs_rotbl[j]) {
-                               if (isblock(fs, cgp->cg_free, bpref + j)) {
-                                       bno = (bpref + j) * fs->fs_frag;
-                                       goto gotit;
-                               }
+       if (cylbp[i] > 0) {
+               /*
+                * found a rotational position, now find the actual
+                * block. A panic if none is actually there.
+                */
+               pos = cylno % fs->fs_cpc;
+               bno = (cylno - pos) * fs->fs_spc / NSPB(fs);
+               if (fs->fs_postbl[pos][i] == -1)
+                       panic("alloccgblk: cyl groups corrupted");
+               for (i = fs->fs_postbl[pos][i]; ; i += fs->fs_rotbl[i]) {
+                       if (isblock(fs, cgp->cg_free, bno + i)) {
+                               bno = (bno + i) * fs->fs_frag;
+                               goto gotit;
                        }
                        }
-                       panic("alloccgblk: can't find blk in cyl");
+                       if (fs->fs_rotbl[i] == 0)
+                               break;
                }
                }
+               panic("alloccgblk: can't find blk in cyl");
        }
        }
+norot:
+       /*
+        * no blocks in the requested cylinder, so take next
+        * available one in this cylinder group.
+        */
        bno = mapsearch(fs, cgp, bpref, fs->fs_frag);
        if (bno == 0)
                return (0);
        bno = mapsearch(fs, cgp, bpref, fs->fs_frag);
        if (bno == 0)
                return (0);
@@ -436,8 +468,7 @@ gotit:
        cgp->cg_cs.cs_nbfree--;
        fs->fs_cstotal.cs_nbfree--;
        fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--;
        cgp->cg_cs.cs_nbfree--;
        fs->fs_cstotal.cs_nbfree--;
        fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--;
-       i = bno * NSPF(fs);
-       cgp->cg_b[i/fs->fs_spc][i%fs->fs_nsect*NRPOS/fs->fs_nsect]--;
+       cgp->cg_b[cbtocylno(fs, bno)][cbtorpos(fs, bno)]--;
        fs->fs_fmod++;
        return (cgp->cg_cgx * fs->fs_fpg + bno);
 }
        fs->fs_fmod++;
        return (cgp->cg_cgx * fs->fs_fpg + bno);
 }
@@ -521,8 +552,7 @@ fre(dev, bno, size)
                cgp->cg_cs.cs_nbfree++;
                fs->fs_cstotal.cs_nbfree++;
                fs->fs_cs(fs, cg).cs_nbfree++;
                cgp->cg_cs.cs_nbfree++;
                fs->fs_cstotal.cs_nbfree++;
                fs->fs_cs(fs, cg).cs_nbfree++;
-               i = bno * NSPF(fs);
-               cgp->cg_b[i/fs->fs_spc][i%fs->fs_nsect*NRPOS/fs->fs_nsect]++;
+               cgp->cg_b[cbtocylno(fs, bno)][cbtorpos(fs, bno)]++;
        } else {
                bbase = bno - (bno % fs->fs_frag);
                /*
        } else {
                bbase = bno - (bno % fs->fs_frag);
                /*
@@ -559,9 +589,7 @@ fre(dev, bno, size)
                        cgp->cg_cs.cs_nbfree++;
                        fs->fs_cstotal.cs_nbfree++;
                        fs->fs_cs(fs, cg).cs_nbfree++;
                        cgp->cg_cs.cs_nbfree++;
                        fs->fs_cstotal.cs_nbfree++;
                        fs->fs_cs(fs, cg).cs_nbfree++;
-                       i = bbase * NSPF(fs);
-                       cgp->cg_b[i / fs->fs_spc]
-                                [i % fs->fs_nsect * NRPOS / fs->fs_nsect]++;
+                       cgp->cg_b[cbtocylno(fs, bbase)][cbtorpos(fs, bbase)]++;
                }
        }
        fs->fs_fmod++;
                }
        }
        fs->fs_fmod++;