Skip to content

Commit ac665d9

Browse files
author
Matthew Wilcox
committed
idr: Add documentation
Move the idr kernel-doc to its own idr.rst file and add a few paragraphs about how to use it. Also add some more kernel-doc. Signed-off-by: Matthew Wilcox <[email protected]>
1 parent 6ce711f commit ac665d9

File tree

4 files changed

+95
-13
lines changed

4 files changed

+95
-13
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: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ struct idr {
3636
.idr_base = (base), \
3737
.idr_next = 0, \
3838
}
39-
#define DEFINE_IDR(name) struct idr name = IDR_INIT
4039

4140
/**
4241
* IDR_INIT() - Initialise an IDR.
@@ -45,6 +44,15 @@ struct idr {
4544
*/
4645
#define IDR_INIT IDR_INIT_BASE(0)
4746

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+
*/
54+
#define DEFINE_IDR(name) struct idr name = IDR_INIT
55+
4856
/**
4957
* idr_get_cursor - Return the current position of the cyclic allocator
5058
* @idr: idr handle
@@ -130,6 +138,12 @@ static inline void idr_init(struct idr *idr)
130138
idr_init_base(idr, 0);
131139
}
132140

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+
*/
133147
static inline bool idr_is_empty(const struct idr *idr)
134148
{
135149
return radix_tree_empty(&idr->idr_rt) &&

0 commit comments

Comments
 (0)