diff options
author | Dan Williams <dan.j.williams@intel.com> | 2007-07-20 03:31:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-20 11:44:19 -0400 |
commit | eb0645a8b1f14da300f40bb9f424640cd1181fbf (patch) | |
tree | 462789626fcd1775bec80d74d19bcd68797589c8 | |
parent | 7c6129c68fe90a61166800b40217a850b8faee98 (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.c | 19 | ||||
-rw-r--r-- | drivers/md/raid5.c | 4 | ||||
-rw-r--r-- | include/linux/async_tx.h | 6 |
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 | */ |
59 | enum async_tx_flags { | 55 | enum 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 |