diff options
author | Tejun Heo <tj@kernel.org> | 2013-02-27 20:04:16 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-27 22:10:16 -0500 |
commit | 3b069c5d857a5f1b8cb6bb74c70d9446089f5077 (patch) | |
tree | 58e005a8e9beba035a2551edd34afe1d802dba53 /drivers/infiniband | |
parent | 4ae42b0ff0f9993c79d7282218b98d8a8a4263f5 (diff) |
IB/core: convert to idr_alloc()
Convert to the much saner new idr interface.
v2: Mike triggered WARN_ON() in idr_preload() because send_mad(),
which may be used from non-process context, was calling
idr_preload() unconditionally. Preload iff @gfp_mask has
__GFP_WAIT.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Sean Hefty <sean.hefty@intel.com>
Reported-by: "Marciniszyn, Mike" <mike.marciniszyn@intel.com>
Cc: Roland Dreier <roland@kernel.org>
Cc: Sean Hefty <sean.hefty@intel.com>
Cc: Hal Rosenstock <hal.rosenstock@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/core/cm.c | 22 | ||||
-rw-r--r-- | drivers/infiniband/core/cma.c | 24 | ||||
-rw-r--r-- | drivers/infiniband/core/sa_query.c | 18 | ||||
-rw-r--r-- | drivers/infiniband/core/ucm.c | 16 | ||||
-rw-r--r-- | drivers/infiniband/core/ucma.c | 32 | ||||
-rw-r--r-- | drivers/infiniband/core/uverbs_cmd.c | 17 |
6 files changed, 48 insertions, 81 deletions
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 394fea2ba1bc..98281fe5ea4b 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c | |||
@@ -382,20 +382,21 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av) | |||
382 | static int cm_alloc_id(struct cm_id_private *cm_id_priv) | 382 | static int cm_alloc_id(struct cm_id_private *cm_id_priv) |
383 | { | 383 | { |
384 | unsigned long flags; | 384 | unsigned long flags; |
385 | int ret, id; | 385 | int id; |
386 | static int next_id; | 386 | static int next_id; |
387 | 387 | ||
388 | do { | 388 | idr_preload(GFP_KERNEL); |
389 | spin_lock_irqsave(&cm.lock, flags); | 389 | spin_lock_irqsave(&cm.lock, flags); |
390 | ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, | 390 | |
391 | next_id, &id); | 391 | id = idr_alloc(&cm.local_id_table, cm_id_priv, next_id, 0, GFP_NOWAIT); |
392 | if (!ret) | 392 | if (id >= 0) |
393 | next_id = ((unsigned) id + 1) & MAX_IDR_MASK; | 393 | next_id = ((unsigned) id + 1) & MAX_IDR_MASK; |
394 | spin_unlock_irqrestore(&cm.lock, flags); | 394 | |
395 | } while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) ); | 395 | spin_unlock_irqrestore(&cm.lock, flags); |
396 | idr_preload_end(); | ||
396 | 397 | ||
397 | cm_id_priv->id.local_id = (__force __be32)id ^ cm.random_id_operand; | 398 | cm_id_priv->id.local_id = (__force __be32)id ^ cm.random_id_operand; |
398 | return ret; | 399 | return id < 0 ? id : 0; |
399 | } | 400 | } |
400 | 401 | ||
401 | static void cm_free_id(__be32 local_id) | 402 | static void cm_free_id(__be32 local_id) |
@@ -3844,7 +3845,6 @@ static int __init ib_cm_init(void) | |||
3844 | cm.remote_sidr_table = RB_ROOT; | 3845 | cm.remote_sidr_table = RB_ROOT; |
3845 | idr_init(&cm.local_id_table); | 3846 | idr_init(&cm.local_id_table); |
3846 | get_random_bytes(&cm.random_id_operand, sizeof cm.random_id_operand); | 3847 | get_random_bytes(&cm.random_id_operand, sizeof cm.random_id_operand); |
3847 | idr_pre_get(&cm.local_id_table, GFP_KERNEL); | ||
3848 | INIT_LIST_HEAD(&cm.timewait_list); | 3848 | INIT_LIST_HEAD(&cm.timewait_list); |
3849 | 3849 | ||
3850 | ret = class_register(&cm_class); | 3850 | ret = class_register(&cm_class); |
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index d789eea32168..c32eeaa3f3b1 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c | |||
@@ -2143,33 +2143,23 @@ static int cma_alloc_port(struct idr *ps, struct rdma_id_private *id_priv, | |||
2143 | unsigned short snum) | 2143 | unsigned short snum) |
2144 | { | 2144 | { |
2145 | struct rdma_bind_list *bind_list; | 2145 | struct rdma_bind_list *bind_list; |
2146 | int port, ret; | 2146 | int ret; |
2147 | 2147 | ||
2148 | bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL); | 2148 | bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL); |
2149 | if (!bind_list) | 2149 | if (!bind_list) |
2150 | return -ENOMEM; | 2150 | return -ENOMEM; |
2151 | 2151 | ||
2152 | do { | 2152 | ret = idr_alloc(ps, bind_list, snum, snum + 1, GFP_KERNEL); |
2153 | ret = idr_get_new_above(ps, bind_list, snum, &port); | 2153 | if (ret < 0) |
2154 | } while ((ret == -EAGAIN) && idr_pre_get(ps, GFP_KERNEL)); | 2154 | goto err; |
2155 | |||
2156 | if (ret) | ||
2157 | goto err1; | ||
2158 | |||
2159 | if (port != snum) { | ||
2160 | ret = -EADDRNOTAVAIL; | ||
2161 | goto err2; | ||
2162 | } | ||
2163 | 2155 | ||
2164 | bind_list->ps = ps; | 2156 | bind_list->ps = ps; |
2165 | bind_list->port = (unsigned short) port; | 2157 | bind_list->port = (unsigned short)ret; |
2166 | cma_bind_port(bind_list, id_priv); | 2158 | cma_bind_port(bind_list, id_priv); |
2167 | return 0; | 2159 | return 0; |
2168 | err2: | 2160 | err: |
2169 | idr_remove(ps, port); | ||
2170 | err1: | ||
2171 | kfree(bind_list); | 2161 | kfree(bind_list); |
2172 | return ret; | 2162 | return ret == -ENOSPC ? -EADDRNOTAVAIL : ret; |
2173 | } | 2163 | } |
2174 | 2164 | ||
2175 | static int cma_alloc_any_port(struct idr *ps, struct rdma_id_private *id_priv) | 2165 | static int cma_alloc_any_port(struct idr *ps, struct rdma_id_private *id_priv) |
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index a8905abc56e4..934f45e79e5e 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c | |||
@@ -611,19 +611,21 @@ static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent) | |||
611 | 611 | ||
612 | static int send_mad(struct ib_sa_query *query, int timeout_ms, gfp_t gfp_mask) | 612 | static int send_mad(struct ib_sa_query *query, int timeout_ms, gfp_t gfp_mask) |
613 | { | 613 | { |
614 | bool preload = gfp_mask & __GFP_WAIT; | ||
614 | unsigned long flags; | 615 | unsigned long flags; |
615 | int ret, id; | 616 | int ret, id; |
616 | 617 | ||
617 | retry: | 618 | if (preload) |
618 | if (!idr_pre_get(&query_idr, gfp_mask)) | 619 | idr_preload(gfp_mask); |
619 | return -ENOMEM; | ||
620 | spin_lock_irqsave(&idr_lock, flags); | 620 | spin_lock_irqsave(&idr_lock, flags); |
621 | ret = idr_get_new(&query_idr, query, &id); | 621 | |
622 | id = idr_alloc(&query_idr, query, 0, 0, GFP_NOWAIT); | ||
623 | |||
622 | spin_unlock_irqrestore(&idr_lock, flags); | 624 | spin_unlock_irqrestore(&idr_lock, flags); |
623 | if (ret == -EAGAIN) | 625 | if (preload) |
624 | goto retry; | 626 | idr_preload_end(); |
625 | if (ret) | 627 | if (id < 0) |
626 | return ret; | 628 | return id; |
627 | 629 | ||
628 | query->mad_buf->timeout_ms = timeout_ms; | 630 | query->mad_buf->timeout_ms = timeout_ms; |
629 | query->mad_buf->context[0] = query; | 631 | query->mad_buf->context[0] = query; |
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index 49b15ac1987e..f2f63933e8a9 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c | |||
@@ -176,7 +176,6 @@ static void ib_ucm_cleanup_events(struct ib_ucm_context *ctx) | |||
176 | static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file) | 176 | static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file) |
177 | { | 177 | { |
178 | struct ib_ucm_context *ctx; | 178 | struct ib_ucm_context *ctx; |
179 | int result; | ||
180 | 179 | ||
181 | ctx = kzalloc(sizeof *ctx, GFP_KERNEL); | 180 | ctx = kzalloc(sizeof *ctx, GFP_KERNEL); |
182 | if (!ctx) | 181 | if (!ctx) |
@@ -187,17 +186,10 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file) | |||
187 | ctx->file = file; | 186 | ctx->file = file; |
188 | INIT_LIST_HEAD(&ctx->events); | 187 | INIT_LIST_HEAD(&ctx->events); |
189 | 188 | ||
190 | do { | 189 | mutex_lock(&ctx_id_mutex); |
191 | result = idr_pre_get(&ctx_id_table, GFP_KERNEL); | 190 | ctx->id = idr_alloc(&ctx_id_table, ctx, 0, 0, GFP_KERNEL); |
192 | if (!result) | 191 | mutex_unlock(&ctx_id_mutex); |
193 | goto error; | 192 | if (ctx->id < 0) |
194 | |||
195 | mutex_lock(&ctx_id_mutex); | ||
196 | result = idr_get_new(&ctx_id_table, ctx, &ctx->id); | ||
197 | mutex_unlock(&ctx_id_mutex); | ||
198 | } while (result == -EAGAIN); | ||
199 | |||
200 | if (result) | ||
201 | goto error; | 193 | goto error; |
202 | 194 | ||
203 | list_add_tail(&ctx->file_list, &file->ctxs); | 195 | list_add_tail(&ctx->file_list, &file->ctxs); |
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index 2709ff581392..5ca44cd9b00c 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c | |||
@@ -145,7 +145,6 @@ static void ucma_put_ctx(struct ucma_context *ctx) | |||
145 | static struct ucma_context *ucma_alloc_ctx(struct ucma_file *file) | 145 | static struct ucma_context *ucma_alloc_ctx(struct ucma_file *file) |
146 | { | 146 | { |
147 | struct ucma_context *ctx; | 147 | struct ucma_context *ctx; |
148 | int ret; | ||
149 | 148 | ||
150 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | 149 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); |
151 | if (!ctx) | 150 | if (!ctx) |
@@ -156,17 +155,10 @@ static struct ucma_context *ucma_alloc_ctx(struct ucma_file *file) | |||
156 | INIT_LIST_HEAD(&ctx->mc_list); | 155 | INIT_LIST_HEAD(&ctx->mc_list); |
157 | ctx->file = file; | 156 | ctx->file = file; |
158 | 157 | ||
159 | do { | 158 | mutex_lock(&mut); |
160 | ret = idr_pre_get(&ctx_idr, GFP_KERNEL); | 159 | ctx->id = idr_alloc(&ctx_idr, ctx, 0, 0, GFP_KERNEL); |
161 | if (!ret) | 160 | mutex_unlock(&mut); |
162 | goto error; | 161 | if (ctx->id < 0) |
163 | |||
164 | mutex_lock(&mut); | ||
165 | ret = idr_get_new(&ctx_idr, ctx, &ctx->id); | ||
166 | mutex_unlock(&mut); | ||
167 | } while (ret == -EAGAIN); | ||
168 | |||
169 | if (ret) | ||
170 | goto error; | 162 | goto error; |
171 | 163 | ||
172 | list_add_tail(&ctx->list, &file->ctx_list); | 164 | list_add_tail(&ctx->list, &file->ctx_list); |
@@ -180,23 +172,15 @@ error: | |||
180 | static struct ucma_multicast* ucma_alloc_multicast(struct ucma_context *ctx) | 172 | static struct ucma_multicast* ucma_alloc_multicast(struct ucma_context *ctx) |
181 | { | 173 | { |
182 | struct ucma_multicast *mc; | 174 | struct ucma_multicast *mc; |
183 | int ret; | ||
184 | 175 | ||
185 | mc = kzalloc(sizeof(*mc), GFP_KERNEL); | 176 | mc = kzalloc(sizeof(*mc), GFP_KERNEL); |
186 | if (!mc) | 177 | if (!mc) |
187 | return NULL; | 178 | return NULL; |
188 | 179 | ||
189 | do { | 180 | mutex_lock(&mut); |
190 | ret = idr_pre_get(&multicast_idr, GFP_KERNEL); | 181 | mc->id = idr_alloc(&multicast_idr, mc, 0, 0, GFP_KERNEL); |
191 | if (!ret) | 182 | mutex_unlock(&mut); |
192 | goto error; | 183 | if (mc->id < 0) |
193 | |||
194 | mutex_lock(&mut); | ||
195 | ret = idr_get_new(&multicast_idr, mc, &mc->id); | ||
196 | mutex_unlock(&mut); | ||
197 | } while (ret == -EAGAIN); | ||
198 | |||
199 | if (ret) | ||
200 | goto error; | 184 | goto error; |
201 | 185 | ||
202 | mc->ctx = ctx; | 186 | mc->ctx = ctx; |
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index e71d834c922a..a7d00f6b3bc1 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
@@ -125,18 +125,17 @@ static int idr_add_uobj(struct idr *idr, struct ib_uobject *uobj) | |||
125 | { | 125 | { |
126 | int ret; | 126 | int ret; |
127 | 127 | ||
128 | retry: | 128 | idr_preload(GFP_KERNEL); |
129 | if (!idr_pre_get(idr, GFP_KERNEL)) | ||
130 | return -ENOMEM; | ||
131 | |||
132 | spin_lock(&ib_uverbs_idr_lock); | 129 | spin_lock(&ib_uverbs_idr_lock); |
133 | ret = idr_get_new(idr, uobj, &uobj->id); | ||
134 | spin_unlock(&ib_uverbs_idr_lock); | ||
135 | 130 | ||
136 | if (ret == -EAGAIN) | 131 | ret = idr_alloc(idr, uobj, 0, 0, GFP_NOWAIT); |
137 | goto retry; | 132 | if (ret >= 0) |
133 | uobj->id = ret; | ||
138 | 134 | ||
139 | return ret; | 135 | spin_unlock(&ib_uverbs_idr_lock); |
136 | idr_preload_end(); | ||
137 | |||
138 | return ret < 0 ? ret : 0; | ||
140 | } | 139 | } |
141 | 140 | ||
142 | void idr_remove_uobj(struct idr *idr, struct ib_uobject *uobj) | 141 | void idr_remove_uobj(struct idr *idr, struct ib_uobject *uobj) |