During mkfs.ext4 /dev/sda1 I run into: | page: 69, remaining size: 18432, length: 2048, i: 126, j: 63 | Step 2 - sg_s[126]: deb09890 length: 2048 offset: 0 sg_d[63].length: 4096 | Step 2 - length: 2048 src_offset: 0 dst_offset: 2048 | page: 69, remaining size: 16384, length: 2048, i: 127, j: 64 | page: 70 in same page table | Step 1 - sg_s[127]: deb098a8 length: 0 offset: 0 sg_d[64].length: 4096 | Step 1 - length: 0 src_offset: 0 dst_offset: 0 | ------------[ cut here ]------------ | kernel BUG at include/linux/scatterlist.h:97! | invalid opcode: 0000 [#5] PREEMPT SMP | EIP is at rd_MEMCPY_do_task+0x780/0x790 [target_core_mod] | [<e0ab38d4>] __transport_execute_tasks+0xd4/0x190 [target_core_mod] So the code assumes that the sg list is only a array while in reality somebody chained it. Using sg_next() works properly and patch makes such a change. With this patch the bug goes away. However after umount/mount of the device my files are gone. So something is still not right. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx> --- drivers/target/target_core_rd.c | 98 ++++++++++++++++++++------------------- 1 files changed, 50 insertions(+), 48 deletions(-) diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index 23cdb09..7a21cbe 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -352,7 +352,7 @@ static int rd_MEMCPY_read(struct rd_request *req) struct rd_dev_sg_table *table; struct scatterlist *sg_d, *sg_s; void *dst, *src; - u32 i = 0, j = 0, dst_offset = 0, src_offset = 0; + u32 dst_offset = 0, src_offset = 0; u32 length, page_end = 0, table_sg_end; u32 rd_offset = req->rd_offset; @@ -369,16 +369,15 @@ static int rd_MEMCPY_read(struct rd_request *req) req->rd_page, req->rd_offset); src_offset = rd_offset; - while (req->rd_size) { - if ((sg_d[i].length - dst_offset) < - (sg_s[j].length - src_offset)) { - length = (sg_d[i].length - dst_offset); - - pr_debug("Step 1 - sg_d[%d]: %p length: %d" - " offset: %u sg_s[%d].length: %u\n", i, - &sg_d[i], sg_d[i].length, sg_d[i].offset, j, - sg_s[j].length); + if ((sg_d->length - dst_offset) < + (sg_s->length - src_offset)) { + length = (sg_d->length - dst_offset); + + pr_debug("Step 1 - sg_d: %p length: %d" + " offset: %u sg_s[%p].length: %u\n", + sg_d, sg_d->length, sg_d->offset, sg_s, + sg_s->length); pr_debug("Step 1 - length: %u dst_offset: %u" " src_offset: %u\n", length, dst_offset, src_offset); @@ -386,22 +385,23 @@ static int rd_MEMCPY_read(struct rd_request *req) if (length > req->rd_size) length = req->rd_size; - dst = sg_virt(&sg_d[i++]) + dst_offset; + dst = sg_virt(sg_d) + dst_offset; BUG_ON(!dst); + sg_d = sg_next(sg_d); - src = sg_virt(&sg_s[j]) + src_offset; + src = sg_virt(sg_s) + src_offset; BUG_ON(!src); dst_offset = 0; src_offset = length; page_end = 0; } else { - length = (sg_s[j].length - src_offset); + length = (sg_s->length - src_offset); - pr_debug("Step 2 - sg_d[%d]: %p length: %d" - " offset: %u sg_s[%d].length: %u\n", i, - &sg_d[i], sg_d[i].length, sg_d[i].offset, - j, sg_s[j].length); + pr_debug("Step 2 - sg_d: %p length: %d" + " offset: %u sg_s[%p].length: %u\n", + sg_d, sg_d->length, sg_d->offset, + sg_s, sg_s->length); pr_debug("Step 2 - length: %u dst_offset: %u" " src_offset: %u\n", length, dst_offset, src_offset); @@ -409,16 +409,17 @@ static int rd_MEMCPY_read(struct rd_request *req) if (length > req->rd_size) length = req->rd_size; - dst = sg_virt(&sg_d[i]) + dst_offset; + dst = sg_virt(sg_d) + dst_offset; BUG_ON(!dst); - if (sg_d[i].length == length) { - i++; + if (sg_d->length == length) { + sg_d = sg_next(sg_d); dst_offset = 0; } else dst_offset = length; - src = sg_virt(&sg_s[j++]) + src_offset; + src = sg_virt(sg_s) + src_offset; + sg_s = sg_next(sg_s); BUG_ON(!src); src_offset = 0; @@ -428,8 +429,8 @@ static int rd_MEMCPY_read(struct rd_request *req) memcpy(dst, src, length); pr_debug("page: %u, remaining size: %u, length: %u," - " i: %u, j: %u\n", req->rd_page, - (req->rd_size - length), length, i, j); + "\n", req->rd_page, + (req->rd_size - length), length); req->rd_size -= length; if (!req->rd_size) @@ -451,7 +452,7 @@ static int rd_MEMCPY_read(struct rd_request *req) if (!table) return -EINVAL; - sg_s = &table->sg_table[j = 0]; + sg_s = table->sg_table; } return 0; @@ -468,7 +469,7 @@ static int rd_MEMCPY_write(struct rd_request *req) struct rd_dev_sg_table *table; struct scatterlist *sg_d, *sg_s; void *dst, *src; - u32 i = 0, j = 0, dst_offset = 0, src_offset = 0; + u32 dst_offset = 0, src_offset = 0; u32 length, page_end = 0, table_sg_end; u32 rd_offset = req->rd_offset; @@ -487,14 +488,14 @@ static int rd_MEMCPY_write(struct rd_request *req) dst_offset = rd_offset; while (req->rd_size) { - if ((sg_s[i].length - src_offset) < - (sg_d[j].length - dst_offset)) { - length = (sg_s[i].length - src_offset); - - pr_debug("Step 1 - sg_s[%d]: %p length: %d" - " offset: %d sg_d[%d].length: %u\n", i, - &sg_s[i], sg_s[i].length, sg_s[i].offset, - j, sg_d[j].length); + if ((sg_s->length - src_offset) < + (sg_d->length - dst_offset)) { + length = (sg_s->length - src_offset); + + pr_debug("Step 1 - sg_s: %p length: %d" + " offset: %d sg_d.length: %u\n", + sg_s, sg_s->length, sg_s->offset, + sg_d->length); pr_debug("Step 1 - length: %u src_offset: %u" " dst_offset: %u\n", length, src_offset, dst_offset); @@ -502,22 +503,23 @@ static int rd_MEMCPY_write(struct rd_request *req) if (length > req->rd_size) length = req->rd_size; - src = sg_virt(&sg_s[i++]) + src_offset; + src = sg_virt(sg_s) + src_offset; BUG_ON(!src); + sg_s = sg_next(sg_s); - dst = sg_virt(&sg_d[j]) + dst_offset; + dst = sg_virt(sg_d) + dst_offset; BUG_ON(!dst); src_offset = 0; dst_offset = length; page_end = 0; } else { - length = (sg_d[j].length - dst_offset); + length = (sg_d->length - dst_offset); - pr_debug("Step 2 - sg_s[%d]: %p length: %d" - " offset: %d sg_d[%d].length: %u\n", i, - &sg_s[i], sg_s[i].length, sg_s[i].offset, - j, sg_d[j].length); + pr_debug("Step 2 - sg_s: %p length: %d" + " offset: %d sg_d.length: %u\n", + sg_s, sg_s->length, sg_s->offset, + sg_d->length); pr_debug("Step 2 - length: %u src_offset: %u" " dst_offset: %u\n", length, src_offset, dst_offset); @@ -525,17 +527,18 @@ static int rd_MEMCPY_write(struct rd_request *req) if (length > req->rd_size) length = req->rd_size; - src = sg_virt(&sg_s[i]) + src_offset; + src = sg_virt(sg_s) + src_offset; BUG_ON(!src); - if (sg_s[i].length == length) { - i++; + if (sg_s->length == length) { + sg_s = sg_next(sg_s); src_offset = 0; } else src_offset = length; - dst = sg_virt(&sg_d[j++]) + dst_offset; + dst = sg_virt(sg_d) + dst_offset; BUG_ON(!dst); + sg_d = sg_next(sg_d); dst_offset = 0; page_end = 1; @@ -543,9 +546,8 @@ static int rd_MEMCPY_write(struct rd_request *req) memcpy(dst, src, length); - pr_debug("page: %u, remaining size: %u, length: %u," - " i: %u, j: %u\n", req->rd_page, - (req->rd_size - length), length, i, j); + pr_debug("page: %u, remaining size: %u, length: %u\n", + req->rd_page, (req->rd_size - length), length); req->rd_size -= length; if (!req->rd_size) @@ -567,7 +569,7 @@ static int rd_MEMCPY_write(struct rd_request *req) if (!table) return -EINVAL; - sg_d = &table->sg_table[j = 0]; + sg_d = table->sg_table; } return 0; -- 1.7.7.1 -- To unsubscribe from this list: send the line "unsubscribe target-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html