From mboxrd@z Thu Jan 1 00:00:00 1970 From: rpeterso@sourceware.org Date: 16 Jul 2007 23:16:36 -0000 Subject: [Cluster-devel] cluster/gfs2/edit gfs2hex.c hexedit.c hexedit. ... Message-ID: <20070716231636.663.qmail@sourceware.org> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit CVSROOT: /cvs/cluster Module name: cluster Changes by: rpeterso at sourceware.org 2007-07-16 23:16:35 Modified files: gfs2/edit : gfs2hex.c hexedit.c hexedit.h savemeta.c Log message: I added the ability to recurse indirect blocks. That means that you can now print a list of all blocks associated with a file. For example, you could print all block numbers associated with journal0 by doing something like: gfs2_edit -p 0x19 /dev/roth_vg/roth_lv assuming, of course, that you know that block 0x19 contains journal0. (You can use gfs2_edit -p jindex to get that information though). I fixed some bugs with restoremeta where it was dying if the metadata to be restored was bigger than the destination file system could hold. I made restoremeta do some "warm fuzzy stuff" to report its progress of the restore operation so the user doesn't think the restoremeta is permanently hung. I renamed some long variable names to short ones to make the code less wordy. I fixed a minor segfault if you hit "j" when your cursor is on the block number of the hex view. I probably should have committed these changes earlier rather than save them up, but some of my changes had serious regressions and I didn't have time to sort it out and fix it until just now (I didn't want to commit a broken version to cvs.) Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/gfs2hex.c.diff?cvsroot=cluster&r1=1.10&r2=1.11 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.c.diff?cvsroot=cluster&r1=1.16&r2=1.17 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.h.diff?cvsroot=cluster&r1=1.9&r2=1.10 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/savemeta.c.diff?cvsroot=cluster&r1=1.1&r2=1.2 --- cluster/gfs2/edit/gfs2hex.c 2007/02/28 21:58:46 1.10 +++ cluster/gfs2/edit/gfs2hex.c 2007/07/16 23:16:35 1.11 @@ -192,6 +192,7 @@ memcpy(&indir->dirent[d].dirent, &de, sizeof(struct gfs2_dirent)); memcpy(&indir->dirent[d].filename, ptr + sizeof(struct gfs2_dirent), de.de_name_len); + indir->dirent[d].filename[de.de_name_len] = '\0'; indir->dirent[d].block = de.de_inum.no_addr; indir->is_dir = TRUE; indir->dirents++; @@ -222,7 +223,7 @@ (gfs1 && di->__pad1 == GFS_FILE_DIR); indirect_blocks = 0; - memset(&indirect, 0, sizeof(indirect)); + memset(indirect, 0, sizeof(indirect)); if (di->di_height > 0) { /* Indirect pointers */ for (x = sizeof(struct gfs2_dinode), y = 0; @@ -230,21 +231,23 @@ x += sizeof(uint64_t), y++) { p = be64_to_cpu(*(uint64_t *)(buf + x)); if (p) { - indirect[indirect_blocks].block = p; - indirect[indirect_blocks].is_dir = FALSE; + indirect->ii[indirect_blocks].block = p; + indirect->ii[indirect_blocks].is_dir = FALSE; indirect_blocks++; } } } - else if (isdir && - !(di->di_flags & GFS2_DIF_EXHASH)) { + else if (isdir && !(di->di_flags & GFS2_DIF_EXHASH)) { int skip = 0; + /* Directory Entries: */ - indirect[0].dirents = 0; - indirect[0].block = block; - indirect[0].is_dir = TRUE; + indirect->ii[0].dirents = 0; + indirect->ii[0].block = block; + indirect->ii[0].is_dir = TRUE; for (x = sizeof(struct gfs2_dinode); x < bufsize; x += skip) { - skip = indirect_dirent(&indirect[0], buf + x, indirect[0].dirents); + skip = indirect_dirent(indirect->ii, + buf + x, + indirect->ii[0].dirents); if (skip <= 0) break; } @@ -267,20 +270,22 @@ struct gfs2_leaf leaf; unsigned int bufoffset; + if (last >= max_block) + break; tmp_bh = bread(&sbd, last); gfs2_leaf_in(&leaf, tmp_bh->b_data); - indirect[indirect_blocks].dirents = 0; + indirect->ii[indirect_blocks].dirents = 0; for (direntcount = 0, bufoffset = sizeof(struct gfs2_leaf); bufoffset < bufsize; direntcount++, bufoffset += skip) { - skip = indirect_dirent(&indirect[indirect_blocks], + skip = indirect_dirent(&indirect->ii[indirect_blocks], tmp_bh->b_data + bufoffset, direntcount); if (skip <= 0) break; } brelse(tmp_bh, not_updated); - indirect[indirect_blocks].block = last; + indirect->ii[indirect_blocks].block = last; indirect_blocks++; last = p; } /* if not duplicate pointer */ @@ -303,24 +308,26 @@ ** ******************************************************************************* ******************************************************************************/ -void do_indirect_extended(char *buf) +int do_indirect_extended(char *buf, struct iinfo *iinf) { unsigned int x, y; uint64_t p; + int i_blocks; - indirect_blocks = 0; - memset(&indirect, 0, sizeof(indirect)); + i_blocks = 0; + memset(iinf, 0, sizeof(struct iinfo)); for (x = (gfs1 ? sizeof(struct gfs_indirect): sizeof(struct gfs2_meta_header)), y = 0; x < bufsize; x += sizeof(uint64_t), y++) { p = be64_to_cpu(*(uint64_t *)(buf + x)); if (p) { - indirect[indirect_blocks].block = p; - indirect[indirect_blocks].is_dir = FALSE; - indirect_blocks++; + iinf->ii[i_blocks].block = p; + iinf->ii[i_blocks].is_dir = FALSE; + i_blocks++; } } + return i_blocks; } /****************************************************************************** --- cluster/gfs2/edit/hexedit.c 2007/06/26 01:25:33 1.16 +++ cluster/gfs2/edit/hexedit.c 2007/07/16 23:16:35 1.17 @@ -46,7 +46,7 @@ int display(int identify_only); extern void eol(int col); -extern void do_indirect_extended(char *buf); +extern int do_indirect_extended(char *buf, struct iinfo *ii); extern void savemeta(const char *in_fn, const char *out_fn, int slow); extern void restoremeta(const char *in_fn, const char *out_device); @@ -822,49 +822,51 @@ /* ------------------------------------------------------------------------ */ /* display_indirect */ /* ------------------------------------------------------------------------ */ -int display_indirect(void) +int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_t startoff) { int start_line, total_dirents, indir_blocks; - int i, cur_height = -1; + int i, cur_height = -1, pndx; uint64_t factor[5]={0,0,0,0,0}; int offsets[5]; last_entry_onscreen[dmode] = 0; - eol(0); + if (!level) + eol(0); start_line = line; if (!has_indirect_blocks()) return -1; - indir_blocks = indirect_blocks; - if (!indirect_blocks) { - if (gfs2_struct_type == GFS2_METATYPE_SB) - print_gfs2("The superblock has 2 directories"); - else - print_gfs2("This directory contains %d directory entries.", - indirect[0].dirents); - indir_blocks = 1; /* not really an indirect block, but treat it as one */ - } - else { - if (gfs2_struct_type == GFS2_METATYPE_DI) { - if (S_ISDIR(di.di_mode)) - print_gfs2("This directory contains %d indirect blocks", - indirect_blocks); + indir_blocks = indblocks; + if (!level) { + if (!indblocks) { + if (gfs2_struct_type == GFS2_METATYPE_SB) + print_gfs2("The superblock has 2 directories"); else - print_gfs2("This inode contains %d indirect blocks", - indirect_blocks); + print_gfs2("This directory contains %d directory entries.", + ind->ii[0].dirents); + indir_blocks = 1; /* not really an indirect block, but treat it as one */ + } + else { + if (gfs2_struct_type == GFS2_METATYPE_DI) { + if (S_ISDIR(di.di_mode)) + print_gfs2("This directory contains %d indirect blocks", + indblocks); + else + print_gfs2("This inode contains %d indirect blocks", + indblocks); + } + else + print_gfs2("This indirect block contains %d indirect blocks", + indblocks); } - else - print_gfs2("This indirect block contains %d indirect blocks", - indirect_blocks); } total_dirents = 0; /* Figure out multiplication factors for indirect pointers. */ - if ((indir_blocks == indirect_blocks) && !S_ISDIR(di.di_mode)) { + if ((indir_blocks == indblocks) && !S_ISDIR(di.di_mode)) { memset(&offsets, 0, sizeof(offsets)); /* See if we are on an inode or have one in history. */ - cur_height = 0; - if (gfs2_struct_type != GFS2_METATYPE_DI) { - cur_height = 0; + cur_height = level; + if (!level && gfs2_struct_type != GFS2_METATYPE_DI) { for (i = 0; i <= blockhist && i < 5; i++) { offsets[i] = blockstack[(blockhist - i) % BLOCK_STACK_SIZE].edit_row[dmode]; if (blockstack[(blockhist - i) % BLOCK_STACK_SIZE].gfs2_struct_type == GFS2_METATYPE_DI) @@ -890,17 +892,19 @@ for (i = 0; i < di.di_height; i++) factor[i + 1] = factor[i] * inptrs; } - print_gfs2(" (at height=%d)", cur_height); - } - if (indirect_blocks) { + if (!level) + print_gfs2(" (at height=%d)", cur_height); eol(0); + } + if (!level && indblocks) { print_gfs2("Indirect blocks:"); + eol(0); } - eol(0); - for (print_entry_ndx = start_row[dmode]; - (!termlines || print_entry_ndx < termlines - start_line - 2 - + start_row[dmode]) && print_entry_ndx < indir_blocks; - print_entry_ndx++) { + for (pndx = start_row[dmode]; + (!termlines || pndx < termlines - start_line - 2 + + start_row[dmode]) && pndx < indir_blocks; + pndx++) { + print_entry_ndx = pndx; if (termlines) { if (edit_row[dmode] >= 0 && line - start_line - 2 == edit_row[dmode] - @@ -908,18 +912,24 @@ COLORS_HIGHLIGHT; move(line, 1); } - if (indir_blocks == indirect_blocks) { - print_gfs2("%d => ", print_entry_ndx); + if (indir_blocks == indblocks) { + if (!termlines) { + int h; + + for (h = 0; h < level; h++) + print_gfs2(" "); + } + print_gfs2("%d => ", pndx); if (termlines) move(line,9); - print_gfs2("0x%llx / %lld", indirect[print_entry_ndx].block, - indirect[print_entry_ndx].block); + print_gfs2("0x%llx / %lld", ind->ii[pndx].block, + ind->ii[pndx].block); if (termlines) { if (edit_row[dmode] >= 0 && line - start_line - 2 == edit_row[dmode] - start_row[dmode]) { sprintf(estring, "%"PRIx64, - indirect[print_entry_ndx].block); + ind->ii[print_entry_ndx].block); strcpy(edit_fmt, "%"PRIx64); edit_size[dmode] = strlen(estring); COLORS_NORMAL; @@ -927,14 +937,14 @@ } if (!S_ISDIR(di.di_mode)) { int hgt; - uint64_t file_offset = 0ull; + uint64_t file_offset = startoff; float human_off; char h; /* Now divide by how deep we are at the moment. */ /* This is how much data is represented by each */ /* indirect pointer for each height we've traversed. */ - offsets[0] = print_entry_ndx; + offsets[0] = pndx; for (hgt = cur_height; hgt >= 0; hgt--) file_offset += offsets[cur_height - hgt] * factor[di.di_height - hgt - 1] * bufsize; @@ -949,18 +959,40 @@ print_gfs2("(data offset 0x%llx / %lld / %6.2f%c)", file_offset, file_offset, human_off, h); print_gfs2(" "); + if (!termlines && level + 1 < di.di_height) { + struct iinfo *more_indir; + int more_ind; + char *tmpbuf; + + more_indir = malloc(sizeof(struct iinfo)); + tmpbuf = malloc(bufsize); + if (tmpbuf) { + do_lseek(fd, + ind->ii[pndx].block * bufsize); + do_read(fd, tmpbuf, + bufsize); /* read in the desired block */ + memset(more_indir, 0, sizeof(struct iinfo)); + more_ind = do_indirect_extended(tmpbuf, + more_indir); + display_indirect(more_indir, + more_ind, level + 1, file_offset); + free(tmpbuf); + } + free(more_indir); + } + print_entry_ndx = pndx; /* restore after recursion */ } } - if (indirect[print_entry_ndx].is_dir) { + if (ind->ii[pndx].is_dir) { int d; - if (indirect[print_entry_ndx].dirents > 1 && - indir_blocks == indirect_blocks) + if (ind->ii[pndx].dirents > 1 && + indir_blocks == indblocks) print_gfs2("(directory leaf with %d entries)", - indirect[print_entry_ndx].dirents); - for (d = 0; d < indirect[print_entry_ndx].dirents; d++) { + ind->ii[pndx].dirents); + for (d = 0; d < ind->ii[pndx].dirents; d++) { total_dirents++; - if (indirect[print_entry_ndx].dirents > 1) { + if (ind->ii[pndx].dirents > 1) { eol(5); if (termlines) { if (edit_row[dmode] >=0 && @@ -969,19 +1001,19 @@ start_row[dmode]) { COLORS_HIGHLIGHT; sprintf(estring, "%"PRIx64, - indirect[print_entry_ndx].dirent[d].block); + ind->ii[pndx].dirent[d].block); strcpy(edit_fmt, "%"PRIx64); } } print_gfs2("%d. (%d). %lld (0x%llx) / %lld (0x%llx): ", total_dirents, d + 1, - indirect[print_entry_ndx].dirent[d].dirent.de_inum.no_formal_ino, - indirect[print_entry_ndx].dirent[d].dirent.de_inum.no_formal_ino, - indirect[print_entry_ndx].dirent[d].block, - indirect[print_entry_ndx].dirent[d].block); + ind->ii[pndx].dirent[d].dirent.de_inum.no_formal_ino, + ind->ii[pndx].dirent[d].dirent.de_inum.no_formal_ino, + ind->ii[pndx].dirent[d].block, + ind->ii[pndx].dirent[d].block); } - print_inode_type(indirect[print_entry_ndx].dirent[d].dirent.de_type); - print_gfs2(" %s", indirect[print_entry_ndx].dirent[d].filename); + print_inode_type(ind->ii[pndx].dirent[d].dirent.de_type); + print_gfs2(" %s", ind->ii[pndx].dirent[d].filename); if (termlines) { if (edit_row[dmode] >= 0 && line - start_line - 2 == edit_row[dmode] - @@ -995,7 +1027,7 @@ if (line >= 7) /* 7 because it was bumped at the end */ last_entry_onscreen[dmode] = line - 7; eol(0); - end_row[dmode] = (indirect_blocks ? indirect_blocks:indirect[0].dirents); + end_row[dmode] = (indblocks ? indblocks:ind->ii[0].dirents); if (end_row[dmode] < last_entry_onscreen[dmode]) end_row[dmode] = last_entry_onscreen[dmode]; lines_per_row[dmode] = 1; @@ -1091,14 +1123,14 @@ struct gfs2_buffer_head *tmp_bh; /* Display any indirect pointers that we have. */ - if (display_indirect() == 0) - return -1; - else if (block_is_rindex()) { + if (block_is_rindex()) { tmp_bh = bread(&sbd, block); tmp_inode = inode_get(&sbd, tmp_bh); parse_rindex(tmp_inode, TRUE); brelse(tmp_bh, not_updated); } + else if (display_indirect(indirect, indirect_blocks, 0, 0) == 0) + return -1; else if (block_is_rglist()) { tmp_bh = bread(&sbd, masterblock("rindex")); tmp_inode = inode_get(&sbd, tmp_bh); @@ -1218,53 +1250,54 @@ lines_per_row[dmode] = 1; if (gfs2_struct_type == GFS2_METATYPE_SB || blk == 0x10 * (4096 / bufsize)) { gfs2_sb_in(&sbd.sd_sb, buf); /* parse it out into the sb structure */ - memset(&indirect, 0, sizeof(indirect)); - indirect[0].block = sbd.sd_sb.sb_master_dir.no_addr; - indirect[0].is_dir = TRUE; - indirect[0].dirents = 2; + memset(indirect, 0, sizeof(indirect)); + indirect->ii[0].block = sbd.sd_sb.sb_master_dir.no_addr; + indirect->ii[0].is_dir = TRUE; + indirect->ii[0].dirents = 2; - memcpy(&indirect[0].dirent[0].filename, "root", 4); - indirect[0].dirent[0].dirent.de_inum.no_formal_ino = + memcpy(&indirect->ii[0].dirent[0].filename, "root", 4); + indirect->ii[0].dirent[0].dirent.de_inum.no_formal_ino = sbd.sd_sb.sb_root_dir.no_formal_ino; - indirect[0].dirent[0].dirent.de_inum.no_addr = + indirect->ii[0].dirent[0].dirent.de_inum.no_addr = sbd.sd_sb.sb_root_dir.no_addr; - indirect[0].dirent[0].block = sbd.sd_sb.sb_root_dir.no_addr; - indirect[0].dirent[0].dirent.de_type = DT_DIR; + indirect->ii[0].dirent[0].block = sbd.sd_sb.sb_root_dir.no_addr; + indirect->ii[0].dirent[0].dirent.de_type = DT_DIR; - memcpy(&indirect[0].dirent[1].filename, "master", 7); - indirect[0].dirent[1].dirent.de_inum.no_formal_ino = + memcpy(&indirect->ii[0].dirent[1].filename, "master", 7); + indirect->ii[0].dirent[1].dirent.de_inum.no_formal_ino = sbd.sd_sb.sb_master_dir.no_formal_ino; - indirect[0].dirent[1].dirent.de_inum.no_addr = + indirect->ii[0].dirent[1].dirent.de_inum.no_addr = sbd.sd_sb.sb_master_dir.no_addr; - indirect[0].dirent[1].block = sbd.sd_sb.sb_master_dir.no_addr; - indirect[0].dirent[1].dirent.de_type = DT_DIR; + indirect->ii[0].dirent[1].block = sbd.sd_sb.sb_master_dir.no_addr; + indirect->ii[0].dirent[1].dirent.de_type = DT_DIR; } else if (gfs2_struct_type == GFS2_METATYPE_DI) { gfs2_dinode_in(&di, buf); /* parse disk inode into structure */ do_dinode_extended(&di, buf); /* get extended data, if any */ } else if (gfs2_struct_type == GFS2_METATYPE_IN) { /* indirect block list */ - do_indirect_extended(buf); + do_indirect_extended(buf, indirect); } else if (gfs2_struct_type == GFS2_METATYPE_LF) { /* directory leaf */ int x; struct gfs2_dirent de; indirect_blocks = 1; - memset(&indirect, 0, sizeof(indirect)); + memset(indirect, 0, sizeof(indirect)); /* Directory Entries: */ for (x = sizeof(struct gfs2_leaf); x < bufsize; x += de.de_rec_len) { gfs2_dirent_in(&de, buf + x); if (de.de_inum.no_addr) { - indirect[indirect_blocks].block = de.de_inum.no_addr; - indirect[indirect_blocks].dirent[x].block = de.de_inum.no_addr; - memcpy(&indirect[indirect_blocks].dirent[x].dirent, &de, + indirect->ii[indirect_blocks].block = de.de_inum.no_addr; + indirect->ii[indirect_blocks].dirent[x].block = de.de_inum.no_addr; + memcpy(&indirect->ii[indirect_blocks].dirent[x].dirent, &de, sizeof(struct gfs2_dirent)); - memcpy(&indirect[indirect_blocks].dirent[x].filename, + memcpy(&indirect->ii[indirect_blocks].dirent[x].filename, buf + x + sizeof(struct gfs2_dirent), de.de_name_len); - indirect[indirect_blocks].is_dir = TRUE; - indirect[indirect_blocks].dirents++; + indirect->ii[indirect_blocks].dirent[x].filename[de.de_name_len] = '\0'; + indirect->ii[indirect_blocks].is_dir = TRUE; + indirect->ii[indirect_blocks].dirents++; } if (de.de_rec_len <= sizeof(struct gfs2_dirent)) break; @@ -1535,9 +1568,11 @@ unsigned int col2; uint64_t *b; - col2 = edit_col[dmode] & 0x08;/* thus 0-7->0, 8-15->8 */ - b = (uint64_t *)&buf[edit_row[dmode]*16 + offset + col2]; - temp_blk=be64_to_cpu(*b); + if (edit_row[dmode] >= 0) { + col2 = edit_col[dmode] & 0x08;/* thus 0-7->0, 8-15->8 */ + b = (uint64_t *)&buf[edit_row[dmode]*16 + offset + col2]; + temp_blk=be64_to_cpu(*b); + } } else sscanf(estring, "%"SCNx64, &temp_blk);/* retrieve in hex */ @@ -1977,6 +2012,10 @@ prog_name = argv[0]; + indirect = malloc(sizeof(struct iinfo)); + if (!indirect) + die("Out of memory."); + memset(indirect, 0, sizeof(struct iinfo)); memset(start_row, 0, sizeof(start_row)); memset(lines_per_row, 0, sizeof(lines_per_row)); memset(end_row, 0, sizeof(end_row)); @@ -2005,7 +2044,7 @@ fd = open(device, O_RDWR); if (fd < 0) - die("can't open %s: %s\n", argv[1], strerror(errno)); + die("can't open %s: %s\n", device, strerror(errno)); max_block = lseek(fd, 0, SEEK_END) / bufsize; read_superblock(); @@ -2033,5 +2072,7 @@ close(fd); if (buf) free(buf); + if (indirect) + free(indirect); exit(EXIT_SUCCESS); } --- cluster/gfs2/edit/hexedit.h 2007/02/28 21:58:46 1.9 +++ cluster/gfs2/edit/hexedit.h 2007/07/16 23:16:35 1.10 @@ -109,6 +109,10 @@ struct gfs2_dirents dirent[64]; }; +struct iinfo { + struct indirect_info ii[512]; +}; + struct gfs_indirect { struct gfs2_meta_header in_header; @@ -168,9 +172,8 @@ }; EXTERN struct blkstack_info blockstack[BLOCK_STACK_SIZE]; -EXTERN struct indirect_info indirect[512]; /* more than the most indirect - pointers possible for any given - 4K block */ +EXTERN struct iinfo *indirect; /* more than the most indirect + pointers possible for any given 4K block */ EXTERN struct indirect_info masterdir; /* Master directory info */ EXTERN int indirect_blocks INIT(0); /* count of indirect blocks */ EXTERN enum dsp_mode dmode INIT(HEX_MODE); --- cluster/gfs2/edit/savemeta.c 2007/06/26 01:25:33 1.1 +++ cluster/gfs2/edit/savemeta.c 2007/07/16 23:16:35 1.2 @@ -434,7 +434,7 @@ /* checking every block kills performance. We only report */ /* every second because we don't need 100 extra messages in */ /* logs made from verbose mode. */ -void warm_fuzzy_stuff(uint64_t block, int force) +void warm_fuzzy_stuff(uint64_t block, int force, int save) { static struct timeval tv; static uint32_t seconds = 0; @@ -451,8 +451,9 @@ percent = (block * 100) / last_fs_block; printf("\r%" PRIu64 " blocks (%" PRIu64 "%%) processed, ", block, percent); - printf("%" PRIu64 " blocks (%" PRIu64 "MB) saved ", - blks_saved, total_out / (1024*1024)); + printf("%" PRIu64 " blocks (%" PRIu64 "MB) %s ", + blks_saved, total_out / (1024*1024), + save?"saved":"restored"); fflush(stdout); } } @@ -464,7 +465,7 @@ uint16_t trailing0; char *p; - warm_fuzzy_stuff(blk, FALSE); + warm_fuzzy_stuff(blk, FALSE, TRUE); memset(savedata, 0, sizeof(struct saved_metablock)); do_lseek(fd, blk * bufsize); do_read(fd, savedata->buf, bufsize); /* read in the block */ @@ -605,7 +606,7 @@ /* There may be a gap between end of file system and end of device */ /* so we tell the user that we've processed everything. */ blk = last_fs_block; - warm_fuzzy_stuff(blk, TRUE); + warm_fuzzy_stuff(blk, TRUE, TRUE); printf("\nMetadata saved to file %s.\n", out_fn); free(savedata); close(out_fd); @@ -622,6 +623,8 @@ uint64_t max_fs_size; do_lseek(fd, 0); + blks_saved = 0; + total_out = 0; while (TRUE) { memset(savedata, 0, sizeof(struct saved_metablock)); rs = read(in_fd, &buf64, sizeof(uint64_t)); @@ -643,12 +646,22 @@ } rs = read(in_fd, &buf16, sizeof(uint16_t)); savedata->siglen = be16_to_cpu(buf16); + total_out += rs + savedata->siglen; if (savedata->siglen > 0 && savedata->siglen <= sizeof(savedata->buf)) { do_read(in_fd, savedata->buf, savedata->siglen); if (first) { gfs2_sb_in(&sbd.sd_sb, savedata->buf); - if (check_sb(&sbd.sd_sb)) { + 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) + ; + else if (check_sb(&sbd.sd_sb)) { fprintf(stderr,"Error: Invalid superblock data.\n"); return -1; } @@ -656,19 +669,28 @@ last_fs_block = lseek(fd, 0, SEEK_END) / bufsize; printf("There are %" PRIu64 " blocks of %" \ - PRIu64 "bytes in the destination file" \ - " system.\n\n", last_fs_block, bufsize); + PRIu64 " bytes in the destination" \ + " file system.\n\n", + last_fs_block, bufsize); first = 0; } + warm_fuzzy_stuff(savedata->blk, FALSE, FALSE); + if (savedata->blk >= last_fs_block) { + printf("Out of space on the destination " + "device; quitting.\n"); + break; + } do_lseek(fd, savedata->blk * bufsize); do_write(fd, savedata->buf, bufsize); writes++; + blks_saved++; } else { fprintf(stderr, "Bad record length: %d for #%" PRIu64".\n", savedata->siglen, savedata->blk); return -1; } } + warm_fuzzy_stuff(savedata->blk, TRUE, FALSE); printf("%" PRIu64 " blocks restored.\n", writes); return 0; }