aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_iscsi.c
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2011-10-06 04:56:57 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-10-20 11:10:07 -0400
commit8d4a690cd4f574bcb70c2cb89c227ba89a51351f (patch)
treed1a0da50cc35e363aed3bf62c80d26029549bca4 /drivers/scsi/scsi_transport_iscsi.c
parentdc55b8274daddffefc34026ed7924138c8c5df17 (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.c59
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 {
81static atomic_t iscsi_session_nr; /* sysfs session id for next new session */ 82static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
82static struct workqueue_struct *iscsi_eh_timer_workq; 83static struct workqueue_struct *iscsi_eh_timer_workq;
83 84
85static 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}
1046EXPORT_SYMBOL_GPL(iscsi_alloc_session); 1054EXPORT_SYMBOL_GPL(iscsi_alloc_session);
1047 1055
1048static 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
1065int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) 1056int 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
1112release_host: 1097release_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}
1116EXPORT_SYMBOL_GPL(iscsi_add_session); 1103EXPORT_SYMBOL_GPL(iscsi_add_session);