[PATCH 2/2] target/rd: fix or rewrite the copy routine

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

 



Okay, I haven't really figured out this copy works in detail and
something here is wring since I lose my data and iblock working.
However it is possible to implement the same functionality with less
code. This patch is proof of it :)
So the advantages of this version is less code, no BUG() statements and
it works on highmem. RD's pages are allocated via GFP_KERNEL so
sg_virt() is fine.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>
---
 drivers/target/target_core_rd.c |  247 +++++++--------------------------------
 1 files changed, 40 insertions(+), 207 deletions(-)

diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c
index d42cbec..1d2c4b6 100644
--- a/drivers/target/target_core_rd.c
+++ b/drivers/target/target_core_rd.c
@@ -341,237 +341,74 @@ static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page)
 	return NULL;
 }
 
-/*	rd_MEMCPY_read():
- *
- *
- */
-static int rd_MEMCPY_read(struct rd_request *req)
+static int rd_MEMCPY(struct rd_request *req, u32 read_rd)
 {
 	struct se_task *task = &req->rd_task;
 	struct rd_dev *dev = req->rd_task.task_se_cmd->se_dev->dev_ptr;
 	struct rd_dev_sg_table *table;
-	struct scatterlist *sg_d, *sg_s;
-	void *dst, *src;
-	u32 dst_offset = 0, src_offset = 0;
-	u32 length, page_end = 0, table_sg_end;
+	struct scatterlist *rd_sg;
+	struct sg_mapping_iter m;
 	u32 rd_offset = req->rd_offset;
+	u32 src_len;
 
 	table = rd_get_sg_table(dev, req->rd_page);
 	if (!table)
 		return -EINVAL;
 
-	table_sg_end = (table->page_end_offset - req->rd_page);
-	sg_d = task->task_sg;
-	sg_s = &table->sg_table[req->rd_page - table->page_start_offset];
+	rd_sg = &table->sg_table[req->rd_page - table->page_start_offset];
 
-	pr_debug("RD[%u]: Read LBA: %llu, Size: %u Page: %u, Offset:"
-		" %u\n", dev->rd_dev_id, task->task_lba, req->rd_size,
-		req->rd_page, req->rd_offset);
+	pr_debug("RD[%u]: %s LBA: %llu, Size: %u Page: %u, Offset: %u\n",
+			dev->rd_dev_id, read_rd ? "Read" : "Write",
+			task->task_lba, req->rd_size, req->rd_page,
+			rd_offset);
 
-	src_offset = rd_offset;
+	src_len = PAGE_SIZE - rd_offset;
+	sg_miter_start(&m, task->task_sg, task->task_sg_nents,
+			read_rd ? SG_MITER_TO_SG : SG_MITER_FROM_SG);
 	while (req->rd_size) {
-		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);
-
-			if (length > req->rd_size)
-				length = req->rd_size;
-
-			dst = sg_virt(sg_d) + dst_offset;
-			BUG_ON(!dst);
-			sg_d = sg_next(sg_d);
-
-			src = sg_virt(sg_s) + src_offset;
-			BUG_ON(!src);
-
-			dst_offset = 0;
-			src_offset = length;
-			page_end = 0;
-		} else {
-			length = (sg_s->length - src_offset);
-
-			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);
-
-			if (length > req->rd_size)
-				length = req->rd_size;
-
-			dst = sg_virt(sg_d) + dst_offset;
-			BUG_ON(!dst);
-
-			if (sg_d->length == length) {
-				sg_d = sg_next(sg_d);
-				dst_offset = 0;
-			} else
-				dst_offset = length;
-
-			src = sg_virt(sg_s) + src_offset;
-			sg_s = sg_next(sg_s);
-			BUG_ON(!src);
-
-			src_offset = 0;
-			page_end = 1;
-		}
+		u32 len;
+		void *rd_addr;
 
-		memcpy(dst, src, length);
+		sg_miter_next(&m);
+		len = min(m.length, src_len);
+		m.consumed = len;
 
-		pr_debug("page: %u, remaining size: %u, length: %u,"
-			"\n", req->rd_page,
-			(req->rd_size - length), length);
+		rd_addr = sg_virt(rd_sg) + rd_offset;
 
-		req->rd_size -= length;
-		if (!req->rd_size)
-			return 0;
+		if (read_rd)
+			memcpy(m.addr, rd_addr, len);
+		else
+			memcpy(rd_addr, m.addr, len);
 
-		if (!page_end)
+		req->rd_size -= len;
+		if (!req->rd_size)
 			continue;
 
-		if (++req->rd_page <= table->page_end_offset) {
-			pr_debug("page: %u in same page table\n",
-				req->rd_page);
+		src_len -= len;
+		if (src_len) {
+			rd_offset += len;
 			continue;
 		}
 
-		pr_debug("getting new page table for page: %u\n",
-				req->rd_page);
-
-		table = rd_get_sg_table(dev, req->rd_page);
-		if (!table)
-			return -EINVAL;
-
-		sg_s = table->sg_table;
-	}
-
-	return 0;
-}
-
-/*	rd_MEMCPY_write():
- *
- *
- */
-static int rd_MEMCPY_write(struct rd_request *req)
-{
-	struct se_task *task = &req->rd_task;
-	struct rd_dev *dev = req->rd_task.task_se_cmd->se_dev->dev_ptr;
-	struct rd_dev_sg_table *table;
-	struct scatterlist *sg_d, *sg_s;
-	void *dst, *src;
-	u32 dst_offset = 0, src_offset = 0;
-	u32 length, page_end = 0, table_sg_end;
-	u32 rd_offset = req->rd_offset;
-
-	table = rd_get_sg_table(dev, req->rd_page);
-	if (!table)
-		return -EINVAL;
-
-	table_sg_end = (table->page_end_offset - req->rd_page);
-	sg_d = &table->sg_table[req->rd_page - table->page_start_offset];
-	sg_s = task->task_sg;
-
-	pr_debug("RD[%d] Write LBA: %llu, Size: %u, Page: %u,"
-		" Offset: %u\n", dev->rd_dev_id, task->task_lba, req->rd_size,
-		req->rd_page, req->rd_offset);
-
-	dst_offset = rd_offset;
-
-	while (req->rd_size) {
-		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);
-
-			if (length > req->rd_size)
-				length = req->rd_size;
-
-			src = sg_virt(sg_s) + src_offset;
-			BUG_ON(!src);
-			sg_s = sg_next(sg_s);
-
-			dst = sg_virt(sg_d) + dst_offset;
-			BUG_ON(!dst);
-
-			src_offset = 0;
-			dst_offset = length;
-			page_end = 0;
-		} else {
-			length = (sg_d->length - dst_offset);
-
-			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);
-
-			if (length > req->rd_size)
-				length = req->rd_size;
-
-			src = sg_virt(sg_s) + src_offset;
-			BUG_ON(!src);
-
-			if (sg_s->length == length) {
-				sg_s = sg_next(sg_s);
-				src_offset = 0;
-			} else
-				src_offset = length;
-
-			dst = sg_virt(sg_d) + dst_offset;
-			BUG_ON(!dst);
-			sg_d = sg_next(sg_d);
-
-			dst_offset = 0;
-			page_end = 1;
-		}
-
-		memcpy(dst, src, length);
-
-		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)
-			return 0;
-
-		if (!page_end)
-			continue;
-
-		if (++req->rd_page <= table->page_end_offset) {
-			pr_debug("page: %u in same page table\n",
-				req->rd_page);
+		/* rd page completed, next one please */
+		req->rd_page++;
+		rd_offset = 0;
+		src_len = PAGE_SIZE;
+		if (req->rd_page <= table->page_end_offset) {
+			rd_sg++;
 			continue;
 		}
 
-		pr_debug("getting new page table for page: %u\n",
-				req->rd_page);
-
 		table = rd_get_sg_table(dev, req->rd_page);
-		if (!table)
+		if (!table) {
+			sg_miter_stop(&m);
 			return -EINVAL;
+		}
 
-		sg_d = table->sg_table;
+		/* since we increment, the first sg entry is correct */
+		rd_sg = table->sg_table;
 	}
-
+	sg_miter_stop(&m);
 	return 0;
 }
 
@@ -591,11 +428,7 @@ static int rd_MEMCPY_do_task(struct se_task *task)
 	req->rd_page = tmp;
 	req->rd_size = task->task_size;
 
-	if (task->task_data_direction == DMA_FROM_DEVICE)
-		ret = rd_MEMCPY_read(req);
-	else
-		ret = rd_MEMCPY_write(req);
-
+	ret = rd_MEMCPY(req, task->task_data_direction == DMA_FROM_DEVICE);
 	if (ret != 0)
 		return ret;
 
-- 
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