mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-20 12:11:26 +00:00
isert: Fix case when iscsid is not able to handle login request on time or at all
In some cases, iscsi-scstd chooses to close the connection device and abort the connection. This can cause invalid device state due to order of isert_conn_dev cleanup and disconnect handling. Make sure we release isert_conn_dev only after we received disconnect event, or we passed the connection to the kernel. This also fixes an issue if iscsi-scstd is run on very CPU intensive load and it does not receive CPU time to serve the login requests. This may get to the extreme of initiator disconnecting before iscsi-scstd had the chance to handle the login request. Signed-off-by: Yan Burman <yanb@mellanox.com> git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/iser@5318 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -115,6 +115,7 @@ struct isert_conn_dev {
|
||||
int is_discovery;
|
||||
struct timer_list tmo_timer;
|
||||
int timer_active;
|
||||
struct kref kref;
|
||||
};
|
||||
|
||||
#define ISER_CONN_DEV_PREFIX "isert/conn"
|
||||
|
||||
@@ -93,15 +93,29 @@ static void isert_del_timer(struct isert_conn_dev *dev)
|
||||
|
||||
static void release_dev(struct isert_conn_dev *dev)
|
||||
{
|
||||
isert_del_timer(dev);
|
||||
kref_init(&dev->kref);
|
||||
|
||||
spin_lock(&isert_listen_dev.conn_lock);
|
||||
dev->occupied = 0;
|
||||
list_del_init(&dev->conn_list_entry);
|
||||
dev->state = CS_INIT;
|
||||
atomic_set(&dev->available, 1);
|
||||
spin_unlock(&isert_listen_dev.conn_lock);
|
||||
}
|
||||
|
||||
static void isert_kref_release_dev(struct kref *kref)
|
||||
{
|
||||
struct isert_conn_dev *dev = container_of(kref,
|
||||
struct isert_conn_dev,
|
||||
kref);
|
||||
release_dev(dev);
|
||||
}
|
||||
|
||||
static void isert_dev_release(struct isert_conn_dev *dev)
|
||||
{
|
||||
kref_put(&dev->kref, isert_kref_release_dev);
|
||||
}
|
||||
|
||||
static void isert_conn_timer_fn(unsigned long arg)
|
||||
{
|
||||
struct isert_conn_dev *conn_dev = (struct isert_conn_dev *)arg;
|
||||
@@ -233,9 +247,10 @@ int isert_conn_alloc(struct iscsi_session *session,
|
||||
goto cleanup_iscsi_conn;
|
||||
#endif
|
||||
|
||||
list_add_tail(&conn->conn_list_entry, &session->conn_list);
|
||||
|
||||
conn->rd_state = 1;
|
||||
isert_dev_release(dev);
|
||||
|
||||
list_add_tail(&conn->conn_list_entry, &session->conn_list);
|
||||
res = isert_login_rsp_tx(cmnd, true, false);
|
||||
vunmap(dev->sg_virt);
|
||||
dev->sg_virt = NULL;
|
||||
@@ -335,6 +350,7 @@ static ssize_t isert_listen_read(struct file *filp, char __user *buf,
|
||||
conn_dev = list_first_entry(&dev->new_conn_list, struct isert_conn_dev,
|
||||
conn_list_entry);
|
||||
list_move(&conn_dev->conn_list_entry, &dev->curr_conn_list);
|
||||
kref_get(&conn_dev->kref);
|
||||
spin_unlock(&dev->conn_lock);
|
||||
|
||||
res = snprintf(k_buff, sizeof(k_buff), "/dev/"ISER_CONN_DEV_PREFIX"%d",
|
||||
@@ -423,6 +439,7 @@ int isert_connection_closed(struct iscsi_conn *iscsi_conn)
|
||||
|
||||
dev->conn = NULL;
|
||||
wake_up(&dev->waitqueue);
|
||||
isert_dev_release(dev);
|
||||
}
|
||||
|
||||
isert_free_connection(iscsi_conn);
|
||||
@@ -480,8 +497,9 @@ static int isert_release(struct inode *inode, struct file *filp)
|
||||
dev->conn = NULL;
|
||||
}
|
||||
|
||||
release_dev(dev);
|
||||
atomic_inc(&dev->available);
|
||||
isert_del_timer(dev);
|
||||
|
||||
isert_dev_release(dev);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
@@ -797,6 +815,7 @@ static void __init isert_setup_cdev(struct isert_conn_dev *dev,
|
||||
dev->login_rsp = NULL;
|
||||
spin_lock_init(&dev->pdu_lock);
|
||||
atomic_set(&dev->available, 1);
|
||||
kref_init(&dev->kref);
|
||||
dev->state = CS_INIT;
|
||||
err = cdev_add(&dev->cdev, dev->devno, 1);
|
||||
/* Fail gracefully if need be */
|
||||
|
||||
Reference in New Issue
Block a user