use proper types for uids, gids
[unix-history] / usr / src / sys / ufs / ffs / ffs_alloc.c
index 139417c..a54f8d7 100644 (file)
@@ -1,16 +1,22 @@
-/*     ffs_alloc.c     6.8     85/01/07        */
+/*
+ * Copyright (c) 1982 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ *
+ *     @(#)ffs_alloc.c 6.17 (Berkeley) %G%
+ */
 
 #include "param.h"
 #include "systm.h"
 #include "mount.h"
 #include "fs.h"
 
 #include "param.h"
 #include "systm.h"
 #include "mount.h"
 #include "fs.h"
-#include "conf.h"
 #include "buf.h"
 #include "inode.h"
 #include "dir.h"
 #include "user.h"
 #include "quota.h"
 #include "kernel.h"
 #include "buf.h"
 #include "inode.h"
 #include "dir.h"
 #include "user.h"
 #include "quota.h"
 #include "kernel.h"
+#include "syslog.h"
 
 extern u_long          hashalloc();
 extern ino_t           ialloccg();
 
 extern u_long          hashalloc();
 extern ino_t           ialloccg();
@@ -106,7 +112,7 @@ realloccg(ip, bprev, bpref, osize, nsize)
        daddr_t bno;
        register struct fs *fs;
        register struct buf *bp, *obp;
        daddr_t bno;
        register struct fs *fs;
        register struct buf *bp, *obp;
-       int cg;
+       int cg, request;
        
        fs = ip->i_fs;
        if ((unsigned)osize > fs->fs_bsize || fragoff(fs, osize) != 0 ||
        
        fs = ip->i_fs;
        if ((unsigned)osize > fs->fs_bsize || fragoff(fs, osize) != 0 ||
@@ -145,7 +151,50 @@ realloccg(ip, bprev, bpref, osize, nsize)
        }
        if (bpref >= fs->fs_size)
                bpref = 0;
        }
        if (bpref >= fs->fs_size)
                bpref = 0;
-       bno = (daddr_t)hashalloc(ip, cg, (long)bpref, nsize,
+       switch (fs->fs_optim) {
+       case FS_OPTSPACE:
+               /*
+                * Allocate an exact sized fragment. Although this makes 
+                * best use of space, we will waste time relocating it if 
+                * the file continues to grow. If the fragmentation is
+                * less than half of the minimum free reserve, we choose
+                * to begin optimizing for time.
+                */
+               request = nsize;
+               if (fs->fs_minfree < 5 ||
+                   fs->fs_cstotal.cs_nffree >
+                   fs->fs_dsize * fs->fs_minfree / (2 * 100))
+                       break;
+               log(LOG_NOTICE, "%s: optimization changed from SPACE to TIME\n",
+                       fs->fs_fsmnt);
+               fs->fs_optim = FS_OPTTIME;
+               break;
+       case FS_OPTTIME:
+               /*
+                * At this point we have discovered a file that is trying
+                * to grow a small fragment to a larger fragment. To save
+                * time, we allocate a full sized block, then free the 
+                * unused portion. If the file continues to grow, the 
+                * `fragextend' call above will be able to grow it in place
+                * without further copying. If aberrant programs cause
+                * disk fragmentation to grow within 2% of the free reserve,
+                * we choose to begin optimizing for space.
+                */
+               request = fs->fs_bsize;
+               if (fs->fs_cstotal.cs_nffree <
+                   fs->fs_dsize * (fs->fs_minfree - 2) / 100)
+                       break;
+               log(LOG_NOTICE, "%s: optimization changed from TIME to SPACE\n",
+                       fs->fs_fsmnt);
+               fs->fs_optim = FS_OPTSPACE;
+               break;
+       default:
+               printf("dev = 0x%x, optim = %d, fs = %s\n",
+                   ip->i_dev, fs->fs_optim, fs->fs_fsmnt);
+               panic("realloccg: bad optim");
+               /* NOTREACHED */
+       }
+       bno = (daddr_t)hashalloc(ip, cg, (long)bpref, request,
                (u_long (*)())alloccg);
        if (bno > 0) {
                obp = bread(ip->i_dev, fsbtodb(fs, bprev), osize);
                (u_long (*)())alloccg);
        if (bno > 0) {
                obp = bread(ip->i_dev, fsbtodb(fs, bprev), osize);
@@ -162,6 +211,9 @@ realloccg(ip, bprev, bpref, osize, nsize)
                }
                brelse(obp);
                free(ip, bprev, (off_t)osize);
                }
                brelse(obp);
                free(ip, bprev, (off_t)osize);
+               if (nsize < request)
+                       free(ip, bno + numfrags(fs, nsize),
+                               (off_t)(request - nsize));
                ip->i_blocks += btodb(nsize - osize);
                ip->i_flag |= IUPD|ICHG;
                return (bp);
                ip->i_blocks += btodb(nsize - osize);
                ip->i_flag |= IUPD|ICHG;
                return (bp);
@@ -274,9 +326,14 @@ dirpref(fs)
  * the file. If no blocks have been allocated in any other section, the
  * policy is to place the section in a cylinder group with a greater than
  * average number of free blocks.  An appropriate cylinder group is found
  * the file. If no blocks have been allocated in any other section, the
  * policy is to place the section in a cylinder group with a greater than
  * average number of free blocks.  An appropriate cylinder group is found
- * by maintaining a rotor that sweeps the cylinder groups. When a new
- * group of blocks is needed, the rotor is advanced until a cylinder group
- * with greater than the average number of free blocks is found.
+ * by using a rotor that sweeps the cylinder groups. When a new group of
+ * blocks is needed, the sweep begins in the cylinder group following the
+ * cylinder group from which the previous allocation was made. The sweep
+ * continues until a cylinder group with greater than the average number
+ * of free blocks is found. If the allocation is for the first block in an
+ * indirect block, the information on the previous allocation is unavailable;
+ * here a best guess is made based upon the logical block number being
+ * allocated.
  * 
  * If a section is already partially allocated, the policy is to
  * contiguously allocate fs_maxcontig blocks.  The end of one of these
  * 
  * If a section is already partially allocated, the policy is to
  * contiguously allocate fs_maxcontig blocks.  The end of one of these
@@ -293,7 +350,8 @@ blkpref(ip, lbn, indx, bap)
        daddr_t *bap;
 {
        register struct fs *fs;
        daddr_t *bap;
 {
        register struct fs *fs;
-       int cg, avgbfree;
+       register int cg;
+       int avgbfree, startcg;
        daddr_t nextblk;
 
        fs = ip->i_fs;
        daddr_t nextblk;
 
        fs = ip->i_fs;
@@ -306,13 +364,18 @@ blkpref(ip, lbn, indx, bap)
                 * Find a cylinder with greater than average number of
                 * unused data blocks.
                 */
                 * Find a cylinder with greater than average number of
                 * unused data blocks.
                 */
+               if (indx == 0 || bap[indx - 1] == 0)
+                       startcg = itog(fs, ip->i_number) + lbn / fs->fs_maxbpg;
+               else
+                       startcg = dtog(fs, bap[indx - 1]) + 1;
+               startcg %= fs->fs_ncg;
                avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg;
                avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg;
-               for (cg = fs->fs_cgrotor + 1; cg < fs->fs_ncg; cg++)
+               for (cg = startcg; cg < fs->fs_ncg; cg++)
                        if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
                                fs->fs_cgrotor = cg;
                                return (fs->fs_fpg * cg + fs->fs_frag);
                        }
                        if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
                                fs->fs_cgrotor = cg;
                                return (fs->fs_fpg * cg + fs->fs_frag);
                        }
-               for (cg = 0; cg <= fs->fs_cgrotor; cg++)
+               for (cg = 0; cg <= startcg; cg++)
                        if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
                                fs->fs_cgrotor = cg;
                                return (fs->fs_fpg * cg + fs->fs_frag);
                        if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
                                fs->fs_cgrotor = cg;
                                return (fs->fs_fpg * cg + fs->fs_frag);
@@ -698,10 +761,15 @@ ialloccg(ip, cg, ipref, mode)
        len = howmany(fs->fs_ipg - cgp->cg_irotor, NBBY);
        loc = skpc(0xff, len, &cgp->cg_iused[start]);
        if (loc == 0) {
        len = howmany(fs->fs_ipg - cgp->cg_irotor, NBBY);
        loc = skpc(0xff, len, &cgp->cg_iused[start]);
        if (loc == 0) {
-               printf("cg = %s, irotor = %d, fs = %s\n",
-                   cg, cgp->cg_irotor, fs->fs_fsmnt);
-               panic("ialloccg: map corrupted");
-               /* NOTREACHED */
+               len = start + 1;
+               start = 0;
+               loc = skpc(0xff, len, &cgp->cg_iused[0]);
+               if (loc == 0) {
+                       printf("cg = %s, irotor = %d, fs = %s\n",
+                           cg, cgp->cg_irotor, fs->fs_fsmnt);
+                       panic("ialloccg: map corrupted");
+                       /* NOTREACHED */
+               }
        }
        i = start + len - loc;
        map = cgp->cg_iused[i];
        }
        i = start + len - loc;
        map = cgp->cg_iused[i];
@@ -908,14 +976,14 @@ mapsearch(fs, cgp, bpref, allocsiz)
        if (loc == 0) {
                len = start + 1;
                start = 0;
        if (loc == 0) {
                len = start + 1;
                start = 0;
-               loc = scanc((unsigned)len, (caddr_t)&cgp->cg_free[start],
+               loc = scanc((unsigned)len, (caddr_t)&cgp->cg_free[0],
                        (caddr_t)fragtbl[fs->fs_frag],
                        (int)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY))));
                if (loc == 0) {
                        printf("start = %d, len = %d, fs = %s\n",
                            start, len, fs->fs_fsmnt);
                        panic("alloccg: map corrupted");
                        (caddr_t)fragtbl[fs->fs_frag],
                        (int)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY))));
                if (loc == 0) {
                        printf("start = %d, len = %d, fs = %s\n",
                            start, len, fs->fs_fsmnt);
                        panic("alloccg: map corrupted");
-                       return (-1);
+                       /* NOTREACHED */
                }
        }
        bno = (start + len - loc) * NBBY;
                }
        }
        bno = (start + len - loc) * NBBY;
@@ -952,5 +1020,5 @@ fserr(fs, cp)
        char *cp;
 {
 
        char *cp;
 {
 
-       printf("%s: %s\n", fs->fs_fsmnt, cp);
+       log(LOG_ERR, "%s: %s\n", fs->fs_fsmnt, cp);
 }
 }