mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-22 13:11:27 +00:00
Currently there is a possibility that a session name is reused and
passed to scst_sess_sysfs_create() before scst_sess_sysfs_del() has finished removing a kobject that is using the same session name. This patch fixes that. It works by maintaining yet another session list, namely a list of sessions registered in sysfs, and by using that list to check for duplicate session names. Signed-off-by: Bart Van Assche <bvanassche@acm.org> git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4464 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -1488,6 +1488,12 @@ struct scst_tgt {
|
||||
/* List of remote sessions per target, protected by scst_mutex */
|
||||
struct list_head sess_list;
|
||||
|
||||
/*
|
||||
* List of remote sessions registered in sysfs per target, protected
|
||||
* by scst_mutex.
|
||||
*/
|
||||
struct list_head sysfs_sess_list;
|
||||
|
||||
/* List entry of targets per template (tgts_list) */
|
||||
struct list_head tgt_list_entry;
|
||||
|
||||
@@ -1674,6 +1680,9 @@ struct scst_session {
|
||||
/* List entry of sessions per target */
|
||||
struct list_head sess_list_entry;
|
||||
|
||||
/* Per target list entry for sessions registered in sysfs. */
|
||||
struct list_head sysfs_sess_list_entry;
|
||||
|
||||
/* List entry for the list that keeps session, waiting for the init */
|
||||
struct list_head sess_init_list_entry;
|
||||
|
||||
|
||||
@@ -3291,6 +3291,7 @@ int scst_alloc_tgt(struct scst_tgt_template *tgtt, struct scst_tgt **tgt)
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&t->sess_list);
|
||||
INIT_LIST_HEAD(&t->sysfs_sess_list);
|
||||
init_waitqueue_head(&t->unreg_waitQ);
|
||||
t->tgtt = tgtt;
|
||||
t->sg_tablesize = tgtt->sg_tablesize;
|
||||
@@ -5107,6 +5108,8 @@ void scst_free_session(struct scst_session *sess)
|
||||
|
||||
mutex_lock(&scst_mutex);
|
||||
|
||||
list_del(&sess->sysfs_sess_list_entry);
|
||||
|
||||
/* Called under lock to protect from too early tgt release */
|
||||
wake_up_all(&sess->tgt->unreg_waitQ);
|
||||
|
||||
|
||||
@@ -6440,7 +6440,7 @@ bool scst_initiator_has_luns(struct scst_tgt *tgt, const char *initiator_name)
|
||||
EXPORT_SYMBOL_GPL(scst_initiator_has_luns);
|
||||
|
||||
/* Supposed to be called under scst_mutex */
|
||||
static char *scst_get_unique_sess_name(struct list_head *sess_list,
|
||||
static char *scst_get_unique_sess_name(struct list_head *sysfs_sess_list,
|
||||
const char *initiator_name)
|
||||
{
|
||||
char *name = (char *)initiator_name;
|
||||
@@ -6453,8 +6453,9 @@ static char *scst_get_unique_sess_name(struct list_head *sess_list,
|
||||
#endif
|
||||
|
||||
restart:
|
||||
list_for_each_entry(s, sess_list, sess_list_entry) {
|
||||
if (s->sess_name && strcmp(name, s->sess_name) == 0) {
|
||||
list_for_each_entry(s, sysfs_sess_list, sysfs_sess_list_entry) {
|
||||
BUG_ON(!s->sess_name);
|
||||
if (strcmp(name, s->sess_name) == 0) {
|
||||
TRACE_DBG("Duplicated session from the same initiator "
|
||||
"%s found", name);
|
||||
|
||||
@@ -6498,6 +6499,8 @@ static int scst_init_session(struct scst_session *sess)
|
||||
TRACE_DBG("Adding sess %p to tgt->sess_list", sess);
|
||||
list_add_tail(&sess->sess_list_entry, &sess->tgt->sess_list);
|
||||
|
||||
INIT_LIST_HEAD(&sess->sysfs_sess_list_entry);
|
||||
|
||||
if (sess->tgt->tgtt->get_initiator_port_transport_id != NULL) {
|
||||
res = sess->tgt->tgtt->get_initiator_port_transport_id(
|
||||
sess->tgt, sess, &sess->transport_id);
|
||||
@@ -6513,7 +6516,7 @@ static int scst_init_session(struct scst_session *sess)
|
||||
}
|
||||
|
||||
res = -ENOMEM;
|
||||
sess->sess_name = scst_get_unique_sess_name(&sess->tgt->sess_list,
|
||||
sess->sess_name = scst_get_unique_sess_name(&sess->tgt->sysfs_sess_list,
|
||||
sess->initiator_name);
|
||||
if (!sess->sess_name)
|
||||
goto failed;
|
||||
@@ -6522,6 +6525,9 @@ static int scst_init_session(struct scst_session *sess)
|
||||
if (res != 0)
|
||||
goto failed;
|
||||
|
||||
list_add_tail(&sess->sysfs_sess_list_entry,
|
||||
&sess->tgt->sysfs_sess_list);
|
||||
|
||||
/*
|
||||
* scst_sess_alloc_tgt_devs() must be called after session added in the
|
||||
* sess_list to not race with scst_check_reassign_sess()!
|
||||
|
||||
Reference in New Issue
Block a user