From: James Bottomley <James.Bottomley@HansenPartnership.com>
To: Bart Van Assche <bart.vanassche@sandisk.com>
Cc: Christoph Hellwig <hch@infradead.org>,
Rusty Russell <rusty@rustcorp.com.au>,
Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>,
linux-kernel <linux-kernel@vger.kernel.org>,
linux-scsi <linux-scsi@vger.kernel.org>
Subject: Re: module: fix module_refcount() return when running in a module exit routine
Date: Wed, 28 Jan 2015 13:45:50 -0800 [thread overview]
Message-ID: <1422481550.2086.16.camel@HansenPartnership.com> (raw)
In-Reply-To: <54C8AAA9.7060300@sandisk.com>
On Wed, 2015-01-28 at 10:23 +0100, Bart Van Assche wrote:
> On 01/23/15 19:42, James Bottomley wrote:
> > diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
> > index 08c90a7..31ba254 100644
> > --- a/drivers/scsi/scsi.c
> > +++ b/drivers/scsi/scsi.c
> > @@ -965,6 +965,15 @@ int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
> > }
> > EXPORT_SYMBOL(scsi_report_opcode);
> >
> > +static int __scsi_device_get_common(struct scsi_device *sdev)
> > +{
> > + if (sdev->sdev_state == SDEV_DEL)
> > + return -ENXIO;
> > + if (!get_device(&sdev->sdev_gendev))
> > + return -ENXIO;
> > + return 0;
> > +}
> > +
> > /**
> > * scsi_device_get - get an additional reference to a scsi_device
> > * @sdev: device to get a reference to
> > @@ -975,19 +984,45 @@ EXPORT_SYMBOL(scsi_report_opcode);
> > */
> > int scsi_device_get(struct scsi_device *sdev)
> > {
> > - if (sdev->sdev_state == SDEV_DEL)
> > - return -ENXIO;
> > - if (!get_device(&sdev->sdev_gendev))
> > - return -ENXIO;
> > - /* We can fail this if we're doing SCSI operations
> > - * from module exit (like cache flush) */
> > - try_module_get(sdev->host->hostt->module);
> > + int ret;
> >
> > - return 0;
> > + ret = __scsi_device_get_common(sdev);
> > + if (ret)
> > + return ret;
> > +
> > + ret = try_module_get(sdev->host->hostt->module);
> > +
> > + if (ret)
> > + put_device(&sdev->sdev_gendev);
> > +
> > + return ret;
> > }
> > EXPORT_SYMBOL(scsi_device_get);
> >
> > /**
> > + * scsi_device_get_in_module_exit() - get an additional reference to a scsi_device
> > + * @sdev: device to get a reference to
> > + *
> > + * Functions identically to scsi_device_get() except that it unconditionally
> > + * gets the module reference. This allows it to be called from module exit
> > + * routines where scsi_device_get() will fail. This routine is still paired
> > + * with scsi_device_put().
> > + */
> > +int scsi_device_get_in_module_exit(struct scsi_device *sdev)
> > +{
> > + int ret;
> > +
> > + ret = __scsi_device_get_common(sdev);
> > + if (ret)
> > + return ret;
> > +
> > + __module_get(sdev->host->hostt->module);
> > +
> > + return 0;
> > +}
> > +EXPORT_SYMBOL(scsi_device_get_in_module_exit);
> > +
> > +/**
> > * scsi_device_put - release a reference to a scsi_device
> > * @sdev: device to release a reference on.
> > *
> > diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
> > index ebf35cb6..057604e 100644
> > --- a/drivers/scsi/sd.c
> > +++ b/drivers/scsi/sd.c
> > @@ -564,16 +564,22 @@ static int sd_major(int major_idx)
> > }
> > }
> >
> > -static struct scsi_disk *__scsi_disk_get(struct gendisk *disk)
> > +static struct scsi_disk *__scsi_disk_get(struct gendisk *disk, int in_exit)
> > {
> > struct scsi_disk *sdkp = NULL;
> >
> > if (disk->private_data) {
> > + int ret;
> > +
> > sdkp = scsi_disk(disk);
> > - if (scsi_device_get(sdkp->device) == 0)
> > - get_device(&sdkp->dev);
> > + if (in_exit)
> > + ret = scsi_device_get_in_module_exit(sdkp->device);
> > else
> > + ret = scsi_device_get(sdkp->device);
> > + if (unlikely(ret))
> > sdkp = NULL;
> > + else
> > + get_device(&sdkp->dev);
> > }
> > return sdkp;
> > }
> > @@ -583,19 +589,19 @@ static struct scsi_disk *scsi_disk_get(struct gendisk *disk)
> > struct scsi_disk *sdkp;
> >
> > mutex_lock(&sd_ref_mutex);
> > - sdkp = __scsi_disk_get(disk);
> > + sdkp = __scsi_disk_get(disk, 0);
> > mutex_unlock(&sd_ref_mutex);
> > return sdkp;
> > }
> >
> > -static struct scsi_disk *scsi_disk_get_from_dev(struct device *dev)
> > +static struct scsi_disk *scsi_disk_get_from_dev(struct device *dev, int in_exit)
> > {
> > struct scsi_disk *sdkp;
> >
> > mutex_lock(&sd_ref_mutex);
> > sdkp = dev_get_drvdata(dev);
> > if (sdkp)
> > - sdkp = __scsi_disk_get(sdkp->disk);
> > + sdkp = __scsi_disk_get(sdkp->disk, in_exit);
> > mutex_unlock(&sd_ref_mutex);
> > return sdkp;
> > }
> > @@ -1525,7 +1531,7 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
> >
> > static void sd_rescan(struct device *dev)
> > {
> > - struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
> > + struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev, 0);
> >
> > if (sdkp) {
> > revalidate_disk(sdkp->disk);
> > @@ -3147,7 +3153,7 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
> > */
> > static void sd_shutdown(struct device *dev)
> > {
> > - struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
> > + struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev, 1);
> >
> > if (!sdkp)
> > return; /* this can happen */
> > @@ -3171,7 +3177,7 @@ exit:
> >
> > static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
> > {
> > - struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
> > + struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev, 0);
> > int ret = 0;
> >
> > if (!sdkp)
> > @@ -3213,7 +3219,7 @@ static int sd_suspend_runtime(struct device *dev)
> >
> > static int sd_resume(struct device *dev)
> > {
> > - struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
> > + struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev, 0);
> > int ret = 0;
> >
> > if (!sdkp->device->manage_start_stop)
> > diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
> > index 2e0281e..0bad37c 100644
> > --- a/include/scsi/scsi_device.h
> > +++ b/include/scsi/scsi_device.h
> > @@ -327,6 +327,7 @@ extern int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh);
> > void scsi_attach_vpd(struct scsi_device *sdev);
> >
> > extern int scsi_device_get(struct scsi_device *);
> > +extern int scsi_device_get_in_module_exit(struct scsi_device *);
> > extern void scsi_device_put(struct scsi_device *);
> > extern struct scsi_device *scsi_device_lookup(struct Scsi_Host *,
> > uint, uint, u64);
>
> Hello James,
>
> Is this the latest version of this patch that is available ? I have
> tried to test the above patch. However, I couldn't test the impact of
> this patch on the SRP initiator driver since my test system didn't boot
> anymore with the above patch applied. That test system boots from an ATA
> disk managed by the SCSI subsystem:
> $ lsscsi | head -n1
> [0:0:0:0] disk ATA KINGSTON SH103S3 BBF0 /dev/sda
Not yet, since I knew it would need a bit of testing to identify all the
potential in_exit acquisitions. However, you could help me by
diagnosing the current failure.
Thanks,
James
next prev parent reply other threads:[~2015-01-28 21:45 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-01-18 16:55 module: fix module_refcount() return when running in a module exit routine James Bottomley
2015-01-18 23:37 ` Rusty Russell
2015-01-18 23:37 ` Rusty Russell
2015-01-19 5:18 ` Masami Hiramatsu
2015-01-19 5:51 ` Rusty Russell
2015-01-19 8:28 ` Christoph Hellwig
2015-01-19 16:07 ` James Bottomley
2015-01-19 16:08 ` James Bottomley
2015-01-20 0:45 ` Rusty Russell
2015-01-20 2:17 ` Masami Hiramatsu
2015-01-20 17:23 ` James Bottomley
2015-01-21 5:30 ` Rusty Russell
2015-01-22 16:50 ` Christoph Hellwig
2015-01-22 17:02 ` James Bottomley
2015-01-23 2:54 ` Rusty Russell
2015-01-23 13:17 ` Christoph Hellwig
2015-01-23 18:42 ` James Bottomley
2015-01-23 23:35 ` Rusty Russell
2015-01-26 17:16 ` Christoph Hellwig
2015-01-28 9:23 ` Bart Van Assche
2015-01-28 21:45 ` James Bottomley [this message]
2015-01-29 12:16 ` Bart Van Assche
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=1422481550.2086.16.camel@HansenPartnership.com \
--to=james.bottomley@hansenpartnership.com \
--cc=bart.vanassche@sandisk.com \
--cc=hch@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=masami.hiramatsu.pt@hitachi.com \
--cc=rusty@rustcorp.com.au \
/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.