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); }