From 2b08b32737c35fc914a6a5c1b1ea1251fb1c2b29 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 19 Mar 2011 19:37:36 +1100 Subject: [PATCH] show state command and library function Shows either a state block read of disk, or similar info for current filesystem. Signed-off-by: NeilBrown --- include/lafs/lafs.h | 2 ++ lib/lafs_alloc.c | 1 + lib/lafs_mount.c | 5 ++- lib/lafs_print_lafs.c | 26 ++++++++++++++ lib/lafs_print_state.c | 49 +++++++++++++++++++++++++++ tools/lafs.c | 77 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 lib/lafs_print_lafs.c create mode 100644 lib/lafs_print_state.c diff --git a/include/lafs/lafs.h b/include/lafs/lafs.h index eab5482..4181339 100644 --- a/include/lafs/lafs.h +++ b/include/lafs/lafs.h @@ -68,6 +68,8 @@ void lafs_segment_count(struct lafs *fs, loff_t addr, int diff); void lafs_print_device(struct lafs_device *dev); void lafs_print_devblock(struct lafs_dev *dev); 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); static inline struct lafs_dblk *dblk(struct lafs_blk *b) { diff --git a/lib/lafs_alloc.c b/lib/lafs_alloc.c index 6255c5d..148a58d 100644 --- a/lib/lafs_alloc.c +++ b/lib/lafs_alloc.c @@ -22,6 +22,7 @@ struct lafs *lafs_alloc(void) } memset(fs, 0, sizeof(*fs)); + fs->statesize = 1024; INIT_LIST_HEAD(&fs->wc[0].blocks); INIT_LIST_HEAD(&fs->wc[1].blocks); diff --git a/lib/lafs_mount.c b/lib/lafs_mount.c index 71c2e24..5be0527 100644 --- a/lib/lafs_mount.c +++ b/lib/lafs_mount.c @@ -92,7 +92,10 @@ char *lafs_mount(struct lafs *fs, int force) ssp = &fs->ss.next; for (s = 1; s < __le32_to_cpu(st->maxsnapshot); s++) { - struct lafs_snapshot *ss = talloc(fs, struct lafs_snapshot); + struct lafs_snapshot *ss; + if (st->root_inodes[s] == 0) + continue; + ss = talloc(fs, struct lafs_snapshot); ss->next = NULL; ss->root_addr = __le64_to_cpu(st->root_inodes[s]); ss->root = NULL; diff --git a/lib/lafs_print_lafs.c b/lib/lafs_print_lafs.c new file mode 100644 index 0000000..265506c --- /dev/null +++ b/lib/lafs_print_lafs.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include "internal.h" + +void lafs_print_lafs(struct lafs *fs) +{ + char uuidstr[37]; + int s; + struct lafs_snapshot *ss; + + printf("LaFS State:\n"); + printf(" Version : %.15s\n", fs->version); + uuid_unparse(fs->uuid, uuidstr); + printf(" UUID : %s\n", uuidstr); + printf(" Seq : %d\n", (int)fs->seq); + printf(" Devices : %d\n", fs->devices); + printf(" Loaded devs: %d\n", fs->loaded_devs); + printf(" BlockSize : %d\n", fs->blocksize); + printf(" StateSize : %d\n", fs->statesize); + printf(" MaxSegsize : %d\n", fs->max_segment); + printf(" CheckPoint : %llu\n", (unsigned long long)fs->checkpoint_cluster); + printf(" NextYouth : %d\n", fs->youth_next); + for (s= 0, ss = &fs->ss; ss ; ss = ss->next) + printf(" Root[%d] : %llu\n", s, (unsigned long long)ss->root_addr); +} diff --git a/lib/lafs_print_state.c b/lib/lafs_print_state.c new file mode 100644 index 0000000..d3c8b05 --- /dev/null +++ b/lib/lafs_print_state.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include "internal.h" + +void lafs_print_state(struct lafs_state *state, int size) +{ + char uuidstr[37]; + u32 crc, crc2; + int l; + int maxss; + + printf("Stateblock:\n"); + printf(" IDtag : %.16s\n", state->idtag); + printf(" Version : %.15s\n", state->version); + uuid_unparse(state->uuid, uuidstr); + printf(" UUID : %s\n", uuidstr); + printf(" Checksum : %08x", (int) __le32_to_cpu(state->checksum)); + crc = state->checksum; + state->checksum = 0; + crc2 = crc32(0, (uint32_t*)state, size); + state->checksum = crc; + if (crc2 == crc) + printf(" (correct)\n"); + else + printf(" (expected %08x)\n", (unsigned int)__le32_to_cpu(crc2)); + printf(" Seq : %d\n", (int)__le32_to_cpu(state->seq)); + printf(" Levels : %d\n", (int)__le32_to_cpu(state->levels)); + printf(" Devices : %d\n", (int)__le32_to_cpu(state->devices)); + printf(" MaxSnap : %d\n", (int)__le32_to_cpu(state->maxsnapshot)); + printf(" NextYouth : %d\n", (int)__le16_to_cpu(state->nextyouth)); + if (__le16_to_cpu(state->nonlog_dev) < 0xFFFF) { + printf(" NonLogSeg : %d\n", (int)__le32_to_cpu(state->nonlog_segment)); + printf(" NonLogDev : %d\n", (int)__le16_to_cpu(state->nonlog_dev)); + printf(" NonLogOff : %d\n", (int)__le16_to_cpu(state->nonlog_offset)); + } + + printf(" CheckPoint : %llu\n", + (unsigned long long)__le64_to_cpu(state->checkpointcluster)); + maxss = __le32_to_cpu(state->maxsnapshot); + if (maxss > (size - sizeof(*state)) / 4) + maxss = (size - sizeof(*state)) / 4; + for (l=0; l < maxss; l++) + printf(" Root[%d] : %llu\n", l+1, + (unsigned long long)__le64_to_cpu(state->root_inodes[l])); + + printf("\n"); +} + diff --git a/tools/lafs.c b/tools/lafs.c index 32e5de7..12a9cc3 100644 --- a/tools/lafs.c +++ b/tools/lafs.c @@ -1248,9 +1248,86 @@ static void c_show_device(struct state *st, void **args) lafs_print_device(dev); talloc_free(dev); } + +/****** SHOW STATE ******/ +static char help_show_state[] = "Show the current fs state or content of a state block"; +static struct args args_show_state[] = { + { "DEVNAME", external, -1, {NULL}, "Device to find state block on"}, + { "-file", external, 0, {NULL}, "File to read state block from"}, + { "-addr", opaque, -1, {NULL}, "Byte address to read block from"}, + TERMINAL_ARG +}; +static void c_show_state(struct state *st, void **args) +{ + char *devname; + long long addr; + struct lafs_device *dv; + struct lafs_state *state; + int fd; + + if (args[4] && !args[2]) { + printf("show state: Cannot give address without device name\n"); + return; + } + if (!args[2]) { + /* Show currently loaded state */ + if (!st->lafs->ss.root_addr) { + printf("show state: LaFS not mounted, no state available\n"); + return; + } + lafs_print_lafs(st->lafs); + return; + } + + devname = args[2]; + if (args[4]) { + char *addrstr = args[4]; + char *endp; + long long device_bytes = 0; + char *err; + + addr = strtoll(addrstr, &endp, 0); + if (endp == addrstr || *endp) { + printf("show state: %s is not a valid number\n", + addrstr); + return; + } + dv = NULL; + fd = open_device(devname, &device_bytes, args[3] != NULL, &err); + if (fd < 0) { + printf("show state: %s\n", err); + free(err); + return; + } + } else { + for (dv = st->lafs->devs; dv ; dv = dv->next) + if (strcmp(devname, dv->name) == 0) + break; + if (!dv) { + + printf("show state: device %s not loaded and no address given\n", + devname); + return; + } + fd = dv->fd; + addr = dv->stateaddr[dv->recent_state]; + } + state = malloc(st->lafs->statesize); + if (lseek64(fd, addr, 0) != addr || + read(fd, state, st->lafs->statesize) != st->lafs->statesize) { + printf("show state: cannot load state block\n"); + return; + } + lafs_print_state(state, st->lafs->statesize); + free(state); + if (!dv) + close(fd); +} + #define SCMD(x) {#x, c_show_##x, args_show_##x, help_show_##x} static struct cmd show_cmds[] = { SCMD(device), + SCMD(state), { NULL, NULL, NULL, NULL} }; -- 2.39.5