From: Dave Chinner <david@fromorbit.com>
To: xfs@oss.sgi.com
Subject: [PATCH 3/5] repair: handle memory allocation failure from blkmap_grow
Date: Mon, 10 Oct 2011 12:08:33 +1100 [thread overview]
Message-ID: <1318208915-14975-4-git-send-email-david@fromorbit.com> (raw)
In-Reply-To: <1318208915-14975-1-git-send-email-david@fromorbit.com>
From: Dave Chinner <dchinner@redhat.com>
If blkmap_grow fails to allocate a new chunk of memory, it returns
with a null blkmap. The sole caller of blkmap_grow does not check
for this failure, and so will segfault if this error ever occurs.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
repair/bmap.c | 33 ++++++++++++++++++++++-----------
repair/bmap.h | 2 +-
repair/dinode.c | 22 ++++++++++++++++++++--
3 files changed, 43 insertions(+), 14 deletions(-)
diff --git a/repair/bmap.c b/repair/bmap.c
index 0ff9315..e290515 100644
--- a/repair/bmap.c
+++ b/repair/bmap.c
@@ -207,29 +207,34 @@ blkmap_next_off(
*/
static blkmap_t *
blkmap_grow(
- blkmap_t **blkmapp)
+ blkmap_t *blkmap)
{
pthread_key_t key = dblkmap_key;
- blkmap_t *blkmap = *blkmapp;
+ blkmap_t *new_blkmap;
+ int new_naexts = blkmap->naexts + 4;
if (pthread_getspecific(key) != blkmap) {
key = ablkmap_key;
ASSERT(pthread_getspecific(key) == blkmap);
}
- blkmap->naexts += 4;
- blkmap = realloc(blkmap, BLKMAP_SIZE(blkmap->naexts));
- if (blkmap == NULL)
+ new_blkmap = realloc(blkmap, BLKMAP_SIZE(new_naexts));
+ if (!new_blkmap) {
do_error(_("realloc failed in blkmap_grow\n"));
- *blkmapp = blkmap;
- pthread_setspecific(key, blkmap);
- return blkmap;
+ return NULL;
+ }
+ new_blkmap->naexts = new_naexts;
+ pthread_setspecific(key, new_blkmap);
+ return new_blkmap;
}
/*
* Set an extent into a block map.
+ *
+ * If this function fails, it leaves the blkmapp untouched so the caller can
+ * handle the error and free the blkmap appropriately.
*/
-void
+int
blkmap_set_ext(
blkmap_t **blkmapp,
xfs_dfiloff_t o,
@@ -239,9 +244,14 @@ blkmap_set_ext(
blkmap_t *blkmap = *blkmapp;
xfs_extnum_t i;
- if (blkmap->nexts == blkmap->naexts)
- blkmap = blkmap_grow(blkmapp);
+ if (blkmap->nexts == blkmap->naexts) {
+ blkmap = blkmap_grow(blkmap);
+ if (!blkmap)
+ return ENOMEM;
+ *blkmapp = blkmap;
+ }
+ ASSERT(blkmap->nexts < blkmap->naexts);
for (i = 0; i < blkmap->nexts; i++) {
if (blkmap->exts[i].startoff > o) {
memmove(blkmap->exts + i + 1,
@@ -255,4 +265,5 @@ blkmap_set_ext(
blkmap->exts[i].startblock = b;
blkmap->exts[i].blockcount = c;
blkmap->nexts++;
+ return 0;
}
diff --git a/repair/bmap.h b/repair/bmap.h
index 58abf95..118ae1e 100644
--- a/repair/bmap.h
+++ b/repair/bmap.h
@@ -43,7 +43,7 @@ typedef struct blkmap {
blkmap_t *blkmap_alloc(xfs_extnum_t nex, int whichfork);
void blkmap_free(blkmap_t *blkmap);
-void blkmap_set_ext(blkmap_t **blkmapp, xfs_dfiloff_t o,
+int blkmap_set_ext(blkmap_t **blkmapp, xfs_dfiloff_t o,
xfs_dfsbno_t b, xfs_dfilblks_t c);
xfs_dfsbno_t blkmap_get(blkmap_t *blkmap, xfs_dfiloff_t o);
diff --git a/repair/dinode.c b/repair/dinode.c
index 5a74538..39a0cb1 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -730,9 +730,27 @@ _("inode %" PRIu64 " - extent offset too large - start %" PRIu64 ", "
goto done;
}
- if (blkmapp && *blkmapp)
- blkmap_set_ext(blkmapp, irec.br_startoff,
+ if (blkmapp && *blkmapp) {
+ error = blkmap_set_ext(blkmapp, irec.br_startoff,
irec.br_startblock, irec.br_blockcount);
+ if (error) {
+ /*
+ * we don't want to clear the inode due to an
+ * internal bmap tracking error, but if we've
+ * run out of memory then we simply can't
+ * validate that the filesystem is consistent.
+ * Hence just abort at this point with an ENOMEM
+ * error.
+ */
+ do_abort(
+_("Fatal error: inode %" PRIu64 " - blkmap_set_ext(): %s\n"
+ "\t%s fork, off - %" PRIu64 ", start - %" PRIu64 ", cnt %" PRIu64 "\n"),
+ ino, strerror(error), forkname,
+ irec.br_startoff, irec.br_startblock,
+ irec.br_blockcount);
+ }
+ }
+
/*
* Profiling shows that the following loop takes the
* most time in all of xfs_repair.
--
1.7.5.4
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next prev parent reply other threads:[~2011-10-10 1:08 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-10-10 1:08 [PATCH 0/5, v3] repair: sector size and blkmap fixes Dave Chinner
2011-10-10 1:08 ` [PATCH 1/5] repair: handle repair of image files on large sector size filesystems Dave Chinner
2011-10-10 14:06 ` Christoph Hellwig
2011-10-13 9:57 ` Alex Elder
2011-10-10 1:08 ` [PATCH 2/5] repair: fix a valgrind reported error on i686 Dave Chinner
2011-10-10 14:07 ` Christoph Hellwig
2011-10-13 9:57 ` Alex Elder
2011-10-10 1:08 ` Dave Chinner [this message]
2011-10-10 14:14 ` [PATCH 3/5] repair: handle memory allocation failure from blkmap_grow Christoph Hellwig
2011-10-13 9:57 ` Alex Elder
2011-10-10 1:08 ` [PATCH 4/5] repair: don't cache large blkmap allocations Dave Chinner
2011-10-10 14:15 ` Christoph Hellwig
2011-10-13 9:57 ` Alex Elder
2011-10-10 1:08 ` [PATCH 5/5] repair: prevent blkmap extent count overflows Dave Chinner
2011-10-10 14:17 ` Christoph Hellwig
2011-10-13 9:58 ` Alex Elder
2011-10-10 14:18 ` [PATCH 0/5, v3] repair: sector size and blkmap fixes Christoph Hellwig
2011-10-10 23:12 ` Dave Chinner
-- strict thread matches above, loose matches on Subject: below --
2011-10-09 23:11 [PATCH 0/5, v2] " Dave Chinner
2011-10-09 23:11 ` [PATCH 3/5] repair: handle memory allocation failure from blkmap_grow Dave Chinner
2011-10-09 23:51 ` Christoph Hellwig
2011-10-10 0:10 ` Dave Chinner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1318208915-14975-4-git-send-email-david@fromorbit.com \
--to=david@fromorbit.com \
--cc=xfs@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox