Blame SOURCES/xfsprogs-3.2.0-prefetch-fix.patch

0690ef
[PATCH] xfs_repair: fix prefetch queue waiting
0690ef
0690ef
This fixes a regression caused by:
0690ef
0690ef
97b1fcf xfs_repair: fix array overrun in do_inode_prefetch
0690ef
0690ef
The thread creation loop has 2 ways to exit; either via
0690ef
the loop counter based on thread_count, or the break statement
0690ef
if we've started enough workers to cover all AGs.
0690ef
0690ef
Whether or not the loop counter "i" reflects the number of
0690ef
threads started depends on whether or not we exited via the
0690ef
break.
0690ef
0690ef
The above commit prevented us from indexing off the end
0690ef
of the queues[] array if we actually advanced "i" all the
0690ef
way to thread_count, but in the case where we break, "i"
0690ef
is one *less* than the nr of threads started, so we don't
0690ef
wait for completion of all threads, and all hell breaks
0690ef
loose in phase 5.
0690ef
0690ef
Just stop with the cleverness of re-using the loop counter -
0690ef
instead, explicitly count threads that we start, and then use
0690ef
that counter to wait for each worker to complete.
0690ef
0690ef
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
0690ef
Reviewed-by: Brian Foster <bfoster@redhat.com>
0690ef
---
0690ef
0690ef
I have one fs which demonstrates the problem, and have verified
0690ef
the regression & tested the fix against that.
0690ef
0690ef
I'll run this over xfstests overnight, but it seems obvious
0690ef
from here (OTOH the other fix seemed obvious too) 
0690ef
0690ef
diff --git a/repair/prefetch.c b/repair/prefetch.c
0690ef
index e47a48e..4c32395 100644
0690ef
--- a/repair/prefetch.c
0690ef
+++ b/repair/prefetch.c
0690ef
@@ -944,6 +944,7 @@ do_inode_prefetch(
0690ef
 	int			i;
0690ef
 	struct work_queue	queue;
0690ef
 	struct work_queue	*queues;
0690ef
+	int			queues_started = 0;
0690ef
 
0690ef
 	/*
0690ef
 	 * If the previous phases of repair have not overflowed the buffer
0690ef
@@ -987,6 +988,7 @@ do_inode_prefetch(
0690ef
 
0690ef
 		create_work_queue(&queues[i], mp, 1);
0690ef
 		queue_work(&queues[i], prefetch_ag_range_work, 0, wargs);
0690ef
+		queues_started++;
0690ef
 
0690ef
 		if (wargs->end_ag >= mp->m_sb.sb_agcount)
0690ef
 			break;
0690ef
@@ -995,7 +997,7 @@ do_inode_prefetch(
0690ef
 	/*
0690ef
 	 * wait for workers to complete
0690ef
 	 */
0690ef
-	while (i--)
0690ef
+	for (i = 0; i < queues_started; i++)
0690ef
 		destroy_work_queue(&queues[i]);
0690ef
 	free(queues);
0690ef
 }
0690ef
0690ef
_______________________________________________
0690ef
xfs mailing list
0690ef
xfs@oss.sgi.com
0690ef
http://oss.sgi.com/mailman/listinfo/xfs
0690ef
0690ef