Skip to content

Commit 9d21874

Browse files
committed
Merge branch 'idr-2018-02-06' of git://git.infradead.org/users/willy/linux-dax
Pull idr updates from Matthew Wilcox: - test-suite improvements - replace the extended API by improving the normal API - performance improvement for IDRs which are 1-based rather than 0-based - add documentation * 'idr-2018-02-06' of git://git.infradead.org/users/willy/linux-dax: idr: Add documentation idr: Make 1-based IDRs more efficient idr: Warn if old iterators see large IDs idr: Rename idr_for_each_entry_ext idr: Remove idr_alloc_ext cls_u32: Convert to idr_alloc_u32 cls_u32: Reinstate cyclic allocation cls_flower: Convert to idr_alloc_u32 cls_bpf: Convert to use idr_alloc_u32 cls_basic: Convert to use idr_alloc_u32 cls_api: Convert to idr_alloc_u32 net sched actions: Convert to use idr_alloc_u32 idr: Add idr_alloc_u32 helper idr: Delete idr_find_ext function idr: Delete idr_replace_ext function idr: Delete idr_remove_ext function IDR test suite: Check handling negative end correctly idr test suite: Fix ida_test_random() radix tree test suite: Remove ARRAY_SIZE
2 parents 4ed8244 + ac665d9 commit 9d21874

File tree

15 files changed

+471
-325
lines changed

15 files changed

+471
-325
lines changed

Documentation/core-api/idr.rst

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
.. SPDX-License-Identifier: CC-BY-SA-4.0
2+
3+
=============
4+
ID Allocation
5+
=============
6+
7+
:Author: Matthew Wilcox
8+
9+
Overview
10+
========
11+
12+
A common problem to solve is allocating identifiers (IDs); generally
13+
small numbers which identify a thing. Examples include file descriptors,
14+
process IDs, packet identifiers in networking protocols, SCSI tags
15+
and device instance numbers. The IDR and the IDA provide a reasonable
16+
solution to the problem to avoid everybody inventing their own. The IDR
17+
provides the ability to map an ID to a pointer, while the IDA provides
18+
only ID allocation, and as a result is much more memory-efficient.
19+
20+
IDR usage
21+
=========
22+
23+
Start by initialising an IDR, either with :c:func:`DEFINE_IDR`
24+
for statically allocated IDRs or :c:func:`idr_init` for dynamically
25+
allocated IDRs.
26+
27+
You can call :c:func:`idr_alloc` to allocate an unused ID. Look up
28+
the pointer you associated with the ID by calling :c:func:`idr_find`
29+
and free the ID by calling :c:func:`idr_remove`.
30+
31+
If you need to change the pointer associated with an ID, you can call
32+
:c:func:`idr_replace`. One common reason to do this is to reserve an
33+
ID by passing a ``NULL`` pointer to the allocation function; initialise the
34+
object with the reserved ID and finally insert the initialised object
35+
into the IDR.
36+
37+
Some users need to allocate IDs larger than ``INT_MAX``. So far all of
38+
these users have been content with a ``UINT_MAX`` limit, and they use
39+
:c:func:`idr_alloc_u32`. If you need IDs that will not fit in a u32,
40+
we will work with you to address your needs.
41+
42+
If you need to allocate IDs sequentially, you can use
43+
:c:func:`idr_alloc_cyclic`. The IDR becomes less efficient when dealing
44+
with larger IDs, so using this function comes at a slight cost.
45+
46+
To perform an action on all pointers used by the IDR, you can
47+
either use the callback-based :c:func:`idr_for_each` or the
48+
iterator-style :c:func:`idr_for_each_entry`. You may need to use
49+
:c:func:`idr_for_each_entry_continue` to continue an iteration. You can
50+
also use :c:func:`idr_get_next` if the iterator doesn't fit your needs.
51+
52+
When you have finished using an IDR, you can call :c:func:`idr_destroy`
53+
to release the memory used by the IDR. This will not free the objects
54+
pointed to from the IDR; if you want to do that, use one of the iterators
55+
to do it.
56+
57+
You can use :c:func:`idr_is_empty` to find out whether there are any
58+
IDs currently allocated.
59+
60+
If you need to take a lock while allocating a new ID from the IDR,
61+
you may need to pass a restrictive set of GFP flags, which can lead
62+
to the IDR being unable to allocate memory. To work around this,
63+
you can call :c:func:`idr_preload` before taking the lock, and then
64+
:c:func:`idr_preload_end` after the allocation.
65+
66+
.. kernel-doc:: include/linux/idr.h
67+
:doc: idr sync
68+
69+
IDA usage
70+
=========
71+
72+
.. kernel-doc:: lib/idr.c
73+
:doc: IDA description
74+
75+
Functions and structures
76+
========================
77+
78+
.. kernel-doc:: include/linux/idr.h
79+
.. kernel-doc:: lib/idr.c

Documentation/core-api/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Core utilities
1616
atomic_ops
1717
refcount-vs-atomic
1818
cpu_hotplug
19+
idr
1920
local_ops
2021
workqueue
2122
genericirq

Documentation/core-api/kernel-api.rst

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -103,18 +103,6 @@ CRC Functions
103103
.. kernel-doc:: lib/crc-itu-t.c
104104
:export:
105105

106-
idr/ida Functions
107-
-----------------
108-
109-
.. kernel-doc:: include/linux/idr.h
110-
:doc: idr sync
111-
112-
.. kernel-doc:: lib/idr.c
113-
:doc: IDA description
114-
115-
.. kernel-doc:: lib/idr.c
116-
:export:
117-
118106
Math Functions in Linux
119107
=======================
120108

include/linux/idr.h

Lines changed: 75 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
#include <linux/radix-tree.h>
1616
#include <linux/gfp.h>
1717
#include <linux/percpu.h>
18-
#include <linux/bug.h>
1918

2019
struct idr {
2120
struct radix_tree_root idr_rt;
21+
unsigned int idr_base;
2222
unsigned int idr_next;
2323
};
2424

@@ -31,10 +31,26 @@ struct idr {
3131
/* Set the IDR flag and the IDR_FREE tag */
3232
#define IDR_RT_MARKER ((__force gfp_t)(3 << __GFP_BITS_SHIFT))
3333

34-
#define IDR_INIT \
35-
{ \
36-
.idr_rt = RADIX_TREE_INIT(IDR_RT_MARKER) \
34+
#define IDR_INIT_BASE(base) { \
35+
.idr_rt = RADIX_TREE_INIT(IDR_RT_MARKER), \
36+
.idr_base = (base), \
37+
.idr_next = 0, \
3738
}
39+
40+
/**
41+
* IDR_INIT() - Initialise an IDR.
42+
*
43+
* A freshly-initialised IDR contains no IDs.
44+
*/
45+
#define IDR_INIT IDR_INIT_BASE(0)
46+
47+
/**
48+
* DEFINE_IDR() - Define a statically-allocated IDR
49+
* @name: Name of IDR
50+
*
51+
* An IDR defined using this macro is ready for use with no additional
52+
* initialisation required. It contains no IDs.
53+
*/
3854
#define DEFINE_IDR(name) struct idr name = IDR_INIT
3955

4056
/**
@@ -82,80 +98,52 @@ static inline void idr_set_cursor(struct idr *idr, unsigned int val)
8298

8399
void idr_preload(gfp_t gfp_mask);
84100

85-
int idr_alloc_cmn(struct idr *idr, void *ptr, unsigned long *index,
86-
unsigned long start, unsigned long end, gfp_t gfp,
87-
bool ext);
88-
89-
/**
90-
* idr_alloc - allocate an id
91-
* @idr: idr handle
92-
* @ptr: pointer to be associated with the new id
93-
* @start: the minimum id (inclusive)
94-
* @end: the maximum id (exclusive)
95-
* @gfp: memory allocation flags
96-
*
97-
* Allocates an unused ID in the range [start, end). Returns -ENOSPC
98-
* if there are no unused IDs in that range.
99-
*
100-
* Note that @end is treated as max when <= 0. This is to always allow
101-
* using @start + N as @end as long as N is inside integer range.
102-
*
103-
* Simultaneous modifications to the @idr are not allowed and should be
104-
* prevented by the user, usually with a lock. idr_alloc() may be called
105-
* concurrently with read-only accesses to the @idr, such as idr_find() and
106-
* idr_for_each_entry().
107-
*/
108-
static inline int idr_alloc(struct idr *idr, void *ptr,
109-
int start, int end, gfp_t gfp)
110-
{
111-
unsigned long id;
112-
int ret;
113-
114-
if (WARN_ON_ONCE(start < 0))
115-
return -EINVAL;
116-
117-
ret = idr_alloc_cmn(idr, ptr, &id, start, end, gfp, false);
118-
119-
if (ret)
120-
return ret;
121-
122-
return id;
123-
}
124-
125-
static inline int idr_alloc_ext(struct idr *idr, void *ptr,
126-
unsigned long *index,
127-
unsigned long start,
128-
unsigned long end,
129-
gfp_t gfp)
130-
{
131-
return idr_alloc_cmn(idr, ptr, index, start, end, gfp, true);
132-
}
133-
134-
int idr_alloc_cyclic(struct idr *, void *entry, int start, int end, gfp_t);
101+
int idr_alloc(struct idr *, void *ptr, int start, int end, gfp_t);
102+
int __must_check idr_alloc_u32(struct idr *, void *ptr, u32 *id,
103+
unsigned long max, gfp_t);
104+
int idr_alloc_cyclic(struct idr *, void *ptr, int start, int end, gfp_t);
105+
void *idr_remove(struct idr *, unsigned long id);
106+
void *idr_find(const struct idr *, unsigned long id);
135107
int idr_for_each(const struct idr *,
136108
int (*fn)(int id, void *p, void *data), void *data);
137109
void *idr_get_next(struct idr *, int *nextid);
138-
void *idr_get_next_ext(struct idr *idr, unsigned long *nextid);
139-
void *idr_replace(struct idr *, void *, int id);
140-
void *idr_replace_ext(struct idr *idr, void *ptr, unsigned long id);
110+
void *idr_get_next_ul(struct idr *, unsigned long *nextid);
111+
void *idr_replace(struct idr *, void *, unsigned long id);
141112
void idr_destroy(struct idr *);
142113

143-
static inline void *idr_remove_ext(struct idr *idr, unsigned long id)
144-
{
145-
return radix_tree_delete_item(&idr->idr_rt, id, NULL);
146-
}
147-
148-
static inline void *idr_remove(struct idr *idr, int id)
114+
/**
115+
* idr_init_base() - Initialise an IDR.
116+
* @idr: IDR handle.
117+
* @base: The base value for the IDR.
118+
*
119+
* This variation of idr_init() creates an IDR which will allocate IDs
120+
* starting at %base.
121+
*/
122+
static inline void idr_init_base(struct idr *idr, int base)
149123
{
150-
return idr_remove_ext(idr, id);
124+
INIT_RADIX_TREE(&idr->idr_rt, IDR_RT_MARKER);
125+
idr->idr_base = base;
126+
idr->idr_next = 0;
151127
}
152128

129+
/**
130+
* idr_init() - Initialise an IDR.
131+
* @idr: IDR handle.
132+
*
133+
* Initialise a dynamically allocated IDR. To initialise a
134+
* statically allocated IDR, use DEFINE_IDR().
135+
*/
153136
static inline void idr_init(struct idr *idr)
154137
{
155-
INIT_RADIX_TREE(&idr->idr_rt, IDR_RT_MARKER);
156-
idr->idr_next = 0;
138+
idr_init_base(idr, 0);
157139
}
158140

141+
/**
142+
* idr_is_empty() - Are there any IDs allocated?
143+
* @idr: IDR handle.
144+
*
145+
* Return: %true if any IDs have been allocated from this IDR.
146+
*/
159147
static inline bool idr_is_empty(const struct idr *idr)
160148
{
161149
return radix_tree_empty(&idr->idr_rt) &&
@@ -174,50 +162,38 @@ static inline void idr_preload_end(void)
174162
}
175163

176164
/**
177-
* idr_find - return pointer for given id
178-
* @idr: idr handle
179-
* @id: lookup key
180-
*
181-
* Return the pointer given the id it has been registered with. A %NULL
182-
* return indicates that @id is not valid or you passed %NULL in
183-
* idr_get_new().
165+
* idr_for_each_entry() - Iterate over an IDR's elements of a given type.
166+
* @idr: IDR handle.
167+
* @entry: The type * to use as cursor
168+
* @id: Entry ID.
184169
*
185-
* This function can be called under rcu_read_lock(), given that the leaf
186-
* pointers lifetimes are correctly managed.
170+
* @entry and @id do not need to be initialized before the loop, and
171+
* after normal termination @entry is left with the value NULL. This
172+
* is convenient for a "not found" value.
187173
*/
188-
static inline void *idr_find_ext(const struct idr *idr, unsigned long id)
189-
{
190-
return radix_tree_lookup(&idr->idr_rt, id);
191-
}
192-
193-
static inline void *idr_find(const struct idr *idr, int id)
194-
{
195-
return idr_find_ext(idr, id);
196-
}
174+
#define idr_for_each_entry(idr, entry, id) \
175+
for (id = 0; ((entry) = idr_get_next(idr, &(id))) != NULL; ++id)
197176

198177
/**
199-
* idr_for_each_entry - iterate over an idr's elements of a given type
200-
* @idr: idr handle
201-
* @entry: the type * to use as cursor
202-
* @id: id entry's key
178+
* idr_for_each_entry_ul() - Iterate over an IDR's elements of a given type.
179+
* @idr: IDR handle.
180+
* @entry: The type * to use as cursor.
181+
* @id: Entry ID.
203182
*
204183
* @entry and @id do not need to be initialized before the loop, and
205-
* after normal terminatinon @entry is left with the value NULL. This
184+
* after normal termination @entry is left with the value NULL. This
206185
* is convenient for a "not found" value.
207186
*/
208-
#define idr_for_each_entry(idr, entry, id) \
209-
for (id = 0; ((entry) = idr_get_next(idr, &(id))) != NULL; ++id)
210-
#define idr_for_each_entry_ext(idr, entry, id) \
211-
for (id = 0; ((entry) = idr_get_next_ext(idr, &(id))) != NULL; ++id)
187+
#define idr_for_each_entry_ul(idr, entry, id) \
188+
for (id = 0; ((entry) = idr_get_next_ul(idr, &(id))) != NULL; ++id)
212189

213190
/**
214-
* idr_for_each_entry_continue - continue iteration over an idr's elements of a given type
215-
* @idr: idr handle
216-
* @entry: the type * to use as cursor
217-
* @id: id entry's key
191+
* idr_for_each_entry_continue() - Continue iteration over an IDR's elements of a given type
192+
* @idr: IDR handle.
193+
* @entry: The type * to use as a cursor.
194+
* @id: Entry ID.
218195
*
219-
* Continue to iterate over list of given type, continuing after
220-
* the current position.
196+
* Continue to iterate over entries, continuing after the current position.
221197
*/
222198
#define idr_for_each_entry_continue(idr, entry, id) \
223199
for ((entry) = idr_get_next((idr), &(id)); \

include/linux/radix-tree.h

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -356,24 +356,9 @@ int radix_tree_split(struct radix_tree_root *, unsigned long index,
356356
int radix_tree_join(struct radix_tree_root *, unsigned long index,
357357
unsigned new_order, void *);
358358

359-
void __rcu **idr_get_free_cmn(struct radix_tree_root *root,
359+
void __rcu **idr_get_free(struct radix_tree_root *root,
360360
struct radix_tree_iter *iter, gfp_t gfp,
361361
unsigned long max);
362-
static inline void __rcu **idr_get_free(struct radix_tree_root *root,
363-
struct radix_tree_iter *iter,
364-
gfp_t gfp,
365-
int end)
366-
{
367-
return idr_get_free_cmn(root, iter, gfp, end > 0 ? end - 1 : INT_MAX);
368-
}
369-
370-
static inline void __rcu **idr_get_free_ext(struct radix_tree_root *root,
371-
struct radix_tree_iter *iter,
372-
gfp_t gfp,
373-
unsigned long end)
374-
{
375-
return idr_get_free_cmn(root, iter, gfp, end - 1);
376-
}
377362

378363
enum {
379364
RADIX_TREE_ITER_TAG_MASK = 0x0f, /* tag index in lower nybble */

0 commit comments

Comments
 (0)