* [Cluster-devel] [PATCH 1/7] libgfs2: Remove another exit() call
2014-02-28 9:35 [Cluster-devel] [PATCH 0/7] gfs2_edit journalX block reference feature and fixes Andrew Price
@ 2014-02-28 9:35 ` Andrew Price
2014-02-28 9:35 ` [Cluster-devel] [PATCH 2/7] gfs2-utils: Fix up some errors reported by clang Andrew Price
` (6 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Andrew Price @ 2014-02-28 9:35 UTC (permalink / raw)
To: cluster-devel.redhat.com
gfs2_get_leaf_nr was another one of those libgfs2 functions which called
exit instead of returning an error value. This updates it with a new
function which does so.
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/edit/savemeta.c | 6 +++++-
gfs2/fsck/pass2.c | 5 ++++-
gfs2/libgfs2/fs_ops.c | 35 ++++++++++++++++++-----------------
gfs2/libgfs2/libgfs2.h | 3 +--
4 files changed, 28 insertions(+), 21 deletions(-)
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
index b4c85d6..c38c5ac 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -543,7 +543,11 @@ static void save_inode_data(struct metafd *mfd)
int li;
for (li = 0; li < (1 << inode->i_di.di_depth); li++) {
- gfs2_get_leaf_nr(inode, li, &leaf_no);
+ if (!lgfs2_get_leaf_ptr(inode, li, &leaf_no)) {
+ fprintf(stderr, "Could not read leaf index %d in dinode %"PRIu64"\n", li,
+ (uint64_t)inode->i_di.di_num.no_addr);
+ exit(-1);
+ }
if (leaf_no == old_leaf ||
gfs2_check_range(&sbd, leaf_no) != 0)
continue;
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index d3b56fc..9fd5be2 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -369,7 +369,10 @@ static int wrong_leaf(struct gfs2_inode *ip, struct gfs2_inum *entry,
de->de_type) == 0) {
log_err(_("The misplaced directory entry was moved to a "
"valid leaf block.\n"));
- gfs2_get_leaf_nr(ip, hash_index, &real_leaf);
+ if (!lgfs2_get_leaf_ptr(ip, hash_index, &real_leaf)) {
+ log_err(_("Could not read leaf %d in dinode %"PRIu64": %s\n"), hash_index,
+ (uint64_t)ip->i_di.di_num.no_addr, strerror(errno));
+ }
if (real_leaf != planned_leaf) {
log_err(_("The planned leaf was split. The new leaf "
"is: %llu (0x%llx). di_blocks=%llu\n"),
diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
index f59f014..198f6eb 100644
--- a/gfs2/libgfs2/fs_ops.c
+++ b/gfs2/libgfs2/fs_ops.c
@@ -25,7 +25,7 @@ static __inline__ uint64_t *metapointer(struct gfs2_buffer_head *bh,
}
/* Detect directory is a stuffed inode */
-static int inode_is_stuffed(struct gfs2_inode *ip)
+static int inode_is_stuffed(const struct gfs2_inode *ip)
{
return !ip->i_di.di_height;
}
@@ -819,20 +819,15 @@ void dirent2_del(struct gfs2_inode *dip, struct gfs2_buffer_head *bh,
prev->de_rec_len = cpu_to_be16(prev_rec_len);
}
-void gfs2_get_leaf_nr(struct gfs2_inode *dip, uint32_t lindex,
- uint64_t *leaf_out)
+int lgfs2_get_leaf_ptr(struct gfs2_inode *dip, const uint32_t lindex, uint64_t *ptr)
{
uint64_t leaf_no;
- int count;
-
- count = gfs2_readi(dip, (char *)&leaf_no, lindex * sizeof(uint64_t),
- sizeof(uint64_t));
- if (count != sizeof(uint64_t)) {
- fprintf(stderr, "gfs2_get_leaf_nr: Bad internal read.\n");
- exit(1);
- }
+ int count = gfs2_readi(dip, (char *)&leaf_no, lindex * sizeof(uint64_t), sizeof(uint64_t));
+ if (count != sizeof(uint64_t))
+ return -1;
- *leaf_out = be64_to_cpu(leaf_no);
+ *ptr = be64_to_cpu(leaf_no);
+ return 0;
}
void dir_split_leaf(struct gfs2_inode *dip, uint32_t start, uint64_t leaf_no,
@@ -1034,13 +1029,15 @@ int gfs2_get_leaf(struct gfs2_inode *dip, uint64_t leaf_no,
* Returns: 0 on success, error code otherwise
*/
-static int get_first_leaf(struct gfs2_inode *dip, uint32_t lindex,
- struct gfs2_buffer_head **bh_out)
+static int get_first_leaf(struct gfs2_inode *dip, uint32_t lindex, struct gfs2_buffer_head **bh_out)
{
uint64_t leaf_no;
- gfs2_get_leaf_nr(dip, lindex, &leaf_no);
+ if (lgfs2_get_leaf_ptr(dip, lindex, &leaf_no) != 0)
+ return -1;
*bh_out = bread(dip->i_sbd, leaf_no);
+ if (*bh_out == NULL)
+ return -1;
return 0;
}
@@ -1085,7 +1082,9 @@ restart:
else
lindex = 0;
- gfs2_get_leaf_nr(dip, lindex, &leaf_no);
+ err = lgfs2_get_leaf_ptr(dip, lindex, &leaf_no);
+ if (err)
+ return err;
for (;;) {
bh = bread(dip->i_sbd, leaf_no);
@@ -1630,7 +1629,9 @@ static int dir_e_del(struct gfs2_inode *dip, const char *filename, int len)
lindex = (1 << (dip->i_di.di_depth))-1;
for(; (lindex >= 0) && !found; lindex--){
- gfs2_get_leaf_nr(dip, lindex, &leaf_no);
+ error = lgfs2_get_leaf_ptr(dip, lindex, &leaf_no);
+ if (error)
+ return error;
while(leaf_no && !found){
bh = bread(dip->i_sbd, leaf_no);
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 6372128..6248e4b 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -479,8 +479,7 @@ extern int gfs2_dirent_del(struct gfs2_inode *dip, const char *filename,
int filename_len);
extern void block_map(struct gfs2_inode *ip, uint64_t lblock, int *new,
uint64_t *dblock, uint32_t *extlen, int prealloc);
-extern void gfs2_get_leaf_nr(struct gfs2_inode *dip, uint32_t index,
- uint64_t *leaf_out);
+extern int lgfs2_get_leaf_ptr(struct gfs2_inode *dip, uint32_t index, uint64_t *ptr) __attribute__((warn_unused_result));
extern void dir_split_leaf(struct gfs2_inode *dip, uint32_t start,
uint64_t leaf_no, struct gfs2_buffer_head *obh);
extern void gfs2_free_block(struct gfs2_sbd *sdp, uint64_t block);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 10+ messages in thread* [Cluster-devel] [PATCH 2/7] gfs2-utils: Fix up some errors reported by clang
2014-02-28 9:35 [Cluster-devel] [PATCH 0/7] gfs2_edit journalX block reference feature and fixes Andrew Price
2014-02-28 9:35 ` [Cluster-devel] [PATCH 1/7] libgfs2: Remove another exit() call Andrew Price
@ 2014-02-28 9:35 ` Andrew Price
2014-02-28 9:35 ` [Cluster-devel] [PATCH 3/7] gfs2_edit: Separate out the journal-related functions to journal.c Andrew Price
` (5 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Andrew Price @ 2014-02-28 9:35 UTC (permalink / raw)
To: cluster-devel.redhat.com
Clang's analyzer found some potential memory leaks, most of which in
reality could never manifest, but it highlighted some places where
malloc and memset were being used unnecessarily, so those have been
removed and replaced with calloc() or literal assignments.
There were also some cases of dead assignments and initialisations, and
uses of uninitialised variables which have also been fixed up.
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/edit/savemeta.c | 7 +++---
gfs2/fsck/inode_hash.c | 6 +----
gfs2/fsck/main.c | 2 +-
gfs2/fsck/pass2.c | 64 +++++++-------------------------------------------
gfs2/fsck/pass3.c | 22 +++--------------
gfs2/fsck/rgrepair.c | 12 ++++------
gfs2/fsck/util.c | 21 +++++------------
gfs2/libgfs2/gfs2l.c | 1 +
gfs2/libgfs2/rgrp.c | 4 +---
9 files changed, 29 insertions(+), 110 deletions(-)
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
index c38c5ac..676bc29 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -397,12 +397,12 @@ static int save_block(int fd, struct metafd *mfd, uint64_t blk)
*/
static void save_ea_block(struct metafd *mfd, struct gfs2_buffer_head *metabh)
{
- int i, e, ea_len = sbd.bsize;
+ int e;
struct gfs2_ea_header ea;
- for (e = sizeof(struct gfs2_meta_header); e < sbd.bsize; e += ea_len) {
+ for (e = sizeof(struct gfs2_meta_header); e < sbd.bsize; e += ea.ea_rec_len) {
uint64_t blk, *b;
- int charoff;
+ int charoff, i;
gfs2_ea_header_in(&ea, metabh->b_data + e);
for (i = 0; i < ea.ea_num_ptrs; i++) {
@@ -417,7 +417,6 @@ static void save_ea_block(struct metafd *mfd, struct gfs2_buffer_head *metabh)
}
if (!ea.ea_rec_len)
break;
- ea_len = ea.ea_rec_len;
}
}
diff --git a/gfs2/fsck/inode_hash.c b/gfs2/fsck/inode_hash.c
index d5a35ce..aca5e61 100644
--- a/gfs2/fsck/inode_hash.c
+++ b/gfs2/fsck/inode_hash.c
@@ -46,15 +46,11 @@ struct inode_info *inodetree_insert(struct gfs2_inum di_num)
return cur;
}
- data = malloc(sizeof(struct inode_info));
+ data = calloc(1, sizeof(struct inode_info));
if (!data) {
log_crit( _("Unable to allocate inode_info structure\n"));
return NULL;
}
- if (!memset(data, 0, sizeof(struct inode_info))) {
- log_crit( _("Error while zeroing inode_info structure\n"));
- return NULL;
- }
/* Add new node and rebalance tree. */
data->di_num.no_addr = di_num.no_addr;
data->di_num.no_formal_ino = di_num.no_formal_ino;
diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c
index b4b1a03..346e580 100644
--- a/gfs2/fsck/main.c
+++ b/gfs2/fsck/main.c
@@ -154,7 +154,7 @@ static int check_statfs(struct gfs2_sbd *sdp)
struct osi_node *n, *next = NULL;
struct rgrp_tree *rgd;
struct gfs2_rindex *ri;
- struct gfs2_statfs_change sc;
+ struct gfs2_statfs_change sc = {0,};
char buf[sizeof(struct gfs2_statfs_change)];
int count;
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index 9fd5be2..c8c047e 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -1413,7 +1413,6 @@ static int check_hash_tbl(struct gfs2_inode *ip, uint64_t *tbl,
struct gfs2_buffer_head *lbh;
int factor;
uint32_t proper_start;
- uint32_t next_proper_start;
int anomaly;
lindex = 0;
@@ -1423,9 +1422,9 @@ static int check_hash_tbl(struct gfs2_inode *ip, uint64_t *tbl,
len = 1;
factor = 0;
leafblk = be64_to_cpu(tbl[lindex]);
- next_proper_start = lindex;
anomaly = 0;
while (lindex + (len << 1) - 1 < hsize) {
+ uint32_t next_proper_start;
if (be64_to_cpu(tbl[lindex + (len << 1) - 1]) !=
leafblk)
break;
@@ -1714,9 +1713,6 @@ static int check_system_dir(struct gfs2_inode *sysinode, const char *dirname,
{
uint64_t iblock = 0, cur_blks;
struct dir_status ds = {0};
- char *filename;
- int filename_len;
- char tmp_name[256];
int error = 0;
log_info( _("Checking system directory inode '%s'\n"), dirname);
@@ -1761,30 +1757,12 @@ static int check_system_dir(struct gfs2_inode *sysinode, const char *dirname,
log_err( _("No '.' entry found for %s directory.\n"), dirname);
if (query( _("Is it okay to add '.' entry? (y/n) "))) {
cur_blks = sysinode->i_di.di_blocks;
- sprintf(tmp_name, ".");
- filename_len = strlen(tmp_name); /* no trailing NULL */
- if (!(filename = malloc(sizeof(char) * filename_len))) {
- log_err( _("Unable to allocate name string\n"));
- stack;
- return -1;
- }
- if (!(memset(filename, 0, sizeof(char) *
- filename_len))) {
- log_err( _("Unable to zero name string\n"));
- stack;
- free(filename);
- return -1;
- }
- memcpy(filename, tmp_name, filename_len);
log_warn( _("Adding '.' entry\n"));
- error = dir_add(sysinode, filename, filename_len,
- &(sysinode->i_di.di_num),
- (sysinode->i_sbd->gfs1 ?
- GFS_FILE_DIR : DT_DIR));
+ error = dir_add(sysinode, ".", 1, &(sysinode->i_di.di_num),
+ (sysinode->i_sbd->gfs1 ? GFS_FILE_DIR : DT_DIR));
if (error) {
- log_err(_("Error adding directory %s: %s\n"),
- filename, strerror(errno));
- free(filename);
+ log_err(_("Error adding directory %s: %s\n"), "'.'",
+ strerror(errno));
return -errno;
}
if (cur_blks != sysinode->i_di.di_blocks)
@@ -1793,7 +1771,6 @@ static int check_system_dir(struct gfs2_inode *sysinode, const char *dirname,
incr_link_count(sysinode->i_di.di_num, sysinode,
"sysinode \".\"");
ds.entry_count++;
- free(filename);
} else
log_err( _("The directory was not fixed.\n"));
}
@@ -1874,9 +1851,6 @@ int pass2(struct gfs2_sbd *sdp)
uint8_t q;
struct dir_status ds = {0};
struct gfs2_inode *ip;
- char *filename;
- int filename_len;
- char tmp_name[256];
int error = 0;
/* Check all the system directory inodes. */
@@ -2007,31 +1981,12 @@ int pass2(struct gfs2_sbd *sdp)
(unsigned long long)dirblk);
if (query( _("Is it okay to add '.' entry? (y/n) "))) {
- sprintf(tmp_name, ".");
- filename_len = strlen(tmp_name); /* no trailing
- NULL */
- if (!(filename = malloc(sizeof(char) *
- filename_len))) {
- log_err(_("Unable to allocate name\n"));
- stack;
- return FSCK_ERROR;
- }
- if (!memset(filename, 0, sizeof(char) *
- filename_len)) {
- log_err( _("Unable to zero name\n"));
- stack;
- return FSCK_ERROR;
- }
- memcpy(filename, tmp_name, filename_len);
-
cur_blks = ip->i_di.di_blocks;
- error = dir_add(ip, filename, filename_len,
- &(ip->i_di.di_num),
- (sdp->gfs1 ? GFS_FILE_DIR :
- DT_DIR));
+ error = dir_add(ip, ".", 1, &(ip->i_di.di_num),
+ (sdp->gfs1 ? GFS_FILE_DIR : DT_DIR));
if (error) {
- log_err(_("Error adding directory %s: %s\n"),
- filename, strerror(errno));
+ log_err(_("Error adding directory %s: %s\n"), "'.'",
+ strerror(errno));
return -errno;
}
if (cur_blks != ip->i_di.di_blocks) {
@@ -2047,7 +2002,6 @@ int pass2(struct gfs2_sbd *sdp)
incr_link_count(ip->i_di.di_num, ip,
_("\". (itself)\""));
ds.entry_count++;
- free(filename);
log_err( _("The directory was fixed.\n"));
} else {
log_err( _("The directory was not fixed.\n"));
diff --git a/gfs2/fsck/pass3.c b/gfs2/fsck/pass3.c
index 4894d8c..6448da3 100644
--- a/gfs2/fsck/pass3.c
+++ b/gfs2/fsck/pass3.c
@@ -19,8 +19,9 @@
static int attach_dotdot_to(struct gfs2_sbd *sdp, uint64_t newdotdot,
uint64_t olddotdot, uint64_t block)
{
- char *filename;
- int filename_len, err;
+ const char *filename = "..";
+ int filename_len = 2;
+ int err;
struct gfs2_inode *ip, *pip;
uint64_t cur_blks;
@@ -33,22 +34,6 @@ static int attach_dotdot_to(struct gfs2_sbd *sdp, uint64_t newdotdot,
* '..' entry for this directory in
* this case? */
- filename_len = strlen("..");
- if (!(filename = malloc((sizeof(char) * filename_len) + 1))) {
- log_err( _("Unable to allocate name\n"));
- fsck_inode_put(&ip);
- fsck_inode_put(&pip);
- stack;
- return -1;
- }
- if (!memset(filename, 0, (sizeof(char) * filename_len) + 1)) {
- log_err( _("Unable to zero name\n"));
- fsck_inode_put(&ip);
- fsck_inode_put(&pip);
- stack;
- return -1;
- }
- memcpy(filename, "..", filename_len);
if (gfs2_dirent_del(ip, filename, filename_len))
log_warn( _("Unable to remove \"..\" directory entry.\n"));
else
@@ -72,7 +57,6 @@ static int attach_dotdot_to(struct gfs2_sbd *sdp, uint64_t newdotdot,
incr_link_count(pip->i_di.di_num, ip, _("new \"..\""));
fsck_inode_put(&ip);
fsck_inode_put(&pip);
- free(filename);
return 0;
}
diff --git a/gfs2/fsck/rgrepair.c b/gfs2/fsck/rgrepair.c
index 2c1d613..4fdbcf7 100644
--- a/gfs2/fsck/rgrepair.c
+++ b/gfs2/fsck/rgrepair.c
@@ -327,7 +327,6 @@ static uint64_t find_next_rgrp_dist(struct gfs2_sbd *sdp, uint64_t blk,
rgrp_dist++;
}
if (found) {
- block = next_block;
log_info( _("rgrp found at 0x%llx, length=%d, "
"used=%llu, free=%d\n"),
prevrgd->ri.ri_addr, length,
@@ -442,7 +441,7 @@ static int gfs2_rindex_rebuild(struct gfs2_sbd *sdp, int *num_rgs,
uint64_t first_rg_dist, initial_first_rg_dist;
struct rgrp_tree *calc_rgd, *prev_rgd;
int number_of_rgs, rgi;
- int rg_was_fnd = FALSE, corrupt_rgs = 0, bitmap_was_fnd;
+ int rg_was_fnd = FALSE, corrupt_rgs = 0;
sdp->rgcalc.osi_node = NULL;
initial_first_rg_dist = first_rg_dist = sdp->sb_addr + 1;
@@ -489,13 +488,10 @@ static int gfs2_rindex_rebuild(struct gfs2_sbd *sdp, int *num_rgs,
/* ------------------------------------------------ */
/* Now go through and count the bitmaps for this RG */
/* ------------------------------------------------ */
- bitmap_was_fnd = FALSE;
- for (fwd_block = blk + 1;
- fwd_block < sdp->device.length;
- fwd_block++) {
+ for (fwd_block = blk + 1; fwd_block < sdp->device.length; fwd_block++) {
+ int bitmap_was_fnd;
bh = bread(sdp, fwd_block);
- bitmap_was_fnd =
- (!gfs2_check_meta(bh, GFS2_METATYPE_RB));
+ bitmap_was_fnd = !gfs2_check_meta(bh, GFS2_METATYPE_RB);
brelse(bh);
if (bitmap_was_fnd) /* if a bitmap */
calc_rgd->ri.ri_length++;
diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c
index 3e3050f..f8ccb3e 100644
--- a/gfs2/fsck/util.c
+++ b/gfs2/fsck/util.c
@@ -365,14 +365,9 @@ int add_duplicate_ref(struct gfs2_inode *ip, uint64_t block,
/* Check for the inode on the invalid inode reference list. */
uint8_t q;
- if (!(id = malloc(sizeof(*id)))) {
- log_crit( _("Unable to allocate "
- "inode_with_dups structure\n"));
- return meta_error;
- }
- if (!(memset(id, 0, sizeof(*id)))) {
- log_crit( _("Unable to zero inode_with_dups "
- "structure\n"));
+ id = calloc(1, sizeof(*id));
+ if (!id) {
+ log_crit( _("Unable to allocate inode_with_dups structure\n"));
return meta_error;
}
id->block_no = ip->i_di.di_num.no_addr;
@@ -429,15 +424,11 @@ struct dir_info *dirtree_insert(struct gfs2_inum inum)
return cur;
}
- data = malloc(sizeof(struct dir_info));
+ data = calloc(1, sizeof(struct dir_info));
if (!data) {
log_crit( _("Unable to allocate dir_info structure\n"));
return NULL;
}
- if (!memset(data, 0, sizeof(struct dir_info))) {
- log_crit( _("Error while zeroing dir_info structure\n"));
- return NULL;
- }
/* Add new node and rebalance tree. */
data->dinode.no_addr = inum.no_addr;
data->dinode.no_formal_ino = inum.no_formal_ino;
@@ -555,8 +546,8 @@ struct gfs2_bmap *gfs2_bmap_create(struct gfs2_sbd *sdp, uint64_t size,
struct gfs2_bmap *il;
*addl_mem_needed = 0L;
- il = malloc(sizeof(*il));
- if (!il || !memset(il, 0, sizeof(*il)))
+ il = calloc(1, sizeof(*il));
+ if (!il)
return NULL;
if (gfs2_blockmap_create(il, size)) {
diff --git a/gfs2/libgfs2/gfs2l.c b/gfs2/libgfs2/gfs2l.c
index e58c827..eda9531 100644
--- a/gfs2/libgfs2/gfs2l.c
+++ b/gfs2/libgfs2/gfs2l.c
@@ -172,6 +172,7 @@ int main(int argc, char *argv[])
ret = lgfs2_lang_parsef(state, opts.src);
if (ret != 0) {
fprintf(stderr, "Parse failed\n");
+ free(opts.fspath);
return ret;
}
diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c
index 8fe7b6d..0752772 100644
--- a/gfs2/libgfs2/rgrp.c
+++ b/gfs2/libgfs2/rgrp.c
@@ -182,11 +182,9 @@ struct rgrp_tree *rgrp_insert(struct osi_root *rgtree, uint64_t rgblock)
return cur;
}
- data = malloc(sizeof(struct rgrp_tree));
+ data = calloc(1, sizeof(struct rgrp_tree));
if (!data)
return NULL;
- if (!memset(data, 0, sizeof(struct rgrp_tree)))
- return NULL;
/* Add new node and rebalance tree. */
data->ri.ri_addr = rgblock;
osi_link_node(&data->node, parent, newn);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 10+ messages in thread* [Cluster-devel] [PATCH 3/7] gfs2_edit: Separate out the journal-related functions to journal.c
2014-02-28 9:35 [Cluster-devel] [PATCH 0/7] gfs2_edit journalX block reference feature and fixes Andrew Price
2014-02-28 9:35 ` [Cluster-devel] [PATCH 1/7] libgfs2: Remove another exit() call Andrew Price
2014-02-28 9:35 ` [Cluster-devel] [PATCH 2/7] gfs2-utils: Fix up some errors reported by clang Andrew Price
@ 2014-02-28 9:35 ` Andrew Price
2014-02-28 9:35 ` [Cluster-devel] [PATCH 4/7] gfs2_edit: Add more intelligence to journal dumps Andrew Price
` (4 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Andrew Price @ 2014-02-28 9:35 UTC (permalink / raw)
To: cluster-devel.redhat.com
From: Bob Peterson <rpeterso@redhat.com>
This patch takes all the code related to dumping journals and puts them
all in a separate journal.c. This will later be used for journal parsing.
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---
gfs2/edit/Makefile.am | 4 +-
gfs2/edit/hexedit.c | 323 +---------------------------------------------
gfs2/edit/hexedit.h | 2 +
gfs2/edit/journal.c | 349 ++++++++++++++++++++++++++++++++++++++++++++++++++
gfs2/edit/journal.h | 8 ++
5 files changed, 363 insertions(+), 323 deletions(-)
create mode 100644 gfs2/edit/journal.c
create mode 100644 gfs2/edit/journal.h
diff --git a/gfs2/edit/Makefile.am b/gfs2/edit/Makefile.am
index c4814dc..8b977ae 100644
--- a/gfs2/edit/Makefile.am
+++ b/gfs2/edit/Makefile.am
@@ -2,9 +2,9 @@ MAINTAINERCLEANFILES = Makefile.in
sbin_PROGRAMS = gfs2_edit
-noinst_HEADERS = gfs2hex.h hexedit.h extended.h
+noinst_HEADERS = gfs2hex.h hexedit.h extended.h journal.h
-gfs2_edit_SOURCES = gfs2hex.c hexedit.c savemeta.c extended.c
+gfs2_edit_SOURCES = gfs2hex.c hexedit.c savemeta.c extended.c journal.c
gfs2_edit_CPPFLAGS = -D_FILE_OFFSET_BITS=64 -DHELPER_PROGRAM \
-I$(top_srcdir)/gfs2/include \
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
index cf57ec8..18d06c7 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -26,6 +26,7 @@
#include "libgfs2.h"
#include "gfs2hex.h"
#include "extended.h"
+#include "journal.h"
const char *mtypes[] = {"none", "sb", "rg", "rb", "di", "in", "lf", "jd",
"lh", "ld", "ea", "ed", "lb", "13", "qc"};
@@ -577,7 +578,7 @@ static void print_usage(void)
/* returns: metatype if block is a GFS2 structure block type */
/* 0 if block is not a GFS2 structure */
/* ------------------------------------------------------------------------ */
-static uint32_t get_block_type(const struct gfs2_buffer_head *lbh)
+uint32_t get_block_type(const struct gfs2_buffer_head *lbh)
{
const struct gfs2_meta_header *mh = lbh->iov.iov_base;
@@ -1508,61 +1509,6 @@ static uint64_t pop_block(void)
}
/* ------------------------------------------------------------------------ */
-/* find_journal_block - figure out where a journal starts, given the name */
-/* Returns: journal block number, changes j_size to the journal size */
-/* ------------------------------------------------------------------------ */
-static uint64_t find_journal_block(const char *journal, uint64_t *j_size)
-{
- int journal_num;
- uint64_t jindex_block, jblock = 0;
- int amtread;
- struct gfs2_buffer_head *jindex_bh, *j_bh;
- char jbuf[sbd.bsize];
-
- journal_num = atoi(journal + 7);
- /* Figure out the block of the jindex file */
- if (sbd.gfs1)
- jindex_block = sbd1->sb_jindex_di.no_addr;
- else
- jindex_block = masterblock("jindex");
- /* read in the block */
- jindex_bh = bread(&sbd, jindex_block);
- /* get the dinode data from it. */
- gfs2_dinode_in(&di, jindex_bh); /* parse disk inode to struct*/
-
- if (!sbd.gfs1)
- do_dinode_extended(&di, jindex_bh); /* parse dir. */
-
- if (sbd.gfs1) {
- struct gfs2_inode *jiinode;
- struct gfs_jindex ji;
-
- jiinode = lgfs2_inode_get(&sbd, jindex_bh);
- if (jiinode == NULL)
- return 0;
- amtread = gfs2_readi(jiinode, (void *)&jbuf,
- journal_num * sizeof(struct gfs_jindex),
- sizeof(struct gfs_jindex));
- if (amtread) {
- gfs_jindex_in(&ji, jbuf);
- jblock = ji.ji_addr;
- *j_size = ji.ji_nsegment * 0x10;
- }
- inode_put(&jiinode);
- } else {
- struct gfs2_dinode jdi;
-
- jblock = indirect->ii[0].dirent[journal_num + 2].block;
- j_bh = bread(&sbd, jblock);
- gfs2_dinode_in(&jdi, j_bh);/* parse dinode to struct */
- *j_size = jdi.di_size;
- brelse(j_bh);
- }
- brelse(jindex_bh);
- return jblock;
-}
-
-/* ------------------------------------------------------------------------ */
/* Find next metadata block of a given type AFTER a given point in the fs */
/* */
/* This is used to find blocks that aren't represented in the bitmaps, such */
@@ -2577,271 +2523,6 @@ 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 */
-/* ------------------------------------------------------------------------ */
-static 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 (sbd.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. */
-/* ------------------------------------------------------------------------ */
-static int fsck_readi(struct gfs2_inode *ip, void *rbuf, uint64_t roffset,
- unsigned int size, uint64_t *abs_block)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- struct gfs2_buffer_head *lbh;
- 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 (roffset >= ip->i_di.di_size)
- return 0;
- if ((roffset + size) > ip->i_di.di_size)
- size = ip->i_di.di_size - roffset;
- if (!size)
- return 0;
- if (isdir) {
- o = roffset % sdp->sd_jbsize;
- lblock = roffset / sdp->sd_jbsize;
- } else {
- lblock = roffset >> sdp->sd_sb.sb_bsize_shift;
- o = roffset & (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);
- if (dblock) {
- lbh = bread(sdp, dblock);
- if (*abs_block == 0)
- *abs_block = lbh->b_blocknr;
- dblock++;
- extlen--;
- } else
- lbh = NULL;
- if (lbh) {
- memcpy(rbuf, lbh->b_data + o, amount);
- brelse(lbh);
- } else {
- memset(rbuf, 0, amount);
- }
- copied += amount;
- lblock++;
- o = (isdir) ? sizeof(struct gfs2_meta_header) : 0;
- }
- return copied;
-}
-
-static 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;
-}
-
-static int is_meta(struct gfs2_buffer_head *lbh)
-{
- uint32_t check_magic = ((struct gfs2_meta_header *)(lbh->b_data))->mh_magic;
-
- check_magic = be32_to_cpu(check_magic);
- if (check_magic == GFS2_MAGIC)
- return 1;
- return 0;
-}
-
-/* ------------------------------------------------------------------------ */
-/* dump_journal - dump a journal file's contents. */
-/* ------------------------------------------------------------------------ */
-static void dump_journal(const char *journal)
-{
- struct gfs2_buffer_head *j_bh = NULL, dummy_bh;
- uint64_t jblock, j_size, jb, abs_block, saveblk;
- int error, start_line, journal_num;
- struct gfs2_inode *j_inode = NULL;
- int ld_blocks = 0;
- uint64_t highest_seq = 0;
- char *jbuf = NULL;
-
- start_line = line;
- lines_per_row[dmode] = 1;
- error = 0;
- journal_num = atoi(journal + 7);
- print_gfs2("Dumping journal #%d.", journal_num);
- eol(0);
- jblock = find_journal_block(journal, &j_size);
- if (!jblock)
- return;
- if (!sbd.gfs1) {
- j_bh = bread(&sbd, jblock);
- j_inode = lgfs2_inode_get(&sbd, j_bh);
- if (j_inode == NULL) {
- fprintf(stderr, "Out of memory\n");
- exit(-1);
- }
- jbuf = malloc(sbd.bsize);
- if (jbuf == NULL) {
- fprintf(stderr, "Out of memory\n");
- exit(-1);
- }
- }
-
- for (jb = 0; jb < j_size; jb += (sbd.gfs1 ? 1:sbd.bsize)) {
- if (sbd.gfs1) {
- if (j_bh)
- brelse(j_bh);
- j_bh = bread(&sbd, jblock + jb);
- abs_block = jblock + jb;
- dummy_bh.b_data = j_bh->b_data;
- } else {
- error = fsck_readi(j_inode, (void *)jbuf, jb,
- sbd.bsize, &abs_block);
- if (!error) /* end of file */
- break;
- dummy_bh.b_data = jbuf;
- }
- if (get_block_type(&dummy_bh) == GFS2_METATYPE_LD) {
- uint64_t *b;
- struct gfs2_log_descriptor ld;
- int ltndx;
- uint32_t logtypes[2][6] = {
- {GFS2_LOG_DESC_METADATA,
- GFS2_LOG_DESC_REVOKE,
- GFS2_LOG_DESC_JDATA,
- 0, 0, 0},
- {GFS_LOG_DESC_METADATA,
- GFS_LOG_DESC_IUL,
- GFS_LOG_DESC_IDA,
- GFS_LOG_DESC_Q,
- GFS_LOG_DESC_LAST,
- 0}};
- const char *logtypestr[2][6] = {
- {"Metadata", "Revoke", "Jdata",
- "Unknown", "Unknown", "Unknown"},
- {"Metadata", "Unlinked inode", "Dealloc inode",
- "Quota", "Final Entry", "Unknown"}};
-
- print_gfs2("0x%llx (j+%4llx): Log descriptor, ",
- abs_block, jb / (sbd.gfs1 ? 1 : sbd.bsize));
- gfs2_log_descriptor_in(&ld, &dummy_bh);
- print_gfs2("type %d ", ld.ld_type);
-
- for (ltndx = 0;; ltndx++) {
- if (ld.ld_type == logtypes[sbd.gfs1][ltndx] ||
- logtypes[sbd.gfs1][ltndx] == 0)
- break;
- }
- print_gfs2("(%s) ", logtypestr[sbd.gfs1][ltndx]);
- print_gfs2("len:%u, data1: %u",
- ld.ld_length, ld.ld_data1);
- eol(0);
- print_gfs2(" ");
- if (sbd.gfs1)
- b = (uint64_t *)(dummy_bh.b_data +
- sizeof(struct gfs_log_descriptor));
- else
- b = (uint64_t *)(dummy_bh.b_data +
- sizeof(struct gfs2_log_descriptor));
- ld_blocks = ld.ld_data1;
- ld_blocks -= print_ld_blocks(b, (dummy_bh.b_data +
- sbd.bsize),
- start_line);
- } else if (get_block_type(&dummy_bh) == GFS2_METATYPE_LH) {
- struct gfs2_log_header lh;
- struct gfs_log_header lh1;
-
- if (sbd.gfs1) {
- gfs_log_header_in(&lh1, &dummy_bh);
- 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, &dummy_bh);
- 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 (sbd.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 *)dummy_bh.b_data,
- (dummy_bh.b_data +
- sbd.bsize), start_line);
- } else if (details && is_meta(&dummy_bh)) {
- saveblk = block;
- block = abs_block;
- display(0);
- block = saveblk;
- }
- }
- inode_put(&j_inode);
- brelse(j_bh);
- blockhist = -1; /* So we don't print anything else */
- free(jbuf);
-}
-
-/* ------------------------------------------------------------------------ */
/* usage - print command line usage */
/* ------------------------------------------------------------------------ */
static void usage(void)
diff --git a/gfs2/edit/hexedit.h b/gfs2/edit/hexedit.h
index 7615242..53a0c72 100644
--- a/gfs2/edit/hexedit.h
+++ b/gfs2/edit/hexedit.h
@@ -67,6 +67,7 @@ extern const char *block_type_str[15];
extern int dsplines;
extern int dsp_lines[DMODES];
extern int combined_display;
+extern int details;
struct gfs2_dirents {
uint64_t block;
@@ -236,5 +237,6 @@ extern uint64_t check_keywords(const char *kword);
extern uint64_t masterblock(const char *fn);
extern void gfs_rgrp_print(struct gfs_rgrp *rg);
extern int has_indirect_blocks(void);
+extern uint32_t get_block_type(const struct gfs2_buffer_head *lbh);
#endif /* __HEXVIEW_DOT_H__ */
diff --git a/gfs2/edit/journal.c b/gfs2/edit/journal.c
new file mode 100644
index 0000000..102b4b9
--- /dev/null
+++ b/gfs2/edit/journal.c
@@ -0,0 +1,349 @@
+#include "clusterautoconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <linux/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <curses.h>
+#include <term.h>
+#include <time.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <dirent.h>
+
+#include <linux/gfs2_ondisk.h>
+#include "copyright.cf"
+
+#include "hexedit.h"
+#include "libgfs2.h"
+#include "extended.h"
+#include "gfs2hex.h"
+#include "journal.h"
+
+/* ------------------------------------------------------------------------ */
+/* find_journal_block - figure out where a journal starts, given the name */
+/* Returns: journal block number, changes j_size to the journal size */
+/* ------------------------------------------------------------------------ */
+uint64_t find_journal_block(const char *journal, uint64_t *j_size)
+{
+ int journal_num;
+ uint64_t jindex_block, jblock = 0;
+ int amtread;
+ struct gfs2_buffer_head *jindex_bh, *j_bh;
+ char jbuf[sbd.bsize];
+
+ journal_num = atoi(journal + 7);
+ /* Figure out the block of the jindex file */
+ if (sbd.gfs1)
+ jindex_block = sbd1->sb_jindex_di.no_addr;
+ else
+ jindex_block = masterblock("jindex");
+ /* read in the block */
+ jindex_bh = bread(&sbd, jindex_block);
+ /* get the dinode data from it. */
+ gfs2_dinode_in(&di, jindex_bh); /* parse disk inode to struct*/
+
+ if (!sbd.gfs1)
+ do_dinode_extended(&di, jindex_bh); /* parse dir. */
+
+ if (sbd.gfs1) {
+ struct gfs2_inode *jiinode;
+ struct gfs_jindex ji;
+
+ jiinode = lgfs2_inode_get(&sbd, jindex_bh);
+ if (jiinode == NULL)
+ return 0;
+ amtread = gfs2_readi(jiinode, (void *)&jbuf,
+ journal_num * sizeof(struct gfs_jindex),
+ sizeof(struct gfs_jindex));
+ if (amtread) {
+ gfs_jindex_in(&ji, jbuf);
+ jblock = ji.ji_addr;
+ *j_size = ji.ji_nsegment * 0x10;
+ }
+ inode_put(&jiinode);
+ } else {
+ struct gfs2_dinode jdi;
+
+ jblock = indirect->ii[0].dirent[journal_num + 2].block;
+ j_bh = bread(&sbd, jblock);
+ gfs2_dinode_in(&jdi, j_bh);/* parse dinode to struct */
+ *j_size = jdi.di_size;
+ brelse(j_bh);
+ }
+ brelse(jindex_bh);
+ return jblock;
+}
+
+static 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;
+}
+
+static int is_meta(struct gfs2_buffer_head *lbh)
+{
+ uint32_t check_magic = ((struct gfs2_meta_header *)(lbh->b_data))->mh_magic;
+
+ check_magic = be32_to_cpu(check_magic);
+ if (check_magic == GFS2_MAGIC)
+ return 1;
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+/* fsck_readi - same as libgfs2's gfs2_readi, but sets absolute block # */
+/* of the first bit of data read. */
+/* ------------------------------------------------------------------------ */
+static int fsck_readi(struct gfs2_inode *ip, void *rbuf, uint64_t roffset,
+ unsigned int size, uint64_t *abs_block)
+{
+ struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_buffer_head *lbh;
+ 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 (roffset >= ip->i_di.di_size)
+ return 0;
+ if ((roffset + size) > ip->i_di.di_size)
+ size = ip->i_di.di_size - roffset;
+ if (!size)
+ return 0;
+ if (isdir) {
+ o = roffset % sdp->sd_jbsize;
+ lblock = roffset / sdp->sd_jbsize;
+ } else {
+ lblock = roffset >> sdp->sd_sb.sb_bsize_shift;
+ o = roffset & (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);
+ if (dblock) {
+ lbh = bread(sdp, dblock);
+ if (*abs_block == 0)
+ *abs_block = lbh->b_blocknr;
+ dblock++;
+ extlen--;
+ } else
+ lbh = NULL;
+ if (lbh) {
+ memcpy(rbuf, lbh->b_data + o, amount);
+ brelse(lbh);
+ } else {
+ memset(rbuf, 0, amount);
+ }
+ copied += amount;
+ lblock++;
+ o = (isdir) ? sizeof(struct gfs2_meta_header) : 0;
+ }
+ return copied;
+}
+
+/* ------------------------------------------------------------------------ */
+/* print_ld_blocks - print all blocks given in a log descriptor */
+/* returns: the number of block numbers it printed */
+/* ------------------------------------------------------------------------ */
+static 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 (sbd.gfs1)
+ b++;
+ }
+ eol(0);
+ return bcount;
+}
+
+/* ------------------------------------------------------------------------ */
+/* dump_journal - dump a journal file's contents. */
+/* ------------------------------------------------------------------------ */
+void dump_journal(const char *journal)
+{
+ struct gfs2_buffer_head *j_bh = NULL, dummy_bh;
+ uint64_t jblock, j_size, jb, abs_block, saveblk;
+ int error, start_line, journal_num;
+ struct gfs2_inode *j_inode = NULL;
+ int ld_blocks = 0;
+ uint64_t highest_seq = 0;
+ char *jbuf = NULL;
+
+ start_line = line;
+ lines_per_row[dmode] = 1;
+ error = 0;
+ journal_num = atoi(journal + 7);
+ print_gfs2("Dumping journal #%d.", journal_num);
+ eol(0);
+ jblock = find_journal_block(journal, &j_size);
+ if (!jblock)
+ return;
+ if (!sbd.gfs1) {
+ j_bh = bread(&sbd, jblock);
+ j_inode = lgfs2_inode_get(&sbd, j_bh);
+ if (j_inode == NULL) {
+ fprintf(stderr, "Out of memory\n");
+ exit(-1);
+ }
+ jbuf = malloc(sbd.bsize);
+ if (jbuf == NULL) {
+ fprintf(stderr, "Out of memory\n");
+ exit(-1);
+ }
+ }
+
+ for (jb = 0; jb < j_size; jb += (sbd.gfs1 ? 1:sbd.bsize)) {
+ if (sbd.gfs1) {
+ if (j_bh)
+ brelse(j_bh);
+ j_bh = bread(&sbd, jblock + jb);
+ abs_block = jblock + jb;
+ dummy_bh.b_data = j_bh->b_data;
+ } else {
+ error = fsck_readi(j_inode, (void *)jbuf, jb,
+ sbd.bsize, &abs_block);
+ if (!error) /* end of file */
+ break;
+ dummy_bh.b_data = jbuf;
+ }
+ if (get_block_type(&dummy_bh) == GFS2_METATYPE_LD) {
+ uint64_t *b;
+ struct gfs2_log_descriptor ld;
+ int ltndx;
+ uint32_t logtypes[2][6] = {
+ {GFS2_LOG_DESC_METADATA,
+ GFS2_LOG_DESC_REVOKE,
+ GFS2_LOG_DESC_JDATA,
+ 0, 0, 0},
+ {GFS_LOG_DESC_METADATA,
+ GFS_LOG_DESC_IUL,
+ GFS_LOG_DESC_IDA,
+ GFS_LOG_DESC_Q,
+ GFS_LOG_DESC_LAST,
+ 0}};
+ const char *logtypestr[2][6] = {
+ {"Metadata", "Revoke", "Jdata",
+ "Unknown", "Unknown", "Unknown"},
+ {"Metadata", "Unlinked inode", "Dealloc inode",
+ "Quota", "Final Entry", "Unknown"}};
+
+ print_gfs2("0x%llx (j+%4llx): Log descriptor, ",
+ abs_block, jb / (sbd.gfs1 ? 1 : sbd.bsize));
+ gfs2_log_descriptor_in(&ld, &dummy_bh);
+ print_gfs2("type %d ", ld.ld_type);
+
+ for (ltndx = 0;; ltndx++) {
+ if (ld.ld_type == logtypes[sbd.gfs1][ltndx] ||
+ logtypes[sbd.gfs1][ltndx] == 0)
+ break;
+ }
+ print_gfs2("(%s) ", logtypestr[sbd.gfs1][ltndx]);
+ print_gfs2("len:%u, data1: %u",
+ ld.ld_length, ld.ld_data1);
+ eol(0);
+ print_gfs2(" ");
+ if (sbd.gfs1)
+ b = (uint64_t *)(dummy_bh.b_data +
+ sizeof(struct gfs_log_descriptor));
+ else
+ b = (uint64_t *)(dummy_bh.b_data +
+ sizeof(struct gfs2_log_descriptor));
+ ld_blocks = ld.ld_data1;
+ ld_blocks -= print_ld_blocks(b, (dummy_bh.b_data +
+ sbd.bsize),
+ start_line);
+ } else if (get_block_type(&dummy_bh) == GFS2_METATYPE_LH) {
+ struct gfs2_log_header lh;
+ struct gfs_log_header lh1;
+
+ if (sbd.gfs1) {
+ gfs_log_header_in(&lh1, &dummy_bh);
+ 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, &dummy_bh);
+ 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 (sbd.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 *)dummy_bh.b_data,
+ (dummy_bh.b_data +
+ sbd.bsize), start_line);
+ } else if (details && is_meta(&dummy_bh)) {
+ saveblk = block;
+ block = abs_block;
+ display(0);
+ block = saveblk;
+ }
+ }
+ inode_put(&j_inode);
+ brelse(j_bh);
+ blockhist = -1; /* So we don't print anything else */
+ free(jbuf);
+}
diff --git a/gfs2/edit/journal.h b/gfs2/edit/journal.h
new file mode 100644
index 0000000..e227a77
--- /dev/null
+++ b/gfs2/edit/journal.h
@@ -0,0 +1,8 @@
+#ifndef __JOURNAL_DOT_H__
+#define __JOURNAL_DOT_H__
+
+extern void dump_journal(const char *journal);
+extern uint64_t find_journal_block(const char *journal, uint64_t *j_size);
+
+
+#endif
--
1.8.5.3
^ permalink raw reply related [flat|nested] 10+ messages in thread* [Cluster-devel] [PATCH 4/7] gfs2_edit: Add more intelligence to journal dumps
2014-02-28 9:35 [Cluster-devel] [PATCH 0/7] gfs2_edit journalX block reference feature and fixes Andrew Price
` (2 preceding siblings ...)
2014-02-28 9:35 ` [Cluster-devel] [PATCH 3/7] gfs2_edit: Separate out the journal-related functions to journal.c Andrew Price
@ 2014-02-28 9:35 ` Andrew Price
2014-02-28 9:35 ` [Cluster-devel] [PATCH 5/7] gfs2_edit: Use the metadata description in get_block_type Andrew Price
` (3 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Andrew Price @ 2014-02-28 9:35 UTC (permalink / raw)
To: cluster-devel.redhat.com
From: Bob Peterson <rpeterso@redhat.com>
This patch adds the ability for a gfs2_edit journal dump to look for
journal entries pertaining to a particular block. The syntax is:
gfs2_edit -p journal0 0x12345 /dev/my_vg/my_lv
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---
gfs2/edit/hexedit.c | 150 ++++++++++++------
gfs2/edit/hexedit.h | 6 +-
gfs2/edit/journal.c | 420 ++++++++++++++++++++++++++++++++++++++++-----------
gfs2/edit/journal.h | 3 +-
gfs2/edit/savemeta.c | 2 +-
5 files changed, 442 insertions(+), 139 deletions(-)
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
index 18d06c7..0aa0771 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -45,8 +45,6 @@ int details = 0;
long int gziplevel = 9;
static int termcols;
-int display(int identify_only);
-
/* for assigning numeric fields: */
#define checkassign(strfield, struct, member, value) do { \
if (strcmp(#member, strfield) == 0) { \
@@ -578,14 +576,73 @@ static void print_usage(void)
/* returns: metatype if block is a GFS2 structure block type */
/* 0 if block is not a GFS2 structure */
/* ------------------------------------------------------------------------ */
-uint32_t get_block_type(const struct gfs2_buffer_head *lbh)
+uint32_t get_block_type(const struct gfs2_buffer_head *lbh, int *structlen)
{
const struct gfs2_meta_header *mh = lbh->iov.iov_base;
+ uint32_t ty;
- if (be32_to_cpu(mh->mh_magic) == GFS2_MAGIC)
- return be32_to_cpu(mh->mh_type);
+ if (!be32_to_cpu(mh->mh_magic) == GFS2_MAGIC)
+ return 0;
- return 0;
+ ty = be32_to_cpu(mh->mh_type);
+ if (structlen == NULL)
+ return ty;
+ switch (ty) {
+ case GFS2_METATYPE_SB: /* 1 */
+ if (sbd.gfs1)
+ *structlen = sizeof(struct gfs_sb);
+ else
+ *structlen = sizeof(struct gfs2_sb);
+ break;
+ case GFS2_METATYPE_RG: /* 2 */
+ *structlen = sizeof(struct gfs2_rgrp);
+ break;
+ case GFS2_METATYPE_RB: /* 3 */
+ *structlen = sizeof(struct gfs2_meta_header);
+ break;
+ case GFS2_METATYPE_DI: /* 4 */
+ *structlen = sizeof(struct gfs2_dinode);
+ break;
+ case GFS2_METATYPE_IN: /* 5 */
+ if (sbd.gfs1)
+ *structlen = sizeof(struct gfs_indirect);
+ else
+ *structlen = sizeof(struct gfs2_meta_header);
+ break;
+ case GFS2_METATYPE_LF: /* 6 */
+ *structlen = sizeof(struct gfs2_leaf);
+ break;
+ case GFS2_METATYPE_JD:
+ *structlen = sizeof(struct gfs2_meta_header);
+ break;
+ case GFS2_METATYPE_LH:
+ *structlen = sizeof(struct gfs2_log_header);
+ break;
+ case GFS2_METATYPE_LD:
+ if (sbd.gfs1)
+ *structlen = sizeof(struct gfs_log_descriptor);
+ else
+ *structlen = sizeof(struct gfs2_log_descriptor);
+ break;
+ case GFS2_METATYPE_EA:
+ *structlen = sizeof(struct gfs2_meta_header) +
+ sizeof(struct gfs2_ea_header);
+ break;
+ case GFS2_METATYPE_ED:
+ *structlen = sizeof(struct gfs2_meta_header) +
+ sizeof(struct gfs2_ea_header);
+ break;
+ case GFS2_METATYPE_LB:
+ *structlen = sizeof(struct gfs2_meta_header);
+ break;
+ case GFS2_METATYPE_QC:
+ *structlen = sizeof(struct gfs2_quota_change);
+ break;
+ default:
+ *structlen = sbd.bsize;
+ break;
+ }
+ return ty;
}
/* ------------------------------------------------------------------------ */
@@ -629,78 +686,52 @@ int display_block_type(int from_restore)
ret_type = GFS2_METATYPE_DI;
struct_len = 0;
} else {
- ret_type = get_block_type(bh);
+ ret_type = get_block_type(bh, &struct_len);
switch (ret_type) {
case GFS2_METATYPE_SB: /* 1 */
print_gfs2("(superblock)");
- if (sbd.gfs1)
- struct_len = sizeof(struct gfs_sb);
- else
- struct_len = sizeof(struct gfs2_sb);
break;
case GFS2_METATYPE_RG: /* 2 */
print_gfs2("(rsrc grp hdr)");
- struct_len = sizeof(struct gfs2_rgrp);
break;
case GFS2_METATYPE_RB: /* 3 */
print_gfs2("(rsrc grp bitblk)");
- struct_len = sizeof(struct gfs2_meta_header);
break;
case GFS2_METATYPE_DI: /* 4 */
print_gfs2("(disk inode)");
- struct_len = sizeof(struct gfs2_dinode);
break;
case GFS2_METATYPE_IN: /* 5 */
print_gfs2("(indir blklist)");
- if (sbd.gfs1)
- struct_len = sizeof(struct gfs_indirect);
- else
- struct_len = sizeof(struct gfs2_meta_header);
break;
case GFS2_METATYPE_LF: /* 6 */
print_gfs2("(directory leaf)");
- struct_len = sizeof(struct gfs2_leaf);
break;
case GFS2_METATYPE_JD:
print_gfs2("(journal data)");
- struct_len = sizeof(struct gfs2_meta_header);
break;
case GFS2_METATYPE_LH:
print_gfs2("(log header)");
- struct_len = sizeof(struct gfs2_log_header);
break;
case GFS2_METATYPE_LD:
print_gfs2("(log descriptor)");
- if (sbd.gfs1)
- struct_len = sizeof(struct gfs_log_descriptor);
- else
- struct_len =
- sizeof(struct gfs2_log_descriptor);
break;
case GFS2_METATYPE_EA:
print_gfs2("(extended attr hdr)");
- struct_len = sizeof(struct gfs2_meta_header) +
- sizeof(struct gfs2_ea_header);
break;
case GFS2_METATYPE_ED:
print_gfs2("(extended attr data)");
- struct_len = sizeof(struct gfs2_meta_header) +
- sizeof(struct gfs2_ea_header);
break;
case GFS2_METATYPE_LB:
print_gfs2("(log buffer)");
- struct_len = sizeof(struct gfs2_meta_header);
break;
case GFS2_METATYPE_QC:
print_gfs2("(quota change)");
- struct_len = sizeof(struct gfs2_quota_change);
break;
case 0:
struct_len = sbd.bsize;
break;
default:
print_gfs2("(wtf?)");
- struct_len = sbd.bsize;
break;
}
}
@@ -855,18 +886,26 @@ static const struct lgfs2_metadata *find_mtype(uint32_t mtype, const unsigned ve
/* ------------------------------------------------------------------------ */
/* hexdump - hex dump the filesystem block to the screen */
/* ------------------------------------------------------------------------ */
-static int hexdump(uint64_t startaddr, int len)
+static int hexdump(uint64_t startaddr, int len, int trunc_zeros,
+ uint64_t flagref)
{
- const unsigned char *pointer,*ptr2;
+ const unsigned char *pointer, *ptr2;
int i;
uint64_t l;
const char *lpBuffer = bh->b_data;
+ const char *zeros_strt = lpBuffer + sbd.bsize;
int print_field, cursor_line;
- const uint32_t block_type = get_block_type(bh);
+ const uint32_t block_type = get_block_type(bh, NULL);
+ uint64_t *ref;
strcpy(edit_fmt,"%02x");
pointer = (unsigned char *)lpBuffer + offset;
ptr2 = (unsigned char *)lpBuffer + offset;
+ ref = (uint64_t *)lpBuffer + offset;
+ if (trunc_zeros) {
+ while (zeros_strt > lpBuffer && (*(zeros_strt - 1) == 0))
+ zeros_strt--;
+ }
l = offset;
print_entry_ndx = 0;
while (((termlines && line < termlines &&
@@ -997,9 +1036,20 @@ static int hexdump(uint64_t startaddr, int len)
}
if (line - 3 > last_entry_onscreen[dmode])
last_entry_onscreen[dmode] = line - 3;
+ if (flagref && be64_to_cpu(*ref) == flagref)
+ print_gfs2("<------------------------- ref to 0x%llx",
+ flagref);
+ ref++;
+ if (flagref && be64_to_cpu(*ref) == flagref)
+ print_gfs2("<------------------------- ref to 0x%llx",
+ flagref);
+ ref++;
eol(0);
- l+=16;
+ l += 16;
print_entry_ndx++;
+ /* This should only happen if trunc_zeros is specified: */
+ if ((const char *)pointer >= zeros_strt)
+ break;
} /* while */
if (sbd.gfs1) {
COLORS_NORMAL;
@@ -1351,7 +1401,7 @@ static void read_master_dir(void)
/* ------------------------------------------------------------------------ */
/* display */
/* ------------------------------------------------------------------------ */
-int display(int identify_only)
+int display(int identify_only, int trunc_zeros, uint64_t flagref)
{
uint64_t blk;
@@ -1446,7 +1496,8 @@ int display(int identify_only)
}
if (dmode == HEX_MODE) /* if hex display mode */
hexdump(dev_offset, (gfs2_struct_type == GFS2_METATYPE_DI)?
- struct_len + di.di_size:sbd.bsize);
+ struct_len + di.di_size:sbd.bsize, trunc_zeros,
+ flagref);
else if (dmode == GFS2_MODE) { /* if structure display */
if (block != JOURNALS_DUMMY_BLOCK)
display_gfs2(); /* display the gfs2 structure */
@@ -1970,7 +2021,7 @@ static void find_print_block_type(void)
tblock = blockstack[blockhist % BLOCK_STACK_SIZE].block;
lbh = bread(&sbd, tblock);
- type = get_block_type(lbh);
+ type = get_block_type(lbh, NULL);
print_block_type(tblock, type, "");
brelse(lbh);
gfs2_rgrp_free(&sbd.rgtree);
@@ -2104,7 +2155,7 @@ static void process_field(const char *field, const char *nstr)
setstring = 1;
fblock = blockstack[blockhist % BLOCK_STACK_SIZE].block;
rbh = bread(&sbd, fblock);
- type = get_block_type(rbh);
+ type = get_block_type(rbh, NULL);
switch (type) {
case GFS2_METATYPE_SB:
gfs2_sb_in(&lsb, rbh);
@@ -2251,7 +2302,7 @@ static void interactive_mode(void)
Quit = FALSE;
editing = FALSE;
while (!Quit) {
- display(FALSE);
+ display(FALSE, 0, 0);
if (editing) {
if (edit_row[dmode] == -1)
block = goto_block();
@@ -2720,9 +2771,16 @@ static void process_parameters(int argc, char *argv[], int pass)
if (termlines || strchr(argv[i],'/')) /* if print or slash */
continue;
- if (!strncmp(argv[i], "journal", 7) &&
- isdigit(argv[i][7])) {
- dump_journal(argv[i]);
+ if (!strncmp(argv[i], "journal", 7) && isdigit(argv[i][7])) {
+ int blk = 0;
+
+ if (i < argc - 1 && isdigit(argv[i + 1][0])) {
+ if (argv[i + 1][0]=='0' && argv[i + 1][1]=='x')
+ sscanf(argv[i + 1], "%x", &blk);
+ else
+ blk = atoi(argv[i + 1]);
+ }
+ dump_journal(argv[i], blk);
continue;
}
keyword_blk = check_keywords(argv[i]);
@@ -2926,7 +2984,7 @@ int main(int argc, char *argv[])
block = blockstack[i + 1].block;
if (!block)
break;
- display(identify);
+ display(identify, 0, 0);
if (!identify) {
display_extended();
printf("-------------------------------------" \
diff --git a/gfs2/edit/hexedit.h b/gfs2/edit/hexedit.h
index 53a0c72..715e3f2 100644
--- a/gfs2/edit/hexedit.h
+++ b/gfs2/edit/hexedit.h
@@ -68,6 +68,7 @@ extern int dsplines;
extern int dsp_lines[DMODES];
extern int combined_display;
extern int details;
+extern const char *allocdesc[2][5];
struct gfs2_dirents {
uint64_t block;
@@ -232,11 +233,12 @@ extern void gfs_dinode_in(struct gfs_dinode *di, struct gfs2_buffer_head *bh);
extern void savemeta(char *out_fn, int saveoption, int gziplevel);
extern void restoremeta(const char *in_fn, const char *out_device,
uint64_t printblocksonly);
-extern int display(int identify_only);
+extern int display(int identify_only, int trunc_zeros, uint64_t flagref);
extern uint64_t check_keywords(const char *kword);
extern uint64_t masterblock(const char *fn);
extern void gfs_rgrp_print(struct gfs_rgrp *rg);
extern int has_indirect_blocks(void);
-extern uint32_t get_block_type(const struct gfs2_buffer_head *lbh);
+extern uint32_t get_block_type(const struct gfs2_buffer_head *lbh,
+ int *structlen);
#endif /* __HEXVIEW_DOT_H__ */
diff --git a/gfs2/edit/journal.c b/gfs2/edit/journal.c
index 102b4b9..c69f349 100644
--- a/gfs2/edit/journal.c
+++ b/gfs2/edit/journal.c
@@ -28,10 +28,10 @@
#include "gfs2hex.h"
#include "journal.h"
-/* ------------------------------------------------------------------------ */
-/* find_journal_block - figure out where a journal starts, given the name */
-/* Returns: journal block number, changes j_size to the journal size */
-/* ------------------------------------------------------------------------ */
+/**
+ * find_journal_block - figure out where a journal starts, given the name
+ * Returns: journal block number, changes j_size to the journal size
+ */
uint64_t find_journal_block(const char *journal, uint64_t *j_size)
{
int journal_num;
@@ -108,10 +108,10 @@ static int is_meta(struct gfs2_buffer_head *lbh)
return 0;
}
-/* ------------------------------------------------------------------------ */
-/* fsck_readi - same as libgfs2's gfs2_readi, but sets absolute block # */
-/* of the first bit of data read. */
-/* ------------------------------------------------------------------------ */
+/**
+ * fsck_readi - same as libgfs2's gfs2_readi, but sets absolute block #
+ * of the first bit of data read.
+ */
static int fsck_readi(struct gfs2_inode *ip, void *rbuf, uint64_t roffset,
unsigned int size, uint64_t *abs_block)
{
@@ -173,60 +173,290 @@ static int fsck_readi(struct gfs2_inode *ip, void *rbuf, uint64_t roffset,
return copied;
}
-/* ------------------------------------------------------------------------ */
-/* print_ld_blocks - print all blocks given in a log descriptor */
-/* returns: the number of block numbers it printed */
-/* ------------------------------------------------------------------------ */
-static int print_ld_blocks(const uint64_t *b, const char *end, int start_line)
+/**
+ * ld_is_pertinent - determine if a log descriptor is pertinent
+ *
+ * This function checks a log descriptor buffer to see if it contains
+ * references to a given traced block, or its rgrp bitmap block.
+ */
+static int ld_is_pertinent(const uint64_t *b, const char *end, uint64_t tblk,
+ struct rgrp_tree *rgd, uint64_t bitblk)
{
- int bcount = 0, i = 0;
+ const uint64_t *blk = b;
+
+ if (!tblk)
+ return 1;
+
+ while (*blk && (char *)blk < end) {
+ if (be64_to_cpu(*blk) == tblk || be64_to_cpu(*blk) == bitblk)
+ return 1;
+ blk++;
+ if (sbd.gfs1)
+ blk++;
+ }
+ return 0;
+}
+
+/**
+ * print_ld_blks - print all blocks given in a log descriptor
+ * returns: the number of block numbers it printed
+ */
+static int print_ld_blks(const uint64_t *b, const char *end, int start_line,
+ uint64_t tblk, uint64_t *tblk_off, uint64_t bitblk,
+ struct rgrp_tree *rgd, uint64_t abs_block, int prnt,
+ uint64_t *bblk_off, int is_meta_ld)
+{
+ int bcount = 0, found_tblk = 0, found_bblk = 0;
static char str[256];
+ if (tblk_off)
+ *tblk_off = 0;
+ if (bblk_off)
+ *bblk_off = 0;
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) {
+ if (prnt && bcount && bcount % 4 == 0) {
eol(0);
print_gfs2(" ");
}
- i++;
- sprintf(str, "0x%llx",
- (unsigned long long)be64_to_cpu(*b));
- print_gfs2("%-18.18s ", str);
bcount++;
+ if (prnt) {
+ sprintf(str, "0x%llx",
+ (unsigned long long)be64_to_cpu(*b));
+ print_gfs2("%-18.18s ", str);
+ }
+ if (!found_tblk && tblk_off)
+ (*tblk_off)++;
+ if (!found_bblk && bblk_off)
+ (*bblk_off)++;
+ if (tblk && (be64_to_cpu(*b) == tblk)) {
+ found_tblk = 1;
+ print_gfs2("<-------------------------0x%llx ",
+ (unsigned long long)tblk);
+ eol(18 * (bcount % 4) + 1);
+ print_gfs2(" ");
+ }
+ if (tblk && rgd && (be64_to_cpu(*b) == bitblk)) {
+ int type, bmap = 0;
+ uint64_t o;
+ struct gfs2_buffer_head *save_bh;
+ struct gfs2_buffer_head *j_bmap_bh;
+
+ found_bblk = 1;
+ print_gfs2("<-------------------------");
+ if (is_meta_ld) {
+ o = tblk - rgd->ri.ri_data0;
+ if (o >= (rgd->bits->bi_start +
+ rgd->bits->bi_len) *
+ GFS2_NBBY)
+ o += (sizeof(struct gfs2_rgrp) -
+ sizeof(struct gfs2_meta_header))
+ * GFS2_NBBY;
+ bmap = o / sbd.sd_blocks_per_bitmap;
+ save_bh = rgd->bh[bmap];
+ j_bmap_bh = bread(&sbd, abs_block +
+ bcount);
+ rgd->bh[bmap] = j_bmap_bh;
+ type = lgfs2_get_bitmap(&sbd, tblk,
+ rgd);
+ brelse(j_bmap_bh);
+ rgd->bh[bmap] = save_bh;
+ print_gfs2("bit for blk 0x%llx is %d "
+ "(%s)",
+ (unsigned long long)tblk,
+ type,
+ allocdesc[sbd.gfs1][type]);
+ } else {
+ print_gfs2("bitmap for blk 0x%llx "
+ "was revoked",
+ (unsigned long long)tblk);
+ }
+ eol(18 * (bcount % 4) + 1);
+ print_gfs2(" ");
+ }
}
b++;
if (sbd.gfs1)
b++;
}
- eol(0);
+ if (prnt)
+ eol(0);
+ if (!found_tblk || !is_meta_ld)
+ *tblk_off = 0;
+ if (!found_bblk || !is_meta_ld)
+ *bblk_off = 0;
return bcount;
}
-/* ------------------------------------------------------------------------ */
-/* dump_journal - dump a journal file's contents. */
-/* ------------------------------------------------------------------------ */
-void dump_journal(const char *journal)
+/**
+ * find_wrap_pt - figure out where a journal wraps
+ * Returns: The wrap point, in bytes
+ */
+static uint64_t find_wrap_pt(struct gfs2_inode *j_inode, char *jbuf,
+ uint64_t jblock, uint64_t j_size)
{
struct gfs2_buffer_head *j_bh = NULL, dummy_bh;
- uint64_t jblock, j_size, jb, abs_block, saveblk;
+ uint64_t jb, abs_block;
+ int error;
+ uint64_t highest_seq = 0;
+
+ for (jb = 0; jb < j_size; jb += (sbd.gfs1 ? 1 : sbd.bsize)) {
+ if (sbd.gfs1) {
+ if (j_bh)
+ brelse(j_bh);
+ j_bh = bread(&sbd, jblock + jb);
+ abs_block = jblock + jb;
+ dummy_bh.b_data = j_bh->b_data;
+ } else {
+ error = fsck_readi(j_inode, (void *)jbuf, jb,
+ sbd.bsize, &abs_block);
+ if (!error) /* end of file */
+ break;
+ dummy_bh.b_data = jbuf;
+ }
+ if (get_block_type(&dummy_bh, NULL) == GFS2_METATYPE_LH) {
+ struct gfs2_log_header lh;
+ struct gfs_log_header lh1;
+
+ if (sbd.gfs1) {
+ gfs_log_header_in(&lh1, &dummy_bh);
+ if (lh1.lh_sequence < highest_seq)
+ return jb;
+ highest_seq = lh1.lh_sequence;
+ } else {
+ gfs2_log_header_in(&lh, &dummy_bh);
+ if (lh.lh_sequence < highest_seq)
+ return jb;
+ highest_seq = lh.lh_sequence;
+ }
+ }
+ if (j_bh)
+ brelse(j_bh);
+ }
+ return 0;
+}
+
+/**
+ * process_ld - process a log descriptor
+ */
+static int process_ld(uint64_t abs_block, uint64_t wrappt, uint64_t j_size,
+ uint64_t jb, struct gfs2_buffer_head *dummy_bh, int tblk,
+ uint64_t *tblk_off, uint64_t bitblk,
+ struct rgrp_tree *rgd, int *prnt, uint64_t *bblk_off)
+{
+ uint64_t *b;
+ struct gfs2_log_descriptor ld;
+ int ltndx, is_meta_ld = 0;
+ int ld_blocks = 0;
+ uint32_t logtypes[2][6] = {
+ {GFS2_LOG_DESC_METADATA, GFS2_LOG_DESC_REVOKE,
+ GFS2_LOG_DESC_JDATA, 0, 0, 0},
+ {GFS_LOG_DESC_METADATA, GFS_LOG_DESC_IUL, GFS_LOG_DESC_IDA,
+ GFS_LOG_DESC_Q, GFS_LOG_DESC_LAST, 0}};
+ const char *logtypestr[2][6] = {
+ {"Metadata", "Revoke", "Jdata",
+ "Unknown", "Unknown", "Unknown"},
+ {"Metadata", "Unlinked inode", "Dealloc inode",
+ "Quota", "Final Entry", "Unknown"}};
+
+ gfs2_log_descriptor_in(&ld, dummy_bh);
+ if (sbd.gfs1)
+ b = (uint64_t *)(dummy_bh->b_data +
+ sizeof(struct gfs_log_descriptor));
+ else
+ b = (uint64_t *)(dummy_bh->b_data +
+ sizeof(struct gfs2_log_descriptor));
+ *prnt = ld_is_pertinent(b, (dummy_bh->b_data + sbd.bsize), tblk, rgd,
+ bitblk);
+
+ if (*prnt) {
+ print_gfs2("0x%llx (j+%4llx): Log descriptor, ",
+ abs_block, ((jb + wrappt) % j_size) / sbd.bsize);
+ print_gfs2("type %d ", ld.ld_type);
+
+ for (ltndx = 0;; ltndx++) {
+ if (ld.ld_type == logtypes[sbd.gfs1][ltndx] ||
+ logtypes[sbd.gfs1][ltndx] == 0)
+ break;
+ }
+ print_gfs2("(%s) ", logtypestr[sbd.gfs1][ltndx]);
+ print_gfs2("len:%u, data1: %u", ld.ld_length, ld.ld_data1);
+ eol(0);
+ print_gfs2(" ");
+ }
+ ld_blocks = ld.ld_data1;
+ if (ld.ld_type == GFS2_LOG_DESC_METADATA ||
+ ld.ld_type == GFS_LOG_DESC_METADATA)
+ is_meta_ld = 1;
+ ld_blocks -= print_ld_blks(b, (dummy_bh->b_data + sbd.bsize), line,
+ tblk, tblk_off, bitblk, rgd, abs_block,
+ *prnt, bblk_off, is_meta_ld);
+
+ return ld_blocks;
+}
+
+/**
+ * meta_has_ref - check if a metadata block references a given block
+ */
+static int meta_has_ref(uint64_t abs_block, int tblk)
+{
+ struct gfs2_buffer_head *mbh;
+ int structlen, ty, has_ref = 0;
+ uint64_t *b;
+
+ mbh = bread(&sbd, abs_block);
+ ty = get_block_type(mbh, &structlen);
+ b = (uint64_t *)(mbh->b_data + structlen);
+ while (ty && (char *)b < mbh->b_data + sbd.bsize) {
+ if (be64_to_cpu(*b) == tblk) {
+ has_ref = 1;
+ break;
+ }
+ b++;
+ }
+ brelse(mbh);
+ return has_ref;
+}
+
+/**
+ * dump_journal - dump a journal file's contents.
+ * @journal: name of the journal to dump
+ * @tblk: block number to trace in the journals
+ *
+ * This function dumps the contents of a journal. If a trace block is specified
+ * then only information printed is: (1) log descriptors that reference that
+ * block, (2) metadata in the journal that references the block, or (3)
+ * rgrp bitmaps that reference that block's allocation bit status.
+ */
+void dump_journal(const char *journal, int tblk)
+{
+ struct gfs2_buffer_head *j_bh = NULL, dummy_bh;
+ uint64_t jblock, j_size, jb, abs_block, saveblk, wrappt = 0;
int error, start_line, journal_num;
struct gfs2_inode *j_inode = NULL;
- int ld_blocks = 0;
+ int ld_blocks = 0, offset_from_ld = 0;
+ uint64_t tblk_off = 0, bblk_off = 0, bitblk = 0;
uint64_t highest_seq = 0;
char *jbuf = NULL;
+ struct rgrp_tree *rgd = NULL;
start_line = line;
lines_per_row[dmode] = 1;
error = 0;
journal_num = atoi(journal + 7);
print_gfs2("Dumping journal #%d.", journal_num);
+ if (tblk) {
+ dmode = HEX_MODE;
+ print_gfs2(" Tracing block 0x%llx", (unsigned long long)tblk);
+ }
eol(0);
jblock = find_journal_block(journal, &j_size);
if (!jblock)
return;
+
if (!sbd.gfs1) {
j_bh = bread(&sbd, jblock);
j_inode = lgfs2_inode_get(&sbd, j_bh);
@@ -241,67 +471,68 @@ void dump_journal(const char *journal)
}
}
- for (jb = 0; jb < j_size; jb += (sbd.gfs1 ? 1:sbd.bsize)) {
+ if (tblk) {
+ uint64_t wp;
+
+ rgd = gfs2_blk2rgrpd(&sbd, tblk);
+ if (!rgd) {
+ print_gfs2("Can't locate the rgrp for block 0x%x",
+ tblk);
+ eol(0);
+ } else {
+ uint64_t o;
+ int bmap = 0;
+
+ print_gfs2("rgd: 0x%llx for 0x%x, ", rgd->ri.ri_addr,
+ rgd->ri.ri_length);
+ o = tblk - rgd->ri.ri_data0;
+ if (o >= (rgd->bits->bi_start +
+ rgd->bits->bi_len) * GFS2_NBBY)
+ o += (sizeof(struct gfs2_rgrp) -
+ sizeof(struct gfs2_meta_header))
+ * GFS2_NBBY;
+ bmap = o / sbd.sd_blocks_per_bitmap;
+ bitblk = rgd->ri.ri_addr + bmap;
+ print_gfs2("bitmap: %d, bitblk: 0x%llx", bmap,
+ (unsigned long long)bitblk);
+ eol(0);
+ }
+
+ wrappt = find_wrap_pt(j_inode, jbuf, jblock, j_size);
+ wp = wrappt / (sbd.gfs1 ? 1 : sbd.bsize);
+ print_gfs2("Starting at journal wrap block: 0x%llx "
+ "(j + 0x%llx)",
+ (unsigned long long)jblock + wp,
+ (unsigned long long)wp);
+ eol(0);
+ }
+
+ for (jb = 0; jb < j_size; jb += (sbd.gfs1 ? 1 : sbd.bsize)) {
+ int is_pertinent = 1;
+
if (sbd.gfs1) {
if (j_bh)
brelse(j_bh);
- j_bh = bread(&sbd, jblock + jb);
- abs_block = jblock + jb;
+ abs_block = jblock + ((jb + wrappt) % j_size);
+ j_bh = bread(&sbd, abs_block);
dummy_bh.b_data = j_bh->b_data;
} else {
- error = fsck_readi(j_inode, (void *)jbuf, jb,
+ error = fsck_readi(j_inode, (void *)jbuf,
+ ((jb + wrappt) % j_size),
sbd.bsize, &abs_block);
if (!error) /* end of file */
break;
dummy_bh.b_data = jbuf;
}
- if (get_block_type(&dummy_bh) == GFS2_METATYPE_LD) {
- uint64_t *b;
- struct gfs2_log_descriptor ld;
- int ltndx;
- uint32_t logtypes[2][6] = {
- {GFS2_LOG_DESC_METADATA,
- GFS2_LOG_DESC_REVOKE,
- GFS2_LOG_DESC_JDATA,
- 0, 0, 0},
- {GFS_LOG_DESC_METADATA,
- GFS_LOG_DESC_IUL,
- GFS_LOG_DESC_IDA,
- GFS_LOG_DESC_Q,
- GFS_LOG_DESC_LAST,
- 0}};
- const char *logtypestr[2][6] = {
- {"Metadata", "Revoke", "Jdata",
- "Unknown", "Unknown", "Unknown"},
- {"Metadata", "Unlinked inode", "Dealloc inode",
- "Quota", "Final Entry", "Unknown"}};
-
- print_gfs2("0x%llx (j+%4llx): Log descriptor, ",
- abs_block, jb / (sbd.gfs1 ? 1 : sbd.bsize));
- gfs2_log_descriptor_in(&ld, &dummy_bh);
- print_gfs2("type %d ", ld.ld_type);
-
- for (ltndx = 0;; ltndx++) {
- if (ld.ld_type == logtypes[sbd.gfs1][ltndx] ||
- logtypes[sbd.gfs1][ltndx] == 0)
- break;
- }
- print_gfs2("(%s) ", logtypestr[sbd.gfs1][ltndx]);
- print_gfs2("len:%u, data1: %u",
- ld.ld_length, ld.ld_data1);
- eol(0);
- print_gfs2(" ");
- if (sbd.gfs1)
- b = (uint64_t *)(dummy_bh.b_data +
- sizeof(struct gfs_log_descriptor));
- else
- b = (uint64_t *)(dummy_bh.b_data +
- sizeof(struct gfs2_log_descriptor));
- ld_blocks = ld.ld_data1;
- ld_blocks -= print_ld_blocks(b, (dummy_bh.b_data +
- sbd.bsize),
- start_line);
- } else if (get_block_type(&dummy_bh) == GFS2_METATYPE_LH) {
+ offset_from_ld++;
+ if (get_block_type(&dummy_bh, NULL) == GFS2_METATYPE_LD) {
+ ld_blocks = process_ld(abs_block, wrappt, j_size, jb,
+ &dummy_bh, tblk, &tblk_off,
+ bitblk, rgd, &is_pertinent,
+ &bblk_off);
+ offset_from_ld = 0;
+ } else if (!tblk &&
+ get_block_type(&dummy_bh, NULL) == GFS2_METATYPE_LH) {
struct gfs2_log_header lh;
struct gfs_log_header lh1;
@@ -310,10 +541,10 @@ void dump_journal(const char *journal)
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,
+ "Flags:%x, Seq: 0x%x, 1st: 0x%x, "
+ "tail: 0x%x, last: 0x%x",
+ abs_block, jb + wrappt,
+ lh1.lh_flags, lh1.lh_sequence,
lh1.lh_first, lh1.lh_tail,
lh1.lh_last_dump);
} else {
@@ -322,8 +553,8 @@ void dump_journal(const char *journal)
&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,
+ abs_block, ((jb + wrappt) % j_size)
+ / sbd.bsize, lh.lh_sequence,
lh.lh_tail, lh.lh_blkno);
}
eol(0);
@@ -332,13 +563,24 @@ void dump_journal(const char *journal)
" continuation block", abs_block, jb);
eol(0);
print_gfs2(" ");
- ld_blocks -= print_ld_blocks((uint64_t *)dummy_bh.b_data,
- (dummy_bh.b_data +
- sbd.bsize), start_line);
- } else if (details && is_meta(&dummy_bh)) {
+ ld_blocks -= print_ld_blks((uint64_t *)dummy_bh.b_data,
+ (dummy_bh.b_data +
+ sbd.bsize), start_line,
+ tblk, &tblk_off, 0, rgd,
+ 0, 1, NULL, 1);
+ } else if (!is_meta(&dummy_bh)) {
+ continue;
+ }
+ /* Check if this metadata block references the block we're
+ trying to trace. */
+ if (details ||
+ (is_pertinent && tblk &&
+ ((tblk_off && offset_from_ld == tblk_off) ||
+ (bblk_off && offset_from_ld == bblk_off))) ||
+ meta_has_ref(abs_block, tblk)) {
saveblk = block;
block = abs_block;
- display(0);
+ display(0, tblk ? 1 : 0, tblk);
block = saveblk;
}
}
@@ -346,4 +588,6 @@ void dump_journal(const char *journal)
brelse(j_bh);
blockhist = -1; /* So we don't print anything else */
free(jbuf);
+ if (!termlines)
+ fflush(stdout);
}
diff --git a/gfs2/edit/journal.h b/gfs2/edit/journal.h
index e227a77..1e5968b 100644
--- a/gfs2/edit/journal.h
+++ b/gfs2/edit/journal.h
@@ -1,8 +1,7 @@
#ifndef __JOURNAL_DOT_H__
#define __JOURNAL_DOT_H__
-extern void dump_journal(const char *journal);
+extern void dump_journal(const char *journal, int tblk);
extern uint64_t find_journal_block(const char *journal, uint64_t *j_size);
-
#endif
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
index 676bc29..c5a33db 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -932,7 +932,7 @@ static int restore_data(int fd, gzFile gzin_fd, int printblocksonly,
block = savedata->blk;
if (printblocksonly > 1 && printblocksonly == block) {
block_in_mem = block;
- display(0);
+ display(0, 0, 0);
return 0;
} else if (printblocksonly == 1) {
print_gfs2("%d (l=0x%x): ", blks_saved,
--
1.8.5.3
^ permalink raw reply related [flat|nested] 10+ messages in thread* [Cluster-devel] [PATCH 5/7] gfs2_edit: Use the metadata description in get_block_type
2014-02-28 9:35 [Cluster-devel] [PATCH 0/7] gfs2_edit journalX block reference feature and fixes Andrew Price
` (3 preceding siblings ...)
2014-02-28 9:35 ` [Cluster-devel] [PATCH 4/7] gfs2_edit: Add more intelligence to journal dumps Andrew Price
@ 2014-02-28 9:35 ` Andrew Price
2014-02-28 9:35 ` [Cluster-devel] [PATCH 6/7] gfs2_edit: Report referencing block address in the new journal code Andrew Price
` (2 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Andrew Price @ 2014-02-28 9:35 UTC (permalink / raw)
To: cluster-devel.redhat.com
Replace the large switch statement in get_block_type() with calls to
lgfs2_get_block_type() and lgfs2_find_mtype().
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/edit/hexedit.c | 68 ++++++-----------------------------------------------
1 file changed, 7 insertions(+), 61 deletions(-)
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
index 0aa0771..ac91c83 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -578,69 +578,15 @@ static void print_usage(void)
/* ------------------------------------------------------------------------ */
uint32_t get_block_type(const struct gfs2_buffer_head *lbh, int *structlen)
{
- const struct gfs2_meta_header *mh = lbh->iov.iov_base;
- uint32_t ty;
+ uint32_t ty = lgfs2_get_block_type(lbh);
- if (!be32_to_cpu(mh->mh_magic) == GFS2_MAGIC)
- return 0;
-
- ty = be32_to_cpu(mh->mh_type);
- if (structlen == NULL)
- return ty;
- switch (ty) {
- case GFS2_METATYPE_SB: /* 1 */
- if (sbd.gfs1)
- *structlen = sizeof(struct gfs_sb);
- else
- *structlen = sizeof(struct gfs2_sb);
- break;
- case GFS2_METATYPE_RG: /* 2 */
- *structlen = sizeof(struct gfs2_rgrp);
- break;
- case GFS2_METATYPE_RB: /* 3 */
- *structlen = sizeof(struct gfs2_meta_header);
- break;
- case GFS2_METATYPE_DI: /* 4 */
- *structlen = sizeof(struct gfs2_dinode);
- break;
- case GFS2_METATYPE_IN: /* 5 */
- if (sbd.gfs1)
- *structlen = sizeof(struct gfs_indirect);
- else
- *structlen = sizeof(struct gfs2_meta_header);
- break;
- case GFS2_METATYPE_LF: /* 6 */
- *structlen = sizeof(struct gfs2_leaf);
- break;
- case GFS2_METATYPE_JD:
- *structlen = sizeof(struct gfs2_meta_header);
- break;
- case GFS2_METATYPE_LH:
- *structlen = sizeof(struct gfs2_log_header);
- break;
- case GFS2_METATYPE_LD:
- if (sbd.gfs1)
- *structlen = sizeof(struct gfs_log_descriptor);
+ if (ty != 0 && structlen != NULL) {
+ unsigned ver = sbd.gfs1 ? LGFS2_MD_GFS1 : LGFS2_MD_GFS2;
+ const struct lgfs2_metadata *mtype = lgfs2_find_mtype(ty, ver);
+ if (mtype != NULL)
+ *structlen = mtype->size;
else
- *structlen = sizeof(struct gfs2_log_descriptor);
- break;
- case GFS2_METATYPE_EA:
- *structlen = sizeof(struct gfs2_meta_header) +
- sizeof(struct gfs2_ea_header);
- break;
- case GFS2_METATYPE_ED:
- *structlen = sizeof(struct gfs2_meta_header) +
- sizeof(struct gfs2_ea_header);
- break;
- case GFS2_METATYPE_LB:
- *structlen = sizeof(struct gfs2_meta_header);
- break;
- case GFS2_METATYPE_QC:
- *structlen = sizeof(struct gfs2_quota_change);
- break;
- default:
- *structlen = sbd.bsize;
- break;
+ *structlen = sbd.bsize;
}
return ty;
}
--
1.8.5.3
^ permalink raw reply related [flat|nested] 10+ messages in thread* [Cluster-devel] [PATCH 6/7] gfs2_edit: Report referencing block address in the new journal code
2014-02-28 9:35 [Cluster-devel] [PATCH 0/7] gfs2_edit journalX block reference feature and fixes Andrew Price
` (4 preceding siblings ...)
2014-02-28 9:35 ` [Cluster-devel] [PATCH 5/7] gfs2_edit: Use the metadata description in get_block_type Andrew Price
@ 2014-02-28 9:35 ` Andrew Price
2014-02-28 9:35 ` [Cluster-devel] [PATCH 7/7] gfs2_edit: More static analysis fixes Andrew Price
2014-03-03 16:57 ` [Cluster-devel] [PATCH] gfs2_edit: Corrections to log descriptor reference parsing Bob Peterson
7 siblings, 0 replies; 10+ messages in thread
From: Andrew Price @ 2014-02-28 9:35 UTC (permalink / raw)
To: cluster-devel.redhat.com
From: Bob Peterson <rpeterso@redhat.com>
When a block is referenced in the journal, the address of the "real"
referencing block is now printed (as well as the address of the block in
the journal).
Also, when a dinode references a block as a extended attribute, it
wasn't properly flagging it as a reference. Now it does.
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/edit/hexedit.c | 19 ++++++++++---------
gfs2/edit/hexedit.h | 3 ++-
gfs2/edit/journal.c | 37 ++++++++++++++++++++++++-------------
gfs2/edit/savemeta.c | 2 +-
4 files changed, 37 insertions(+), 24 deletions(-)
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
index ac91c83..5c5ac89 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -833,7 +833,7 @@ static const struct lgfs2_metadata *find_mtype(uint32_t mtype, const unsigned ve
/* hexdump - hex dump the filesystem block to the screen */
/* ------------------------------------------------------------------------ */
static int hexdump(uint64_t startaddr, int len, int trunc_zeros,
- uint64_t flagref)
+ uint64_t flagref, uint64_t ref_blk)
{
const unsigned char *pointer, *ptr2;
int i;
@@ -983,12 +983,12 @@ static int hexdump(uint64_t startaddr, int len, int trunc_zeros,
if (line - 3 > last_entry_onscreen[dmode])
last_entry_onscreen[dmode] = line - 3;
if (flagref && be64_to_cpu(*ref) == flagref)
- print_gfs2("<------------------------- ref to 0x%llx",
- flagref);
+ print_gfs2("<------------------------- ref in 0x%llx "
+ "to 0x%llx", ref_blk, flagref);
ref++;
if (flagref && be64_to_cpu(*ref) == flagref)
- print_gfs2("<------------------------- ref to 0x%llx",
- flagref);
+ print_gfs2("<------------------------- ref in 0x%llx "
+ "to 0x%llx", ref_blk, flagref);
ref++;
eol(0);
l += 16;
@@ -1347,7 +1347,8 @@ static void read_master_dir(void)
/* ------------------------------------------------------------------------ */
/* display */
/* ------------------------------------------------------------------------ */
-int display(int identify_only, int trunc_zeros, uint64_t flagref)
+int display(int identify_only, int trunc_zeros, uint64_t flagref,
+ uint64_t ref_blk)
{
uint64_t blk;
@@ -1443,7 +1444,7 @@ int display(int identify_only, int trunc_zeros, uint64_t flagref)
if (dmode == HEX_MODE) /* if hex display mode */
hexdump(dev_offset, (gfs2_struct_type == GFS2_METATYPE_DI)?
struct_len + di.di_size:sbd.bsize, trunc_zeros,
- flagref);
+ flagref, ref_blk);
else if (dmode == GFS2_MODE) { /* if structure display */
if (block != JOURNALS_DUMMY_BLOCK)
display_gfs2(); /* display the gfs2 structure */
@@ -2248,7 +2249,7 @@ static void interactive_mode(void)
Quit = FALSE;
editing = FALSE;
while (!Quit) {
- display(FALSE, 0, 0);
+ display(FALSE, 0, 0, 0);
if (editing) {
if (edit_row[dmode] == -1)
block = goto_block();
@@ -2930,7 +2931,7 @@ int main(int argc, char *argv[])
block = blockstack[i + 1].block;
if (!block)
break;
- display(identify, 0, 0);
+ display(identify, 0, 0, 0);
if (!identify) {
display_extended();
printf("-------------------------------------" \
diff --git a/gfs2/edit/hexedit.h b/gfs2/edit/hexedit.h
index 715e3f2..541684a 100644
--- a/gfs2/edit/hexedit.h
+++ b/gfs2/edit/hexedit.h
@@ -233,7 +233,8 @@ extern void gfs_dinode_in(struct gfs_dinode *di, struct gfs2_buffer_head *bh);
extern void savemeta(char *out_fn, int saveoption, int gziplevel);
extern void restoremeta(const char *in_fn, const char *out_device,
uint64_t printblocksonly);
-extern int display(int identify_only, int trunc_zeros, uint64_t flagref);
+extern int display(int identify_only, int trunc_zeros, uint64_t flagref,
+ uint64_t ref_blk);
extern uint64_t check_keywords(const char *kword);
extern uint64_t masterblock(const char *fn);
extern void gfs_rgrp_print(struct gfs_rgrp *rg);
diff --git a/gfs2/edit/journal.c b/gfs2/edit/journal.c
index c69f349..3c2f5c7 100644
--- a/gfs2/edit/journal.c
+++ b/gfs2/edit/journal.c
@@ -204,7 +204,8 @@ static int ld_is_pertinent(const uint64_t *b, const char *end, uint64_t tblk,
static int print_ld_blks(const uint64_t *b, const char *end, int start_line,
uint64_t tblk, uint64_t *tblk_off, uint64_t bitblk,
struct rgrp_tree *rgd, uint64_t abs_block, int prnt,
- uint64_t *bblk_off, int is_meta_ld)
+ uint64_t *bblk_off, int is_meta_ld,
+ uint64_t ld_blk_refs[])
{
int bcount = 0, found_tblk = 0, found_bblk = 0;
static char str[256];
@@ -222,6 +223,8 @@ static int print_ld_blks(const uint64_t *b, const char *end, int start_line,
eol(0);
print_gfs2(" ");
}
+ if (ld_blk_refs)
+ ld_blk_refs[bcount] = be64_to_cpu(*b);
bcount++;
if (prnt) {
sprintf(str, "0x%llx",
@@ -345,7 +348,8 @@ static uint64_t find_wrap_pt(struct gfs2_inode *j_inode, char *jbuf,
static int process_ld(uint64_t abs_block, uint64_t wrappt, uint64_t j_size,
uint64_t jb, struct gfs2_buffer_head *dummy_bh, int tblk,
uint64_t *tblk_off, uint64_t bitblk,
- struct rgrp_tree *rgd, int *prnt, uint64_t *bblk_off)
+ struct rgrp_tree *rgd, int *prnt, uint64_t *bblk_off,
+ uint64_t ld_blk_refs[])
{
uint64_t *b;
struct gfs2_log_descriptor ld;
@@ -393,7 +397,7 @@ static int process_ld(uint64_t abs_block, uint64_t wrappt, uint64_t j_size,
is_meta_ld = 1;
ld_blocks -= print_ld_blks(b, (dummy_bh->b_data + sbd.bsize), line,
tblk, tblk_off, bitblk, rgd, abs_block,
- *prnt, bblk_off, is_meta_ld);
+ *prnt, bblk_off, is_meta_ld, ld_blk_refs);
return ld_blocks;
}
@@ -406,15 +410,19 @@ static int meta_has_ref(uint64_t abs_block, int tblk)
struct gfs2_buffer_head *mbh;
int structlen, ty, has_ref = 0;
uint64_t *b;
+ struct gfs2_dinode *dinode;
mbh = bread(&sbd, abs_block);
ty = get_block_type(mbh, &structlen);
+ if (ty == GFS2_METATYPE_DI) {
+ dinode = (struct gfs2_dinode *)mbh->b_data;
+ if (be64_to_cpu(dinode->di_eattr) == tblk)
+ has_ref = 1;
+ }
b = (uint64_t *)(mbh->b_data + structlen);
- while (ty && (char *)b < mbh->b_data + sbd.bsize) {
- if (be64_to_cpu(*b) == tblk) {
+ while (!has_ref && ty && (char *)b < mbh->b_data + sbd.bsize) {
+ if (be64_to_cpu(*b) == tblk)
has_ref = 1;
- break;
- }
b++;
}
brelse(mbh);
@@ -442,6 +450,7 @@ void dump_journal(const char *journal, int tblk)
uint64_t highest_seq = 0;
char *jbuf = NULL;
struct rgrp_tree *rgd = NULL;
+ uint64_t ld_blk_refs[503]; /* The most blks a LD can have */
start_line = line;
lines_per_row[dmode] = 1;
@@ -529,7 +538,7 @@ void dump_journal(const char *journal, int tblk)
ld_blocks = process_ld(abs_block, wrappt, j_size, jb,
&dummy_bh, tblk, &tblk_off,
bitblk, rgd, &is_pertinent,
- &bblk_off);
+ &bblk_off, ld_blk_refs);
offset_from_ld = 0;
} else if (!tblk &&
get_block_type(&dummy_bh, NULL) == GFS2_METATYPE_LH) {
@@ -567,20 +576,22 @@ void dump_journal(const char *journal, int tblk)
(dummy_bh.b_data +
sbd.bsize), start_line,
tblk, &tblk_off, 0, rgd,
- 0, 1, NULL, 1);
+ 0, 1, NULL, 1, NULL);
} else if (!is_meta(&dummy_bh)) {
continue;
}
/* Check if this metadata block references the block we're
trying to trace. */
- if (details ||
- (is_pertinent && tblk &&
+ if (details || (tblk && ((is_pertinent &&
((tblk_off && offset_from_ld == tblk_off) ||
(bblk_off && offset_from_ld == bblk_off))) ||
- meta_has_ref(abs_block, tblk)) {
+ meta_has_ref(abs_block, tblk)))) {
saveblk = block;
block = abs_block;
- display(0, tblk ? 1 : 0, tblk);
+ if (tblk)
+ display(0, 1, tblk, ld_blk_refs[offset_from_ld]);
+ else
+ display(0, 0, 0, 0);
block = saveblk;
}
}
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
index c5a33db..5bf7963 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -932,7 +932,7 @@ static int restore_data(int fd, gzFile gzin_fd, int printblocksonly,
block = savedata->blk;
if (printblocksonly > 1 && printblocksonly == block) {
block_in_mem = block;
- display(0, 0, 0);
+ display(0, 0, 0, 0);
return 0;
} else if (printblocksonly == 1) {
print_gfs2("%d (l=0x%x): ", blks_saved,
--
1.8.5.3
^ permalink raw reply related [flat|nested] 10+ messages in thread* [Cluster-devel] [PATCH 7/7] gfs2_edit: More static analysis fixes
2014-02-28 9:35 [Cluster-devel] [PATCH 0/7] gfs2_edit journalX block reference feature and fixes Andrew Price
` (5 preceding siblings ...)
2014-02-28 9:35 ` [Cluster-devel] [PATCH 6/7] gfs2_edit: Report referencing block address in the new journal code Andrew Price
@ 2014-02-28 9:35 ` Andrew Price
2014-03-03 16:57 ` [Cluster-devel] [PATCH] gfs2_edit: Corrections to log descriptor reference parsing Bob Peterson
7 siblings, 0 replies; 10+ messages in thread
From: Andrew Price @ 2014-02-28 9:35 UTC (permalink / raw)
To: cluster-devel.redhat.com
Fix some more minor issues found by Coverity and Clang, including
unchecked lseek()s, unbound strcpy()s, branching based on an
uninitialised variable, potential NULL pointer derefs, some dead
assignments and a dangling reference to a local variable.
Signed-off-by: Andrew Price <anprice@redhat.com>
---
gfs2/edit/extended.c | 5 +----
gfs2/edit/gfs2hex.c | 7 ++++---
gfs2/edit/hexedit.c | 13 +++++++------
gfs2/edit/journal.c | 36 +++++++++++++++---------------------
gfs2/edit/savemeta.c | 18 ++++++------------
5 files changed, 33 insertions(+), 46 deletions(-)
diff --git a/gfs2/edit/extended.c b/gfs2/edit/extended.c
index 793ef6b..e5cb12c 100644
--- a/gfs2/edit/extended.c
+++ b/gfs2/edit/extended.c
@@ -391,9 +391,8 @@ static void print_block_details(struct iinfo *ind, int level, int cur_height,
return;
}
while (thisblk) {
- lseek(sbd.device_fd, thisblk * sbd.bsize, SEEK_SET);
/* read in the desired block */
- if (read(sbd.device_fd, tmpbuf, sbd.bsize) != sbd.bsize) {
+ if (pread(sbd.device_fd, tmpbuf, sbd.bsize, thisblk * sbd.bsize) != sbd.bsize) {
fprintf(stderr, "bad read: %s from %s:%d: block %lld "
"(0x%llx)\n", strerror(errno), __FUNCTION__,
__LINE__,
@@ -446,7 +445,6 @@ static int print_gfs_jindex(struct gfs2_inode *dij)
char jbuf[sizeof(struct gfs_jindex)];
start_line = line;
- error = 0;
print_gfs2("Journal index entries found: %d.",
dij->i_di.di_size / sizeof(struct gfs_jindex));
eol(0);
@@ -516,7 +514,6 @@ static int parse_rindex(struct gfs2_inode *dip, int print_rindex)
char highlighted_addr[32];
start_line = line;
- error = 0;
print_gfs2("RG index entries found: %d.", dip->i_di.di_size /
sizeof(struct gfs2_rindex));
eol(0);
diff --git a/gfs2/edit/gfs2hex.c b/gfs2/edit/gfs2hex.c
index 979aee0..b6075f4 100644
--- a/gfs2/edit/gfs2hex.c
+++ b/gfs2/edit/gfs2hex.c
@@ -38,7 +38,6 @@ char efield[64];
int edit_mode = 0;
int edit_row[DMODES], edit_col[DMODES];
int edit_size[DMODES], last_entry_onscreen[DMODES];
-char edit_fmt[80];
enum dsp_mode dmode = HEX_MODE; /* display mode */
uint64_t block = 0;
int blockhist = 0;
@@ -201,9 +200,11 @@ void print_it(const char *label, const char *fmt, const char *fmt2, ...)
if (termlines) {
refresh();
if (line == (edit_row[dmode] * lines_per_row[dmode]) + 4) {
- strcpy(efield, label + 2); /* it's indented */
+ strncpy(efield, label + 2, 63); /* it's indented */
+ efield[63] = '\0';
strcpy(estring, tmp_string);
- strcpy(edit_fmt, fmt);
+ strncpy(edit_fmt, fmt, 79);
+ edit_fmt[79] = '\0';
edit_size[dmode] = strlen(estring);
COLORS_NORMAL;
}
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
index 5c5ac89..bc3ca35 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -1583,7 +1583,7 @@ static uint64_t find_metablockoftype_rg(uint64_t startblk, int metatype, int pri
struct osi_node *next = NULL;
uint64_t blk, errblk;
int first = 1, found = 0;
- struct rgrp_tree *rgd;
+ struct rgrp_tree *rgd = NULL;
struct gfs2_rindex *ri;
blk = 0;
@@ -1726,7 +1726,7 @@ uint64_t check_keywords(const char *kword)
blk = get_rg_addr(rgnum);
} else if (!strncmp(kword, "journals", 8)) {
blk = JOURNALS_DUMMY_BLOCK;
- } else if (!strncmp(kword, "journal", 7) && isdigit(kword[7])) {
+ } else if (strlen(kword) > 7 && !strncmp(kword, "journal", 7) && isdigit(kword[7])) {
uint64_t j_size;
blk = find_journal_block(kword, &j_size);
@@ -1837,8 +1837,7 @@ static void hex_edit(int *exitch)
ch += (estring[i+1] - 'A' + 0x0a);
bh->b_data[offset + hexoffset] = ch;
}
- lseek(sbd.device_fd, dev_offset, SEEK_SET);
- if (write(sbd.device_fd, bh->b_data, sbd.bsize) !=
+ if (pwrite(sbd.device_fd, bh->b_data, sbd.bsize, dev_offset) !=
sbd.bsize) {
fprintf(stderr, "write error: %s from %s:%d: "
"offset %lld (0x%llx)\n",
@@ -2676,8 +2675,10 @@ static void parameterpass1(int argc, char *argv[], int i)
termlines = 0;
else if (!strcasecmp(argv[i], "-x"))
dmode = HEX_MODE;
- else if (!device[0] && strchr(argv[i],'/'))
- strcpy(device, argv[i]);
+ else if (!device[0] && strchr(argv[i],'/')) {
+ strncpy(device, argv[i], NAME_MAX-1);
+ device[NAME_MAX-1] = '\0';
+ }
}
/* ------------------------------------------------------------------------ */
diff --git a/gfs2/edit/journal.c b/gfs2/edit/journal.c
index 3c2f5c7..5000c2e 100644
--- a/gfs2/edit/journal.c
+++ b/gfs2/edit/journal.c
@@ -98,16 +98,6 @@ static void check_journal_wrap(uint64_t seq, uint64_t *highest_seq)
*highest_seq = seq;
}
-static int is_meta(struct gfs2_buffer_head *lbh)
-{
- uint32_t check_magic = ((struct gfs2_meta_header *)(lbh->b_data))->mh_magic;
-
- check_magic = be32_to_cpu(check_magic);
- if (check_magic == GFS2_MAGIC)
- return 1;
- return 0;
-}
-
/**
* fsck_readi - same as libgfs2's gfs2_readi, but sets absolute block #
* of the first bit of data read.
@@ -115,16 +105,20 @@ static int is_meta(struct gfs2_buffer_head *lbh)
static int fsck_readi(struct gfs2_inode *ip, void *rbuf, uint64_t roffset,
unsigned int size, uint64_t *abs_block)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp;
struct gfs2_buffer_head *lbh;
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 isdir;
int copied = 0;
+ if (ip == NULL)
+ return 0;
+ sdp = ip->i_sbd;
+ isdir = !!(S_ISDIR(ip->i_di.di_mode));
*abs_block = 0;
if (roffset >= ip->i_di.di_size)
return 0;
@@ -287,9 +281,9 @@ static int print_ld_blks(const uint64_t *b, const char *end, int start_line,
}
if (prnt)
eol(0);
- if (!found_tblk || !is_meta_ld)
+ if (tblk_off && (!found_tblk || !is_meta_ld))
*tblk_off = 0;
- if (!found_bblk || !is_meta_ld)
+ if (bblk_off && (!found_bblk || !is_meta_ld))
*bblk_off = 0;
return bcount;
}
@@ -443,7 +437,7 @@ void dump_journal(const char *journal, int tblk)
{
struct gfs2_buffer_head *j_bh = NULL, dummy_bh;
uint64_t jblock, j_size, jb, abs_block, saveblk, wrappt = 0;
- int error, start_line, journal_num;
+ int start_line, journal_num;
struct gfs2_inode *j_inode = NULL;
int ld_blocks = 0, offset_from_ld = 0;
uint64_t tblk_off = 0, bblk_off = 0, bitblk = 0;
@@ -454,7 +448,6 @@ void dump_journal(const char *journal, int tblk)
start_line = line;
lines_per_row[dmode] = 1;
- error = 0;
journal_num = atoi(journal + 7);
print_gfs2("Dumping journal #%d.", journal_num);
if (tblk) {
@@ -518,6 +511,7 @@ void dump_journal(const char *journal, int tblk)
for (jb = 0; jb < j_size; jb += (sbd.gfs1 ? 1 : sbd.bsize)) {
int is_pertinent = 1;
+ uint32_t block_type = 0;
if (sbd.gfs1) {
if (j_bh)
@@ -526,7 +520,7 @@ void dump_journal(const char *journal, int tblk)
j_bh = bread(&sbd, abs_block);
dummy_bh.b_data = j_bh->b_data;
} else {
- error = fsck_readi(j_inode, (void *)jbuf,
+ int error = fsck_readi(j_inode, (void *)jbuf,
((jb + wrappt) % j_size),
sbd.bsize, &abs_block);
if (!error) /* end of file */
@@ -534,14 +528,14 @@ void dump_journal(const char *journal, int tblk)
dummy_bh.b_data = jbuf;
}
offset_from_ld++;
- if (get_block_type(&dummy_bh, NULL) == GFS2_METATYPE_LD) {
+ block_type = get_block_type(&dummy_bh, NULL);
+ if (block_type == GFS2_METATYPE_LD) {
ld_blocks = process_ld(abs_block, wrappt, j_size, jb,
&dummy_bh, tblk, &tblk_off,
bitblk, rgd, &is_pertinent,
&bblk_off, ld_blk_refs);
offset_from_ld = 0;
- } else if (!tblk &&
- get_block_type(&dummy_bh, NULL) == GFS2_METATYPE_LH) {
+ } else if (!tblk && block_type == GFS2_METATYPE_LH) {
struct gfs2_log_header lh;
struct gfs_log_header lh1;
@@ -577,7 +571,7 @@ void dump_journal(const char *journal, int tblk)
sbd.bsize), start_line,
tblk, &tblk_off, 0, rgd,
0, 1, NULL, 1, NULL);
- } else if (!is_meta(&dummy_bh)) {
+ } else if (block_type == 0) {
continue;
}
/* Check if this metadata block references the block we're
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
index 5bf7963..c9f2d0a 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -662,7 +662,7 @@ static void save_allocated(struct rgrp_tree *rgd, struct metafd *mfd)
* If we don't, we may run into metadata allocation issues. */
m = lgfs2_bm_scan(rgd, i, ibuf, GFS2_BLKST_UNLINKED);
for (j = 0; j < m; j++) {
- blktype = save_block(sbd.device_fd, mfd, block);
+ save_block(sbd.device_fd, mfd, block);
}
}
free(ibuf);
@@ -933,6 +933,7 @@ static int restore_data(int fd, gzFile gzin_fd, int printblocksonly,
if (printblocksonly > 1 && printblocksonly == block) {
block_in_mem = block;
display(0, 0, 0, 0);
+ bh = NULL;
return 0;
} else if (printblocksonly == 1) {
print_gfs2("%d (l=0x%x): ", blks_saved,
@@ -944,19 +945,10 @@ static int restore_data(int fd, gzFile gzin_fd, int printblocksonly,
if (savedata->blk >= sbd.fssize) {
printf("\nOut of space on the destination "
"device; quitting.\n");
+ bh = NULL;
break;
}
- if (lseek(fd, savedata->blk * sbd.bsize, SEEK_SET) !=
- savedata->blk * sbd.bsize) {
- fprintf(stderr, "bad seek: %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 (write(fd, savedata->buf, sbd.bsize) != sbd.bsize) {
+ if (pwrite(fd, savedata->buf, sbd.bsize, savedata->blk * sbd.bsize) != sbd.bsize) {
fprintf(stderr, "write error: %s from "
"%s:%d: block %lld (0x%llx)\n",
strerror(errno), __FUNCTION__,
@@ -970,6 +962,8 @@ static int restore_data(int fd, gzFile gzin_fd, int printblocksonly,
fsync(fd);
}
blks_saved++;
+ /* Don't leave a dangling reference to our local dummy_bh */
+ bh = NULL;
}
if (!printblocksonly && !find_highblk)
warm_fuzzy_stuff(sbd.fssize, TRUE);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 10+ messages in thread* [Cluster-devel] [PATCH] gfs2_edit: Corrections to log descriptor reference parsing
2014-02-28 9:35 [Cluster-devel] [PATCH 0/7] gfs2_edit journalX block reference feature and fixes Andrew Price
` (6 preceding siblings ...)
2014-02-28 9:35 ` [Cluster-devel] [PATCH 7/7] gfs2_edit: More static analysis fixes Andrew Price
@ 2014-03-03 16:57 ` Bob Peterson
2014-03-03 18:56 ` Andrew Price
7 siblings, 1 reply; 10+ messages in thread
From: Bob Peterson @ 2014-03-03 16:57 UTC (permalink / raw)
To: cluster-devel.redhat.com
----- Original Message -----
| This patch set mainly adds a feature to gfs2_edit which allows us to
| highlight
| the entries in a journal dump which refer to a particular block address. The
| patches for this were written by Bob and I've rebased them on top of the the
| current master branch with some added tweaks and cleanups. (Patches 3 to 6)
|
| I've also included some patches which address a number of minor/potential
| issues discovered by static analysis and remove another exit() call from
| libgfs2. (Patches 1, 2 and 7)
|
| Andrew Price (4):
| libgfs2: Remove another exit() call
| gfs2-utils: Fix up some errors reported by clang
| gfs2_edit: Use the metadata description in get_block_type
| gfs2_edit: More static analysis fixes
|
| Bob Peterson (3):
| gfs2_edit: Separate out the journal-related functions to journal.c
| gfs2_edit: Add more intelligence to journal dumps
| gfs2_edit: Report referencing block address in the new journal code
Hi Andy,
The patches look good, but I've got another one, #8, which also
makes a correction.
Regards,
Bob Peterson
---
The previous code in the journal dumping code to determine log descriptor
references was convoluted and didn't work properly in all cases. This
version is better and simpler.
diff --git a/gfs2/edit/journal.c b/gfs2/edit/journal.c
index 5000c2e..118d068 100644
--- a/gfs2/edit/journal.c
+++ b/gfs2/edit/journal.c
@@ -198,8 +198,7 @@ static int ld_is_pertinent(const uint64_t *b, const char *end, uint64_t tblk,
static int print_ld_blks(const uint64_t *b, const char *end, int start_line,
uint64_t tblk, uint64_t *tblk_off, uint64_t bitblk,
struct rgrp_tree *rgd, uint64_t abs_block, int prnt,
- uint64_t *bblk_off, int is_meta_ld,
- uint64_t ld_blk_refs[])
+ uint64_t *bblk_off, int is_meta_ld)
{
int bcount = 0, found_tblk = 0, found_bblk = 0;
static char str[256];
@@ -217,8 +216,6 @@ static int print_ld_blks(const uint64_t *b, const char *end, int start_line,
eol(0);
print_gfs2(" ");
}
- if (ld_blk_refs)
- ld_blk_refs[bcount] = be64_to_cpu(*b);
bcount++;
if (prnt) {
sprintf(str, "0x%llx",
@@ -342,8 +339,7 @@ static uint64_t find_wrap_pt(struct gfs2_inode *j_inode, char *jbuf,
static int process_ld(uint64_t abs_block, uint64_t wrappt, uint64_t j_size,
uint64_t jb, struct gfs2_buffer_head *dummy_bh, int tblk,
uint64_t *tblk_off, uint64_t bitblk,
- struct rgrp_tree *rgd, int *prnt, uint64_t *bblk_off,
- uint64_t ld_blk_refs[])
+ struct rgrp_tree *rgd, int *prnt, uint64_t *bblk_off)
{
uint64_t *b;
struct gfs2_log_descriptor ld;
@@ -391,7 +387,7 @@ static int process_ld(uint64_t abs_block, uint64_t wrappt, uint64_t j_size,
is_meta_ld = 1;
ld_blocks -= print_ld_blks(b, (dummy_bh->b_data + sbd.bsize), line,
tblk, tblk_off, bitblk, rgd, abs_block,
- *prnt, bblk_off, is_meta_ld, ld_blk_refs);
+ *prnt, bblk_off, is_meta_ld);
return ld_blocks;
}
@@ -423,6 +419,27 @@ static int meta_has_ref(uint64_t abs_block, int tblk)
return has_ref;
}
+
+/**
+ * get_ldref - get a log descriptor reference block, given a block number
+ *
+ * Note that we can't pass in abs_block here, because journal wrap may
+ * mean that the block we're intered in, in the journal, is before the
+ * log descriptor that holds the reference we need.
+ */
+static uint64_t get_ldref(uint64_t abs_ld, int offset_from_ld)
+{
+ struct gfs2_buffer_head *jbh;
+ uint64_t *b, refblk;
+
+ jbh = bread(&sbd, abs_ld);
+ b = (uint64_t *)(jbh->b_data + sizeof(struct gfs2_log_descriptor));
+ b += offset_from_ld - 1;
+ refblk = be64_to_cpu(*b);
+ brelse(jbh);
+ return refblk;
+}
+
/**
* dump_journal - dump a journal file's contents.
* @journal: name of the journal to dump
@@ -444,7 +461,7 @@ void dump_journal(const char *journal, int tblk)
uint64_t highest_seq = 0;
char *jbuf = NULL;
struct rgrp_tree *rgd = NULL;
- uint64_t ld_blk_refs[503]; /* The most blks a LD can have */
+ uint64_t abs_ld = 0;
start_line = line;
lines_per_row[dmode] = 1;
@@ -533,8 +550,9 @@ void dump_journal(const char *journal, int tblk)
ld_blocks = process_ld(abs_block, wrappt, j_size, jb,
&dummy_bh, tblk, &tblk_off,
bitblk, rgd, &is_pertinent,
- &bblk_off, ld_blk_refs);
+ &bblk_off);
offset_from_ld = 0;
+ abs_ld = abs_block;
} else if (!tblk && block_type == GFS2_METATYPE_LH) {
struct gfs2_log_header lh;
struct gfs_log_header lh1;
@@ -570,22 +588,28 @@ void dump_journal(const char *journal, int tblk)
(dummy_bh.b_data +
sbd.bsize), start_line,
tblk, &tblk_off, 0, rgd,
- 0, 1, NULL, 1, NULL);
+ 0, 1, NULL, 1);
} else if (block_type == 0) {
continue;
}
/* Check if this metadata block references the block we're
trying to trace. */
- if (details || (tblk && ((is_pertinent &&
- ((tblk_off && offset_from_ld == tblk_off) ||
+ if (details ||
+ ((tblk) &&
+ ((is_pertinent &&
+ ((tblk_off && offset_from_ld == tblk_off) ||
(bblk_off && offset_from_ld == bblk_off))) ||
- meta_has_ref(abs_block, tblk)))) {
+ meta_has_ref(abs_block, tblk)))) {
+ uint64_t ref_blk = 0;
+
saveblk = block;
block = abs_block;
- if (tblk)
- display(0, 1, tblk, ld_blk_refs[offset_from_ld]);
- else
+ if (tblk && !details) {
+ ref_blk = get_ldref(abs_ld, offset_from_ld);
+ display(0, 1, tblk, ref_blk);
+ } else {
display(0, 0, 0, 0);
+ }
block = saveblk;
}
}
^ permalink raw reply related [flat|nested] 10+ messages in thread* [Cluster-devel] [PATCH] gfs2_edit: Corrections to log descriptor reference parsing
2014-03-03 16:57 ` [Cluster-devel] [PATCH] gfs2_edit: Corrections to log descriptor reference parsing Bob Peterson
@ 2014-03-03 18:56 ` Andrew Price
0 siblings, 0 replies; 10+ messages in thread
From: Andrew Price @ 2014-03-03 18:56 UTC (permalink / raw)
To: cluster-devel.redhat.com
Hi Bob,
On 03/03/14 16:57, Bob Peterson wrote:
> ----- Original Message -----
> | This patch set mainly adds a feature to gfs2_edit which allows us to
> | highlight
> | the entries in a journal dump which refer to a particular block address. The
> | patches for this were written by Bob and I've rebased them on top of the the
> | current master branch with some added tweaks and cleanups. (Patches 3 to 6)
> |
> | I've also included some patches which address a number of minor/potential
> | issues discovered by static analysis and remove another exit() call from
> | libgfs2. (Patches 1, 2 and 7)
> |
> | Andrew Price (4):
> | libgfs2: Remove another exit() call
> | gfs2-utils: Fix up some errors reported by clang
> | gfs2_edit: Use the metadata description in get_block_type
> | gfs2_edit: More static analysis fixes
> |
> | Bob Peterson (3):
> | gfs2_edit: Separate out the journal-related functions to journal.c
> | gfs2_edit: Add more intelligence to journal dumps
> | gfs2_edit: Report referencing block address in the new journal code
>
> Hi Andy,
>
> The patches look good, but I've got another one, #8, which also
> makes a correction.
Thanks, it looks good. I've pushed this to gfs2-utils.git (with a tiny
typo fix in a comment) along with the other patches.
Cheers,
Andy
> Regards,
>
> Bob Peterson
> ---
> The previous code in the journal dumping code to determine log descriptor
> references was convoluted and didn't work properly in all cases. This
> version is better and simpler.
>
> diff --git a/gfs2/edit/journal.c b/gfs2/edit/journal.c
> index 5000c2e..118d068 100644
> --- a/gfs2/edit/journal.c
> +++ b/gfs2/edit/journal.c
> @@ -198,8 +198,7 @@ static int ld_is_pertinent(const uint64_t *b, const char *end, uint64_t tblk,
> static int print_ld_blks(const uint64_t *b, const char *end, int start_line,
> uint64_t tblk, uint64_t *tblk_off, uint64_t bitblk,
> struct rgrp_tree *rgd, uint64_t abs_block, int prnt,
> - uint64_t *bblk_off, int is_meta_ld,
> - uint64_t ld_blk_refs[])
> + uint64_t *bblk_off, int is_meta_ld)
> {
> int bcount = 0, found_tblk = 0, found_bblk = 0;
> static char str[256];
> @@ -217,8 +216,6 @@ static int print_ld_blks(const uint64_t *b, const char *end, int start_line,
> eol(0);
> print_gfs2(" ");
> }
> - if (ld_blk_refs)
> - ld_blk_refs[bcount] = be64_to_cpu(*b);
> bcount++;
> if (prnt) {
> sprintf(str, "0x%llx",
> @@ -342,8 +339,7 @@ static uint64_t find_wrap_pt(struct gfs2_inode *j_inode, char *jbuf,
> static int process_ld(uint64_t abs_block, uint64_t wrappt, uint64_t j_size,
> uint64_t jb, struct gfs2_buffer_head *dummy_bh, int tblk,
> uint64_t *tblk_off, uint64_t bitblk,
> - struct rgrp_tree *rgd, int *prnt, uint64_t *bblk_off,
> - uint64_t ld_blk_refs[])
> + struct rgrp_tree *rgd, int *prnt, uint64_t *bblk_off)
> {
> uint64_t *b;
> struct gfs2_log_descriptor ld;
> @@ -391,7 +387,7 @@ static int process_ld(uint64_t abs_block, uint64_t wrappt, uint64_t j_size,
> is_meta_ld = 1;
> ld_blocks -= print_ld_blks(b, (dummy_bh->b_data + sbd.bsize), line,
> tblk, tblk_off, bitblk, rgd, abs_block,
> - *prnt, bblk_off, is_meta_ld, ld_blk_refs);
> + *prnt, bblk_off, is_meta_ld);
>
> return ld_blocks;
> }
> @@ -423,6 +419,27 @@ static int meta_has_ref(uint64_t abs_block, int tblk)
> return has_ref;
> }
>
> +
> +/**
> + * get_ldref - get a log descriptor reference block, given a block number
> + *
> + * Note that we can't pass in abs_block here, because journal wrap may
> + * mean that the block we're intered in, in the journal, is before the
> + * log descriptor that holds the reference we need.
> + */
> +static uint64_t get_ldref(uint64_t abs_ld, int offset_from_ld)
> +{
> + struct gfs2_buffer_head *jbh;
> + uint64_t *b, refblk;
> +
> + jbh = bread(&sbd, abs_ld);
> + b = (uint64_t *)(jbh->b_data + sizeof(struct gfs2_log_descriptor));
> + b += offset_from_ld - 1;
> + refblk = be64_to_cpu(*b);
> + brelse(jbh);
> + return refblk;
> +}
> +
> /**
> * dump_journal - dump a journal file's contents.
> * @journal: name of the journal to dump
> @@ -444,7 +461,7 @@ void dump_journal(const char *journal, int tblk)
> uint64_t highest_seq = 0;
> char *jbuf = NULL;
> struct rgrp_tree *rgd = NULL;
> - uint64_t ld_blk_refs[503]; /* The most blks a LD can have */
> + uint64_t abs_ld = 0;
>
> start_line = line;
> lines_per_row[dmode] = 1;
> @@ -533,8 +550,9 @@ void dump_journal(const char *journal, int tblk)
> ld_blocks = process_ld(abs_block, wrappt, j_size, jb,
> &dummy_bh, tblk, &tblk_off,
> bitblk, rgd, &is_pertinent,
> - &bblk_off, ld_blk_refs);
> + &bblk_off);
> offset_from_ld = 0;
> + abs_ld = abs_block;
> } else if (!tblk && block_type == GFS2_METATYPE_LH) {
> struct gfs2_log_header lh;
> struct gfs_log_header lh1;
> @@ -570,22 +588,28 @@ void dump_journal(const char *journal, int tblk)
> (dummy_bh.b_data +
> sbd.bsize), start_line,
> tblk, &tblk_off, 0, rgd,
> - 0, 1, NULL, 1, NULL);
> + 0, 1, NULL, 1);
> } else if (block_type == 0) {
> continue;
> }
> /* Check if this metadata block references the block we're
> trying to trace. */
> - if (details || (tblk && ((is_pertinent &&
> - ((tblk_off && offset_from_ld == tblk_off) ||
> + if (details ||
> + ((tblk) &&
> + ((is_pertinent &&
> + ((tblk_off && offset_from_ld == tblk_off) ||
> (bblk_off && offset_from_ld == bblk_off))) ||
> - meta_has_ref(abs_block, tblk)))) {
> + meta_has_ref(abs_block, tblk)))) {
> + uint64_t ref_blk = 0;
> +
> saveblk = block;
> block = abs_block;
> - if (tblk)
> - display(0, 1, tblk, ld_blk_refs[offset_from_ld]);
> - else
> + if (tblk && !details) {
> + ref_blk = get_ldref(abs_ld, offset_from_ld);
> + display(0, 1, tblk, ref_blk);
> + } else {
> display(0, 0, 0, 0);
> + }
> block = saveblk;
> }
> }
>
^ permalink raw reply [flat|nested] 10+ messages in thread