[PATCH 09/14] repair: track logical to physical block mapping moreeffeciently

Christoph Hellwig hch at infradead.org
Thu Nov 12 04:18:21 CST 2009


On Wed, Oct 21, 2009 at 02:06:19PM -0500, Alex Elder wrote:
> Christoph Hellwig wrote:
> > Currently we track the logical to physical block mapping by a structure which
> > contains an array of physicial blocks.  This is extremly efficient and is
> 
> Should this be "extremely inefficient?"
> 
> > replaced with the normal starblock storage we use in the kernel and on disk
> > in this patch.
> 
> While you're at fixing the above comment, maybe just re-word this
> sentence because I don't really grok it very well...

Thanks, updated in the version below.

> > +	ASSERT(whichfork == XFS_DATA_FORK || whichfork == XFS_ATTR_FORK);
> > +
> >  	if (nex < 1)
> >  		nex = 1;
> > -	if ((blkmap = malloc(BLKMAP_SIZE(nex))) == NULL) {
> > -		do_warn(_("malloc failed in blkmap_alloc (%u bytes)\n"),
> > -			BLKMAP_SIZE(nex));
> > -		return blkmap;
> > +
> > +	key = whichfork ? ablkmap_key : dblkmap_key;
> > +	blkmap = pthread_getspecific(key);
> > +	if (!blkmap || blkmap->naexts < nex) {
> > +		blkmap = realloc(blkmap, BLKMAP_SIZE(nex));
> 
> Does the above really have to be a realloc() call, or can
> it simply be a free()/malloc() instead?  Also, could the
> existing ts_alloc() function be adjusted to accomodate the
> usage here?

It has to be a realloc, we need to keep the existing content.  We really
need to do the growing based on the existing size, so ts_alloc doesn't
fit.  We could try to introduce a ts_realloc, but I'm not sure it's
worth it.

> >  {
> > -	blkent_t	**entp;
> > -	xfs_extnum_t	i;
> > -
> > -	if (blkmap == NULL)
> > -		return;
> > -	for (i = 0, entp = blkmap->ents; i < blkmap->nents; i++, entp++)
> > -		free(*entp);
> > -	free(blkmap);
> > +	/* nothing to do! - keep the memory around for the next inode */
> 
> Nobody ever frees it though, either.  I guess it gets done at
> exit but I like things tidy (could arrange for a destructor
> function to be called, at pthread_key_create() time).

This would complicate things quite a bit, and it would actually cause a
lot more malloc/free cycles that potentially slow repair down.  Right
now we only have to allocate the map if the next inode has a larger
extent map than the previously processed one, which means we can safe
a lot of malloc/free cycles.  Which still can be quite slow in
multi-threaded programs.

-- 

Subject: repair: track logical to physical block mapping more effeciently
From: Barry Naujok <bnaujok at sgi.com>

Currently we track the logical to physical block mapping by a structure which
contains an array of physicial blocks.  This is extremly inefficient and is
replaced with the normal startblock, length extent descriptors.

In addition also use thread-local storage for the block map, this is possible
because repair only processes one inode at a given time per thread, and the
block map does not have to outlive the processing of a single inode.

The combination of those factors means we can use pthread thread-local
storage to store the block map, and we can re-use the allocation over
and over again.

This should be ported over to xfs_db eventually, or even better we could try
to share the code.

[hch: added a small fix in blkmap_set_ext to not call memmove unless needed]

Signed-off-by: Barry Naujok <bnaujok at sgi.com>
Signed-off-by: Christoph Hellwig <hch at lst.de>
Reviewed-by: Alex Elder <aelder at sgi.com>

Index: xfsprogs-dev/repair/bmap.c
===================================================================
--- xfsprogs-dev.orig/repair/bmap.c	2009-10-19 01:55:18.807285612 +0200
+++ xfsprogs-dev/repair/bmap.c	2009-11-12 11:17:04.371006486 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2001,2005,2008 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -21,106 +21,46 @@
 #include "bmap.h"
 
 /*
- * Block mapping code taken from xfs_db.
- */
-
-/*
- * Append an extent to the block entry.
- */
-void
-blkent_append(
-	blkent_t	**entp,
-	xfs_dfsbno_t	b,
-	xfs_dfilblks_t	c)
-{
-	blkent_t	*ent;
-	size_t		size;
-	int		i;
-
-	ent = *entp;
-	size = BLKENT_SIZE(c + ent->nblks);
-	if ((*entp = ent = realloc(ent, size)) == NULL) {
-		do_warn(_("realloc failed in blkent_append (%u bytes)\n"),
-			size);
-		return;
-	}
-	for (i = 0; i < c; i++)
-		ent->blks[ent->nblks + i] = b + i;
-	ent->nblks += c;
-}
-
-/*
- * Make a new block entry.
- */
-blkent_t *
-blkent_new(
-	xfs_dfiloff_t	o,
-	xfs_dfsbno_t	b,
-	xfs_dfilblks_t	c)
-{
-	blkent_t	*ent;
-	int		i;
-
-	if ((ent = malloc(BLKENT_SIZE(c))) == NULL) {
-		do_warn(_("malloc failed in blkent_new (%u bytes)\n"),
-			BLKENT_SIZE(c));
-		return ent;
-	}
-	ent->nblks = c;
-	ent->startoff = o;
-	for (i = 0; i < c; i++)
-		ent->blks[i] = b + i;
-	return ent;
-}
-
-/*
- * Prepend an extent to the block entry.
+ * Track the logical to physical block mapping for inodes.
+ *
+ * Repair only processes one inode at a given time per thread, and the
+ * block map does not have to outlive the processing of a single inode.
+ *
+ * The combination of those factors means we can use pthreads thread-local
+ * storage to store the block map, and we can re-use the allocation over
+ * and over again.
  */
-void
-blkent_prepend(
-	blkent_t	**entp,
-	xfs_dfsbno_t	b,
-	xfs_dfilblks_t	c)
-{
-	int		i;
-	blkent_t	*newent;
-	blkent_t	*oldent;
 
-	oldent = *entp;
-	if ((newent = malloc(BLKENT_SIZE(oldent->nblks + c))) == NULL) {
-		do_warn(_("malloc failed in blkent_prepend (%u bytes)\n"),
-			BLKENT_SIZE(oldent->nblks + c));
-		*entp = newent;
-		return;
-	}
-	newent->nblks = oldent->nblks + c;
-	newent->startoff = oldent->startoff - c;
-	for (i = 0; i < c; i++)
-		newent->blks[i] = b + c;
-	for (; i < oldent->nblks + c; i++)
-		newent->blks[i] = oldent->blks[i - c];
-	free(oldent);
-	*entp = newent;
-}
+pthread_key_t	dblkmap_key;
+pthread_key_t	ablkmap_key;
 
-/*
- * Allocate a block map.
- */
 blkmap_t *
 blkmap_alloc(
-	xfs_extnum_t	nex)
+	xfs_extnum_t	nex,
+	int		whichfork)
 {
+	pthread_key_t	key;
 	blkmap_t	*blkmap;
 
+	ASSERT(whichfork == XFS_DATA_FORK || whichfork == XFS_ATTR_FORK);
+
 	if (nex < 1)
 		nex = 1;
-	if ((blkmap = malloc(BLKMAP_SIZE(nex))) == NULL) {
-		do_warn(_("malloc failed in blkmap_alloc (%u bytes)\n"),
-			BLKMAP_SIZE(nex));
-		return blkmap;
+
+	key = whichfork ? ablkmap_key : dblkmap_key;
+	blkmap = pthread_getspecific(key);
+	if (!blkmap || blkmap->naexts < nex) {
+		blkmap = realloc(blkmap, BLKMAP_SIZE(nex));
+		if (!blkmap) {
+			do_warn(_("malloc failed in blkmap_alloc (%u bytes)\n"),
+				BLKMAP_SIZE(nex));
+			return NULL;
+		}
+		pthread_setspecific(key, blkmap);
+		blkmap->naexts = nex;
 	}
-	blkmap->naents = nex;
-	blkmap->nents = 0;
+
+	blkmap->nexts = 0;
 	return blkmap;
 }
 
@@ -131,14 +71,7 @@ void
 blkmap_free(
 	blkmap_t	*blkmap)
 {
-	blkent_t	**entp;
-	xfs_extnum_t	i;
-
-	if (blkmap == NULL)
-		return;
-	for (i = 0, entp = blkmap->ents; i < blkmap->nents; i++, entp++)
-		free(*entp);
-	free(blkmap);
+	/* nothing to do! - keep the memory around for the next inode */
 }
 
 /*
@@ -149,20 +82,18 @@ blkmap_get(
 	blkmap_t	*blkmap,
 	xfs_dfiloff_t	o)
 {
-	blkent_t	*ent;
-	blkent_t	**entp;
+	bmap_ext_t	*ext = blkmap->exts;
 	int		i;
 
-	for (i = 0, entp = blkmap->ents; i < blkmap->nents; i++, entp++) {
-		ent = *entp;
-		if (o >= ent->startoff && o < ent->startoff + ent->nblks)
-			return ent->blks[o - ent->startoff];
+	for (i = 0; i < blkmap->nexts; i++, ext++) {
+		if (o >= ext->startoff && o < ext->startoff + ext->blockcount)
+			return ext->startblock + (o - ext->startoff);
 	}
 	return NULLDFSBNO;
 }
 
 /*
- * Get a chunk of entries from a block map.
+ * Get a chunk of entries from a block map - only used for reading dirv2 blocks
  */
 int
 blkmap_getn(
@@ -172,93 +103,62 @@ blkmap_getn(
 	bmap_ext_t	**bmpp,
 	bmap_ext_t	*bmpp_single)
 {
-	bmap_ext_t	*bmp;
-	blkent_t	*ent;
-	xfs_dfiloff_t	ento;
-	blkent_t	**entp;
+	bmap_ext_t	*bmp = NULL;
+	bmap_ext_t	*ext;
 	int		i;
 	int		nex;
 
 	if (nb == 1) {
-		/* 
+		/*
 		 * in the common case, when mp->m_dirblkfsbs == 1,
 		 * avoid additional malloc/free overhead
 		 */
 		bmpp_single->startblock = blkmap_get(blkmap, o);
-		bmpp_single->blockcount = 1;
-		bmpp_single->startoff = 0;
-		bmpp_single->flag = 0;
-		*bmpp = bmpp_single;
-		return (bmpp_single->startblock != NULLDFSBNO) ? 1 : 0;
+		goto single_ext;
 	}
-	for (i = nex = 0, bmp = NULL, entp = blkmap->ents;
-	     i < blkmap->nents;
-	     i++, entp++) {
-		ent = *entp;
-		if (ent->startoff >= o + nb)
+	ext = blkmap->exts;
+	nex = 0;
+	for (i = 0; i < blkmap->nexts; i++, ext++) {
+
+		if (ext->startoff >= o + nb)
 			break;
-		if (ent->startoff + ent->nblks <= o)
+		if (ext->startoff + ext->blockcount <= o)
 			continue;
-		for (ento = ent->startoff;
-		     ento < ent->startoff + ent->nblks && ento < o + nb;
-		     ento++) {
-			if (ento < o)
-				continue;
-			if (bmp &&
-			    bmp[nex - 1].startoff + bmp[nex - 1].blockcount ==
-				    ento &&
-			    bmp[nex - 1].startblock + bmp[nex - 1].blockcount ==
-				    ent->blks[ento - ent->startoff])
-				bmp[nex - 1].blockcount++;
-			else {
-				bmp = realloc(bmp, ++nex * sizeof(*bmp));
-				if (bmp == NULL) {
-					do_warn(_("blkmap_getn realloc failed"
-						" (%u bytes)\n"),
-						nex * sizeof(*bmp));
-					continue;
-				}
-				bmp[nex - 1].startoff = ento;
-				bmp[nex - 1].startblock =
-					ent->blks[ento - ent->startoff];
-				bmp[nex - 1].blockcount = 1;
-				bmp[nex - 1].flag = 0;
-			}
+
+		/*
+		 * if all the requested blocks are in one extent (also common),
+		 * use the bmpp_single option as well
+		 */
+		if (!bmp && o >= ext->startoff &&
+		    o + nb <= ext->startoff + ext->blockcount) {
+			bmpp_single->startblock =
+				 ext->startblock + (o - ext->startoff);
+			goto single_ext;
 		}
+
+		/*
+		 * rare case - multiple extents for a single dir block
+		 */
+		bmp = malloc(nb * sizeof(bmap_ext_t));
+		if (!bmp)
+			do_error(_("blkmap_getn malloc failed (%u bytes)\n"),
+						nb * sizeof(bmap_ext_t));
+
+		bmp[nex].startblock = ext->startblock + (o - ext->startoff);
+		bmp[nex].blockcount = MIN(nb, ext->blockcount -
+				(bmp[nex].startblock - ext->startblock));
+		o += bmp[nex].blockcount;
+		nb -= bmp[nex].blockcount;
+		nex++;
 	}
 	*bmpp = bmp;
 	return nex;
-}
-
-/*
- * Make a block map larger.
- */
-void
-blkmap_grow(
-	blkmap_t	**blkmapp,
-	blkent_t	**entp,
-	blkent_t	*newent)
-{
-	blkmap_t	*blkmap;
-	size_t		size;
-	int		i;
-	int		idx;
 
-	blkmap = *blkmapp;
-	idx = (int)(entp - blkmap->ents);
-	if (blkmap->naents == blkmap->nents) {
-		size = BLKMAP_SIZE(blkmap->nents + 1);
-		if ((*blkmapp = blkmap = realloc(blkmap, size)) == NULL) {
-			do_warn(_("realloc failed in blkmap_grow (%u bytes)\n"),
-				size);
-			return;
-		}
-		blkmap->naents++;
-	}
-	for (i = blkmap->nents; i > idx; i--)
-		blkmap->ents[i] = blkmap->ents[i - 1];
-	blkmap->ents[idx] = newent;
-	blkmap->nents++;
+single_ext:
+	bmpp_single->blockcount = nb;
+	bmpp_single->startoff = 0;	/* not even used by caller! */
+	*bmpp = bmpp_single;
+	return (bmpp_single->startblock != NULLDFSBNO) ? 1 : 0;
 }
 
 /*
@@ -268,12 +168,12 @@ xfs_dfiloff_t
 blkmap_last_off(
 	blkmap_t	*blkmap)
 {
-	blkent_t	*ent;
+	bmap_ext_t	*ext;
 
-	if (!blkmap->nents)
+	if (!blkmap->nexts)
 		return NULLDFILOFF;
-	ent = blkmap->ents[blkmap->nents - 1];
-	return ent->startoff + ent->nblks;
+	ext = blkmap->exts + blkmap->nexts - 1;
+	return ext->startoff + ext->blockcount;
 }
 
 /*
@@ -285,73 +185,45 @@ blkmap_next_off(
 	xfs_dfiloff_t	o,
 	int		*t)
 {
-	blkent_t	*ent;
-	blkent_t	**entp;
+	bmap_ext_t	*ext;
 
-	if (!blkmap->nents)
+	if (!blkmap->nexts)
 		return NULLDFILOFF;
 	if (o == NULLDFILOFF) {
 		*t = 0;
-		ent = blkmap->ents[0];
-		return ent->startoff;
+		return blkmap->exts[0].startoff;
 	}
-	entp = &blkmap->ents[*t];
-	ent = *entp;
-	if (o < ent->startoff + ent->nblks - 1)
+	ext = blkmap->exts + *t;
+	if (o < ext->startoff + ext->blockcount - 1)
 		return o + 1;
-	entp++;
-	if (entp >= &blkmap->ents[blkmap->nents])
+	if (*t >= blkmap->nexts - 1)
 		return NULLDFILOFF;
 	(*t)++;
-	ent = *entp;
-	return ent->startoff;
+	return ext[1].startoff;
 }
 
 /*
- * Set a block value in a block map.
+ * Make a block map larger.
  */
-void
-blkmap_set_blk(
-	blkmap_t	**blkmapp,
-	xfs_dfiloff_t	o,
-	xfs_dfsbno_t	b)
+static blkmap_t *
+blkmap_grow(
+	blkmap_t	**blkmapp)
 {
-	blkmap_t	*blkmap;
-	blkent_t	*ent;
-	blkent_t	**entp;
-	blkent_t	*nextent;
-
-	blkmap = *blkmapp;
-	for (entp = blkmap->ents; entp < &blkmap->ents[blkmap->nents]; entp++) {
-		ent = *entp;
-		if (o < ent->startoff - 1) {
-			ent = blkent_new(o, b, 1);
-			blkmap_grow(blkmapp, entp, ent);
-			return;
-		}
-		if (o == ent->startoff - 1) {
-			blkent_prepend(entp, b, 1);
-			return;
-		}
-		if (o >= ent->startoff && o < ent->startoff + ent->nblks) {
-			ent->blks[o - ent->startoff] = b;
-			return;
-		}
-		if (o > ent->startoff + ent->nblks)
-			continue;
-		blkent_append(entp, b, 1);
-		if (entp == &blkmap->ents[blkmap->nents - 1])
-			return;
-		ent = *entp;
-		nextent = entp[1];
-		if (ent->startoff + ent->nblks < nextent->startoff)
-			return;
-		blkent_append(entp, nextent->blks[0], nextent->nblks);
-		blkmap_shrink(blkmap, &entp[1]);
-		return;
+	pthread_key_t	key = dblkmap_key;
+	blkmap_t	*blkmap = *blkmapp;
+
+	if (pthread_getspecific(key) != blkmap) {
+		key = ablkmap_key;
+		ASSERT(pthread_getspecific(key) == blkmap);
 	}
-	ent = blkent_new(o, b, 1);
-	blkmap_grow(blkmapp, entp, ent);
+
+	blkmap->naexts += 4;
+	blkmap = realloc(blkmap, BLKMAP_SIZE(blkmap->naexts));
+	if (blkmap == NULL)
+		do_error(_("realloc failed in blkmap_grow\n"));
+	*blkmapp = blkmap;
+	pthread_setspecific(key, blkmap);
+	return blkmap;
 }
 
 /*
@@ -364,46 +236,23 @@ blkmap_set_ext(
 	xfs_dfsbno_t	b,
 	xfs_dfilblks_t	c)
 {
-	blkmap_t	*blkmap;
-	blkent_t	*ent;
-	blkent_t	**entp;
+	blkmap_t	*blkmap = *blkmapp;
 	xfs_extnum_t	i;
 
-	blkmap = *blkmapp;
-	if (!blkmap->nents) {
-		blkmap->ents[0] = blkent_new(o, b, c);
-		blkmap->nents = 1;
-		return;
-	}
-	entp = &blkmap->ents[blkmap->nents - 1];
-	ent = *entp;
-	if (ent->startoff + ent->nblks == o) {
-		blkent_append(entp, b, c);
-		return;
-	}
-	if (ent->startoff + ent->nblks < o) {
-		ent = blkent_new(o, b, c);
-		blkmap_grow(blkmapp, &blkmap->ents[blkmap->nents], ent);
-		return;
-	}
-	for (i = 0; i < c; i++)
-		blkmap_set_blk(blkmapp, o + i, b + i);
-}
+	if (blkmap->nexts == blkmap->naexts)
+		blkmap = blkmap_grow(blkmapp);
 
-/*
- * Make a block map smaller.
- */
-void
-blkmap_shrink(
-	blkmap_t	*blkmap,
-	blkent_t	**entp)
-{
-	int		i;
-	int		idx;
+	for (i = 0; i < blkmap->nexts; i++) {
+		if (blkmap->exts[i].startoff > o) {
+			memmove(blkmap->exts + i + 1,
+				blkmap->exts + i,
+				sizeof(bmap_ext_t) * (blkmap->nexts - i));
+			break;
+		}
+	}
 
-	free(*entp);
-	idx = (int)(entp - blkmap->ents);
-	for (i = idx + 1; i < blkmap->nents; i++)
-		blkmap->ents[i] = blkmap->ents[i - 1];
-	blkmap->nents--;
+	blkmap->exts[i].startoff = o;
+	blkmap->exts[i].startblock = b;
+	blkmap->exts[i].blockcount = c;
+	blkmap->nexts++;
 }
Index: xfsprogs-dev/repair/bmap.h
===================================================================
--- xfsprogs-dev.orig/repair/bmap.h	2009-10-19 01:55:18.824256628 +0200
+++ xfsprogs-dev/repair/bmap.h	2009-11-12 11:12:12.138274565 +0100
@@ -16,59 +16,41 @@
  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/*
- * Block mapping code taken from xfs_db.
- */
+#ifndef _XFS_REPAIR_BMAP_H
+#define _XFS_REPAIR_BMAP_H
 
 /*
- * Block map entry.
+ * Extent descriptor.
  */
-typedef struct blkent {
+typedef struct bmap_ext {
 	xfs_dfiloff_t	startoff;
-	xfs_dfilblks_t	nblks;
-	xfs_dfsbno_t	blks[1];
-} blkent_t;
-#define	BLKENT_SIZE(n)	\
-	(offsetof(blkent_t, blks) + (sizeof(xfs_dfsbno_t) * (n)))
+	xfs_dfsbno_t	startblock;
+	xfs_dfilblks_t	blockcount;
+} bmap_ext_t;
 
 /*
  * Block map.
  */
 typedef	struct blkmap {
-	int		naents;
-	int		nents;
-	blkent_t	*ents[1];
+	int		naexts;
+	int		nexts;
+	bmap_ext_t	exts[1];
 } blkmap_t;
-#define	BLKMAP_SIZE(n)	\
-	(offsetof(blkmap_t, ents) + (sizeof(blkent_t *) * (n)))
 
-/*
- * Extent descriptor.
- */
-typedef struct bmap_ext {
-	xfs_dfiloff_t	startoff;
-	xfs_dfsbno_t	startblock;
-	xfs_dfilblks_t	blockcount;
-	int		flag;
-} bmap_ext_t;
+#define	BLKMAP_SIZE(n)	\
+	(offsetof(blkmap_t, exts) + (sizeof(bmap_ext_t) * (n)))
 
-void		blkent_append(blkent_t **entp, xfs_dfsbno_t b,
-			      xfs_dfilblks_t c);
-blkent_t	*blkent_new(xfs_dfiloff_t o, xfs_dfsbno_t b, xfs_dfilblks_t c);
-void		blkent_prepend(blkent_t **entp, xfs_dfsbno_t b,
-			       xfs_dfilblks_t c);
-blkmap_t	*blkmap_alloc(xfs_extnum_t);
+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,
+			       xfs_dfsbno_t b, xfs_dfilblks_t c);
+
 xfs_dfsbno_t	blkmap_get(blkmap_t *blkmap, xfs_dfiloff_t o);
 int		blkmap_getn(blkmap_t *blkmap, xfs_dfiloff_t o,
-			    xfs_dfilblks_t nb, bmap_ext_t **bmpp, 
+			    xfs_dfilblks_t nb, bmap_ext_t **bmpp,
 			    bmap_ext_t *bmpp_single);
-void		blkmap_grow(blkmap_t **blkmapp, blkent_t **entp,
-			    blkent_t *newent);
 xfs_dfiloff_t	blkmap_last_off(blkmap_t *blkmap);
 xfs_dfiloff_t	blkmap_next_off(blkmap_t *blkmap, xfs_dfiloff_t o, int *t);
-void		blkmap_set_blk(blkmap_t **blkmapp, xfs_dfiloff_t o,
-			       xfs_dfsbno_t b);
-void		blkmap_set_ext(blkmap_t **blkmapp, xfs_dfiloff_t o,
-			       xfs_dfsbno_t b, xfs_dfilblks_t c);
-void		blkmap_shrink(blkmap_t *blkmap, blkent_t **entp);
+
+#endif /* _XFS_REPAIR_BMAP_H */
Index: xfsprogs-dev/repair/dinode.c
===================================================================
--- xfsprogs-dev.orig/repair/dinode.c	2009-10-19 01:55:18.842284064 +0200
+++ xfsprogs-dev/repair/dinode.c	2009-11-12 11:12:12.143274713 +0100
@@ -2050,7 +2050,7 @@ process_inode_data_fork(
 		*nextents = 1;
 
 	if (dinoc->di_format != XFS_DINODE_FMT_LOCAL && type != XR_INO_RTDATA)
-		*dblkmap = blkmap_alloc(*nextents);
+		*dblkmap = blkmap_alloc(*nextents, XFS_DATA_FORK);
 	*nextents = 0;
 
 	switch (dinoc->di_format) {
@@ -2172,14 +2172,14 @@ process_inode_attr_fork(
 		err = process_lclinode(mp, agno, ino, dino, XFS_ATTR_FORK);
 		break;
 	case XFS_DINODE_FMT_EXTENTS:
-		ablkmap = blkmap_alloc(*anextents);
+		ablkmap = blkmap_alloc(*anextents, XFS_ATTR_FORK);
 		*anextents = 0;
 		err = process_exinode(mp, agno, ino, dino, type, dirty,
 				atotblocks, anextents, &ablkmap,
 				XFS_ATTR_FORK, check_dups);
 		break;
 	case XFS_DINODE_FMT_BTREE:
-		ablkmap = blkmap_alloc(*anextents);
+		ablkmap = blkmap_alloc(*anextents, XFS_ATTR_FORK);
 		*anextents = 0;
 		err = process_btinode(mp, agno, ino, dino, type, dirty,
 				atotblocks, anextents, &ablkmap,
Index: xfsprogs-dev/repair/init.c
===================================================================
--- xfsprogs-dev.orig/repair/init.c	2009-11-12 11:11:41.025026345 +0100
+++ xfsprogs-dev/repair/init.c	2009-11-12 11:12:12.143274713 +0100
@@ -24,19 +24,24 @@
 #include "pthread.h"
 #include "avl.h"
 #include "dir.h"
+#include "bmap.h"
 #include "incore.h"
 #include "prefetch.h"
 #include <sys/resource.h>
 
+/* TODO: dirbuf/freemap key usage is completely b0rked - only used for dirv1 */
 static pthread_key_t dirbuf_key;
 static pthread_key_t dir_freemap_key;
 static pthread_key_t attr_freemap_key;
 
+extern pthread_key_t dblkmap_key;
+extern pthread_key_t ablkmap_key;
+
 static void
 ts_alloc(pthread_key_t key, unsigned n, size_t size)
 {
 	void *voidp;
-	voidp = malloc((n)*(size));
+	voidp = calloc(n, size);
 	if (voidp == NULL) {
 		do_error(_("ts_alloc: cannot allocate thread specific storage\n"));
 		/* NO RETURN */
@@ -52,6 +57,9 @@ ts_create(void)
 	pthread_key_create(&dirbuf_key, NULL);
 	pthread_key_create(&dir_freemap_key, NULL);
 	pthread_key_create(&attr_freemap_key, NULL);
+
+	pthread_key_create(&dblkmap_key, NULL);
+	pthread_key_create(&ablkmap_key, NULL);
 }
 
 void




More information about the xfs mailing list