Skip to content

Commit cf39319

Browse files
committed
Merge branch 'idr-4.11' of git://git.infradead.org/users/willy/linux-dax
Pull IDR rewrite from Matthew Wilcox: "The most significant part of the following is the patch to rewrite the IDR & IDA to be clients of the radix tree. But there's much more, including an enhancement of the IDA to be significantly more space efficient, an IDR & IDA test suite, some improvements to the IDR API (and driver changes to take advantage of those improvements), several improvements to the radix tree test suite and RCU annotations. The IDR & IDA rewrite had a good spin in linux-next and Andrew's tree for most of the last cycle. Coupled with the IDR test suite, I feel pretty confident that any remaining bugs are quite hard to hit. 0-day did a great job of watching my git tree and pointing out problems; as it hit them, I added new test-cases to be sure not to be caught the same way twice" Willy goes on to expand a bit on the IDR rewrite rationale: "The radix tree and the IDR use very similar data structures. Merging the two codebases lets us share the memory allocation pools, and results in a net deletion of 500 lines of code. It also opens up the possibility of exposing more of the features of the radix tree to users of the IDR (and I have some interesting patches along those lines waiting for 4.12) It also shrinks the size of the 'struct idr' from 40 bytes to 24 which will shrink a fair few data structures that embed an IDR" * 'idr-4.11' of git://git.infradead.org/users/willy/linux-dax: (32 commits) radix tree test suite: Add config option for map shift idr: Add missing __rcu annotations radix-tree: Fix __rcu annotations radix-tree: Add rcu_dereference and rcu_assign_pointer calls radix tree test suite: Run iteration tests for longer radix tree test suite: Fix split/join memory leaks radix tree test suite: Fix leaks in regression2.c radix tree test suite: Fix leaky tests radix tree test suite: Enable address sanitizer radix_tree_iter_resume: Fix out of bounds error radix-tree: Store a pointer to the root in each node radix-tree: Chain preallocated nodes through ->parent radix tree test suite: Dial down verbosity with -v radix tree test suite: Introduce kmalloc_verbose idr: Return the deleted entry from idr_remove radix tree test suite: Build separate binaries for some tests ida: Use exceptional entries for small IDAs ida: Move ida_bitmap to a percpu variable Reimplement IDR and IDA using the radix tree radix-tree: Add radix_tree_iter_delete ...
2 parents 5ecc5ac + c6ce3e2 commit cf39319

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1703
-2077
lines changed

drivers/atm/nicstar.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,13 +1980,12 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe)
19801980
card->lbfqc = ns_stat_lfbqc_get(stat);
19811981

19821982
id = le32_to_cpu(rsqe->buffer_handle);
1983-
skb = idr_find(&card->idr, id);
1983+
skb = idr_remove(&card->idr, id);
19841984
if (!skb) {
19851985
RXPRINTK(KERN_ERR
1986-
"nicstar%d: idr_find() failed!\n", card->index);
1986+
"nicstar%d: skb not found!\n", card->index);
19871987
return;
19881988
}
1989-
idr_remove(&card->idr, id);
19901989
dma_sync_single_for_cpu(&card->pcidev->dev,
19911990
NS_PRV_DMA(skb),
19921991
(NS_PRV_BUFTYPE(skb) == BUF_SM

drivers/block/drbd/drbd_main.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2915,11 +2915,9 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
29152915
idr_remove(&connection->peer_devices, vnr);
29162916
out_idr_remove_from_resource:
29172917
for_each_connection(connection, resource) {
2918-
peer_device = idr_find(&connection->peer_devices, vnr);
2919-
if (peer_device) {
2920-
idr_remove(&connection->peer_devices, vnr);
2918+
peer_device = idr_remove(&connection->peer_devices, vnr);
2919+
if (peer_device)
29212920
kref_put(&connection->kref, drbd_destroy_connection);
2922-
}
29232921
}
29242922
for_each_peer_device_safe(peer_device, tmp_peer_device, device) {
29252923
list_del(&peer_device->peer_devices);

drivers/firewire/core-cdev.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,8 +1307,7 @@ static void iso_resource_work(struct work_struct *work)
13071307
*/
13081308
if (r->todo == ISO_RES_REALLOC && !success &&
13091309
!client->in_shutdown &&
1310-
idr_find(&client->resource_idr, r->resource.handle)) {
1311-
idr_remove(&client->resource_idr, r->resource.handle);
1310+
idr_remove(&client->resource_idr, r->resource.handle)) {
13121311
client_put(client);
13131312
free = true;
13141313
}

drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,10 @@ static void amdgpu_bo_list_destroy(struct amdgpu_fpriv *fpriv, int id)
7070
struct amdgpu_bo_list *list;
7171

7272
mutex_lock(&fpriv->bo_list_lock);
73-
list = idr_find(&fpriv->bo_list_handles, id);
73+
list = idr_remove(&fpriv->bo_list_handles, id);
7474
if (list) {
75+
/* Another user may have a reference to this list still */
7576
mutex_lock(&list->lock);
76-
idr_remove(&fpriv->bo_list_handles, id);
7777
mutex_unlock(&list->lock);
7878
amdgpu_bo_list_free(list);
7979
}

drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,11 @@ static int amdgpu_ctx_free(struct amdgpu_fpriv *fpriv, uint32_t id)
135135
struct amdgpu_ctx *ctx;
136136

137137
mutex_lock(&mgr->lock);
138-
ctx = idr_find(&mgr->ctx_handles, id);
139-
if (ctx) {
140-
idr_remove(&mgr->ctx_handles, id);
138+
ctx = idr_remove(&mgr->ctx_handles, id);
139+
if (ctx)
141140
kref_put(&ctx->refcount, amdgpu_ctx_do_release);
142-
mutex_unlock(&mgr->lock);
143-
return 0;
144-
}
145141
mutex_unlock(&mgr->lock);
146-
return -EINVAL;
142+
return ctx ? 0 : -EINVAL;
147143
}
148144

149145
static int amdgpu_ctx_query(struct amdgpu_device *adev,

drivers/net/wireless/marvell/mwifiex/txrx.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -346,9 +346,7 @@ void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
346346
return;
347347

348348
spin_lock_irqsave(&priv->ack_status_lock, flags);
349-
ack_skb = idr_find(&priv->ack_status_frames, tx_status->tx_token_id);
350-
if (ack_skb)
351-
idr_remove(&priv->ack_status_frames, tx_status->tx_token_id);
349+
ack_skb = idr_remove(&priv->ack_status_frames, tx_status->tx_token_id);
352350
spin_unlock_irqrestore(&priv->ack_status_lock, flags);
353351

354352
if (ack_skb) {

drivers/target/target_core_user.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -642,9 +642,7 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
642642
WARN_ON(tcmu_hdr_get_op(entry->hdr.len_op) != TCMU_OP_CMD);
643643

644644
spin_lock(&udev->commands_lock);
645-
cmd = idr_find(&udev->commands, entry->hdr.cmd_id);
646-
if (cmd)
647-
idr_remove(&udev->commands, cmd->cmd_id);
645+
cmd = idr_remove(&udev->commands, entry->hdr.cmd_id);
648646
spin_unlock(&udev->commands_lock);
649647

650648
if (!cmd) {

include/linux/idr.h

Lines changed: 67 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -12,47 +12,29 @@
1212
#ifndef __IDR_H__
1313
#define __IDR_H__
1414

15-
#include <linux/types.h>
16-
#include <linux/bitops.h>
17-
#include <linux/init.h>
18-
#include <linux/rcupdate.h>
15+
#include <linux/radix-tree.h>
16+
#include <linux/gfp.h>
17+
#include <linux/percpu.h>
18+
19+
struct idr {
20+
struct radix_tree_root idr_rt;
21+
unsigned int idr_next;
22+
};
1923

2024
/*
21-
* Using 6 bits at each layer allows us to allocate 7 layers out of each page.
22-
* 8 bits only gave us 3 layers out of every pair of pages, which is less
23-
* efficient except for trees with a largest element between 192-255 inclusive.
25+
* The IDR API does not expose the tagging functionality of the radix tree
26+
* to users. Use tag 0 to track whether a node has free space below it.
2427
*/
25-
#define IDR_BITS 6
26-
#define IDR_SIZE (1 << IDR_BITS)
27-
#define IDR_MASK ((1 << IDR_BITS)-1)
28-
29-
struct idr_layer {
30-
int prefix; /* the ID prefix of this idr_layer */
31-
int layer; /* distance from leaf */
32-
struct idr_layer __rcu *ary[1<<IDR_BITS];
33-
int count; /* When zero, we can release it */
34-
union {
35-
/* A zero bit means "space here" */
36-
DECLARE_BITMAP(bitmap, IDR_SIZE);
37-
struct rcu_head rcu_head;
38-
};
39-
};
28+
#define IDR_FREE 0
4029

41-
struct idr {
42-
struct idr_layer __rcu *hint; /* the last layer allocated from */
43-
struct idr_layer __rcu *top;
44-
int layers; /* only valid w/o concurrent changes */
45-
int cur; /* current pos for cyclic allocation */
46-
spinlock_t lock;
47-
int id_free_cnt;
48-
struct idr_layer *id_free;
49-
};
30+
/* Set the IDR flag and the IDR_FREE tag */
31+
#define IDR_RT_MARKER ((__force gfp_t)(3 << __GFP_BITS_SHIFT))
5032

51-
#define IDR_INIT(name) \
33+
#define IDR_INIT \
5234
{ \
53-
.lock = __SPIN_LOCK_UNLOCKED(name.lock), \
35+
.idr_rt = RADIX_TREE_INIT(IDR_RT_MARKER) \
5436
}
55-
#define DEFINE_IDR(name) struct idr name = IDR_INIT(name)
37+
#define DEFINE_IDR(name) struct idr name = IDR_INIT
5638

5739
/**
5840
* idr_get_cursor - Return the current position of the cyclic allocator
@@ -62,9 +44,9 @@ struct idr {
6244
* idr_alloc_cyclic() if it is free (otherwise the search will start from
6345
* this position).
6446
*/
65-
static inline unsigned int idr_get_cursor(struct idr *idr)
47+
static inline unsigned int idr_get_cursor(const struct idr *idr)
6648
{
67-
return READ_ONCE(idr->cur);
49+
return READ_ONCE(idr->idr_next);
6850
}
6951

7052
/**
@@ -77,7 +59,7 @@ static inline unsigned int idr_get_cursor(struct idr *idr)
7759
*/
7860
static inline void idr_set_cursor(struct idr *idr, unsigned int val)
7961
{
80-
WRITE_ONCE(idr->cur, val);
62+
WRITE_ONCE(idr->idr_next, val);
8163
}
8264

8365
/**
@@ -97,22 +79,31 @@ static inline void idr_set_cursor(struct idr *idr, unsigned int val)
9779
* period).
9880
*/
9981

100-
/*
101-
* This is what we export.
102-
*/
103-
104-
void *idr_find_slowpath(struct idr *idp, int id);
10582
void idr_preload(gfp_t gfp_mask);
106-
int idr_alloc(struct idr *idp, void *ptr, int start, int end, gfp_t gfp_mask);
107-
int idr_alloc_cyclic(struct idr *idr, void *ptr, int start, int end, gfp_t gfp_mask);
108-
int idr_for_each(struct idr *idp,
83+
int idr_alloc(struct idr *, void *entry, int start, int end, gfp_t);
84+
int idr_alloc_cyclic(struct idr *, void *entry, int start, int end, gfp_t);
85+
int idr_for_each(const struct idr *,
10986
int (*fn)(int id, void *p, void *data), void *data);
110-
void *idr_get_next(struct idr *idp, int *nextid);
111-
void *idr_replace(struct idr *idp, void *ptr, int id);
112-
void idr_remove(struct idr *idp, int id);
113-
void idr_destroy(struct idr *idp);
114-
void idr_init(struct idr *idp);
115-
bool idr_is_empty(struct idr *idp);
87+
void *idr_get_next(struct idr *, int *nextid);
88+
void *idr_replace(struct idr *, void *, int id);
89+
void idr_destroy(struct idr *);
90+
91+
static inline void *idr_remove(struct idr *idr, int id)
92+
{
93+
return radix_tree_delete_item(&idr->idr_rt, id, NULL);
94+
}
95+
96+
static inline void idr_init(struct idr *idr)
97+
{
98+
INIT_RADIX_TREE(&idr->idr_rt, IDR_RT_MARKER);
99+
idr->idr_next = 0;
100+
}
101+
102+
static inline bool idr_is_empty(const struct idr *idr)
103+
{
104+
return radix_tree_empty(&idr->idr_rt) &&
105+
radix_tree_tagged(&idr->idr_rt, IDR_FREE);
106+
}
116107

117108
/**
118109
* idr_preload_end - end preload section started with idr_preload()
@@ -137,77 +128,75 @@ static inline void idr_preload_end(void)
137128
* This function can be called under rcu_read_lock(), given that the leaf
138129
* pointers lifetimes are correctly managed.
139130
*/
140-
static inline void *idr_find(struct idr *idr, int id)
131+
static inline void *idr_find(const struct idr *idr, int id)
141132
{
142-
struct idr_layer *hint = rcu_dereference_raw(idr->hint);
143-
144-
if (hint && (id & ~IDR_MASK) == hint->prefix)
145-
return rcu_dereference_raw(hint->ary[id & IDR_MASK]);
146-
147-
return idr_find_slowpath(idr, id);
133+
return radix_tree_lookup(&idr->idr_rt, id);
148134
}
149135

150136
/**
151137
* idr_for_each_entry - iterate over an idr's elements of a given type
152-
* @idp: idr handle
138+
* @idr: idr handle
153139
* @entry: the type * to use as cursor
154140
* @id: id entry's key
155141
*
156142
* @entry and @id do not need to be initialized before the loop, and
157143
* after normal terminatinon @entry is left with the value NULL. This
158144
* is convenient for a "not found" value.
159145
*/
160-
#define idr_for_each_entry(idp, entry, id) \
161-
for (id = 0; ((entry) = idr_get_next(idp, &(id))) != NULL; ++id)
146+
#define idr_for_each_entry(idr, entry, id) \
147+
for (id = 0; ((entry) = idr_get_next(idr, &(id))) != NULL; ++id)
162148

163149
/**
164-
* idr_for_each_entry - continue iteration over an idr's elements of a given type
165-
* @idp: idr handle
150+
* idr_for_each_entry_continue - continue iteration over an idr's elements of a given type
151+
* @idr: idr handle
166152
* @entry: the type * to use as cursor
167153
* @id: id entry's key
168154
*
169155
* Continue to iterate over list of given type, continuing after
170156
* the current position.
171157
*/
172-
#define idr_for_each_entry_continue(idp, entry, id) \
173-
for ((entry) = idr_get_next((idp), &(id)); \
158+
#define idr_for_each_entry_continue(idr, entry, id) \
159+
for ((entry) = idr_get_next((idr), &(id)); \
174160
entry; \
175-
++id, (entry) = idr_get_next((idp), &(id)))
161+
++id, (entry) = idr_get_next((idr), &(id)))
176162

177163
/*
178164
* IDA - IDR based id allocator, use when translation from id to
179165
* pointer isn't necessary.
180-
*
181-
* IDA_BITMAP_LONGS is calculated to be one less to accommodate
182-
* ida_bitmap->nr_busy so that the whole struct fits in 128 bytes.
183166
*/
184167
#define IDA_CHUNK_SIZE 128 /* 128 bytes per chunk */
185-
#define IDA_BITMAP_LONGS (IDA_CHUNK_SIZE / sizeof(long) - 1)
168+
#define IDA_BITMAP_LONGS (IDA_CHUNK_SIZE / sizeof(long))
186169
#define IDA_BITMAP_BITS (IDA_BITMAP_LONGS * sizeof(long) * 8)
187170

188171
struct ida_bitmap {
189-
long nr_busy;
190172
unsigned long bitmap[IDA_BITMAP_LONGS];
191173
};
192174

175+
DECLARE_PER_CPU(struct ida_bitmap *, ida_bitmap);
176+
193177
struct ida {
194-
struct idr idr;
195-
struct ida_bitmap *free_bitmap;
178+
struct radix_tree_root ida_rt;
196179
};
197180

198-
#define IDA_INIT(name) { .idr = IDR_INIT((name).idr), .free_bitmap = NULL, }
199-
#define DEFINE_IDA(name) struct ida name = IDA_INIT(name)
181+
#define IDA_INIT { \
182+
.ida_rt = RADIX_TREE_INIT(IDR_RT_MARKER | GFP_NOWAIT), \
183+
}
184+
#define DEFINE_IDA(name) struct ida name = IDA_INIT
200185

201186
int ida_pre_get(struct ida *ida, gfp_t gfp_mask);
202187
int ida_get_new_above(struct ida *ida, int starting_id, int *p_id);
203188
void ida_remove(struct ida *ida, int id);
204189
void ida_destroy(struct ida *ida);
205-
void ida_init(struct ida *ida);
206190

207191
int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end,
208192
gfp_t gfp_mask);
209193
void ida_simple_remove(struct ida *ida, unsigned int id);
210194

195+
static inline void ida_init(struct ida *ida)
196+
{
197+
INIT_RADIX_TREE(&ida->ida_rt, IDR_RT_MARKER | GFP_NOWAIT);
198+
}
199+
211200
/**
212201
* ida_get_new - allocate new ID
213202
* @ida: idr handle
@@ -220,11 +209,8 @@ static inline int ida_get_new(struct ida *ida, int *p_id)
220209
return ida_get_new_above(ida, 0, p_id);
221210
}
222211

223-
static inline bool ida_is_empty(struct ida *ida)
212+
static inline bool ida_is_empty(const struct ida *ida)
224213
{
225-
return idr_is_empty(&ida->idr);
214+
return radix_tree_empty(&ida->ida_rt);
226215
}
227-
228-
void __init idr_init_cache(void);
229-
230216
#endif /* __IDR_H__ */

0 commit comments

Comments
 (0)