From: NeilBrown Date: Fri, 25 Mar 2011 22:03:34 +0000 (+1100) Subject: Load and Print cluster header X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=1726373f906e467252ebc36aebb9166b7139fe19;p=lafs-utils.git Load and Print cluster header Signed-off-by: NeilBrown --- diff --git a/include/lafs/lafs.h b/include/lafs/lafs.h index bee11ff..8525f43 100644 --- a/include/lafs/lafs.h +++ b/include/lafs/lafs.h @@ -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, diff --git a/lib/lafs_cluster_flush.c b/lib/lafs_cluster_flush.c index 2409d8a..4412c39 100644 --- a/lib/lafs_cluster_flush.c +++ b/lib/lafs_cluster_flush.c @@ -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 index 0000000..464d0d8 --- /dev/null +++ b/lib/lafs_load_cluster.c @@ -0,0 +1,58 @@ +#include +#include +#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; iblocksize, 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 index 0000000..4138ea7 --- /dev/null +++ b/lib/lafs_print_cluster.c @@ -0,0 +1,133 @@ +#include +#include +#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<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< %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 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); +} diff --git a/tools/lafs.c b/tools/lafs.c index 6e5735d..1a21b23 100644 --- a/tools/lafs.c +++ b/tools/lafs.c @@ -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),