Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 9383e745e23602bc45f9c92184feea59 > files > 93

gfs2-utils-0.1.62-28.el5.src.rpm

commit 7ce660b860982feb4a4c0c08e3e778111d0700aa
Author: Bob Peterson <rpeterso@redhat.com>
Date:   Thu Dec 17 17:27:04 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

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");