aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/Makefile2
-rw-r--r--kernel/module.c5
-rw-r--r--kernel/slow-work-debugfs.c (renamed from kernel/slow-work-proc.c)4
-rw-r--r--kernel/slow-work.c64
-rw-r--r--kernel/slow-work.h6
5 files changed, 51 insertions, 30 deletions
diff --git a/kernel/Makefile b/kernel/Makefile
index 776ffed1556d..d7c13d249b2d 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -94,7 +94,7 @@ obj-$(CONFIG_X86_DS) += trace/
94obj-$(CONFIG_RING_BUFFER) += trace/ 94obj-$(CONFIG_RING_BUFFER) += trace/
95obj-$(CONFIG_SMP) += sched_cpupri.o 95obj-$(CONFIG_SMP) += sched_cpupri.o
96obj-$(CONFIG_SLOW_WORK) += slow-work.o 96obj-$(CONFIG_SLOW_WORK) += slow-work.o
97obj-$(CONFIG_SLOW_WORK_PROC) += slow-work-proc.o 97obj-$(CONFIG_SLOW_WORK_DEBUG) += slow-work-debugfs.o
98obj-$(CONFIG_PERF_EVENTS) += perf_event.o 98obj-$(CONFIG_PERF_EVENTS) += perf_event.o
99 99
100ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y) 100ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y)
diff --git a/kernel/module.c b/kernel/module.c
index 8b7d8805819d..5842a71cf052 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1187,7 +1187,8 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect,
1187 1187
1188 /* Count loaded sections and allocate structures */ 1188 /* Count loaded sections and allocate structures */
1189 for (i = 0; i < nsect; i++) 1189 for (i = 0; i < nsect; i++)
1190 if (sechdrs[i].sh_flags & SHF_ALLOC) 1190 if (sechdrs[i].sh_flags & SHF_ALLOC
1191 && sechdrs[i].sh_size)
1191 nloaded++; 1192 nloaded++;
1192 size[0] = ALIGN(sizeof(*sect_attrs) 1193 size[0] = ALIGN(sizeof(*sect_attrs)
1193 + nloaded * sizeof(sect_attrs->attrs[0]), 1194 + nloaded * sizeof(sect_attrs->attrs[0]),
@@ -1207,6 +1208,8 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect,
1207 for (i = 0; i < nsect; i++) { 1208 for (i = 0; i < nsect; i++) {
1208 if (! (sechdrs[i].sh_flags & SHF_ALLOC)) 1209 if (! (sechdrs[i].sh_flags & SHF_ALLOC))
1209 continue; 1210 continue;
1211 if (!sechdrs[i].sh_size)
1212 continue;
1210 sattr->address = sechdrs[i].sh_addr; 1213 sattr->address = sechdrs[i].sh_addr;
1211 sattr->name = kstrdup(secstrings + sechdrs[i].sh_name, 1214 sattr->name = kstrdup(secstrings + sechdrs[i].sh_name,
1212 GFP_KERNEL); 1215 GFP_KERNEL);
diff --git a/kernel/slow-work-proc.c b/kernel/slow-work-debugfs.c
index 3988032571f5..e45c43645298 100644
--- a/kernel/slow-work-proc.c
+++ b/kernel/slow-work-debugfs.c
@@ -57,7 +57,7 @@ static void slow_work_print_mark(struct seq_file *m, struct slow_work *work)
57} 57}
58 58
59/* 59/*
60 * Describe a slow work item for /proc 60 * Describe a slow work item for debugfs
61 */ 61 */
62static int slow_work_runqueue_show(struct seq_file *m, void *v) 62static int slow_work_runqueue_show(struct seq_file *m, void *v)
63{ 63{
@@ -211,7 +211,7 @@ static const struct seq_operations slow_work_runqueue_ops = {
211}; 211};
212 212
213/* 213/*
214 * open "/proc/slow_work_rq" to list queue contents 214 * open "/sys/kernel/debug/slow_work/runqueue" to list queue contents
215 */ 215 */
216static int slow_work_runqueue_open(struct inode *inode, struct file *file) 216static int slow_work_runqueue_open(struct inode *inode, struct file *file)
217{ 217{
diff --git a/kernel/slow-work.c b/kernel/slow-work.c
index da94f3c101af..00889bd3c590 100644
--- a/kernel/slow-work.c
+++ b/kernel/slow-work.c
@@ -16,7 +16,7 @@
16#include <linux/kthread.h> 16#include <linux/kthread.h>
17#include <linux/freezer.h> 17#include <linux/freezer.h>
18#include <linux/wait.h> 18#include <linux/wait.h>
19#include <linux/proc_fs.h> 19#include <linux/debugfs.h>
20#include "slow-work.h" 20#include "slow-work.h"
21 21
22static void slow_work_cull_timeout(unsigned long); 22static void slow_work_cull_timeout(unsigned long);
@@ -109,12 +109,36 @@ static struct module *slow_work_unreg_module;
109static struct slow_work *slow_work_unreg_work_item; 109static struct slow_work *slow_work_unreg_work_item;
110static DECLARE_WAIT_QUEUE_HEAD(slow_work_unreg_wq); 110static DECLARE_WAIT_QUEUE_HEAD(slow_work_unreg_wq);
111static DEFINE_MUTEX(slow_work_unreg_sync_lock); 111static DEFINE_MUTEX(slow_work_unreg_sync_lock);
112
113static void slow_work_set_thread_processing(int id, struct slow_work *work)
114{
115 if (work)
116 slow_work_thread_processing[id] = work->owner;
117}
118static void slow_work_done_thread_processing(int id, struct slow_work *work)
119{
120 struct module *module = slow_work_thread_processing[id];
121
122 slow_work_thread_processing[id] = NULL;
123 smp_mb();
124 if (slow_work_unreg_work_item == work ||
125 slow_work_unreg_module == module)
126 wake_up_all(&slow_work_unreg_wq);
127}
128static void slow_work_clear_thread_processing(int id)
129{
130 slow_work_thread_processing[id] = NULL;
131}
132#else
133static void slow_work_set_thread_processing(int id, struct slow_work *work) {}
134static void slow_work_done_thread_processing(int id, struct slow_work *work) {}
135static void slow_work_clear_thread_processing(int id) {}
112#endif 136#endif
113 137
114/* 138/*
115 * Data for tracking currently executing items for indication through /proc 139 * Data for tracking currently executing items for indication through /proc
116 */ 140 */
117#ifdef CONFIG_SLOW_WORK_PROC 141#ifdef CONFIG_SLOW_WORK_DEBUG
118struct slow_work *slow_work_execs[SLOW_WORK_THREAD_LIMIT]; 142struct slow_work *slow_work_execs[SLOW_WORK_THREAD_LIMIT];
119pid_t slow_work_pids[SLOW_WORK_THREAD_LIMIT]; 143pid_t slow_work_pids[SLOW_WORK_THREAD_LIMIT];
120DEFINE_RWLOCK(slow_work_execs_lock); 144DEFINE_RWLOCK(slow_work_execs_lock);
@@ -197,9 +221,6 @@ static unsigned slow_work_calc_vsmax(void)
197 */ 221 */
198static noinline bool slow_work_execute(int id) 222static noinline bool slow_work_execute(int id)
199{ 223{
200#ifdef CONFIG_MODULES
201 struct module *module;
202#endif
203 struct slow_work *work = NULL; 224 struct slow_work *work = NULL;
204 unsigned vsmax; 225 unsigned vsmax;
205 bool very_slow; 226 bool very_slow;
@@ -236,10 +257,7 @@ static noinline bool slow_work_execute(int id)
236 very_slow = false; /* avoid the compiler warning */ 257 very_slow = false; /* avoid the compiler warning */
237 } 258 }
238 259
239#ifdef CONFIG_MODULES 260 slow_work_set_thread_processing(id, work);
240 if (work)
241 slow_work_thread_processing[id] = work->owner;
242#endif
243 if (work) { 261 if (work) {
244 slow_work_mark_time(work); 262 slow_work_mark_time(work);
245 slow_work_begin_exec(id, work); 263 slow_work_begin_exec(id, work);
@@ -287,15 +305,7 @@ static noinline bool slow_work_execute(int id)
287 305
288 /* sort out the race between module unloading and put_ref() */ 306 /* sort out the race between module unloading and put_ref() */
289 slow_work_put_ref(work); 307 slow_work_put_ref(work);
290 308 slow_work_done_thread_processing(id, work);
291#ifdef CONFIG_MODULES
292 module = slow_work_thread_processing[id];
293 slow_work_thread_processing[id] = NULL;
294 smp_mb();
295 if (slow_work_unreg_work_item == work ||
296 slow_work_unreg_module == module)
297 wake_up_all(&slow_work_unreg_wq);
298#endif
299 309
300 return true; 310 return true;
301 311
@@ -310,7 +320,7 @@ auto_requeue:
310 else 320 else
311 list_add_tail(&work->link, &slow_work_queue); 321 list_add_tail(&work->link, &slow_work_queue);
312 spin_unlock_irq(&slow_work_queue_lock); 322 spin_unlock_irq(&slow_work_queue_lock);
313 slow_work_thread_processing[id] = NULL; 323 slow_work_clear_thread_processing(id);
314 return true; 324 return true;
315} 325}
316 326
@@ -813,7 +823,7 @@ static void slow_work_new_thread_execute(struct slow_work *work)
813static const struct slow_work_ops slow_work_new_thread_ops = { 823static const struct slow_work_ops slow_work_new_thread_ops = {
814 .owner = THIS_MODULE, 824 .owner = THIS_MODULE,
815 .execute = slow_work_new_thread_execute, 825 .execute = slow_work_new_thread_execute,
816#ifdef CONFIG_SLOW_WORK_PROC 826#ifdef CONFIG_SLOW_WORK_DEBUG
817 .desc = slow_work_new_thread_desc, 827 .desc = slow_work_new_thread_desc,
818#endif 828#endif
819}; 829};
@@ -943,6 +953,7 @@ EXPORT_SYMBOL(slow_work_register_user);
943 */ 953 */
944static void slow_work_wait_for_items(struct module *module) 954static void slow_work_wait_for_items(struct module *module)
945{ 955{
956#ifdef CONFIG_MODULES
946 DECLARE_WAITQUEUE(myself, current); 957 DECLARE_WAITQUEUE(myself, current);
947 struct slow_work *work; 958 struct slow_work *work;
948 int loop; 959 int loop;
@@ -989,6 +1000,7 @@ static void slow_work_wait_for_items(struct module *module)
989 1000
990 remove_wait_queue(&slow_work_unreg_wq, &myself); 1001 remove_wait_queue(&slow_work_unreg_wq, &myself);
991 mutex_unlock(&slow_work_unreg_sync_lock); 1002 mutex_unlock(&slow_work_unreg_sync_lock);
1003#endif /* CONFIG_MODULES */
992} 1004}
993 1005
994/** 1006/**
@@ -1043,9 +1055,15 @@ static int __init init_slow_work(void)
1043 if (slow_work_max_max_threads < nr_cpus * 2) 1055 if (slow_work_max_max_threads < nr_cpus * 2)
1044 slow_work_max_max_threads = nr_cpus * 2; 1056 slow_work_max_max_threads = nr_cpus * 2;
1045#endif 1057#endif
1046#ifdef CONFIG_SLOW_WORK_PROC 1058#ifdef CONFIG_SLOW_WORK_DEBUG
1047 proc_create("slow_work_rq", S_IFREG | 0400, NULL, 1059 {
1048 &slow_work_runqueue_fops); 1060 struct dentry *dbdir;
1061
1062 dbdir = debugfs_create_dir("slow_work", NULL);
1063 if (dbdir && !IS_ERR(dbdir))
1064 debugfs_create_file("runqueue", S_IFREG | 0400, dbdir,
1065 NULL, &slow_work_runqueue_fops);
1066 }
1049#endif 1067#endif
1050 return 0; 1068 return 0;
1051} 1069}
diff --git a/kernel/slow-work.h b/kernel/slow-work.h
index 3c2f007f3ad6..321f3c59d732 100644
--- a/kernel/slow-work.h
+++ b/kernel/slow-work.h
@@ -19,7 +19,7 @@
19/* 19/*
20 * slow-work.c 20 * slow-work.c
21 */ 21 */
22#ifdef CONFIG_SLOW_WORK_PROC 22#ifdef CONFIG_SLOW_WORK_DEBUG
23extern struct slow_work *slow_work_execs[]; 23extern struct slow_work *slow_work_execs[];
24extern pid_t slow_work_pids[]; 24extern pid_t slow_work_pids[];
25extern rwlock_t slow_work_execs_lock; 25extern rwlock_t slow_work_execs_lock;
@@ -30,9 +30,9 @@ extern struct list_head vslow_work_queue;
30extern spinlock_t slow_work_queue_lock; 30extern spinlock_t slow_work_queue_lock;
31 31
32/* 32/*
33 * slow-work-proc.c 33 * slow-work-debugfs.c
34 */ 34 */
35#ifdef CONFIG_SLOW_WORK_PROC 35#ifdef CONFIG_SLOW_WORK_DEBUG
36extern const struct file_operations slow_work_runqueue_fops; 36extern const struct file_operations slow_work_runqueue_fops;
37 37
38extern void slow_work_new_thread_desc(struct slow_work *, struct seq_file *); 38extern void slow_work_new_thread_desc(struct slow_work *, struct seq_file *);