dm-buffered: fix a bug when calling memcpy Fix a bug if the buffer is allocated using __vmalloc or if it is allocated from slab cache. Signed-off-by: Mikulas Patocka --- drivers/md/dm-buffered-target.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) Index: linux-2.6/drivers/md/dm-buffered-target.c =================================================================== --- linux-2.6.orig/drivers/md/dm-buffered-target.c +++ linux-2.6/drivers/md/dm-buffered-target.c @@ -76,18 +76,6 @@ static sector_t _buffered_size(struct dm return _to_block(bc, ti->len - bc->start) + (_sector_mod(bc, ti->len) ? 1 : 0); } -static void _memcpy(struct buffered_c *bc, struct dm_buffer *bp, - struct page *dst, struct page *src, - loff_t dst_offset, loff_t src_offset, size_t len) -{ - void *d = kmap_local_page(dst); - void *s = kmap_local_page(src); - - memcpy(d + dst_offset, s + src_offset, len); - kunmap_local(d); - kunmap_local(s); -} - /* * Process @bvec of @bio optionally doing 2 bufio I/Os * in case the page of the bio_vec overlaps two buffers. @@ -103,6 +91,7 @@ static void _io(struct buffered_c *bc, s struct dm_buffer *bp; while (total_len) { + char *p; block = _to_block(bc, sector); buffer_offset = to_bytes(_sector_mod(bc, sector)); len = min(block_size - buffer_offset, total_len); @@ -137,8 +126,10 @@ static void _io(struct buffered_c *bc, s WARN_ON_ONCE(block != dm_bufio_get_block_number(bp)); /* Superfluous call to cover the API example */ buffer = dm_bufio_get_block_data(bp); - _memcpy(bc, bp, virt_to_page(buffer), bvec->bv_page, - buffer_offset, bvec_offset, len); + + p = kmap_local_page(bvec->bv_page); + memcpy(buffer + buffer_offset, p + bvec_offset, len); + kunmap_local(p); /* Superfluous conditional to show both functions dirtying buffers. */ if (!buffer_offset && len == block_size) @@ -150,8 +141,8 @@ static void _io(struct buffered_c *bc, s } else { /* (Superfluous) function consistency check example */ WARN_ON(block != dm_bufio_get_block_number(bp)); - _memcpy(bc, bp, bvec->bv_page, virt_to_page(buffer), - bvec_offset, buffer_offset, len); + p = kmap_local_page(bvec->bv_page); + memcpy(p + bvec_offset, buffer + buffer_offset, len); dm_bufio_release(bp); }