From 209a8253601557fa32aec84f236c6f5a3f985733 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Tue, 22 Jul 2014 00:22:06 +0000 Subject: [PATCH] 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 git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@5701 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/include/scst.h | 1 + scst/src/scst_main.c | 50 +++++++++++++++++++++++++------------------- scst/src/scst_priv.h | 1 + 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/scst/include/scst.h b/scst/include/scst.h index 505a724f9..1afa7cb23 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -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 */ diff --git a/scst/src/scst_main.c b/scst/src/scst_main.c index 678bb9aef..a4c999696 100644 --- a/scst/src/scst_main.c +++ b/scst/src/scst_main.c @@ -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, diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index bba383e43..4f742c8a0 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -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,