cluster: RHEL55 - GFS2: gfs2_edit savemeta bugs
Bob Peterson
rpeterso at fedoraproject.org
Thu Dec 17 23:25:42 UTC 2009
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=7ce660b860982feb4a4c0c08e3e778111d0700aa
Commit: 7ce660b860982feb4a4c0c08e3e778111d0700aa
Parent: e956129acaab0ab20b96b53b8ac0a494428806a1
Author: Bob Peterson <rpeterso at redhat.com>
AuthorDate: Thu Dec 17 17:27:04 2009 -0600
Committer: Bob Peterson <rpeterso at redhat.com>
CommitterDate: Thu Dec 17 17:27: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 | 26 +++++---
gfs2/edit/hexedit.h | 4 +-
gfs2/edit/savemeta.c | 162 +++++++++++++++++++++++++++-----------------------
3 files changed, 106 insertions(+), 86 deletions(-)
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
index 0d3af3e..49577f9 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -51,7 +51,7 @@ const char *allocdesc[2][5] = {
int display(int identify_only);
extern void savemeta(const char *out_fn, int slow);
extern void restoremeta(const char *in_fn, const char *out_device,
- int printblocksonly);
+ uint64_t printblocksonly);
/* for assigning numeric fields: */
#define checkassign(strfield, struct, member, value) do { \
@@ -1820,8 +1820,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);
@@ -3256,17 +3255,22 @@ 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]);
}
@@ -3467,12 +3471,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;
@@ -3488,6 +3492,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 d7dbe85..68116f5 100644
--- a/gfs2/edit/hexedit.h
+++ b/gfs2/edit/hexedit.h
@@ -42,7 +42,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 */
@@ -184,6 +184,8 @@ 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);
struct gfs2_dirents {
uint64_t block;
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
index a2082ea..6c36b69 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -98,13 +98,7 @@ int get_gfs_struct_info(char *buf, int *block_type, int *struct_len)
*struct_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)
- *struct_len = sbd.bsize;
- else
- *struct_len = sizeof(struct gfs2_meta_header);
+ *struct_len = sbd.bsize;
break;
case GFS2_METATYPE_LH: /* 8 (log header) */
if (gfs1)
@@ -325,11 +319,9 @@ void save_inode_data(int out_fd)
osi_list_t *prev_list, *cur_list, *tmp;
struct gfs2_buffer_head *metabh, *mybh;
int i;
- char *buf;
for (i = 0; i < GFS2_MAX_META_HEIGHT; i++)
osi_list_init(&metalist[i]);
- buf = malloc(sbd.bsize);
metabh = bread(&sbd.buf_list, block);
if (gfs1)
inode = inode_get(&sbd, metabh);
@@ -338,8 +330,15 @@ 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++){
@@ -398,7 +397,6 @@ void save_inode_data(int out_fd)
brelse(metabh, not_updated);
}
inode_put(inode, not_updated);
- free(buf);
}
void get_journal_inode_blocks(void)
@@ -702,26 +700,26 @@ int restore_data(int fd, int in_fd, int printblocksonly)
uint64_t buf64, writes = 0, highest_valid_block = 0;
uint16_t buf16;
int first = 1, pos;
- char buf[256];
+ char rdbuf[256];
char gfs_superblock_id[8] = {0x01, 0x16, 0x19, 0x70,
0x00, 0x00, 0x00, 0x01};
if (!printblocksonly)
do_lseek(fd, 0);
do_lseek(in_fd, 0);
- rs = read(in_fd, buf, sizeof(buf));
- if (rs != sizeof(buf)) {
+ rs = read(in_fd, rdbuf, sizeof(rdbuf));
+ if (rs != sizeof(rdbuf)) {
fprintf(stderr, "Error: File is too small.\n");
return -1;
}
- for (pos = 0; pos < sizeof(buf) - sizeof(uint64_t) - sizeof(uint16_t);
+ for (pos = 0; pos < sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t);
pos++) {
- if (!memcmp(&buf[pos + sizeof(uint64_t) + sizeof(uint16_t)],
+ if (!memcmp(&rdbuf[pos + sizeof(uint64_t) + sizeof(uint16_t)],
gfs_superblock_id, sizeof(gfs_superblock_id))) {
break;
}
}
- if (pos == sizeof(buf) - sizeof(uint64_t) - sizeof(uint16_t))
+ if (pos == sizeof(rdbuf) - sizeof(uint64_t) - sizeof(uint16_t))
pos = 0;
do_lseek(in_fd, pos);
blks_saved = total_out = 0;
@@ -749,68 +747,80 @@ 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)
- do_read(in_fd, savedata->buf,
- savedata->siglen);
- 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;
+ 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 (printblocksonly) {
+ 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;
+ }
+ 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;
- }
- do_lseek(fd, savedata->blk * sbd.bsize);
- do_write(fd, savedata->buf, sbd.bsize);
- writes++;
}
- blks_saved++;
} else {
- fprintf(stderr, "\nBad record length: %d for block #%"
- PRIu64 " (0x%" PRIx64").\n", savedata->siglen,
- savedata->blk, 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;
+ }
+ do_lseek(fd, savedata->blk * sbd.bsize);
+ do_write(fd, savedata->buf, sbd.bsize);
+ writes++;
}
+ blks_saved++;
}
if (!printblocksonly)
warm_fuzzy_stuff(savedata->blk, TRUE, FALSE);
@@ -830,7 +840,7 @@ void complain(const char *complaint)
}
void restoremeta(const char *in_fn, const char *out_device,
- int printblocksonly)
+ uint64_t printblocksonly)
{
int in_fd, error;
@@ -849,7 +859,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