scst: Make scst_cmd_threads.threads_list locking more fine-grained

Introduce a new synchronization object, namely scst_cmd_threads.thr_lock,
to protect scst_cmd_threads.threads_list.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@5701 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2014-07-22 00:22:06 +00:00
parent 9c51087ee8
commit 209a825360
3 changed files with 30 additions and 22 deletions
+1
View File
@@ -1908,6 +1908,7 @@ struct scst_cmd_threads {
/* io_context_mutex protects io_context and io_context_refcnt. */
struct mutex io_context_mutex;
spinlock_t thr_lock; /* Protects nr_threads and threads_list */
int nr_threads; /* number of processing threads */
struct list_head threads_list; /* processing threads */
+28 -22
View File
@@ -1848,7 +1848,6 @@ void scst_unregister_virtual_dev_driver(struct scst_dev_type *dev_type)
}
EXPORT_SYMBOL_GPL(scst_unregister_virtual_dev_driver);
/* scst_mutex supposed to be held */
int scst_add_threads(struct scst_cmd_threads *cmd_threads,
struct scst_device *dev, struct scst_tgt_dev *tgt_dev, int num)
{
@@ -1863,9 +1862,9 @@ int scst_add_threads(struct scst_cmd_threads *cmd_threads,
goto out;
}
list_for_each_entry(thr, &cmd_threads->threads_list, thread_list_entry) {
n++;
}
spin_lock(&cmd_threads->thr_lock);
n = cmd_threads->nr_threads;
spin_unlock(&cmd_threads->thr_lock);
TRACE_DBG("cmd_threads %p, dev %s, tgt_dev %p, num %d, n %d",
cmd_threads, dev ? dev->virt_name : NULL, tgt_dev, num, n);
@@ -1881,7 +1880,7 @@ int scst_add_threads(struct scst_cmd_threads *cmd_threads,
}
for (i = 0; i < num; i++) {
thr = kmalloc(sizeof(*thr), GFP_KERNEL);
thr = kzalloc(sizeof(*thr), GFP_KERNEL);
if (!thr) {
res = -ENOMEM;
PRINT_ERROR("Fail to allocate thr %d", res);
@@ -1924,8 +1923,10 @@ int scst_add_threads(struct scst_cmd_threads *cmd_threads,
"%d", rc);
}
spin_lock(&cmd_threads->thr_lock);
list_add(&thr->thread_list_entry, &cmd_threads->threads_list);
cmd_threads->nr_threads++;
spin_unlock(&cmd_threads->thr_lock);
TRACE_DBG("Added thr %p to threads list (nr_threads %d, n %d)",
thr, cmd_threads->nr_threads, n);
@@ -1955,39 +1956,43 @@ out:
return res;
}
/* scst_mutex supposed to be held */
void scst_del_threads(struct scst_cmd_threads *cmd_threads, int num)
{
struct scst_cmd_thread_t *ct, *tmp;
TRACE_ENTRY();
if (num == 0)
goto out;
list_for_each_entry_safe_reverse(ct, tmp, &cmd_threads->threads_list,
thread_list_entry) {
for ( ; num != 0; num--) {
struct scst_cmd_thread_t *ct = NULL, *ct2;
int rc;
spin_lock(&cmd_threads->thr_lock);
list_for_each_entry_reverse(ct2, &cmd_threads->threads_list,
thread_list_entry) {
if (!ct2->being_stopped) {
ct = ct2;
ct->being_stopped = true;
cmd_threads->nr_threads--;
break;
}
}
spin_unlock(&cmd_threads->thr_lock);
if (!ct)
break;
rc = kthread_stop(ct->cmd_thread);
if (rc != 0 && rc != -EINTR)
TRACE_MGMT_DBG("kthread_stop() failed: %d", rc);
spin_lock(&cmd_threads->thr_lock);
list_del(&ct->thread_list_entry);
spin_unlock(&cmd_threads->thr_lock);
kfree(ct);
cmd_threads->nr_threads--;
--num;
if (num == 0)
break;
}
EXTRACHECKS_BUG_ON((cmd_threads->nr_threads == 0) &&
(cmd_threads->io_context != NULL));
out:
TRACE_EXIT();
return;
}
@@ -1999,14 +2004,14 @@ int scst_set_thr_cpu_mask(struct scst_cmd_threads *cmd_threads,
struct scst_cmd_thread_t *thr;
int rc = 0;
lockdep_assert_held(&scst_mutex);
spin_lock(&cmd_threads->thr_lock);
list_for_each_entry(thr, &cmd_threads->threads_list,
thread_list_entry) {
rc = set_cpus_allowed_ptr(thr->cmd_thread, cpu_mask);
if (rc)
break;
}
spin_unlock(&cmd_threads->thr_lock);
return rc;
}
@@ -2197,6 +2202,7 @@ void scst_init_threads(struct scst_cmd_threads *cmd_threads)
init_waitqueue_head(&cmd_threads->cmd_list_waitQ);
INIT_LIST_HEAD(&cmd_threads->threads_list);
mutex_init(&cmd_threads->io_context_mutex);
spin_lock_init(&cmd_threads->thr_lock);
mutex_lock(&scst_cmd_threads_mutex);
list_add_tail(&cmd_threads->lists_list_entry,
+1
View File
@@ -211,6 +211,7 @@ extern cpumask_t default_cpu_mask;
struct scst_cmd_thread_t {
struct task_struct *cmd_thread;
struct list_head thread_list_entry;
bool being_stopped;
};
static inline bool scst_set_io_context(struct scst_cmd *cmd,