public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
From: Mike Anderson <andmike@us.ibm.com>
To: Christoph Hellwig <hch@infradead.org>
Cc: James Bottomley <James.Bottomley@steeleye.com>,
	"Justin T. Gibbs" <gibbs@scsiguy.com>,
	Doug Ledford <dledford@redhat.com>,
	Matthew Wilcox <willy@debian.org>,
	Marcelo Tosatti <marcelo@conectiva.com.br>,
	linux-scsi mailing list <linux-scsi@vger.kernel.org>
Subject: Re: [PATCH] sym53c8xx PPR negotiation fix
Date: Thu, 6 Nov 2003 01:04:08 -0800	[thread overview]
Message-ID: <20031106090408.GA1398@beaverton.ibm.com> (raw)
In-Reply-To: <20031104071001.A10128@infradead.org>

Christoph Hellwig [hch@infradead.org] wrote:
> Umm, the code implementing ->slave_destroy may no more exist when the
> scsi_device reference count hits zero..

Ok here is an update. This should address both issues of not calling
slave_destroy on scan'd but not configured devices and also calling
slave_destroy on host removal prior to the return of scsi_remove_host.

I added a piece of two test runs. A more complete log is available.

Ex 1. Configured device mounted with unexpected disconnect followed by
unmount.

chk_scsi_ref: Remove adapter

kobject ./<NULL>: cleaning up
kobject scsi_device/2:0:0:0: cleaning up
kobject ./<NULL>: cleaning up
kobject queue/iosched: cleaning up
kobject sdd/queue: cleaning up
scsi_debug: slave_destroy <2 0 0 0>
kobject scsi_host/host2: cleaning up

chk_scsi_ref: umount sdd

Buffer I/O error on device sdd, logical block 1
lost page write due to I/O error on sdd
kobject host2/2:0:0:0: cleaning up
kobject adapter1/host2: cleaning up
kobject pseudo_0/adapter1: cleaning up
kobject ./<NULL>: cleaning up
kobject block/sdd: cleaning up

Ex 2. Scanning a device that was not configured.

scsi_debug: slave_alloc <9 0 1 0>
scsi_debug: cmd 12 00 00 00 24 00
scsi_debug: ... <9 0 1 0> non-zero result=0x10000
scsi_debug: slave_destroy <9 0 1 0>
kobject ./<NULL>: cleaning up

-andmike
--
Michael Anderson
andmike@us.ibm.com


DESC
This patch splits the scsi device struct device register into init and
add. It also addresses memory leak issues of not calling slave_destroy on
scsi_devices that are not configured in.

Details:
* Make scsi_device_dev_release extern for scsi_scan to use in
alloc_sdev.
* Move scsi_free_sdev code to scsi_device_dev_release. Have
scsi_free_sdev call slave_destroy plus put_device.
* Changed name of scsi_device_register to scsi_sysfs_add_sdev to
match host call and align with split struct device init.
* Move sdev_gendev device and class init to scsi_alloc_sdev.

Thu Nov  6 07:43:56 UTC 2003
EDESC


 drivers/scsi/scsi_priv.h  |    3 +-
 drivers/scsi/scsi_scan.c  |   42 ++++++++++++++++++----------------
 drivers/scsi/scsi_sysfs.c |   56 +++++++++++++++++++++++-----------------------
 3 files changed, 54 insertions(+), 47 deletions(-)

diff -puN drivers/scsi/scsi_priv.h~sdev_ldm_reg drivers/scsi/scsi_priv.h
--- scsi-bugfixes-2.6/drivers/scsi/scsi_priv.h~sdev_ldm_reg	Tue Nov  4 23:17:24 2003
+++ scsi-bugfixes-2.6-andmike/drivers/scsi/scsi_priv.h	Tue Nov  4 23:17:24 2003
@@ -143,7 +143,8 @@ extern void scsi_exit_sysctl(void);
 #endif /* CONFIG_SYSCTL */
 
 /* scsi_sysfs.c */
-extern int scsi_device_register(struct scsi_device *);
+extern void scsi_device_dev_release(struct device *);
+extern int scsi_sysfs_add_sdev(struct scsi_device *);
 extern int scsi_sysfs_add_host(struct Scsi_Host *);
 extern int scsi_sysfs_register(void);
 extern void scsi_sysfs_unregister(void);
diff -puN drivers/scsi/scsi_scan.c~sdev_ldm_reg drivers/scsi/scsi_scan.c
--- scsi-bugfixes-2.6/drivers/scsi/scsi_scan.c~sdev_ldm_reg	Tue Nov  4 23:17:24 2003
+++ scsi-bugfixes-2.6-andmike/drivers/scsi/scsi_scan.c	Tue Nov  4 23:17:24 2003
@@ -236,6 +236,25 @@ static struct scsi_device *scsi_alloc_sd
 			goto out_free_queue;
 	}
 
+	if (get_device(&sdev->host->shost_gendev)) {
+
+		device_initialize(&sdev->sdev_gendev);
+		sdev->sdev_gendev.parent = &sdev->host->shost_gendev;
+		sdev->sdev_gendev.bus = &scsi_bus_type;
+		sdev->sdev_gendev.release = scsi_device_dev_release;
+		sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d",
+			sdev->host->host_no, sdev->channel, sdev->id,
+			sdev->lun);
+
+		class_device_initialize(&sdev->sdev_classdev);
+		sdev->sdev_classdev.dev = &sdev->sdev_gendev;
+		sdev->sdev_classdev.class = &sdev_class;
+		snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE,
+			 "%d:%d:%d:%d", sdev->host->host_no,
+			 sdev->channel, sdev->id, sdev->lun);
+	} else
+		goto out_free_queue;
+
 	/*
 	 * If there are any same target siblings, add this to the
 	 * sibling list
@@ -282,24 +301,9 @@ out:
  **/
 void scsi_free_sdev(struct scsi_device *sdev)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(sdev->host->host_lock, flags);
-	list_del(&sdev->siblings);
-	list_del(&sdev->same_target_siblings);
-	spin_unlock_irqrestore(sdev->host->host_lock, flags);
-
-	if (sdev->request_queue)
-		scsi_free_queue(sdev->request_queue);
-
-	spin_lock_irqsave(sdev->host->host_lock, flags);
-	list_del(&sdev->starved_entry);
-	if (sdev->single_lun && --sdev->sdev_target->starget_refcnt == 0)
-		kfree(sdev->sdev_target);
-	spin_unlock_irqrestore(sdev->host->host_lock, flags);
-
-	kfree(sdev->inquiry);
-	kfree(sdev);
+	if (sdev->host->hostt->slave_destroy)
+		sdev->host->hostt->slave_destroy(sdev);
+	put_device(&sdev->sdev_gendev);
 }
 
 /**
@@ -642,7 +646,7 @@ static int scsi_add_lun(struct scsi_devi
 	 * register it and tell the rest of the kernel
 	 * about it.
 	 */
-	scsi_device_register(sdev);
+	scsi_sysfs_add_sdev(sdev);
 
 	return SCSI_SCAN_LUN_PRESENT;
 }
diff -puN drivers/scsi/scsi_sysfs.c~sdev_ldm_reg drivers/scsi/scsi_sysfs.c
--- scsi-bugfixes-2.6/drivers/scsi/scsi_sysfs.c~sdev_ldm_reg	Tue Nov  4 23:17:24 2003
+++ scsi-bugfixes-2.6-andmike/drivers/scsi/scsi_sysfs.c	Tue Nov  4 23:17:24 2003
@@ -115,14 +115,29 @@ static void scsi_device_cls_release(stru
 	put_device(&sdev->sdev_gendev);
 }
 
-static void scsi_device_dev_release(struct device *dev)
+void scsi_device_dev_release(struct device *dev)
 {
 	struct scsi_device *sdev;
 	struct device *parent;
+	unsigned long flags;
 
 	parent = dev->parent;
 	sdev = to_scsi_device(dev);
-	scsi_free_sdev(sdev);
+
+	spin_lock_irqsave(sdev->host->host_lock, flags);
+	list_del(&sdev->siblings);
+	list_del(&sdev->same_target_siblings);
+	list_del(&sdev->starved_entry);
+	if (sdev->single_lun && --sdev->sdev_target->starget_refcnt == 0)
+		kfree(sdev->sdev_target);
+	spin_unlock_irqrestore(sdev->host->host_lock, flags);
+
+	if (sdev->request_queue)
+		scsi_free_queue(sdev->request_queue);
+
+	kfree(sdev->inquiry);
+	kfree(sdev);
+
 	put_device(parent);
 }
 
@@ -321,29 +336,18 @@ static int attr_add(struct device *dev, 
 }
 
 /**
- * scsi_device_register - register a scsi device with the scsi bus
- * @sdev:	scsi_device to register
+ * scsi_sysfs_add_sdev - add scsi device to sysfs
+ * @sdev:	scsi_device to add
  *
  * Return value:
  * 	0 on Success / non-zero on Failure
  **/
-int scsi_device_register(struct scsi_device *sdev)
+int scsi_sysfs_add_sdev(struct scsi_device *sdev)
 {
-	int error = 0, i;
+	int error = -EINVAL, i;
 
-	set_bit(SDEV_ADD, &sdev->sdev_state);
-	device_initialize(&sdev->sdev_gendev);
-	sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d",
-		sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
-	sdev->sdev_gendev.parent = &sdev->host->shost_gendev;
-	sdev->sdev_gendev.bus = &scsi_bus_type;
-	sdev->sdev_gendev.release = scsi_device_dev_release;
-
-	class_device_initialize(&sdev->sdev_classdev);
-	sdev->sdev_classdev.dev = &sdev->sdev_gendev;
-	sdev->sdev_classdev.class = &sdev_class;
-	snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE, "%d:%d:%d:%d",
-		sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
+	if (test_and_set_bit(SDEV_ADD, &sdev->sdev_state))
+		return error;
 
 	error = device_add(&sdev->sdev_gendev);
 	if (error) {
@@ -351,8 +355,6 @@ int scsi_device_register(struct scsi_dev
 		return error;
 	}
 
-	get_device(sdev->sdev_gendev.parent);
-
 	error = class_device_add(&sdev->sdev_classdev);
 	if (error) {
 		printk(KERN_INFO "error 2\n");
@@ -396,12 +398,12 @@ clean_device:
  **/
 void scsi_remove_device(struct scsi_device *sdev)
 {
-	set_bit(SDEV_DEL, &sdev->sdev_state);
-	class_device_unregister(&sdev->sdev_classdev);
-	if (sdev->host->hostt->slave_destroy)
-		sdev->host->hostt->slave_destroy(sdev);
-	device_del(&sdev->sdev_gendev);
-	put_device(&sdev->sdev_gendev);
+	if (test_and_clear_bit(SDEV_ADD, &sdev->sdev_state)) {
+		set_bit(SDEV_DEL, &sdev->sdev_state);
+		class_device_unregister(&sdev->sdev_classdev);
+		device_del(&sdev->sdev_gendev);
+		scsi_free_sdev(sdev);
+	}
 }
 
 int scsi_register_driver(struct device_driver *drv)

_

  parent reply	other threads:[~2003-11-06  9:01 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-10-29 17:07 [PATCH] sym53c8xx PPR negotiation fix Doug Ledford
2003-10-29 17:11 ` James Bottomley
2003-10-29 17:50   ` Matthew Wilcox
2003-10-29 18:02     ` Doug Ledford
     [not found]       ` <20031029183159.GE25237@parcelfarce.linux.theplanet.co.uk>
2003-10-29 18:45         ` Doug Ledford
2003-10-31 23:55           ` Justin T. Gibbs
2003-10-31 23:55             ` James Bottomley
2003-11-01  0:08               ` Doug Ledford
2003-11-01  0:16                 ` Justin T. Gibbs
2003-11-01  1:22                   ` Mike Anderson
2003-11-01  2:34                     ` James Bottomley
2003-11-01  3:09                       ` Doug Ledford
2003-11-03 18:10                       ` Mike Anderson
2003-11-04  7:10                         ` Christoph Hellwig
2003-11-05  9:26                           ` Mike Anderson
2003-11-06  9:04                           ` Mike Anderson [this message]
2003-11-06  9:07                             ` Christoph Hellwig
2003-11-06  9:21                               ` Mike Anderson
2003-11-01  0:02             ` Doug Ledford

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=20031106090408.GA1398@beaverton.ibm.com \
    --to=andmike@us.ibm.com \
    --cc=James.Bottomley@steeleye.com \
    --cc=dledford@redhat.com \
    --cc=gibbs@scsiguy.com \
    --cc=hch@infradead.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=marcelo@conectiva.com.br \
    --cc=willy@debian.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox