aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2007-07-20 03:31:46 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-20 11:44:19 -0400
commiteb0645a8b1f14da300f40bb9f424640cd1181fbf (patch)
tree462789626fcd1775bec80d74d19bcd68797589c8
parent7c6129c68fe90a61166800b40217a850b8faee98 (diff)
async_tx: fix kmap_atomic usage in async_memcpy
Andrew Morton: [async_memcpy] is very wrong if both ASYNC_TX_KMAP_DST and ASYNC_TX_KMAP_SRC can ever be set. We'll end up using the same kmap slot for both src add dest and we get either corrupted data or a BUG. Evgeniy Polyakov: Btw, shouldn't it always be kmap_atomic() even if flag is not set. That pages are usual one returned by alloc_page(). So fix the usage of kmap_atomic and kill the ASYNC_TX_KMAP_DST and ASYNC_TX_KMAP_SRC flags. Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Evgeniy Polyakov <johnpol@2ka.mipt.ru> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--crypto/async_tx/async_memcpy.c19
-rw-r--r--drivers/md/raid5.c4
-rw-r--r--include/linux/async_tx.h6
3 files changed, 6 insertions, 23 deletions
diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c
index a973f4ef897d..047e533fcc5b 100644
--- a/crypto/async_tx/async_memcpy.c
+++ b/crypto/async_tx/async_memcpy.c
@@ -36,7 +36,6 @@
36 * @offset: offset in pages to start transaction 36 * @offset: offset in pages to start transaction
37 * @len: length in bytes 37 * @len: length in bytes
38 * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK, 38 * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK,
39 * ASYNC_TX_KMAP_SRC, ASYNC_TX_KMAP_DST
40 * @depend_tx: memcpy depends on the result of this transaction 39 * @depend_tx: memcpy depends on the result of this transaction
41 * @cb_fn: function to call when the memcpy completes 40 * @cb_fn: function to call when the memcpy completes
42 * @cb_param: parameter to pass to the callback routine 41 * @cb_param: parameter to pass to the callback routine
@@ -88,23 +87,13 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
88 __FUNCTION__); 87 __FUNCTION__);
89 } 88 }
90 89
91 if (flags & ASYNC_TX_KMAP_DST) 90 dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;
92 dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset; 91 src_buf = kmap_atomic(src, KM_USER1) + src_offset;
93 else
94 dest_buf = page_address(dest) + dest_offset;
95
96 if (flags & ASYNC_TX_KMAP_SRC)
97 src_buf = kmap_atomic(src, KM_USER0) + src_offset;
98 else
99 src_buf = page_address(src) + src_offset;
100 92
101 memcpy(dest_buf, src_buf, len); 93 memcpy(dest_buf, src_buf, len);
102 94
103 if (flags & ASYNC_TX_KMAP_DST) 95 kunmap_atomic(dest_buf, KM_USER0);
104 kunmap_atomic(dest_buf, KM_USER0); 96 kunmap_atomic(src_buf, KM_USER1);
105
106 if (flags & ASYNC_TX_KMAP_SRC)
107 kunmap_atomic(src_buf, KM_USER0);
108 97
109 async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param); 98 async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
110 } 99 }
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index c8dfdb302916..d90ee145effe 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -493,12 +493,12 @@ async_copy_data(int frombio, struct bio *bio, struct page *page,
493 if (frombio) 493 if (frombio)
494 tx = async_memcpy(page, bio_page, page_offset, 494 tx = async_memcpy(page, bio_page, page_offset,
495 b_offset, clen, 495 b_offset, clen,
496 ASYNC_TX_DEP_ACK | ASYNC_TX_KMAP_SRC, 496 ASYNC_TX_DEP_ACK,
497 tx, NULL, NULL); 497 tx, NULL, NULL);
498 else 498 else
499 tx = async_memcpy(bio_page, page, b_offset, 499 tx = async_memcpy(bio_page, page, b_offset,
500 page_offset, clen, 500 page_offset, clen,
501 ASYNC_TX_DEP_ACK | ASYNC_TX_KMAP_DST, 501 ASYNC_TX_DEP_ACK,
502 tx, NULL, NULL); 502 tx, NULL, NULL);
503 } 503 }
504 if (clen < len) /* hit end of page */ 504 if (clen < len) /* hit end of page */
diff --git a/include/linux/async_tx.h b/include/linux/async_tx.h
index ff1255079fa1..bdca3f1b3213 100644
--- a/include/linux/async_tx.h
+++ b/include/linux/async_tx.h
@@ -51,10 +51,6 @@ struct dma_chan_ref {
51 * @ASYNC_TX_ACK: immediately ack the descriptor, precludes setting up a 51 * @ASYNC_TX_ACK: immediately ack the descriptor, precludes setting up a
52 * dependency chain 52 * dependency chain
53 * @ASYNC_TX_DEP_ACK: ack the dependency descriptor. Useful for chaining. 53 * @ASYNC_TX_DEP_ACK: ack the dependency descriptor. Useful for chaining.
54 * @ASYNC_TX_KMAP_SRC: if the transaction is to be performed synchronously
55 * take an atomic mapping (KM_USER0) on the source page(s)
56 * @ASYNC_TX_KMAP_DST: if the transaction is to be performed synchronously
57 * take an atomic mapping (KM_USER0) on the dest page(s)
58 */ 54 */
59enum async_tx_flags { 55enum async_tx_flags {
60 ASYNC_TX_XOR_ZERO_DST = (1 << 0), 56 ASYNC_TX_XOR_ZERO_DST = (1 << 0),
@@ -62,8 +58,6 @@ enum async_tx_flags {
62 ASYNC_TX_ASSUME_COHERENT = (1 << 2), 58 ASYNC_TX_ASSUME_COHERENT = (1 << 2),
63 ASYNC_TX_ACK = (1 << 3), 59 ASYNC_TX_ACK = (1 << 3),
64 ASYNC_TX_DEP_ACK = (1 << 4), 60 ASYNC_TX_DEP_ACK = (1 << 4),
65 ASYNC_TX_KMAP_SRC = (1 << 5),
66 ASYNC_TX_KMAP_DST = (1 << 6),
67}; 61};
68 62
69#ifdef CONFIG_DMA_ENGINE 63#ifdef CONFIG_DMA_ENGINE