@@ -1755,17 +1755,16 @@ static DECLARE_TRANSPORT_CLASS_NS(iscsi_connection_class,
struct iscsi_net {
struct sock *nls;
+ spinlock_t sesslock;
+ struct list_head sesslist;
+ spinlock_t connlock;
+ struct list_head connlist;
+ struct list_head connlist_err;
};
static int iscsi_net_id __read_mostly;
static DEFINE_MUTEX(rx_queue_mutex);
-static LIST_HEAD(sesslist);
-static DEFINE_SPINLOCK(sesslock);
-static LIST_HEAD(connlist);
-static LIST_HEAD(connlist_err);
-static DEFINE_SPINLOCK(connlock);
-
static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn)
{
struct iscsi_cls_session *sess = iscsi_dev_to_session(conn->dev.parent);
@@ -1780,19 +1779,18 @@ static struct iscsi_cls_session *iscsi_session_lookup(struct net *net,
{
unsigned long flags;
struct iscsi_cls_session *sess;
- struct net *ns;
+ struct iscsi_net *isn;
- spin_lock_irqsave(&sesslock, flags);
- list_for_each_entry(sess, &sesslist, sess_list) {
+ isn = net_generic(net, iscsi_net_id);
+
+ spin_lock_irqsave(&isn->sesslock, flags);
+ list_for_each_entry(sess, &isn->sesslist, sess_list) {
if (sess->sid == sid) {
- ns = iscsi_sess_net(sess);
- if (ns != net)
- continue;
- spin_unlock_irqrestore(&sesslock, flags);
+ spin_unlock_irqrestore(&isn->sesslock, flags);
return sess;
}
}
- spin_unlock_irqrestore(&sesslock, flags);
+ spin_unlock_irqrestore(&isn->sesslock, flags);
return NULL;
}
@@ -1804,19 +1802,18 @@ static struct iscsi_cls_conn *iscsi_conn_lookup(struct net *net, uint32_t sid,
{
unsigned long flags;
struct iscsi_cls_conn *conn;
- struct net *ns;
+ struct iscsi_net *isn;
- spin_lock_irqsave(&connlock, flags);
- list_for_each_entry(conn, &connlist, conn_list) {
+ isn = net_generic(net, iscsi_net_id);
+
+ spin_lock_irqsave(&isn->connlock, flags);
+ list_for_each_entry(conn, &isn->connlist, conn_list) {
if ((conn->cid == cid) && (iscsi_conn_get_sid(conn) == sid)) {
- ns = iscsi_conn_net(conn);
- if (ns != net)
- continue;
- spin_unlock_irqrestore(&connlock, flags);
+ spin_unlock_irqrestore(&isn->connlock, flags);
return conn;
}
}
- spin_unlock_irqrestore(&connlock, flags);
+ spin_unlock_irqrestore(&isn->connlock, flags);
return NULL;
}
@@ -2228,6 +2225,9 @@ EXPORT_SYMBOL_GPL(iscsi_alloc_session);
int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
{
struct Scsi_Host *shost = iscsi_session_to_shost(session);
+ struct iscsi_cls_host *ihost = shost->shost_data;
+ struct net *net = iscsi_host_net(ihost);
+ struct iscsi_net *isn = net_generic(net, iscsi_net_id);
unsigned long flags;
int id = 0;
int err;
@@ -2271,9 +2271,9 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
goto release_dev;
}
- spin_lock_irqsave(&sesslock, flags);
- list_add(&session->sess_list, &sesslist);
- spin_unlock_irqrestore(&sesslock, flags);
+ spin_lock_irqsave(&isn->sesslock, flags);
+ list_add(&session->sess_list, &isn->sesslist);
+ spin_unlock_irqrestore(&isn->sesslock, flags);
iscsi_session_event(session, ISCSI_KEVENT_CREATE_SESSION);
ISCSI_DBG_TRANS_SESSION(session, "Completed session adding\n");
@@ -2343,15 +2343,17 @@ static int iscsi_iter_destroy_conn_fn(struct device *dev, void *data)
void iscsi_remove_session(struct iscsi_cls_session *session)
{
+ struct net *net = iscsi_sess_net(session);
+ struct iscsi_net *isn = net_generic(net, iscsi_net_id);
unsigned long flags;
int err;
ISCSI_DBG_TRANS_SESSION(session, "Removing session\n");
- spin_lock_irqsave(&sesslock, flags);
+ spin_lock_irqsave(&isn->sesslock, flags);
if (!list_empty(&session->sess_list))
list_del(&session->sess_list);
- spin_unlock_irqrestore(&sesslock, flags);
+ spin_unlock_irqrestore(&isn->sesslock, flags);
if (!cancel_work_sync(&session->block_work))
cancel_delayed_work_sync(&session->recovery_work);
@@ -2562,20 +2564,22 @@ static int iscsi_iter_force_destroy_conn_fn(struct device *dev, void *data)
void iscsi_force_destroy_session(struct iscsi_cls_session *session)
{
struct iscsi_transport *transport = session->transport;
+ struct net *net = iscsi_sess_net(session);
+ struct iscsi_net *isn = net_generic(net, iscsi_net_id);
unsigned long flags;
WARN_ON_ONCE(system_state == SYSTEM_RUNNING);
- spin_lock_irqsave(&sesslock, flags);
+ spin_lock_irqsave(&isn->sesslock, flags);
if (list_empty(&session->sess_list)) {
- spin_unlock_irqrestore(&sesslock, flags);
+ spin_unlock_irqrestore(&isn->sesslock, flags);
/*
* Conn/ep is already freed. Session is being torn down via
* async path. For shutdown we don't care about it so return.
*/
return;
}
- spin_unlock_irqrestore(&sesslock, flags);
+ spin_unlock_irqrestore(&isn->sesslock, flags);
device_for_each_child(&session->dev, NULL,
iscsi_iter_force_destroy_conn_fn);
@@ -2646,6 +2650,8 @@ int iscsi_add_conn(struct iscsi_cls_conn *conn)
int err;
unsigned long flags;
struct iscsi_cls_session *session = iscsi_dev_to_session(conn->dev.parent);
+ struct net *net = iscsi_sess_net(session);
+ struct iscsi_net *isn = net_generic(net, iscsi_net_id);
err = device_add(&conn->dev);
if (err) {
@@ -2661,9 +2667,9 @@ int iscsi_add_conn(struct iscsi_cls_conn *conn)
return err;
}
- spin_lock_irqsave(&connlock, flags);
- list_add(&conn->conn_list, &connlist);
- spin_unlock_irqrestore(&connlock, flags);
+ spin_lock_irqsave(&isn->connlock, flags);
+ list_add(&conn->conn_list, &isn->connlist);
+ spin_unlock_irqrestore(&isn->connlock, flags);
return 0;
}
@@ -2678,11 +2684,14 @@ EXPORT_SYMBOL_GPL(iscsi_add_conn);
*/
void iscsi_remove_conn(struct iscsi_cls_conn *conn)
{
+ struct net *net = iscsi_conn_net(conn);
+ struct iscsi_net *isn = net_generic(net, iscsi_net_id);
+
unsigned long flags;
- spin_lock_irqsave(&connlock, flags);
+ spin_lock_irqsave(&isn->connlock, flags);
list_del(&conn->conn_list);
- spin_unlock_irqrestore(&connlock, flags);
+ spin_unlock_irqrestore(&isn->connlock, flags);
transport_unregister_device(&conn->dev);
device_del(&conn->dev);
@@ -3466,20 +3475,21 @@ iscsi_set_path(struct net *net, struct iscsi_transport *transport,
return err;
}
-static int iscsi_session_has_conns(int sid)
+static int iscsi_session_has_conns(struct net *net, int sid)
{
+ struct iscsi_net *isn = net_generic(net, iscsi_net_id);
struct iscsi_cls_conn *conn;
unsigned long flags;
int found = 0;
- spin_lock_irqsave(&connlock, flags);
- list_for_each_entry(conn, &connlist, conn_list) {
+ spin_lock_irqsave(&isn->connlock, flags);
+ list_for_each_entry(conn, &isn->connlist, conn_list) {
if (iscsi_conn_get_sid(conn) == sid) {
found = 1;
break;
}
}
- spin_unlock_irqrestore(&connlock, flags);
+ spin_unlock_irqrestore(&isn->connlock, flags);
return found;
}
@@ -4192,7 +4202,7 @@ iscsi_if_recv_msg(struct net *net, struct sk_buff *skb,
session = iscsi_session_lookup(net, ev->u.d_session.sid);
if (!session)
err = -EINVAL;
- else if (iscsi_session_has_conns(ev->u.d_session.sid))
+ else if (iscsi_session_has_conns(net, ev->u.d_session.sid))
err = -EBUSY;
else
transport->destroy_session(session);
@@ -4201,15 +4211,16 @@ iscsi_if_recv_msg(struct net *net, struct sk_buff *skb,
session = iscsi_session_lookup(net, ev->u.d_session.sid);
if (!session)
err = -EINVAL;
- else if (iscsi_session_has_conns(ev->u.d_session.sid))
+ else if (iscsi_session_has_conns(net, ev->u.d_session.sid))
err = -EBUSY;
else {
+ struct iscsi_net *isn = net_generic(net, iscsi_net_id);
unsigned long flags;
/* Prevent this session from being found again */
- spin_lock_irqsave(&sesslock, flags);
+ spin_lock_irqsave(&isn->sesslock, flags);
list_del_init(&session->sess_list);
- spin_unlock_irqrestore(&sesslock, flags);
+ spin_unlock_irqrestore(&isn->sesslock, flags);
queue_work(system_unbound_wq, &session->destroy_work);
}
@@ -5211,6 +5222,13 @@ static int __net_init iscsi_net_init(struct net *net)
if (!nls)
return -ENOMEM;
isn = net_generic(net, iscsi_net_id);
+
+ INIT_LIST_HEAD(&isn->sesslist);
+ spin_lock_init(&isn->sesslock);
+ INIT_LIST_HEAD(&isn->connlist);
+ INIT_LIST_HEAD(&isn->connlist_err);
+ spin_lock_init(&isn->connlock);
+
isn->nls = nls;
return 0;
}