Re: [PATCH 1/1] Remove LUNs that no longer exist when we scan a target with REPORT LUNS.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sunday 15 August 2010 20:08:33 realrichardsharpe@xxxxxxxxx wrote:
> From: Richard Sharpe <realrichardsharpe@xxxxxxxxx>
>
> 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.

What happens if you stack the device? Say you got multipath on top of this or 
device-mapper? Does this work properly ? For multipath I would expect it to 
work OK, and multipath device would queue the I/O until a LUN with the same 
SCSI_ID would reappear.
>
> Signed-off-by: Richard Sharpe <realrichardsharpe@xxxxxxxxx>
> ---
>  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;


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux