diff options
Diffstat (limited to 'lib/idr.c')
-rw-r--r-- | lib/idr.c | 24 |
1 files changed, 17 insertions, 7 deletions
@@ -38,6 +38,15 @@ | |||
38 | #include <linux/percpu.h> | 38 | #include <linux/percpu.h> |
39 | #include <linux/hardirq.h> | 39 | #include <linux/hardirq.h> |
40 | 40 | ||
41 | #define MAX_IDR_SHIFT (sizeof(int) * 8 - 1) | ||
42 | #define MAX_IDR_BIT (1U << MAX_IDR_SHIFT) | ||
43 | |||
44 | /* Leave the possibility of an incomplete final layer */ | ||
45 | #define MAX_IDR_LEVEL ((MAX_IDR_SHIFT + IDR_BITS - 1) / IDR_BITS) | ||
46 | |||
47 | /* Number of id_layer structs to leave in free list */ | ||
48 | #define MAX_IDR_FREE (MAX_IDR_LEVEL * 2) | ||
49 | |||
41 | static struct kmem_cache *idr_layer_cache; | 50 | static struct kmem_cache *idr_layer_cache; |
42 | static DEFINE_PER_CPU(struct idr_layer *, idr_preload_head); | 51 | static DEFINE_PER_CPU(struct idr_layer *, idr_preload_head); |
43 | static DEFINE_PER_CPU(int, idr_preload_cnt); | 52 | static DEFINE_PER_CPU(int, idr_preload_cnt); |
@@ -542,8 +551,8 @@ void idr_remove(struct idr *idp, int id) | |||
542 | struct idr_layer *p; | 551 | struct idr_layer *p; |
543 | struct idr_layer *to_free; | 552 | struct idr_layer *to_free; |
544 | 553 | ||
545 | /* Mask off upper bits we don't use for the search. */ | 554 | if (WARN_ON_ONCE(id < 0)) |
546 | id &= MAX_IDR_MASK; | 555 | return; |
547 | 556 | ||
548 | sub_remove(idp, (idp->layers - 1) * IDR_BITS, id); | 557 | sub_remove(idp, (idp->layers - 1) * IDR_BITS, id); |
549 | if (idp->top && idp->top->count == 1 && (idp->layers > 1) && | 558 | if (idp->top && idp->top->count == 1 && (idp->layers > 1) && |
@@ -650,14 +659,14 @@ void *idr_find(struct idr *idp, int id) | |||
650 | int n; | 659 | int n; |
651 | struct idr_layer *p; | 660 | struct idr_layer *p; |
652 | 661 | ||
662 | if (WARN_ON_ONCE(id < 0)) | ||
663 | return NULL; | ||
664 | |||
653 | p = rcu_dereference_raw(idp->top); | 665 | p = rcu_dereference_raw(idp->top); |
654 | if (!p) | 666 | if (!p) |
655 | return NULL; | 667 | return NULL; |
656 | n = (p->layer+1) * IDR_BITS; | 668 | n = (p->layer+1) * IDR_BITS; |
657 | 669 | ||
658 | /* Mask off upper bits we don't use for the search. */ | ||
659 | id &= MAX_IDR_MASK; | ||
660 | |||
661 | if (id > idr_max(p->layer + 1)) | 670 | if (id > idr_max(p->layer + 1)) |
662 | return NULL; | 671 | return NULL; |
663 | BUG_ON(n == 0); | 672 | BUG_ON(n == 0); |
@@ -799,14 +808,15 @@ void *idr_replace(struct idr *idp, void *ptr, int id) | |||
799 | int n; | 808 | int n; |
800 | struct idr_layer *p, *old_p; | 809 | struct idr_layer *p, *old_p; |
801 | 810 | ||
811 | if (WARN_ON_ONCE(id < 0)) | ||
812 | return ERR_PTR(-EINVAL); | ||
813 | |||
802 | p = idp->top; | 814 | p = idp->top; |
803 | if (!p) | 815 | if (!p) |
804 | return ERR_PTR(-EINVAL); | 816 | return ERR_PTR(-EINVAL); |
805 | 817 | ||
806 | n = (p->layer+1) * IDR_BITS; | 818 | n = (p->layer+1) * IDR_BITS; |
807 | 819 | ||
808 | id &= MAX_IDR_MASK; | ||
809 | |||
810 | if (id >= (1 << n)) | 820 | if (id >= (1 << n)) |
811 | return ERR_PTR(-EINVAL); | 821 | return ERR_PTR(-EINVAL); |
812 | 822 | ||