From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10226 invoked by alias); 30 Jul 2008 22:25:28 -0000 Received: (qmail 10220 invoked by alias); 30 Jul 2008 22:25:28 -0000 X-Spam-Status: No, hits=1.8 required=5.0 tests=BAYES_00,J_CHICKENPOX_35,J_CHICKENPOX_53,J_CHICKENPOX_62,J_CHICKENPOX_63,J_CHICKENPOX_64,J_CHICKENPOX_66,J_CHICKENPOX_73,KAM_MX,SPF_HELO_PASS X-Spam-Check-By: sourceware.org X-Spam-Checker-Version: SpamAssassin 3.2.4 (2008-01-01) on bastion.fedora.phx.redhat.com X-Spam-Level: Subject: RHEL5 - gfs2_edit: Improved gfs journal dumps To: cluster-cvs-relay@redhat.com X-Project: Cluster Project X-Git-Module: cluster.git X-Git-Refname: refs/heads/RHEL5 X-Git-Reftype: branch X-Git-Oldrev: 67f13d16f385f42165d0196917fcd7bb8c5b0a1d X-Git-Newrev: bf130aa9983f13ab5b2a40181680fc2c35f1f3e1 From: Bob Peterson Message-Id: <20080730222443.029D112001F@lists.fedorahosted.org> Date: Thu, 31 Jul 2008 05:02:00 -0000 X-Scanned-By: MIMEDefang 2.58 on 172.16.52.254 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: 2008-q3/txt/msg00184.txt.bz2 Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=bf130aa9983f13ab5b2a40181680fc2c35f1f3e1 Commit: bf130aa9983f13ab5b2a40181680fc2c35f1f3e1 Parent: 67f13d16f385f42165d0196917fcd7bb8c5b0a1d Author: Bob Peterson AuthorDate: Wed Jul 30 17:16:52 2008 -0500 Committer: Bob Peterson CommitterDate: Wed Jul 30 17:21:30 2008 -0500 gfs2_edit: Improved gfs journal dumps bz 450004 This patch adds three important improvements to journal dumps: 1. It now recognizes and dumps GFS1 log descriptor continuation blocks and dumps them correctly. 2. It now prints a marker where the journal wrapped so you can locate the most recently added entries easily. 3. The absolute block number of the journal block is now printed with the entries (in addition to the journal offset). This makes it easier to find the correct journal block you need to see. --- gfs2/edit/hexedit.c | 173 ++++++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 144 insertions(+), 29 deletions(-) diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c index 5a0e619..4d28a62 100644 --- a/gfs2/edit/hexedit.c +++ b/gfs2/edit/hexedit.c @@ -2235,15 +2235,129 @@ void gfs_log_header_print(struct gfs_log_header *lh) } /* ------------------------------------------------------------------------ */ +/* print_ld_blocks - print all blocks given in a log descriptor */ +/* returns: the number of block numbers it printed */ +/* ------------------------------------------------------------------------ */ +int print_ld_blocks(const uint64_t *b, const char *end, int start_line) +{ + int bcount = 0, i = 0; + static char str[256]; + + while (*b && (char *)b < end) { + if (!termlines || + (print_entry_ndx >= start_row[dmode] && + ((print_entry_ndx - start_row[dmode])+1) * + lines_per_row[dmode] <= termlines - start_line - 2)) { + if (i && i % 4 == 0) { + eol(0); + print_gfs2(" "); + } + i++; + sprintf(str, "0x%llx", + (unsigned long long)be64_to_cpu(*b)); + print_gfs2("%-18.18s ", str); + bcount++; + } + b++; + if (gfs1) + b++; + } + eol(0); + return bcount; +} + +/* ------------------------------------------------------------------------ */ +/* fsck_readi - same as libgfs2's gfs2_readi, but sets absolute block # */ +/* of the first bit of data read. */ +/* ------------------------------------------------------------------------ */ +int fsck_readi(struct gfs2_inode *ip, void *buf, uint64_t offset, + unsigned int size, uint64_t *abs_block) +{ + struct gfs2_sbd *sdp = ip->i_sbd; + struct gfs2_buffer_head *bh; + uint64_t lblock, dblock; + unsigned int o; + uint32_t extlen = 0; + unsigned int amount; + int not_new = 0; + int isdir = !!(S_ISDIR(ip->i_di.di_mode)); + int copied = 0; + + *abs_block = 0; + if (offset >= ip->i_di.di_size) + return 0; + if ((offset + size) > ip->i_di.di_size) + size = ip->i_di.di_size - offset; + if (!size) + return 0; + if (isdir) { + lblock = offset; + o = do_div(lblock, sdp->sd_jbsize); + } else { + lblock = offset >> sdp->sd_sb.sb_bsize_shift; + o = offset & (sdp->bsize - 1); + } + + if (!ip->i_di.di_height) /* inode_is_stuffed */ + o += sizeof(struct gfs2_dinode); + else if (isdir) + o += sizeof(struct gfs2_meta_header); + + while (copied < size) { + amount = size - copied; + if (amount > sdp->bsize - o) + amount = sdp->bsize - o; + if (!extlen) + block_map(ip, lblock, ¬_new, &dblock, &extlen, + FALSE, not_updated); + if (dblock) { + bh = bread(sdp, dblock); + if (*abs_block == 0) + *abs_block = bh->b_blocknr; + dblock++; + extlen--; + } else + bh = NULL; + if (bh) { + memcpy(buf, bh->b_data + o, amount); + brelse(bh, not_updated); + } else { + memset(buf, 0, amount); + } + copied += amount; + lblock++; + o = (isdir) ? sizeof(struct gfs2_meta_header) : 0; + } + return copied; +} + +void check_journal_wrap(uint64_t seq, uint64_t *highest_seq) +{ + if (seq < *highest_seq) { + print_gfs2("------------------------------------------------" + "------------------------------------------------"); + eol(0); + print_gfs2("Journal wrapped here."); + eol(0); + print_gfs2("------------------------------------------------" + "------------------------------------------------"); + eol(0); + } + *highest_seq = seq; +} + +/* ------------------------------------------------------------------------ */ /* dump_journal - dump a journal file's contents. */ /* ------------------------------------------------------------------------ */ void dump_journal(const char *journal) { struct gfs2_buffer_head *j_bh = NULL; - uint64_t jblock, j_size, jb; + uint64_t jblock, j_size, jb, abs_block; int error, start_line, journal_num; char jbuf[sbd.bsize]; struct gfs2_inode *j_inode = NULL; + int ld_blocks = 0; + uint64_t highest_seq = 0; start_line = line; lines_per_row[dmode] = 1; @@ -2264,17 +2378,18 @@ void dump_journal(const char *journal) if (j_bh) brelse(j_bh, not_updated); j_bh = bread(&sbd, jblock + jb); + abs_block = jblock + jb; memcpy(jbuf, j_bh->b_data, sbd.bsize); } else { - error = gfs2_readi(j_inode, (void *)&jbuf, jb, - sbd.bsize); + error = fsck_readi(j_inode, (void *)&jbuf, jb, + sbd.bsize, &abs_block); if (!error) /* end of file */ break; } if (get_block_type(jbuf) == GFS2_METATYPE_LD) { uint64_t *b; struct gfs2_log_descriptor ld; - int i = 0, ltndx; + int ltndx; uint32_t logtypes[2][6] = { {GFS2_LOG_DESC_METADATA, GFS2_LOG_DESC_REVOKE, @@ -2292,8 +2407,8 @@ void dump_journal(const char *journal) {"Metadata", "Unlinked inode", "Dealloc inode", "Quota", "Final Entry", "Unknown"}}; - print_gfs2("Block #%4llx: Log descriptor, ", - jb / (gfs1 ? 1 : sbd.bsize)); + print_gfs2("0x%llx (j+%4llx): Log descriptor, ", + abs_block, jb / (gfs1 ? 1 : sbd.bsize)); gfs2_log_descriptor_in(&ld, jbuf); print_gfs2("type %d ", ld.ld_type); @@ -2306,50 +2421,50 @@ void dump_journal(const char *journal) print_gfs2("len:%u, data1: %u", ld.ld_length, ld.ld_data1); eol(0); - print_gfs2(" "); + print_gfs2(" "); if (gfs1) b = (uint64_t *)(jbuf + sizeof(struct gfs_log_descriptor)); else b = (uint64_t *)(jbuf + sizeof(struct gfs2_log_descriptor)); - while (*b && (char *)b < (jbuf + sbd.bsize)) { - if (!termlines || - (print_entry_ndx >= start_row[dmode] && - ((print_entry_ndx - start_row[dmode])+1) * - lines_per_row[dmode] <= termlines - start_line - 2)) { - if (i && i % 4 == 0) { - eol(0); - print_gfs2(" "); - } - i++; - print_gfs2("0x%08llx ", be64_to_cpu(*b)); - } - b++; - if (gfs1) - b++; - } - eol(0); + ld_blocks = ld.ld_data1; + ld_blocks -= print_ld_blocks(b, (jbuf + sbd.bsize), + start_line); } else if (get_block_type(jbuf) == GFS2_METATYPE_LH) { struct gfs2_log_header lh; struct gfs_log_header lh1; if (gfs1) { gfs_log_header_in(&lh1, jbuf); - print_gfs2("Block #%4llx: Log header: Flags = " - "%08x, Seq = 0x%x, first = 0x%x " - "tail = 0x%x, last = 0x%x", + check_journal_wrap(lh1.lh_sequence, + &highest_seq); + print_gfs2("0x%llx (j+%4llx): Log header: " + "Flags:%x, Seq: 0x%x, " + "1st: 0x%x, tail: 0x%x, " + "last: 0x%x", abs_block, jb, lh1.lh_flags, lh1.lh_sequence, lh1.lh_first, lh1.lh_tail, lh1.lh_last_dump); } else { gfs2_log_header_in(&lh, jbuf); - print_gfs2("Block #%4llx: Log header: Seq" - "= 0x%x, tail = 0x%x, blk = 0x%x", + check_journal_wrap(lh.lh_sequence, + &highest_seq); + print_gfs2("0x%llx (j+%4llx): Log header: Seq" + ": 0x%x, tail: 0x%x, blk: 0x%x", + abs_block, jb / sbd.bsize, lh.lh_sequence, lh.lh_tail, lh.lh_blkno); } eol(0); + } else if (gfs1 && ld_blocks > 0) { + print_gfs2("0x%llx (j+%4llx): GFS log descriptor" + " continuation block", abs_block, jb); + eol(0); + print_gfs2(" "); + ld_blocks -= print_ld_blocks((uint64_t *)jbuf, + (jbuf + sbd.bsize), + start_line); } } brelse(j_bh, not_updated);