linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: realrichardsharpe@gmail.com
To: linux-scsi@vger.kernel.org
Cc: Richard Sharpe <realrichardsharpe@gmail.com>
Subject: [PATCH 1/1] Remove LUNs that no longer exist when we scan a target with REPORT LUNS.
Date: Sun, 15 Aug 2010 17:08:33 -0700	[thread overview]
Message-ID: <1281917313-1855-2-git-send-email-realrichardsharpe@gmail.com> (raw)
In-Reply-To: <1281917313-1855-1-git-send-email-realrichardsharpe@gmail.com>

From: Richard Sharpe <realrichardsharpe@gmail.com>

If the target returns logical_unit_not_supported when we send REPORT LUNS
it means that it supports REPORT LUNS but there really are no LUNs there.
Delete LUN 0 in that case.

Also, when parsing the LUNs reported, remove any LUNs that used to exist
in the gaps, and remove LUNs beyond the end of those reported. They no
longer exist.

Also don't scan a target where the ID is too large or the channel is
too large.

Tested by adding four LUNs with scst_local and then deleting them in
various combinations, including deleting from LUN 0, deleting from last
LUN and deleting in the middle out.

Signed-off-by: Richard Sharpe <realrichardsharpe@gmail.com>
---
 drivers/scsi/scsi_scan.c |   65 +++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 62 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 1c027a9..d0f5d30 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -1309,7 +1309,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
 	char devname[64];
 	unsigned char scsi_cmd[MAX_COMMAND_SIZE];
 	unsigned int length;
-	unsigned int lun;
+	unsigned int lun, old_lun = 0;
 	unsigned int num_luns;
 	unsigned int retries;
 	int result;
@@ -1410,6 +1410,22 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
 		if (result == 0)
 			break;
 		else if (scsi_sense_valid(&sshdr)) {
+			/* 
+			 * This is awful. We should use a named constant!
+			 * If the target returns logical_unit_not_supported
+			 * then there really are zero LUNs there, so delete
+			 * LUN 0 if it exists. 
+			 */
+			if (sshdr.asc == 0x25) {
+				struct scsi_device *sdev = NULL;
+				sdev = scsi_device_lookup_by_target(starget, 0);
+				if (sdev) {
+					scsi_device_put(sdev);
+					__scsi_remove_device(sdev);
+					SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
+						"Removing LUN 0\n"));
+				}
+			}
 			if (sshdr.sense_key != UNIT_ATTENTION)
 				break;
 		}
@@ -1473,6 +1489,27 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
 		} else {
 			int res;
 
+			/*
+			 * First, check for and remove any missing LUNs, as
+			 * they have been removed on the target.
+			 */
+			if (lun > old_lun + 1) {
+				unsigned int i;
+				for (i = old_lun + 1; i < lun; i++) {
+					struct scsi_device *sdev;
+					sdev = scsi_device_lookup_by_target(
+							starget, i);
+					if (sdev) {
+						scsi_device_put(sdev);
+						__scsi_remove_device(sdev);
+						SCSI_LOG_SCAN_BUS(3, 
+							printk(KERN_INFO
+							"Removing LUN %d\n", 
+							i));
+					}
+				}
+			}
+
 			res = scsi_probe_and_add_lun(starget,
 				lun, NULL, NULL, rescan, NULL);
 			if (res == SCSI_SCAN_NO_RESPONSE) {
@@ -1485,6 +1522,26 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
 				        " aborted\n", lun);
 				break;
 			}
+
+			old_lun = lun;
+		}
+	}
+
+	/*
+	 * Remove any device that no longer exist. Does not work for LUN 0.
+	 * See above.
+	 */
+	if (lun < shost->max_lun) {
+		int i = 0;
+		for (i = lun + 1; i < shost->max_lun; i++) {
+			struct scsi_device *sdev;
+			sdev = scsi_device_lookup_by_target(starget, i);
+			if (sdev) {
+				scsi_device_put(sdev);
+				__scsi_remove_device(sdev);
+				SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
+					"Removed LUN %d\n", i));
+			}
 		}
 	}
 
@@ -1565,9 +1622,11 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel,
 	int res;
 	struct scsi_target *starget;
 
-	if (shost->this_id == id)
+	if (shost->this_id == id ||
+		id > shost->max_id ||
+		channel > shost->max_channel)
 		/*
-		 * Don't scan the host adapter
+		 * Don't scan the host adapter or dis-allowed ones.
 		 */
 		return;
 
-- 
1.6.6.1


  reply	other threads:[~2010-08-16  0:09 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-08-16  0:08 (unknown), realrichardsharpe
2010-08-16  0:08 ` realrichardsharpe [this message]
2010-08-16 13:45   ` [PATCH 1/1] Remove LUNs that no longer exist when we scan a target with REPORT LUNS Konrad Rzeszutek Wilk
2010-08-16 13:59     ` Richard Sharpe
2010-08-16 14:58       ` Konrad Rzeszutek Wilk
2010-08-18 15:37     ` Loke, Chetan
2010-08-18 15:10   ` Richard Sharpe
2010-08-18 15:13     ` James Bottomley
2010-08-20  2:59       ` Richard Sharpe

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=1281917313-1855-2-git-send-email-realrichardsharpe@gmail.com \
    --to=realrichardsharpe@gmail.com \
    --cc=linux-scsi@vger.kernel.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;
as well as URLs for NNTP newsgroup(s).