From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8658 invoked by alias); 30 Jul 2008 22:22:23 -0000 Received: (qmail 8652 invoked by alias); 30 Jul 2008 22:22:23 -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: STABLE2 - 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/STABLE2 X-Git-Reftype: branch X-Git-Oldrev: 82fb630c2f5b055ca04a22b3525e5f6bbe3478b8 X-Git-Newrev: 9c002edb83960dcb151117e04ba1eb36c50fa243 From: Bob Peterson Message-Id: <20080730222133.CD3C512001F@lists.fedorahosted.org> Date: Wed, 30 Jul 2008 22:25: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/msg00183.txt.bz2 Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=9c002edb83960dcb151117e04ba1eb36c50fa243 Commit: 9c002edb83960dcb151117e04ba1eb36c50fa243 Parent: 82fb630c2f5b055ca04a22b3525e5f6bbe3478b8 Author: Bob Peterson AuthorDate: Wed Jul 30 17:16:52 2008 -0500 Committer: Bob Peterson CommitterDate: Wed Jul 30 17:16:52 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 78de17f..534d8cb 100644 --- a/gfs2/edit/hexedit.c +++ b/gfs2/edit/hexedit.c @@ -2237,15 +2237,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; @@ -2266,17 +2380,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, @@ -2294,8 +2409,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); @@ -2308,50 +2423,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);