cluster: STABLE3 - GFS2: gfs2_edit savemeta bugs
Bob Peterson
rpeterso at fedoraproject.org
Thu Dec 17 23:20:50 UTC 2009
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=a26a9856c295be1de37186299eb52034a1c9cd66
Commit: a26a9856c295be1de37186299eb52034a1c9cd66
Parent: baea48ccc79bbc3ef2723c2eae26b1d144dea645
Author: Bob Peterson <rpeterso at redhat.com>
AuthorDate: Thu Dec 17 17:15:49 2009 -0600
Committer: Bob Peterson <rpeterso at 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");
More information about the cluster-commits
mailing list