Re: [PATCH 5/7] target: Check sess_tearing_down in target_get_sess_cmd()

2012-07-17 Thread Roland Dreier
On Mon, Jul 16, 2012 at 6:56 PM, Nicholas A. Bellinger
n...@linux-iscsi.org wrote:
 Do you have a plan for how to handle this?  Do we really want to plumb
 through another callback to tell the fabric driver to free the command
 in this case?

 I need to think more about this ahead of changing it back again for-3.6
 now that other fabrics have the assumption of target_submit_cmd() would
 not fail.

 There is a clear case with qla2xxx for just changing it back (we might
 end up doing that just yet) but I wanted to get the other important bits
 into for-next into place first..

Sleeping on things, I now feel pretty strongly that having target_submit_cmd
return an error value for immediate errors where the command does not
make it into the target core is the right approach.

Freeing commands is already one of the most confusing and complex parts
of the target code, with check_stop_free, cmd_wait_comp and
SCF_ACK_KREF.  Adding another code flow back to the fabric driver
with yet another set of semantics around freeing a command seems like
it's making things even harder to maintain.

On the other hand, every caller of target_submit_cmd() in the tree already
has an error path where it handles problems it detects right before calling
target_submit_cmd(), and so it's trivial to share that for problems detected
inside target_submit_cmd().  If you look at patch 4/7, pretty much the
only changes are like going from

target_submit_cmd(...);

to

if (target_submit_cmd(...))
goto err;

and in fact the -handle_cmd() wrapper that qla_target uses to call
target_submit_cmd via tcm_qla2xxx already has a return value that
qla_target handled properly!

I guess another approach would be to split target_submit_cmd() into
the target_get_sess_cmd() part and the rest of it, and have fabric
drivers handle errors queueing commands but not have to worry about
the submit cmd part failing.  But I'm not sure that's any better.

Andy, any feelings about this one way or another?  Christoph?

Thanks,
  Roland
--
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 5/7] target: Check sess_tearing_down in target_get_sess_cmd()

2012-07-17 Thread Christoph Hellwig
On Tue, Jul 17, 2012 at 09:34:49AM -0700, Roland Dreier wrote:
 Sleeping on things, I now feel pretty strongly that having target_submit_cmd
 return an error value for immediate errors where the command does not
 make it into the target core is the right approach.

I think it is.  When I tried to convert other drivers to
target_submit_cmd while doing the target processing thread removal that
would have simplified a lot of things.

 Freeing commands is already one of the most confusing and complex parts
 of the target code, with check_stop_free, cmd_wait_comp and
 SCF_ACK_KREF.  Adding another code flow back to the fabric driver
 with yet another set of semantics around freeing a command seems like
 it's making things even harder to maintain.

True.  And the above mess really needs to be simplified, too.

--
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 5/7] target: Check sess_tearing_down in target_get_sess_cmd()

2012-07-17 Thread Andy Grover
On 07/17/2012 09:39 AM, Christoph Hellwig wrote:
 On Tue, Jul 17, 2012 at 09:34:49AM -0700, Roland Dreier wrote:
 Sleeping on things, I now feel pretty strongly that having target_submit_cmd
 return an error value for immediate errors where the command does not
 make it into the target core is the right approach.
 
 I think it is.  When I tried to convert other drivers to
 target_submit_cmd while doing the target processing thread removal that
 would have simplified a lot of things.
 
 Freeing commands is already one of the most confusing and complex parts
 of the target code, with check_stop_free, cmd_wait_comp and
 SCF_ACK_KREF.  Adding another code flow back to the fabric driver
 with yet another set of semantics around freeing a command seems like
 it's making things even harder to maintain.
 
 True.  And the above mess really needs to be simplified, too.

I'm ok with submit_cmd returning a value for now. Maybe in the end it
doesn't, but getting the code working comes first.

This is one of those areas that needs a complete rewrite, so who cares
if there's some dirt on the floor when the whole joint is due for
remodeling.

-- Andy
--
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 5/7] target: Check sess_tearing_down in target_get_sess_cmd()

2012-07-17 Thread Nicholas A. Bellinger
On Tue, 2012-07-17 at 09:34 -0700, Roland Dreier wrote:
 On Mon, Jul 16, 2012 at 6:56 PM, Nicholas A. Bellinger
 n...@linux-iscsi.org wrote:
  Do you have a plan for how to handle this?  Do we really want to plumb
  through another callback to tell the fabric driver to free the command
  in this case?
 
  I need to think more about this ahead of changing it back again for-3.6
  now that other fabrics have the assumption of target_submit_cmd() would
  not fail.
 
  There is a clear case with qla2xxx for just changing it back (we might
  end up doing that just yet) but I wanted to get the other important bits
  into for-next into place first..
 
 Sleeping on things, I now feel pretty strongly that having target_submit_cmd
 return an error value for immediate errors where the command does not
 make it into the target core is the right approach.
 
 Freeing commands is already one of the most confusing and complex parts
 of the target code, with check_stop_free, cmd_wait_comp and
 SCF_ACK_KREF.  Adding another code flow back to the fabric driver
 with yet another set of semantics around freeing a command seems like
 it's making things even harder to maintain.
 

I wasn't talking about adding another release path.  I was thinking more
about a TFO call to optionally abort HW/SW exchange if we can't accept
the command in question.

Not to mention, this could end up being useful for other purposes beyond
the initial target_submit_cmd() failure case due to active I/O shutdown.
(aborts + active I/O shutdown with active SRP WRITEs with ib_srpt come
to mind needing something like this..)

 On the other hand, every caller of target_submit_cmd() in the tree already
 has an error path where it handles problems it detects right before calling
 target_submit_cmd(), and so it's trivial to share that for problems detected
 inside target_submit_cmd().  If you look at patch 4/7, pretty much the
 only changes are like going from
 
 target_submit_cmd(...);
 
 to
 
 if (target_submit_cmd(...))
 goto err;
 
 and in fact the -handle_cmd() wrapper that qla_target uses to call
 target_submit_cmd via tcm_qla2xxx already has a return value that
 qla_target handled properly!
 

Sure, there is no doubting tcm_qla2xxx's usage of this return value back
into qla_target.c code.. 

 I guess another approach would be to split target_submit_cmd() into
 the target_get_sess_cmd() part and the rest of it, and have fabric
 drivers handle errors queueing commands but not have to worry about
 the submit cmd part failing.  But I'm not sure that's any better.
 
 Andy, any feelings about this one way or another?  Christoph?
 

Ok, so for-3.6 it makes the most sense to just convert this back to
propagate up the return code, but only for target_get_sess_cmd() failure
case..

That said, I'll go ahead and respin patch #4 on top of for-next, and
post the updated patch shortly with the same CC's and ask for ACKs from
the necessary folks.

--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


Re: [PATCH 5/7] target: Check sess_tearing_down in target_get_sess_cmd()

2012-07-16 Thread Nicholas A. Bellinger
On Mon, 2012-07-16 at 11:04 -0700, Roland Dreier wrote:
 From: Roland Dreier rol...@purestorage.com
 
 Target core code assumes that target_splice_sess_cmd_list() has set
 sess_tearing_down and moved the list of pending commands to
 sess_wait_list, no more commands will be added to the session; if any
 are added, nothing keeps the se_session from being freed while the
 command is still in flight, which e.g. leads to use-after-free of
 se_cmd-se_sess in target_release_cmd_kref().
 
 To enforce this invariant, put a check of sess_tearing_down inside of
 sess_cmd_lock in target_get_sess_cmd(); any checks before this are
 racy and can lead to the use-after-free described above.  For example,
 the qla_target check in qlt_do_work() checks sess_tearing_down from
 work thread context but then drops all locks before calling
 target_submit_cmd() (as it must, since that is a sleeping function).
 
 However, since no locks are held, anything can happen with respect to
 the session it has looked up -- although it does correctly get
 sess_kref within its lock, so the memory won't be freed while
 target_submit_cmd() is actually running, nothing stops eg an ACL from
 being dropped and calling -shutdown_session() (which calls into
 target_splice_sess_cmd_list()) before we get to target_get_sess_cmd().
 Once this happens, the se_session memory can be freed as soon as
 target_submit_cmd() returns and qlt_do_work() drops its reference,
 even though we've just added a command to sess_cmd_list.
 
 To prevent this use-after-free, check sess_tearing_down inside of
 sess_cmd_lock right before target_get_sess_cmd() adds a command to
 sess_cmd_list; this is synchronized with target_splice_sess_cmd_list()
 so that every command is either waited for or not added to the queue.
 
 Signed-off-by: Roland Dreier rol...@purestorage.com
 ---
  drivers/target/target_core_transport.c |   24 +++-
  1 file changed, 19 insertions(+), 5 deletions(-)
 
 diff --git a/drivers/target/target_core_transport.c 
 b/drivers/target/target_core_transport.c
 index 34ca821..23e6e2d 100644
 --- a/drivers/target/target_core_transport.c
 +++ b/drivers/target/target_core_transport.c
 @@ -73,7 +73,7 @@ static void transport_complete_task_attr(struct se_cmd 
 *cmd);
  static void transport_handle_queue_full(struct se_cmd *cmd,
   struct se_device *dev);
  static int transport_generic_get_mem(struct se_cmd *cmd);
 -static void target_get_sess_cmd(struct se_session *, struct se_cmd *, bool);
 +static int target_get_sess_cmd(struct se_session *, struct se_cmd *, bool);
  static void transport_put_cmd(struct se_cmd *cmd);
  static void transport_remove_cmd_from_queue(struct se_cmd *cmd);
  static int transport_set_sense_codes(struct se_cmd *cmd, u8 asc, u8 ascq);
 @@ -1570,7 +1570,9 @@ int target_submit_cmd(struct se_cmd *se_cmd, struct 
 se_session *se_sess,
* for fabrics using TARGET_SCF_ACK_KREF that expect a second
* kref_put() to happen during fabric packet acknowledgement.
*/
 - target_get_sess_cmd(se_sess, se_cmd, (flags  TARGET_SCF_ACK_KREF));
 + rc = target_get_sess_cmd(se_sess, se_cmd, (flags  
 TARGET_SCF_ACK_KREF));
 + if (rc)
 + return rc;

OK, I see where you where going with the target_submit_cmd() failure
here now..

However, I'm still leaning towards a way to do this for tcm_qla2xxx that
does not require all fabric callers to handle target_submit_cmd()
exceptions directly..

How about a special target_get_sess_cmd() failure callback to free
se_cmd when target_get_sess_cmd() fails, but not actually send a SCSI
response back out to the fabric here during session shutdown..?

That said, I'm going to commit this patch (slightly changed to keep
target_submit_cmd() returning void for now) but I'd still like a better
way of handling this particular failure without propagating up the
return value.

   /*
* Signal bidirectional data payloads to target-core
*/
 @@ -1664,7 +1666,11 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct 
 se_session *se_sess,
   se_cmd-se_tmr_req-ref_task_tag = tag;
  
   /* See target_submit_cmd for commentary */
 - target_get_sess_cmd(se_sess, se_cmd, (flags  TARGET_SCF_ACK_KREF));
 + ret = target_get_sess_cmd(se_sess, se_cmd, (flags  
 TARGET_SCF_ACK_KREF));
 + if (ret) {
 + core_tmr_release_req(se_cmd-se_tmr_req);
 + return ret;
 + }
  
   ret = transport_lookup_tmr_lun(se_cmd, unpacked_lun);
   if (ret) {
 @@ -3650,10 +3656,11 @@ EXPORT_SYMBOL(transport_generic_free_cmd);
   * @se_cmd:  command descriptor to add
   * @ack_kref:Signal that fabric will perform an ack 
 target_put_sess_cmd()
   */
 -static void target_get_sess_cmd(struct se_session *se_sess, struct se_cmd 
 *se_cmd,
 - bool ack_kref)
 +static int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd 
 *se_cmd,
 +bool ack_kref)
  {
 

Re: [PATCH 5/7] target: Check sess_tearing_down in target_get_sess_cmd()

2012-07-16 Thread Roland Dreier
On Mon, Jul 16, 2012 at 4:08 PM, Nicholas A. Bellinger
n...@linux-iscsi.org wrote:
 However, I'm still leaning towards a way to do this for tcm_qla2xxx that
 does not require all fabric callers to handle target_submit_cmd()
 exceptions directly..

 How about a special target_get_sess_cmd() failure callback to free
 se_cmd when target_get_sess_cmd() fails, but not actually send a SCSI
 response back out to the fabric here during session shutdown..?

I guess that's OK, although I'm not sure it ends up being cleaner.  If
you look at my 4/7 patch, you see that all target_submit_cmd callers
have an error path where they handle terminating commands that
fail processing just before calling submit_cmd anyway.

eg for qla2xxx we'll need a callback to call qlt_send_term_exchange()
in addition to the error path call that qlt_do_work() has anyway.
Similarly tcm_fc ends up with a second call to ft_send_resp_code_and_free().
etc.

But I don't really have a strong feeling about this, if the view is that
submit_cmd() should never return failure directly then I'm OK with that.

 That said, I'm going to commit this patch (slightly changed to keep
 target_submit_cmd() returning void for now) but I'd still like a better
 way of handling this particular failure without propagating up the
 return value.

OK, I'll take a look at how you handle this...

 - 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 5/7] target: Check sess_tearing_down in target_get_sess_cmd()

2012-07-16 Thread Roland Dreier
 OK, I'll take a look at how you handle this...

So looking at commit bc187ea6c3b3 in the tree you just pushed out
(target: Check sess_tearing_down in target_get_sess_cmd()) it looks
like you just return from target_submit_cmd() if we fail to add the
command to sess_cmd_list -- doesn't this mean we just leak those
commands and possibly leave the HW sitting there with open exchanges?

Do you have a plan for how to handle this?  Do we really want to plumb
through another callback to tell the fabric driver to free the command
in this case?

 - 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 5/7] target: Check sess_tearing_down in target_get_sess_cmd()

2012-07-16 Thread Nicholas A. Bellinger
On Mon, 2012-07-16 at 18:40 -0700, Roland Dreier wrote:
  OK, I'll take a look at how you handle this...
 
 So looking at commit bc187ea6c3b3 in the tree you just pushed out
 (target: Check sess_tearing_down in target_get_sess_cmd()) it looks
 like you just return from target_submit_cmd() if we fail to add the
 command to sess_cmd_list -- doesn't this mean we just leak those
 commands and possibly leave the HW sitting there with open exchanges?
 

With dropping patch #5 for now, I assume that would be the case..

 Do you have a plan for how to handle this?  Do we really want to plumb
 through another callback to tell the fabric driver to free the command
 in this case?
 

I need to think more about this ahead of changing it back again for-3.6
now that other fabrics have the assumption of target_submit_cmd() would
not fail.

There is a clear case with qla2xxx for just changing it back (we might
end up doing that just yet) but I wanted to get the other important bits
into for-next into place first..




--
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 5/7] target: Check sess_tearing_down in target_get_sess_cmd()

2012-07-16 Thread Nicholas A. Bellinger
On Mon, 2012-07-16 at 18:56 -0700, Nicholas A. Bellinger wrote:
 On Mon, 2012-07-16 at 18:40 -0700, Roland Dreier wrote:
   OK, I'll take a look at how you handle this...
  
  So looking at commit bc187ea6c3b3 in the tree you just pushed out
  (target: Check sess_tearing_down in target_get_sess_cmd()) it looks
  like you just return from target_submit_cmd() if we fail to add the
  command to sess_cmd_list -- doesn't this mean we just leak those
  commands and possibly leave the HW sitting there with open exchanges?
  
 
 With dropping patch #5 for now, I assume that would be the case..
 

Or with patch #4 even..


--
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