scst: Make sure that scst_get_unique_sess_name() is called under scst_mutex

such that session names are again guaranteed to be unique (follow-up for r4452).


git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4454 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Bart Van Assche
2012-08-07 18:06:37 +00:00
parent 239d6243ec
commit 46a3540873
3 changed files with 48 additions and 51 deletions

View File

@@ -5027,8 +5027,7 @@ static void scst_clear_reservation(struct scst_tgt_dev *tgt_dev)
}
struct scst_session *scst_alloc_session(struct scst_tgt *tgt, gfp_t gfp_mask,
const char *name,
const char *initiator_name)
const char *initiator_name)
{
struct scst_session *sess;
int i;
@@ -5064,22 +5063,16 @@ struct scst_session *scst_alloc_session(struct scst_tgt *tgt, gfp_t gfp_mask,
spin_lock_init(&sess->lat_lock);
#endif
sess->name = kstrdup(name, gfp_mask);
if (!sess->name)
goto out_free;
sess->initiator_name = kstrdup(initiator_name, gfp_mask);
if (sess->initiator_name == NULL) {
PRINT_ERROR("%s", "Unable to dup sess->initiator_name");
goto out_free_sess_name;
goto out_free;
}
out:
TRACE_EXIT();
return sess;
out_free_sess_name:
kfree(sess->name);
out_free:
kmem_cache_free(scst_sess_cachep, sess);
sess = NULL;
@@ -5122,7 +5115,8 @@ void scst_free_session(struct scst_session *sess)
kfree(sess->transport_id);
kfree(sess->initiator_name);
kfree(sess->name);
if (sess->name != sess->initiator_name)
kfree(sess->name);
kmem_cache_free(scst_sess_cachep, sess);

View File

@@ -348,7 +348,6 @@ int scst_assign_dev_handler(struct scst_device *dev,
struct scst_dev_type *handler);
struct scst_session *scst_alloc_session(struct scst_tgt *tgt, gfp_t gfp_mask,
const char *name,
const char *initiator_name);
void scst_free_session(struct scst_session *sess);
void scst_free_session_callback(struct scst_session *sess);

View File

@@ -6412,6 +6412,42 @@ bool scst_initiator_has_luns(struct scst_tgt *tgt, const char *initiator_name)
}
EXPORT_SYMBOL_GPL(scst_initiator_has_luns);
static char *scst_get_unique_sess_name(struct list_head *sess_list,
const char* initiator_name)
{
char *name = (char *)initiator_name;
struct scst_session *s;
int len = 0, n = 1;
BUG_ON(!initiator_name);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
lockdep_assert_held(&scst_mutex);
#endif
restart:
list_for_each_entry(s, sess_list, sess_list_entry) {
if (s->name && strcmp(name, s->name) == 0) {
TRACE_DBG("Duplicated session from the same initiator "
"%s found", name);
if (name == initiator_name) {
len = strlen(initiator_name) + 20;
name = kmalloc(len, GFP_KERNEL);
if (name == NULL) {
PRINT_ERROR("Unable to allocate a "
"replacement name (size %d)",
len);
}
}
snprintf(name, len, "%s_%d", initiator_name, n);
n++;
goto restart;
}
}
return name;
}
static int scst_init_session(struct scst_session *sess)
{
int res = 0;
@@ -6448,6 +6484,12 @@ static int scst_init_session(struct scst_session *sess)
sess->transport_id), sess->tgt->rel_tgt_id);
}
res = -ENOMEM;
sess->name = scst_get_unique_sess_name(&sess->tgt->sess_list,
sess->initiator_name);
if (!sess->name)
goto failed;
res = scst_sess_sysfs_create(sess);
if (res != 0)
goto failed;
@@ -6513,37 +6555,6 @@ restart:
return res;
}
static char *scst_get_unique_sess_name(struct list_head *sess_list,
const char* initiator_name)
{
char *name = (char *)initiator_name;
struct scst_session *s;
int len = 0, n = 1;
restart:
list_for_each_entry(s, sess_list, sess_list_entry) {
if (strcmp(name, s->name) == 0) {
TRACE_DBG("Duplicated session from the same initiator "
"%s found", name);
if (name == initiator_name) {
len = strlen(initiator_name) + 20;
name = kmalloc(len, GFP_KERNEL);
if (name == NULL) {
PRINT_ERROR("Unable to allocate a "
"replacement name (size %d)",
len);
}
}
snprintf(name, len, "%s_%d", initiator_name, n);
n++;
goto restart;
}
}
return name;
}
/**
* scst_register_session() - register session
* @tgt: target
@@ -6591,19 +6602,14 @@ struct scst_session *scst_register_session(struct scst_tgt *tgt, int atomic,
const char *initiator_name, void *tgt_priv, void *result_fn_data,
void (*result_fn) (struct scst_session *sess, void *data, int result))
{
struct scst_session *sess = NULL;
char *name;
struct scst_session *sess;
int res;
unsigned long flags;
TRACE_ENTRY();
name = scst_get_unique_sess_name(&tgt->sess_list, initiator_name);
if (!name)
goto out;
sess = scst_alloc_session(tgt, atomic ? GFP_ATOMIC : GFP_KERNEL,
name, initiator_name);
initiator_name);
if (sess == NULL)
goto out;
@@ -6628,8 +6634,6 @@ struct scst_session *scst_register_session(struct scst_tgt *tgt, int atomic,
}
out:
if (name != initiator_name)
kfree(name);
TRACE_EXIT();
return sess;