Re[4]: [PATCH 03/11][v3] async_tx: add support for asynchronous RAID6 recovery operations

2009-01-17 Thread Yuri Tikhonov
On Friday, January 16, 2009 you wrote:

 On Fri, Jan 16, 2009 at 4:51 AM, Yuri Tikhonov y...@emcraft.com wrote:
  The reason why I preferred to use async_pq() instead of async_xor()
 here is to maximize the chance that the whole D+D recovery operation
 will be handled in one ADMA device, i.e. without channels switch and
 the latency introduced because of that.


 This should be a function of the async_tx_find_channel implementation.
  The default version tries to keep a chain of operations on one
 channel.

 struct dma_chan *
 __async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
 enum dma_transaction_type tx_type)
 {
 /* see if we can keep the chain on one channel */
 if (depend_tx 
 dma_has_cap(tx_type, depend_tx-chan-device-cap_mask))
 return depend_tx-chan;
 return dma_find_channel(tx_type);
 }

 Right. Then I need to update my ADMA driver, and add support for 
explicit DMA_XOR capability on channels which can process DMA_PQ.
Thanks.

 Regards, Yuri

 --
 Yuri Tikhonov, Senior Software Engineer
 Emcraft Systems, www.emcraft.com

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re[2]: [PATCH 03/11][v3] async_tx: add support for asynchronous RAID6 recovery operations

2009-01-16 Thread Yuri Tikhonov

On Thursday, January 15, 2009 Dan Williams wrote:

 On Mon, Jan 12, 2009 at 5:43 PM, Yuri Tikhonov y...@emcraft.com wrote:
 +   /* (2) Calculate Q+Qxy */
 +   lptrs[0] = ptrs[failb];
 +   lptrs[1] = ptrs[disks-1];
 +   lptrs[2] = NULL;
 +   tx = async_pq(lptrs, NULL, 0, 1, bytes, ASYNC_TX_DEP_ACK,
 + tx, NULL, NULL);
 +
 +   /* (3) Calculate P+Pxy */
 +   lptrs[0] = ptrs[faila];
 +   lptrs[1] = ptrs[disks-2];
 +   lptrs[2] = NULL;
 +   tx = async_pq(lptrs, NULL, 0, 1, bytes, ASYNC_TX_DEP_ACK,
 + tx, NULL, NULL);
 +

 These two calls convinced me that ASYNC_TX_PQ_ZERO_{P,Q} need to go.
 A 1-source async_pq operation does not make sense.

 Another source is hidden under not-set ASYNC_TX_PQ_ZERO_{P,Q} :) 
Though, I agree, this looks rather misleading.

   These should be:

/* (2) Calculate Q+Qxy */
lptrs[0] = ptrs[disks-1];
lptrs[1] = ptrs[failb];
tx = async_xor(lptrs[0], lptrs, 0, 2, bytes,
   ASYNC_TX_XOR_DROP_DST|ASYNC_TX_DEP_ACK, tx, NULL, NULL);

 /* (3) Calculate P+Pxy */
lptrs[0] = ptrs[disks-2];
lptrs[1] = ptrs[faila];
tx = async_xor(lptrs[0], lptrs, 0, 2, bytes,
   ASYNC_TX_XOR_DROP_DST|ASYNC_TX_DEP_ACK, tx, NULL, NULL);


 The reason why I preferred to use async_pq() instead of async_xor() 
here is to maximize the chance that the whole D+D recovery operation 
will be handled in one ADMA device, i.e. without channels switch and 
the latency introduced because of that.

 So, if we'll decide to stay with ASYNC_TX_PQ_ZERO_{P,Q}, then this 
should be probably kept unchanged, but if we'll get rid of 
ASYNC_TX_PQ_ZERO_{P,Q}, then, obviously, we'll have to use 
async_xor()s here as you suggest.


 Regards, Yuri

 --
 Yuri Tikhonov, Senior Software Engineer
 Emcraft Systems, www.emcraft.com

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: Re[2]: [PATCH 03/11][v3] async_tx: add support for asynchronous RAID6 recovery operations

2009-01-16 Thread Dan Williams
On Fri, Jan 16, 2009 at 4:51 AM, Yuri Tikhonov y...@emcraft.com wrote:
  The reason why I preferred to use async_pq() instead of async_xor()
 here is to maximize the chance that the whole D+D recovery operation
 will be handled in one ADMA device, i.e. without channels switch and
 the latency introduced because of that.


This should be a function of the async_tx_find_channel implementation.
 The default version tries to keep a chain of operations on one
channel.

struct dma_chan *
__async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
enum dma_transaction_type tx_type)
{
/* see if we can keep the chain on one channel */
if (depend_tx 
dma_has_cap(tx_type, depend_tx-chan-device-cap_mask))
return depend_tx-chan;
return dma_find_channel(tx_type);
}

--
Dan
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 03/11][v3] async_tx: add support for asynchronous RAID6 recovery operations

2009-01-14 Thread Dan Williams
On Mon, Jan 12, 2009 at 5:43 PM, Yuri Tikhonov y...@emcraft.com wrote:
 +   /* (2) Calculate Q+Qxy */
 +   lptrs[0] = ptrs[failb];
 +   lptrs[1] = ptrs[disks-1];
 +   lptrs[2] = NULL;
 +   tx = async_pq(lptrs, NULL, 0, 1, bytes, ASYNC_TX_DEP_ACK,
 + tx, NULL, NULL);
 +
 +   /* (3) Calculate P+Pxy */
 +   lptrs[0] = ptrs[faila];
 +   lptrs[1] = ptrs[disks-2];
 +   lptrs[2] = NULL;
 +   tx = async_pq(lptrs, NULL, 0, 1, bytes, ASYNC_TX_DEP_ACK,
 + tx, NULL, NULL);
 +

These two calls convinced me that ASYNC_TX_PQ_ZERO_{P,Q} need to go.
A 1-source async_pq operation does not make sense.  These should be:

   /* (2) Calculate Q+Qxy */
   lptrs[0] = ptrs[disks-1];
   lptrs[1] = ptrs[failb];
   tx = async_xor(lptrs[0], lptrs, 0, 2, bytes,
  ASYNC_TX_XOR_DROP_DST|ASYNC_TX_DEP_ACK, tx, NULL, NULL);

/* (3) Calculate P+Pxy */
   lptrs[0] = ptrs[disks-2];
   lptrs[1] = ptrs[faila];
   tx = async_xor(lptrs[0], lptrs, 0, 2, bytes,
  ASYNC_TX_XOR_DROP_DST|ASYNC_TX_DEP_ACK, tx, NULL, NULL);

Regards,
Dan
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 03/11][v3] async_tx: add support for asynchronous RAID6 recovery operations

2009-01-12 Thread Yuri Tikhonov
This patch extends async_tx API with two operations for recovery
operations on RAID6 array with two failed disks using new async_pq()
operation. Patch introduces the following functions:

 async_r6_dd_recov() recovers after double data disk failure

 async_r6_dp_recov() recovers after D+P failure

Signed-off-by: Yuri Tikhonov y...@emcraft.com
Signed-off-by: Ilya Yanok ya...@emcraft.com
---
 crypto/async_tx/Kconfig |5 +
 crypto/async_tx/Makefile|1 +
 crypto/async_tx/async_r6recov.c |  286 +++
 include/linux/async_tx.h|   11 ++
 4 files changed, 303 insertions(+), 0 deletions(-)
 create mode 100644 crypto/async_tx/async_r6recov.c

diff --git a/crypto/async_tx/Kconfig b/crypto/async_tx/Kconfig
index cb6d731..0b56224 100644
--- a/crypto/async_tx/Kconfig
+++ b/crypto/async_tx/Kconfig
@@ -18,3 +18,8 @@ config ASYNC_PQ
tristate
select ASYNC_CORE
 
+config ASYNC_R6RECOV
+   tristate
+   select ASYNC_CORE
+   select ASYNC_PQ
+
diff --git a/crypto/async_tx/Makefile b/crypto/async_tx/Makefile
index 1b99265..0ed8f13 100644
--- a/crypto/async_tx/Makefile
+++ b/crypto/async_tx/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_ASYNC_MEMCPY) += async_memcpy.o
 obj-$(CONFIG_ASYNC_MEMSET) += async_memset.o
 obj-$(CONFIG_ASYNC_XOR) += async_xor.o
 obj-$(CONFIG_ASYNC_PQ) += async_pq.o
+obj-$(CONFIG_ASYNC_R6RECOV) += async_r6recov.o
diff --git a/crypto/async_tx/async_r6recov.c b/crypto/async_tx/async_r6recov.c
new file mode 100644
index 000..8642c14
--- /dev/null
+++ b/crypto/async_tx/async_r6recov.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright(c) 2007 Yuri Tikhonov y...@emcraft.com
+ *
+ * Developed for DENX Software Engineering GmbH
+ *
+ * Asynchronous RAID-6 recovery calculations ASYNC_TX API.
+ *
+ * based on async_xor.c code written by:
+ * Dan Williams dan.j.willi...@intel.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include linux/kernel.h
+#include linux/interrupt.h
+#include linux/dma-mapping.h
+#include linux/raid/xor.h
+#include linux/async_tx.h
+
+#include ../drivers/md/raid6.h
+
+/**
+ * async_r6_dd_recov - attempt to calculate two data misses using dma engines.
+ * @disks: number of disks in the RAID-6 array
+ * @bytes: size of strip
+ * @faila: first failed drive index
+ * @failb: second failed drive index
+ * @ptrs: array of pointers to strips (last two must be p and q, respectively)
+ * @flags: ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+ * @depend_tx: depends on the result of this transaction.
+ * @cb: function to call when the operation completes
+ * @cb_param: parameter to pass to the callback routine
+ */
+struct dma_async_tx_descriptor *
+async_r6_dd_recov(int disks, size_t bytes, int faila, int failb,
+   struct page **ptrs, enum async_tx_flags flags,
+   struct dma_async_tx_descriptor *depend_tx,
+   dma_async_tx_callback cb, void *cb_param)
+{
+   struct dma_async_tx_descriptor *tx = NULL;
+   struct page *lptrs[disks];
+   unsigned char lcoef[disks-4];
+   int i = 0, k = 0, fc = -1;
+   uint8_t bc[2];
+   dma_async_tx_callback lcb = NULL;
+   void *lcb_param = NULL;
+
+   /* Assume that failb  faila */
+   if (faila  failb) {
+   fc = faila;
+   faila = failb;
+   failb = fc;
+   }
+
+   /* Try to compute missed data asynchronously. */
+   if (disks == 4) {
+   /*
+* Pxy and Qxy are zero in this case so we already have
+* P+Pxy and Q+Qxy in P and Q strips respectively.
+*/
+   tx = depend_tx;
+   lcb = cb;
+   lcb_param = cb_param;
+   goto do_mult;
+   }
+
+   /*
+* (1) Calculate Qxy and Pxy:
+* Qxy = A(0)*D(0) + ... + A(n-1)*D(n-1) + A(n+1)*D(n+1) + ... +
+*   A(m-1)*D(m-1) + A(m+1)*D(m+1) + ... + A(disks-1)*D(disks-1),
+* where n = faila, m = failb.
+*/
+   for (i = 0, k = 0; i  disks - 2; i++) {
+   if (i != faila  i != failb) {
+   lptrs[k] = ptrs[i];
+   lcoef[k] = raid6_gfexp[i];
+   k++;
+   }
+   }
+
+   lptrs[k] = ptrs[faila];
+   lptrs[k+1] = ptrs[failb];
+