|
@@ -24,6 +24,7 @@
|
|
#include <linux/mutex.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/bsg-lib.h>
|
|
#include <linux/bsg-lib.h>
|
|
|
|
+#include <linux/idr.h>
|
|
#include <net/tcp.h>
|
|
#include <net/tcp.h>
|
|
#include <scsi/scsi.h>
|
|
#include <scsi/scsi.h>
|
|
#include <scsi/scsi_host.h>
|
|
#include <scsi/scsi_host.h>
|
|
@@ -81,6 +82,7 @@ struct iscsi_internal {
|
|
static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
|
|
static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
|
|
static struct workqueue_struct *iscsi_eh_timer_workq;
|
|
static struct workqueue_struct *iscsi_eh_timer_workq;
|
|
|
|
|
|
|
|
+static DEFINE_IDA(iscsi_sess_ida);
|
|
/*
|
|
/*
|
|
* list of registered transports and lock that must
|
|
* list of registered transports and lock that must
|
|
* be held while accessing list. The iscsi_transport_lock must
|
|
* be held while accessing list. The iscsi_transport_lock must
|
|
@@ -990,6 +992,7 @@ static void __iscsi_unbind_session(struct work_struct *work)
|
|
struct Scsi_Host *shost = iscsi_session_to_shost(session);
|
|
struct Scsi_Host *shost = iscsi_session_to_shost(session);
|
|
struct iscsi_cls_host *ihost = shost->shost_data;
|
|
struct iscsi_cls_host *ihost = shost->shost_data;
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
|
|
+ unsigned int target_id;
|
|
|
|
|
|
ISCSI_DBG_TRANS_SESSION(session, "Unbinding session\n");
|
|
ISCSI_DBG_TRANS_SESSION(session, "Unbinding session\n");
|
|
|
|
|
|
@@ -1001,10 +1004,15 @@ static void __iscsi_unbind_session(struct work_struct *work)
|
|
mutex_unlock(&ihost->mutex);
|
|
mutex_unlock(&ihost->mutex);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ target_id = session->target_id;
|
|
session->target_id = ISCSI_MAX_TARGET;
|
|
session->target_id = ISCSI_MAX_TARGET;
|
|
spin_unlock_irqrestore(&session->lock, flags);
|
|
spin_unlock_irqrestore(&session->lock, flags);
|
|
mutex_unlock(&ihost->mutex);
|
|
mutex_unlock(&ihost->mutex);
|
|
|
|
|
|
|
|
+ if (session->ida_used)
|
|
|
|
+ ida_simple_remove(&iscsi_sess_ida, target_id);
|
|
|
|
+
|
|
scsi_remove_target(&session->dev);
|
|
scsi_remove_target(&session->dev);
|
|
iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
|
|
iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
|
|
ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n");
|
|
ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n");
|
|
@@ -1045,59 +1053,36 @@ iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(iscsi_alloc_session);
|
|
EXPORT_SYMBOL_GPL(iscsi_alloc_session);
|
|
|
|
|
|
-static int iscsi_get_next_target_id(struct device *dev, void *data)
|
|
|
|
-{
|
|
|
|
- struct iscsi_cls_session *session;
|
|
|
|
- unsigned long flags;
|
|
|
|
- int err = 0;
|
|
|
|
-
|
|
|
|
- if (!iscsi_is_session_dev(dev))
|
|
|
|
- return 0;
|
|
|
|
-
|
|
|
|
- session = iscsi_dev_to_session(dev);
|
|
|
|
- spin_lock_irqsave(&session->lock, flags);
|
|
|
|
- if (*((unsigned int *) data) == session->target_id)
|
|
|
|
- err = -EEXIST;
|
|
|
|
- spin_unlock_irqrestore(&session->lock, flags);
|
|
|
|
- return err;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
|
|
int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
|
|
{
|
|
{
|
|
struct Scsi_Host *shost = iscsi_session_to_shost(session);
|
|
struct Scsi_Host *shost = iscsi_session_to_shost(session);
|
|
struct iscsi_cls_host *ihost;
|
|
struct iscsi_cls_host *ihost;
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
- unsigned int id = target_id;
|
|
|
|
|
|
+ int id = 0;
|
|
int err;
|
|
int err;
|
|
|
|
|
|
ihost = shost->shost_data;
|
|
ihost = shost->shost_data;
|
|
session->sid = atomic_add_return(1, &iscsi_session_nr);
|
|
session->sid = atomic_add_return(1, &iscsi_session_nr);
|
|
|
|
|
|
- if (id == ISCSI_MAX_TARGET) {
|
|
|
|
- for (id = 0; id < ISCSI_MAX_TARGET; id++) {
|
|
|
|
- err = device_for_each_child(&shost->shost_gendev, &id,
|
|
|
|
- iscsi_get_next_target_id);
|
|
|
|
- if (!err)
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
|
|
+ if (target_id == ISCSI_MAX_TARGET) {
|
|
|
|
+ id = ida_simple_get(&iscsi_sess_ida, 0, 0, GFP_KERNEL);
|
|
|
|
|
|
- if (id == ISCSI_MAX_TARGET) {
|
|
|
|
|
|
+ if (id < 0) {
|
|
iscsi_cls_session_printk(KERN_ERR, session,
|
|
iscsi_cls_session_printk(KERN_ERR, session,
|
|
- "Too many iscsi targets. Max "
|
|
|
|
- "number of targets is %d.\n",
|
|
|
|
- ISCSI_MAX_TARGET - 1);
|
|
|
|
- err = -EOVERFLOW;
|
|
|
|
- goto release_host;
|
|
|
|
|
|
+ "Failure in Target ID Allocation\n");
|
|
|
|
+ return id;
|
|
}
|
|
}
|
|
- }
|
|
|
|
- session->target_id = id;
|
|
|
|
|
|
+ session->target_id = (unsigned int)id;
|
|
|
|
+ session->ida_used = true;
|
|
|
|
+ } else
|
|
|
|
+ session->target_id = target_id;
|
|
|
|
|
|
dev_set_name(&session->dev, "session%u", session->sid);
|
|
dev_set_name(&session->dev, "session%u", session->sid);
|
|
err = device_add(&session->dev);
|
|
err = device_add(&session->dev);
|
|
if (err) {
|
|
if (err) {
|
|
iscsi_cls_session_printk(KERN_ERR, session,
|
|
iscsi_cls_session_printk(KERN_ERR, session,
|
|
"could not register session's dev\n");
|
|
"could not register session's dev\n");
|
|
- goto release_host;
|
|
|
|
|
|
+ goto release_ida;
|
|
}
|
|
}
|
|
transport_register_device(&session->dev);
|
|
transport_register_device(&session->dev);
|
|
|
|
|
|
@@ -1109,8 +1094,10 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
|
|
ISCSI_DBG_TRANS_SESSION(session, "Completed session adding\n");
|
|
ISCSI_DBG_TRANS_SESSION(session, "Completed session adding\n");
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
-release_host:
|
|
|
|
- scsi_host_put(shost);
|
|
|
|
|
|
+release_ida:
|
|
|
|
+ if (session->ida_used)
|
|
|
|
+ ida_simple_remove(&iscsi_sess_ida, session->target_id);
|
|
|
|
+
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(iscsi_add_session);
|
|
EXPORT_SYMBOL_GPL(iscsi_add_session);
|