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 *);
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);
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,
}
-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;
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);
--- /dev/null
+#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;
+}
--- /dev/null
+#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);
+}
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),