diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2011-10-06 04:56:57 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-10-20 11:10:07 -0400 |
commit | 8d4a690cd4f574bcb70c2cb89c227ba89a51351f (patch) | |
tree | d1a0da50cc35e363aed3bf62c80d26029549bca4 /drivers/scsi/scsi_transport_iscsi.c | |
parent | dc55b8274daddffefc34026ed7924138c8c5df17 (diff) |
[SCSI] iscsi class: Replace iscsi_get_next_target_id with IDA
Replaced the iscsi_get_next_target_id with IDA to make
target-id allocation efficient for iscsi offload drivers
This patch should be applied after Jonathen Cameron Patch
"ida : simplified functions for id allocation"
Signed-off-by: John Soni Jose <jose0here@gmail.com>
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/scsi_transport_iscsi.c')
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 59 |
1 files changed, 23 insertions, 36 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index c58f6766f4c7..d746c351588f 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/mutex.h> | 24 | #include <linux/mutex.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/bsg-lib.h> | 26 | #include <linux/bsg-lib.h> |
27 | #include <linux/idr.h> | ||
27 | #include <net/tcp.h> | 28 | #include <net/tcp.h> |
28 | #include <scsi/scsi.h> | 29 | #include <scsi/scsi.h> |
29 | #include <scsi/scsi_host.h> | 30 | #include <scsi/scsi_host.h> |
@@ -81,6 +82,7 @@ struct iscsi_internal { | |||
81 | static atomic_t iscsi_session_nr; /* sysfs session id for next new session */ | 82 | static atomic_t iscsi_session_nr; /* sysfs session id for next new session */ |
82 | static struct workqueue_struct *iscsi_eh_timer_workq; | 83 | static struct workqueue_struct *iscsi_eh_timer_workq; |
83 | 84 | ||
85 | static DEFINE_IDA(iscsi_sess_ida); | ||
84 | /* | 86 | /* |
85 | * list of registered transports and lock that must | 87 | * list of registered transports and lock that must |
86 | * be held while accessing list. The iscsi_transport_lock must | 88 | * be held while accessing list. The iscsi_transport_lock must |
@@ -990,6 +992,7 @@ static void __iscsi_unbind_session(struct work_struct *work) | |||
990 | struct Scsi_Host *shost = iscsi_session_to_shost(session); | 992 | struct Scsi_Host *shost = iscsi_session_to_shost(session); |
991 | struct iscsi_cls_host *ihost = shost->shost_data; | 993 | struct iscsi_cls_host *ihost = shost->shost_data; |
992 | unsigned long flags; | 994 | unsigned long flags; |
995 | unsigned int target_id; | ||
993 | 996 | ||
994 | ISCSI_DBG_TRANS_SESSION(session, "Unbinding session\n"); | 997 | ISCSI_DBG_TRANS_SESSION(session, "Unbinding session\n"); |
995 | 998 | ||
@@ -1001,10 +1004,15 @@ static void __iscsi_unbind_session(struct work_struct *work) | |||
1001 | mutex_unlock(&ihost->mutex); | 1004 | mutex_unlock(&ihost->mutex); |
1002 | return; | 1005 | return; |
1003 | } | 1006 | } |
1007 | |||
1008 | target_id = session->target_id; | ||
1004 | session->target_id = ISCSI_MAX_TARGET; | 1009 | session->target_id = ISCSI_MAX_TARGET; |
1005 | spin_unlock_irqrestore(&session->lock, flags); | 1010 | spin_unlock_irqrestore(&session->lock, flags); |
1006 | mutex_unlock(&ihost->mutex); | 1011 | mutex_unlock(&ihost->mutex); |
1007 | 1012 | ||
1013 | if (session->ida_used) | ||
1014 | ida_simple_remove(&iscsi_sess_ida, target_id); | ||
1015 | |||
1008 | scsi_remove_target(&session->dev); | 1016 | scsi_remove_target(&session->dev); |
1009 | iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION); | 1017 | iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION); |
1010 | ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n"); | 1018 | ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n"); |
@@ -1045,59 +1053,36 @@ iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport, | |||
1045 | } | 1053 | } |
1046 | EXPORT_SYMBOL_GPL(iscsi_alloc_session); | 1054 | EXPORT_SYMBOL_GPL(iscsi_alloc_session); |
1047 | 1055 | ||
1048 | static int iscsi_get_next_target_id(struct device *dev, void *data) | ||
1049 | { | ||
1050 | struct iscsi_cls_session *session; | ||
1051 | unsigned long flags; | ||
1052 | int err = 0; | ||
1053 | |||
1054 | if (!iscsi_is_session_dev(dev)) | ||
1055 | return 0; | ||
1056 | |||
1057 | session = iscsi_dev_to_session(dev); | ||
1058 | spin_lock_irqsave(&session->lock, flags); | ||
1059 | if (*((unsigned int *) data) == session->target_id) | ||
1060 | err = -EEXIST; | ||
1061 | spin_unlock_irqrestore(&session->lock, flags); | ||
1062 | return err; | ||
1063 | } | ||
1064 | |||
1065 | int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) | 1056 | int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) |
1066 | { | 1057 | { |
1067 | struct Scsi_Host *shost = iscsi_session_to_shost(session); | 1058 | struct Scsi_Host *shost = iscsi_session_to_shost(session); |
1068 | struct iscsi_cls_host *ihost; | 1059 | struct iscsi_cls_host *ihost; |
1069 | unsigned long flags; | 1060 | unsigned long flags; |
1070 | unsigned int id = target_id; | 1061 | int id = 0; |
1071 | int err; | 1062 | int err; |
1072 | 1063 | ||
1073 | ihost = shost->shost_data; | 1064 | ihost = shost->shost_data; |
1074 | session->sid = atomic_add_return(1, &iscsi_session_nr); | 1065 | session->sid = atomic_add_return(1, &iscsi_session_nr); |
1075 | 1066 | ||
1076 | if (id == ISCSI_MAX_TARGET) { | 1067 | if (target_id == ISCSI_MAX_TARGET) { |
1077 | for (id = 0; id < ISCSI_MAX_TARGET; id++) { | 1068 | id = ida_simple_get(&iscsi_sess_ida, 0, 0, GFP_KERNEL); |
1078 | err = device_for_each_child(&shost->shost_gendev, &id, | ||
1079 | iscsi_get_next_target_id); | ||
1080 | if (!err) | ||
1081 | break; | ||
1082 | } | ||
1083 | 1069 | ||
1084 | if (id == ISCSI_MAX_TARGET) { | 1070 | if (id < 0) { |
1085 | iscsi_cls_session_printk(KERN_ERR, session, | 1071 | iscsi_cls_session_printk(KERN_ERR, session, |
1086 | "Too many iscsi targets. Max " | 1072 | "Failure in Target ID Allocation\n"); |
1087 | "number of targets is %d.\n", | 1073 | return id; |
1088 | ISCSI_MAX_TARGET - 1); | ||
1089 | err = -EOVERFLOW; | ||
1090 | goto release_host; | ||
1091 | } | 1074 | } |
1092 | } | 1075 | session->target_id = (unsigned int)id; |
1093 | session->target_id = id; | 1076 | session->ida_used = true; |
1077 | } else | ||
1078 | session->target_id = target_id; | ||
1094 | 1079 | ||
1095 | dev_set_name(&session->dev, "session%u", session->sid); | 1080 | dev_set_name(&session->dev, "session%u", session->sid); |
1096 | err = device_add(&session->dev); | 1081 | err = device_add(&session->dev); |
1097 | if (err) { | 1082 | if (err) { |
1098 | iscsi_cls_session_printk(KERN_ERR, session, | 1083 | iscsi_cls_session_printk(KERN_ERR, session, |
1099 | "could not register session's dev\n"); | 1084 | "could not register session's dev\n"); |
1100 | goto release_host; | 1085 | goto release_ida; |
1101 | } | 1086 | } |
1102 | transport_register_device(&session->dev); | 1087 | transport_register_device(&session->dev); |
1103 | 1088 | ||
@@ -1109,8 +1094,10 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) | |||
1109 | ISCSI_DBG_TRANS_SESSION(session, "Completed session adding\n"); | 1094 | ISCSI_DBG_TRANS_SESSION(session, "Completed session adding\n"); |
1110 | return 0; | 1095 | return 0; |
1111 | 1096 | ||
1112 | release_host: | 1097 | release_ida: |
1113 | scsi_host_put(shost); | 1098 | if (session->ida_used) |
1099 | ida_simple_remove(&iscsi_sess_ida, session->target_id); | ||
1100 | |||
1114 | return err; | 1101 | return err; |
1115 | } | 1102 | } |
1116 | EXPORT_SYMBOL_GPL(iscsi_add_session); | 1103 | EXPORT_SYMBOL_GPL(iscsi_add_session); |