aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSagi Grimberg <sagig@mellanox.com>2015-06-11 12:58:34 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2015-06-23 03:43:40 -0400
commite2e21bd8f979a24462070cc89fae11e819cae90a (patch)
tree06ab5dcf58dcf1d58f72f53659af9f8090e1e07d
parent7c0d0d51d26497866d2951a35f1736fc765e4fcf (diff)
target/user: Fix inconsistent kmap_atomic/kunmap_atomic
Pointers that are mapped by kmap_atomic() + offset must be unmapped without the offset. That would cause problems if the SG element length exceeds the PAGE_SIZE limit. Signed-off-by: Sagi Grimberg <sagig@mellanox.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/target/target_core_user.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index 949e6165ef8a..078ef6e3eb70 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -260,7 +260,8 @@ static void alloc_and_scatter_data_area(struct tcmu_dev *udev,
260 260
261 /* Uh oh, we wrapped the buffer. Must split sg across 2 iovs. */ 261 /* Uh oh, we wrapped the buffer. Must split sg across 2 iovs. */
262 if (sg->length != copy_bytes) { 262 if (sg->length != copy_bytes) {
263 from += copy_bytes; 263 void *from_skip = from + copy_bytes;
264
264 copy_bytes = sg->length - copy_bytes; 265 copy_bytes = sg->length - copy_bytes;
265 266
266 (*iov)->iov_len = copy_bytes; 267 (*iov)->iov_len = copy_bytes;
@@ -270,7 +271,7 @@ static void alloc_and_scatter_data_area(struct tcmu_dev *udev,
270 if (copy_data) { 271 if (copy_data) {
271 to = (void *) udev->mb_addr + 272 to = (void *) udev->mb_addr +
272 udev->data_off + udev->data_head; 273 udev->data_off + udev->data_head;
273 memcpy(to, from, copy_bytes); 274 memcpy(to, from_skip, copy_bytes);
274 tcmu_flush_dcache_range(to, copy_bytes); 275 tcmu_flush_dcache_range(to, copy_bytes);
275 } 276 }
276 277
@@ -281,7 +282,7 @@ static void alloc_and_scatter_data_area(struct tcmu_dev *udev,
281 copy_bytes, udev->data_size); 282 copy_bytes, udev->data_size);
282 } 283 }
283 284
284 kunmap_atomic(from); 285 kunmap_atomic(from - sg->offset);
285 } 286 }
286} 287}
287 288
@@ -309,18 +310,19 @@ static void gather_and_free_data_area(struct tcmu_dev *udev,
309 310
310 /* Uh oh, wrapped the data buffer for this sg's data */ 311 /* Uh oh, wrapped the data buffer for this sg's data */
311 if (sg->length != copy_bytes) { 312 if (sg->length != copy_bytes) {
313 void *to_skip = to + copy_bytes;
314
312 from = (void *) udev->mb_addr + 315 from = (void *) udev->mb_addr +
313 udev->data_off + udev->data_tail; 316 udev->data_off + udev->data_tail;
314 WARN_ON(udev->data_tail); 317 WARN_ON(udev->data_tail);
315 to += copy_bytes;
316 copy_bytes = sg->length - copy_bytes; 318 copy_bytes = sg->length - copy_bytes;
317 tcmu_flush_dcache_range(from, copy_bytes); 319 tcmu_flush_dcache_range(from, copy_bytes);
318 memcpy(to, from, copy_bytes); 320 memcpy(to_skip, from, copy_bytes);
319 321
320 UPDATE_HEAD(udev->data_tail, 322 UPDATE_HEAD(udev->data_tail,
321 copy_bytes, udev->data_size); 323 copy_bytes, udev->data_size);
322 } 324 }
323 kunmap_atomic(to); 325 kunmap_atomic(to - sg->offset);
324 } 326 }
325} 327}
326 328