Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121// SPDX-License-Identifier: GPL-2.0/* * KUnit helpers for backtrace suppression * * Copyright (C) 2025 Alessandro Carminati <acarmina@redhat.com> * Copyright (C) 2024 Guenter Roeck <linux@roeck-us.net> */
#include <kunit/resource.h>#include <linux/export.h>#include <linux/rculist.h>#include <linux/sched.h>#include <linux/sched/task.h>#include <linux/spinlock.h>
#include "hooks-impl.h"
struct kunit_suppressed_warning { struct list_head node; struct task_struct *task; struct kunit *test; atomic_t counter;};
static LIST_HEAD(suppressed_warnings);static DEFINE_SPINLOCK(suppressed_warnings_lock);
static void kunit_suppress_warning_remove(struct kunit_suppressed_warning *w){ unsigned long flags;
spin_lock_irqsave(&suppressed_warnings_lock, flags); list_del_rcu(&w->node); spin_unlock_irqrestore(&suppressed_warnings_lock, flags); put_task_struct(w->task);}
KUNIT_DEFINE_ACTION_WRAPPER(kunit_suppress_warning_cleanup, kunit_suppress_warning_remove, struct kunit_suppressed_warning *);
bool kunit_has_active_suppress_warning(void){ return __kunit_is_suppressed_warning_impl(false);}EXPORT_SYMBOL_GPL(kunit_has_active_suppress_warning);
struct kunit_suppressed_warning *kunit_start_suppress_warning(struct kunit *test){ struct kunit_suppressed_warning *w; unsigned long flags; int ret;
if (kunit_has_active_suppress_warning()) { KUNIT_FAIL(test, "Another suppression block is already active"); return NULL; }
w = kunit_kzalloc(test, sizeof(*w), GFP_KERNEL); if (!w) { KUNIT_FAIL(test, "Failed to allocate suppression handle."); return NULL; }
w->task = get_task_struct(current); w->test = test;
spin_lock_irqsave(&suppressed_warnings_lock, flags); list_add_rcu(&w->node, &suppressed_warnings); spin_unlock_irqrestore(&suppressed_warnings_lock, flags);
ret = kunit_add_action_or_reset(test, kunit_suppress_warning_cleanup, w); if (ret) { KUNIT_FAIL(test, "Failed to add suppression cleanup action."); return NULL; }
return w;}EXPORT_SYMBOL_GPL(kunit_start_suppress_warning);
void kunit_end_suppress_warning(struct kunit *test, struct kunit_suppressed_warning *w){ if (!w) return; kunit_release_action(test, kunit_suppress_warning_cleanup, w);}EXPORT_SYMBOL_GPL(kunit_end_suppress_warning);
void __kunit_suppress_auto_cleanup(struct kunit_suppressed_warning **wp){ if (*wp) kunit_end_suppress_warning((*wp)->test, *wp);}EXPORT_SYMBOL_GPL(__kunit_suppress_auto_cleanup);
int kunit_suppressed_warning_count(struct kunit_suppressed_warning *w){ return w ? atomic_read(&w->counter) : 0;}EXPORT_SYMBOL_GPL(kunit_suppressed_warning_count);
bool __kunit_is_suppressed_warning_impl(bool count){ struct kunit_suppressed_warning *w;
guard(rcu)(); list_for_each_entry_rcu(w, &suppressed_warnings, node) { if (w->task == current) { if (count) atomic_inc(&w->counter); return true; } }
return false;}