Author: jeff
Date: Sat Apr 24 07:05:35 2010
New Revision: 207141
URL: http://svn.freebsd.org/changeset/base/207141

Log:
   - Merge soft-updates journaling from projects/suj/head into head.  This
     brings in support for an optional intent log which eliminates the need
     for background fsck on unclean shutdown.
  
  Sponsored by:   iXsystems, Yahoo!, and Juniper.
  With help from: McKusick and Peter Holm

Added:
  head/sbin/fsck_ffs/suj.c   (contents, props changed)
Modified:
  head/lib/libufs/Makefile
  head/lib/libufs/cgroup.c
  head/lib/libufs/inode.c
  head/lib/libufs/libufs.h
  head/lib/libufs/sblock.c
  head/lib/libufs/type.c
  head/sbin/dumpfs/dumpfs.c
  head/sbin/fsck_ffs/Makefile
  head/sbin/fsck_ffs/fsck.h
  head/sbin/fsck_ffs/gjournal.c
  head/sbin/fsck_ffs/main.c
  head/sbin/fsck_ffs/pass5.c
  head/sbin/fsdb/fsdb.c
  head/sbin/fsdb/fsdbutil.c
  head/sbin/tunefs/tunefs.8
  head/sbin/tunefs/tunefs.c
  head/sys/kern/vfs_bio.c
  head/sys/kern/vfs_subr.c
  head/sys/sys/buf.h
  head/sys/sys/mount.h
  head/sys/ufs/ffs/ffs_alloc.c
  head/sys/ufs/ffs/ffs_balloc.c
  head/sys/ufs/ffs/ffs_extern.h
  head/sys/ufs/ffs/ffs_inode.c
  head/sys/ufs/ffs/ffs_snapshot.c
  head/sys/ufs/ffs/ffs_softdep.c
  head/sys/ufs/ffs/ffs_subr.c
  head/sys/ufs/ffs/ffs_vfsops.c
  head/sys/ufs/ffs/ffs_vnops.c
  head/sys/ufs/ffs/fs.h
  head/sys/ufs/ffs/softdep.h
  head/sys/ufs/ufs/dinode.h
  head/sys/ufs/ufs/inode.h
  head/sys/ufs/ufs/ufs_dirhash.c
  head/sys/ufs/ufs/ufs_extern.h
  head/sys/ufs/ufs/ufs_lookup.c
  head/sys/ufs/ufs/ufs_vnops.c
  head/sys/ufs/ufs/ufsmount.h
  head/usr.sbin/makefs/ffs/ffs_bswap.c

Modified: head/lib/libufs/Makefile
==============================================================================
--- head/lib/libufs/Makefile    Sat Apr 24 05:03:42 2010        (r207140)
+++ head/lib/libufs/Makefile    Sat Apr 24 07:05:35 2010        (r207141)
@@ -3,7 +3,7 @@
 LIB=   ufs
 SHLIBDIR?= /lib
 
-SRCS=  block.c cgroup.c inode.c sblock.c type.c
+SRCS=  block.c cgroup.c inode.c sblock.c type.c ffs_subr.c ffs_tables.c
 INCS=  libufs.h
 
 MAN=   bread.3 cgread.3 libufs.3 sbread.3 ufs_disk_close.3
@@ -16,8 +16,11 @@ MLINKS+= ufs_disk_close.3 ufs_disk_fillo
 MLINKS+= ufs_disk_close.3 ufs_disk_fillout_blank.3
 MLINKS+= ufs_disk_close.3 ufs_disk_write.3
 
-WARNS?=        3
+.PATH:  ${.CURDIR}/../../sys/ufs/ffs
 
+WARNS?=        2
+
+DEBUG_FLAGS = -g
 CFLAGS+= -D_LIBUFS
 .if defined(LIBUFS_DEBUG)
 CFLAGS+= -D_LIBUFS_DEBUGGING

Modified: head/lib/libufs/cgroup.c
==============================================================================
--- head/lib/libufs/cgroup.c    Sat Apr 24 05:03:42 2010        (r207140)
+++ head/lib/libufs/cgroup.c    Sat Apr 24 07:05:35 2010        (r207141)
@@ -40,11 +40,143 @@ __FBSDID("$FreeBSD$");
 #include <errno.h>
 #include <fcntl.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include <libufs.h>
 
+ufs2_daddr_t
+cgballoc(struct uufsd *disk)
+{
+       u_int8_t *blksfree;
+       struct cg *cgp;
+       struct fs *fs;
+       long bno;
+
+       fs = &disk->d_fs;
+       cgp = &disk->d_cg;
+       blksfree = cg_blksfree(cgp);
+       for (bno = 0; bno < fs->fs_fpg / fs->fs_frag; bno++)
+               if (ffs_isblock(fs, blksfree, bno))
+                       goto gotit;
+       return (0);
+gotit:
+       fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--;
+       ffs_clrblock(fs, blksfree, (long)bno);
+       ffs_clusteracct(fs, cgp, bno, -1);
+       cgp->cg_cs.cs_nbfree--;
+       fs->fs_cstotal.cs_nbfree--;
+       fs->fs_fmod = 1;
+       return (cgbase(fs, cgp->cg_cgx) + blkstofrags(fs, bno));
+}
+
+int
+cgbfree(struct uufsd *disk, ufs2_daddr_t bno, long size)
+{
+       u_int8_t *blksfree;
+       struct fs *fs;
+       struct cg *cgp;
+       ufs1_daddr_t fragno, cgbno;
+       int i, cg, blk, frags, bbase;
+
+       fs = &disk->d_fs;
+       cg = dtog(fs, bno);
+       if (cgread1(disk, cg) != 1)
+               return (-1);
+       cgp = &disk->d_cg;
+       cgbno = dtogd(fs, bno);
+       blksfree = cg_blksfree(cgp);
+       if (size == fs->fs_bsize) {
+               fragno = fragstoblks(fs, cgbno);
+               ffs_setblock(fs, blksfree, fragno);
+               ffs_clusteracct(fs, cgp, fragno, 1);
+               cgp->cg_cs.cs_nbfree++;
+               fs->fs_cstotal.cs_nbfree++;
+               fs->fs_cs(fs, cg).cs_nbfree++;
+       } else {
+               bbase = cgbno - fragnum(fs, cgbno);
+               /*
+                * decrement the counts associated with the old frags
+                */
+               blk = blkmap(fs, blksfree, bbase);
+               ffs_fragacct(fs, blk, cgp->cg_frsum, -1);
+               /*
+                * deallocate the fragment
+                */
+               frags = numfrags(fs, size);
+               for (i = 0; i < frags; i++)
+                       setbit(blksfree, cgbno + i);
+               cgp->cg_cs.cs_nffree += i;
+               fs->fs_cstotal.cs_nffree += i;
+               fs->fs_cs(fs, cg).cs_nffree += i;
+               /*
+                * add back in counts associated with the new frags
+                */
+               blk = blkmap(fs, blksfree, bbase);
+               ffs_fragacct(fs, blk, cgp->cg_frsum, 1);
+               /*
+                * if a complete block has been reassembled, account for it
+                */
+               fragno = fragstoblks(fs, bbase);
+               if (ffs_isblock(fs, blksfree, fragno)) {
+                       cgp->cg_cs.cs_nffree -= fs->fs_frag;
+                       fs->fs_cstotal.cs_nffree -= fs->fs_frag;
+                       fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag;
+                       ffs_clusteracct(fs, cgp, fragno, 1);
+                       cgp->cg_cs.cs_nbfree++;
+                       fs->fs_cstotal.cs_nbfree++;
+                       fs->fs_cs(fs, cg).cs_nbfree++;
+               }
+       }
+       return cgwrite(disk);
+}
+
+ino_t
+cgialloc(struct uufsd *disk)
+{
+       struct ufs2_dinode *dp2;
+       u_int8_t *inosused;
+       struct cg *cgp;
+       struct fs *fs;
+       ino_t ino;
+       int i;
+
+       fs = &disk->d_fs;
+       cgp = &disk->d_cg;
+       inosused = cg_inosused(cgp);
+       for (ino = 0; ino < fs->fs_ipg / NBBY; ino++)
+               if (isclr(inosused, ino))
+                       goto gotit;
+       return (0);
+gotit:
+       if (fs->fs_magic == FS_UFS2_MAGIC &&
+           ino + INOPB(fs) > cgp->cg_initediblk &&
+           cgp->cg_initediblk < cgp->cg_niblk) {
+               char block[MAXBSIZE];
+               bzero(block, (int)fs->fs_bsize);
+               dp2 = (struct ufs2_dinode *)&block;
+               for (i = 0; i < INOPB(fs); i++) {
+                       dp2->di_gen = arc4random() / 2 + 1;
+                       dp2++;
+               }
+               if (bwrite(disk, ino_to_fsba(fs,
+                   cgp->cg_cgx * fs->fs_ipg + cgp->cg_initediblk),
+                   block, fs->fs_bsize))
+                       return (0);
+               cgp->cg_initediblk += INOPB(fs);
+       }
+
+       setbit(inosused, ino);
+       cgp->cg_irotor = ino;
+       cgp->cg_cs.cs_nifree--;
+       fs->fs_cstotal.cs_nifree--;
+       fs->fs_cs(fs, cgp->cg_cgx).cs_nifree--;
+       fs->fs_fmod = 1;
+
+       return (ino + (cgp->cg_cgx * fs->fs_ipg));
+}
+
 int
 cgread(struct uufsd *disk)
 {
@@ -55,14 +187,12 @@ int
 cgread1(struct uufsd *disk, int c)
 {
        struct fs *fs;
-       off_t ccg;
 
        fs = &disk->d_fs;
 
        if ((unsigned)c >= fs->fs_ncg) {
                return (0);
        }
-       ccg = fsbtodb(fs, cgtod(fs, c)) * disk->d_bsize;
        if (bread(disk, fsbtodb(fs, cgtod(fs, c)), disk->d_cgunion.d_buf,
            fs->fs_bsize) == -1) {
                ERROR(disk, "unable to read cylinder group");
@@ -73,6 +203,12 @@ cgread1(struct uufsd *disk, int c)
 }
 
 int
+cgwrite(struct uufsd *disk)
+{
+       return (cgwrite1(disk, disk->d_lcg));
+}
+
+int
 cgwrite1(struct uufsd *disk, int c)
 {
        struct fs *fs;

Modified: head/lib/libufs/inode.c
==============================================================================
--- head/lib/libufs/inode.c     Sat Apr 24 05:03:42 2010        (r207140)
+++ head/lib/libufs/inode.c     Sat Apr 24 07:05:35 2010        (r207141)
@@ -93,3 +93,19 @@ gotit:       switch (disk->d_ufs) {
        ERROR(disk, "unknown UFS filesystem type");
        return (-1);
 }
+
+int
+putino(struct uufsd *disk)
+{
+       struct fs *fs;
+
+       fs = &disk->d_fs;
+       if (disk->d_inoblock == NULL) {
+               ERROR(disk, "No inode block allocated");
+               return (-1);
+       }
+       if (bwrite(disk, fsbtodb(fs, ino_to_fsba(&disk->d_fs, disk->d_inomin)),
+           disk->d_inoblock, disk->d_fs.fs_bsize) <= 0)
+               return (-1);
+       return (0);
+}

Modified: head/lib/libufs/libufs.h
==============================================================================
--- head/lib/libufs/libufs.h    Sat Apr 24 05:03:42 2010        (r207140)
+++ head/lib/libufs/libufs.h    Sat Apr 24 07:05:35 2010        (r207141)
@@ -71,6 +71,7 @@ struct uufsd {
        int d_fd;               /* raw device file descriptor */
        long d_bsize;           /* device bsize */
        ufs2_daddr_t d_sblock;  /* superblock location */
+       struct csum *d_sbcsum;  /* Superblock summary info */
        caddr_t d_inoblock;     /* inode block */
        ino_t d_inomin;         /* low inode */
        ino_t d_inomax;         /* high inode */
@@ -109,14 +110,19 @@ int berase(struct uufsd *, ufs2_daddr_t,
 /*
  * cgroup.c
  */
+ufs2_daddr_t cgballoc(struct uufsd *);
+int cgbfree(struct uufsd *, ufs2_daddr_t, long);
+ino_t cgialloc(struct uufsd *);
 int cgread(struct uufsd *);
 int cgread1(struct uufsd *, int);
+int cgwrite(struct uufsd *);
 int cgwrite1(struct uufsd *, int);
 
 /*
  * inode.c
  */
 int getino(struct uufsd *, void **, ino_t, int *);
+int putino(struct uufsd *);
 
 /*
  * sblock.c
@@ -132,6 +138,16 @@ int ufs_disk_fillout(struct uufsd *, con
 int ufs_disk_fillout_blank(struct uufsd *, const char *);
 int ufs_disk_write(struct uufsd *);
 
+/*
+ * ffs_subr.c
+ */
+void   ffs_clrblock(struct fs *, u_char *, ufs1_daddr_t);
+void   ffs_clusteracct(struct fs *, struct cg *, ufs1_daddr_t, int);
+void   ffs_fragacct(struct fs *, int, int32_t [], int);
+int    ffs_isblock(struct fs *, u_char *, ufs1_daddr_t);
+int    ffs_isfreeblock(struct fs *, u_char *, ufs1_daddr_t);
+void   ffs_setblock(struct fs *, u_char *, ufs1_daddr_t);
+
 __END_DECLS
 
 #endif /* __LIBUFS_H__ */

Modified: head/lib/libufs/sblock.c
==============================================================================
--- head/lib/libufs/sblock.c    Sat Apr 24 05:03:42 2010        (r207140)
+++ head/lib/libufs/sblock.c    Sat Apr 24 07:05:35 2010        (r207141)
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
+#include <stdlib.h>
 #include <unistd.h>
 
 #include <libufs.h>
@@ -49,8 +50,11 @@ static int superblocks[] = SBLOCKSEARCH;
 int
 sbread(struct uufsd *disk)
 {
+       uint8_t block[MAXBSIZE];
        struct fs *fs;
        int sb, superblock;
+       int i, size, blks;
+       uint8_t *space;
 
        ERROR(disk, NULL);
 
@@ -86,6 +90,34 @@ sbread(struct uufsd *disk)
        }
        disk->d_bsize = fs->fs_fsize / fsbtodb(fs, 1);
        disk->d_sblock = superblock / disk->d_bsize;
+       /*
+        * Read in the superblock summary information.
+        */
+       size = fs->fs_cssize;
+       blks = howmany(size, fs->fs_fsize);
+       size += fs->fs_ncg * sizeof(int32_t);
+       space = malloc(size);
+       if (space == NULL) {
+               ERROR(disk, "failed to allocate space for summary information");
+               return (-1);
+       }
+       fs->fs_csp = (struct csum *)space;
+       for (i = 0; i < blks; i += fs->fs_frag) {
+               size = fs->fs_bsize;
+               if (i + fs->fs_frag > blks)
+                       size = (blks - i) * fs->fs_fsize;
+               if (bread(disk, fsbtodb(fs, fs->fs_csaddr + i), block, size)
+                   == -1) {
+                       ERROR(disk, "Failed to read sb summary information");
+                       free(fs->fs_csp);
+                       return (-1);
+               }
+               bcopy(block, space, size);
+               space += size;
+       }
+       fs->fs_maxcluster = (uint32_t *)space;
+       disk->d_sbcsum = fs->fs_csp;
+
        return (0);
 }
 
@@ -93,6 +125,8 @@ int
 sbwrite(struct uufsd *disk, int all)
 {
        struct fs *fs;
+       int blks, size;
+       uint8_t *space;
        unsigned i;
 
        ERROR(disk, NULL);
@@ -107,6 +141,22 @@ sbwrite(struct uufsd *disk, int all)
                ERROR(disk, "failed to write superblock");
                return (-1);
        }
+       /*
+        * Write superblock summary information.
+        */
+       blks = howmany(fs->fs_cssize, fs->fs_fsize);
+       space = (uint8_t *)disk->d_sbcsum;
+       for (i = 0; i < blks; i += fs->fs_frag) {
+               size = fs->fs_bsize;
+               if (i + fs->fs_frag > blks)
+                       size = (blks - i) * fs->fs_fsize;
+               if (bwrite(disk, fsbtodb(fs, fs->fs_csaddr + i), space, size)
+                   == -1) {
+                       ERROR(disk, "Failed to write sb summary information");
+                       return (-1);
+               }
+               space += size;
+       }
        if (all) {
                for (i = 0; i < fs->fs_ncg; i++)
                        if (bwrite(disk, fsbtodb(fs, cgsblock(fs, i)),

Modified: head/lib/libufs/type.c
==============================================================================
--- head/lib/libufs/type.c      Sat Apr 24 05:03:42 2010        (r207140)
+++ head/lib/libufs/type.c      Sat Apr 24 07:05:35 2010        (r207141)
@@ -66,6 +66,10 @@ ufs_disk_close(struct uufsd *disk)
                free((char *)(uintptr_t)disk->d_name);
                disk->d_name = NULL;
        }
+       if (disk->d_sbcsum != NULL) {
+               free(disk->d_sbcsum);
+               disk->d_sbcsum = NULL;
+       }
        return (0);
 }
 
@@ -156,6 +160,7 @@ again:      if ((ret = stat(name, &st)) < 0) 
        disk->d_mine = 0;
        disk->d_ufs = 0;
        disk->d_error = NULL;
+       disk->d_sbcsum = NULL;
 
        if (oname != name) {
                name = strdup(name);

Modified: head/sbin/dumpfs/dumpfs.c
==============================================================================
--- head/sbin/dumpfs/dumpfs.c   Sat Apr 24 05:03:42 2010        (r207140)
+++ head/sbin/dumpfs/dumpfs.c   Sat Apr 24 07:05:35 2010        (r207141)
@@ -238,7 +238,7 @@ dumpfs(const char *name)
        if (fsflags & FS_UNCLEAN)
                printf("unclean ");
        if (fsflags & FS_DOSOFTDEP)
-               printf("soft-updates ");
+               printf("soft-updates%s ", (fsflags & FS_SUJ) ? "+journal" : "");
        if (fsflags & FS_NEEDSFSCK)
                printf("needs fsck run ");
        if (fsflags & FS_INDEXDIRS)
@@ -255,7 +255,7 @@ dumpfs(const char *name)
                printf("nfsv4acls ");
        fsflags &= ~(FS_UNCLEAN | FS_DOSOFTDEP | FS_NEEDSFSCK | FS_INDEXDIRS |
                     FS_ACLS | FS_MULTILABEL | FS_GJOURNAL | FS_FLAGS_UPDATED |
-                    FS_NFS4ACLS);
+                    FS_NFS4ACLS | FS_SUJ);
        if (fsflags != 0)
                printf("unknown flags (%#x)", fsflags);
        putchar('\n');

Modified: head/sbin/fsck_ffs/Makefile
==============================================================================
--- head/sbin/fsck_ffs/Makefile Sat Apr 24 05:03:42 2010        (r207140)
+++ head/sbin/fsck_ffs/Makefile Sat Apr 24 07:05:35 2010        (r207141)
@@ -7,8 +7,7 @@ LINKS+= ${BINDIR}/fsck_ffs ${BINDIR}/fsc
 MAN=   fsck_ffs.8
 MLINKS=        fsck_ffs.8 fsck_ufs.8 fsck_ffs.8 fsck_4.2bsd.8
 SRCS=  dir.c ea.c fsutil.c inode.c main.c pass1.c pass1b.c pass2.c pass3.c \
-       pass4.c pass5.c setup.c utilities.c ffs_subr.c ffs_tables.c gjournal.c \
-       getmntopts.c
+       pass4.c pass5.c setup.c suj.c utilities.c gjournal.c getmntopts.c
 DPADD= ${LIBUFS}
 LDADD= -lufs
 WARNS?=        2

Modified: head/sbin/fsck_ffs/fsck.h
==============================================================================
--- head/sbin/fsck_ffs/fsck.h   Sat Apr 24 05:03:42 2010        (r207140)
+++ head/sbin/fsck_ffs/fsck.h   Sat Apr 24 07:05:35 2010        (r207141)
@@ -347,10 +347,6 @@ void               direrror(ino_t ino, const char *er
 int            dirscan(struct inodesc *);
 int            dofix(struct inodesc *, const char *msg);
 int            eascan(struct inodesc *, struct ufs2_dinode *dp);
-void           ffs_clrblock(struct fs *, u_char *, ufs1_daddr_t);
-void           ffs_fragacct(struct fs *, int, int32_t [], int);
-int            ffs_isblock(struct fs *, u_char *, ufs1_daddr_t);
-void           ffs_setblock(struct fs *, u_char *, ufs1_daddr_t);
 void           fileerror(ino_t cwd, ino_t ino, const char *errmesg);
 int            findino(struct inodesc *);
 int            findname(struct inodesc *);
@@ -392,3 +388,4 @@ void                sblock_init(void);
 void           setinodebuf(ino_t);
 int            setup(char *dev);
 void           gjournal_check(const char *filesys);
+int            suj_check(const char *filesys);

Modified: head/sbin/fsck_ffs/gjournal.c
==============================================================================
--- head/sbin/fsck_ffs/gjournal.c       Sat Apr 24 05:03:42 2010        
(r207140)
+++ head/sbin/fsck_ffs/gjournal.c       Sat Apr 24 07:05:35 2010        
(r207141)
@@ -96,27 +96,6 @@ struct ufs2_dinode ufs2_zino;
 static void putcgs(void);
 
 /*
- * Write current block of inodes.
- */
-static int
-putino(struct uufsd *disk, ino_t inode)
-{
-       caddr_t inoblock;
-       struct fs *fs;
-       ssize_t ret;
-
-       fs = &disk->d_fs;
-       inoblock = disk->d_inoblock;
-
-       assert(inoblock != NULL);
-       assert(inode >= disk->d_inomin && inode <= disk->d_inomax);
-       ret = bwrite(disk, fsbtodb(fs, ino_to_fsba(fs, inode)), inoblock,
-           fs->fs_bsize);
-
-       return (ret == -1 ? -1 : 0);
-}
-
-/*
  * Return cylinder group from the cache or load it if it is not in the
  * cache yet.
  * Don't cache more than MAX_CACHED_CGS cylinder groups.
@@ -242,13 +221,11 @@ cancelcgs(void)
 #endif
 
 /*
- * Open the given provider, load statistics.
+ * Open the given provider, load superblock.
  */
 static void
-getdisk(void)
+opendisk(void)
 {
-       int i;
-
        if (disk != NULL)
                return;
        disk = malloc(sizeof(*disk));
@@ -259,24 +236,6 @@ getdisk(void)
                    disk->d_error);
        }
        fs = &disk->d_fs;
-       fs->fs_csp = malloc((size_t)fs->fs_cssize);
-       if (fs->fs_csp == NULL)
-               err(1, "malloc(%zu)", (size_t)fs->fs_cssize);
-       bzero(fs->fs_csp, (size_t)fs->fs_cssize);
-       for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize) {
-               if (bread(disk, fsbtodb(fs, fs->fs_csaddr + numfrags(fs, i)),
-                   (void *)(((char *)fs->fs_csp) + i),
-                   (size_t)(fs->fs_cssize - i < fs->fs_bsize ? fs->fs_cssize - 
i : fs->fs_bsize)) == -1) {
-                       err(1, "bread: %s", disk->d_error);
-               }
-       }
-       if (fs->fs_contigsumsize > 0) {
-               fs->fs_maxcluster = malloc(fs->fs_ncg * sizeof(int32_t));
-               if (fs->fs_maxcluster == NULL)
-                       err(1, "malloc(%zu)", fs->fs_ncg * sizeof(int32_t));
-               for (i = 0; i < fs->fs_ncg; i++)
-                       fs->fs_maxcluster[i] = fs->fs_contigsumsize;
-       }
 }
 
 /*
@@ -286,11 +245,6 @@ static void
 closedisk(void)
 {
 
-       free(fs->fs_csp);
-       if (fs->fs_contigsumsize > 0) {
-               free(fs->fs_maxcluster);
-               fs->fs_maxcluster = NULL;
-       }
        fs->fs_clean = 1;
        if (sbwrite(disk, 0) == -1)
                err(1, "sbwrite(%s)", devnam);
@@ -301,227 +255,6 @@ closedisk(void)
        fs = NULL;
 }
 
-/*
- * Write the statistics back, call closedisk().
- */
-static void
-putdisk(void)
-{
-       int i;
-
-       assert(disk != NULL && fs != NULL);
-       for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize) {
-               if (bwrite(disk, fsbtodb(fs, fs->fs_csaddr + numfrags(fs, i)),
-                   (void *)(((char *)fs->fs_csp) + i),
-                   (size_t)(fs->fs_cssize - i < fs->fs_bsize ? fs->fs_cssize - 
i : fs->fs_bsize)) == -1) {
-                       err(1, "bwrite: %s", disk->d_error);
-               }
-       }
-       closedisk();
-}
-
-#if 0
-/*
- * Free memory, close the disk, but don't write anything back.
- */
-static void
-canceldisk(void)
-{
-       int i;
-
-       assert(disk != NULL && fs != NULL);
-       free(fs->fs_csp);
-       if (fs->fs_contigsumsize > 0)
-               free(fs->fs_maxcluster);
-       if (ufs_disk_close(disk) == -1)
-               err(1, "ufs_disk_close(%s)", devnam);
-       free(disk);
-       disk = NULL;
-       fs = NULL;
-}
-#endif
-
-static int
-isblock(unsigned char *cp, ufs1_daddr_t h)
-{
-       unsigned char mask;
-
-       switch ((int)fs->fs_frag) {
-       case 8:
-               return (cp[h] == 0xff);
-       case 4:
-               mask = 0x0f << ((h & 0x1) << 2);
-               return ((cp[h >> 1] & mask) == mask);
-       case 2:
-               mask = 0x03 << ((h & 0x3) << 1);
-               return ((cp[h >> 2] & mask) == mask);
-       case 1:
-               mask = 0x01 << (h & 0x7);
-               return ((cp[h >> 3] & mask) == mask);
-       default:
-               assert(!"isblock: invalid number of fragments");
-       }
-       return (0);
-}
-
-/*
- * put a block into the map
- */
-static void
-setblock(unsigned char *cp, ufs1_daddr_t h)
-{
-
-       switch ((int)fs->fs_frag) {
-       case 8:
-               cp[h] = 0xff;
-               return;
-       case 4:
-               cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
-               return;
-       case 2:
-               cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
-               return;
-       case 1:
-               cp[h >> 3] |= (0x01 << (h & 0x7));
-               return;
-       default:
-               assert(!"setblock: invalid number of fragments");
-       }
-}
-
-/*
- * check if a block is free
- */
-static int
-isfreeblock(u_char *cp, ufs1_daddr_t h)
-{
-
-       switch ((int)fs->fs_frag) {
-       case 8:
-               return (cp[h] == 0);
-       case 4:
-               return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0);
-       case 2:
-               return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0);
-       case 1:
-               return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0);
-       default:
-               assert(!"isfreeblock: invalid number of fragments");
-       }
-       return (0);
-}
-
-/*
- * Update the frsum fields to reflect addition or deletion
- * of some frags.
- */
-void
-fragacct(int fragmap, int32_t fraglist[], int cnt)
-{
-       int inblk;
-       int field, subfield;
-       int siz, pos;
-
-       inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
-       fragmap <<= 1;
-       for (siz = 1; siz < fs->fs_frag; siz++) {
-               if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
-                       continue;
-               field = around[siz];
-               subfield = inside[siz];
-               for (pos = siz; pos <= fs->fs_frag; pos++) {
-                       if ((fragmap & field) == subfield) {
-                               fraglist[siz] += cnt;
-                               pos += siz;
-                               field <<= siz;
-                               subfield <<= siz;
-                       }
-                       field <<= 1;
-                       subfield <<= 1;
-               }
-       }
-}
-
-static void
-clusteracct(struct cg *cgp, ufs1_daddr_t blkno)
-{
-       int32_t *sump;
-       int32_t *lp;
-       u_char *freemapp, *mapp;
-       int i, start, end, forw, back, map, bit;
-
-       if (fs->fs_contigsumsize <= 0)
-               return;
-       freemapp = cg_clustersfree(cgp);
-       sump = cg_clustersum(cgp);
-       /*
-        * Clear the actual block.
-        */
-       setbit(freemapp, blkno);
-       /*
-        * Find the size of the cluster going forward.
-        */
-       start = blkno + 1;
-       end = start + fs->fs_contigsumsize;
-       if (end >= cgp->cg_nclusterblks)
-               end = cgp->cg_nclusterblks;
-       mapp = &freemapp[start / NBBY];
-       map = *mapp++;
-       bit = 1 << (start % NBBY);
-       for (i = start; i < end; i++) {
-               if ((map & bit) == 0)
-                       break;
-               if ((i & (NBBY - 1)) != (NBBY - 1)) {
-                       bit <<= 1;
-               } else {
-                       map = *mapp++;
-                       bit = 1;
-               }
-       }
-       forw = i - start;
-       /*
-        * Find the size of the cluster going backward.
-        */
-       start = blkno - 1;
-       end = start - fs->fs_contigsumsize;
-       if (end < 0)
-               end = -1;
-       mapp = &freemapp[start / NBBY];
-       map = *mapp--;
-       bit = 1 << (start % NBBY);
-       for (i = start; i > end; i--) {
-               if ((map & bit) == 0)
-                       break;
-               if ((i & (NBBY - 1)) != 0) {
-                       bit >>= 1;
-               } else {
-                       map = *mapp--;
-                       bit = 1 << (NBBY - 1);
-               }
-       }
-       back = start - i;
-       /*
-        * Account for old cluster and the possibly new forward and
-        * back clusters.
-        */
-       i = back + forw + 1;
-       if (i > fs->fs_contigsumsize)
-               i = fs->fs_contigsumsize;
-       sump[i]++;
-       if (back > 0)
-               sump[back]--;
-       if (forw > 0)
-               sump[forw]--;
-       /*
-        * Update cluster summary information.
-        */
-       lp = &sump[fs->fs_contigsumsize];
-       for (i = fs->fs_contigsumsize; i > 0; i--)
-               if (*lp-- > 0)
-                       break;
-       fs->fs_maxcluster[cgp->cg_cgx] = i;
-}
-
 static void
 blkfree(ufs2_daddr_t bno, long size)
 {
@@ -539,10 +272,10 @@ blkfree(ufs2_daddr_t bno, long size)
        blksfree = cg_blksfree(cgp);
        if (size == fs->fs_bsize) {
                fragno = fragstoblks(fs, cgbno);
-               if (!isfreeblock(blksfree, fragno))
+               if (!ffs_isfreeblock(fs, blksfree, fragno))
                        assert(!"blkfree: freeing free block");
-               setblock(blksfree, fragno);
-               clusteracct(cgp, fragno);
+               ffs_setblock(fs, blksfree, fragno);
+               ffs_clusteracct(fs, cgp, fragno, 1);
                cgp->cg_cs.cs_nbfree++;
                fs->fs_cstotal.cs_nbfree++;
                fs->fs_cs(fs, cg).cs_nbfree++;
@@ -552,7 +285,7 @@ blkfree(ufs2_daddr_t bno, long size)
                 * decrement the counts associated with the old frags
                 */
                blk = blkmap(fs, blksfree, bbase);
-               fragacct(blk, cgp->cg_frsum, -1);
+               ffs_fragacct(fs, blk, cgp->cg_frsum, -1);
                /*
                 * deallocate the fragment
                 */
@@ -569,16 +302,16 @@ blkfree(ufs2_daddr_t bno, long size)
                 * add back in counts associated with the new frags
                 */
                blk = blkmap(fs, blksfree, bbase);
-               fragacct(blk, cgp->cg_frsum, 1);
+               ffs_fragacct(fs, blk, cgp->cg_frsum, 1);
                /*
                 * if a complete block has been reassembled, account for it
                 */
                fragno = fragstoblks(fs, bbase);
-               if (isblock(blksfree, fragno)) {
+               if (ffs_isblock(fs, blksfree, fragno)) {
                        cgp->cg_cs.cs_nffree -= fs->fs_frag;
                        fs->fs_cstotal.cs_nffree -= fs->fs_frag;
                        fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag;
-                       clusteracct(cgp, fragno);
+                       ffs_clusteracct(fs, cgp, fragno, 1);
                        cgp->cg_cs.cs_nbfree++;
                        fs->fs_cstotal.cs_nbfree++;
                        fs->fs_cs(fs, cg).cs_nbfree++;
@@ -599,7 +332,7 @@ freeindir(ufs2_daddr_t blk, int level)
        if (bread(disk, fsbtodb(fs, blk), (void *)&sblks, (size_t)fs->fs_bsize) 
== -1)
                err(1, "bread: %s", disk->d_error);
        blks = (ufs2_daddr_t *)&sblks;
-       for (i = 0; i < howmany(fs->fs_bsize, sizeof(ufs2_daddr_t)); i++) {
+       for (i = 0; i < NINDIR(fs); i++) {
                if (blks[i] == 0)
                        break;
                if (level == 0)
@@ -671,7 +404,7 @@ gjournal_check(const char *filesys)
        int cg, mode;
 
        devnam = filesys;
-       getdisk();
+       opendisk();
        /* Are there any unreferenced inodes in this file system? */
        if (fs->fs_unrefs == 0) {
                //printf("No unreferenced inodes.\n");
@@ -747,7 +480,7 @@ gjournal_check(const char *filesys)
                        /* Zero-fill the inode. */
                        *dino = ufs2_zino;
                        /* Write the inode back. */
-                       if (putino(disk, ino) == -1)
+                       if (putino(disk) == -1)
                                err(1, "putino(cg=%d ino=%d)", cg, ino);
                        if (cgp->cg_unrefs == 0) {
                                //printf("No more unreferenced inodes in 
cg=%d.\n", cg);
@@ -772,5 +505,5 @@ gjournal_check(const char *filesys)
        /* Write back modified cylinder groups. */
        putcgs();
        /* Write back updated statistics and super-block. */
-       putdisk();
+       closedisk();
 }

Modified: head/sbin/fsck_ffs/main.c
==============================================================================
--- head/sbin/fsck_ffs/main.c   Sat Apr 24 05:03:42 2010        (r207140)
+++ head/sbin/fsck_ffs/main.c   Sat Apr 24 07:05:35 2010        (r207141)
@@ -242,8 +242,9 @@ checkfilesys(char *filesys)
                if ((fsreadfd = open(filesys, O_RDONLY)) < 0 || readsb(0) == 0)
                        exit(3);        /* Cannot read superblock */
                close(fsreadfd);
-               if (sblock.fs_flags & FS_NEEDSFSCK)
-                       exit(4);        /* Earlier background failed */
+               /* Earlier background failed or journaled */
+               if (sblock.fs_flags & (FS_NEEDSFSCK | FS_SUJ))
+                       exit(4);
                if ((sblock.fs_flags & FS_DOSOFTDEP) == 0)
                        exit(5);        /* Not running soft updates */
                size = MIBSIZE;
@@ -299,7 +300,7 @@ checkfilesys(char *filesys)
                        pfatal("MOUNTED READ-ONLY, CANNOT RUN IN BACKGROUND\n");
                } else if ((fsreadfd = open(filesys, O_RDONLY)) >= 0) {
                        if (readsb(0) != 0) {
-                               if (sblock.fs_flags & FS_NEEDSFSCK) {
+                               if (sblock.fs_flags & (FS_NEEDSFSCK | FS_SUJ)) {
                                        bkgrdflag = 0;
                                        pfatal("UNEXPECTED INCONSISTENCY, %s\n",
                                            "CANNOT RUN IN BACKGROUND\n");
@@ -384,6 +385,26 @@ checkfilesys(char *filesys)
                    sblock.fs_cstotal.cs_nffree * 100.0 / sblock.fs_dsize);
                return (0);
        }
+       /*
+        * Determine if we can and should do journal recovery.
+        */
+       if ((sblock.fs_flags & (FS_SUJ | FS_NEEDSFSCK)) == FS_SUJ) {
+               if (preen || reply("USE JOURNAL?")) {
+                       if (suj_check(filesys) == 0) {
+                               if (chkdoreload(mntp) == 0)
+                                       exit(0);
+                               exit(4);
+                       }
+                       /* suj_check failed, fall through. */
+               }
+               printf("** Skipping journal, falling through to full fsck\n");
+               /*
+                * Write the superblock so we don't try to recover the
+                * journal on another pass.
+                */
+               sblock.fs_mtime = time(NULL);
+               sbdirty();
+       }
        
        /*
         * Cleared if any questions answered no. Used to decide if

Modified: head/sbin/fsck_ffs/pass5.c
==============================================================================
--- head/sbin/fsck_ffs/pass5.c  Sat Apr 24 05:03:42 2010        (r207140)
+++ head/sbin/fsck_ffs/pass5.c  Sat Apr 24 07:05:35 2010        (r207141)
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
 #include <inttypes.h>
 #include <limits.h>
 #include <string.h>
+#include <libufs.h>
 
 #include "fsck.h"
 

Added: head/sbin/fsck_ffs/suj.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sbin/fsck_ffs/suj.c    Sat Apr 24 07:05:35 2010        (r207141)
@@ -0,0 +1,4699 @@
+/*-
+ * Copyright 2009, 2010 Jeffrey W. Roberson <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+
+#include <ufs/ufs/ufsmount.h>
+#include <ufs/ufs/dinode.h>
+#include <ufs/ufs/dir.h>
+#include <ufs/ffs/fs.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <libufs.h>
+#include <string.h>
+#include <strings.h>
+#include <err.h>
+#include <assert.h>
+
+#include "fsck.h"
+
+#define        DOTDOT_OFFSET   DIRECTSIZ(1)
+#define        SUJ_HASHSIZE    2048
+#define        SUJ_HASHMASK    (SUJ_HASHSIZE - 1)
+#define        SUJ_HASH(x)     ((x * 2654435761) & SUJ_HASHMASK)
+
+struct suj_seg {
+       TAILQ_ENTRY(suj_seg) ss_next;
+       struct jsegrec  ss_rec;
+       uint8_t         *ss_blk;
+};
+
+struct suj_rec {
+       TAILQ_ENTRY(suj_rec) sr_next;
+       union jrec      *sr_rec;
+};
+TAILQ_HEAD(srechd, suj_rec);
+
+struct suj_ino {
+       LIST_ENTRY(suj_ino)     si_next;
+       struct srechd           si_recs;
+       struct srechd           si_newrecs;
+       struct srechd           si_movs;
+       struct jtrncrec         *si_trunc;
+       ino_t                   si_ino;
+       char                    si_skipparent;
+       char                    si_hasrecs;
+       char                    si_blkadj;
+       char                    si_linkadj;
+       int                     si_mode;
+       nlink_t                 si_nlinkadj;
+       nlink_t                 si_nlink;
+       nlink_t                 si_dotlinks;
+};
+LIST_HEAD(inohd, suj_ino);
+
+struct suj_blk {
+       LIST_ENTRY(suj_blk)     sb_next;
+       struct srechd           sb_recs;
+       ufs2_daddr_t            sb_blk;
+};
+LIST_HEAD(blkhd, suj_blk);
+
+struct data_blk {
+       LIST_ENTRY(data_blk)    db_next;
+       uint8_t                 *db_buf;
+       ufs2_daddr_t            db_blk;
+       int                     db_size;
+       int                     db_dirty;
+};
+
+struct ino_blk {
+       LIST_ENTRY(ino_blk)     ib_next;
+       uint8_t                 *ib_buf;
+       int                     ib_dirty;
+       ufs2_daddr_t            ib_blk;
+};
+LIST_HEAD(iblkhd, ino_blk);
+
+struct suj_cg {
+       LIST_ENTRY(suj_cg)      sc_next;
+       struct blkhd            sc_blkhash[SUJ_HASHSIZE];
+       struct inohd            sc_inohash[SUJ_HASHSIZE];
+       struct iblkhd           sc_iblkhash[SUJ_HASHSIZE];
+       struct ino_blk          *sc_lastiblk;
+       struct suj_ino          *sc_lastino;
+       struct suj_blk          *sc_lastblk;
+       uint8_t                 *sc_cgbuf;
+       struct cg               *sc_cgp;
+       int                     sc_dirty;
+       int                     sc_cgx;
+};
+

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to