gfs2-utils: master - GFS2: gfs2_edit savemeta bugs

Bob Peterson rpeterso at fedoraproject.org
Thu Dec 17 23:19:40 UTC 2009


Gitweb:        http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitdiff;h=a7617752851a33d75245ab20e58df9e966904b7b
Commit:        a7617752851a33d75245ab20e58df9e966904b7b
Parent:        78c2c90520d9f20ac0c8879dc62e13816aad78d3
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:22:24 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 1b8ca7b..5ccb76e 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -39,10 +39,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 {		\
@@ -1818,8 +1814,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);
@@ -2146,7 +2141,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;
 
@@ -3253,17 +3248,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]);
 }
@@ -3462,12 +3462,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;
@@ -3483,6 +3483,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 ca56276..3985c45 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -86,13 +86,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)
@@ -360,8 +354,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++){
@@ -789,95 +790,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);
@@ -897,7 +901,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;
 
@@ -916,7 +920,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