Adding WAPBL support for dumpfs(8)

next diffs:
- tunefs(8) showing log information and setting log size
- fsck_ffs(8) WAPBL support

ok jasper@


Index: sbin/dumpfs/dumpfs.c
===================================================================
RCS file: /Volumes/CSP/cvs/src/sbin/dumpfs/dumpfs.c,v
retrieving revision 1.32
diff -u -r1.32 dumpfs.c
--- sbin/dumpfs/dumpfs.c        20 Jan 2015 18:22:21 -0000      1.32
+++ sbin/dumpfs/dumpfs.c        28 Oct 2015 10:40:26 -0000
@@ -40,14 +40,18 @@
 
 #include <sys/param.h> /* DEV_BSIZE MAXBSIZE isset */
 #include <sys/time.h>
+#include <sys/wapbl.h>
+#include <sys/wapbl_replay.h>
 
 #include <ufs/ufs/dinode.h>
+#include <ufs/ufs/ufs_wapbl.h>
 #include <ufs/ffs/fs.h>
 
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <fstab.h>
+#include <stddef.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -68,12 +72,26 @@
 } cgun;
 #define acg    cgun.cg
 
-int    dumpfs(int, const char *);
-int    dumpcg(const char *, int, int);
-int    marshal(const char *);
-int    open_disk(const char *);
-void   pbits(void *, int);
-__dead void    usage(void);
+union {
+       struct wapbl_wc_header wh;
+       struct wapbl_wc_null wn;
+       char pad[MAXBSIZE];
+} jbuf;
+#define awh    jbuf.wh
+#define awn    jbuf.wn
+
+int dojournal = 0;
+
+int             dumpfs(int, const char *);
+int             dumpcg(const char *, int, int);
+int             marshal(const char *);
+int             open_disk(const char *);
+void            pbits(void *, int);
+int             print_journal(const char *, int);
+const char     *wapbl_type_string(unsigned);
+void            print_journal_header(const char *);
+off_t           print_journal_entries(const char *, size_t);
+__dead void     usage(void);
 
 int
 main(int argc, char *argv[])
@@ -84,8 +102,11 @@
 
        domarshal = eval = 0;
 
-       while ((ch = getopt(argc, argv, "m")) != -1) {
+       while ((ch = getopt(argc, argv, "jm")) != -1) {
                switch (ch) {
+               case 'j':       /* WAPBL journal */
+                       dojournal = 1;
+                       break;
                case 'm':
                        domarshal = 1;
                        break;
@@ -258,6 +279,15 @@
            afs.fs_cgrotor, afs.fs_fmod, afs.fs_ronly, afs.fs_clean);
        printf("avgfpdir %d\tavgfilesize %d\n",
            afs.fs_avgfpdir, afs.fs_avgfilesize);
+       if (dojournal) {
+               printf("wapbl version 0x%x\tlocation %u\tflags 0x%x\n",
+                   afs.fs_journal_version, afs.fs_journal_location,
+                   afs.fs_journal_flags);
+               printf("wapbl loc0 %llu\tloc1 %llu",
+                   afs.fs_journallocs[0], afs.fs_journallocs[1]);
+               printf("\tloc2 %llu\tloc3 %llu\n",
+                   afs.fs_journallocs[2], afs.fs_journallocs[3]);
+       }
        printf("flags\t");
        if (afs.fs_magic == FS_UFS2_MAGIC ||
            afs.fs_ffs1_flags & FS_FLAGS_UPDATED)
@@ -270,6 +300,8 @@
                printf("unclean ");
        if (fsflags & FS_DOSOFTDEP)
                printf("soft-updates ");
+       if (fsflags & FS_DOWAPBL)
+               printf("wapbl ");
        if (fsflags & FS_FLAGS_UPDATED)
                printf("updated ");
 #if 0
@@ -281,6 +313,10 @@
        printf("fsmnt\t%s\n", afs.fs_fsmnt);
        printf("volname\t%s\tswuid\t%ju\n",
                afs.fs_volname, (uintmax_t)afs.fs_swuid);
+       if (dojournal) {
+               printf("\n");
+               print_journal(name, fd);
+       }
        printf("\ncs[].cs_(nbfree,ndir,nifree,nffree):\n\t");
        afs.fs_csp = calloc(1, afs.fs_cssize);
        for (i = 0, j = 0; i < afs.fs_cssize; i += afs.fs_bsize, j++) {
@@ -457,9 +493,182 @@
        printf("\n");
 }
 
+int
+print_journal(const char *name, int fd)
+{
+       daddr_t off;
+       size_t count, blklen, bno, skip;
+       off_t boff, head, tail, len;
+       uint32_t generation;
+
+       if (afs.fs_journal_version != UFS_WAPBL_VERSION)
+               return 0;
+
+       generation = 0;
+       head = tail = 0;
+
+       switch (afs.fs_journal_location) {
+       case UFS_WAPBL_JOURNALLOC_END_PARTITION:
+       case UFS_WAPBL_JOURNALLOC_IN_FILESYSTEM:
+
+               off    = afs.fs_journallocs[0];
+               count  = afs.fs_journallocs[1];
+               blklen = afs.fs_journallocs[2];
+
+               for (bno=0; bno<count; bno += skip / blklen) {
+
+                       skip = blklen;
+
+                       boff = bno * blklen;
+                       if (bno * blklen >= 2 * blklen &&
+                         ((head >= tail && (boff < tail || boff >= head)) ||
+                         (head < tail && (boff >= head && boff < tail))))
+                               continue;
+
+                       printf("journal block %lu offset %lld\n",
+                               (unsigned long)bno, (long long) boff);
+
+                       if (lseek(fd, (off_t)(off*blklen) + boff, SEEK_SET)
+                           == (off_t)-1)
+                               return (1);
+                       if (read(fd, &jbuf, blklen) != (ssize_t)blklen) {
+                               warnx("%s: error reading journal", name);
+                               return 1;
+                       }
+
+                       switch (awh.wc_type) {
+                       case 0:
+                               break;
+                       case WAPBL_WC_HEADER:
+                               print_journal_header(name);
+                               if (awh.wc_generation > generation) {
+                                       head = awh.wc_head;
+                                       tail = awh.wc_tail;
+                               }
+                               generation = awh.wc_generation;
+                               skip = awh.wc_len;
+                               break;
+                       default:
+                               len = print_journal_entries(name, blklen);
+                               skip = awh.wc_len;
+                               if (len != (off_t)skip)
+                                       printf("  CORRUPTED RECORD\n");
+                               break;
+                       }
+
+                       if (blklen == 0)
+                               break;
+
+                       skip = (skip + blklen - 1) / blklen * blklen;
+                       if (skip == 0)
+                               break;
+
+               }
+               break;
+       }
+
+       return 0;
+}
+
+const char *
+wapbl_type_string(unsigned t)
+{
+       static char buf[12];
+
+       switch (t) {
+       case WAPBL_WC_BLOCKS:
+               return "blocks";
+       case WAPBL_WC_REVOCATIONS:
+               return "revocations";
+       case WAPBL_WC_INODES:
+               return "inodes";
+       case WAPBL_WC_HEADER:
+               return "header";
+       }
+
+       snprintf(buf,sizeof(buf),"%08x",t);
+       return buf;
+}
+
+void
+print_journal_header(const char *name)
+{
+       printf("  type %s len %d  version %u\n",
+               wapbl_type_string(awh.wc_type), awh.wc_len,
+               awh.wc_version);
+       printf("  checksum      %08x  generation %9u\n",
+               awh.wc_checksum, awh.wc_generation);
+       printf("  fsid %08x.%08x  time %llu nsec %u\n",
+               awh.wc_fsid[0], awh.wc_fsid[1],
+               (unsigned long long)awh.wc_time, awh.wc_timensec);
+       printf("  log_bshift  %10u  fs_bshift %10u\n",
+               awh.wc_log_dev_bshift, awh.wc_fs_dev_bshift);
+       printf("  head        %10lld  tail      %10lld\n",
+               (long long)awh.wc_head, (long long)awh.wc_tail);
+       printf("  circ_off    %10lld  circ_size %10lld\n",
+               (long long)awh.wc_circ_off, (long long)awh.wc_circ_size);
+}
+
+off_t
+print_journal_entries(const char *name, size_t blklen)
+{
+       int i, n;
+       struct wapbl_wc_blocklist *wcb;
+       struct wapbl_wc_inodelist *wci;
+       off_t len = 0;
+       int ph;
+
+       printf("  type %s len %d",
+               wapbl_type_string(awn.wc_type), awn.wc_len);
+
+       switch (awn.wc_type) {
+       case WAPBL_WC_BLOCKS:
+       case WAPBL_WC_REVOCATIONS:
+               wcb = (struct wapbl_wc_blocklist *)&awn;
+               printf("  blkcount %u\n", wcb->wc_blkcount);
+               ph = (blklen - offsetof(struct wapbl_wc_blocklist, wc_blocks))
+                       / sizeof(wcb->wc_blocks[0]);
+               n = MIN(wcb->wc_blkcount, ph);
+               for (i=0; i<n; i++) {
+                       if (/* verbose */ 1) {
+                               printf("  %3d: daddr %14llu  dlen %d\n", i,
+                                (unsigned long long)wcb->wc_blocks[i].wc_daddr,
+                                wcb->wc_blocks[i].wc_dlen);
+                       }
+                       len += wcb->wc_blocks[i].wc_dlen;
+               }
+               if (awn.wc_type == WAPBL_WC_BLOCKS) {
+                       if (len % blklen)
+                               len += blklen - len % blklen;
+               } else
+                       len = 0;
+               break;
+       case WAPBL_WC_INODES:
+               wci = (struct wapbl_wc_inodelist *)&awn;
+               printf("  count %u clear %u\n",
+                       wci->wc_inocnt, wci->wc_clear);
+               ph = (blklen - offsetof(struct wapbl_wc_inodelist, wc_inodes))
+                       / sizeof(wci->wc_inodes[0]);
+               n = MIN(wci->wc_inocnt, ph);
+               for (i=0; i<n; ++i) {
+                       if (/* verbose */ 1) {
+                               printf("  %3d: inumber %10u  imode %08x\n", i,
+                                       wci->wc_inodes[i].wc_inumber,
+                                       wci->wc_inodes[i].wc_imode);
+                       }
+               }
+               break;
+       default:
+               printf("\n");
+               break;
+       }
+
+       return len + blklen;
+}
+
 __dead void
 usage(void)
 {
-       (void)fprintf(stderr, "usage: dumpfs [-m] filesys | device\n");
+       (void)fprintf(stderr, "usage: dumpfs [-jm] filesys | device\n");
        exit(1);
 }

Reply via email to