From: Michael Reed <mdr@sgi.com>
To: Mike Christie <michaelc@cs.wisc.edu>
Cc: linux-scsi <linux-scsi@vger.kernel.org>,
James Smart <James.Smart@Emulex.Com>,
James Bottomley <James.Bottomley@suse.de>,
Hannes Reinecke <hare@suse.de>
Subject: Re: [PATCH 1/1] mid-layer unblocks blocked sdev leaving queue stopped
Date: Wed, 24 Feb 2010 14:17:59 -0600 [thread overview]
Message-ID: <4B858977.1030707@sgi.com> (raw)
In-Reply-To: <4B7B12B7.8050601@sgi.com>
Michael Reed wrote:
> Mike Christie wrote:
>> On 02/10/2010 04:24 PM, Michael Reed wrote:
>>>> + /*
>>>> + * If device is blocked, leave state alone and let blocker
>>>> + * unblock when appropriate. Otherwise, set the device
>>>> + * running here so that slave configure may perform i/o.
>>>> + */
>>>> + if (sdev->sdev_state != SDEV_BLOCK) {
>>>> + ret = scsi_device_set_state(sdev, SDEV_RUNNING);
>> Do we need locking here? Is it possible that right after we check the
>> sdev_state for being blocked, it could be be set to blocked?
>
> Since the sdev_state can be set to blocked upon entry to the routines,
> it seems likely that it could transition as you describe. The host_lock
> appears to be the right lock for this. Nice catch. It does, however,
> open a can of worms. The documentation for the _block()/_unblock()
> functions state that it is assumed the host_lock is held upon entry.
> This doesn't line up with the code, which explicitly releases the
> host_lock before calling scsi_internal_device_[un]block().
>
> I previously toyed around with an alternate method of resolving this which
> put the onus on the unblocking thread which doesn't care about the
> sdev_state. As scsi_internal_device_block() is the routine which stops
> the queue, I made scsi_internal_device_unblock() allow for the
> possibility that another thread had transitioned sdev_state from SDEV_BLOCK.
>
> It's been long enough that I don't recall why I chose the patch I
> posted to resolve the issue, but this patch was also effective at
> resolving the issue. It also confines the change to the _block()/
> _unblock() pair of routines and doesn't require changes to the
> existing locking logic. In retrospect, this patch was probably the
> one I should have chosen to post.
>
> Please review.
I've encountered a test system which exhibits this problem regularly.
This patch consistently corrects the hang and allows the system to
boot. I used a printk to confirm the condition was encountered.
Please consider this patch for integration to stable as well as
any other appropriate trees.
Thank you.
Mike
>
> Signed-off-by: Michael Reed <mdr@sgi.com>
>
> --- a/drivers/scsi/scsi_lib.c 2010-02-08 11:19:57.000000000 -0600
> +++ b/drivers/scsi/scsi_lib.c 2010-02-11 14:35:26.249142688 -0600
> @@ -2376,7 +2376,7 @@ EXPORT_SYMBOL(scsi_target_resume);
> * (which must be a legal transition). When the device is in this
> * state, all commands are deferred until the scsi lld reenables
> * the device with scsi_device_unblock or device_block_tmo fires.
> - * This routine assumes the host_lock is held on entry.
> + * This routine assumes the host_lock is not held on entry.
> */
> int
> scsi_internal_device_block(struct scsi_device *sdev)
> @@ -2420,7 +2420,7 @@ EXPORT_SYMBOL_GPL(scsi_internal_device_b
> * This routine transitions the device to the SDEV_RUNNING state
> * (which must be a legal transition) allowing the midlayer to
> * goose the queue for this device. This routine assumes the
> - * host_lock is held upon entry.
> + * host_lock is not held upon entry.
> */
> int
> scsi_internal_device_unblock(struct scsi_device *sdev)
> @@ -2431,15 +2431,23 @@ scsi_internal_device_unblock(struct scsi
> /*
> * Try to transition the scsi device to SDEV_RUNNING
> * and goose the device queue if successful.
> + * It's possible that an sdev may be blocked before it is
> + * completely set up. scsi_sysfs_add_sdev() and scsi_add_lun()
> + * will unconditionally attempt to transition the sdev to
> + * SDEV_RUNNING. To avoid leaving the queue stopped, we
> + * allow for the sdev to already be in the SDEV_RUNNING state.
> */
> + spin_lock_irqsave(q->queue_lock, flags);
> +
> if (sdev->sdev_state == SDEV_BLOCK)
> sdev->sdev_state = SDEV_RUNNING;
> else if (sdev->sdev_state == SDEV_CREATED_BLOCK)
> sdev->sdev_state = SDEV_CREATED;
> - else
> + else if (sdev->sdev_state != SDEV_RUNNING || !blk_queue_stopped(q)) {
> + spin_unlock_irqrestore(q->queue_lock, flags);
> return -EINVAL;
> + }
>
> - spin_lock_irqsave(q->queue_lock, flags);
> blk_start_queue(q);
> spin_unlock_irqrestore(q->queue_lock, flags);
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2010-02-24 20:18 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-12-16 22:43 [PATCH 1/1] mid-layer unblocks blocked sdev leaving queue stopped Michael Reed
2010-02-10 22:24 ` Michael Reed
2010-02-10 22:57 ` Mike Christie
2010-02-16 21:48 ` Michael Reed
2010-02-24 20:17 ` Michael Reed [this message]
2010-03-09 16:14 ` James Smart
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4B858977.1030707@sgi.com \
--to=mdr@sgi.com \
--cc=James.Bottomley@suse.de \
--cc=James.Smart@Emulex.Com \
--cc=hare@suse.de \
--cc=linux-scsi@vger.kernel.org \
--cc=michaelc@cs.wisc.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.