summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-03-14 16:00:56 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2016-08-28 19:15:20 -0800
commitbd1f4c3b60629c957f03b7f94db1bced11801106 (patch)
tree432253558f1cf3b5d3a373798f8dd3a4dfb66d48
parent0dd77eed2b36a0145bd8a6a4e73935e8b533cc28 (diff)
workqueue: system_unbound_freezable_wq
-rw-r--r--fs/bcachefs/journal.c2
-rw-r--r--include/linux/workqueue.h1
-rw-r--r--kernel/async.c2
-rw-r--r--kernel/workqueue.c38
4 files changed, 39 insertions, 4 deletions
diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c
index ae8c213c638f..c0ea77524792 100644
--- a/fs/bcachefs/journal.c
+++ b/fs/bcachefs/journal.c
@@ -807,7 +807,7 @@ const char *bch_journal_read(struct cache_set *c, struct list_head *list)
for_each_cache(ca, c, iter)
closure_call(&ca->journal.read,
bch_journal_read_device,
- system_unbound_wq,
+ system_unbound_freezable_wq,
&jlist.cl);
closure_sync(&jlist.cl);
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index b853f6d1a458..d4bc4482eebe 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -355,6 +355,7 @@ extern struct workqueue_struct *system_highpri_wq;
extern struct workqueue_struct *system_long_wq;
extern struct workqueue_struct *system_unbound_wq;
extern struct workqueue_struct *system_freezable_wq;
+extern struct workqueue_struct *system_unbound_freezable_wq;
extern struct workqueue_struct *system_power_efficient_wq;
extern struct workqueue_struct *system_freezable_power_efficient_wq;
diff --git a/kernel/async.c b/kernel/async.c
index d2edd6efec56..7b3d7dc1f2cf 100644
--- a/kernel/async.c
+++ b/kernel/async.c
@@ -191,7 +191,7 @@ static async_cookie_t __async_schedule(async_func_t func, void *data, struct asy
current->flags |= PF_USED_ASYNC;
/* schedule for execution */
- queue_work(system_unbound_wq, &entry->work);
+ queue_work(system_unbound_freezable_wq, &entry->work);
return newcookie;
}
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 8e6a3a44d088..1e29ea444b24 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -343,6 +343,8 @@ struct workqueue_struct *system_unbound_wq __read_mostly;
EXPORT_SYMBOL_GPL(system_unbound_wq);
struct workqueue_struct *system_freezable_wq __read_mostly;
EXPORT_SYMBOL_GPL(system_freezable_wq);
+struct workqueue_struct *system_unbound_freezable_wq __read_mostly;
+EXPORT_SYMBOL_GPL(system_unbound_freezable_wq);
struct workqueue_struct *system_power_efficient_wq __read_mostly;
EXPORT_SYMBOL_GPL(system_power_efficient_wq);
struct workqueue_struct *system_freezable_power_efficient_wq __read_mostly;
@@ -521,15 +523,43 @@ static inline void debug_work_activate(struct work_struct *work) { }
static inline void debug_work_deactivate(struct work_struct *work) { }
#endif
+noinline
+bool __context_is_freezable(struct task_struct *task)
+{
+ struct worker *worker = task->flags & PF_WQ_WORKER
+ ? kthread_data(task)
+ : NULL;
+
+ if (worker) {
+ if (!(worker->current_pwq->wq->flags & WQ_FREEZABLE)) {
+ printk(KERN_ERR "context %s not freezable\n", context_name());
+ }
+
+ BUG_ON(!(worker->current_pwq->wq->flags & WQ_FREEZABLE));
+ return worker->current_pwq->wq->flags & WQ_FREEZABLE;
+ } else
+ return !(task->flags & PF_NOFREEZE);
+
+}
+
bool context_is_freezable(void)
{
+#if 1
+ return __context_is_freezable(current);
+#else
struct worker *worker;
worker = current_wq_worker();
- if (worker)
+ if (worker) {
+ if (!(worker->current_pwq->wq->flags & WQ_FREEZABLE)) {
+ printk(KERN_ERR "context %s not freezable\n", context_name());
+ }
+
+ BUG_ON(!(worker->current_pwq->wq->flags & WQ_FREEZABLE));
return worker->current_pwq->wq->flags & WQ_FREEZABLE;
- else
+ } else
return !(current->flags & PF_NOFREEZE);
+#endif
}
const char *context_name(void)
@@ -5569,6 +5599,9 @@ static int __init init_workqueues(void)
WQ_UNBOUND_MAX_ACTIVE);
system_freezable_wq = alloc_workqueue("events_freezable",
WQ_FREEZABLE, 0);
+ system_unbound_freezable_wq = alloc_workqueue("events_unbound_freezable",
+ WQ_UNBOUND|WQ_FREEZABLE,
+ WQ_UNBOUND_MAX_ACTIVE);
system_power_efficient_wq = alloc_workqueue("events_power_efficient",
WQ_POWER_EFFICIENT, 0);
system_freezable_power_efficient_wq = alloc_workqueue("events_freezable_power_efficient",
@@ -5576,6 +5609,7 @@ static int __init init_workqueues(void)
0);
BUG_ON(!system_wq || !system_highpri_wq || !system_long_wq ||
!system_unbound_wq || !system_freezable_wq ||
+ !system_unbound_freezable_wq ||
!system_power_efficient_wq ||
!system_freezable_power_efficient_wq);