aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2010-05-25 02:38:26 -0400
committerGrant Likely <grant.likely@secretlab.ca>2010-05-25 02:38:26 -0400
commitb1e50ebcf24668e57f058deb48b0704b5391ed0f (patch)
tree17e1b69b249d0738317b732186340c9dd053f1a1 /lib
parent0c2a2ae32793e3500a15a449612485f5d17dd431 (diff)
parent7e125f7b9cbfce4101191b8076d606c517a73066 (diff)
Merge remote branch 'origin' into secretlab/next-spi
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig.debug21
-rw-r--r--lib/Kconfig.kgdb24
-rw-r--r--lib/Makefile5
-rw-r--r--lib/atomic64.c4
-rw-r--r--lib/atomic64_test.c164
-rw-r--r--lib/bug.c2
-rw-r--r--lib/debugobjects.c63
-rw-r--r--lib/hweight.c19
-rw-r--r--lib/idr.c2
-rw-r--r--lib/kobject.c115
-rw-r--r--lib/kobject_uevent.c109
-rw-r--r--lib/kref.c15
-rw-r--r--lib/rbtree.c48
13 files changed, 542 insertions, 49 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 935248bdbc47..d85be90d5888 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -512,6 +512,18 @@ config PROVE_RCU
512 512
513 Say N if you are unsure. 513 Say N if you are unsure.
514 514
515config PROVE_RCU_REPEATEDLY
516 bool "RCU debugging: don't disable PROVE_RCU on first splat"
517 depends on PROVE_RCU
518 default n
519 help
520 By itself, PROVE_RCU will disable checking upon issuing the
521 first warning (or "splat"). This feature prevents such
522 disabling, allowing multiple RCU-lockdep warnings to be printed
523 on a single reboot.
524
525 Say N if you are unsure.
526
515config LOCKDEP 527config LOCKDEP
516 bool 528 bool
517 depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT 529 depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
@@ -793,7 +805,7 @@ config RCU_CPU_STALL_DETECTOR
793config RCU_CPU_STALL_VERBOSE 805config RCU_CPU_STALL_VERBOSE
794 bool "Print additional per-task information for RCU_CPU_STALL_DETECTOR" 806 bool "Print additional per-task information for RCU_CPU_STALL_DETECTOR"
795 depends on RCU_CPU_STALL_DETECTOR && TREE_PREEMPT_RCU 807 depends on RCU_CPU_STALL_DETECTOR && TREE_PREEMPT_RCU
796 default n 808 default y
797 help 809 help
798 This option causes RCU to printk detailed per-task information 810 This option causes RCU to printk detailed per-task information
799 for any tasks that are stalling the current RCU grace period. 811 for any tasks that are stalling the current RCU grace period.
@@ -1086,6 +1098,13 @@ config DMA_API_DEBUG
1086 This option causes a performance degredation. Use only if you want 1098 This option causes a performance degredation. Use only if you want
1087 to debug device drivers. If unsure, say N. 1099 to debug device drivers. If unsure, say N.
1088 1100
1101config ATOMIC64_SELFTEST
1102 bool "Perform an atomic64_t self-test at boot"
1103 help
1104 Enable this option to test the atomic64_t functions at boot.
1105
1106 If unsure, say N.
1107
1089source "samples/Kconfig" 1108source "samples/Kconfig"
1090 1109
1091source "lib/Kconfig.kgdb" 1110source "lib/Kconfig.kgdb"
diff --git a/lib/Kconfig.kgdb b/lib/Kconfig.kgdb
index 9b5d1d7f2ef7..43cb93fa2651 100644
--- a/lib/Kconfig.kgdb
+++ b/lib/Kconfig.kgdb
@@ -3,7 +3,7 @@ config HAVE_ARCH_KGDB
3 bool 3 bool
4 4
5menuconfig KGDB 5menuconfig KGDB
6 bool "KGDB: kernel debugging with remote gdb" 6 bool "KGDB: kernel debugger"
7 depends on HAVE_ARCH_KGDB 7 depends on HAVE_ARCH_KGDB
8 depends on DEBUG_KERNEL && EXPERIMENTAL 8 depends on DEBUG_KERNEL && EXPERIMENTAL
9 help 9 help
@@ -57,4 +57,26 @@ config KGDB_TESTS_BOOT_STRING
57 information about other strings you could use beyond the 57 information about other strings you could use beyond the
58 default of V1F100. 58 default of V1F100.
59 59
60config KGDB_LOW_LEVEL_TRAP
61 bool "KGDB: Allow debugging with traps in notifiers"
62 depends on X86 || MIPS
63 default n
64 help
65 This will add an extra call back to kgdb for the breakpoint
66 exception handler on which will will allow kgdb to step
67 through a notify handler.
68
69config KGDB_KDB
70 bool "KGDB_KDB: include kdb frontend for kgdb"
71 default n
72 help
73 KDB frontend for kernel
74
75config KDB_KEYBOARD
76 bool "KGDB_KDB: keyboard as input device"
77 depends on VT && KGDB_KDB
78 default n
79 help
80 KDB can use a PS/2 type keyboard for an input device
81
60endif # KGDB 82endif # KGDB
diff --git a/lib/Makefile b/lib/Makefile
index 0d4015205c64..9e6d3c29d73a 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -39,7 +39,10 @@ lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
39lib-$(CONFIG_GENERIC_FIND_FIRST_BIT) += find_next_bit.o 39lib-$(CONFIG_GENERIC_FIND_FIRST_BIT) += find_next_bit.o
40lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o 40lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
41obj-$(CONFIG_GENERIC_FIND_LAST_BIT) += find_last_bit.o 41obj-$(CONFIG_GENERIC_FIND_LAST_BIT) += find_last_bit.o
42
43CFLAGS_hweight.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS))
42obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o 44obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
45
43obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o 46obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
44obj-$(CONFIG_BTREE) += btree.o 47obj-$(CONFIG_BTREE) += btree.o
45obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o 48obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
@@ -101,6 +104,8 @@ obj-$(CONFIG_GENERIC_CSUM) += checksum.o
101 104
102obj-$(CONFIG_GENERIC_ATOMIC64) += atomic64.o 105obj-$(CONFIG_GENERIC_ATOMIC64) += atomic64.o
103 106
107obj-$(CONFIG_ATOMIC64_SELFTEST) += atomic64_test.o
108
104hostprogs-y := gen_crc32table 109hostprogs-y := gen_crc32table
105clean-files := crc32table.h 110clean-files := crc32table.h
106 111
diff --git a/lib/atomic64.c b/lib/atomic64.c
index 8bee16ec7524..a21c12bc727c 100644
--- a/lib/atomic64.c
+++ b/lib/atomic64.c
@@ -162,12 +162,12 @@ int atomic64_add_unless(atomic64_t *v, long long a, long long u)
162{ 162{
163 unsigned long flags; 163 unsigned long flags;
164 spinlock_t *lock = lock_addr(v); 164 spinlock_t *lock = lock_addr(v);
165 int ret = 1; 165 int ret = 0;
166 166
167 spin_lock_irqsave(lock, flags); 167 spin_lock_irqsave(lock, flags);
168 if (v->counter != u) { 168 if (v->counter != u) {
169 v->counter += a; 169 v->counter += a;
170 ret = 0; 170 ret = 1;
171 } 171 }
172 spin_unlock_irqrestore(lock, flags); 172 spin_unlock_irqrestore(lock, flags);
173 return ret; 173 return ret;
diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c
new file mode 100644
index 000000000000..65e482caf5e9
--- /dev/null
+++ b/lib/atomic64_test.c
@@ -0,0 +1,164 @@
1/*
2 * Testsuite for atomic64_t functions
3 *
4 * Copyright © 2010 Luca Barbieri
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11#include <linux/init.h>
12#include <asm/atomic.h>
13
14#define INIT(c) do { atomic64_set(&v, c); r = c; } while (0)
15static __init int test_atomic64(void)
16{
17 long long v0 = 0xaaa31337c001d00dLL;
18 long long v1 = 0xdeadbeefdeafcafeLL;
19 long long v2 = 0xfaceabadf00df001LL;
20 long long onestwos = 0x1111111122222222LL;
21 long long one = 1LL;
22
23 atomic64_t v = ATOMIC64_INIT(v0);
24 long long r = v0;
25 BUG_ON(v.counter != r);
26
27 atomic64_set(&v, v1);
28 r = v1;
29 BUG_ON(v.counter != r);
30 BUG_ON(atomic64_read(&v) != r);
31
32 INIT(v0);
33 atomic64_add(onestwos, &v);
34 r += onestwos;
35 BUG_ON(v.counter != r);
36
37 INIT(v0);
38 atomic64_add(-one, &v);
39 r += -one;
40 BUG_ON(v.counter != r);
41
42 INIT(v0);
43 r += onestwos;
44 BUG_ON(atomic64_add_return(onestwos, &v) != r);
45 BUG_ON(v.counter != r);
46
47 INIT(v0);
48 r += -one;
49 BUG_ON(atomic64_add_return(-one, &v) != r);
50 BUG_ON(v.counter != r);
51
52 INIT(v0);
53 atomic64_sub(onestwos, &v);
54 r -= onestwos;
55 BUG_ON(v.counter != r);
56
57 INIT(v0);
58 atomic64_sub(-one, &v);
59 r -= -one;
60 BUG_ON(v.counter != r);
61
62 INIT(v0);
63 r -= onestwos;
64 BUG_ON(atomic64_sub_return(onestwos, &v) != r);
65 BUG_ON(v.counter != r);
66
67 INIT(v0);
68 r -= -one;
69 BUG_ON(atomic64_sub_return(-one, &v) != r);
70 BUG_ON(v.counter != r);
71
72 INIT(v0);
73 atomic64_inc(&v);
74 r += one;
75 BUG_ON(v.counter != r);
76
77 INIT(v0);
78 r += one;
79 BUG_ON(atomic64_inc_return(&v) != r);
80 BUG_ON(v.counter != r);
81
82 INIT(v0);
83 atomic64_dec(&v);
84 r -= one;
85 BUG_ON(v.counter != r);
86
87 INIT(v0);
88 r -= one;
89 BUG_ON(atomic64_dec_return(&v) != r);
90 BUG_ON(v.counter != r);
91
92 INIT(v0);
93 BUG_ON(atomic64_xchg(&v, v1) != v0);
94 r = v1;
95 BUG_ON(v.counter != r);
96
97 INIT(v0);
98 BUG_ON(atomic64_cmpxchg(&v, v0, v1) != v0);
99 r = v1;
100 BUG_ON(v.counter != r);
101
102 INIT(v0);
103 BUG_ON(atomic64_cmpxchg(&v, v2, v1) != v0);
104 BUG_ON(v.counter != r);
105
106 INIT(v0);
107 BUG_ON(atomic64_add_unless(&v, one, v0));
108 BUG_ON(v.counter != r);
109
110 INIT(v0);
111 BUG_ON(!atomic64_add_unless(&v, one, v1));
112 r += one;
113 BUG_ON(v.counter != r);
114
115#if defined(CONFIG_X86) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(_ASM_GENERIC_ATOMIC64_H)
116 INIT(onestwos);
117 BUG_ON(atomic64_dec_if_positive(&v) != (onestwos - 1));
118 r -= one;
119 BUG_ON(v.counter != r);
120
121 INIT(0);
122 BUG_ON(atomic64_dec_if_positive(&v) != -one);
123 BUG_ON(v.counter != r);
124
125 INIT(-one);
126 BUG_ON(atomic64_dec_if_positive(&v) != (-one - one));
127 BUG_ON(v.counter != r);
128#else
129#warning Please implement atomic64_dec_if_positive for your architecture, and add it to the IF above
130#endif
131
132 INIT(onestwos);
133 BUG_ON(!atomic64_inc_not_zero(&v));
134 r += one;
135 BUG_ON(v.counter != r);
136
137 INIT(0);
138 BUG_ON(atomic64_inc_not_zero(&v));
139 BUG_ON(v.counter != r);
140
141 INIT(-one);
142 BUG_ON(!atomic64_inc_not_zero(&v));
143 r += one;
144 BUG_ON(v.counter != r);
145
146#ifdef CONFIG_X86
147 printk(KERN_INFO "atomic64 test passed for %s platform %s CX8 and %s SSE\n",
148#ifdef CONFIG_X86_64
149 "x86-64",
150#elif defined(CONFIG_X86_CMPXCHG64)
151 "i586+",
152#else
153 "i386+",
154#endif
155 boot_cpu_has(X86_FEATURE_CX8) ? "with" : "without",
156 boot_cpu_has(X86_FEATURE_XMM) ? "with" : "without");
157#else
158 printk(KERN_INFO "atomic64 test passed\n");
159#endif
160
161 return 0;
162}
163
164core_initcall(test_atomic64);
diff --git a/lib/bug.c b/lib/bug.c
index 300e41afbf97..f13daf435211 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -165,7 +165,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
165 (void *)bugaddr); 165 (void *)bugaddr);
166 166
167 show_regs(regs); 167 show_regs(regs);
168 add_taint(TAINT_WARN); 168 add_taint(BUG_GET_TAINT(bug));
169 return BUG_TRAP_TYPE_WARN; 169 return BUG_TRAP_TYPE_WARN;
170 } 170 }
171 171
diff --git a/lib/debugobjects.c b/lib/debugobjects.c
index b862b30369ff..deebcc57d4e6 100644
--- a/lib/debugobjects.c
+++ b/lib/debugobjects.c
@@ -141,6 +141,7 @@ alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr)
141 obj->object = addr; 141 obj->object = addr;
142 obj->descr = descr; 142 obj->descr = descr;
143 obj->state = ODEBUG_STATE_NONE; 143 obj->state = ODEBUG_STATE_NONE;
144 obj->astate = 0;
144 hlist_del(&obj->node); 145 hlist_del(&obj->node);
145 146
146 hlist_add_head(&obj->node, &b->list); 147 hlist_add_head(&obj->node, &b->list);
@@ -252,8 +253,10 @@ static void debug_print_object(struct debug_obj *obj, char *msg)
252 253
253 if (limit < 5 && obj->descr != descr_test) { 254 if (limit < 5 && obj->descr != descr_test) {
254 limit++; 255 limit++;
255 WARN(1, KERN_ERR "ODEBUG: %s %s object type: %s\n", msg, 256 WARN(1, KERN_ERR "ODEBUG: %s %s (active state %u) "
256 obj_states[obj->state], obj->descr->name); 257 "object type: %s\n",
258 msg, obj_states[obj->state], obj->astate,
259 obj->descr->name);
257 } 260 }
258 debug_objects_warnings++; 261 debug_objects_warnings++;
259} 262}
@@ -447,7 +450,10 @@ void debug_object_deactivate(void *addr, struct debug_obj_descr *descr)
447 case ODEBUG_STATE_INIT: 450 case ODEBUG_STATE_INIT:
448 case ODEBUG_STATE_INACTIVE: 451 case ODEBUG_STATE_INACTIVE:
449 case ODEBUG_STATE_ACTIVE: 452 case ODEBUG_STATE_ACTIVE:
450 obj->state = ODEBUG_STATE_INACTIVE; 453 if (!obj->astate)
454 obj->state = ODEBUG_STATE_INACTIVE;
455 else
456 debug_print_object(obj, "deactivate");
451 break; 457 break;
452 458
453 case ODEBUG_STATE_DESTROYED: 459 case ODEBUG_STATE_DESTROYED:
@@ -553,6 +559,53 @@ out_unlock:
553 raw_spin_unlock_irqrestore(&db->lock, flags); 559 raw_spin_unlock_irqrestore(&db->lock, flags);
554} 560}
555 561
562/**
563 * debug_object_active_state - debug checks object usage state machine
564 * @addr: address of the object
565 * @descr: pointer to an object specific debug description structure
566 * @expect: expected state
567 * @next: state to move to if expected state is found
568 */
569void
570debug_object_active_state(void *addr, struct debug_obj_descr *descr,
571 unsigned int expect, unsigned int next)
572{
573 struct debug_bucket *db;
574 struct debug_obj *obj;
575 unsigned long flags;
576
577 if (!debug_objects_enabled)
578 return;
579
580 db = get_bucket((unsigned long) addr);
581
582 raw_spin_lock_irqsave(&db->lock, flags);
583
584 obj = lookup_object(addr, db);
585 if (obj) {
586 switch (obj->state) {
587 case ODEBUG_STATE_ACTIVE:
588 if (obj->astate == expect)
589 obj->astate = next;
590 else
591 debug_print_object(obj, "active_state");
592 break;
593
594 default:
595 debug_print_object(obj, "active_state");
596 break;
597 }
598 } else {
599 struct debug_obj o = { .object = addr,
600 .state = ODEBUG_STATE_NOTAVAILABLE,
601 .descr = descr };
602
603 debug_print_object(&o, "active_state");
604 }
605
606 raw_spin_unlock_irqrestore(&db->lock, flags);
607}
608
556#ifdef CONFIG_DEBUG_OBJECTS_FREE 609#ifdef CONFIG_DEBUG_OBJECTS_FREE
557static void __debug_check_no_obj_freed(const void *address, unsigned long size) 610static void __debug_check_no_obj_freed(const void *address, unsigned long size)
558{ 611{
@@ -774,7 +827,7 @@ static int __init fixup_free(void *addr, enum debug_obj_state state)
774 } 827 }
775} 828}
776 829
777static int 830static int __init
778check_results(void *addr, enum debug_obj_state state, int fixups, int warnings) 831check_results(void *addr, enum debug_obj_state state, int fixups, int warnings)
779{ 832{
780 struct debug_bucket *db; 833 struct debug_bucket *db;
@@ -917,7 +970,7 @@ void __init debug_objects_early_init(void)
917/* 970/*
918 * Convert the statically allocated objects to dynamic ones: 971 * Convert the statically allocated objects to dynamic ones:
919 */ 972 */
920static int debug_objects_replace_static_objects(void) 973static int __init debug_objects_replace_static_objects(void)
921{ 974{
922 struct debug_bucket *db = obj_hash; 975 struct debug_bucket *db = obj_hash;
923 struct hlist_node *node, *tmp; 976 struct hlist_node *node, *tmp;
diff --git a/lib/hweight.c b/lib/hweight.c
index 63ee4eb1228d..3c79d50814cf 100644
--- a/lib/hweight.c
+++ b/lib/hweight.c
@@ -9,7 +9,7 @@
9 * The Hamming Weight of a number is the total number of bits set in it. 9 * The Hamming Weight of a number is the total number of bits set in it.
10 */ 10 */
11 11
12unsigned int hweight32(unsigned int w) 12unsigned int __sw_hweight32(unsigned int w)
13{ 13{
14#ifdef ARCH_HAS_FAST_MULTIPLIER 14#ifdef ARCH_HAS_FAST_MULTIPLIER
15 w -= (w >> 1) & 0x55555555; 15 w -= (w >> 1) & 0x55555555;
@@ -24,29 +24,30 @@ unsigned int hweight32(unsigned int w)
24 return (res + (res >> 16)) & 0x000000FF; 24 return (res + (res >> 16)) & 0x000000FF;
25#endif 25#endif
26} 26}
27EXPORT_SYMBOL(hweight32); 27EXPORT_SYMBOL(__sw_hweight32);
28 28
29unsigned int hweight16(unsigned int w) 29unsigned int __sw_hweight16(unsigned int w)
30{ 30{
31 unsigned int res = w - ((w >> 1) & 0x5555); 31 unsigned int res = w - ((w >> 1) & 0x5555);
32 res = (res & 0x3333) + ((res >> 2) & 0x3333); 32 res = (res & 0x3333) + ((res >> 2) & 0x3333);
33 res = (res + (res >> 4)) & 0x0F0F; 33 res = (res + (res >> 4)) & 0x0F0F;
34 return (res + (res >> 8)) & 0x00FF; 34 return (res + (res >> 8)) & 0x00FF;
35} 35}
36EXPORT_SYMBOL(hweight16); 36EXPORT_SYMBOL(__sw_hweight16);
37 37
38unsigned int hweight8(unsigned int w) 38unsigned int __sw_hweight8(unsigned int w)
39{ 39{
40 unsigned int res = w - ((w >> 1) & 0x55); 40 unsigned int res = w - ((w >> 1) & 0x55);
41 res = (res & 0x33) + ((res >> 2) & 0x33); 41 res = (res & 0x33) + ((res >> 2) & 0x33);
42 return (res + (res >> 4)) & 0x0F; 42 return (res + (res >> 4)) & 0x0F;
43} 43}
44EXPORT_SYMBOL(hweight8); 44EXPORT_SYMBOL(__sw_hweight8);
45 45
46unsigned long hweight64(__u64 w) 46unsigned long __sw_hweight64(__u64 w)
47{ 47{
48#if BITS_PER_LONG == 32 48#if BITS_PER_LONG == 32
49 return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w); 49 return __sw_hweight32((unsigned int)(w >> 32)) +
50 __sw_hweight32((unsigned int)w);
50#elif BITS_PER_LONG == 64 51#elif BITS_PER_LONG == 64
51#ifdef ARCH_HAS_FAST_MULTIPLIER 52#ifdef ARCH_HAS_FAST_MULTIPLIER
52 w -= (w >> 1) & 0x5555555555555555ul; 53 w -= (w >> 1) & 0x5555555555555555ul;
@@ -63,4 +64,4 @@ unsigned long hweight64(__u64 w)
63#endif 64#endif
64#endif 65#endif
65} 66}
66EXPORT_SYMBOL(hweight64); 67EXPORT_SYMBOL(__sw_hweight64);
diff --git a/lib/idr.c b/lib/idr.c
index 2eb1dca03681..422a9d5069cc 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -623,7 +623,7 @@ void *idr_get_next(struct idr *idp, int *nextidp)
623 } 623 }
624 return NULL; 624 return NULL;
625} 625}
626 626EXPORT_SYMBOL(idr_get_next);
627 627
628 628
629/** 629/**
diff --git a/lib/kobject.c b/lib/kobject.c
index 8115eb1bbf4d..f07c57252e82 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -850,6 +850,121 @@ struct kset *kset_create_and_add(const char *name,
850} 850}
851EXPORT_SYMBOL_GPL(kset_create_and_add); 851EXPORT_SYMBOL_GPL(kset_create_and_add);
852 852
853
854static DEFINE_SPINLOCK(kobj_ns_type_lock);
855static const struct kobj_ns_type_operations *kobj_ns_ops_tbl[KOBJ_NS_TYPES];
856
857int kobj_ns_type_register(const struct kobj_ns_type_operations *ops)
858{
859 enum kobj_ns_type type = ops->type;
860 int error;
861
862 spin_lock(&kobj_ns_type_lock);
863
864 error = -EINVAL;
865 if (type >= KOBJ_NS_TYPES)
866 goto out;
867
868 error = -EINVAL;
869 if (type <= KOBJ_NS_TYPE_NONE)
870 goto out;
871
872 error = -EBUSY;
873 if (kobj_ns_ops_tbl[type])
874 goto out;
875
876 error = 0;
877 kobj_ns_ops_tbl[type] = ops;
878
879out:
880 spin_unlock(&kobj_ns_type_lock);
881 return error;
882}
883
884int kobj_ns_type_registered(enum kobj_ns_type type)
885{
886 int registered = 0;
887
888 spin_lock(&kobj_ns_type_lock);
889 if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES))
890 registered = kobj_ns_ops_tbl[type] != NULL;
891 spin_unlock(&kobj_ns_type_lock);
892
893 return registered;
894}
895
896const struct kobj_ns_type_operations *kobj_child_ns_ops(struct kobject *parent)
897{
898 const struct kobj_ns_type_operations *ops = NULL;
899
900 if (parent && parent->ktype->child_ns_type)
901 ops = parent->ktype->child_ns_type(parent);
902
903 return ops;
904}
905
906const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj)
907{
908 return kobj_child_ns_ops(kobj->parent);
909}
910
911
912const void *kobj_ns_current(enum kobj_ns_type type)
913{
914 const void *ns = NULL;
915
916 spin_lock(&kobj_ns_type_lock);
917 if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) &&
918 kobj_ns_ops_tbl[type])
919 ns = kobj_ns_ops_tbl[type]->current_ns();
920 spin_unlock(&kobj_ns_type_lock);
921
922 return ns;
923}
924
925const void *kobj_ns_netlink(enum kobj_ns_type type, struct sock *sk)
926{
927 const void *ns = NULL;
928
929 spin_lock(&kobj_ns_type_lock);
930 if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) &&
931 kobj_ns_ops_tbl[type])
932 ns = kobj_ns_ops_tbl[type]->netlink_ns(sk);
933 spin_unlock(&kobj_ns_type_lock);
934
935 return ns;
936}
937
938const void *kobj_ns_initial(enum kobj_ns_type type)
939{
940 const void *ns = NULL;
941
942 spin_lock(&kobj_ns_type_lock);
943 if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) &&
944 kobj_ns_ops_tbl[type])
945 ns = kobj_ns_ops_tbl[type]->initial_ns();
946 spin_unlock(&kobj_ns_type_lock);
947
948 return ns;
949}
950
951/*
952 * kobj_ns_exit - invalidate a namespace tag
953 *
954 * @type: the namespace type (i.e. KOBJ_NS_TYPE_NET)
955 * @ns: the actual namespace being invalidated
956 *
957 * This is called when a tag is no longer valid. For instance,
958 * when a network namespace exits, it uses this helper to
959 * make sure no sb's sysfs_info points to the now-invalidated
960 * netns.
961 */
962void kobj_ns_exit(enum kobj_ns_type type, const void *ns)
963{
964 sysfs_exit_ns(type, ns);
965}
966
967
853EXPORT_SYMBOL(kobject_get); 968EXPORT_SYMBOL(kobject_get);
854EXPORT_SYMBOL(kobject_put); 969EXPORT_SYMBOL(kobject_put);
855EXPORT_SYMBOL(kobject_del); 970EXPORT_SYMBOL(kobject_del);
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 7b48d44ced6e..59c15511d58a 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -19,18 +19,24 @@
19#include <linux/kobject.h> 19#include <linux/kobject.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/slab.h> 21#include <linux/slab.h>
22 22#include <linux/user_namespace.h>
23#include <linux/socket.h> 23#include <linux/socket.h>
24#include <linux/skbuff.h> 24#include <linux/skbuff.h>
25#include <linux/netlink.h> 25#include <linux/netlink.h>
26#include <net/sock.h> 26#include <net/sock.h>
27#include <net/net_namespace.h>
27 28
28 29
29u64 uevent_seqnum; 30u64 uevent_seqnum;
30char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH; 31char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
31static DEFINE_SPINLOCK(sequence_lock); 32static DEFINE_SPINLOCK(sequence_lock);
32#if defined(CONFIG_NET) 33#ifdef CONFIG_NET
33static struct sock *uevent_sock; 34struct uevent_sock {
35 struct list_head list;
36 struct sock *sk;
37};
38static LIST_HEAD(uevent_sock_list);
39static DEFINE_MUTEX(uevent_sock_mutex);
34#endif 40#endif
35 41
36/* the strings here must match the enum in include/linux/kobject.h */ 42/* the strings here must match the enum in include/linux/kobject.h */
@@ -77,6 +83,37 @@ out:
77 return ret; 83 return ret;
78} 84}
79 85
86static int kobj_bcast_filter(struct sock *dsk, struct sk_buff *skb, void *data)
87{
88 struct kobject *kobj = data;
89 const struct kobj_ns_type_operations *ops;
90
91 ops = kobj_ns_ops(kobj);
92 if (ops) {
93 const void *sock_ns, *ns;
94 ns = kobj->ktype->namespace(kobj);
95 sock_ns = ops->netlink_ns(dsk);
96 return sock_ns != ns;
97 }
98
99 return 0;
100}
101
102static int kobj_usermode_filter(struct kobject *kobj)
103{
104 const struct kobj_ns_type_operations *ops;
105
106 ops = kobj_ns_ops(kobj);
107 if (ops) {
108 const void *init_ns, *ns;
109 ns = kobj->ktype->namespace(kobj);
110 init_ns = ops->initial_ns();
111 return ns != init_ns;
112 }
113
114 return 0;
115}
116
80/** 117/**
81 * kobject_uevent_env - send an uevent with environmental data 118 * kobject_uevent_env - send an uevent with environmental data
82 * 119 *
@@ -100,6 +137,9 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
100 u64 seq; 137 u64 seq;
101 int i = 0; 138 int i = 0;
102 int retval = 0; 139 int retval = 0;
140#ifdef CONFIG_NET
141 struct uevent_sock *ue_sk;
142#endif
103 143
104 pr_debug("kobject: '%s' (%p): %s\n", 144 pr_debug("kobject: '%s' (%p): %s\n",
105 kobject_name(kobj), kobj, __func__); 145 kobject_name(kobj), kobj, __func__);
@@ -211,7 +251,9 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
211 251
212#if defined(CONFIG_NET) 252#if defined(CONFIG_NET)
213 /* send netlink message */ 253 /* send netlink message */
214 if (uevent_sock) { 254 mutex_lock(&uevent_sock_mutex);
255 list_for_each_entry(ue_sk, &uevent_sock_list, list) {
256 struct sock *uevent_sock = ue_sk->sk;
215 struct sk_buff *skb; 257 struct sk_buff *skb;
216 size_t len; 258 size_t len;
217 259
@@ -233,18 +275,21 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
233 } 275 }
234 276
235 NETLINK_CB(skb).dst_group = 1; 277 NETLINK_CB(skb).dst_group = 1;
236 retval = netlink_broadcast(uevent_sock, skb, 0, 1, 278 retval = netlink_broadcast_filtered(uevent_sock, skb,
237 GFP_KERNEL); 279 0, 1, GFP_KERNEL,
280 kobj_bcast_filter,
281 kobj);
238 /* ENOBUFS should be handled in userspace */ 282 /* ENOBUFS should be handled in userspace */
239 if (retval == -ENOBUFS) 283 if (retval == -ENOBUFS)
240 retval = 0; 284 retval = 0;
241 } else 285 } else
242 retval = -ENOMEM; 286 retval = -ENOMEM;
243 } 287 }
288 mutex_unlock(&uevent_sock_mutex);
244#endif 289#endif
245 290
246 /* call uevent_helper, usually only enabled during early boot */ 291 /* call uevent_helper, usually only enabled during early boot */
247 if (uevent_helper[0]) { 292 if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
248 char *argv [3]; 293 char *argv [3];
249 294
250 argv [0] = uevent_helper; 295 argv [0] = uevent_helper;
@@ -320,18 +365,58 @@ int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
320EXPORT_SYMBOL_GPL(add_uevent_var); 365EXPORT_SYMBOL_GPL(add_uevent_var);
321 366
322#if defined(CONFIG_NET) 367#if defined(CONFIG_NET)
323static int __init kobject_uevent_init(void) 368static int uevent_net_init(struct net *net)
324{ 369{
325 uevent_sock = netlink_kernel_create(&init_net, NETLINK_KOBJECT_UEVENT, 370 struct uevent_sock *ue_sk;
326 1, NULL, NULL, THIS_MODULE); 371
327 if (!uevent_sock) { 372 ue_sk = kzalloc(sizeof(*ue_sk), GFP_KERNEL);
373 if (!ue_sk)
374 return -ENOMEM;
375
376 ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT,
377 1, NULL, NULL, THIS_MODULE);
378 if (!ue_sk->sk) {
328 printk(KERN_ERR 379 printk(KERN_ERR
329 "kobject_uevent: unable to create netlink socket!\n"); 380 "kobject_uevent: unable to create netlink socket!\n");
330 return -ENODEV; 381 return -ENODEV;
331 } 382 }
332 netlink_set_nonroot(NETLINK_KOBJECT_UEVENT, NL_NONROOT_RECV); 383 mutex_lock(&uevent_sock_mutex);
384 list_add_tail(&ue_sk->list, &uevent_sock_list);
385 mutex_unlock(&uevent_sock_mutex);
333 return 0; 386 return 0;
334} 387}
335 388
389static void uevent_net_exit(struct net *net)
390{
391 struct uevent_sock *ue_sk;
392
393 mutex_lock(&uevent_sock_mutex);
394 list_for_each_entry(ue_sk, &uevent_sock_list, list) {
395 if (sock_net(ue_sk->sk) == net)
396 goto found;
397 }
398 mutex_unlock(&uevent_sock_mutex);
399 return;
400
401found:
402 list_del(&ue_sk->list);
403 mutex_unlock(&uevent_sock_mutex);
404
405 netlink_kernel_release(ue_sk->sk);
406 kfree(ue_sk);
407}
408
409static struct pernet_operations uevent_net_ops = {
410 .init = uevent_net_init,
411 .exit = uevent_net_exit,
412};
413
414static int __init kobject_uevent_init(void)
415{
416 netlink_set_nonroot(NETLINK_KOBJECT_UEVENT, NL_NONROOT_RECV);
417 return register_pernet_subsys(&uevent_net_ops);
418}
419
420
336postcore_initcall(kobject_uevent_init); 421postcore_initcall(kobject_uevent_init);
337#endif 422#endif
diff --git a/lib/kref.c b/lib/kref.c
index 6d19f690380b..d3d227a08a4b 100644
--- a/lib/kref.c
+++ b/lib/kref.c
@@ -16,23 +16,13 @@
16#include <linux/slab.h> 16#include <linux/slab.h>
17 17
18/** 18/**
19 * kref_set - initialize object and set refcount to requested number.
20 * @kref: object in question.
21 * @num: initial reference counter
22 */
23void kref_set(struct kref *kref, int num)
24{
25 atomic_set(&kref->refcount, num);
26 smp_mb();
27}
28
29/**
30 * kref_init - initialize object. 19 * kref_init - initialize object.
31 * @kref: object in question. 20 * @kref: object in question.
32 */ 21 */
33void kref_init(struct kref *kref) 22void kref_init(struct kref *kref)
34{ 23{
35 kref_set(kref, 1); 24 atomic_set(&kref->refcount, 1);
25 smp_mb();
36} 26}
37 27
38/** 28/**
@@ -72,7 +62,6 @@ int kref_put(struct kref *kref, void (*release)(struct kref *kref))
72 return 0; 62 return 0;
73} 63}
74 64
75EXPORT_SYMBOL(kref_set);
76EXPORT_SYMBOL(kref_init); 65EXPORT_SYMBOL(kref_init);
77EXPORT_SYMBOL(kref_get); 66EXPORT_SYMBOL(kref_get);
78EXPORT_SYMBOL(kref_put); 67EXPORT_SYMBOL(kref_put);
diff --git a/lib/rbtree.c b/lib/rbtree.c
index e2aa3be29858..15e10b1afdd2 100644
--- a/lib/rbtree.c
+++ b/lib/rbtree.c
@@ -44,6 +44,11 @@ static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
44 else 44 else
45 root->rb_node = right; 45 root->rb_node = right;
46 rb_set_parent(node, right); 46 rb_set_parent(node, right);
47
48 if (root->augment_cb) {
49 root->augment_cb(node);
50 root->augment_cb(right);
51 }
47} 52}
48 53
49static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) 54static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
@@ -67,12 +72,20 @@ static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
67 else 72 else
68 root->rb_node = left; 73 root->rb_node = left;
69 rb_set_parent(node, left); 74 rb_set_parent(node, left);
75
76 if (root->augment_cb) {
77 root->augment_cb(node);
78 root->augment_cb(left);
79 }
70} 80}
71 81
72void rb_insert_color(struct rb_node *node, struct rb_root *root) 82void rb_insert_color(struct rb_node *node, struct rb_root *root)
73{ 83{
74 struct rb_node *parent, *gparent; 84 struct rb_node *parent, *gparent;
75 85
86 if (root->augment_cb)
87 root->augment_cb(node);
88
76 while ((parent = rb_parent(node)) && rb_is_red(parent)) 89 while ((parent = rb_parent(node)) && rb_is_red(parent))
77 { 90 {
78 gparent = rb_parent(parent); 91 gparent = rb_parent(parent);
@@ -227,12 +240,15 @@ void rb_erase(struct rb_node *node, struct rb_root *root)
227 else 240 else
228 { 241 {
229 struct rb_node *old = node, *left; 242 struct rb_node *old = node, *left;
243 int old_parent_cb = 0;
244 int successor_parent_cb = 0;
230 245
231 node = node->rb_right; 246 node = node->rb_right;
232 while ((left = node->rb_left) != NULL) 247 while ((left = node->rb_left) != NULL)
233 node = left; 248 node = left;
234 249
235 if (rb_parent(old)) { 250 if (rb_parent(old)) {
251 old_parent_cb = 1;
236 if (rb_parent(old)->rb_left == old) 252 if (rb_parent(old)->rb_left == old)
237 rb_parent(old)->rb_left = node; 253 rb_parent(old)->rb_left = node;
238 else 254 else
@@ -247,8 +263,10 @@ void rb_erase(struct rb_node *node, struct rb_root *root)
247 if (parent == old) { 263 if (parent == old) {
248 parent = node; 264 parent = node;
249 } else { 265 } else {
266 successor_parent_cb = 1;
250 if (child) 267 if (child)
251 rb_set_parent(child, parent); 268 rb_set_parent(child, parent);
269
252 parent->rb_left = child; 270 parent->rb_left = child;
253 271
254 node->rb_right = old->rb_right; 272 node->rb_right = old->rb_right;
@@ -259,6 +277,24 @@ void rb_erase(struct rb_node *node, struct rb_root *root)
259 node->rb_left = old->rb_left; 277 node->rb_left = old->rb_left;
260 rb_set_parent(old->rb_left, node); 278 rb_set_parent(old->rb_left, node);
261 279
280 if (root->augment_cb) {
281 /*
282 * Here, three different nodes can have new children.
283 * The parent of the successor node that was selected
284 * to replace the node to be erased.
285 * The node that is getting erased and is now replaced
286 * by its successor.
287 * The parent of the node getting erased-replaced.
288 */
289 if (successor_parent_cb)
290 root->augment_cb(parent);
291
292 root->augment_cb(node);
293
294 if (old_parent_cb)
295 root->augment_cb(rb_parent(old));
296 }
297
262 goto color; 298 goto color;
263 } 299 }
264 300
@@ -267,15 +303,19 @@ void rb_erase(struct rb_node *node, struct rb_root *root)
267 303
268 if (child) 304 if (child)
269 rb_set_parent(child, parent); 305 rb_set_parent(child, parent);
270 if (parent) 306
271 { 307 if (parent) {
272 if (parent->rb_left == node) 308 if (parent->rb_left == node)
273 parent->rb_left = child; 309 parent->rb_left = child;
274 else 310 else
275 parent->rb_right = child; 311 parent->rb_right = child;
276 } 312
277 else 313 if (root->augment_cb)
314 root->augment_cb(parent);
315
316 } else {
278 root->rb_node = child; 317 root->rb_node = child;
318 }
279 319
280 color: 320 color:
281 if (color == RB_BLACK) 321 if (color == RB_BLACK)