aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/cpumask.c4
-rw-r--r--lib/debugobjects.c127
-rw-r--r--lib/idr.c46
-rw-r--r--lib/vsprintf.c14
4 files changed, 167 insertions, 24 deletions
diff --git a/lib/cpumask.c b/lib/cpumask.c
index 3389e2440da0..1f71b97de0f9 100644
--- a/lib/cpumask.c
+++ b/lib/cpumask.c
@@ -109,10 +109,10 @@ bool alloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags, int node)
109#endif 109#endif
110 /* FIXME: Bandaid to save us from old primitives which go to NR_CPUS. */ 110 /* FIXME: Bandaid to save us from old primitives which go to NR_CPUS. */
111 if (*mask) { 111 if (*mask) {
112 unsigned char *ptr = (unsigned char *)cpumask_bits(*mask);
112 unsigned int tail; 113 unsigned int tail;
113 tail = BITS_TO_LONGS(NR_CPUS - nr_cpumask_bits) * sizeof(long); 114 tail = BITS_TO_LONGS(NR_CPUS - nr_cpumask_bits) * sizeof(long);
114 memset(cpumask_bits(*mask) + cpumask_size() - tail, 115 memset(ptr + cpumask_size() - tail, 0, tail);
115 0, tail);
116 } 116 }
117 117
118 return *mask != NULL; 118 return *mask != NULL;
diff --git a/lib/debugobjects.c b/lib/debugobjects.c
index 5d99be1fd988..2755a3bd16a1 100644
--- a/lib/debugobjects.c
+++ b/lib/debugobjects.c
@@ -30,7 +30,7 @@ struct debug_bucket {
30 30
31static struct debug_bucket obj_hash[ODEBUG_HASH_SIZE]; 31static struct debug_bucket obj_hash[ODEBUG_HASH_SIZE];
32 32
33static struct debug_obj obj_static_pool[ODEBUG_POOL_SIZE]; 33static struct debug_obj obj_static_pool[ODEBUG_POOL_SIZE] __initdata;
34 34
35static DEFINE_SPINLOCK(pool_lock); 35static DEFINE_SPINLOCK(pool_lock);
36 36
@@ -50,12 +50,23 @@ static int debug_objects_enabled __read_mostly
50 50
51static struct debug_obj_descr *descr_test __read_mostly; 51static struct debug_obj_descr *descr_test __read_mostly;
52 52
53static void free_obj_work(struct work_struct *work);
54static DECLARE_WORK(debug_obj_work, free_obj_work);
55
53static int __init enable_object_debug(char *str) 56static int __init enable_object_debug(char *str)
54{ 57{
55 debug_objects_enabled = 1; 58 debug_objects_enabled = 1;
56 return 0; 59 return 0;
57} 60}
61
62static int __init disable_object_debug(char *str)
63{
64 debug_objects_enabled = 0;
65 return 0;
66}
67
58early_param("debug_objects", enable_object_debug); 68early_param("debug_objects", enable_object_debug);
69early_param("no_debug_objects", disable_object_debug);
59 70
60static const char *obj_states[ODEBUG_STATE_MAX] = { 71static const char *obj_states[ODEBUG_STATE_MAX] = {
61 [ODEBUG_STATE_NONE] = "none", 72 [ODEBUG_STATE_NONE] = "none",
@@ -146,25 +157,51 @@ alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr)
146} 157}
147 158
148/* 159/*
149 * Put the object back into the pool or give it back to kmem_cache: 160 * workqueue function to free objects.
150 */ 161 */
151static void free_object(struct debug_obj *obj) 162static void free_obj_work(struct work_struct *work)
152{ 163{
153 unsigned long idx = (unsigned long)(obj - obj_static_pool); 164 struct debug_obj *obj;
154 unsigned long flags; 165 unsigned long flags;
155 166
156 if (obj_pool_free < ODEBUG_POOL_SIZE || idx < ODEBUG_POOL_SIZE) { 167 spin_lock_irqsave(&pool_lock, flags);
157 spin_lock_irqsave(&pool_lock, flags); 168 while (obj_pool_free > ODEBUG_POOL_SIZE) {
158 hlist_add_head(&obj->node, &obj_pool); 169 obj = hlist_entry(obj_pool.first, typeof(*obj), node);
159 obj_pool_free++; 170 hlist_del(&obj->node);
160 obj_pool_used--; 171 obj_pool_free--;
161 spin_unlock_irqrestore(&pool_lock, flags); 172 /*
162 } else { 173 * We release pool_lock across kmem_cache_free() to
163 spin_lock_irqsave(&pool_lock, flags); 174 * avoid contention on pool_lock.
164 obj_pool_used--; 175 */
165 spin_unlock_irqrestore(&pool_lock, flags); 176 spin_unlock_irqrestore(&pool_lock, flags);
166 kmem_cache_free(obj_cache, obj); 177 kmem_cache_free(obj_cache, obj);
178 spin_lock_irqsave(&pool_lock, flags);
167 } 179 }
180 spin_unlock_irqrestore(&pool_lock, flags);
181}
182
183/*
184 * Put the object back into the pool and schedule work to free objects
185 * if necessary.
186 */
187static void free_object(struct debug_obj *obj)
188{
189 unsigned long flags;
190 int sched = 0;
191
192 spin_lock_irqsave(&pool_lock, flags);
193 /*
194 * schedule work when the pool is filled and the cache is
195 * initialized:
196 */
197 if (obj_pool_free > ODEBUG_POOL_SIZE && obj_cache)
198 sched = !work_pending(&debug_obj_work);
199 hlist_add_head(&obj->node, &obj_pool);
200 obj_pool_free++;
201 obj_pool_used--;
202 spin_unlock_irqrestore(&pool_lock, flags);
203 if (sched)
204 schedule_work(&debug_obj_work);
168} 205}
169 206
170/* 207/*
@@ -876,6 +913,63 @@ void __init debug_objects_early_init(void)
876} 913}
877 914
878/* 915/*
916 * Convert the statically allocated objects to dynamic ones:
917 */
918static int debug_objects_replace_static_objects(void)
919{
920 struct debug_bucket *db = obj_hash;
921 struct hlist_node *node, *tmp;
922 struct debug_obj *obj, *new;
923 HLIST_HEAD(objects);
924 int i, cnt = 0;
925
926 for (i = 0; i < ODEBUG_POOL_SIZE; i++) {
927 obj = kmem_cache_zalloc(obj_cache, GFP_KERNEL);
928 if (!obj)
929 goto free;
930 hlist_add_head(&obj->node, &objects);
931 }
932
933 /*
934 * When debug_objects_mem_init() is called we know that only
935 * one CPU is up, so disabling interrupts is enough
936 * protection. This avoids the lockdep hell of lock ordering.
937 */
938 local_irq_disable();
939
940 /* Remove the statically allocated objects from the pool */
941 hlist_for_each_entry_safe(obj, node, tmp, &obj_pool, node)
942 hlist_del(&obj->node);
943 /* Move the allocated objects to the pool */
944 hlist_move_list(&objects, &obj_pool);
945
946 /* Replace the active object references */
947 for (i = 0; i < ODEBUG_HASH_SIZE; i++, db++) {
948 hlist_move_list(&db->list, &objects);
949
950 hlist_for_each_entry(obj, node, &objects, node) {
951 new = hlist_entry(obj_pool.first, typeof(*obj), node);
952 hlist_del(&new->node);
953 /* copy object data */
954 *new = *obj;
955 hlist_add_head(&new->node, &db->list);
956 cnt++;
957 }
958 }
959
960 printk(KERN_DEBUG "ODEBUG: %d of %d active objects replaced\n", cnt,
961 obj_pool_used);
962 local_irq_enable();
963 return 0;
964free:
965 hlist_for_each_entry_safe(obj, node, tmp, &objects, node) {
966 hlist_del(&obj->node);
967 kmem_cache_free(obj_cache, obj);
968 }
969 return -ENOMEM;
970}
971
972/*
879 * Called after the kmem_caches are functional to setup a dedicated 973 * Called after the kmem_caches are functional to setup a dedicated
880 * cache pool, which has the SLAB_DEBUG_OBJECTS flag set. This flag 974 * cache pool, which has the SLAB_DEBUG_OBJECTS flag set. This flag
881 * prevents that the debug code is called on kmem_cache_free() for the 975 * prevents that the debug code is called on kmem_cache_free() for the
@@ -890,8 +984,11 @@ void __init debug_objects_mem_init(void)
890 sizeof (struct debug_obj), 0, 984 sizeof (struct debug_obj), 0,
891 SLAB_DEBUG_OBJECTS, NULL); 985 SLAB_DEBUG_OBJECTS, NULL);
892 986
893 if (!obj_cache) 987 if (!obj_cache || debug_objects_replace_static_objects()) {
894 debug_objects_enabled = 0; 988 debug_objects_enabled = 0;
895 else 989 if (obj_cache)
990 kmem_cache_destroy(obj_cache);
991 printk(KERN_WARNING "ODEBUG: out of memory.\n");
992 } else
896 debug_objects_selftest(); 993 debug_objects_selftest();
897} 994}
diff --git a/lib/idr.c b/lib/idr.c
index dab4bca86f5d..80ca9aca038b 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -579,6 +579,52 @@ int idr_for_each(struct idr *idp,
579EXPORT_SYMBOL(idr_for_each); 579EXPORT_SYMBOL(idr_for_each);
580 580
581/** 581/**
582 * idr_get_next - lookup next object of id to given id.
583 * @idp: idr handle
584 * @id: pointer to lookup key
585 *
586 * Returns pointer to registered object with id, which is next number to
587 * given id.
588 */
589
590void *idr_get_next(struct idr *idp, int *nextidp)
591{
592 struct idr_layer *p, *pa[MAX_LEVEL];
593 struct idr_layer **paa = &pa[0];
594 int id = *nextidp;
595 int n, max;
596
597 /* find first ent */
598 n = idp->layers * IDR_BITS;
599 max = 1 << n;
600 p = rcu_dereference(idp->top);
601 if (!p)
602 return NULL;
603
604 while (id < max) {
605 while (n > 0 && p) {
606 n -= IDR_BITS;
607 *paa++ = p;
608 p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]);
609 }
610
611 if (p) {
612 *nextidp = id;
613 return p;
614 }
615
616 id += 1 << n;
617 while (n < fls(id)) {
618 n += IDR_BITS;
619 p = *--paa;
620 }
621 }
622 return NULL;
623}
624
625
626
627/**
582 * idr_replace - replace pointer for given id 628 * idr_replace - replace pointer for given id
583 * @idp: idr handle 629 * @idp: idr handle
584 * @ptr: pointer you want associated with the id 630 * @ptr: pointer you want associated with the id
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index dc1674377009..be3001f912e4 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -398,7 +398,7 @@ static noinline char* put_dec(char *buf, unsigned long long num)
398 398
399enum format_type { 399enum format_type {
400 FORMAT_TYPE_NONE, /* Just a string part */ 400 FORMAT_TYPE_NONE, /* Just a string part */
401 FORMAT_TYPE_WITDH, 401 FORMAT_TYPE_WIDTH,
402 FORMAT_TYPE_PRECISION, 402 FORMAT_TYPE_PRECISION,
403 FORMAT_TYPE_CHAR, 403 FORMAT_TYPE_CHAR,
404 FORMAT_TYPE_STR, 404 FORMAT_TYPE_STR,
@@ -770,7 +770,7 @@ static int format_decode(const char *fmt, struct printf_spec *spec)
770 const char *start = fmt; 770 const char *start = fmt;
771 771
772 /* we finished early by reading the field width */ 772 /* we finished early by reading the field width */
773 if (spec->type == FORMAT_TYPE_WITDH) { 773 if (spec->type == FORMAT_TYPE_WIDTH) {
774 if (spec->field_width < 0) { 774 if (spec->field_width < 0) {
775 spec->field_width = -spec->field_width; 775 spec->field_width = -spec->field_width;
776 spec->flags |= LEFT; 776 spec->flags |= LEFT;
@@ -828,7 +828,7 @@ static int format_decode(const char *fmt, struct printf_spec *spec)
828 spec->field_width = skip_atoi(&fmt); 828 spec->field_width = skip_atoi(&fmt);
829 else if (*fmt == '*') { 829 else if (*fmt == '*') {
830 /* it's the next argument */ 830 /* it's the next argument */
831 spec->type = FORMAT_TYPE_WITDH; 831 spec->type = FORMAT_TYPE_WIDTH;
832 return ++fmt - start; 832 return ++fmt - start;
833 } 833 }
834 834
@@ -843,7 +843,7 @@ precision:
843 spec->precision = 0; 843 spec->precision = 0;
844 } else if (*fmt == '*') { 844 } else if (*fmt == '*') {
845 /* it's the next argument */ 845 /* it's the next argument */
846 spec->type = FORMAT_TYPE_WITDH; 846 spec->type = FORMAT_TYPE_PRECISION;
847 return ++fmt - start; 847 return ++fmt - start;
848 } 848 }
849 } 849 }
@@ -1002,7 +1002,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
1002 break; 1002 break;
1003 } 1003 }
1004 1004
1005 case FORMAT_TYPE_WITDH: 1005 case FORMAT_TYPE_WIDTH:
1006 spec.field_width = va_arg(args, int); 1006 spec.field_width = va_arg(args, int);
1007 break; 1007 break;
1008 1008
@@ -1306,7 +1306,7 @@ do { \
1306 case FORMAT_TYPE_NONE: 1306 case FORMAT_TYPE_NONE:
1307 break; 1307 break;
1308 1308
1309 case FORMAT_TYPE_WITDH: 1309 case FORMAT_TYPE_WIDTH:
1310 case FORMAT_TYPE_PRECISION: 1310 case FORMAT_TYPE_PRECISION:
1311 save_arg(int); 1311 save_arg(int);
1312 break; 1312 break;
@@ -1472,7 +1472,7 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
1472 break; 1472 break;
1473 } 1473 }
1474 1474
1475 case FORMAT_TYPE_WITDH: 1475 case FORMAT_TYPE_WIDTH:
1476 spec.field_width = get_arg(int); 1476 spec.field_width = get_arg(int);
1477 break; 1477 break;
1478 1478