[PATCH] target/rd: use sg_next() while walking through the sg list

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux