Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5157b4aa authored by Dan Williams's avatar Dan Williams Committed by Linus Torvalds
Browse files

raid6: fix recovery performance regression



The raid6 recovery code should immediately drop back to the optimized
synchronous path when a p+q dma resource is not available.  Otherwise we
run the non-optimized/multi-pass async code in sync mode.

Verified with raid6test (NDISKS=255)

Applies to kernels >= 2.6.32.

Cc: <stable@kernel.org>
Acked-by: default avatarNeilBrown <neilb@suse.de>
Reported-by: default avatarH. Peter Anvin <hpa@zytor.com>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 7ebd4675
Loading
Loading
Loading
Loading
+13 −8
Original line number Diff line number Diff line
@@ -324,6 +324,7 @@ struct dma_async_tx_descriptor *
async_raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
			struct page **blocks, struct async_submit_ctl *submit)
{
	void *scribble = submit->scribble;
	int non_zero_srcs, i;

	BUG_ON(faila == failb);
@@ -332,11 +333,13 @@ async_raid6_2data_recov(int disks, size_t bytes, int faila, int failb,

	pr_debug("%s: disks: %d len: %zu\n", __func__, disks, bytes);

	/* we need to preserve the contents of 'blocks' for the async
	 * case, so punt to synchronous if a scribble buffer is not available
	/* if a dma resource is not available or a scribble buffer is not
	 * available punt to the synchronous path.  In the 'dma not
	 * available' case be sure to use the scribble buffer to
	 * preserve the content of 'blocks' as the caller intended.
	 */
	if (!submit->scribble) {
		void **ptrs = (void **) blocks;
	if (!async_dma_find_channel(DMA_PQ) || !scribble) {
		void **ptrs = scribble ? scribble : (void **) blocks;

		async_tx_quiesce(&submit->depend_tx);
		for (i = 0; i < disks; i++)
@@ -406,11 +409,13 @@ async_raid6_datap_recov(int disks, size_t bytes, int faila,

	pr_debug("%s: disks: %d len: %zu\n", __func__, disks, bytes);

	/* we need to preserve the contents of 'blocks' for the async
	 * case, so punt to synchronous if a scribble buffer is not available
	/* if a dma resource is not available or a scribble buffer is not
	 * available punt to the synchronous path.  In the 'dma not
	 * available' case be sure to use the scribble buffer to
	 * preserve the content of 'blocks' as the caller intended.
	 */
	if (!scribble) {
		void **ptrs = (void **) blocks;
	if (!async_dma_find_channel(DMA_PQ) || !scribble) {
		void **ptrs = scribble ? scribble : (void **) blocks;

		async_tx_quiesce(&submit->depend_tx);
		for (i = 0; i < disks; i++)