diff options
author | Tejun Heo <tj@kernel.org> | 2013-02-27 20:04:53 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-27 22:10:19 -0500 |
commit | 54924ea33f3ba702243ba4ab068d7d2852db8098 (patch) | |
tree | 0a5adb06fe63726325ef9197bb4d49f2567d5231 /ipc | |
parent | 6b207ba3ebe7428a18878c58130e13a3e3bccef9 (diff) |
ipc: convert to idr_alloc()
Convert to the much saner new idr interface.
The new interface doesn't directly translate to the way idr_pre_get()
was used around ipc_addid() as preloading disables preemption. From
my cursory reading, it seems like we should be able to do all
allocation from ipc_addid(), so I moved it there. Can you please
check whether this would be okay? If this is wrong and ipc_addid()
should be allowed to be called from non-sleepable context, I'd suggest
allocating id itself in the outer functions and later install the
pointer using idr_replace().
Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: Sedat Dilek <sedat.dilek@gmail.com>
Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
Cc: Stanislav Kinsbursky <skinsbursky@parallels.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: James Morris <jmorris@namei.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/util.c | 30 |
1 files changed, 9 insertions, 21 deletions
diff --git a/ipc/util.c b/ipc/util.c index 74e1d9c7a98a..464a8abd779f 100644 --- a/ipc/util.c +++ b/ipc/util.c | |||
@@ -252,7 +252,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) | |||
252 | { | 252 | { |
253 | kuid_t euid; | 253 | kuid_t euid; |
254 | kgid_t egid; | 254 | kgid_t egid; |
255 | int id, err; | 255 | int id; |
256 | int next_id = ids->next_id; | 256 | int next_id = ids->next_id; |
257 | 257 | ||
258 | if (size > IPCMNI) | 258 | if (size > IPCMNI) |
@@ -261,17 +261,21 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) | |||
261 | if (ids->in_use >= size) | 261 | if (ids->in_use >= size) |
262 | return -ENOSPC; | 262 | return -ENOSPC; |
263 | 263 | ||
264 | idr_preload(GFP_KERNEL); | ||
265 | |||
264 | spin_lock_init(&new->lock); | 266 | spin_lock_init(&new->lock); |
265 | new->deleted = 0; | 267 | new->deleted = 0; |
266 | rcu_read_lock(); | 268 | rcu_read_lock(); |
267 | spin_lock(&new->lock); | 269 | spin_lock(&new->lock); |
268 | 270 | ||
269 | err = idr_get_new_above(&ids->ipcs_idr, new, | 271 | id = idr_alloc(&ids->ipcs_idr, new, |
270 | (next_id < 0) ? 0 : ipcid_to_idx(next_id), &id); | 272 | (next_id < 0) ? 0 : ipcid_to_idx(next_id), 0, |
271 | if (err) { | 273 | GFP_NOWAIT); |
274 | idr_preload_end(); | ||
275 | if (id < 0) { | ||
272 | spin_unlock(&new->lock); | 276 | spin_unlock(&new->lock); |
273 | rcu_read_unlock(); | 277 | rcu_read_unlock(); |
274 | return err; | 278 | return id; |
275 | } | 279 | } |
276 | 280 | ||
277 | ids->in_use++; | 281 | ids->in_use++; |
@@ -307,19 +311,10 @@ static int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids, | |||
307 | struct ipc_ops *ops, struct ipc_params *params) | 311 | struct ipc_ops *ops, struct ipc_params *params) |
308 | { | 312 | { |
309 | int err; | 313 | int err; |
310 | retry: | ||
311 | err = idr_pre_get(&ids->ipcs_idr, GFP_KERNEL); | ||
312 | |||
313 | if (!err) | ||
314 | return -ENOMEM; | ||
315 | 314 | ||
316 | down_write(&ids->rw_mutex); | 315 | down_write(&ids->rw_mutex); |
317 | err = ops->getnew(ns, params); | 316 | err = ops->getnew(ns, params); |
318 | up_write(&ids->rw_mutex); | 317 | up_write(&ids->rw_mutex); |
319 | |||
320 | if (err == -EAGAIN) | ||
321 | goto retry; | ||
322 | |||
323 | return err; | 318 | return err; |
324 | } | 319 | } |
325 | 320 | ||
@@ -376,8 +371,6 @@ static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids, | |||
376 | struct kern_ipc_perm *ipcp; | 371 | struct kern_ipc_perm *ipcp; |
377 | int flg = params->flg; | 372 | int flg = params->flg; |
378 | int err; | 373 | int err; |
379 | retry: | ||
380 | err = idr_pre_get(&ids->ipcs_idr, GFP_KERNEL); | ||
381 | 374 | ||
382 | /* | 375 | /* |
383 | * Take the lock as a writer since we are potentially going to add | 376 | * Take the lock as a writer since we are potentially going to add |
@@ -389,8 +382,6 @@ retry: | |||
389 | /* key not used */ | 382 | /* key not used */ |
390 | if (!(flg & IPC_CREAT)) | 383 | if (!(flg & IPC_CREAT)) |
391 | err = -ENOENT; | 384 | err = -ENOENT; |
392 | else if (!err) | ||
393 | err = -ENOMEM; | ||
394 | else | 385 | else |
395 | err = ops->getnew(ns, params); | 386 | err = ops->getnew(ns, params); |
396 | } else { | 387 | } else { |
@@ -413,9 +404,6 @@ retry: | |||
413 | } | 404 | } |
414 | up_write(&ids->rw_mutex); | 405 | up_write(&ids->rw_mutex); |
415 | 406 | ||
416 | if (err == -EAGAIN) | ||
417 | goto retry; | ||
418 | |||
419 | return err; | 407 | return err; |
420 | } | 408 | } |
421 | 409 | ||