lkml.org 
[lkml]   [2022]   [Feb]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 1/9] lib/ref_tracker: add unlocked leak print helper
    Date
    To have reliable detection of leaks, caller must be able to check under the same
    lock both: tracked counter and the leaks. dir.lock is natural candidate for such
    lock and unlocked print helper can be called with this lock taken.
    As a bonus we can reuse this helper in ref_tracker_dir_exit.

    Signed-off-by: Andrzej Hajda <andrzej.hajda@intel.com>
    Reviewed-by: Chris Wilson <chris.p.wilson@intel.com>
    ---
    include/linux/ref_tracker.h | 8 +++++
    lib/ref_tracker.c | 66 +++++++++++++++++++++----------------
    2 files changed, 46 insertions(+), 28 deletions(-)

    diff --git a/include/linux/ref_tracker.h b/include/linux/ref_tracker.h
    index 60f3453be23e6..b9c968a716483 100644
    --- a/include/linux/ref_tracker.h
    +++ b/include/linux/ref_tracker.h
    @@ -32,6 +32,9 @@ static inline void ref_tracker_dir_init(struct ref_tracker_dir *dir,

    void ref_tracker_dir_exit(struct ref_tracker_dir *dir);

    +void __ref_tracker_dir_print(struct ref_tracker_dir *dir,
    + unsigned int display_limit);
    +
    void ref_tracker_dir_print(struct ref_tracker_dir *dir,
    unsigned int display_limit);

    @@ -52,6 +55,11 @@ static inline void ref_tracker_dir_exit(struct ref_tracker_dir *dir)
    {
    }

    +static inline void __ref_tracker_dir_print(struct ref_tracker_dir *dir,
    + unsigned int display_limit)
    +{
    +}
    +
    static inline void ref_tracker_dir_print(struct ref_tracker_dir *dir,
    unsigned int display_limit)
    {
    diff --git a/lib/ref_tracker.c b/lib/ref_tracker.c
    index a6789c0c626b0..1b0c6d645d64a 100644
    --- a/lib/ref_tracker.c
    +++ b/lib/ref_tracker.c
    @@ -14,6 +14,38 @@ struct ref_tracker {
    depot_stack_handle_t free_stack_handle;
    };

    +void __ref_tracker_dir_print(struct ref_tracker_dir *dir,
    + unsigned int display_limit)
    +{
    + struct ref_tracker *tracker;
    + unsigned int i = 0;
    +
    + lockdep_assert_held(&dir->lock);
    +
    + list_for_each_entry(tracker, &dir->list, head) {
    + if (i < display_limit) {
    + pr_err("leaked reference.\n");
    + if (tracker->alloc_stack_handle)
    + stack_depot_print(tracker->alloc_stack_handle);
    + i++;
    + } else {
    + break;
    + }
    + }
    +}
    +EXPORT_SYMBOL(__ref_tracker_dir_print);
    +
    +void ref_tracker_dir_print(struct ref_tracker_dir *dir,
    + unsigned int display_limit)
    +{
    + unsigned long flags;
    +
    + spin_lock_irqsave(&dir->lock, flags);
    + __ref_tracker_dir_print(dir, display_limit);
    + spin_unlock_irqrestore(&dir->lock, flags);
    +}
    +EXPORT_SYMBOL(ref_tracker_dir_print);
    +
    void ref_tracker_dir_exit(struct ref_tracker_dir *dir)
    {
    struct ref_tracker *tracker, *n;
    @@ -26,13 +58,13 @@ void ref_tracker_dir_exit(struct ref_tracker_dir *dir)
    kfree(tracker);
    dir->quarantine_avail++;
    }
    - list_for_each_entry_safe(tracker, n, &dir->list, head) {
    - pr_err("leaked reference.\n");
    - if (tracker->alloc_stack_handle)
    - stack_depot_print(tracker->alloc_stack_handle);
    + if (!list_empty(&dir->list)) {
    + __ref_tracker_dir_print(dir, 16);
    leak = true;
    - list_del(&tracker->head);
    - kfree(tracker);
    + list_for_each_entry_safe(tracker, n, &dir->list, head) {
    + list_del(&tracker->head);
    + kfree(tracker);
    + }
    }
    spin_unlock_irqrestore(&dir->lock, flags);
    WARN_ON_ONCE(leak);
    @@ -40,28 +72,6 @@ void ref_tracker_dir_exit(struct ref_tracker_dir *dir)
    }
    EXPORT_SYMBOL(ref_tracker_dir_exit);

    -void ref_tracker_dir_print(struct ref_tracker_dir *dir,
    - unsigned int display_limit)
    -{
    - struct ref_tracker *tracker;
    - unsigned long flags;
    - unsigned int i = 0;
    -
    - spin_lock_irqsave(&dir->lock, flags);
    - list_for_each_entry(tracker, &dir->list, head) {
    - if (i < display_limit) {
    - pr_err("leaked reference.\n");
    - if (tracker->alloc_stack_handle)
    - stack_depot_print(tracker->alloc_stack_handle);
    - i++;
    - } else {
    - break;
    - }
    - }
    - spin_unlock_irqrestore(&dir->lock, flags);
    -}
    -EXPORT_SYMBOL(ref_tracker_dir_print);
    -
    int ref_tracker_alloc(struct ref_tracker_dir *dir,
    struct ref_tracker **trackerp,
    gfp_t gfp)
    --
    2.25.1
    \
     
     \ /
      Last update: 2022-02-17 15:06    [W:5.055 / U:1.340 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site