From 6b10ac7c262d7a2fb16bb7d5a133da05f721ba1a Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Thu, 11 Jun 2015 19:58:34 +0300 Subject: [PATCH] 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 Signed-off-by: Nicholas Bellinger Orabug: 25395066 (cherry picked from commit e2e21bd8f979a24462070cc89fae11e819cae90a) Signed-off-by: Kyle Fortin Reviewed-by: Shan Hai --- drivers/target/target_core_user.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index aebaad55e23f..2c8485905317 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, /* Uh oh, we wrapped the buffer. Must split sg across 2 iovs. */ if (sg->length != copy_bytes) { - from += copy_bytes; + void *from_skip = from + copy_bytes; + copy_bytes = sg->length - copy_bytes; (*iov)->iov_len = copy_bytes; @@ -270,7 +271,7 @@ static void alloc_and_scatter_data_area(struct tcmu_dev *udev, if (copy_data) { to = (void *) udev->mb_addr + udev->data_off + udev->data_head; - memcpy(to, from, copy_bytes); + memcpy(to, from_skip, copy_bytes); tcmu_flush_dcache_range(to, copy_bytes); } @@ -281,7 +282,7 @@ static void alloc_and_scatter_data_area(struct tcmu_dev *udev, copy_bytes, udev->data_size); } - kunmap_atomic(from); + kunmap_atomic(from - sg->offset); } } @@ -309,18 +310,19 @@ static void gather_and_free_data_area(struct tcmu_dev *udev, /* Uh oh, wrapped the data buffer for this sg's data */ if (sg->length != copy_bytes) { + void *to_skip = to + copy_bytes; + from = (void *) udev->mb_addr + udev->data_off + udev->data_tail; WARN_ON(udev->data_tail); - to += copy_bytes; copy_bytes = sg->length - copy_bytes; tcmu_flush_dcache_range(from, copy_bytes); - memcpy(to, from, copy_bytes); + memcpy(to_skip, from, copy_bytes); UPDATE_HEAD(udev->data_tail, copy_bytes, udev->data_size); } - kunmap_atomic(to); + kunmap_atomic(to - sg->offset); } } -- 2.50.1