* [PATCH 8/8] scsi_dh: create lookup cache
@ 2008-07-17 7:39 Hannes Reinecke
0 siblings, 0 replies; 2+ messages in thread
From: Hannes Reinecke @ 2008-07-17 7:39 UTC (permalink / raw)
To: James Bottomley; +Cc: linux-scsi
Create a cache of devices that are seen in a system. This will avoid
the unnecessary traversal of the device list in the scsi_dh when there
are multiple luns of a same type.
Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/scsi/device_handler/scsi_dh.c | 129 +++++++++++++++++++++++++++------
1 files changed, 105 insertions(+), 24 deletions(-)
diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c
index a915968..a518f2e 100644
--- a/drivers/scsi/device_handler/scsi_dh.c
+++ b/drivers/scsi/device_handler/scsi_dh.c
@@ -24,8 +24,16 @@
#include <scsi/scsi_dh.h>
#include "../scsi_priv.h"
+struct scsi_dh_devinfo_list {
+ struct list_head node;
+ char vendor[9];
+ char model[17];
+ struct scsi_device_handler *handler;
+};
+
static DEFINE_SPINLOCK(list_lock);
static LIST_HEAD(scsi_dh_list);
+static LIST_HEAD(scsi_dh_dev_list);
static struct scsi_device_handler *get_device_handler(const char *name)
{
@@ -42,21 +50,94 @@ static struct scsi_device_handler *get_device_handler(const char *name)
return found;
}
-static int device_handler_match(struct scsi_device_handler *tmp,
- struct scsi_device *sdev)
+
+static struct scsi_device_handler *
+scsi_dh_cache_lookup(struct scsi_device *sdev)
{
- int i;
-
- for(i = 0; tmp->devlist[i].vendor; i++) {
- if (!strncmp(sdev->vendor, tmp->devlist[i].vendor,
- strlen(tmp->devlist[i].vendor)) &&
- !strncmp(sdev->model, tmp->devlist[i].model,
- strlen(tmp->devlist[i].model))) {
- return 1;
+ struct scsi_dh_devinfo_list *tmp;
+ struct scsi_device_handler *found_dh = NULL;
+
+ spin_lock(&list_lock);
+ list_for_each_entry(tmp, &scsi_dh_dev_list, node) {
+ if (!strncmp(sdev->vendor, tmp->vendor, strlen(tmp->vendor)) &&
+ !strncmp(sdev->model, tmp->model, strlen(tmp->model))) {
+ found_dh = tmp->handler;
+ break;
}
}
+ spin_unlock(&list_lock);
- return 0;
+ return found_dh;
+}
+
+static int scsi_dh_handler_lookup(struct scsi_device_handler *scsi_dh,
+ struct scsi_device *sdev)
+{
+ int i, found = 0;
+
+ for(i = 0; scsi_dh->devlist[i].vendor; i++) {
+ if (!strncmp(sdev->vendor, scsi_dh->devlist[i].vendor,
+ strlen(scsi_dh->devlist[i].vendor)) &&
+ !strncmp(sdev->model, scsi_dh->devlist[i].model,
+ strlen(scsi_dh->devlist[i].model))) {
+ found = 1;
+ break;
+ }
+ }
+ return found;
+}
+
+/*
+ * device_handler_match - Attach a device handler to a device
+ * @scsi_dh - The device handler to match against or NULL
+ * @sdev - SCSI device to be tested against @scsi_dh
+ *
+ * Tests @sdev against the device handler @scsi_dh or against
+ * all registered device_handler if @scsi_dh == NULL.
+ * Returns the found device handler or NULL if not found.
+ */
+static struct scsi_device_handler *
+device_handler_match(struct scsi_device_handler *scsi_dh,
+ struct scsi_device *sdev)
+{
+ struct scsi_device_handler *found_dh = NULL;
+ struct scsi_dh_devinfo_list *tmp;
+
+ found_dh = scsi_dh_cache_lookup(sdev);
+ if (found_dh)
+ return found_dh;
+
+ if (scsi_dh) {
+ if (scsi_dh_handler_lookup(scsi_dh, sdev))
+ found_dh = scsi_dh;
+ } else {
+ struct scsi_device_handler *tmp_dh;
+
+ spin_lock(&list_lock);
+ list_for_each_entry(tmp_dh, &scsi_dh_list, list) {
+ if (scsi_dh_handler_lookup(tmp_dh, sdev))
+ found_dh = tmp_dh;
+ }
+ spin_unlock(&list_lock);
+ }
+
+ if (found_dh) { /* If device is found, add it to the cache */
+ tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
+ if (tmp) {
+ strncpy(tmp->vendor, sdev->vendor, 8);
+ strncpy(tmp->model, sdev->model, 16);
+ tmp->vendor[8] = '\0';
+ tmp->model[16] = '\0';
+ tmp->handler = found_dh;
+ spin_lock(&list_lock);
+ list_add(&tmp->node, &scsi_dh_dev_list);
+ spin_unlock(&list_lock);
+ } else {
+ found_dh = NULL;
+ }
+ }
+
+ return found_dh;
}
/*
@@ -203,26 +284,18 @@ static int scsi_dh_notifier(struct notifier_block *nb,
struct device *dev = data;
struct scsi_device *sdev;
int err = 0;
- struct scsi_device_handler *tmp, *devinfo = NULL;
+ struct scsi_device_handler *devinfo = NULL;
if (!scsi_is_sdev_device(dev))
return 0;
sdev = to_scsi_device(dev);
- spin_lock(&list_lock);
- list_for_each_entry(tmp, &scsi_dh_list, list) {
- if (device_handler_match(tmp, sdev)) {
- devinfo = tmp;
- break;
- }
- }
- spin_unlock(&list_lock);
-
- if (!devinfo)
- goto out;
-
if (action == BUS_NOTIFY_ADD_DEVICE) {
+ devinfo = device_handler_match(NULL, sdev);
+ if (!devinfo)
+ goto out;
+
err = scsi_dh_handler_attach(sdev, devinfo);
if (!err)
err = device_create_file(dev, &scsi_dh_state_attr);
@@ -312,6 +385,8 @@ EXPORT_SYMBOL_GPL(scsi_register_device_handler);
*/
int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
{
+ struct scsi_dh_devinfo_list *tmp, *pos;
+
if (!get_device_handler(scsi_dh->name))
return -ENODEV;
@@ -320,6 +395,12 @@ int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
spin_lock(&list_lock);
list_del(&scsi_dh->list);
+ list_for_each_entry_safe(pos, tmp, &scsi_dh_dev_list, node) {
+ if (pos->handler == scsi_dh) {
+ list_del(&pos->node);
+ kfree(pos);
+ }
+ }
spin_unlock(&list_lock);
printk(KERN_INFO "%s: device handler unregistered\n", scsi_dh->name);
--
1.5.2.4
^ permalink raw reply related [flat|nested] 2+ messages in thread* [PATCH 0/8] scsi_dh update
@ 2008-07-17 23:52 Chandra Seetharaman
2008-07-17 23:53 ` [PATCH 8/8] scsi_dh: create lookup cache Chandra Seetharaman
0 siblings, 1 reply; 2+ messages in thread
From: Chandra Seetharaman @ 2008-07-17 23:52 UTC (permalink / raw)
To: James.Bottomley, hare, linux-scsi; +Cc: dm-devel
Hi James, Hannes,
These are the same set of patches that Hannes sent early this morning with the
prelog below.
I just ported it to compile clean on top of 2.6.26-git6.
Made 3 additional changes:
1. Added a break under MODE_SELECT option in function get_req() (in 3/8)
2. Added the ifndef portion for scsi_dh_attach() and scsi_dh_detach (in 6/8)
3. Moved the definition of SCSI_DH_DEV_UNSUPP from 6/8 to 3/8.
regards,
chandra
------ Here is the 0/8 from Hannes's original patchset. -----------
Hi James,
this is the (hopefully final) update to my scsi_dh patchset.
Features are:
- Move device-table matching into the device_handler infrastructure,
so that individual drivers don't have to implement it themselves
- Adds a 'dh_state' sysfs attribute for manually attaching device
handler to new or unknown disks; this allows to override the
internal device tables
- Update the dm-multipath code to attach the device handler
specified in the multipath configuration
- Add a cache to speed up lookup of several identical devices
- Update existing EMC, RDAC, and hp_sw device handler to use
the new infrastructure
- Add new SPC-3 ALUA device handler
The NetApp device handler has been left out for now as it's still
under development.
Please apply.
Cheers,
Hannes
--------------------------------------------------------------------
^ permalink raw reply [flat|nested] 2+ messages in thread
* [PATCH 8/8] scsi_dh: create lookup cache
2008-07-17 23:52 [PATCH 0/8] scsi_dh update Chandra Seetharaman
@ 2008-07-17 23:53 ` Chandra Seetharaman
0 siblings, 0 replies; 2+ messages in thread
From: Chandra Seetharaman @ 2008-07-17 23:53 UTC (permalink / raw)
To: James.Bottomley, hare, linux-scsi; +Cc: dm-devel
Create a cache of devices that are seen in a system. This will avoid
the unnecessary traversal of the device list in the scsi_dh when there
are multiple luns of a same type.
Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/scsi/device_handler/scsi_dh.c | 129 +++++++++++++++++++++++++++------
1 files changed, 105 insertions(+), 24 deletions(-)
Index: linux-2.6.26-git5/drivers/scsi/device_handler/scsi_dh.c
===================================================================
--- linux-2.6.26-git5.orig/drivers/scsi/device_handler/scsi_dh.c
+++ linux-2.6.26-git5/drivers/scsi/device_handler/scsi_dh.c
@@ -24,8 +24,16 @@
#include <scsi/scsi_dh.h>
#include "../scsi_priv.h"
+struct scsi_dh_devinfo_list {
+ struct list_head node;
+ char vendor[9];
+ char model[17];
+ struct scsi_device_handler *handler;
+};
+
static DEFINE_SPINLOCK(list_lock);
static LIST_HEAD(scsi_dh_list);
+static LIST_HEAD(scsi_dh_dev_list);
static struct scsi_device_handler *get_device_handler(const char *name)
{
@@ -42,21 +50,94 @@ static struct scsi_device_handler *get_d
return found;
}
-static int device_handler_match(struct scsi_device_handler *tmp,
- struct scsi_device *sdev)
+
+static struct scsi_device_handler *
+scsi_dh_cache_lookup(struct scsi_device *sdev)
{
- int i;
+ struct scsi_dh_devinfo_list *tmp;
+ struct scsi_device_handler *found_dh = NULL;
- for(i = 0; tmp->devlist[i].vendor; i++) {
- if (!strncmp(sdev->vendor, tmp->devlist[i].vendor,
- strlen(tmp->devlist[i].vendor)) &&
- !strncmp(sdev->model, tmp->devlist[i].model,
- strlen(tmp->devlist[i].model))) {
- return 1;
+ spin_lock(&list_lock);
+ list_for_each_entry(tmp, &scsi_dh_dev_list, node) {
+ if (!strncmp(sdev->vendor, tmp->vendor, strlen(tmp->vendor)) &&
+ !strncmp(sdev->model, tmp->model, strlen(tmp->model))) {
+ found_dh = tmp->handler;
+ break;
}
}
+ spin_unlock(&list_lock);
- return 0;
+ return found_dh;
+}
+
+static int scsi_dh_handler_lookup(struct scsi_device_handler *scsi_dh,
+ struct scsi_device *sdev)
+{
+ int i, found = 0;
+
+ for(i = 0; scsi_dh->devlist[i].vendor; i++) {
+ if (!strncmp(sdev->vendor, scsi_dh->devlist[i].vendor,
+ strlen(scsi_dh->devlist[i].vendor)) &&
+ !strncmp(sdev->model, scsi_dh->devlist[i].model,
+ strlen(scsi_dh->devlist[i].model))) {
+ found = 1;
+ break;
+ }
+ }
+ return found;
+}
+
+/*
+ * device_handler_match - Attach a device handler to a device
+ * @scsi_dh - The device handler to match against or NULL
+ * @sdev - SCSI device to be tested against @scsi_dh
+ *
+ * Tests @sdev against the device handler @scsi_dh or against
+ * all registered device_handler if @scsi_dh == NULL.
+ * Returns the found device handler or NULL if not found.
+ */
+static struct scsi_device_handler *
+device_handler_match(struct scsi_device_handler *scsi_dh,
+ struct scsi_device *sdev)
+{
+ struct scsi_device_handler *found_dh = NULL;
+ struct scsi_dh_devinfo_list *tmp;
+
+ found_dh = scsi_dh_cache_lookup(sdev);
+ if (found_dh)
+ return found_dh;
+
+ if (scsi_dh) {
+ if (scsi_dh_handler_lookup(scsi_dh, sdev))
+ found_dh = scsi_dh;
+ } else {
+ struct scsi_device_handler *tmp_dh;
+
+ spin_lock(&list_lock);
+ list_for_each_entry(tmp_dh, &scsi_dh_list, list) {
+ if (scsi_dh_handler_lookup(tmp_dh, sdev))
+ found_dh = tmp_dh;
+ }
+ spin_unlock(&list_lock);
+ }
+
+ if (found_dh) { /* If device is found, add it to the cache */
+ tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
+ if (tmp) {
+ strncpy(tmp->vendor, sdev->vendor, 8);
+ strncpy(tmp->model, sdev->model, 16);
+ tmp->vendor[8] = '\0';
+ tmp->model[16] = '\0';
+ tmp->handler = found_dh;
+ spin_lock(&list_lock);
+ list_add(&tmp->node, &scsi_dh_dev_list);
+ spin_unlock(&list_lock);
+ } else {
+ found_dh = NULL;
+ }
+ }
+
+ return found_dh;
}
/*
@@ -203,26 +284,18 @@ static int scsi_dh_notifier(struct notif
struct device *dev = data;
struct scsi_device *sdev;
int err = 0;
- struct scsi_device_handler *tmp, *devinfo = NULL;
+ struct scsi_device_handler *devinfo = NULL;
if (!scsi_is_sdev_device(dev))
return 0;
sdev = to_scsi_device(dev);
- spin_lock(&list_lock);
- list_for_each_entry(tmp, &scsi_dh_list, list) {
- if (device_handler_match(tmp, sdev)) {
- devinfo = tmp;
- break;
- }
- }
- spin_unlock(&list_lock);
-
- if (!devinfo)
- goto out;
-
if (action == BUS_NOTIFY_ADD_DEVICE) {
+ devinfo = device_handler_match(NULL, sdev);
+ if (!devinfo)
+ goto out;
+
err = scsi_dh_handler_attach(sdev, devinfo);
if (!err)
err = device_create_file(dev, &scsi_dh_state_attr);
@@ -312,6 +385,8 @@ EXPORT_SYMBOL_GPL(scsi_register_device_h
*/
int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
{
+ struct scsi_dh_devinfo_list *tmp, *pos;
+
if (!get_device_handler(scsi_dh->name))
return -ENODEV;
@@ -320,6 +395,12 @@ int scsi_unregister_device_handler(struc
spin_lock(&list_lock);
list_del(&scsi_dh->list);
+ list_for_each_entry_safe(pos, tmp, &scsi_dh_dev_list, node) {
+ if (pos->handler == scsi_dh) {
+ list_del(&pos->node);
+ kfree(pos);
+ }
+ }
spin_unlock(&list_lock);
printk(KERN_INFO "%s: device handler unregistered\n", scsi_dh->name);
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2008-07-17 23:53 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-17 7:39 [PATCH 8/8] scsi_dh: create lookup cache Hannes Reinecke
-- strict thread matches above, loose matches on Subject: below --
2008-07-17 23:52 [PATCH 0/8] scsi_dh update Chandra Seetharaman
2008-07-17 23:53 ` [PATCH 8/8] scsi_dh: create lookup cache Chandra Seetharaman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox