diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/fork.c | 14 | ||||
-rw-r--r-- | kernel/module.c | 2 | ||||
-rw-r--r-- | kernel/printk.c | 33 | ||||
-rw-r--r-- | kernel/signal.c | 11 | ||||
-rw-r--r-- | kernel/softirq.c | 11 | ||||
-rw-r--r-- | kernel/sysctl.c | 12 | ||||
-rw-r--r-- | kernel/trace/Kconfig | 10 | ||||
-rw-r--r-- | kernel/trace/ring_buffer.c | 3 | ||||
-rw-r--r-- | kernel/trace/trace.c | 23 | ||||
-rw-r--r-- | kernel/user.c | 67 |
10 files changed, 121 insertions, 65 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 4430eb1376f2..be022c200da6 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -178,7 +178,7 @@ void __init fork_init(unsigned long mempages) | |||
178 | /* create a slab on which task_structs can be allocated */ | 178 | /* create a slab on which task_structs can be allocated */ |
179 | task_struct_cachep = | 179 | task_struct_cachep = |
180 | kmem_cache_create("task_struct", sizeof(struct task_struct), | 180 | kmem_cache_create("task_struct", sizeof(struct task_struct), |
181 | ARCH_MIN_TASKALIGN, SLAB_PANIC, NULL); | 181 | ARCH_MIN_TASKALIGN, SLAB_PANIC | SLAB_NOTRACK, NULL); |
182 | #endif | 182 | #endif |
183 | 183 | ||
184 | /* do the arch specific task caches init */ | 184 | /* do the arch specific task caches init */ |
@@ -1470,20 +1470,20 @@ void __init proc_caches_init(void) | |||
1470 | { | 1470 | { |
1471 | sighand_cachep = kmem_cache_create("sighand_cache", | 1471 | sighand_cachep = kmem_cache_create("sighand_cache", |
1472 | sizeof(struct sighand_struct), 0, | 1472 | sizeof(struct sighand_struct), 0, |
1473 | SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_DESTROY_BY_RCU, | 1473 | SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_DESTROY_BY_RCU| |
1474 | sighand_ctor); | 1474 | SLAB_NOTRACK, sighand_ctor); |
1475 | signal_cachep = kmem_cache_create("signal_cache", | 1475 | signal_cachep = kmem_cache_create("signal_cache", |
1476 | sizeof(struct signal_struct), 0, | 1476 | sizeof(struct signal_struct), 0, |
1477 | SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); | 1477 | SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL); |
1478 | files_cachep = kmem_cache_create("files_cache", | 1478 | files_cachep = kmem_cache_create("files_cache", |
1479 | sizeof(struct files_struct), 0, | 1479 | sizeof(struct files_struct), 0, |
1480 | SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); | 1480 | SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL); |
1481 | fs_cachep = kmem_cache_create("fs_cache", | 1481 | fs_cachep = kmem_cache_create("fs_cache", |
1482 | sizeof(struct fs_struct), 0, | 1482 | sizeof(struct fs_struct), 0, |
1483 | SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); | 1483 | SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL); |
1484 | mm_cachep = kmem_cache_create("mm_struct", | 1484 | mm_cachep = kmem_cache_create("mm_struct", |
1485 | sizeof(struct mm_struct), ARCH_MIN_MMSTRUCT_ALIGN, | 1485 | sizeof(struct mm_struct), ARCH_MIN_MMSTRUCT_ALIGN, |
1486 | SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); | 1486 | SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL); |
1487 | vm_area_cachep = KMEM_CACHE(vm_area_struct, SLAB_PANIC); | 1487 | vm_area_cachep = KMEM_CACHE(vm_area_struct, SLAB_PANIC); |
1488 | mmap_init(); | 1488 | mmap_init(); |
1489 | } | 1489 | } |
diff --git a/kernel/module.c b/kernel/module.c index e4ab36ce7672..215aaab09e91 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -2899,7 +2899,7 @@ void print_modules(void) | |||
2899 | struct module *mod; | 2899 | struct module *mod; |
2900 | char buf[8]; | 2900 | char buf[8]; |
2901 | 2901 | ||
2902 | printk("Modules linked in:"); | 2902 | printk(KERN_DEFAULT "Modules linked in:"); |
2903 | /* Most callers should already have preempt disabled, but make sure */ | 2903 | /* Most callers should already have preempt disabled, but make sure */ |
2904 | preempt_disable(); | 2904 | preempt_disable(); |
2905 | list_for_each_entry_rcu(mod, &modules, list) | 2905 | list_for_each_entry_rcu(mod, &modules, list) |
diff --git a/kernel/printk.c b/kernel/printk.c index 5052b5497c67..b4d97b54c1ec 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -687,20 +687,35 @@ asmlinkage int vprintk(const char *fmt, va_list args) | |||
687 | sizeof(printk_buf) - printed_len, fmt, args); | 687 | sizeof(printk_buf) - printed_len, fmt, args); |
688 | 688 | ||
689 | 689 | ||
690 | p = printk_buf; | ||
691 | |||
692 | /* Do we have a loglevel in the string? */ | ||
693 | if (p[0] == '<') { | ||
694 | unsigned char c = p[1]; | ||
695 | if (c && p[2] == '>') { | ||
696 | switch (c) { | ||
697 | case '0' ... '7': /* loglevel */ | ||
698 | current_log_level = c - '0'; | ||
699 | /* Fallthrough - make sure we're on a new line */ | ||
700 | case 'd': /* KERN_DEFAULT */ | ||
701 | if (!new_text_line) { | ||
702 | emit_log_char('\n'); | ||
703 | new_text_line = 1; | ||
704 | } | ||
705 | /* Fallthrough - skip the loglevel */ | ||
706 | case 'c': /* KERN_CONT */ | ||
707 | p += 3; | ||
708 | break; | ||
709 | } | ||
710 | } | ||
711 | } | ||
712 | |||
690 | /* | 713 | /* |
691 | * Copy the output into log_buf. If the caller didn't provide | 714 | * Copy the output into log_buf. If the caller didn't provide |
692 | * appropriate log level tags, we insert them here | 715 | * appropriate log level tags, we insert them here |
693 | */ | 716 | */ |
694 | for (p = printk_buf; *p; p++) { | 717 | for ( ; *p; p++) { |
695 | if (new_text_line) { | 718 | if (new_text_line) { |
696 | /* If a token, set current_log_level and skip over */ | ||
697 | if (p[0] == '<' && p[1] >= '0' && p[1] <= '7' && | ||
698 | p[2] == '>') { | ||
699 | current_log_level = p[1] - '0'; | ||
700 | p += 3; | ||
701 | printed_len -= 3; | ||
702 | } | ||
703 | |||
704 | /* Always output the token */ | 719 | /* Always output the token */ |
705 | emit_log_char('<'); | 720 | emit_log_char('<'); |
706 | emit_log_char(current_log_level + '0'); | 721 | emit_log_char(current_log_level + '0'); |
diff --git a/kernel/signal.c b/kernel/signal.c index 809a228019ad..d81f4952eebb 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -832,6 +832,7 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, | |||
832 | { | 832 | { |
833 | struct sigpending *pending; | 833 | struct sigpending *pending; |
834 | struct sigqueue *q; | 834 | struct sigqueue *q; |
835 | int override_rlimit; | ||
835 | 836 | ||
836 | trace_sched_signal_send(sig, t); | 837 | trace_sched_signal_send(sig, t); |
837 | 838 | ||
@@ -863,9 +864,13 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, | |||
863 | make sure at least one signal gets delivered and don't | 864 | make sure at least one signal gets delivered and don't |
864 | pass on the info struct. */ | 865 | pass on the info struct. */ |
865 | 866 | ||
866 | q = __sigqueue_alloc(t, GFP_ATOMIC, (sig < SIGRTMIN && | 867 | if (sig < SIGRTMIN) |
867 | (is_si_special(info) || | 868 | override_rlimit = (is_si_special(info) || info->si_code >= 0); |
868 | info->si_code >= 0))); | 869 | else |
870 | override_rlimit = 0; | ||
871 | |||
872 | q = __sigqueue_alloc(t, GFP_ATOMIC | __GFP_NOTRACK_FALSE_POSITIVE, | ||
873 | override_rlimit); | ||
869 | if (q) { | 874 | if (q) { |
870 | list_add_tail(&q->list, &pending->list); | 875 | list_add_tail(&q->list, &pending->list); |
871 | switch ((unsigned long) info) { | 876 | switch ((unsigned long) info) { |
diff --git a/kernel/softirq.c b/kernel/softirq.c index 258885a543db..b41fb710e114 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -382,6 +382,17 @@ void __tasklet_hi_schedule(struct tasklet_struct *t) | |||
382 | 382 | ||
383 | EXPORT_SYMBOL(__tasklet_hi_schedule); | 383 | EXPORT_SYMBOL(__tasklet_hi_schedule); |
384 | 384 | ||
385 | void __tasklet_hi_schedule_first(struct tasklet_struct *t) | ||
386 | { | ||
387 | BUG_ON(!irqs_disabled()); | ||
388 | |||
389 | t->next = __get_cpu_var(tasklet_hi_vec).head; | ||
390 | __get_cpu_var(tasklet_hi_vec).head = t; | ||
391 | __raise_softirq_irqoff(HI_SOFTIRQ); | ||
392 | } | ||
393 | |||
394 | EXPORT_SYMBOL(__tasklet_hi_schedule_first); | ||
395 | |||
385 | static void tasklet_action(struct softirq_action *a) | 396 | static void tasklet_action(struct softirq_action *a) |
386 | { | 397 | { |
387 | struct tasklet_struct *list; | 398 | struct tasklet_struct *list; |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 2ccee08f92f1..ab462b9968d5 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/security.h> | 27 | #include <linux/security.h> |
28 | #include <linux/ctype.h> | 28 | #include <linux/ctype.h> |
29 | #include <linux/utsname.h> | 29 | #include <linux/utsname.h> |
30 | #include <linux/kmemcheck.h> | ||
30 | #include <linux/smp_lock.h> | 31 | #include <linux/smp_lock.h> |
31 | #include <linux/fs.h> | 32 | #include <linux/fs.h> |
32 | #include <linux/init.h> | 33 | #include <linux/init.h> |
@@ -967,6 +968,17 @@ static struct ctl_table kern_table[] = { | |||
967 | .proc_handler = &proc_dointvec, | 968 | .proc_handler = &proc_dointvec, |
968 | }, | 969 | }, |
969 | #endif | 970 | #endif |
971 | #ifdef CONFIG_KMEMCHECK | ||
972 | { | ||
973 | .ctl_name = CTL_UNNUMBERED, | ||
974 | .procname = "kmemcheck", | ||
975 | .data = &kmemcheck_enabled, | ||
976 | .maxlen = sizeof(int), | ||
977 | .mode = 0644, | ||
978 | .proc_handler = &proc_dointvec, | ||
979 | }, | ||
980 | #endif | ||
981 | |||
970 | /* | 982 | /* |
971 | * NOTE: do not add new entries to this table unless you have read | 983 | * NOTE: do not add new entries to this table unless you have read |
972 | * Documentation/sysctl/ctl_unnumbered.txt | 984 | * Documentation/sysctl/ctl_unnumbered.txt |
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 4a13e5a01ce3..61071fecc82e 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig | |||
@@ -147,7 +147,7 @@ config IRQSOFF_TRACER | |||
147 | disabled by default and can be runtime (re-)started | 147 | disabled by default and can be runtime (re-)started |
148 | via: | 148 | via: |
149 | 149 | ||
150 | echo 0 > /debugfs/tracing/tracing_max_latency | 150 | echo 0 > /sys/kernel/debug/tracing/tracing_max_latency |
151 | 151 | ||
152 | (Note that kernel size and overhead increases with this option | 152 | (Note that kernel size and overhead increases with this option |
153 | enabled. This option and the preempt-off timing option can be | 153 | enabled. This option and the preempt-off timing option can be |
@@ -168,7 +168,7 @@ config PREEMPT_TRACER | |||
168 | disabled by default and can be runtime (re-)started | 168 | disabled by default and can be runtime (re-)started |
169 | via: | 169 | via: |
170 | 170 | ||
171 | echo 0 > /debugfs/tracing/tracing_max_latency | 171 | echo 0 > /sys/kernel/debug/tracing/tracing_max_latency |
172 | 172 | ||
173 | (Note that kernel size and overhead increases with this option | 173 | (Note that kernel size and overhead increases with this option |
174 | enabled. This option and the irqs-off timing option can be | 174 | enabled. This option and the irqs-off timing option can be |
@@ -261,7 +261,7 @@ config PROFILE_ANNOTATED_BRANCHES | |||
261 | This tracer profiles all the the likely and unlikely macros | 261 | This tracer profiles all the the likely and unlikely macros |
262 | in the kernel. It will display the results in: | 262 | in the kernel. It will display the results in: |
263 | 263 | ||
264 | /debugfs/tracing/profile_annotated_branch | 264 | /sys/kernel/debug/tracing/profile_annotated_branch |
265 | 265 | ||
266 | Note: this will add a significant overhead, only turn this | 266 | Note: this will add a significant overhead, only turn this |
267 | on if you need to profile the system's use of these macros. | 267 | on if you need to profile the system's use of these macros. |
@@ -274,7 +274,7 @@ config PROFILE_ALL_BRANCHES | |||
274 | taken in the kernel is recorded whether it hit or miss. | 274 | taken in the kernel is recorded whether it hit or miss. |
275 | The results will be displayed in: | 275 | The results will be displayed in: |
276 | 276 | ||
277 | /debugfs/tracing/profile_branch | 277 | /sys/kernel/debug/tracing/profile_branch |
278 | 278 | ||
279 | This option also enables the likely/unlikely profiler. | 279 | This option also enables the likely/unlikely profiler. |
280 | 280 | ||
@@ -323,7 +323,7 @@ config STACK_TRACER | |||
323 | select KALLSYMS | 323 | select KALLSYMS |
324 | help | 324 | help |
325 | This special tracer records the maximum stack footprint of the | 325 | This special tracer records the maximum stack footprint of the |
326 | kernel and displays it in debugfs/tracing/stack_trace. | 326 | kernel and displays it in /sys/kernel/debug/tracing/stack_trace. |
327 | 327 | ||
328 | This tracer works by hooking into every function call that the | 328 | This tracer works by hooking into every function call that the |
329 | kernel executes, and keeping a maximum stack depth value and | 329 | kernel executes, and keeping a maximum stack depth value and |
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 2e642b2b7253..dc4dc70171ce 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/debugfs.h> | 10 | #include <linux/debugfs.h> |
11 | #include <linux/uaccess.h> | 11 | #include <linux/uaccess.h> |
12 | #include <linux/hardirq.h> | 12 | #include <linux/hardirq.h> |
13 | #include <linux/kmemcheck.h> | ||
13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
14 | #include <linux/percpu.h> | 15 | #include <linux/percpu.h> |
15 | #include <linux/mutex.h> | 16 | #include <linux/mutex.h> |
@@ -1270,6 +1271,7 @@ rb_move_tail(struct ring_buffer_per_cpu *cpu_buffer, | |||
1270 | if (tail < BUF_PAGE_SIZE) { | 1271 | if (tail < BUF_PAGE_SIZE) { |
1271 | /* Mark the rest of the page with padding */ | 1272 | /* Mark the rest of the page with padding */ |
1272 | event = __rb_page_index(tail_page, tail); | 1273 | event = __rb_page_index(tail_page, tail); |
1274 | kmemcheck_annotate_bitfield(event, bitfield); | ||
1273 | rb_event_set_padding(event); | 1275 | rb_event_set_padding(event); |
1274 | } | 1276 | } |
1275 | 1277 | ||
@@ -1327,6 +1329,7 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer, | |||
1327 | return NULL; | 1329 | return NULL; |
1328 | 1330 | ||
1329 | event = __rb_page_index(tail_page, tail); | 1331 | event = __rb_page_index(tail_page, tail); |
1332 | kmemcheck_annotate_bitfield(event, bitfield); | ||
1330 | rb_update_event(event, type, length); | 1333 | rb_update_event(event, type, length); |
1331 | 1334 | ||
1332 | /* The passed in type is zero for DATA */ | 1335 | /* The passed in type is zero for DATA */ |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 8acd9b81a5d7..c1878bfb2e1e 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -344,7 +344,7 @@ static raw_spinlock_t ftrace_max_lock = | |||
344 | /* | 344 | /* |
345 | * Copy the new maximum trace into the separate maximum-trace | 345 | * Copy the new maximum trace into the separate maximum-trace |
346 | * structure. (this way the maximum trace is permanently saved, | 346 | * structure. (this way the maximum trace is permanently saved, |
347 | * for later retrieval via /debugfs/tracing/latency_trace) | 347 | * for later retrieval via /sys/kernel/debug/tracing/latency_trace) |
348 | */ | 348 | */ |
349 | static void | 349 | static void |
350 | __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu) | 350 | __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu) |
@@ -2414,21 +2414,20 @@ static const struct file_operations tracing_iter_fops = { | |||
2414 | 2414 | ||
2415 | static const char readme_msg[] = | 2415 | static const char readme_msg[] = |
2416 | "tracing mini-HOWTO:\n\n" | 2416 | "tracing mini-HOWTO:\n\n" |
2417 | "# mkdir /debug\n" | 2417 | "# mount -t debugfs nodev /sys/kernel/debug\n\n" |
2418 | "# mount -t debugfs nodev /debug\n\n" | 2418 | "# cat /sys/kernel/debug/tracing/available_tracers\n" |
2419 | "# cat /debug/tracing/available_tracers\n" | ||
2420 | "wakeup preemptirqsoff preemptoff irqsoff function sched_switch nop\n\n" | 2419 | "wakeup preemptirqsoff preemptoff irqsoff function sched_switch nop\n\n" |
2421 | "# cat /debug/tracing/current_tracer\n" | 2420 | "# cat /sys/kernel/debug/tracing/current_tracer\n" |
2422 | "nop\n" | 2421 | "nop\n" |
2423 | "# echo sched_switch > /debug/tracing/current_tracer\n" | 2422 | "# echo sched_switch > /sys/kernel/debug/tracing/current_tracer\n" |
2424 | "# cat /debug/tracing/current_tracer\n" | 2423 | "# cat /sys/kernel/debug/tracing/current_tracer\n" |
2425 | "sched_switch\n" | 2424 | "sched_switch\n" |
2426 | "# cat /debug/tracing/trace_options\n" | 2425 | "# cat /sys/kernel/debug/tracing/trace_options\n" |
2427 | "noprint-parent nosym-offset nosym-addr noverbose\n" | 2426 | "noprint-parent nosym-offset nosym-addr noverbose\n" |
2428 | "# echo print-parent > /debug/tracing/trace_options\n" | 2427 | "# echo print-parent > /sys/kernel/debug/tracing/trace_options\n" |
2429 | "# echo 1 > /debug/tracing/tracing_enabled\n" | 2428 | "# echo 1 > /sys/kernel/debug/tracing/tracing_enabled\n" |
2430 | "# cat /debug/tracing/trace > /tmp/trace.txt\n" | 2429 | "# cat /sys/kernel/debug/tracing/trace > /tmp/trace.txt\n" |
2431 | "# echo 0 > /debug/tracing/tracing_enabled\n" | 2430 | "# echo 0 > /sys/kernel/debug/tracing/tracing_enabled\n" |
2432 | ; | 2431 | ; |
2433 | 2432 | ||
2434 | static ssize_t | 2433 | static ssize_t |
diff --git a/kernel/user.c b/kernel/user.c index 850e0ba41c1e..2c000e7132ac 100644 --- a/kernel/user.c +++ b/kernel/user.c | |||
@@ -75,21 +75,6 @@ static void uid_hash_remove(struct user_struct *up) | |||
75 | put_user_ns(up->user_ns); | 75 | put_user_ns(up->user_ns); |
76 | } | 76 | } |
77 | 77 | ||
78 | static struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent) | ||
79 | { | ||
80 | struct user_struct *user; | ||
81 | struct hlist_node *h; | ||
82 | |||
83 | hlist_for_each_entry(user, h, hashent, uidhash_node) { | ||
84 | if (user->uid == uid) { | ||
85 | atomic_inc(&user->__count); | ||
86 | return user; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | return NULL; | ||
91 | } | ||
92 | |||
93 | #ifdef CONFIG_USER_SCHED | 78 | #ifdef CONFIG_USER_SCHED |
94 | 79 | ||
95 | static void sched_destroy_user(struct user_struct *up) | 80 | static void sched_destroy_user(struct user_struct *up) |
@@ -119,6 +104,23 @@ static int sched_create_user(struct user_struct *up) { return 0; } | |||
119 | 104 | ||
120 | #if defined(CONFIG_USER_SCHED) && defined(CONFIG_SYSFS) | 105 | #if defined(CONFIG_USER_SCHED) && defined(CONFIG_SYSFS) |
121 | 106 | ||
107 | static struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent) | ||
108 | { | ||
109 | struct user_struct *user; | ||
110 | struct hlist_node *h; | ||
111 | |||
112 | hlist_for_each_entry(user, h, hashent, uidhash_node) { | ||
113 | if (user->uid == uid) { | ||
114 | /* possibly resurrect an "almost deleted" object */ | ||
115 | if (atomic_inc_return(&user->__count) == 1) | ||
116 | cancel_delayed_work(&user->work); | ||
117 | return user; | ||
118 | } | ||
119 | } | ||
120 | |||
121 | return NULL; | ||
122 | } | ||
123 | |||
122 | static struct kset *uids_kset; /* represents the /sys/kernel/uids/ directory */ | 124 | static struct kset *uids_kset; /* represents the /sys/kernel/uids/ directory */ |
123 | static DEFINE_MUTEX(uids_mutex); | 125 | static DEFINE_MUTEX(uids_mutex); |
124 | 126 | ||
@@ -283,12 +285,12 @@ int __init uids_sysfs_init(void) | |||
283 | return uids_user_create(&root_user); | 285 | return uids_user_create(&root_user); |
284 | } | 286 | } |
285 | 287 | ||
286 | /* work function to remove sysfs directory for a user and free up | 288 | /* delayed work function to remove sysfs directory for a user and free up |
287 | * corresponding structures. | 289 | * corresponding structures. |
288 | */ | 290 | */ |
289 | static void cleanup_user_struct(struct work_struct *w) | 291 | static void cleanup_user_struct(struct work_struct *w) |
290 | { | 292 | { |
291 | struct user_struct *up = container_of(w, struct user_struct, work); | 293 | struct user_struct *up = container_of(w, struct user_struct, work.work); |
292 | unsigned long flags; | 294 | unsigned long flags; |
293 | int remove_user = 0; | 295 | int remove_user = 0; |
294 | 296 | ||
@@ -297,15 +299,12 @@ static void cleanup_user_struct(struct work_struct *w) | |||
297 | */ | 299 | */ |
298 | uids_mutex_lock(); | 300 | uids_mutex_lock(); |
299 | 301 | ||
300 | local_irq_save(flags); | 302 | spin_lock_irqsave(&uidhash_lock, flags); |
301 | 303 | if (atomic_read(&up->__count) == 0) { | |
302 | if (atomic_dec_and_lock(&up->__count, &uidhash_lock)) { | ||
303 | uid_hash_remove(up); | 304 | uid_hash_remove(up); |
304 | remove_user = 1; | 305 | remove_user = 1; |
305 | spin_unlock_irqrestore(&uidhash_lock, flags); | ||
306 | } else { | ||
307 | local_irq_restore(flags); | ||
308 | } | 306 | } |
307 | spin_unlock_irqrestore(&uidhash_lock, flags); | ||
309 | 308 | ||
310 | if (!remove_user) | 309 | if (!remove_user) |
311 | goto done; | 310 | goto done; |
@@ -331,16 +330,28 @@ done: | |||
331 | */ | 330 | */ |
332 | static void free_user(struct user_struct *up, unsigned long flags) | 331 | static void free_user(struct user_struct *up, unsigned long flags) |
333 | { | 332 | { |
334 | /* restore back the count */ | ||
335 | atomic_inc(&up->__count); | ||
336 | spin_unlock_irqrestore(&uidhash_lock, flags); | 333 | spin_unlock_irqrestore(&uidhash_lock, flags); |
337 | 334 | INIT_DELAYED_WORK(&up->work, cleanup_user_struct); | |
338 | INIT_WORK(&up->work, cleanup_user_struct); | 335 | schedule_delayed_work(&up->work, msecs_to_jiffies(1000)); |
339 | schedule_work(&up->work); | ||
340 | } | 336 | } |
341 | 337 | ||
342 | #else /* CONFIG_USER_SCHED && CONFIG_SYSFS */ | 338 | #else /* CONFIG_USER_SCHED && CONFIG_SYSFS */ |
343 | 339 | ||
340 | static struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent) | ||
341 | { | ||
342 | struct user_struct *user; | ||
343 | struct hlist_node *h; | ||
344 | |||
345 | hlist_for_each_entry(user, h, hashent, uidhash_node) { | ||
346 | if (user->uid == uid) { | ||
347 | atomic_inc(&user->__count); | ||
348 | return user; | ||
349 | } | ||
350 | } | ||
351 | |||
352 | return NULL; | ||
353 | } | ||
354 | |||
344 | int uids_sysfs_init(void) { return 0; } | 355 | int uids_sysfs_init(void) { return 0; } |
345 | static inline int uids_user_create(struct user_struct *up) { return 0; } | 356 | static inline int uids_user_create(struct user_struct *up) { return 0; } |
346 | static inline void uids_mutex_lock(void) { } | 357 | static inline void uids_mutex_lock(void) { } |