From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18215 invoked by alias); 2 Sep 2009 15:37:43 -0000 Received: (qmail 18190 invoked by alias); 2 Sep 2009 15:37:42 -0000 X-SWARE-Spam-Status: No, hits=0.3 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_33,J_CHICKENPOX_61,J_CHICKENPOX_64,J_CHICKENPOX_66,J_CHICKENPOX_73,J_CHICKENPOX_84,SPF_HELO_PASS X-Spam-Status: No, hits=0.3 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_33,J_CHICKENPOX_61,J_CHICKENPOX_64,J_CHICKENPOX_66,J_CHICKENPOX_73,J_CHICKENPOX_84,SPF_HELO_PASS X-Spam-Check-By: sourceware.org X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on bastion2.fedora.phx.redhat.com Subject: gfs2-utils: master - gfs2_edit -p block# shows wrong height/offset on gfs1 and segfaults on gfs2 To: cluster-cvs-relay@redhat.com X-Project: Cluster Project X-Git-Module: gfs2-utils.git X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Oldrev: 1997a38b4d48b9fcd1603e8d1024a9d9608d8cd1 X-Git-Newrev: 7ad8cc851a94207fd044e29c9fb728ef4185f77b From: Bob Peterson Message-Id: <20090902153718.A8ABD120209@lists.fedorahosted.org> Date: Wed, 02 Sep 2009 15:37:00 -0000 X-Scanned-By: MIMEDefang 2.67 on 10.5.11.21 Mailing-List: contact cluster-cvs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: cluster-cvs-owner@sourceware.org X-SW-Source: 2009-q3/txt/msg00286.txt.bz2 Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitdiff;h=7ad8cc851a94207fd044e29c9fb728ef4185f77b Commit: 7ad8cc851a94207fd044e29c9fb728ef4185f77b Parent: 1997a38b4d48b9fcd1603e8d1024a9d9608d8cd1 Author: Bob Peterson AuthorDate: Wed Sep 2 10:13:14 2009 -0500 Committer: Bob Peterson CommitterDate: Wed Sep 2 10:14:43 2009 -0500 gfs2_edit -p block# shows wrong height/offset on gfs1 and segfaults on gfs2 The gfs2_edit tool was using crude calculations to try to figure out indirect block offsets when showing and printing indirect blocks. Those calculations have been switched to use "metapath" calculations to take out the guesswork. rhbz#506343 --- gfs2/edit/gfs2hex.c | 16 +++++- gfs2/edit/gfs2hex.h | 2 +- gfs2/edit/hexedit.c | 151 +++++++++++++++++++++++++++++++++------------------ gfs2/edit/hexedit.h | 3 + 4 files changed, 115 insertions(+), 57 deletions(-) diff --git a/gfs2/edit/gfs2hex.c b/gfs2/edit/gfs2hex.c index db87204..3bc1294 100644 --- a/gfs2/edit/gfs2hex.c +++ b/gfs2/edit/gfs2hex.c @@ -280,7 +280,7 @@ static int indirect_dirent(struct indirect_info *indir, char *ptr, int d) ******************************************************************************/ void do_dinode_extended(struct gfs2_dinode *dine, char *dinebuf) { - unsigned int x, y; + unsigned int x, y, ptroff = 0; uint64_t p, last; int isdir = !!(S_ISDIR(dine->di_mode)) || (gfs1 && dine->__pad1 == GFS_FILE_DIR); @@ -294,9 +294,12 @@ void do_dinode_extended(struct gfs2_dinode *dine, char *dinebuf) p = be64_to_cpu(*(uint64_t *)(dinebuf + x)); if (p) { indirect->ii[indirect_blocks].block = p; + indirect->ii[indirect_blocks].mp.mp_list[0] = + ptroff; indirect->ii[indirect_blocks].is_dir = FALSE; indirect_blocks++; } + ptroff++; } } else if (isdir && !(dine->di_flags & GFS2_DIF_EXHASH)) { @@ -370,14 +373,20 @@ void do_dinode_extended(struct gfs2_dinode *dine, char *dinebuf) ** ******************************************************************************* ******************************************************************************/ -int do_indirect_extended(char *diebuf, struct iinfo *iinf) +int do_indirect_extended(char *diebuf, struct iinfo *iinf, int hgt) { unsigned int x, y; uint64_t p; int i_blocks; i_blocks = 0; - memset(iinf, 0, sizeof(struct iinfo)); + for (x = 0; x < 512; x++) { + iinf->ii[x].is_dir = 0; + iinf->ii[x].height = 0; + iinf->ii[x].block = 0; + iinf->ii[x].dirents = 0; + memset(&iinf->ii[x].dirent, 0, sizeof(struct gfs2_dirents)); + } for (x = (gfs1 ? sizeof(struct gfs_indirect): sizeof(struct gfs2_meta_header)), y = 0; x < sbd.bsize; @@ -385,6 +394,7 @@ int do_indirect_extended(char *diebuf, struct iinfo *iinf) p = be64_to_cpu(*(uint64_t *)(diebuf + x)); if (p) { iinf->ii[i_blocks].block = p; + iinf->ii[i_blocks].mp.mp_list[hgt] = i_blocks; iinf->ii[i_blocks].is_dir = FALSE; i_blocks++; } diff --git a/gfs2/edit/gfs2hex.h b/gfs2/edit/gfs2hex.h index 93ed134..5a351d6 100644 --- a/gfs2/edit/gfs2hex.h +++ b/gfs2/edit/gfs2hex.h @@ -7,7 +7,7 @@ int display_gfs2(void); int edit_gfs2(void); void do_dinode_extended(struct gfs2_dinode *di, char *buf); void print_gfs2(const char *fmt, ...); -int do_indirect_extended(char *diebuf, struct iinfo *iinf); +int do_indirect_extended(char *diebuf, struct iinfo *iinf, int hgt); void do_leaf_extended(char *dlebuf, struct iinfo *indir); void eol(int col); diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c index 684fc05..1b8ca7b 100644 --- a/gfs2/edit/hexedit.c +++ b/gfs2/edit/hexedit.c @@ -40,7 +40,6 @@ const char *allocdesc[2][5] = { int display(int identify_only); extern void do_leaf_extended(char *buf, struct iinfo *indir); -extern int do_indirect_extended(char *buf, struct iinfo *ii); extern void savemeta(char *out_fn, int slow); extern void restoremeta(const char *in_fn, const char *out_device, int printblocksonly); @@ -429,8 +428,6 @@ static void print_usage(void) Erase(); } - - /* ------------------------------------------------------------------------ */ /* get_block_type */ /* returns: metatype if block is a GFS2 structure block type */ @@ -1300,14 +1297,70 @@ static int display_leaf(struct iinfo *ind) } /* ------------------------------------------------------------------------ */ +/* metapath_to_lblock - convert from metapath, height to logical block */ +/* ------------------------------------------------------------------------ */ +static uint64_t metapath_to_lblock(struct metapath *mp, int hgt) +{ + int h; + uint64_t lblock = 0; + uint64_t factor[GFS2_MAX_META_HEIGHT]; + + if (di.di_height < 2) + return mp->mp_list[0]; + /* figure out multiplication factors for each height */ + memset(&factor, 0, sizeof(factor)); + factor[di.di_height - 1] = 1ull; + for (h = di.di_height - 2; h >= 0; h--) + factor[h] = factor[h + 1] * sbd.sd_inptrs; + for (h = 0; h <= hgt; h++) + lblock += (mp->mp_list[h] * factor[h]); + return lblock; +} + +/* ------------------------------------------------------------------------ */ +/* dinode_valid - check if we have a dinode in recent history */ +/* ------------------------------------------------------------------------ */ +static int dinode_valid(void) +{ + int i; + + if (gfs2_struct_type == GFS2_METATYPE_DI) + return 1; + for (i = 0; i <= blockhist && i < 5; i++) { + if (blockstack[(blockhist - i) % + BLOCK_STACK_SIZE].gfs2_struct_type == + GFS2_METATYPE_DI) + return 1; + } + return 0; +} + +/* ------------------------------------------------------------------------ */ +/* get_height */ +/* ------------------------------------------------------------------------ */ +static int get_height(void) +{ + int cur_height = 0, i; + + if (gfs2_struct_type != GFS2_METATYPE_DI) { + for (i = 0; i <= blockhist && i < 5; i++) { + if (blockstack[(blockhist - i) % + BLOCK_STACK_SIZE].gfs2_struct_type == + GFS2_METATYPE_DI) + break; + cur_height++; + } + } + return cur_height; +} + +/* ------------------------------------------------------------------------ */ /* display_indirect */ /* ------------------------------------------------------------------------ */ static int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_t startoff) { int start_line, total_dirents; - int i, cur_height = -1, pndx; - uint64_t factor[5]={0,0,0,0,0}; - int offsets[5]; + int cur_height = -1, pndx; last_entry_onscreen[dmode] = 0; if (!has_indirect_blocks()) @@ -1326,39 +1379,15 @@ static int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_ indblocks); } total_dirents = 0; - /* Figure out multiplication factors for indirect pointers. */ - if (!S_ISDIR(di.di_mode)) { - memset(&offsets, 0, sizeof(offsets)); + if (dinode_valid() && !S_ISDIR(di.di_mode)) { /* See if we are on an inode or have one in history. */ - 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) - break; - cur_height++; - } - } - if (cur_height >= 0) { - int diptrs, inptrs; - - if (gfs1) { - diptrs = 483; - inptrs = 501; - } else { - diptrs = (sbd.bsize - sizeof(sizeof(struct gfs2_dinode))) / sizeof(uint64_t); - inptrs = (sbd.bsize - sizeof(sizeof(struct gfs2_meta_header))) / - sizeof(uint64_t); - } - /* Multiply out the max factor based on inode height.*/ - /* This is how much data is represented by each */ - /* indirect pointer at each height. */ - factor[0] = 1ull; - for (i = 0; i < di.di_height; i++) - factor[i + 1] = factor[i] * inptrs; + if (level) + cur_height = level; + else { + cur_height = get_height(); + print_gfs2(" (at height %d of %d)", + cur_height, di.di_height); } - if (!level) - print_gfs2(" (at height %d)", cur_height); } eol(0); if (!level && indblocks) { @@ -1403,20 +1432,13 @@ static int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_ COLORS_NORMAL; } } - if (!S_ISDIR(di.di_mode)) { - int hgt; + if (dinode_valid() && !S_ISDIR(di.di_mode)) { float human_off; char h; - file_offset = startoff; - - /* 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] = pndx; - for (hgt = cur_height; hgt >= 0; hgt--) - file_offset += offsets[cur_height - hgt] * - factor[di.di_height - hgt - 1] * sbd.bsize; + file_offset = metapath_to_lblock(&ind->ii[pndx].mp, + cur_height) * + sbd.bsize; print_gfs2(" "); h = 'K'; human_off = (file_offset / 1024.0); @@ -1431,8 +1453,9 @@ static int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_ } else file_offset = 0; - if (!termlines && ((level + 1 < di.di_height) || - (S_ISDIR(di.di_mode) && !level))) { + if (dinode_valid() && !termlines && + ((level + 1 < di.di_height) || + (S_ISDIR(di.di_mode) && !level))) { struct iinfo *more_indir; int more_ind; char *tmpbuf; @@ -1459,8 +1482,19 @@ static int display_indirect(struct iinfo *ind, int indblocks, int level, uint64_ do_leaf_extended(tmpbuf, more_indir); display_leaf(more_indir); } else { + int x; + + for (x = 0; x < 512; x++) { + memcpy(&more_indir->ii[x].mp, + &ind->ii[pndx].mp, + sizeof(struct metapath)); + more_indir->ii[x]. + mp.mp_list[cur_height+1] = + x; + } more_ind = do_indirect_extended(tmpbuf, - more_indir); + more_indir, + cur_height + 1); display_indirect(more_indir, more_ind, level + 1, file_offset); @@ -1826,8 +1860,15 @@ int display(int identify_only) 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, indirect); - indirect_blocks = 1; + int i, hgt = get_height(); + + if (blockhist) { + for (i = 0; i < 512; i++) + memcpy(&indirect->ii[i].mp, + &blockstack[blockhist - 1].mp, + sizeof(struct metapath)); + } + indirect_blocks = do_indirect_extended(buf, indirect, hgt); } else if (gfs2_struct_type == GFS2_METATYPE_LF) { /* directory leaf */ do_leaf_extended(buf, indirect); @@ -1876,6 +1917,10 @@ static void push_block(uint64_t blk) blockstack[bhst].lines_per_row[i] = lines_per_row[i]; } blockstack[bhst].gfs2_struct_type = gfs2_struct_type; + if (edit_row[dmode] >= 0) + memcpy(&blockstack[bhst].mp, + &indirect->ii[edit_row[dmode]].mp, + sizeof(struct metapath)); blockhist++; blockstack[blockhist % BLOCK_STACK_SIZE].block = blk; } diff --git a/gfs2/edit/hexedit.h b/gfs2/edit/hexedit.h index e53f72f..e4b0ea1 100644 --- a/gfs2/edit/hexedit.h +++ b/gfs2/edit/hexedit.h @@ -171,8 +171,10 @@ struct gfs2_dirents { struct indirect_info { int is_dir; + int height; uint64_t block; uint32_t dirents; + struct metapath mp; struct gfs2_dirents dirent[64]; }; @@ -189,6 +191,7 @@ struct blkstack_info { int edit_col[DMODES]; enum dsp_mode dmode; int gfs2_struct_type; + struct metapath mp; }; struct gfs_sb {