Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=e6bb3d27cd0... Commit: e6bb3d27cd08c50f04825f5873023d19534c5fe6 Parent: 803f914e2d9a6397bf09dabede18590b0a0fb29a Author: Andrew Price anprice@redhat.com AuthorDate: Wed Jan 18 15:14:57 2017 +0000 Committer: Andrew Price anprice@redhat.com CommitterDate: Wed Jan 18 16:21:54 2017 +0000
gfs2_edit savemeta: Save corrupt rgrp headers
Previously, savemeta used gfs2_rgrp_read() to read resource groups. This includes a metadata check which fails the read if the resource groups are corrupt. Since we want to save corruption in order to analyze it, we need to read the rgrp headers without checking them. Use a new, simplified rgrp_read() function for that.
Also avoid the effect of a similar metadata check in get_gfs_struct_info() when saving rgrps.
Signed-off-by: Andrew Price anprice@redhat.com --- gfs2/edit/savemeta.c | 34 ++++++++++++++++++++++++++++++++-- 1 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c index da24645..dee405b 100644 --- a/gfs2/edit/savemeta.c +++ b/gfs2/edit/savemeta.c @@ -417,7 +417,8 @@ static int save_bh(struct metafd *mfd, struct gfs2_buffer_head *savebh, uint64_t because we want to know if the source inode is a system inode not the block within the inode "blk". They may or may not be the same thing. */ - if (get_gfs_struct_info(savebh, owner, blktype, &blklen) && !block_is_systemfile(owner)) + if (get_gfs_struct_info(savebh, owner, blktype, &blklen) && + !block_is_systemfile(owner) && owner != 0) return 0; /* Not metadata, and not system file, so skip it */
/* No need to save trailing zeroes */ @@ -770,12 +771,41 @@ static void save_allocated(struct rgrp_tree *rgd, struct metafd *mfd) free(ibuf); }
+/* We don't use gfs2_rgrp_read() here as it checks for metadata sanity and we + want to save rgrp headers even if they're corrupt. */ +static int rgrp_read(struct gfs2_sbd *sdp, struct rgrp_tree *rgd) +{ + unsigned x, length = rgd->ri.ri_length; + struct gfs2_buffer_head **bhs; + + if (length == 0 || gfs2_check_range(sdp, rgd->ri.ri_addr)) + return -1; + + bhs = calloc(length, sizeof(struct gfs2_buffer_head *)); + if (bhs == NULL) + return -1; + + if (breadm(sdp, bhs, length, rgd->ri.ri_addr)) { + free(bhs); + return -1; + } + for (x = 0; x < length; x++) + rgd->bits[x].bi_bh = bhs[x]; + + if (sdp->gfs1) + gfs_rgrp_in((struct gfs_rgrp *)&rgd->rg, rgd->bits[0].bi_bh); + else + gfs2_rgrp_in(&rgd->rg, rgd->bits[0].bi_bh); + free(bhs); + return 0; +} + static void save_rgrp(struct metafd *mfd, struct rgrp_tree *rgd, int withcontents) { uint64_t addr = rgd->ri.ri_addr; uint32_t i;
- if (gfs2_rgrp_read(&sbd, rgd)) + if (rgrp_read(&sbd, rgd)) return; log_debug("RG at %"PRIu64" (0x%"PRIx64") is %u long\n", addr, addr, rgd->ri.ri_length);
cluster-commits@lists.fedorahosted.org