aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig.debug11
-rw-r--r--lib/dma-debug.c1
-rw-r--r--lib/dynamic_debug.c98
-rw-r--r--lib/idr.c13
-rw-r--r--lib/kobject.c39
5 files changed, 130 insertions, 32 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 21ac83070a80..69a32664c289 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -353,7 +353,7 @@ config SLUB_DEBUG_ON
353config SLUB_STATS 353config SLUB_STATS
354 default n 354 default n
355 bool "Enable SLUB performance statistics" 355 bool "Enable SLUB performance statistics"
356 depends on SLUB && SLUB_DEBUG && SYSFS 356 depends on SLUB && SYSFS
357 help 357 help
358 SLUB statistics are useful to debug SLUBs allocation behavior in 358 SLUB statistics are useful to debug SLUBs allocation behavior in
359 order find ways to optimize the allocator. This should never be 359 order find ways to optimize the allocator. This should never be
@@ -461,6 +461,15 @@ config DEBUG_MUTEXES
461 This feature allows mutex semantics violations to be detected and 461 This feature allows mutex semantics violations to be detected and
462 reported. 462 reported.
463 463
464config BKL
465 bool "Big Kernel Lock" if (SMP || PREEMPT)
466 default y
467 help
468 This is the traditional lock that is used in old code instead
469 of proper locking. All drivers that use the BKL should depend
470 on this symbol.
471 Say Y here unless you are working on removing the BKL.
472
464config DEBUG_LOCK_ALLOC 473config DEBUG_LOCK_ALLOC
465 bool "Lock debugging: detect incorrect freeing of live locks" 474 bool "Lock debugging: detect incorrect freeing of live locks"
466 depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT 475 depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index 01e64270e246..4bfb0471f106 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -590,6 +590,7 @@ out_unlock:
590static const struct file_operations filter_fops = { 590static const struct file_operations filter_fops = {
591 .read = filter_read, 591 .read = filter_read,
592 .write = filter_write, 592 .write = filter_write,
593 .llseek = default_llseek,
593}; 594};
594 595
595static int dma_debug_fs_init(void) 596static int dma_debug_fs_init(void)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 7bd6df781ce5..3094318bfea7 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -393,6 +393,40 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
393 return 0; 393 return 0;
394} 394}
395 395
396static int ddebug_exec_query(char *query_string)
397{
398 unsigned int flags = 0, mask = 0;
399 struct ddebug_query query;
400#define MAXWORDS 9
401 int nwords;
402 char *words[MAXWORDS];
403
404 nwords = ddebug_tokenize(query_string, words, MAXWORDS);
405 if (nwords <= 0)
406 return -EINVAL;
407 if (ddebug_parse_query(words, nwords-1, &query))
408 return -EINVAL;
409 if (ddebug_parse_flags(words[nwords-1], &flags, &mask))
410 return -EINVAL;
411
412 /* actually go and implement the change */
413 ddebug_change(&query, flags, mask);
414 return 0;
415}
416
417static __initdata char ddebug_setup_string[1024];
418static __init int ddebug_setup_query(char *str)
419{
420 if (strlen(str) >= 1024) {
421 pr_warning("ddebug boot param string too large\n");
422 return 0;
423 }
424 strcpy(ddebug_setup_string, str);
425 return 1;
426}
427
428__setup("ddebug_query=", ddebug_setup_query);
429
396/* 430/*
397 * File_ops->write method for <debugfs>/dynamic_debug/conrol. Gathers the 431 * File_ops->write method for <debugfs>/dynamic_debug/conrol. Gathers the
398 * command text from userspace, parses and executes it. 432 * command text from userspace, parses and executes it.
@@ -400,12 +434,8 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
400static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf, 434static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf,
401 size_t len, loff_t *offp) 435 size_t len, loff_t *offp)
402{ 436{
403 unsigned int flags = 0, mask = 0;
404 struct ddebug_query query;
405#define MAXWORDS 9
406 int nwords;
407 char *words[MAXWORDS];
408 char tmpbuf[256]; 437 char tmpbuf[256];
438 int ret;
409 439
410 if (len == 0) 440 if (len == 0)
411 return 0; 441 return 0;
@@ -419,16 +449,9 @@ static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf,
419 printk(KERN_INFO "%s: read %d bytes from userspace\n", 449 printk(KERN_INFO "%s: read %d bytes from userspace\n",
420 __func__, (int)len); 450 __func__, (int)len);
421 451
422 nwords = ddebug_tokenize(tmpbuf, words, MAXWORDS); 452 ret = ddebug_exec_query(tmpbuf);
423 if (nwords <= 0) 453 if (ret)
424 return -EINVAL; 454 return ret;
425 if (ddebug_parse_query(words, nwords-1, &query))
426 return -EINVAL;
427 if (ddebug_parse_flags(words[nwords-1], &flags, &mask))
428 return -EINVAL;
429
430 /* actually go and implement the change */
431 ddebug_change(&query, flags, mask);
432 455
433 *offp += len; 456 *offp += len;
434 return len; 457 return len;
@@ -689,13 +712,14 @@ static void ddebug_remove_all_tables(void)
689 mutex_unlock(&ddebug_lock); 712 mutex_unlock(&ddebug_lock);
690} 713}
691 714
692static int __init dynamic_debug_init(void) 715static __initdata int ddebug_init_success;
716
717static int __init dynamic_debug_init_debugfs(void)
693{ 718{
694 struct dentry *dir, *file; 719 struct dentry *dir, *file;
695 struct _ddebug *iter, *iter_start; 720
696 const char *modname = NULL; 721 if (!ddebug_init_success)
697 int ret = 0; 722 return -ENODEV;
698 int n = 0;
699 723
700 dir = debugfs_create_dir("dynamic_debug", NULL); 724 dir = debugfs_create_dir("dynamic_debug", NULL);
701 if (!dir) 725 if (!dir)
@@ -706,6 +730,16 @@ static int __init dynamic_debug_init(void)
706 debugfs_remove(dir); 730 debugfs_remove(dir);
707 return -ENOMEM; 731 return -ENOMEM;
708 } 732 }
733 return 0;
734}
735
736static int __init dynamic_debug_init(void)
737{
738 struct _ddebug *iter, *iter_start;
739 const char *modname = NULL;
740 int ret = 0;
741 int n = 0;
742
709 if (__start___verbose != __stop___verbose) { 743 if (__start___verbose != __stop___verbose) {
710 iter = __start___verbose; 744 iter = __start___verbose;
711 modname = iter->modname; 745 modname = iter->modname;
@@ -723,12 +757,26 @@ static int __init dynamic_debug_init(void)
723 } 757 }
724 ret = ddebug_add_module(iter_start, n, modname); 758 ret = ddebug_add_module(iter_start, n, modname);
725 } 759 }
760
761 /* ddebug_query boot param got passed -> set it up */
762 if (ddebug_setup_string[0] != '\0') {
763 ret = ddebug_exec_query(ddebug_setup_string);
764 if (ret)
765 pr_warning("Invalid ddebug boot param %s",
766 ddebug_setup_string);
767 else
768 pr_info("ddebug initialized with string %s",
769 ddebug_setup_string);
770 }
771
726out_free: 772out_free:
727 if (ret) { 773 if (ret)
728 ddebug_remove_all_tables(); 774 ddebug_remove_all_tables();
729 debugfs_remove(dir); 775 else
730 debugfs_remove(file); 776 ddebug_init_success = 1;
731 }
732 return 0; 777 return 0;
733} 778}
734module_init(dynamic_debug_init); 779/* Allow early initialization for boot messages via boot param */
780arch_initcall(dynamic_debug_init);
781/* Debugfs setup must be done later */
782module_init(dynamic_debug_init_debugfs);
diff --git a/lib/idr.c b/lib/idr.c
index 7f1a4f0acf50..5e0966be0f7c 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -284,7 +284,7 @@ static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
284 * idr_get_new_above - allocate new idr entry above or equal to a start id 284 * idr_get_new_above - allocate new idr entry above or equal to a start id
285 * @idp: idr handle 285 * @idp: idr handle
286 * @ptr: pointer you want associated with the id 286 * @ptr: pointer you want associated with the id
287 * @start_id: id to start search at 287 * @starting_id: id to start search at
288 * @id: pointer to the allocated handle 288 * @id: pointer to the allocated handle
289 * 289 *
290 * This is the allocate id function. It should be called with any 290 * This is the allocate id function. It should be called with any
@@ -479,7 +479,7 @@ EXPORT_SYMBOL(idr_remove_all);
479 479
480/** 480/**
481 * idr_destroy - release all cached layers within an idr tree 481 * idr_destroy - release all cached layers within an idr tree
482 * idp: idr handle 482 * @idp: idr handle
483 */ 483 */
484void idr_destroy(struct idr *idp) 484void idr_destroy(struct idr *idp)
485{ 485{
@@ -586,10 +586,11 @@ EXPORT_SYMBOL(idr_for_each);
586/** 586/**
587 * idr_get_next - lookup next object of id to given id. 587 * idr_get_next - lookup next object of id to given id.
588 * @idp: idr handle 588 * @idp: idr handle
589 * @id: pointer to lookup key 589 * @nextidp: pointer to lookup key
590 * 590 *
591 * Returns pointer to registered object with id, which is next number to 591 * Returns pointer to registered object with id, which is next number to
592 * given id. 592 * given id. After being looked up, *@nextidp will be updated for the next
593 * iteration.
593 */ 594 */
594 595
595void *idr_get_next(struct idr *idp, int *nextidp) 596void *idr_get_next(struct idr *idp, int *nextidp)
@@ -758,7 +759,7 @@ EXPORT_SYMBOL(ida_pre_get);
758/** 759/**
759 * ida_get_new_above - allocate new ID above or equal to a start id 760 * ida_get_new_above - allocate new ID above or equal to a start id
760 * @ida: ida handle 761 * @ida: ida handle
761 * @staring_id: id to start search at 762 * @starting_id: id to start search at
762 * @p_id: pointer to the allocated handle 763 * @p_id: pointer to the allocated handle
763 * 764 *
764 * Allocate new ID above or equal to @ida. It should be called with 765 * Allocate new ID above or equal to @ida. It should be called with
@@ -912,7 +913,7 @@ EXPORT_SYMBOL(ida_remove);
912 913
913/** 914/**
914 * ida_destroy - release all cached layers within an ida tree 915 * ida_destroy - release all cached layers within an ida tree
915 * ida: ida handle 916 * @ida: ida handle
916 */ 917 */
917void ida_destroy(struct ida *ida) 918void ida_destroy(struct ida *ida)
918{ 919{
diff --git a/lib/kobject.c b/lib/kobject.c
index f07c57252e82..82dc34c095c2 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -746,17 +746,56 @@ void kset_unregister(struct kset *k)
746 */ 746 */
747struct kobject *kset_find_obj(struct kset *kset, const char *name) 747struct kobject *kset_find_obj(struct kset *kset, const char *name)
748{ 748{
749 return kset_find_obj_hinted(kset, name, NULL);
750}
751
752/**
753 * kset_find_obj_hinted - search for object in kset given a predecessor hint.
754 * @kset: kset we're looking in.
755 * @name: object's name.
756 * @hint: hint to possible object's predecessor.
757 *
758 * Check the hint's next object and if it is a match return it directly,
759 * otherwise, fall back to the behavior of kset_find_obj(). Either way
760 * a reference for the returned object is held and the reference on the
761 * hinted object is released.
762 */
763struct kobject *kset_find_obj_hinted(struct kset *kset, const char *name,
764 struct kobject *hint)
765{
749 struct kobject *k; 766 struct kobject *k;
750 struct kobject *ret = NULL; 767 struct kobject *ret = NULL;
751 768
752 spin_lock(&kset->list_lock); 769 spin_lock(&kset->list_lock);
770
771 if (!hint)
772 goto slow_search;
773
774 /* end of list detection */
775 if (hint->entry.next == kset->list.next)
776 goto slow_search;
777
778 k = container_of(hint->entry.next, struct kobject, entry);
779 if (!kobject_name(k) || strcmp(kobject_name(k), name))
780 goto slow_search;
781
782 ret = kobject_get(k);
783 goto unlock_exit;
784
785slow_search:
753 list_for_each_entry(k, &kset->list, entry) { 786 list_for_each_entry(k, &kset->list, entry) {
754 if (kobject_name(k) && !strcmp(kobject_name(k), name)) { 787 if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
755 ret = kobject_get(k); 788 ret = kobject_get(k);
756 break; 789 break;
757 } 790 }
758 } 791 }
792
793unlock_exit:
759 spin_unlock(&kset->list_lock); 794 spin_unlock(&kset->list_lock);
795
796 if (hint)
797 kobject_put(hint);
798
760 return ret; 799 return ret;
761} 800}
762 801