Re: [PATCH] target: Remove unused se_cmd.cmd_spdtl

2012-08-18 Thread Roland Dreier
On Fri, Aug 17, 2012 at 6:02 PM, Nicholas A. Bellinger
n...@linux-iscsi.org wrote:
 No, or at least that is not what happens anymore with current target
 core + iscsi-target code..

 The se_cmd-data_length re-assignment here is what will be used by
 iscsi-target fabric code for all iSCSI descriptor related allocations
 +ransfer, instead of the original fabric 'expected transfer length' that
 declares the size of the SCSI initiator's available buffer at the other
 end.

Not sure I follow this.  Isn't cmd-data_length also what we use to
allocate the buffer used to store the data we're going to transfer?

I guess my example with READ(10) actually works, because
iblock_execute_rw() just uses the buffer allocated, rather than
paying attention to the sector count in the command.

But what if an initiator sends, say, REPORT LUNS or PR OUT
with an allocation length of 8192, but a transport-level length
of only 4096?  If the REPORT LUNS or PR OUT response is
bigger than 4096 bytes, we'll overflow the allocated buffer with
your patch, right?

 - R.
--
To unsubscribe from this list: send the line unsubscribe linux-scsi in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] target: Remove unused se_cmd.cmd_spdtl

2012-08-17 Thread Boaz Harrosh
We should switch this topic to the scsi mailing list

On 08/17/2012 01:49 PM, Boaz Harrosh wrote:

 On 08/17/2012 01:12 AM, Nicholas A. Bellinger wrote:
 
 On Thu, 2012-08-16 at 09:24 -0700, Roland Dreier wrote:
 Actually I'm not sure removing cmd_spdtl is the right answer.

 If /dev/sda is a device on an iSCSI initiator exported by an LIO
 target, try doing:

 # sg_raw -r512 /dev/sda 28 0 0 0 0 0 0 0 2 0

 This issues a READ (10) for 2 sectors, but only sends a length of 512
 at the transfer level.

 The target responds by setting the residual to 512 but transmits all
 1024 bytes, 
 
 
 Is this the correct behavior from the Target? I would imagine that the
 target needs to only send 512 bytes (transfer level size) and set the
 OVERFLOW bit and residual to 512.
 
 Not that it really matter because as you stated below the Initiator makes
 sure nothing bad happens.
 
 BTW what target are we talking about, on the other side of the initiator
 here? (There are two targets in this setup right?)
 
 and the Linux initiator at least rejects it because it
 hits:

 if (tcp_task-data_offset + tcp_conn-in.datalen  total_in_length) {
 ISCSI_DBG_TCP(conn, data_offset(%d) + data_len(%d)  
   total_length_in(%d)\n, tcp_task-data_offset,
   tcp_conn-in.datalen, total_in_length);
 return ISCSI_ERR_DATA_OFFSET;
 }


 Ok, this is the 'overflow' case when the fabric -data_length (expected
 data transfer length of the initiator's buffer) is smaller than the SCSI
 CDB allocation length or sectors*block_size (attempted transfer length)
 the target has been asked to process.

 The following patch which appears to do the right thing from the
 perspective of the target for overflow, but AFAICT open-iscsi still
 returns GOOD status w/ no data-in payload (at least via sg_raw) when the
 iscsi-target is signaling overflow bit in iSCSI Data IN PDU.  Not sure
 yet why this is the case, but drivers/scsi/libiscsi.c:iscsi_data_in_rsp
 code:

if (rhdr-flags  (ISCSI_FLAG_DATA_UNDERFLOW |
ISCSI_FLAG_DATA_OVERFLOW)) {
 int res_count = be32_to_cpu(rhdr-residual_count);

 if (res_count  0 
 (rhdr-flags  ISCSI_FLAG_CMD_OVERFLOW ||
  res_count = scsi_in(sc)-length))
 scsi_in(sc)-resid = res_count;
 else
 sc-result = (DID_BAD_TARGET  16) | 
 rhdr-cmd_status;
 }

 
 
 OK I admit I kind of rearranged all this code a few years ago. Guilty ;-) 
 
 Well now that I look at it again, I think it is totally wrong!!
 The scsi and block layer do not know anything about CMD_OVERFLOW
 If a scsi_in/out(sc)-resid is set it only ever means UNDERFLOW.
 
 Both scsi and block expects to only do transfer_length - resid.
 This is why you get empty buffer back because the transfer_length=512
 minus resid=512 means zero bytes.
 
 So the || ISCSI_FLAG_CMD_OVERFLOW case is wrong.
 
 Now the big question is what to do. Fail the all command, or say
 nothing?
 
 The correct thing is to teach the middle layers about overflow,
 With some kind of warning level system.
 I was also thinking that we can make resid signed and signal
 an overflow with a negative resid. Now the math of
 transfer_length - resid will become correct since it means
 more, in the case above 512 - (-512) would be our 1024 CDB len.
 
 For now this code must be fixed. And the command must fail.
 Do you need that I prepare a patch? (Please you do it, I'm
 swamped, it'll take me time)
 There are 3 more places like this.
 
 BTW did you notice how in the code above we have mixed up the
 use of: ISCSI_FLAG_DATA_OVERFLOW and ISCSI_FLAG_CMD_OVERFLOW?
 That's another bug, here it should be ISCSI_FLAG_DATA_OVERFLOW
 only. The other places with the other flags.
 
 appears to be setting resid for non bidi cases correctly, right..? (mnc
 + boaz CC'ed)

 How about the following to ensure we restrict overflow to keep the
 existing (smaller) cmd-data_length assignment, and only re-assign this
 value for the underflow case..?  (hch CC'ed)

 WDYT..?

 diff --git a/drivers/target/target_core_transport.c 
 b/drivers/target/target_core_transport.c
 index 0eaae23..63b3594 100644
 --- a/drivers/target/target_core_transport.c
 +++ b/drivers/target/target_core_transport.c
 @@ -1183,15 +1183,20 @@ int target_cmd_size_check(struct se_cmd *cmd, 
 unsigned int size)
 /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */
 goto out_invalid_cdb_field;
 }
 -
 +   /*
 +* For the overflow case keep the existing fabric provided
 +* -data_length.  Otherwise for the underflow case, reset
 +* -data_length to the smaller SCSI expected data transfer
 +* length.
 +*/
 if (size  cmd-data_length) {
 
 
 I'm a bit out of context. Is 

Re: [PATCH] target: Remove unused se_cmd.cmd_spdtl

2012-08-17 Thread Nicholas A. Bellinger
(CC'ing linux-scsi as per request by Boaz)

On Fri, 2012-08-17 at 13:49 +0300, Boaz Harrosh wrote:
 On 08/17/2012 01:12 AM, Nicholas A. Bellinger wrote:
 
  On Thu, 2012-08-16 at 09:24 -0700, Roland Dreier wrote:
  Actually I'm not sure removing cmd_spdtl is the right answer.
 
  If /dev/sda is a device on an iSCSI initiator exported by an LIO
  target, try doing:
 
  # sg_raw -r512 /dev/sda 28 0 0 0 0 0 0 0 2 0
 
  This issues a READ (10) for 2 sectors, but only sends a length of 512
  at the transfer level.
 
  The target responds by setting the residual to 512 but transmits all
  1024 bytes, 
 
 
 Is this the correct behavior from the Target? I would imagine that the
 target needs to only send 512 bytes (transfer level size) and set the
 OVERFLOW bit and residual to 512.
 

So my proposed target patch below to keep the smaller cmd-data_length
assignment for the SCSI overflow case in target_cmd_size_check() makes
the target do the right thing here, which is:

Transfer 512 bytes and set the OVERFLOW bit in se_cmd (to signal to the
fabric to also set OVERFLOW bit) with a residual count of 512 bytes
reported during the DATAIN sequence back across the wire..


 Not that it really matter because as you stated below the Initiator makes
 sure nothing bad happens.
 
 BTW what target are we talking about, on the other side of the initiator
 here? (There are two targets in this setup right?)
 

This is on the final target side running TCM + fabric driver

  and the Linux initiator at least rejects it because it
  hits:
 
 if (tcp_task-data_offset + tcp_conn-in.datalen  total_in_length) {
 ISCSI_DBG_TCP(conn, data_offset(%d) + data_len(%d)  
   total_length_in(%d)\n, tcp_task-data_offset,
   tcp_conn-in.datalen, total_in_length);
 return ISCSI_ERR_DATA_OFFSET;
 }
 
  
  Ok, this is the 'overflow' case when the fabric -data_length (expected
  data transfer length of the initiator's buffer) is smaller than the SCSI
  CDB allocation length or sectors*block_size (attempted transfer length)
  the target has been asked to process.
  
  The following patch which appears to do the right thing from the
  perspective of the target for overflow, but AFAICT open-iscsi still
  returns GOOD status w/ no data-in payload (at least via sg_raw) when the
  iscsi-target is signaling overflow bit in iSCSI Data IN PDU.  Not sure
  yet why this is the case, but drivers/scsi/libiscsi.c:iscsi_data_in_rsp
  code:
  
 if (rhdr-flags  (ISCSI_FLAG_DATA_UNDERFLOW |
 ISCSI_FLAG_DATA_OVERFLOW)) {
  int res_count = be32_to_cpu(rhdr-residual_count);
  
  if (res_count  0 
  (rhdr-flags  ISCSI_FLAG_CMD_OVERFLOW ||
   res_count = scsi_in(sc)-length))
  scsi_in(sc)-resid = res_count;
  else
  sc-result = (DID_BAD_TARGET  16) | 
  rhdr-cmd_status;
  }
  
 
 
 OK I admit I kind of rearranged all this code a few years ago. Guilty ;-) 
 
 Well now that I look at it again, I think it is totally wrong!!
 The scsi and block layer do not know anything about CMD_OVERFLOW
 If a scsi_in/out(sc)-resid is set it only ever means UNDERFLOW.
 
 Both scsi and block expects to only do transfer_length - resid.
 This is why you get empty buffer back because the transfer_length=512
 minus resid=512 means zero bytes.
 
 So the || ISCSI_FLAG_CMD_OVERFLOW case is wrong.
 

Mmmm, your're right..  I could have sworn at one point that open-iscsi
returned DID_BAD_TARGET status for all OVERFLOW cases, and set the
proper residual + completed scsi_cmnd for UNDERFLOW cases.

Doing the reverse in the current code is definitely not correct.

 Now the big question is what to do. Fail the all command, or say
 nothing?
 
 The correct thing is to teach the middle layers about overflow,
 With some kind of warning level system.
 I was also thinking that we can make resid signed and signal
 an overflow with a negative resid. Now the math of
 transfer_length - resid will become correct since it means
 more, in the case above 512 - (-512) would be our 1024 CDB len.
 
 For now this code must be fixed. And the command must fail.
 Do you need that I prepare a patch? (Please you do it, I'm
 swamped, it'll take me time)
 There are 3 more places like this.
 

Swamped here as well atm..  mnc/hannes, would you mind taking a look at
a patch to address these bugs in open-iscsi..?  I'm happy to test them
against target-pending to make sure we get these correct, and add them
into scsi-testsuite for your own use.

 BTW did you notice how in the code above we have mixed up the
 use of: ISCSI_FLAG_DATA_OVERFLOW and ISCSI_FLAG_CMD_OVERFLOW?
 That's another bug, here it should be ISCSI_FLAG_DATA_OVERFLOW
 only. The other places with the other flags.
 

nod

  appears to be setting resid for non bidi cases correctly, right..? (mnc
  + boaz CC'ed)
  
  How 

Re: [PATCH] target: Remove unused se_cmd.cmd_spdtl

2012-08-17 Thread Nicholas A. Bellinger
On Fri, 2012-08-17 at 11:46 -0700, Roland Dreier wrote:
 On Thu, Aug 16, 2012 at 3:12 PM, Nicholas A. Bellinger
 n...@linux-iscsi.org wrote:
  diff --git a/drivers/target/target_core_transport.c 
  b/drivers/target/target_core_transport.c
  index 0eaae23..63b3594 100644
  --- a/drivers/target/target_core_transport.c
  +++ b/drivers/target/target_core_transport.c
  @@ -1183,15 +1183,20 @@ int target_cmd_size_check(struct se_cmd *cmd, 
  unsigned int size)
  /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */
  goto out_invalid_cdb_field;
  }
  -
  +   /*
  +* For the overflow case keep the existing fabric provided
  +* -data_length.  Otherwise for the underflow case, reset
  +* -data_length to the smaller SCSI expected data transfer
  +* length.
  +*/
  if (size  cmd-data_length) {
  cmd-se_cmd_flags |= SCF_OVERFLOW_BIT;
  cmd-residual_count = (size - cmd-data_length);
  } else {
  cmd-se_cmd_flags |= SCF_UNDERFLOW_BIT;
  cmd-residual_count = (cmd-data_length - size);
  +   cmd-data_length = size;
  }
  -   cmd-data_length = size;
  }
 
  return 0;
 
 I don't think this can work... if my memory of the code is right, if we do 
 this,
 then the target core will only allocate the smaller (fabric) data length worth
 of buffer space, but then it will actually execute whatever the CDB says to
 do. 

No, or at least that is not what happens anymore with current target
core + iscsi-target code..

The se_cmd-data_length re-assignment here is what will be used by
iscsi-target fabric code for all iSCSI descriptor related allocations
+ransfer, instead of the original fabric 'expected transfer length' that
declares the size of the SCSI initiator's available buffer at the other
end.

At one point in v4.0 code iscsi-target had it's own
iscsi_cmd-data_length (which might be what your thinking of), but this
was removed during 3.4 by Agrover in favor of just using
se_cmd-data_length from the possibly underflow adjusted value.

  So in my original example we're probably OK because we'll allocate a
 full page anyway, but I think something like:
 
 # sg_raw -r512 /dev/sda 28 0 0 0 0 0 0 0 9 0
 
 would cause the target core to allocate 1 page but then read 9 sectors.
 

With the patch above to target_cmd_size_check() in place to skip
re-assignment of se_cmd-data_length for the overflow case, it appears
the target (at least) is doing the right thing now with your test case:

[root@initiator ~]# sg_raw -r512 /dev/sdi 28 0 0 0 0 0 0 0 9 0
sg_raw -r512 /dev/sdi 28 0 0 0 0 0 0 0 9 0
SCSI Status: Good 

Sense Information:
sense buffer empty

Received -3584 bytes of data:

Target side:

[82582.697668] Got SCSI Command, ITT: 0x7e40, CmdSN: 0x02d9, 
ExpXferLen: 512, Length: 0, CID: 0
[82582.697673] TARGET_CORE[iSCSI]: Expected Transfer Length: 512 does not match 
SCSI CDB Length: 4608 for SAM Opcode: 0x28
[82582.709696] Received CmdSN matches ExpCmdSN, incremented ExpCmdSN to: 
0x02da
[82582.709876] Updated MaxCmdSN to 0x02f9
[82582.709881] Built DataIN ITT: 0x7e40, StatSN: 0x905625fd, DataSN: 
0x, Offset: 0, Length: 512, CID: 0

So aside from the open-iscsi client bugs that Boaz has pointed out wrt
to overflow/underflow handling, I'll verify over the weekend with
loopback + tcm_qla2xxx fabrics and if everything looks fine will plan to
include this patch into master - for next week's 3.6-rc-fixes PULL
request.

Thanks Roland!

--nab

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