]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - lib/idr.c
dma-debug: add a schedule point in debug_dma_dump_mappings()
[mirror_ubuntu-bionic-kernel.git] / lib / idr.c
index edd9b2be1651fa99ae3a6274bda38c1bd7159a64..8dda36edf3149604b96ad7afa0540b331542d0ad 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -111,13 +111,27 @@ void *idr_get_next(struct idr *idr, int *nextid)
 {
        struct radix_tree_iter iter;
        void __rcu **slot;
-
-       slot = radix_tree_iter_find(&idr->idr_rt, &iter, *nextid);
+       void *entry = NULL;
+
+       radix_tree_for_each_slot(slot, &idr->idr_rt, &iter, *nextid) {
+               entry = rcu_dereference_raw(*slot);
+               if (!entry)
+                       continue;
+               if (!radix_tree_deref_retry(entry))
+                       break;
+               if (slot != (void *)&idr->idr_rt.rnode &&
+                               entry != (void *)RADIX_TREE_INTERNAL_NODE)
+                       break;
+               slot = radix_tree_iter_retry(&iter);
+       }
        if (!slot)
                return NULL;
 
+       if (WARN_ON_ONCE(iter.index > INT_MAX))
+               return NULL;
+
        *nextid = iter.index;
-       return rcu_dereference_raw(*slot);
+       return entry;
 }
 EXPORT_SYMBOL(idr_get_next);
 
@@ -171,7 +185,7 @@ void *idr_replace_ext(struct idr *idr, void *ptr, unsigned long id)
        if (!slot || radix_tree_tag_get(&idr->idr_rt, id, IDR_FREE))
                return ERR_PTR(-ENOENT);
 
-       __radix_tree_replace(&idr->idr_rt, node, slot, ptr, NULL, NULL);
+       __radix_tree_replace(&idr->idr_rt, node, slot, ptr, NULL);
 
        return entry;
 }