RE: Possible bug in scsi_lib.c:scsi_req_map_sg()

2007-03-02 Thread Dachepalli, Sudhir
Hello All,

I am noticing the following panic on SLES 10 ( as well as Redhat 5 ).
I modified "scsi_lib.c" to print some debugging information.
Our driver is a Multipath failover module and we are using
"scsi_execute_async" API for routing IO's.
In earlier kernels we used "scsi_do_req" API.


Messages

Mar  1 20:20:35 linux kernel:  mppLnx_do_queuecommand :: cs 10, bufflen
110592 use_sg 27
Mar  1 20:20:35 linux kernel:  mppLnx_do_queuecommand :: cs 10, bufflen
4096 use_sg 1
Mar  1 20:20:35 linux kernel:  mppLnx_do_queuecommand :: cs 10, bufflen
4096 use_sg 1
Mar  1 20:20:35 linux kernel:  mppLnx_do_queuecommand :: cs 10, bufflen
4096 use_sg 1
Mar  1 20:20:35 linux kernel:  mppLnx_do_queuecommand :: cs 10, bufflen
4096 use_sg 1
Mar  1 20:20:35 linux kernel:  mppLnx_do_queuecommand :: cs 10, bufflen
7168 use_sg 7
Mar  1 20:20:35 linux kernel:  scsi_req_map_sg:: calling bio_put
Mar  1 20:20:35 linux kernel:
scsi_req_map_sg::i=2,len=1024,data_len=3072,off=2048,PAGE_SIZE=4096,byte
s=1024,nr_vecs=0, nr_pages=0
Mar  1 20:20:35 linux kernel: scsi_req_map_sg:: bio->bi_io_vec is NULL
Mar  1 20:20:35 linux kernel: Unable to handle kernel paging request at
82bcfe3c0030 RIP:
Mar  1 20:20:35 linux kernel: {kmem_cache_free+86}
Mar  1 20:20:35 linux kernel: PGD 0
Mar  1 20:20:35 linux kernel: Oops:  [1] SMP
Mar  1 20:20:35 linux kernel: last sysfs file:
/class/mppUpper/mppUpper/dev
Mar  1 20:20:35 linux kernel: CPU 0
Mar  1 20:20:35 linux kernel: Modules linked in: ipv6 af_packet button
battery ac apparmor aamatch_pcre loop dm_mod shpchp pci_hotplug
hw_random ide_cd ehci_hcd uhci_hcd cdrom usbcore e1000 i8xx_tco
parport_pc lp parport ext3 jbd mppVhba edd fan thermal processor mptfc
aacraid lpfc qla2xxx firmware_class scsi_transport_fc mptspi mptscsih
mptbase scsi_transport_spi ata_piix libata piix mppUpper sg sd_mod
scsi_mod ide_disk ide_core
Mar  1 20:20:35 linux kernel: Pid: 1085, comm: mpp_dcr Tainted: G U
2.6.16.16-1.6-smp #1
Mar  1 20:20:35 linux kernel: RIP: 0010:[]
{kmem_cache_free+86}
Mar  1 20:20:35 linux kernel: RSP: 0018:81007c2fdd88  EFLAGS:
00010086
Mar  1 20:20:35 linux kernel: RAX: 82bcfe3c RBX:
810037fbd000 RCX: 003f
Mar  1 20:20:35 linux kernel: RDX: 8100c000 RSI:
 RDI: 0007f000
Mar  1 20:20:35 linux kernel: RBP: 810037fdf640 R08:
803d2240 R09: 81007c2fdb78
Mar  1 20:20:35 linux kernel: R10: 0001 R11:
8015a4e0 R12: 81007da72880
Mar  1 20:20:35 linux kernel: R13: 0296 R14:
0800 R15: 
Mar  1 20:20:35 linux kernel: FS:  2b7d68de36d0()
GS:80444000() knlGS:
Mar  1 20:20:35 linux kernel: CS:  0010 DS:  ES:  CR0:
8005003b
Mar  1 20:20:35 linux kernel: CR2: 82bcfe3c0030 CR3:
67dc6000 CR4: 06e0
Mar  1 20:20:35 linux kernel: Process mpp_dcr (pid: 1085, threadinfo
81007c2fc000, task 81007c9bd850)
Mar  1 20:20:35 linux kernel: Stack: 81007c69f328 0400
 810063368d00
Mar  1 20:20:35 linux kernel:810037fdf640 0400
810063368d00 8017ef77
Mar  1 20:20:35 linux kernel:0400 810054239188
Mar  1 20:20:35 linux kernel: Call Trace:
{bio_free+51}
{:scsi_mod:scsi_execute_async+480}
Mar  1 20:20:35 linux kernel:
{:mppVhba:mppLnx_do_queuecommand+2577}
Mar  1 20:20:35 linux kernel:
{:mppVhba:mppLnx_scsi_done+0}
{:mppVhba:mppLnx_dpc_handler+531}
Mar  1 20:20:35 linux kernel:{child_rip+8}
{:mppVhba:mppLnx_dpc_handler+0}
Mar  1 20:20:35 linux kernel:{child_rip+0}
Mar  1 20:20:35 linux kernel:
Mar  1 20:20:35 linux kernel: Code: 48 8b 48 30 0f b7 51 28 65 8b 04 25
30 00 00 00 39 c2 0f 84
Mar  1 20:20:35 linux kernel: RIP {kmem_cache_free+86}
RSP 
Mar  1 20:20:35 linux kernel: CR2: 82bcfe3c0030
 




Scsi_lib.c ( scsi_req_map_sg )
--

static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl,
int nsegs, unsigned bufflen, gfp_t gfp)
{
struct request_queue *q = rq->q;
int nr_pages = (bufflen + sgl[0].offset + PAGE_SIZE - 1) >>
PAGE_SHIFT;
unsigned int data_len = 0, len, bytes, off;
struct page *page;
struct bio *bio = NULL;
int i, err, nr_vecs = 0;

for (i = 0; i < nsegs; i++) {
page = sgl[i].page;
off = sgl[i].offset;
len = sgl[i].length;
data_len += len;

while (len > 0) {
bytes = min_t(unsigned int, len, PAGE_SIZE -
off);

if (!bio) {
nr_vecs = min_t(int, BIO_MAX_PAGES,
nr_pages);
nr_pages -= nr_vecs;

bio = bio_alloc(gfp, nr_vecs);
if (!bio) {
err = -ENOMEM;
 

Re: Possible bug in scsi_lib.c:scsi_req_map_sg()

2007-03-02 Thread Mike Christie
Dachepalli, Sudhir wrote:
> scsi_req_map_sg::i=2,len=1024,data_len=3072,off=2048,PAGE_SIZE=4096,byte
> s=1024,nr_vecs=0, nr_pages=0


> if (bio_add_pc_page(q, bio, page, bytes, off) !=
> bytes) {
> printk("scsi_req_map_sg:: calling
> bio_put \n");
>  
> printk("scsi_req_map_sg::i=%d,len=%d,data_len=%d,off=%d,PAGE_SIZE=%ld,by
> tes=%d,nr_vecs=%d, nr_pages=%d\n",
>  
> i,len,data_len,off,PAGE_SIZE,bytes,nr_vecs,nr_pages);
> if( bio->bi_io_vec == NULL )


I think Boaz's first patch in this thread that counts the offsets
correctly should be merged.

I am not sure about the second one. If allocating a bio with zero vecs
is valid, then I guess the patch should be merged. bio_alloc_bioset
looks like it allows this, but people probably never do it (just when
they hit bugs like this one :)). But I think if we are counting segments
correctly we will not need that patch for this problem will we Boaz?
Boaz, maybe you could also send the first patch in a seperate mail so
that it can be merged (I do not think James wants to cut and paste two
patches from one mail).

Also, you do not want to use scsi_execute_async. I am trying to kill it.
The original patches, never had that function and the later patches had
a warning that you should not use it and that you should just use the
request and the blk_rq* helpers directly.
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Possible bug in scsi_lib.c:scsi_req_map_sg()

2007-03-02 Thread Mike Christie
Mike Christie wrote:
> Dachepalli, Sudhir wrote:
>> scsi_req_map_sg::i=2,len=1024,data_len=3072,off=2048,PAGE_SIZE=4096,byte
>> s=1024,nr_vecs=0, nr_pages=0
> 
> 
>> if (bio_add_pc_page(q, bio, page, bytes, off) !=
>> bytes) {
>> printk("scsi_req_map_sg:: calling
>> bio_put \n");
>>  
>> printk("scsi_req_map_sg::i=%d,len=%d,data_len=%d,off=%d,PAGE_SIZE=%ld,by
>> tes=%d,nr_vecs=%d, nr_pages=%d\n",
>>  
>> i,len,data_len,off,PAGE_SIZE,bytes,nr_vecs,nr_pages);
>> if( bio->bi_io_vec == NULL )
> 
> 
> I think Boaz's first patch in this thread that counts the offsets
> correctly should be merged.

Just one clarification.

When I wrote scsi_execute_async, it was meant as a temp hack so we would
kill scsi_request and fix scatterlists for drivers like iscsi_tcp and
ib_iser, but in the original patches and the patches I am sending now I
modify the blk helpers and have sg use them directly.

scsi_execute_async was meant to be temporary only supported what sg and
st and other mainline drivers were sending at the time, so it did not
support something like:

sg[0].offset 0;
sg[0].length = 4096;
sg[1].offset = 1024;
sg[1].offset = 3072;

because sg and st can only have a offset for the first sg element
(offsets for the sg element is supported).

If we are going to support whatever scsi_do_req supported the we should
merge Boaz's patch.

If scsi_execute_async is going to be limited to what is in mainline
until I can kill it, then we may not want to merge Boaz's patch and just
have people convert the code to use blk_get_request, blk_rq_map_kern or
blk_rq_map_user and blk_execute_rq_nowait.
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] iscsi tcp set queue dma alignment to zero

2007-03-02 Thread Mike Christie
Pete Wyckoff wrote:
> Add a slave_configure function to iSCSI TCP to remove any DMA
> alignment restriction.  This permits the use of direct IO from
> arbitrary addresses.
> 
> Signed-off-by: Pete Wyckoff <[EMAIL PROTECTED]>
> ---
>  drivers/scsi/iscsi_tcp.c |   11 +++
>  1 files changed, 11 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
> index 4376840..f48eedd 100644
> --- a/drivers/scsi/iscsi_tcp.c
> +++ b/drivers/scsi/iscsi_tcp.c
> @@ -2132,6 +2132,16 @@ static void iscsi_tcp_session_destroy(struct 
> iscsi_cls_session *cls_session)
>   iscsi_session_teardown(cls_session);
>  }
>  
> +/*
> + * New device attached.  Turn off the DMA alignment restriction on
> + * the request queue.
> + */
> +static int iscsi_tcp_slave_configure(struct scsi_device *sdev)
> +{
> + blk_queue_dma_alignment(sdev->request_queue, 0);
> + return 0;
> +}
> +

I think the comments are not needed, but that is not a big deal. I will
put this in my tree and send it to James if he does not pick it up from
linux-scsi.

Thanks for the patch.

Erez, I do not think ib_iser should have any limit either (I only looked
at the code for a little bit though). You may want to do the the same
for iser.
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: Possible bug in scsi_lib.c:scsi_req_map_sg()

2007-03-02 Thread Dachepalli, Sudhir
Mike,

I applied "patch 1" posted by Boaz Harrosh to my SLES 10 kernel.
So far IO's are running for 45 minutes which is the longest in my
numerous re-tries.


We were not aware that "scsi_execute_async" was temperory workaround.

Where is the depricated warning that you mentioned about ?
I tried to look in scsi_lib.c and scsi_device.h


Regards,
Sudhir 

-Original Message-
From: Mike Christie [mailto:[EMAIL PROTECTED] 
Sent: Friday, March 02, 2007 4:00 PM
To: Dachepalli, Sudhir
Cc: Benny Halevy; Jens Axboe; Boaz Harrosh; linux-scsi@vger.kernel.org;
James Bottomley
Subject: Re: Possible bug in scsi_lib.c:scsi_req_map_sg()

Mike Christie wrote:
> Dachepalli, Sudhir wrote:
>> scsi_req_map_sg::i=2,len=1024,data_len=3072,off=2048,PAGE_SIZE=4096,b
>> yte
>> s=1024,nr_vecs=0, nr_pages=0
> 
> 
>> if (bio_add_pc_page(q, bio, page, bytes, off)
!=
>> bytes) {
>> printk("scsi_req_map_sg:: calling 
>> bio_put \n");
>>  
>> printk("scsi_req_map_sg::i=%d,len=%d,data_len=%d,off=%d,PAGE_SIZE=%ld
>> ,by
>> tes=%d,nr_vecs=%d, nr_pages=%d\n",
>>  
>> i,len,data_len,off,PAGE_SIZE,bytes,nr_vecs,nr_pages);
>> if( bio->bi_io_vec == NULL )
> 
> 
> I think Boaz's first patch in this thread that counts the offsets 
> correctly should be merged.

Just one clarification.

When I wrote scsi_execute_async, it was meant as a temp hack so we would
kill scsi_request and fix scatterlists for drivers like iscsi_tcp and
ib_iser, but in the original patches and the patches I am sending now I
modify the blk helpers and have sg use them directly.

scsi_execute_async was meant to be temporary only supported what sg and
st and other mainline drivers were sending at the time, so it did not
support something like:

sg[0].offset 0;
sg[0].length = 4096;
sg[1].offset = 1024;
sg[1].offset = 3072;

because sg and st can only have a offset for the first sg element
(offsets for the sg element is supported).

If we are going to support whatever scsi_do_req supported the we should
merge Boaz's patch.

If scsi_execute_async is going to be limited to what is in mainline
until I can kill it, then we may not want to merge Boaz's patch and just
have people convert the code to use blk_get_request, blk_rq_map_kern or
blk_rq_map_user and blk_execute_rq_nowait.
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/3] tgt fixes

2007-03-02 Thread FUJITA Tomonori
This patchset fixes sense buffer handling bugs and scsi command leak
with cleanups to remove bio hacks.

The patchset are made over scsi-rc-fixes tree.
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/3] tgt: rm bio hacks in scsi tgt

2007-03-02 Thread FUJITA Tomonori
From: Mike Christie <[EMAIL PROTECTED]>

scsi tgt breaks up a command into multple scatterlists
if we cannot fit all the data in one. This was because
the block rq helpers did not support large requests and
because we can get a command of any old size so it is
hard to preallocate pages for scatterlist large enough
(we cannot really preallocate pages with the bio map
user path). In 2.6.20, we added large request support to
the block layer helper, blk_rq_map_user. And at LSF,
we talked about increasing SCSI_MAX_PHYS_SEGMENTS for
scsi tgt if we want to support really really :) large
(greater than 256 * PAGE_SIZE in the worst mapping case)
requests.

The only target currently implemented does not even support
the multiple scatterlists stuff and only supports smaller
requests, so this patch just coverts scsi tgt to use
blk_rq_map_user.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
Signed-off-by: FUJITA Tomonori <[EMAIL PROTECTED]>
---
 drivers/scsi/scsi_tgt_lib.c |  133 +++
 include/scsi/scsi_cmnd.h|3 -
 2 files changed, 34 insertions(+), 102 deletions(-)

diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
index d402aff..47c29a9 100644
--- a/drivers/scsi/scsi_tgt_lib.c
+++ b/drivers/scsi/scsi_tgt_lib.c
@@ -28,7 +28,6 @@ #include 
 #include 
 #include 
 #include 
-#include <../drivers/md/dm-bio-list.h>
 
 #include "scsi_tgt_priv.h"
 
@@ -42,9 +41,8 @@ static struct kmem_cache *scsi_tgt_cmd_c
 struct scsi_tgt_cmd {
/* TODO replace work with James b's code */
struct work_struct work;
-   /* TODO replace the lists with a large bio */
-   struct bio_list xfer_done_list;
-   struct bio_list xfer_list;
+   /* TODO fix limits of some drivers */
+   struct bio *bio;
 
struct list_head hash_list;
struct request *rq;
@@ -93,7 +91,12 @@ struct scsi_cmnd *scsi_host_get_command(
if (!tcmd)
goto put_dev;
 
-   rq = blk_get_request(shost->uspace_req_q, write, gfp_mask);
+   /*
+* The blk helpers are used to the READ/WRITE requests
+* transfering data from a initiator point of view. Since
+* we are in target mode we want the opposite.
+*/
+   rq = blk_get_request(shost->uspace_req_q, !write, gfp_mask);
if (!rq)
goto free_tcmd;
 
@@ -111,8 +114,6 @@ struct scsi_cmnd *scsi_host_get_command(
rq->cmd_flags |= REQ_TYPE_BLOCK_PC;
rq->end_io_data = tcmd;
 
-   bio_list_init(&tcmd->xfer_list);
-   bio_list_init(&tcmd->xfer_done_list);
tcmd->rq = rq;
 
return cmd;
@@ -157,22 +158,6 @@ void scsi_host_put_command(struct Scsi_H
 }
 EXPORT_SYMBOL_GPL(scsi_host_put_command);
 
-static void scsi_unmap_user_pages(struct scsi_tgt_cmd *tcmd)
-{
-   struct bio *bio;
-
-   /* must call bio_endio in case bio was bounced */
-   while ((bio = bio_list_pop(&tcmd->xfer_done_list))) {
-   bio_endio(bio, bio->bi_size, 0);
-   bio_unmap_user(bio);
-   }
-
-   while ((bio = bio_list_pop(&tcmd->xfer_list))) {
-   bio_endio(bio, bio->bi_size, 0);
-   bio_unmap_user(bio);
-   }
-}
-
 static void cmd_hashlist_del(struct scsi_cmnd *cmd)
 {
struct request_queue *q = cmd->request->q;
@@ -185,6 +170,11 @@ static void cmd_hashlist_del(struct scsi
spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags);
 }
 
+static void scsi_unmap_user_pages(struct scsi_tgt_cmd *tcmd)
+{
+   blk_rq_unmap_user(tcmd->bio);
+}
+
 static void scsi_tgt_cmd_destroy(struct work_struct *work)
 {
struct scsi_tgt_cmd *tcmd =
@@ -193,16 +183,6 @@ static void scsi_tgt_cmd_destroy(struct
 
dprintk("cmd %p %d %lu\n", cmd, cmd->sc_data_direction,
rq_data_dir(cmd->request));
-   /*
-* We fix rq->cmd_flags here since when we told bio_map_user
-* to write vm for WRITE commands, blk_rq_bio_prep set
-* rq_data_dir the flags to READ.
-*/
-   if (cmd->sc_data_direction == DMA_TO_DEVICE)
-   cmd->request->cmd_flags |= REQ_RW;
-   else
-   cmd->request->cmd_flags &= ~REQ_RW;
-
scsi_unmap_user_pages(tcmd);
scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd);
 }
@@ -215,6 +195,7 @@ static void init_scsi_tgt_cmd(struct req
struct list_head *head;
 
tcmd->tag = tag;
+   tcmd->bio = NULL;
INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy);
spin_lock_irqsave(&qdata->cmd_hash_lock, flags);
head = &qdata->cmd_hash[cmd_hashfn(tag)];
@@ -419,52 +400,33 @@ static int scsi_map_user_pages(struct sc
struct request *rq = cmd->request;
void *uaddr = tcmd->buffer;
unsigned int len = tcmd->bufflen;
-   struct bio *bio;
int err;
 
-   while (len > 0) {
-   dprintk("%lx %u\n", (unsigned long) uaddr, len);
-   bio = bio_map_user(q, NULL, (unsigned long) uaddr, len, rw);
-

[PATCH 3/3] tgt: fix scsi command leak

2007-03-02 Thread FUJITA Tomonori
The failure to map user-space pages leads to scsi command leak. It can
happens mostly because of user-space daemon bugs (or OOM). This patch
makes tgt just notify a LLD of the failure with sense when
blk_rq_map_user() fails.

Signed-off-by: FUJITA Tomonori <[EMAIL PROTECTED]>
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/scsi_tgt_lib.c |   23 ---
 1 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
index dc8781a..c05dff9 100644
--- a/drivers/scsi/scsi_tgt_lib.c
+++ b/drivers/scsi/scsi_tgt_lib.c
@@ -459,6 +459,16 @@ static struct request *tgt_cmd_hash_look
return rq;
 }
 
+static void scsi_tgt_build_sense(unsigned char *sense_buffer, unsigned char 
key,
+unsigned char asc, unsigned char asq)
+{
+   sense_buffer[0] = 0x70;
+   sense_buffer[2] = key;
+   sense_buffer[7] = 0xa;
+   sense_buffer[12] = asc;
+   sense_buffer[13] = asq;
+}
+
 int scsi_tgt_kspace_exec(int host_no, int result, u64 tag,
 unsigned long uaddr, u32 len, unsigned long 
sense_uaddr,
 u32 sense_len, u8 rw)
@@ -514,9 +524,16 @@ int scsi_tgt_kspace_exec(int host_no, in
if (len) {
err = scsi_map_user_pages(rq->end_io_data, cmd, uaddr, len, rw);
if (err) {
-   eprintk("%p %d\n", cmd, err);
-   err = -EAGAIN;
-   goto done;
+   /*
+* user-space daemon bugs or OOM
+* TODO: we can do better for OOM.
+*/
+   eprintk("cmd %p ret %d uaddr %lx len %d rw %d\n",
+   cmd, err, uaddr, len, rw);
+   cmd->result = SAM_STAT_CHECK_CONDITION;
+   memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+   scsi_tgt_build_sense(cmd->sense_buffer,
+HARDWARE_ERROR, 0, 0);
}
}
err = scsi_tgt_transfer_response(cmd);
-- 
1.4.3.2

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/3] tgt: fix sesnse buffer problems

2007-03-02 Thread FUJITA Tomonori
This patch simplify the way to notify LLDs of the command completion
and addresses the following sense buffer problems:

- can't handle both data and sense.
- forces user-space to use aligned sense buffer

tgt copies sense_data from userspace to cmnd->sense_buffer (if
necessary), maps user-space pages (if necessary) and then calls
host->transfer_response (host->transfer_data is removed).

Signed-off-by: FUJITA Tomonori <[EMAIL PROTECTED]>
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/ibmvscsi/ibmvstgt.c |   21 ++-
 drivers/scsi/scsi_tgt_if.c   |6 +-
 drivers/scsi/scsi_tgt_lib.c  |  120 +++--
 drivers/scsi/scsi_tgt_priv.h |5 +-
 include/scsi/scsi_host.h |   19 ++-
 include/scsi/scsi_tgt_if.h   |6 +-
 6 files changed, 44 insertions(+), 133 deletions(-)

diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c
index e28260f..07e5cbe 100644
--- a/drivers/scsi/ibmvscsi/ibmvstgt.c
+++ b/drivers/scsi/ibmvscsi/ibmvstgt.c
@@ -273,23 +273,9 @@ static int ibmvstgt_rdma(struct scsi_cmn
rest -= mlen;
}
 out:
-
return 0;
 }
 
-static int ibmvstgt_transfer_data(struct scsi_cmnd *sc,
- void (*done)(struct scsi_cmnd *))
-{
-   struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
-   int err;
-
-   err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1);
-
-   done(sc);
-
-   return err;
-}
-
 static int ibmvstgt_cmd_done(struct scsi_cmnd *sc,
 void (*done)(struct scsi_cmnd *))
 {
@@ -297,7 +283,11 @@ static int ibmvstgt_cmd_done(struct scsi
struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
struct srp_target *target = iue->target;
 
-   dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]);
+   dprintk("%p %p %x %u\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0],
+   cmd->usg_sg);
+
+   if (sc->use_sg)
+   srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 
1);
 
spin_lock_irqsave(&target->lock, flags);
list_del(&iue->ilist);
@@ -794,7 +784,6 @@ static struct scsi_host_template ibmvstg
.use_clustering = DISABLE_CLUSTERING,
.max_sectors= DEFAULT_MAX_SECTORS,
.transfer_response  = ibmvstgt_cmd_done,
-   .transfer_data  = ibmvstgt_transfer_data,
.eh_abort_handler   = ibmvstgt_eh_abort_handler,
.tsk_mgmt_response  = ibmvstgt_tsk_mgmt_response,
.shost_attrs= ibmvstgt_attrs,
diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c
index f5d4412..7e18310 100644
--- a/drivers/scsi/scsi_tgt_if.c
+++ b/drivers/scsi/scsi_tgt_if.c
@@ -179,10 +179,12 @@ static int event_recv_msg(struct tgt_eve
switch (ev->hdr.type) {
case TGT_UEVENT_CMD_RSP:
err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no,
-  ev->p.cmd_rsp.tag,
   ev->p.cmd_rsp.result,
-  ev->p.cmd_rsp.len,
+  ev->p.cmd_rsp.tag,
   ev->p.cmd_rsp.uaddr,
+  ev->p.cmd_rsp.len,
+  ev->p.cmd_rsp.sense_uaddr,
+  ev->p.cmd_rsp.sense_len,
   ev->p.cmd_rsp.rw);
break;
case TGT_UEVENT_TSK_MGMT_RSP:
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
index 47c29a9..dc8781a 100644
--- a/drivers/scsi/scsi_tgt_lib.c
+++ b/drivers/scsi/scsi_tgt_lib.c
@@ -47,9 +47,6 @@ struct scsi_tgt_cmd {
struct list_head hash_list;
struct request *rq;
u64 tag;
-
-   void *buffer;
-   unsigned bufflen;
 };
 
 #define TGT_HASH_ORDER 4
@@ -330,10 +327,14 @@ static void scsi_tgt_cmd_done(struct scs
dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request));
 
scsi_tgt_uspace_send_status(cmd, tcmd->tag);
+
+   if (cmd->request_buffer)
+   scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
+
queue_work(scsi_tgtd, &tcmd->work);
 }
 
-static int __scsi_tgt_transfer_response(struct scsi_cmnd *cmd)
+static int scsi_tgt_transfer_response(struct scsi_cmnd *cmd)
 {
struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd);
int err;
@@ -346,30 +347,12 @@ static int __scsi_tgt_transfer_response(
case SCSI_MLQUEUE_DEVICE_BUSY:
return -EAGAIN;
}
-
return 0;
 }
 
-static void scsi_tgt_transfer_response(struct scsi_cmnd *cmd)
-{
-   struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data;
-   int err;
-
-   err = __scsi_tgt_transfer_response(cmd);
-   if (!err)
-   return;
-
-   cmd->result = DID_BUS_BU