diff options
Diffstat (limited to 'ipc/util.c')
| -rw-r--r-- | ipc/util.c | 16 | 
1 files changed, 12 insertions, 4 deletions
diff --git a/ipc/util.c b/ipc/util.c index 72fd0785ac94..74e1d9c7a98a 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -122,6 +122,7 @@ void ipc_init_ids(struct ipc_ids *ids)  	ids->in_use = 0;  	ids->seq = 0; +	ids->next_id = -1;  	{  		int seq_limit = INT_MAX/SEQ_MULTIPLIER;  		if (seq_limit > USHRT_MAX) @@ -252,6 +253,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 next_id = ids->next_id;  	if (size > IPCMNI)  		size = IPCMNI; @@ -264,7 +266,8 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)  	rcu_read_lock();  	spin_lock(&new->lock); -	err = idr_get_new(&ids->ipcs_idr, new, &id); +	err = idr_get_new_above(&ids->ipcs_idr, new, +				(next_id < 0) ? 0 : ipcid_to_idx(next_id), &id);  	if (err) {  		spin_unlock(&new->lock);  		rcu_read_unlock(); @@ -277,9 +280,14 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)  	new->cuid = new->uid = euid;  	new->gid = new->cgid = egid; -	new->seq = ids->seq++; -	if(ids->seq > ids->seq_max) -		ids->seq = 0; +	if (next_id < 0) { +		new->seq = ids->seq++; +		if (ids->seq > ids->seq_max) +			ids->seq = 0; +	} else { +		new->seq = ipcid_to_seqx(next_id); +		ids->next_id = -1; +	}  	new->id = ipc_buildid(id, new->seq);  	return id;  |