Fixes possible crashes on threads management. Issue with volatile bool noticed by Bart Van Assche <bvanassche@acm.org>, great thanks!

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@2052 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2010-09-04 17:16:08 +00:00
parent 0679e4e7a1
commit 9963c18578
6 changed files with 17 additions and 47 deletions
+1 -8
View File
@@ -1525,14 +1525,6 @@ struct scst_cmd_threads {
struct io_context *io_context; /* IO context of the threads pool */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
/*
* Those kernels don't support ref counting based IO context sharing
* between threads/processes, so need own ref counting.
*/
struct kref io_context_kref;
#endif
bool io_context_ready;
int nr_threads; /* number of processing threads */
@@ -2177,6 +2169,7 @@ struct scst_thr_data_hdr {
*/
struct scst_async_io_context_keeper {
struct kref aic_keeper_kref;
bool aic_ready;
struct io_context *aic;
struct task_struct *aic_keeper_thr;
wait_queue_head_t aic_keeper_waitQ;
+4 -5
View File
@@ -3004,7 +3004,7 @@ found:
t->acg_dev->acg->acg_io_grouping_type);
} else {
res = t;
if ((volatile bool)!res->active_cmd_threads->io_context_ready) {
if (!*(volatile bool*)&res->active_cmd_threads->io_context_ready) {
TRACE_MGMT_DBG("IO context for t %p not yet "
"initialized, waiting...", t);
msleep(100);
@@ -3056,9 +3056,7 @@ static int scst_ioc_keeper_thread(void *arg)
sBUG_ON(aic_keeper->aic != NULL);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
aic_keeper->aic = get_io_context(GFP_KERNEL);
#else
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
aic_keeper->aic = get_io_context(GFP_KERNEL, -1);
#endif
TRACE_MGMT_DBG("Alloced new async IO context %p (aic %p)",
@@ -3068,6 +3066,7 @@ static int scst_ioc_keeper_thread(void *arg)
put_io_context(aic_keeper->aic);
/* We are ready */
aic_keeper->aic_ready = true;
wake_up_all(&aic_keeper->aic_keeper_waitQ);
wait_event_interruptible(aic_keeper->aic_keeper_waitQ,
@@ -3129,7 +3128,7 @@ int scst_tgt_dev_setup_threads(struct scst_tgt_dev *tgt_dev)
}
wait_event(aic_keeper->aic_keeper_waitQ,
aic_keeper->aic != NULL);
aic_keeper->aic_ready);
TRACE_MGMT_DBG("Created async io context %p "
"for not shared tgt_dev %p (dev %s)",
+1 -1
View File
@@ -1525,7 +1525,7 @@ out_wait:
* Wait for io_context gets initialized to avoid possible races
* for it from the sharing it tgt_devs.
*/
while ((volatile bool)!cmd_threads->io_context_ready) {
while (!*(volatile bool*)&cmd_threads->io_context_ready) {
TRACE_DBG("Waiting for io_context for cmd_threads %p "
"initialized", cmd_threads);
msleep(50);
+4
View File
@@ -199,6 +199,10 @@ static inline bool scst_set_io_context(struct scst_cmd *cmd,
{
bool res;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
return false;
#endif
#ifdef CONFIG_SCST_TEST_IO_IN_SIRQ
return false;
#endif
+5 -2
View File
@@ -2339,7 +2339,7 @@ int scst_sess_sysfs_create(struct scst_session *sess)
restart:
list_for_each_entry(s, &sess->tgt->sess_list, sess_list_entry) {
if (!sess->sess_kobj_ready)
if (!s->sess_kobj_ready)
continue;
if (strcmp(name, kobject_name(&s->sess_kobj)) == 0) {
@@ -2368,6 +2368,8 @@ restart:
init_completion(&sess->sess_kobj_release_cmpl);
TRACE_DBG("Adding session %s to sysfs", name);
res = kobject_init_and_add(&sess->sess_kobj, &scst_session_ktype,
sess->tgt->tgt_sess_kobj, name);
if (res != 0) {
@@ -2410,7 +2412,8 @@ void scst_sess_sysfs_del(struct scst_session *sess)
if (!sess->sess_kobj_ready)
goto out;
TRACE_DBG("Deleting session %s", kobject_name(&sess->sess_kobj));
TRACE_DBG("Deleting session %s from sysfs",
kobject_name(&sess->sess_kobj));
kobject_del(&sess->sess_kobj);
kobject_put(&sess->sess_kobj);
+2 -31
View File
@@ -4252,13 +4252,6 @@ static inline int test_cmd_threads(struct scst_cmd_threads *p_cmd_threads)
return res;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
static void scst_io_context_kref_release(struct kref *kref)
{
/* Nothing to do */
}
#endif
int scst_cmd_thread(void *arg)
{
struct scst_cmd_threads *p_cmd_threads = (struct scst_cmd_threads *)arg;
@@ -4280,9 +4273,7 @@ int scst_cmd_thread(void *arg)
if (p_cmd_threads != &scst_main_cmd_threads) {
if (p_cmd_threads->io_context == NULL) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
p_cmd_threads->io_context = get_io_context(GFP_KERNEL);
#else
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
p_cmd_threads->io_context = get_io_context(GFP_KERNEL, -1);
#endif
TRACE_MGMT_DBG("Alloced new IO context %p "
@@ -4294,18 +4285,10 @@ int scst_cmd_thread(void *arg)
* ref counted via nr_threads below.
*/
put_io_context(p_cmd_threads->io_context);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
kref_init(&p_cmd_threads->io_context_kref);
#endif
} else {
put_io_context(current->io_context);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
put_io_context(current->io_context);
current->io_context = ioc_task_link(p_cmd_threads->io_context);
#else
current->io_context = p_cmd_threads->io_context;
kref_get(&p_cmd_threads->io_context_kref);
TRACE_DBG("new refcount %d",
atomic_read(&p_cmd_threads->io_context_kref.refcount));
#endif
TRACE_MGMT_DBG("Linked IO context %p "
"(p_cmd_threads %p)", p_cmd_threads->io_context,
@@ -4353,18 +4336,6 @@ int scst_cmd_thread(void *arg)
!list_empty(&p_cmd_threads->active_cmd_list));
if (p_cmd_threads != &scst_main_cmd_threads) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
TRACE_DBG("old refcount %d",
atomic_read(&p_cmd_threads->io_context_kref.refcount));
if (!kref_put(&p_cmd_threads->io_context_kref,
scst_io_context_kref_release)) {
/*
* Prevent io_context from being destroyed, we still
* need it.
*/
current->io_context = NULL;
}
#endif
if (p_cmd_threads->nr_threads == 1)
p_cmd_threads->io_context = NULL;
}