mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-18 21:26:31 +00:00
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:
+1
-8
@@ -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
@@ -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)",
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user