Merge tag 'block-5.19-2022-07-01' of git://git.kernel.dk/linux-block
[linux-2.6-block.git] / lib / ref_tracker.c
index a6789c0c626b0f68ad67c264cd19177a63fb82d2..dc7b14aa3431e2bf7a97a7e78220f04da144563d 100644 (file)
@@ -20,6 +20,7 @@ void ref_tracker_dir_exit(struct ref_tracker_dir *dir)
        unsigned long flags;
        bool leak = false;
 
+       dir->dead = true;
        spin_lock_irqsave(&dir->lock, flags);
        list_for_each_entry_safe(tracker, n, &dir->quarantine, head) {
                list_del(&tracker->head);
@@ -37,6 +38,7 @@ void ref_tracker_dir_exit(struct ref_tracker_dir *dir)
        spin_unlock_irqrestore(&dir->lock, flags);
        WARN_ON_ONCE(leak);
        WARN_ON_ONCE(refcount_read(&dir->untracked) != 1);
+       WARN_ON_ONCE(refcount_read(&dir->no_tracker) != 1);
 }
 EXPORT_SYMBOL(ref_tracker_dir_exit);
 
@@ -72,6 +74,12 @@ int ref_tracker_alloc(struct ref_tracker_dir *dir,
        gfp_t gfp_mask = gfp;
        unsigned long flags;
 
+       WARN_ON_ONCE(dir->dead);
+
+       if (!trackerp) {
+               refcount_inc(&dir->no_tracker);
+               return 0;
+       }
        if (gfp & __GFP_DIRECT_RECLAIM)
                gfp_mask |= __GFP_NOFAIL;
        *trackerp = tracker = kzalloc(sizeof(*tracker), gfp_mask);
@@ -81,7 +89,6 @@ int ref_tracker_alloc(struct ref_tracker_dir *dir,
                return -ENOMEM;
        }
        nr_entries = stack_trace_save(entries, ARRAY_SIZE(entries), 1);
-       nr_entries = filter_irq_stacks(entries, nr_entries);
        tracker->alloc_stack_handle = stack_depot_save(entries, nr_entries, gfp);
 
        spin_lock_irqsave(&dir->lock, flags);
@@ -95,17 +102,23 @@ int ref_tracker_free(struct ref_tracker_dir *dir,
                     struct ref_tracker **trackerp)
 {
        unsigned long entries[REF_TRACKER_STACK_ENTRIES];
-       struct ref_tracker *tracker = *trackerp;
        depot_stack_handle_t stack_handle;
+       struct ref_tracker *tracker;
        unsigned int nr_entries;
        unsigned long flags;
 
+       WARN_ON_ONCE(dir->dead);
+
+       if (!trackerp) {
+               refcount_dec(&dir->no_tracker);
+               return 0;
+       }
+       tracker = *trackerp;
        if (!tracker) {
                refcount_dec(&dir->untracked);
                return -EEXIST;
        }
        nr_entries = stack_trace_save(entries, ARRAY_SIZE(entries), 1);
-       nr_entries = filter_irq_stacks(entries, nr_entries);
        stack_handle = stack_depot_save(entries, nr_entries, GFP_ATOMIC);
 
        spin_lock_irqsave(&dir->lock, flags);