expand lost+found when running out of space
authorKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Tue, 12 Feb 1985 12:55:35 +0000 (04:55 -0800)
committerKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Tue, 12 Feb 1985 12:55:35 +0000 (04:55 -0800)
SCCS-vsn: sbin/fsck/dir.c 3.5
SCCS-vsn: sbin/fsck/utilities.c 3.3

usr/src/sbin/fsck/dir.c
usr/src/sbin/fsck/utilities.c

index d697dca..2082201 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char version[] = "@(#)dir.c     3.4 (Berkeley) %G%";
+static char version[] = "@(#)dir.c     3.5 (Berkeley) %G%";
 #endif
 
 #include <sys/param.h>
 #endif
 
 #include <sys/param.h>
@@ -14,6 +14,7 @@ static char version[] = "@(#)dir.c    3.4 (Berkeley) %G%";
 
 char   *endpathname = &pathname[BUFSIZ - 2];
 char   *lfname = "lost+found";
 
 char   *endpathname = &pathname[BUFSIZ - 2];
 char   *lfname = "lost+found";
+struct dirtemplate emptydir = { 0, DIRBLKSIZ };
 
 DIRECT *fsck_readdir();
 
 
 DIRECT *fsck_readdir();
 
@@ -299,8 +300,8 @@ linkup(orphan, pdir)
                printf("\n\n");
                return (0);
        }
                printf("\n\n");
                return (0);
        }
-       if (fragoff(&sblock, dp->di_size)) {
-               dp->di_size = fragroundup(&sblock, dp->di_size);
+       if (dp->di_size % DIRBLKSIZ) {
+               dp->di_size = roundup(dp->di_size, DIRBLKSIZ);
                inodirty();
        }
        len = strlen(lfname);
                inodirty();
        }
        len = strlen(lfname);
@@ -312,7 +313,7 @@ linkup(orphan, pdir)
        idesc.id_filesize = dp->di_size;
        idesc.id_parent = orphan;       /* this is the inode to enter */
        idesc.id_fix = DONTKNOW;
        idesc.id_filesize = dp->di_size;
        idesc.id_parent = orphan;       /* this is the inode to enter */
        idesc.id_fix = DONTKNOW;
-       if ((ckinode(dp, &idesc) & ALTERED) == 0) {
+       if (makeentry(dp, &idesc) == 0) {
                pfatal("SORRY. NO SPACE IN lost+found DIRECTORY");
                printf("\n\n");
                return (0);
                pfatal("SORRY. NO SPACE IN lost+found DIRECTORY");
                printf("\n\n");
                return (0);
@@ -340,6 +341,73 @@ linkup(orphan, pdir)
        return (1);
 }
 
        return (1);
 }
 
+/*
+ * make an entry in a directory
+ */
+makeentry(dp, idesc)
+       DINODE *dp;
+       struct inodesc *idesc;
+{
+       
+       if ((ckinode(dp, idesc) & ALTERED) != 0)
+               return (1);
+       if (expanddir(dp) == 0)
+               return (0);
+       idesc->id_filesize = dp->di_size;
+       return (ckinode(dp, idesc) & ALTERED);
+}
+
+/*
+ * Attempt to expand the size of a directory
+ */
+expanddir(dp)
+       register DINODE *dp;
+{
+       daddr_t lastbn, newblk;
+       char *cp, firstblk[DIRBLKSIZ];
+
+       lastbn = lblkno(&sblock, dp->di_size);
+       if (lastbn >= NDADDR - 1)
+               return (0);
+       if ((newblk = allocblk(sblock.fs_frag)) == 0)
+               return (0);
+       dp->di_db[lastbn + 1] = dp->di_db[lastbn];
+       dp->di_db[lastbn] = newblk;
+       dp->di_size += sblock.fs_bsize;
+       dp->di_blocks += btodb(sblock.fs_bsize);
+       if (getblk(&fileblk, dp->di_db[lastbn + 1],
+           dblksize(&sblock, dp, lastbn + 1)) == NULL)
+               goto bad;
+       bcopy(dirblk.b_buf, firstblk, DIRBLKSIZ);
+       if (getblk(&fileblk, newblk, sblock.fs_bsize) == NULL)
+               goto bad;
+       bcopy(firstblk, dirblk.b_buf, DIRBLKSIZ);
+       for (cp = &dirblk.b_buf[DIRBLKSIZ];
+            cp < &dirblk.b_buf[sblock.fs_bsize];
+            cp += DIRBLKSIZ)
+               bcopy((char *)&emptydir, cp, sizeof emptydir);
+       dirty(&fileblk);
+       if (getblk(&fileblk, dp->di_db[lastbn + 1],
+           dblksize(&sblock, dp, lastbn + 1)) == NULL)
+               goto bad;
+       bcopy((char *)&emptydir, dirblk.b_buf, sizeof emptydir);
+       pwarn("NO SPACE LEFT IN %s", pathname);
+       if (preen)
+               printf(" (EXPANDED)\n");
+       else if (reply("EXPAND") == 0)
+               goto bad;
+       dirty(&fileblk);
+       inodirty();
+       return (1);
+bad:
+       dp->di_db[lastbn] = dp->di_db[lastbn + 1];
+       dp->di_db[lastbn + 1] = 0;
+       dp->di_size -= sblock.fs_bsize;
+       dp->di_blocks -= btodb(sblock.fs_bsize);
+       freeblk(newblk, sblock.fs_frag);
+       return (0);
+}
+
 /*
  * generate a temporary name for the lost+found directory.
  */
 /*
  * generate a temporary name for the lost+found directory.
  */
index 3d68b1e..646a86b 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char version[] = "@(#)utilities.c       3.2 (Berkeley) %G%";
+static char version[] = "@(#)utilities.c       3.3 (Berkeley) %G%";
 #endif
 
 #include <stdio.h>
 #endif
 
 #include <stdio.h>
@@ -178,6 +178,50 @@ bwrite(fcp, buf, blk, size)
        return (0);
 }
 
        return (0);
 }
 
+/*
+ * allocate a data block with the specified number of fragments
+ */
+allocblk(frags)
+       int frags;
+{
+       register int i, j, k;
+
+       if (frags <= 0 || frags > sblock.fs_frag)
+               return (0);
+       for (i = 0; i < fmax - sblock.fs_frag; i += sblock.fs_frag) {
+               for (j = 0; j <= sblock.fs_frag - frags; j++) {
+                       if (getbmap(i + j))
+                               continue;
+                       for (k = 1; k < frags; k++)
+                               if (getbmap(i + j + k))
+                                       break;
+                       if (k < frags) {
+                               j += k;
+                               continue;
+                       }
+                       for (k = 0; k < frags; k++)
+                               setbmap(i + j + k);
+                       n_blks += frags;
+                       return (i + j);
+               }
+       }
+       return (0);
+}
+
+/*
+ * Free a previously allocated block
+ */
+freeblk(blkno, frags)
+       daddr_t blkno;
+       int frags;
+{
+       struct inodesc idesc;
+
+       idesc.id_blkno = blkno;
+       idesc.id_numfrags = frags;
+       pass4check(&idesc);
+}
+
 catch()
 {
 
 catch()
 {