]> git.neil.brown.name Git - lafs-utils.git/commitdiff
Load and Print cluster header
authorNeilBrown <neilb@suse.de>
Fri, 25 Mar 2011 22:03:34 +0000 (09:03 +1100)
committerNeilBrown <neilb@suse.de>
Fri, 25 Mar 2011 22:03:34 +0000 (09:03 +1100)
Signed-off-by: NeilBrown <neilb@suse.de>
include/lafs/lafs.h
lib/lafs_cluster_flush.c
lib/lafs_load_cluster.c [new file with mode: 0644]
lib/lafs_print_cluster.c [new file with mode: 0644]
tools/lafs.c

index bee11fff4a0b8e962e1f8900be18cf0c709693c4..8525f432137bae8b726f8e41ffaf47db2e42fddd 100644 (file)
@@ -47,6 +47,7 @@ struct lafs_dblk *lafs_dblk(struct lafs_ino *ino,
 int lafs_load_dblk(struct lafs_dblk *);
 int lafs_find_dblk(struct lafs_dblk *);
 struct lafs_ino *lafs_import_inode(struct lafs_dblk *db);
+int lafs_load_cluster(struct lafs *fs, u64 addr, struct cluster_head **chp);
 
 int lafs_read_virtual(struct lafs *, char *, loff_t);
 int lafs_sched_blk(struct lafs_blk *);
@@ -57,6 +58,8 @@ int lafs_write_state(struct lafs *fs);
 int lafs_checkpoint(struct lafs *fs);
 void lafs_incorporate(struct lafs_iblk *ib);
 void lafs_cluster_allocate(struct lafs_blk *b, int cnum);
+int lafs_calc_cluster_csum(struct cluster_head *head);
+int lafs_load_cluster(struct lafs *fs, u64 addr, struct cluster_head **chp);
 void lafs_cluster_flush(struct lafs *fs, int cnum);
 void lafs_flush_inode(struct lafs_ino *inode);
 void lafs_flush(struct lafs *lafs);
@@ -76,6 +79,8 @@ char *lafs_mount(struct lafs *fs, int force);
 void lafs_print_state(struct lafs_state *state, int size);
 void lafs_print_lafs(struct lafs *fs);
 void lafs_print_inode(struct lafs_ino *ino);
+void lafs_print_cluster(struct cluster_head *head, int blocksize,
+                       int groups, int verbose);
 u32 lafs_find_next(struct lafs_ino *ino, u32 bnum);
 int lafs_hash_name(u32 seed, int len, const char *name);
 void lafs_dir_init_block(char *block, int psz, const char *name, int len,
index 2409d8a21a35c52c393a12c3d7653d4538e2b9d9..4412c39c97e07a9383f312e07187be0c317313db 100644 (file)
@@ -221,7 +221,7 @@ static void cluster_incdesc(struct lafs_cluster *wc, struct descriptor *desc_sta
 }
 
 
-static int calc_cluster_csum(struct cluster_head *head)
+int lafs_calc_cluster_csum(struct cluster_head *head)
 {
        unsigned int oldcsum = head->checksum;
        unsigned long long newcsum = 0;
@@ -317,7 +317,7 @@ void lafs_cluster_flush(struct lafs *fs, int cnum)
        ch->prev_addr = __cpu_to_le64(wc->prev_addr);
        wc->prev_addr = head_addr[i];
        ch->this_addr = __cpu_to_le64(wc->prev_addr);
-       ch->checksum = calc_cluster_csum(ch);
+       ch->checksum = lafs_calc_cluster_csum(ch);
 
        dv = dev_by_num(fs, wc->seg.dev);
 
diff --git a/lib/lafs_load_cluster.c b/lib/lafs_load_cluster.c
new file mode 100644 (file)
index 0000000..464d0d8
--- /dev/null
@@ -0,0 +1,58 @@
+#include <memory.h>
+#include <lafs/lafs.h>
+#include "internal.h"
+
+/* Load a cluster-header given a virtual device address.
+ * If the start looks OK, we load the full Hlength bytes in
+ * malloced space, otherwise just the header-header
+ *
+ * Return:
+ *   0 if all OK
+ *   1 if truncated
+ *  -1 if read error
+ */
+
+int lafs_load_cluster(struct lafs *fs, u64 addr, struct cluster_head **chp)
+{
+       char *buf = malloc(fs->blocksize);
+       struct cluster_head *ch;
+       int err;
+       int len;
+       int csum;
+       int blocks;
+       int i;
+
+       err = lafs_read_virtual(fs, buf, addr);
+       if (err) {
+               free(buf);
+               return -1;
+       }
+       ch = (void*)buf;
+       *chp = ch;
+       if (memcmp(ch->idtag, "LaFSHead", 8) != 0)
+               return 1;
+       if (memcmp(ch->uuid, fs->uuid, 16) != 0)
+               return 1;
+       if (__le64_to_cpu(ch->this_addr) != addr)
+               return 1;
+       len = __le16_to_cpu(ch->Hlength);
+       if (len < sizeof(*ch))
+               return 1;
+       blocks = (len + fs->blocksize-1) >> fs->blockbits;
+       if (blocks == 1)
+               return 0;
+       buf = realloc(buf, blocks << fs->blockbits);
+       for (i=1; i<blocks; i++)
+               if (lafs_read_virtual(fs, buf + i * fs->blocksize, addr+i)) {
+                       free(buf);
+                       return -1;
+               }
+       ch = (void*)buf;
+       *chp = ch;
+       csum = ch->checksum;
+       lafs_calc_cluster_csum(ch);
+       if (ch->checksum == csum)
+               return 0;
+       else
+               return 1;
+}
diff --git a/lib/lafs_print_cluster.c b/lib/lafs_print_cluster.c
new file mode 100644 (file)
index 0000000..4138ea7
--- /dev/null
@@ -0,0 +1,133 @@
+#include <stdio.h>
+#include <lafs/lafs.h>
+#include "internal.h"
+
+static char *VerifyNames[] = {"Null", "Next", "Next2", "Sum",};
+static char *FlagNames[] = {"Checkpoint","Start","End", NULL};
+
+void lafs_print_cluster(struct cluster_head *head, int blocksize,
+                       int groups, int verbose)
+{
+       struct group_head *gh;
+       struct miniblock *mb;
+       struct descriptor *desc;
+       u64 start;
+       int i;
+       long offset = 0;
+
+       if (verbose) {
+               printf("ClusterHead:\n");
+               printf(" IdTag     : %.8s\n", head->idtag);
+               printf(" Flags     :");
+               if (le32_to_cpu(head->flags)==0) printf(" -none-");
+               else for (i=0; FlagNames[i]; i++)
+                            if (le32_to_cpu(head->flags)&(1<<i))
+                                    printf(" %s", FlagNames[i]);
+               printf("\n");
+               printf(" Seq       : %llu\n", (unsigned long long)__le64_to_cpu(head->seq));
+               printf(" Hlength   : %d\n", (int)__le16_to_cpu(head->Hlength));
+               printf(" Clength   : %d\n", (int)__le16_to_cpu(head->Clength));
+               printf(" Checksum  : %08x\n", (unsigned int)le32_to_cpu(head->checksum));
+               printf(" Verify    : %s\n", VerifyNames[(int)__le16_to_cpu(head->verify_type)]);
+               printf(" NEXT      : %llu\n", (unsigned long long)__le64_to_cpu(head->next_addr));
+               printf(" THIS      : %llu\n", (unsigned long long)__le64_to_cpu(head->this_addr));
+               printf(" PREV      : %llu\n", (unsigned long long)__le64_to_cpu(head->prev_addr));
+       } else {
+               char *sep="";
+               printf("Cluster %llu(", (unsigned long long)__le64_to_cpu(head->seq));
+               for (i=0; FlagNames[i]; i++)
+                       if (le32_to_cpu(head->flags)&(1<<i)) {
+                               printf("%s%s", sep, FlagNames[i]);
+                               sep = ",";
+                       }
+               printf(") %llu < %llu > %llu\n",
+                      (unsigned long long)__le64_to_cpu(head->prev_addr),
+                      (unsigned long long)__le64_to_cpu(head->this_addr),
+                      (unsigned long long)__le64_to_cpu(head->next_addr));
+       }
+       if (!groups)
+               return;
+
+       start = __le64_to_cpu(head->this_addr);
+       offset = (__le16_to_cpu(head->Hlength)+blocksize-1)/blocksize;
+
+       gh = head->groups;
+       i = 0;
+       while ( ((char*)gh - (char*)head) < __le16_to_cpu(head->Hlength)) {
+               int j=0;
+               if (verbose) {
+                       printf(" Group[%d]:\n", i);
+                       printf("  Inum    : %d\n", (int)le32_to_cpu(gh->inum));
+                       printf("  FSnum   : %d\n", (int)le32_to_cpu(gh->fsnum));
+                       printf("  Flag    : %s\n", (__le16_to_cpu(gh->truncatenum_and_flag) & 0x8000) ? "old":"new");
+                       printf("  TRnum   : %d\n", (int)__le16_to_cpu(gh->truncatenum_and_flag) & 0x7fff);
+                       printf("  Size    : %d words\n", (int)__le16_to_cpu(gh->group_size_words));
+               } else
+                       printf(" Inode: %d/%d\n", (int)le32_to_cpu(gh->fsnum),
+                              (int)le32_to_cpu(gh->inum));
+               desc = gh->u.desc;
+               while (((char*)desc - (char*)gh) < __le16_to_cpu(gh->group_size_words)*4) {
+                       if (__le16_to_cpu(desc->block_bytes) <= DescMiniOffset ||
+                           __le16_to_cpu(desc->block_bytes) == DescIndex ) {
+                               char *typ;
+                               if (__le16_to_cpu(desc->block_bytes) != DescIndex)
+                                       typ = "Data";
+                               else
+                                       typ = "Index";
+                               if (verbose) {
+                                       printf("  Desc[%d]:\n", j);
+                                       printf("   Block   : %u\n", (unsigned)le32_to_cpu(desc->block_num));
+                                       printf("   Count   : %u\n", __le16_to_cpu(desc->block_cnt));
+                                       printf("   Type    : %s\n", typ);
+                                       printf("   Offset  : %ld (%llu)\n", offset,
+                                              (unsigned long long)start + offset);
+                               } else {
+                                       if (__le16_to_cpu(desc->block_cnt) == 1)
+                                               printf("  %s  : %u  (%llu)\n", typ,
+                                                      (unsigned)le32_to_cpu(desc->block_num),
+                                                      (unsigned long long)start + offset);
+                                       else
+                                               printf("  %s  : %u-%u  (%llu)\n", typ,
+                                                      (unsigned)le32_to_cpu(desc->block_num),
+                                                      (unsigned)le32_to_cpu(desc->block_num)
+                                                      + __le16_to_cpu(desc->block_cnt) - 1,
+                                                      (unsigned long long)start + offset);
+                               }
+                               offset += __le16_to_cpu(desc->block_cnt);
+                               desc++;
+                       } else {
+                               int len, k;
+                               mb = (struct miniblock *)desc;
+                               len = __le16_to_cpu(mb->length) - DescMiniOffset;
+                               if (verbose) {
+                                       printf("  MiniBlock[%d]:\n", j);
+                                       printf("   Block   : %u\n", (unsigned)le32_to_cpu(mb->block_num));
+                                       printf("   Offset  : %u\n", __le16_to_cpu(mb->block_offset));
+                                       printf("   length  : %u\n", len);
+                               } else
+                                       printf("  Update: %u+%u - %u bytes\n",
+                                              (unsigned)le32_to_cpu(mb->block_num),
+                                              __le16_to_cpu(mb->block_offset), len);
+                               mb++;
+                               if (verbose) {
+                                       printf("   Content : ");
+                                       for (k=0; k<len; k++) {
+                                               printf(" %02x", ((unsigned char*)mb)[k]);
+                                               if (k > 100) {
+                                                       printf(" .....");
+                                                       break;
+                                               }
+                                       }
+                                       printf("\n");
+                               }
+                               mb = (struct miniblock *)(((char*)mb) + ROUND_UP(len));
+                               desc = (struct descriptor *)mb;
+                       }
+                       j++;
+               }
+               gh = (struct group_head*)desc;
+               i++;
+       }
+       if (verbose)
+               printf(" Final Offset : %ld (next %llu)\n", offset, (unsigned long long)start+offset);
+}
index 6e5735d2f1cecfbd65f368eebb9c22c4a0a029ff..1a21b23131bf203ac6875892dc451825b0df3921 100644 (file)
@@ -1459,8 +1459,114 @@ static void c_show_state(struct state *st, void **args)
                close(fd);
 }
 
+/****** SHOW CLUSTER ******/
+static char help_show_cluster[] = "Show one or more cluster headers";
+static struct args args_show_cluster[] = {
+       { "ADDR", opaque, -1, {NULL}, "Virtual address of cluster to display"},
+       { "-verbose", flag, -1, {NULL}, "Show fine detail of descriptors"},
+       { "-segment", flag, -1, {NULL}, "Show all following clusters in segment"},
+       { "-checkpoint", flag, -1, {NULL},  "Show following clusters in checkpoint"},
+       { "-reverse", flag, -1, {NULL}, "Follow backward chain rather than forward"},
+       { "-n", opaque, -1, {NULL}, "Show this many clusters"},
+       TERMINAL_ARG
+};
+static void c_show_cluster(struct state *st, void **args)
+{
+       long long start, addr;
+       int again = 1;
+       int verbose = 0;
+       int cnt;
+       int max = 0;
+
+       if (!st->lafs->blocksize) {
+               printf("show cluster: lafs not ready to find clusters\n");
+               return;
+       }
+
+       if (args[2] == NULL)
+               start = st->lafs->checkpoint_cluster;
+       else {
+               char *addrstr = args[2];
+               char *endp;
+               start = strtoll(addrstr, &endp, 0);
+               if (endp == addrstr || *endp) {
+                       printf("show cluster: %s is not a valid address\n", addrstr);
+                       return;
+               }
+       }
+       if (args[7]) {
+               char *nstr = args[7];
+               char *endp;
+               max = strtoll(nstr, &endp, 0);
+               if (endp == nstr || *endp) {
+                       printf("show cluster: %s is not a valid number\n", nstr);
+                       return;
+               }
+       }
+
+       addr = start;
+       if (args[3])
+               verbose = 1;
+       while (again) {
+               struct cluster_head *ch;
+               long long prev;
+               int err = lafs_load_cluster(st->lafs, addr, &ch);
+               if (err < 0) {
+                       printf("show cluster: read error at %llu\n",
+                              (unsigned long long) addr);
+                       return;
+               }
+               if (err == 1) {
+                       if (verbose)
+                               lafs_print_cluster(ch, st->lafs->blocksize, 0, 1);
+                       printf("(bad cluster header)\n");
+                       free(ch);
+                       return;
+               }
+               lafs_print_cluster(ch, st->lafs->blocksize, 1, verbose);
+               cnt++;
+               prev = addr;
+               if (args[6])
+                       addr = __le64_to_cpu(ch->prev_addr);
+               else
+                       addr = __le64_to_cpu(ch->next_addr);
+               again = 0;
+               if (args[4]) {
+                       int dev1, dev2;
+                       loff_t seg1, seg2, off1, off2;
+                       virttoseg(st->lafs, start, &dev1, &seg1, &off1);
+                       virttoseg(st->lafs, addr, &dev2, &seg2, &off2);
+                       if (dev1 == dev2 && seg1 == seg2)
+                               again = 1;
+                       /* Avoid going in wrong direction */
+                       if (args[6]) {
+                               if (addr >= prev)
+                                       again = 0;
+                       } else {
+                               if (addr <= prev)
+                                       again = 0;
+                       }
+               }
+               if (args[5]) {
+                       int f = __le32_to_cpu(ch->flags);
+                       if (f & CH_Checkpoint) {
+                               if (args[6] && !(f & CH_CheckpointStart))
+                                       again = 1;
+                               if (!args[6] && !(f & CH_CheckpointEnd))
+                                       again = 1;
+                       }
+               }
+               if (max && cnt < max)
+                       again = 1;
+               if (addr == prev)
+                       again = 0;
+               free(ch);
+       }
+}
+
 #define SCMD(x) {#x, c_show_##x, args_show_##x, help_show_##x}
 static struct cmd show_cmds[] = {
+       SCMD(cluster),
        SCMD(device),
        SCMD(inode),
        SCMD(state),