* [PATCH v3 1/4] lib/scatterlist: factor out sg_miter_get_next_page() from sg_miter_next()
2013-06-23 12:37 [PATCH v3 0/4] introduce sg_pcopy_from_buffer() and sg_pcopy_to_buffer() Akinobu Mita
@ 2013-06-23 12:37 ` Akinobu Mita
2013-06-23 12:37 ` [PATCH v3 2/4] lib/scatterlist: introduce sg_pcopy_from_buffer() and sg_pcopy_to_buffer() Akinobu Mita
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Akinobu Mita @ 2013-06-23 12:37 UTC (permalink / raw)
To: linux-kernel, akpm
Cc: Akinobu Mita, Tejun Heo, Imre Deak, Herbert Xu, David S. Miller,
linux-crypto, James E.J. Bottomley, Douglas Gilbert, linux-scsi
This function is used to proceed page iterator to the next page if
necessary, and will be used to implement the variants of
sg_copy_{from,to}_buffer() later.
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Acked-by: Tejun Heo <tj@kernel.org>
Cc: Tejun Heo <tj@kernel.org>
Cc: Imre Deak <imre.deak@intel.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: linux-crypto@vger.kernel.org
Cc: "James E.J. Bottomley" <JBottomley@parallels.com>
Cc: Douglas Gilbert <dgilbert@interlog.com>
Cc: linux-scsi@vger.kernel.org
---
* Change from v2
- Add Acked-by line
lib/scatterlist.c | 39 ++++++++++++++++++++++++---------------
1 file changed, 24 insertions(+), 15 deletions(-)
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index a1cf8ca..c35b929 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -453,6 +453,28 @@ void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl,
}
EXPORT_SYMBOL(sg_miter_start);
+static bool sg_miter_get_next_page(struct sg_mapping_iter *miter)
+{
+ if (!miter->__remaining) {
+ struct scatterlist *sg;
+ unsigned long pgoffset;
+
+ if (!__sg_page_iter_next(&miter->piter))
+ return false;
+
+ sg = miter->piter.sg;
+ pgoffset = miter->piter.sg_pgoffset;
+
+ miter->__offset = pgoffset ? 0 : sg->offset;
+ miter->__remaining = sg->offset + sg->length -
+ (pgoffset << PAGE_SHIFT) - miter->__offset;
+ miter->__remaining = min_t(unsigned long, miter->__remaining,
+ PAGE_SIZE - miter->__offset);
+ }
+
+ return true;
+}
+
/**
* sg_miter_next - proceed mapping iterator to the next mapping
* @miter: sg mapping iter to proceed
@@ -478,22 +500,9 @@ bool sg_miter_next(struct sg_mapping_iter *miter)
* Get to the next page if necessary.
* __remaining, __offset is adjusted by sg_miter_stop
*/
- if (!miter->__remaining) {
- struct scatterlist *sg;
- unsigned long pgoffset;
-
- if (!__sg_page_iter_next(&miter->piter))
- return false;
-
- sg = miter->piter.sg;
- pgoffset = miter->piter.sg_pgoffset;
+ if (!sg_miter_get_next_page(miter))
+ return false;
- miter->__offset = pgoffset ? 0 : sg->offset;
- miter->__remaining = sg->offset + sg->length -
- (pgoffset << PAGE_SHIFT) - miter->__offset;
- miter->__remaining = min_t(unsigned long, miter->__remaining,
- PAGE_SIZE - miter->__offset);
- }
miter->page = sg_page_iter_page(&miter->piter);
miter->consumed = miter->length = miter->__remaining;
--
1.8.1.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v3 2/4] lib/scatterlist: introduce sg_pcopy_from_buffer() and sg_pcopy_to_buffer()
2013-06-23 12:37 [PATCH v3 0/4] introduce sg_pcopy_from_buffer() and sg_pcopy_to_buffer() Akinobu Mita
2013-06-23 12:37 ` [PATCH v3 1/4] lib/scatterlist: factor out sg_miter_get_next_page() from sg_miter_next() Akinobu Mita
@ 2013-06-23 12:37 ` Akinobu Mita
2013-06-24 23:27 ` Tejun Heo
2013-06-23 12:37 ` [PATCH v3 3/4] crypto: talitos: use sg_pcopy_to_buffer() Akinobu Mita
2013-06-23 12:37 ` [PATCH v3 4/4] scsi_debug: fix do_device_access() with wrap around range Akinobu Mita
3 siblings, 1 reply; 7+ messages in thread
From: Akinobu Mita @ 2013-06-23 12:37 UTC (permalink / raw)
To: linux-kernel, akpm
Cc: Akinobu Mita, Tejun Heo, Imre Deak, Herbert Xu, David S. Miller,
linux-crypto, James E.J. Bottomley, Douglas Gilbert, linux-scsi
The only difference between sg_pcopy_{from,to}_buffer() and
sg_copy_{from,to}_buffer() is an additional argument that specifies
the number of bytes to skip the SG list before copying.
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Imre Deak <imre.deak@intel.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: linux-crypto@vger.kernel.org
Cc: "James E.J. Bottomley" <JBottomley@parallels.com>
Cc: Douglas Gilbert <dgilbert@interlog.com>
Cc: linux-scsi@vger.kernel.org
---
* Changes from v2
- Rename sg_miter_seek() to sg_miter_skip()
- Remove the restriction on when sg_miter_skip() can be called
include/linux/scatterlist.h | 5 +++
lib/scatterlist.c | 88 ++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 88 insertions(+), 5 deletions(-)
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index 2680677..adae88f 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -244,6 +244,11 @@ size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,
size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
void *buf, size_t buflen);
+size_t sg_pcopy_from_buffer(struct scatterlist *sgl, unsigned int nents,
+ void *buf, size_t buflen, off_t skip);
+size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents,
+ void *buf, size_t buflen, off_t skip);
+
/*
* Maximum number of entries that will be allocated in one piece, if
* a list larger than this is required then chaining will be utilized.
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index c35b929..129a82f 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -476,6 +476,43 @@ static bool sg_miter_get_next_page(struct sg_mapping_iter *miter)
}
/**
+ * sg_miter_skip - reposition mapping iterator
+ * @miter: sg mapping iter to be skipped
+ * @offset: number of bytes to plus the current location
+ *
+ * Description:
+ * Sets the offset of @miter to its current location plus @offset bytes.
+ * If mapping iterator @miter has been proceeded by sg_miter_next(), this
+ * stops @miter.
+ *
+ * Context:
+ * Don't care if @miter is stopped, or not proceeded yet.
+ * Otherwise, preemption disabled if the SG_MITER_ATOMIC is set.
+ *
+ * Returns:
+ * true if @miter contains the valid mapping. false if end of sg
+ * list is reached.
+ */
+static bool sg_miter_skip(struct sg_mapping_iter *miter, off_t offset)
+{
+ sg_miter_stop(miter);
+
+ while (offset) {
+ off_t consumed;
+
+ if (!sg_miter_get_next_page(miter))
+ return false;
+
+ consumed = min_t(off_t, offset, miter->__remaining);
+ miter->__offset += consumed;
+ miter->__remaining -= consumed;
+ offset -= consumed;
+ }
+
+ return true;
+}
+
+/**
* sg_miter_next - proceed mapping iterator to the next mapping
* @miter: sg mapping iter to proceed
*
@@ -561,14 +598,16 @@ EXPORT_SYMBOL(sg_miter_stop);
* @nents: Number of SG entries
* @buf: Where to copy from
* @buflen: The number of bytes to copy
- * @to_buffer: transfer direction (non zero == from an sg list to a
- * buffer, 0 == from a buffer to an sg list
+ * @skip: Number of bytes to skip before copying
+ * @to_buffer: transfer direction (true == from an sg list to a
+ * buffer, false == from a buffer to an sg list
*
* Returns the number of copied bytes.
*
**/
static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents,
- void *buf, size_t buflen, int to_buffer)
+ void *buf, size_t buflen, off_t skip,
+ bool to_buffer)
{
unsigned int offset = 0;
struct sg_mapping_iter miter;
@@ -582,6 +621,9 @@ static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents,
sg_miter_start(&miter, sgl, nents, sg_flags);
+ if (!sg_miter_skip(&miter, skip))
+ return false;
+
local_irq_save(flags);
while (sg_miter_next(&miter) && offset < buflen) {
@@ -616,7 +658,7 @@ static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents,
size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,
void *buf, size_t buflen)
{
- return sg_copy_buffer(sgl, nents, buf, buflen, 0);
+ return sg_copy_buffer(sgl, nents, buf, buflen, 0, false);
}
EXPORT_SYMBOL(sg_copy_from_buffer);
@@ -633,6 +675,42 @@ EXPORT_SYMBOL(sg_copy_from_buffer);
size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
void *buf, size_t buflen)
{
- return sg_copy_buffer(sgl, nents, buf, buflen, 1);
+ return sg_copy_buffer(sgl, nents, buf, buflen, 0, true);
}
EXPORT_SYMBOL(sg_copy_to_buffer);
+
+/**
+ * sg_pcopy_from_buffer - Copy from a linear buffer to an SG list
+ * @sgl: The SG list
+ * @nents: Number of SG entries
+ * @buf: Where to copy from
+ * @skip: Number of bytes to skip before copying
+ * @buflen: The number of bytes to copy
+ *
+ * Returns the number of copied bytes.
+ *
+ **/
+size_t sg_pcopy_from_buffer(struct scatterlist *sgl, unsigned int nents,
+ void *buf, size_t buflen, off_t skip)
+{
+ return sg_copy_buffer(sgl, nents, buf, buflen, skip, false);
+}
+EXPORT_SYMBOL(sg_pcopy_from_buffer);
+
+/**
+ * sg_pcopy_to_buffer - Copy from an SG list to a linear buffer
+ * @sgl: The SG list
+ * @nents: Number of SG entries
+ * @buf: Where to copy to
+ * @skip: Number of bytes to skip before copying
+ * @buflen: The number of bytes to copy
+ *
+ * Returns the number of copied bytes.
+ *
+ **/
+size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents,
+ void *buf, size_t buflen, off_t skip)
+{
+ return sg_copy_buffer(sgl, nents, buf, buflen, skip, true);
+}
+EXPORT_SYMBOL(sg_pcopy_to_buffer);
--
1.8.1.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v3 2/4] lib/scatterlist: introduce sg_pcopy_from_buffer() and sg_pcopy_to_buffer()
2013-06-23 12:37 ` [PATCH v3 2/4] lib/scatterlist: introduce sg_pcopy_from_buffer() and sg_pcopy_to_buffer() Akinobu Mita
@ 2013-06-24 23:27 ` Tejun Heo
0 siblings, 0 replies; 7+ messages in thread
From: Tejun Heo @ 2013-06-24 23:27 UTC (permalink / raw)
To: Akinobu Mita
Cc: linux-kernel, akpm, Imre Deak, Herbert Xu, David S. Miller,
linux-crypto, James E.J. Bottomley, Douglas Gilbert, linux-scsi
On Sun, Jun 23, 2013 at 09:37:39PM +0900, Akinobu Mita wrote:
> The only difference between sg_pcopy_{from,to}_buffer() and
> sg_copy_{from,to}_buffer() is an additional argument that specifies
> the number of bytes to skip the SG list before copying.
>
> Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
> Cc: Tejun Heo <tj@kernel.org>
> Cc: Imre Deak <imre.deak@intel.com>
> Cc: Herbert Xu <herbert@gondor.apana.org.au>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: linux-crypto@vger.kernel.org
> Cc: "James E.J. Bottomley" <JBottomley@parallels.com>
> Cc: Douglas Gilbert <dgilbert@interlog.com>
> Cc: linux-scsi@vger.kernel.org
Acked-by: Tejun Heo <tj@kernel.org>
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 3/4] crypto: talitos: use sg_pcopy_to_buffer()
2013-06-23 12:37 [PATCH v3 0/4] introduce sg_pcopy_from_buffer() and sg_pcopy_to_buffer() Akinobu Mita
2013-06-23 12:37 ` [PATCH v3 1/4] lib/scatterlist: factor out sg_miter_get_next_page() from sg_miter_next() Akinobu Mita
2013-06-23 12:37 ` [PATCH v3 2/4] lib/scatterlist: introduce sg_pcopy_from_buffer() and sg_pcopy_to_buffer() Akinobu Mita
@ 2013-06-23 12:37 ` Akinobu Mita
2013-06-23 12:37 ` [PATCH v3 4/4] scsi_debug: fix do_device_access() with wrap around range Akinobu Mita
3 siblings, 0 replies; 7+ messages in thread
From: Akinobu Mita @ 2013-06-23 12:37 UTC (permalink / raw)
To: linux-kernel, akpm
Cc: Akinobu Mita, Herbert Xu, Horia Geanta, David S. Miller, linux-crypto
Use sg_pcopy_to_buffer() which is better than the function previously used.
Because it doesn't do kmap/kunmap for skipped pages.
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Horia Geanta <horia.geanta@freescale.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: linux-crypto@vger.kernel.org
---
* No change from v2
drivers/crypto/talitos.c | 60 +-----------------------------------------------
1 file changed, 1 insertion(+), 59 deletions(-)
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 5b2b5e6..661dc3e 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -1112,64 +1112,6 @@ static int sg_count(struct scatterlist *sg_list, int nbytes, bool *chained)
return sg_nents;
}
-/**
- * sg_copy_end_to_buffer - Copy end data from SG list to a linear buffer
- * @sgl: The SG list
- * @nents: Number of SG entries
- * @buf: Where to copy to
- * @buflen: The number of bytes to copy
- * @skip: The number of bytes to skip before copying.
- * Note: skip + buflen should equal SG total size.
- *
- * Returns the number of copied bytes.
- *
- **/
-static size_t sg_copy_end_to_buffer(struct scatterlist *sgl, unsigned int nents,
- void *buf, size_t buflen, unsigned int skip)
-{
- unsigned int offset = 0;
- unsigned int boffset = 0;
- struct sg_mapping_iter miter;
- unsigned long flags;
- unsigned int sg_flags = SG_MITER_ATOMIC;
- size_t total_buffer = buflen + skip;
-
- sg_flags |= SG_MITER_FROM_SG;
-
- sg_miter_start(&miter, sgl, nents, sg_flags);
-
- local_irq_save(flags);
-
- while (sg_miter_next(&miter) && offset < total_buffer) {
- unsigned int len;
- unsigned int ignore;
-
- if ((offset + miter.length) > skip) {
- if (offset < skip) {
- /* Copy part of this segment */
- ignore = skip - offset;
- len = miter.length - ignore;
- if (boffset + len > buflen)
- len = buflen - boffset;
- memcpy(buf + boffset, miter.addr + ignore, len);
- } else {
- /* Copy all of this segment (up to buflen) */
- len = miter.length;
- if (boffset + len > buflen)
- len = buflen - boffset;
- memcpy(buf + boffset, miter.addr, len);
- }
- boffset += len;
- }
- offset += miter.length;
- }
-
- sg_miter_stop(&miter);
-
- local_irq_restore(flags);
- return boffset;
-}
-
/*
* allocate and map the extended descriptor
*/
@@ -1800,7 +1742,7 @@ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
if (to_hash_later) {
int nents = sg_count(areq->src, nbytes, &chained);
- sg_copy_end_to_buffer(areq->src, nents,
+ sg_pcopy_to_buffer(areq->src, nents,
req_ctx->bufnext,
to_hash_later,
nbytes - to_hash_later);
--
1.8.1.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v3 4/4] scsi_debug: fix do_device_access() with wrap around range
2013-06-23 12:37 [PATCH v3 0/4] introduce sg_pcopy_from_buffer() and sg_pcopy_to_buffer() Akinobu Mita
` (2 preceding siblings ...)
2013-06-23 12:37 ` [PATCH v3 3/4] crypto: talitos: use sg_pcopy_to_buffer() Akinobu Mita
@ 2013-06-23 12:37 ` Akinobu Mita
2013-06-24 23:34 ` Douglas Gilbert
3 siblings, 1 reply; 7+ messages in thread
From: Akinobu Mita @ 2013-06-23 12:37 UTC (permalink / raw)
To: linux-kernel, akpm
Cc: Akinobu Mita, James E.J. Bottomley, Douglas Gilbert, linux-scsi
do_device_access() is a function that abstracts copying SG list from/to
ramdisk storage (fake_storep).
It must deal with the ranges exceeding actual fake_storep size, because
such ranges are valid if virtual_gb is set greater than zero, and they
should be treated as fake_storep is repeatedly mirrored up to virtual size.
Unfortunately, it can't deal with the range which wraps around the end of
fake_storep. A wrap around range is copied by two sg_copy_{from,to}_buffer()
calls, but sg_copy_{from,to}_buffer() can't copy from/to in the middle of
SG list, therefore the second call can't copy correctly.
This fixes it by using sg_pcopy_{from,to}_buffer() that can copy from/to
the middle of SG list.
This also simplifies the assignment of sdb->resid in fill_from_dev_buffer().
Because fill_from_dev_buffer() is now only called once per command
execution cycle. So it is not necessary to take care to decrease
sdb->resid if fill_from_dev_buffer() is called more than once.
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Cc: "James E.J. Bottomley" <JBottomley@parallels.com>
Cc: Douglas Gilbert <dgilbert@interlog.com>
Cc: linux-scsi@vger.kernel.org
---
* No change from v2
drivers/scsi/scsi_debug.c | 48 ++++++++++++++++++++++++++++++++++++-----------
1 file changed, 37 insertions(+), 11 deletions(-)
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 21239b3..1b15f98 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -417,10 +417,7 @@ static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents,
arr, arr_len);
- if (sdb->resid)
- sdb->resid -= act_len;
- else
- sdb->resid = scsi_bufflen(scp) - act_len;
+ sdb->resid = scsi_bufflen(scp) - act_len;
return 0;
}
@@ -1614,24 +1611,48 @@ static int check_device_access_params(struct sdebug_dev_info *devi,
return 0;
}
+/* Returns number of bytes copied or -1 if error. */
static int do_device_access(struct scsi_cmnd *scmd,
struct sdebug_dev_info *devi,
unsigned long long lba, unsigned int num, int write)
{
int ret;
unsigned long long block, rest = 0;
- int (*func)(struct scsi_cmnd *, unsigned char *, int);
+ struct scsi_data_buffer *sdb;
+ enum dma_data_direction dir;
+ size_t (*func)(struct scatterlist *, unsigned int, void *, size_t,
+ off_t);
+
+ if (write) {
+ sdb = scsi_out(scmd);
+ dir = DMA_TO_DEVICE;
+ func = sg_pcopy_to_buffer;
+ } else {
+ sdb = scsi_in(scmd);
+ dir = DMA_FROM_DEVICE;
+ func = sg_pcopy_from_buffer;
+ }
- func = write ? fetch_to_dev_buffer : fill_from_dev_buffer;
+ if (!sdb->length)
+ return 0;
+ if (!(scsi_bidi_cmnd(scmd) || scmd->sc_data_direction == dir))
+ return -1;
block = do_div(lba, sdebug_store_sectors);
if (block + num > sdebug_store_sectors)
rest = block + num - sdebug_store_sectors;
- ret = func(scmd, fake_storep + (block * scsi_debug_sector_size),
- (num - rest) * scsi_debug_sector_size);
- if (!ret && rest)
- ret = func(scmd, fake_storep, rest * scsi_debug_sector_size);
+ ret = func(sdb->table.sgl, sdb->table.nents,
+ fake_storep + (block * scsi_debug_sector_size),
+ (num - rest) * scsi_debug_sector_size, 0);
+ if (ret != (num - rest) * scsi_debug_sector_size)
+ return ret;
+
+ if (rest) {
+ ret += func(sdb->table.sgl, sdb->table.nents,
+ fake_storep, rest * scsi_debug_sector_size,
+ (num - rest) * scsi_debug_sector_size);
+ }
return ret;
}
@@ -1888,7 +1909,12 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
read_lock_irqsave(&atomic_rw, iflags);
ret = do_device_access(SCpnt, devip, lba, num, 0);
read_unlock_irqrestore(&atomic_rw, iflags);
- return ret;
+ if (ret == -1)
+ return DID_ERROR << 16;
+
+ scsi_in(SCpnt)->resid = scsi_bufflen(SCpnt) - ret;
+
+ return 0;
}
static void dump_sector(unsigned char *buf, int len)
--
1.8.1.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v3 4/4] scsi_debug: fix do_device_access() with wrap around range
2013-06-23 12:37 ` [PATCH v3 4/4] scsi_debug: fix do_device_access() with wrap around range Akinobu Mita
@ 2013-06-24 23:34 ` Douglas Gilbert
0 siblings, 0 replies; 7+ messages in thread
From: Douglas Gilbert @ 2013-06-24 23:34 UTC (permalink / raw)
To: Akinobu Mita; +Cc: linux-kernel, akpm, James E.J. Bottomley, linux-scsi
On 13-06-23 02:37 PM, Akinobu Mita wrote:
> do_device_access() is a function that abstracts copying SG list from/to
> ramdisk storage (fake_storep).
>
> It must deal with the ranges exceeding actual fake_storep size, because
> such ranges are valid if virtual_gb is set greater than zero, and they
> should be treated as fake_storep is repeatedly mirrored up to virtual size.
>
> Unfortunately, it can't deal with the range which wraps around the end of
> fake_storep. A wrap around range is copied by two sg_copy_{from,to}_buffer()
> calls, but sg_copy_{from,to}_buffer() can't copy from/to in the middle of
> SG list, therefore the second call can't copy correctly.
>
> This fixes it by using sg_pcopy_{from,to}_buffer() that can copy from/to
> the middle of SG list.
>
> This also simplifies the assignment of sdb->resid in fill_from_dev_buffer().
> Because fill_from_dev_buffer() is now only called once per command
> execution cycle. So it is not necessary to take care to decrease
> sdb->resid if fill_from_dev_buffer() is called more than once.
>
> Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
> Cc: "James E.J. Bottomley" <JBottomley@parallels.com>
> Cc: Douglas Gilbert <dgilbert@interlog.com>
> Cc: linux-scsi@vger.kernel.org
> ---
>
> * No change from v2
Acked-by: Douglas Gilbert <dgilbert@interlog.com>
^ permalink raw reply [flat|nested] 7+ messages in thread