aboutsummaryrefslogtreecommitdiffstats
path: root/lib/debugobjects.c
diff options
context:
space:
mode:
authorYang Shi <yang.shi@linux.alibaba.com>2018-02-05 18:18:28 -0500
committerThomas Gleixner <tglx@linutronix.de>2018-02-13 04:59:18 -0500
commit1ea9b98b007a662e402551a41a4413becad40a65 (patch)
treecef4f8fbd02f40a5df91a22a9b6469c90f0a3d4a /lib/debugobjects.c
parent636e1970fd7deaa0d0ee0dfb6ac65fbd690b32d2 (diff)
debugobjects: Use global free list in __debug_check_no_obj_freed()
__debug_check_no_obj_freed() iterates over the to be freed memory region in chunks and iterates over the corresponding hash bucket list for each chunk. This can accumulate to hundred thousands of checked objects. In the worst case this can trigger the soft lockup detector: NMI watchdog: BUG: soft lockup - CPU#15 stuck for 22s! CPU: 15 PID: 110342 Comm: stress-ng-getde Call Trace: [<ffffffff8141177e>] debug_check_no_obj_freed+0x13e/0x220 [<ffffffff811f8751>] __free_pages_ok+0x1f1/0x5c0 [<ffffffff811fa785>] __free_pages+0x25/0x40 [<ffffffff812638db>] __free_slab+0x19b/0x270 [<ffffffff812639e9>] discard_slab+0x39/0x50 [<ffffffff812679f7>] __slab_free+0x207/0x270 [<ffffffff81269966>] ___cache_free+0xa6/0xb0 [<ffffffff8126c267>] qlist_free_all+0x47/0x80 [<ffffffff8126c5a9>] quarantine_reduce+0x159/0x190 [<ffffffff8126b3bf>] kasan_kmalloc+0xaf/0xc0 [<ffffffff8126b8a2>] kasan_slab_alloc+0x12/0x20 [<ffffffff81265e8a>] kmem_cache_alloc+0xfa/0x360 [<ffffffff812abc8f>] ? getname_flags+0x4f/0x1f0 [<ffffffff812abc8f>] getname_flags+0x4f/0x1f0 [<ffffffff812abe42>] getname+0x12/0x20 [<ffffffff81298da9>] do_sys_open+0xf9/0x210 [<ffffffff81298ede>] SyS_open+0x1e/0x20 [<ffffffff817d6e01>] entry_SYSCALL_64_fastpath+0x1f/0xc2 The code path might be called in either atomic or non-atomic context, but in_atomic() can't tell if the current context is atomic or not on a PREEMPT=n kernel, so cond_resched() can't be used to prevent the softlockup. Utilize the global free list to shorten the loop execution time. [ tglx: Massaged changelog ] Suggested-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Yang Shi <yang.shi@linux.alibaba.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: longman@redhat.com Link: https://lkml.kernel.org/r/1517872708-24207-5-git-send-email-yang.shi@linux.alibaba.com
Diffstat (limited to 'lib/debugobjects.c')
-rw-r--r--lib/debugobjects.c16
1 files changed, 7 insertions, 9 deletions
diff --git a/lib/debugobjects.c b/lib/debugobjects.c
index 3e79c100271f..faab2c4ea024 100644
--- a/lib/debugobjects.c
+++ b/lib/debugobjects.c
@@ -751,13 +751,13 @@ EXPORT_SYMBOL_GPL(debug_object_active_state);
751static void __debug_check_no_obj_freed(const void *address, unsigned long size) 751static void __debug_check_no_obj_freed(const void *address, unsigned long size)
752{ 752{
753 unsigned long flags, oaddr, saddr, eaddr, paddr, chunks; 753 unsigned long flags, oaddr, saddr, eaddr, paddr, chunks;
754 struct hlist_node *tmp;
755 HLIST_HEAD(freelist);
756 struct debug_obj_descr *descr; 754 struct debug_obj_descr *descr;
757 enum debug_obj_state state; 755 enum debug_obj_state state;
758 struct debug_bucket *db; 756 struct debug_bucket *db;
757 struct hlist_node *tmp;
759 struct debug_obj *obj; 758 struct debug_obj *obj;
760 int cnt, objs_checked = 0; 759 int cnt, objs_checked = 0;
760 bool work = false;
761 761
762 saddr = (unsigned long) address; 762 saddr = (unsigned long) address;
763 eaddr = saddr + size; 763 eaddr = saddr + size;
@@ -788,18 +788,12 @@ repeat:
788 goto repeat; 788 goto repeat;
789 default: 789 default:
790 hlist_del(&obj->node); 790 hlist_del(&obj->node);
791 hlist_add_head(&obj->node, &freelist); 791 work |= __free_object(obj);
792 break; 792 break;
793 } 793 }
794 } 794 }
795 raw_spin_unlock_irqrestore(&db->lock, flags); 795 raw_spin_unlock_irqrestore(&db->lock, flags);
796 796
797 /* Now free them */
798 hlist_for_each_entry_safe(obj, tmp, &freelist, node) {
799 hlist_del(&obj->node);
800 free_object(obj);
801 }
802
803 if (cnt > debug_objects_maxchain) 797 if (cnt > debug_objects_maxchain)
804 debug_objects_maxchain = cnt; 798 debug_objects_maxchain = cnt;
805 799
@@ -808,6 +802,10 @@ repeat:
808 802
809 if (objs_checked > debug_objects_maxchecked) 803 if (objs_checked > debug_objects_maxchecked)
810 debug_objects_maxchecked = objs_checked; 804 debug_objects_maxchecked = objs_checked;
805
806 /* Schedule work to actually kmem_cache_free() objects */
807 if (work)
808 schedule_work(&debug_obj_work);
811} 809}
812 810
813void debug_check_no_obj_freed(const void *address, unsigned long size) 811void debug_check_no_obj_freed(const void *address, unsigned long size)