mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-19 19:51:27 +00:00
I/O context creation and cleanup in SCST command-processing threads is
protected by io_context_mutex. The patch below changes that mutex from a single mutex for all command threads to one mutex per thread pool. + Two quickly succeeding command thread management actions, e.g. setting both threads_num and threads_pool_type via scst.conf, can trigger the bug mentioned below. That bug can be triggered because kthread_stop() can stop a thread before it has started. So it can happen that an I/O context is created inside scst_cmd_thread() but not cleaned up because the thread for which p_cmd_threads->nr_threads == 1would evaluate to true is never started. The patch below fixes this by guaranteeing that if an I/O context has been created for a thread pool that it gets cleaned up too. Signed-off-by: Bart Van Assche <bvanassche@acm.org> with fixes/cleanups git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@3152 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -1684,9 +1684,13 @@ struct scst_cmd_threads {
|
||||
wait_queue_head_t cmd_list_waitQ;
|
||||
|
||||
struct io_context *io_context; /* IO context of the threads pool */
|
||||
int io_context_refcnt;
|
||||
|
||||
bool io_context_ready;
|
||||
|
||||
/* io_context_mutex protects io_context and io_context_refcnt. */
|
||||
struct mutex io_context_mutex;
|
||||
|
||||
int nr_threads; /* number of processing threads */
|
||||
struct list_head threads_list; /* processing threads */
|
||||
|
||||
|
||||
@@ -1629,7 +1629,7 @@ int scst_add_threads(struct scst_cmd_threads *cmd_threads,
|
||||
}
|
||||
|
||||
out_wait:
|
||||
if (cmd_threads != &scst_main_cmd_threads) {
|
||||
if (i > 0 && cmd_threads != &scst_main_cmd_threads) {
|
||||
/*
|
||||
* Wait for io_context gets initialized to avoid possible races
|
||||
* for it from the sharing it tgt_devs.
|
||||
@@ -1665,7 +1665,7 @@ void scst_del_threads(struct scst_cmd_threads *cmd_threads, int num)
|
||||
struct scst_device *dev;
|
||||
|
||||
rc = kthread_stop(ct->cmd_thread);
|
||||
if (rc < 0)
|
||||
if (rc != 0 && rc != -EINTR)
|
||||
TRACE_MGMT_DBG("kthread_stop() failed: %d", rc);
|
||||
|
||||
list_del(&ct->thread_list_entry);
|
||||
@@ -1879,6 +1879,7 @@ void scst_init_threads(struct scst_cmd_threads *cmd_threads)
|
||||
INIT_LIST_HEAD(&cmd_threads->active_cmd_list);
|
||||
init_waitqueue_head(&cmd_threads->cmd_list_waitQ);
|
||||
INIT_LIST_HEAD(&cmd_threads->threads_list);
|
||||
mutex_init(&cmd_threads->io_context_mutex);
|
||||
|
||||
mutex_lock(&scst_suspend_mutex);
|
||||
list_add_tail(&cmd_threads->lists_list_entry,
|
||||
|
||||
@@ -4150,7 +4150,6 @@ static inline int test_cmd_threads(struct scst_cmd_threads *p_cmd_threads)
|
||||
int scst_cmd_thread(void *arg)
|
||||
{
|
||||
struct scst_cmd_threads *p_cmd_threads = arg;
|
||||
static DEFINE_MUTEX(io_context_mutex);
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -4162,36 +4161,38 @@ int scst_cmd_thread(void *arg)
|
||||
#endif
|
||||
current->flags |= PF_NOFREEZE;
|
||||
|
||||
mutex_lock(&io_context_mutex);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
|
||||
mutex_lock(&p_cmd_threads->io_context_mutex);
|
||||
|
||||
WARN_ON(current->io_context);
|
||||
|
||||
if (p_cmd_threads != &scst_main_cmd_threads) {
|
||||
/*
|
||||
* For linked IO contexts io_context might be not NULL while
|
||||
* io_context 0.
|
||||
*/
|
||||
if (p_cmd_threads->io_context == NULL) {
|
||||
#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 "
|
||||
"(p_cmd_threads %p)",
|
||||
p_cmd_threads->io_context,
|
||||
p_cmd_threads);
|
||||
/*
|
||||
* Put the extra reference. It isn't needed, because we
|
||||
* ref counted via nr_threads below.
|
||||
* Put the extra reference created by get_io_context()
|
||||
* because we don't need it.
|
||||
*/
|
||||
put_io_context(p_cmd_threads->io_context);
|
||||
} else {
|
||||
#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);
|
||||
#endif
|
||||
TRACE_MGMT_DBG("Linked IO context %p "
|
||||
"(p_cmd_threads %p)", p_cmd_threads->io_context,
|
||||
p_cmd_threads);
|
||||
}
|
||||
p_cmd_threads->io_context_refcnt++;
|
||||
}
|
||||
|
||||
mutex_unlock(&io_context_mutex);
|
||||
mutex_unlock(&p_cmd_threads->io_context_mutex);
|
||||
#endif
|
||||
|
||||
p_cmd_threads->io_context_ready = true;
|
||||
|
||||
@@ -4227,12 +4228,14 @@ int scst_cmd_thread(void *arg)
|
||||
}
|
||||
spin_unlock_irq(&p_cmd_threads->cmd_list_lock);
|
||||
|
||||
EXTRACHECKS_BUG_ON((p_cmd_threads->nr_threads == 1) &&
|
||||
!list_empty(&p_cmd_threads->active_cmd_list));
|
||||
|
||||
if ((p_cmd_threads != &scst_main_cmd_threads) &&
|
||||
(p_cmd_threads->nr_threads == 1))
|
||||
p_cmd_threads->io_context = NULL;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
|
||||
if (p_cmd_threads != &scst_main_cmd_threads) {
|
||||
mutex_lock(&p_cmd_threads->io_context_mutex);
|
||||
if (--p_cmd_threads->io_context_refcnt == 0)
|
||||
p_cmd_threads->io_context = NULL;
|
||||
mutex_unlock(&p_cmd_threads->io_context_mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
PRINT_INFO("Processing thread %s (PID %d) finished", current->comm,
|
||||
current->pid);
|
||||
|
||||
Reference in New Issue
Block a user