diff options
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) { kuid_t euid; kgid_t egid; - int id, err; + int id; int next_id = ids->next_id; if (size > IPCMNI) @@ -261,17 +261,21 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) if (ids->in_use >= size) return -ENOSPC; + idr_preload(GFP_KERNEL); + spin_lock_init(&new->lock); new->deleted = 0; rcu_read_lock(); spin_lock(&new->lock); - err = idr_get_new_above(&ids->ipcs_idr, new, - (next_id < 0) ? 0 : ipcid_to_idx(next_id), &id); - if (err) { + id = idr_alloc(&ids->ipcs_idr, new, + (next_id < 0) ? 0 : ipcid_to_idx(next_id), 0, + GFP_NOWAIT); + idr_preload_end(); + if (id < 0) { spin_unlock(&new->lock); rcu_read_unlock(); - return err; + return id; } ids->in_use++; @@ -307,19 +311,10 @@ static int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids, struct ipc_ops *ops, struct ipc_params *params) { int err; -retry: - err = idr_pre_get(&ids->ipcs_idr, GFP_KERNEL); - - if (!err) - return -ENOMEM; down_write(&ids->rw_mutex); err = ops->getnew(ns, params); up_write(&ids->rw_mutex); - - if (err == -EAGAIN) - goto retry; - return err; } @@ -376,8 +371,6 @@ static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids, struct kern_ipc_perm *ipcp; int flg = params->flg; int err; -retry: - err = idr_pre_get(&ids->ipcs_idr, GFP_KERNEL); /* * Take the lock as a writer since we are potentially going to add @@ -389,8 +382,6 @@ retry: /* key not used */ if (!(flg & IPC_CREAT)) err = -ENOENT; - else if (!err) - err = -ENOMEM; else err = ops->getnew(ns, params); } else { @@ -413,9 +404,6 @@ retry: } up_write(&ids->rw_mutex); - if (err == -EAGAIN) - goto retry; - return err; } |