Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=a26... Commit: a26a9856c295be1de37186299eb52034a1c9cd66 Parent: baea48ccc79bbc3ef2723c2eae26b1d144dea645 Author: Bob Peterson rpeterso@redhat.com AuthorDate: Thu Dec 17 17:15:49 2009 -0600 Committer: Bob Peterson rpeterso@redhat.com CommitterDate: Thu Dec 17 17:15:49 2009 -0600
GFS2: gfs2_edit savemeta bugs
This patch fixes a problem whereby directory hash tables were not being saved by gfs2_edit's savemeta option. Also, this introduces a new option to print individual records from a savemeta file: gfs2_edit printsavedmeta /home/bob/my.meta 0x12345
rhbz#528786 --- gfs2/edit/hexedit.c | 30 ++++---- gfs2/edit/hexedit.h | 7 ++- gfs2/edit/savemeta.c | 190 ++++++++++++++++++++++++++------------------------ 3 files changed, 119 insertions(+), 108 deletions(-)
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c index 8ba3d03..b6b8fe9 100644 --- a/gfs2/edit/hexedit.c +++ b/gfs2/edit/hexedit.c @@ -37,10 +37,6 @@ const char *allocdesc[2][5] = { #define RGLIST_DUMMY_BLOCK -2
int display(int identify_only); -extern void do_leaf_extended(char *buf, struct iinfo *indir); -extern void savemeta(char *out_fn, int slow); -extern void restoremeta(const char *in_fn, const char *out_device, - int printblocksonly);
/* for assigning numeric fields: */ #define checkassign(strfield, struct, member, value) do { \ @@ -1816,8 +1812,7 @@ int display(int identify_only) if (read(sbd.device_fd, buf, sbd.bsize) != sbd.bsize) { fprintf(stderr, "read error: %s from %s:%d: " "offset %lld (0x%llx)\n", - strerror(errno), __FUNCTION__, - __LINE__, + strerror(errno), __FUNCTION__, __LINE__, (unsigned long long)dev_offset, (unsigned long long)dev_offset); exit(-1); @@ -2144,7 +2139,7 @@ static uint64_t find_metablockoftype(const char *strtype, int print) /* Check if the word is a keyword such as "sb" or "rindex" */ /* Returns: block number if it is, else 0 */ /* ------------------------------------------------------------------------ */ -static uint64_t check_keywords(const char *kword) +uint64_t check_keywords(const char *kword) { uint64_t blk = 0;
@@ -3251,17 +3246,22 @@ static void parameterpass1(int argc, char *argv[], int i) termlines = 0; else if (!strcasecmp(argv[i], "savergs")) termlines = 0; - else if (!strcasecmp(argv[i], "printsavedmeta")) - restoremeta(argv[i+1], argv[i+2], - TRUE); - else if (!strcasecmp(argv[i], "restoremeta")) + else if (!strcasecmp(argv[i], "printsavedmeta")) { + if (dmode == INIT_MODE) + dmode = GFS2_MODE; + restoremeta(argv[i+1], argv[i+2], TRUE); + } else if (!strcasecmp(argv[i], "restoremeta")) { + if (dmode == INIT_MODE) + dmode = HEX_MODE; /* hopefully not used */ restoremeta(argv[i+1], argv[i+2], FALSE); - else if (!strcmp(argv[i], "rgcount")) + } else if (!strcmp(argv[i], "rgcount")) termlines = 0; else if (!strcmp(argv[i], "rgflags")) termlines = 0; else if (!strcmp(argv[i], "rg")) termlines = 0; + else if (!strcasecmp(argv[i], "-x")) + dmode = HEX_MODE; else if (!device[0] && strchr(argv[i],'/')) strcpy(device, argv[i]); } @@ -3460,12 +3460,12 @@ int main(int argc, char *argv[]) memset(edit_col, 0, sizeof(edit_col)); memset(edit_size, 0, sizeof(edit_size)); memset(last_entry_onscreen, 0, sizeof(last_entry_onscreen)); - dmode = HEX_MODE; + dmode = INIT_MODE; sbd.bsize = 4096; type_alloc(buf, char, sbd.bsize); /* allocate/malloc a new 4K buffer */ block = starting_blk = 0x10; for (i = 0; i < BLOCK_STACK_SIZE; i++) { - blockstack[i].dmode = dmode; + blockstack[i].dmode = HEX_MODE; blockstack[i].block = block; for (j = 0; j < DMODES; j++) { blockstack[i].start_row[j] = 0; @@ -3481,6 +3481,8 @@ int main(int argc, char *argv[]) memset(device, 0, sizeof(device)); termlines = 30; /* assume interactive mode until we find -p */ process_parameters(argc, argv, 0); + if (dmode == INIT_MODE) + dmode = HEX_MODE;
fd = open(device, O_RDWR); if (fd < 0) diff --git a/gfs2/edit/hexedit.h b/gfs2/edit/hexedit.h index e4b0ea1..88964a2 100644 --- a/gfs2/edit/hexedit.h +++ b/gfs2/edit/hexedit.h @@ -18,7 +18,7 @@ #endif
#define DMODES 3 -enum dsp_mode { HEX_MODE = 0, GFS2_MODE = 1, EXTENDED_MODE = 2 }; +enum dsp_mode { HEX_MODE = 0, GFS2_MODE = 1, EXTENDED_MODE = 2, INIT_MODE = 3 }; #define BLOCK_STACK_SIZE 256
#define GFS_FORMAT_SB (100) /* Super-Block */ @@ -159,8 +159,11 @@ extern void gfs_jindex_in(struct gfs_jindex *jindex, char *buf); extern void gfs_log_header_in(struct gfs_log_header *head, char *buf); extern void gfs_log_header_print(struct gfs_log_header *lh); extern void gfs_dinode_in(struct gfs_dinode *di, char *buf); +extern int display(int identify_only); +extern uint64_t check_keywords(const char *kword); extern void savemeta(char *out_fn, int saveoption); -extern void restoremeta(const char *in_fn, const char *out_device, int printblocksonly); +extern void restoremeta(const char *in_fn, const char *out_device, + uint64_t printblocksonly); extern uint64_t masterblock(const char *fn);
struct gfs2_dirents { diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c index cfe8f82..85fcde7 100644 --- a/gfs2/edit/savemeta.c +++ b/gfs2/edit/savemeta.c @@ -84,13 +84,7 @@ static int get_gfs_struct_info(char *gbuf, int *block_type, int *gstruct_len) *gstruct_len = sbd.bsize; /*sizeof(struct gfs_leaf);*/ break; case GFS2_METATYPE_JD: /* 7 (journal data) */ - /* GFS1 keeps indirect pointers in GFS2_METATYPE_JD blocks - so we need to save the whole block. For GFS2, we don't - want to, or we might capture user data, which is bad. */ - if (gfs1) - *gstruct_len = sbd.bsize; - else - *gstruct_len = sizeof(struct gfs2_meta_header); + *gstruct_len = sbd.bsize; break; case GFS2_METATYPE_LH: /* 8 (log header) */ if (gfs1) @@ -358,8 +352,15 @@ static void save_inode_data(int out_fd) height = inode->i_di.di_height; /* If this is a user inode, we don't follow to the file height. We stop one level less. That way we save off the indirect - pointer blocks but not the actual file contents. */ - if (height && !block_is_systemfile()) + pointer blocks but not the actual file contents. The exception + is directories, where the height represents the level at which + the hash table exists, and we have to save the directory data. */ + if (inode->i_di.di_flags & GFS2_DIF_EXHASH && + (S_ISDIR(inode->i_di.di_mode) || + (gfs1 && inode->i_di.__pad1 == GFS_FILE_DIR))) + height++; + else if (height && !block_is_systemfile() && + !S_ISDIR(inode->i_di.di_mode)) height--; osi_list_add(&metabh->b_altlist, &metalist[0]); for (i = 1; i <= height; i++){ @@ -787,95 +788,98 @@ static int restore_data(int fd, int in_fd, int printblocksonly) } rs = read(in_fd, &buf16, sizeof(uint16_t)); savedata->siglen = be16_to_cpu(buf16); - if (savedata->siglen <= sizeof(savedata->buf)) { - if (savedata->siglen && - read(in_fd, savedata->buf, savedata->siglen) != - savedata->siglen) { - fprintf(stderr, "read error: %s from %s:%d: " - "block %lld (0x%llx)\n", - strerror(errno), __FUNCTION__, - __LINE__, - (unsigned long long)savedata->blk, - (unsigned long long)savedata->blk); - exit(-1); + if (savedata->siglen > sizeof(savedata->buf)) { + fprintf(stderr, "\nBad record length: %d for block #%" + PRIu64 " (0x%" PRIx64").\n", savedata->siglen, + savedata->blk, savedata->blk); + return -1; + } + if (savedata->siglen && + read(in_fd, savedata->buf, savedata->siglen) != + savedata->siglen) { + fprintf(stderr, "read error: %s from %s:%d: " + "block %lld (0x%llx)\n", + strerror(errno), __FUNCTION__, __LINE__, + (unsigned long long)savedata->blk, + (unsigned long long)savedata->blk); + exit(-1); + } + if (first) { + struct gfs2_sb bufsb; + + memcpy(&bufsb, savedata->buf, sizeof(bufsb)); + gfs2_sb_in(&sbd.sd_sb, (void *)&bufsb); + sbd1 = (struct gfs_sb *)&sbd.sd_sb; + if (sbd1->sb_fs_format == GFS_FORMAT_FS && + sbd1->sb_header.mh_type == + GFS_METATYPE_SB && + sbd1->sb_header.mh_format == + GFS_FORMAT_SB && + sbd1->sb_multihost_format == + GFS_FORMAT_MULTI) { + gfs1 = TRUE; + } else if (check_sb(&sbd.sd_sb)) { + fprintf(stderr,"Error: Invalid superblock data.\n"); + return -1; } - if (first) { - struct gfs2_sb bufsb; - - memcpy(&bufsb, savedata->buf, sizeof(bufsb)); - gfs2_sb_in(&sbd.sd_sb, (void *)&bufsb); - sbd1 = (struct gfs_sb *)&sbd.sd_sb; - if (sbd1->sb_fs_format == GFS_FORMAT_FS && - sbd1->sb_header.mh_type == - GFS_METATYPE_SB && - sbd1->sb_header.mh_format == - GFS_FORMAT_SB && - sbd1->sb_multihost_format == - GFS_FORMAT_MULTI) { - gfs1 = TRUE; - } else if (check_sb(&sbd.sd_sb)) { - fprintf(stderr,"Error: Invalid superblock data.\n"); - return -1; - } - sbd.bsize = sbd.sd_sb.sb_bsize; - if (!printblocksonly) { - last_fs_block = - lseek(fd, 0, SEEK_END) / - sbd.bsize; - printf("There are %" PRIu64 " blocks of " \ - "%u bytes in the destination" \ - " file system.\n\n", - last_fs_block, sbd.bsize); - } else { - printf("This is %s metadata\n", gfs1 ? - "gfs (not gfs2)" : "gfs2"); - } - first = 0; + sbd.bsize = sbd.sd_sb.sb_bsize; + if (!printblocksonly) { + last_fs_block = + lseek(fd, 0, SEEK_END) / sbd.bsize; + printf("There are %" PRIu64 " blocks of " \ + "%u bytes in the destination" \ + " file system.\n\n", + last_fs_block, sbd.bsize); + } else { + printf("This is %s metadata\n", gfs1 ? + "gfs (not gfs2)" : "gfs2"); } - if (printblocksonly) { + first = 0; + } + if (printblocksonly) { + block = savedata->blk; + if (block > highest_valid_block) + highest_valid_block = block; + if (printblocksonly > 1 && printblocksonly == block) { + memcpy(buf, savedata->buf, sbd.bsize); + block_in_mem = block; + display(0); + return 0; + } else if (printblocksonly == 1) { print_gfs2("%d (l=0x%x): ", blks_saved, savedata->siglen); - block = savedata->blk; - if (block > highest_valid_block) - highest_valid_block = block; display_block_type(savedata->buf, TRUE); - } else { - warm_fuzzy_stuff(savedata->blk, FALSE, FALSE); - if (savedata->blk >= last_fs_block) { - printf("\nOut of space on the destination " - "device; quitting.\n"); - break; - } - if (lseek(fd, savedata->blk * sbd.bsize, - SEEK_SET) != - savedata->blk * sbd.bsize) { - fprintf(stderr, "bad seek: %s from %s:" - "%d: block %lld (0x%llx)\n", - strerror(errno), __FUNCTION__, - __LINE__, (unsigned long long) - savedata->blk, - (unsigned long long) - savedata->blk); - exit(-1); - } - if (write(fd, savedata->buf, sbd.bsize) != - sbd.bsize) { - fprintf(stderr, "write error: %s from " - "%s:%d: block %lld (0x%llx)\n", - strerror(errno), - __FUNCTION__, __LINE__, - (unsigned long long)savedata->blk, - (unsigned long long)savedata->blk); - exit(-1); - } - writes++; } - blks_saved++; } else { - fprintf(stderr, "\nBad record length: %d for block #%" - PRIu64".\n", savedata->siglen, savedata->blk); - return -1; + warm_fuzzy_stuff(savedata->blk, FALSE, FALSE); + if (savedata->blk >= last_fs_block) { + printf("\nOut of space on the destination " + "device; quitting.\n"); + break; + } + if (lseek(fd, savedata->blk * sbd.bsize, SEEK_SET) != + savedata->blk * sbd.bsize) { + fprintf(stderr, "bad seek: %s from %s:" + "%d: block %lld (0x%llx)\n", + strerror(errno), __FUNCTION__, + __LINE__, (unsigned long long) + savedata->blk, + (unsigned long long) + savedata->blk); + exit(-1); + } + if (write(fd, savedata->buf, sbd.bsize) != sbd.bsize) { + fprintf(stderr, "write error: %s from " + "%s:%d: block %lld (0x%llx)\n", + strerror(errno), + __FUNCTION__, __LINE__, + (unsigned long long)savedata->blk, + (unsigned long long)savedata->blk); + exit(-1); + } + writes++; } + blks_saved++; } if (!printblocksonly) warm_fuzzy_stuff(savedata->blk, TRUE, FALSE); @@ -895,7 +899,7 @@ static void complain(const char *complaint) }
void restoremeta(const char *in_fn, const char *out_device, - int printblocksonly) + uint64_t printblocksonly) { int in_fd, error;
@@ -914,7 +918,9 @@ void restoremeta(const char *in_fn, const char *out_device, if (sbd.device_fd < 0) die("Can't open destination file system %s: %s\n", out_device, strerror(errno)); - } + } else if (out_device) /* for printsavedmeta, the out_device is an + optional block no */ + printblocksonly = check_keywords(out_device); savedata = malloc(sizeof(struct saved_metablock)); if (!savedata) die("Can't allocate memory for the restore operation.\n");
cluster-commits@lists.fedorahosted.org