b233244
From 26d61e8347b27a981d647d3ea4ec8c7f462c1fcf Mon Sep 17 00:00:00 2001
b233244
From: Alan Stern <stern@rowland.harvard.edu>
b233244
Date: Mon, 3 Aug 2015 11:57:21 -0400
b233244
Subject: [PATCH 1/2] SCSI: refactor device-matching code in scsi_devinfo.c
b233244
b233244
In drivers/scsi/scsi_devinfo.c, the scsi_dev_info_list_del_keyed() and
b233244
scsi_get_device_flags_keyed() routines contain a large amount of
b233244
duplicate code for finding vendor/product matches in a
b233244
scsi_dev_info_list.  This patch factors out the duplicate code and
b233244
puts it in a separate function, scsi_dev_info_list_find().
b233244
b233244
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
b233244
Suggested-by: Giulio Bernardi <ugilio@gmail.com>
b233244
Signed-off-by: James Bottomley <JBottomley@Odin.com>
b233244
---
b233244
 drivers/scsi/scsi_devinfo.c | 112 ++++++++++++++++----------------------------
b233244
 1 file changed, 41 insertions(+), 71 deletions(-)
b233244
b233244
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
b233244
index 9f77d23239a2..2f49a224462d 100644
b233244
--- a/drivers/scsi/scsi_devinfo.c
b233244
+++ b/drivers/scsi/scsi_devinfo.c
b233244
@@ -390,25 +390,26 @@ int scsi_dev_info_list_add_keyed(int compatible, char *vendor, char *model,
b233244
 EXPORT_SYMBOL(scsi_dev_info_list_add_keyed);
b233244
 
b233244
 /**
b233244
- * scsi_dev_info_list_del_keyed - remove one dev_info list entry.
b233244
+ * scsi_dev_info_list_find - find a matching dev_info list entry.
b233244
  * @vendor:	vendor string
b233244
  * @model:	model (product) string
b233244
  * @key:	specify list to use
b233244
  *
b233244
  * Description:
b233244
- * 	Remove and destroy one dev_info entry for @vendor, @model
b233244
+ *	Finds the first dev_info entry matching @vendor, @model
b233244
  * 	in list specified by @key.
b233244
  *
b233244
- * Returns: 0 OK, -error on failure.
b233244
+ * Returns: pointer to matching entry, or ERR_PTR on failure.
b233244
  **/
b233244
-int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key)
b233244
+static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor,
b233244
+		const char *model, int key)
b233244
 {
b233244
-	struct scsi_dev_info_list *devinfo, *found = NULL;
b233244
+	struct scsi_dev_info_list *devinfo;
b233244
 	struct scsi_dev_info_list_table *devinfo_table =
b233244
 		scsi_devinfo_lookup_by_key(key);
b233244
 
b233244
 	if (IS_ERR(devinfo_table))
b233244
-		return PTR_ERR(devinfo_table);
b233244
+		return (struct scsi_dev_info_list *) devinfo_table;
b233244
 
b233244
 	list_for_each_entry(devinfo, &devinfo_table->scsi_dev_info_list,
b233244
 			    dev_info_list) {
b233244
@@ -452,25 +453,42 @@ int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key)
b233244
 			if (memcmp(devinfo->model, model,
b233244
 				   min(max, strlen(devinfo->model))))
b233244
 				continue;
b233244
-			found = devinfo;
b233244
+			return devinfo;
b233244
 		} else {
b233244
 			if (!memcmp(devinfo->vendor, vendor,
b233244
 				     sizeof(devinfo->vendor)) &&
b233244
 			     !memcmp(devinfo->model, model,
b233244
 				      sizeof(devinfo->model)))
b233244
-				found = devinfo;
b233244
+				return devinfo;
b233244
 		}
b233244
-		if (found)
b233244
-			break;
b233244
 	}
b233244
 
b233244
-	if (found) {
b233244
-		list_del(&found->dev_info_list);
b233244
-		kfree(found);
b233244
-		return 0;
b233244
-	}
b233244
+	return ERR_PTR(-ENOENT);
b233244
+}
b233244
+
b233244
+/**
b233244
+ * scsi_dev_info_list_del_keyed - remove one dev_info list entry.
b233244
+ * @vendor:	vendor string
b233244
+ * @model:	model (product) string
b233244
+ * @key:	specify list to use
b233244
+ *
b233244
+ * Description:
b233244
+ *	Remove and destroy one dev_info entry for @vendor, @model
b233244
+ *	in list specified by @key.
b233244
+ *
b233244
+ * Returns: 0 OK, -error on failure.
b233244
+ **/
b233244
+int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key)
b233244
+{
b233244
+	struct scsi_dev_info_list *found;
b233244
 
b233244
-	return -ENOENT;
b233244
+	found = scsi_dev_info_list_find(vendor, model, key);
b233244
+	if (IS_ERR(found))
b233244
+		return PTR_ERR(found);
b233244
+
b233244
+	list_del(&found->dev_info_list);
b233244
+	kfree(found);
b233244
+	return 0;
b233244
 }
b233244
 EXPORT_SYMBOL(scsi_dev_info_list_del_keyed);
b233244
 
b233244
@@ -565,64 +583,16 @@ int scsi_get_device_flags_keyed(struct scsi_device *sdev,
b233244
 				int key)
b233244
 {
b233244
 	struct scsi_dev_info_list *devinfo;
b233244
-	struct scsi_dev_info_list_table *devinfo_table;
b233244
+	int err;
b233244
 
b233244
-	devinfo_table = scsi_devinfo_lookup_by_key(key);
b233244
+	devinfo = scsi_dev_info_list_find(vendor, model, key);
b233244
+	if (!IS_ERR(devinfo))
b233244
+		return devinfo->flags;
b233244
 
b233244
-	if (IS_ERR(devinfo_table))
b233244
-		return PTR_ERR(devinfo_table);
b233244
+	err = PTR_ERR(devinfo);
b233244
+	if (err != -ENOENT)
b233244
+		return err;
b233244
 
b233244
-	list_for_each_entry(devinfo, &devinfo_table->scsi_dev_info_list,
b233244
-			    dev_info_list) {
b233244
-		if (devinfo->compatible) {
b233244
-			/*
b233244
-			 * Behave like the older version of get_device_flags.
b233244
-			 */
b233244
-			size_t max;
b233244
-			/*
b233244
-			 * XXX why skip leading spaces? If an odd INQUIRY
b233244
-			 * value, that should have been part of the
b233244
-			 * scsi_static_device_list[] entry, such as "  FOO"
b233244
-			 * rather than "FOO". Since this code is already
b233244
-			 * here, and we don't know what device it is
b233244
-			 * trying to work with, leave it as-is.
b233244
-			 */
b233244
-			max = 8;	/* max length of vendor */
b233244
-			while ((max > 0) && *vendor == ' ') {
b233244
-				max--;
b233244
-				vendor++;
b233244
-			}
b233244
-			/*
b233244
-			 * XXX removing the following strlen() would be
b233244
-			 * good, using it means that for a an entry not in
b233244
-			 * the list, we scan every byte of every vendor
b233244
-			 * listed in scsi_static_device_list[], and never match
b233244
-			 * a single one (and still have to compare at
b233244
-			 * least the first byte of each vendor).
b233244
-			 */
b233244
-			if (memcmp(devinfo->vendor, vendor,
b233244
-				    min(max, strlen(devinfo->vendor))))
b233244
-				continue;
b233244
-			/*
b233244
-			 * Skip spaces again.
b233244
-			 */
b233244
-			max = 16;	/* max length of model */
b233244
-			while ((max > 0) && *model == ' ') {
b233244
-				max--;
b233244
-				model++;
b233244
-			}
b233244
-			if (memcmp(devinfo->model, model,
b233244
-				   min(max, strlen(devinfo->model))))
b233244
-				continue;
b233244
-			return devinfo->flags;
b233244
-		} else {
b233244
-			if (!memcmp(devinfo->vendor, vendor,
b233244
-				     sizeof(devinfo->vendor)) &&
b233244
-			     !memcmp(devinfo->model, model,
b233244
-				      sizeof(devinfo->model)))
b233244
-				return devinfo->flags;
b233244
-		}
b233244
-	}
b233244
 	/* nothing found, return nothing */
b233244
 	if (key != SCSI_DEVINFO_GLOBAL)
b233244
 		return 0;
b233244
-- 
b233244
2.5.0
b233244