From f6dae0c6d06251901a710db6841d0d44df10f1a2 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Mon, 15 Mar 2010 22:19:25 +0000 Subject: [PATCH] * Mon Mar 15 2010 Eric Sandeen 3.1.1-6 - Fix missing locking for btree manipulation in xfs_repair --- xfsprogs-3.1.1-btree-locking.patch | 108 +++++++++++++++++++++++++++++ xfsprogs.spec | 7 +- 2 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 xfsprogs-3.1.1-btree-locking.patch diff --git a/xfsprogs-3.1.1-btree-locking.patch b/xfsprogs-3.1.1-btree-locking.patch new file mode 100644 index 0000000..291d6d1 --- /dev/null +++ b/xfsprogs-3.1.1-btree-locking.patch @@ -0,0 +1,108 @@ +From: Dave Chinner +Date: Sun, 14 Mar 2010 22:52:08 +0000 (+1100) +Subject: xfsprogs: duplicate extent btrees in xfs_repair need locking +X-Git-Url: http://git.kernel.org/?p=fs%2Fxfs%2Fxfsprogs-dev.git;a=commitdiff_plain;h=853a75b3b30b0556fb5f100d4087f1ce46769bd1 + +xfsprogs: duplicate extent btrees in xfs_repair need locking + +The per-ag duplicate extent btrees can be search concurrently from multiple +threads. This occurs when inode extent lists are being processed and inodes +with extents in the same AG are checked concurrently. The btrees have an +internal traversal cursor, so doing concurrent searches can result in the +cursor being corrupted for both searches. + +Add an external lock for each duplicate extent tree and use it for searches, +inserts and deletes to ensure that we don't trash the state of any operation. + +Signed-off-by: Dave Chinner +Reviewed-by: Christoph Hellwig +--- + +diff --git a/repair/incore_ext.c b/repair/incore_ext.c +index a362e5a..60dd4c4 100644 +--- a/repair/incore_ext.c ++++ b/repair/incore_ext.c +@@ -74,6 +74,7 @@ static rt_ext_flist_t rt_ext_flist; + static avl64tree_desc_t *rt_ext_tree_ptr; /* dup extent tree for rt */ + + static struct btree_root **dup_extent_trees; /* per ag dup extent trees */ ++static pthread_mutex_t *dup_extent_tree_locks; + + static avltree_desc_t **extent_bno_ptrs; /* + * array of extent tree ptrs +@@ -108,7 +109,9 @@ void + release_dup_extent_tree( + xfs_agnumber_t agno) + { ++ pthread_mutex_lock(&dup_extent_tree_locks[agno]); + btree_clear(dup_extent_trees[agno]); ++ pthread_mutex_unlock(&dup_extent_tree_locks[agno]); + } + + int +@@ -117,12 +120,16 @@ add_dup_extent( + xfs_agblock_t startblock, + xfs_extlen_t blockcount) + { ++ int ret; + #ifdef XR_DUP_TRACE + fprintf(stderr, "Adding dup extent - %d/%d %d\n", agno, startblock, + blockcount); + #endif +- return btree_insert(dup_extent_trees[agno], startblock, ++ pthread_mutex_lock(&dup_extent_tree_locks[agno]); ++ ret = btree_insert(dup_extent_trees[agno], startblock, + (void *)(uintptr_t)(startblock + blockcount)); ++ pthread_mutex_unlock(&dup_extent_tree_locks[agno]); ++ return ret; + } + + int +@@ -132,13 +139,22 @@ search_dup_extent( + xfs_agblock_t end_agbno) + { + unsigned long bno; ++ int ret; + +- if (!btree_find(dup_extent_trees[agno], start_agbno, &bno)) +- return 0; /* this really shouldn't happen */ +- if (bno < end_agbno) +- return 1; +- return (uintptr_t)btree_peek_prev(dup_extent_trees[agno], NULL) > ++ pthread_mutex_lock(&dup_extent_tree_locks[agno]); ++ if (!btree_find(dup_extent_trees[agno], start_agbno, &bno)) { ++ ret = 0; ++ goto out; /* this really shouldn't happen */ ++ } ++ if (bno < end_agbno) { ++ ret = 1; ++ goto out; ++ } ++ ret = (uintptr_t)btree_peek_prev(dup_extent_trees[agno], NULL) > + start_agbno; ++out: ++ pthread_mutex_unlock(&dup_extent_tree_locks[agno]); ++ return ret; + } + + +@@ -856,6 +872,10 @@ incore_ext_init(xfs_mount_t *mp) + if (!dup_extent_trees) + do_error(_("couldn't malloc dup extent tree descriptor table\n")); + ++ dup_extent_tree_locks = calloc(agcount, sizeof(pthread_mutex_t)); ++ if (!dup_extent_tree_locks) ++ do_error(_("couldn't malloc dup extent tree descriptor table\n")); ++ + if ((extent_bno_ptrs = malloc(agcount * + sizeof(avltree_desc_t *))) == NULL) + do_error( +@@ -879,6 +899,7 @@ incore_ext_init(xfs_mount_t *mp) + + for (i = 0; i < agcount; i++) { + btree_init(&dup_extent_trees[i]); ++ pthread_mutex_init(&dup_extent_tree_locks[i], NULL); + avl_init_tree(extent_bno_ptrs[i], &avl_extent_tree_ops); + avl_init_tree(extent_bcnt_ptrs[i], &avl_extent_bcnt_tree_ops); + } + diff --git a/xfsprogs.spec b/xfsprogs.spec index 6203816..338d38e 100644 --- a/xfsprogs.spec +++ b/xfsprogs.spec @@ -1,7 +1,7 @@ Summary: Utilities for managing the XFS filesystem Name: xfsprogs Version: 3.1.1 -Release: 5%{?dist} +Release: 6%{?dist} # Licensing based on generic "GNU GENERAL PUBLIC LICENSE" # in source, with no mention of version. # doc/COPYING file specifies what is GPL and what is LGPL @@ -21,6 +21,7 @@ Conflicts: xfsdump < 3.0.1 Patch0: xfsprogs-3.1.0-glibc-fixes.patch Patch1: xfsprogs-3.1.1-fd-test-fix.patch Patch2: xfsprogs-3.1.1-empty-blkid-fix.patch +Patch3: xfsprogs-3.1.1-btree-locking.patch %description A set of commands to use the XFS filesystem, including mkfs.xfs. @@ -68,6 +69,7 @@ in building or running the xfstests QA suite. %patch0 -p1 %patch1 -p1 %patch2 -p1 +%patch3 -p1 %build export tagname=CC DEBUG=-DNDEBUG @@ -193,6 +195,9 @@ rm -rf $RPM_BUILD_ROOT %{_includedir}/xfs/xfs_types.h %changelog +* Mon Mar 15 2010 Eric Sandeen 3.1.1-6 +- Fix missing locking for btree manipulation in xfs_repair + * Fri Feb 12 2010 Eric Sandeen 3.1.1-5 - --enable-static=no doesn't work; just nuke static libs