From: Eric Sandeen Date: Mon, 24 Aug 2015 01:52:45 +0000 (+1000) Subject: xfs_repair: unconditionally free blockmaps when threads complete X-Git-Tag: v4.2.0-rc3~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bd7581425a223f58f1730e5a9ea14c8f0b51e0a2;p=thirdparty%2Fxfsprogs-dev.git xfs_repair: unconditionally free blockmaps when threads complete blkmap_free() doesn't actually free the block map unless it's inordinately large; this keeps us from constantly freeing and re-allocating blockmaps for each inode, which makes sense. However, once the threads which have allocated these structures exit, we should actually free them; they can grow up to 2MB for each of the data and attr maps, for each thread, and not be freed through the normal blkmap_free() test. Signed-off-by: Eric Sandeen Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- diff --git a/repair/bmap.c b/repair/bmap.c index 26556328c..abe9f48de 100644 --- a/repair/bmap.c +++ b/repair/bmap.c @@ -82,7 +82,8 @@ blkmap_alloc( * extents) then free it to release the memory. This prevents us from pinning * large tracts of memory due to corrupted fork values or one-off fragmented * files. Otherwise we have nothing to do but keep the memory around for the - * next inode + * next inode. + * When the thread is done, it should do an unconditional, final free. */ void blkmap_free( @@ -103,6 +104,20 @@ blkmap_free( free(blkmap); } +void +blkmap_free_final(void) +{ + blkmap_t *blkmap; + + blkmap = pthread_getspecific(dblkmap_key); + pthread_setspecific(dblkmap_key, NULL); + free(blkmap); + + blkmap = pthread_getspecific(ablkmap_key); + pthread_setspecific(ablkmap_key, NULL); + free(blkmap); +} + /* * Get one entry from a block map. */ diff --git a/repair/bmap.h b/repair/bmap.h index 973081a69..501ef6b5d 100644 --- a/repair/bmap.h +++ b/repair/bmap.h @@ -58,6 +58,7 @@ extern pthread_key_t ablkmap_key; blkmap_t *blkmap_alloc(xfs_extnum_t nex, int whichfork); void blkmap_free(blkmap_t *blkmap); +void blkmap_free_final(void); int blkmap_set_ext(blkmap_t **blkmapp, xfs_fileoff_t o, xfs_fsblock_t b, xfs_filblks_t c); diff --git a/repair/phase3.c b/repair/phase3.c index 20786af33..76c944036 100644 --- a/repair/phase3.c +++ b/repair/phase3.c @@ -27,6 +27,7 @@ #include "err_protos.h" #include "dinode.h" #include "progress.h" +#include "bmap.h" static void process_agi_unlinked( @@ -75,6 +76,7 @@ process_ag_func( wait_for_inode_prefetch(arg); do_log(_(" - agno = %d\n"), agno); process_aginodes(wq->mp, arg, agno, 1, 0, 1); + blkmap_free_final(); cleanup_inode_prefetch(arg); } diff --git a/repair/phase4.c b/repair/phase4.c index e0571e874..1a7d7b5f5 100644 --- a/repair/phase4.c +++ b/repair/phase4.c @@ -138,6 +138,7 @@ process_ag_func( wait_for_inode_prefetch(arg); do_log(_(" - agno = %d\n"), agno); process_aginodes(wq->mp, arg, agno, 0, 1, 0); + blkmap_free_final(); cleanup_inode_prefetch(arg); /*