diff options
Diffstat (limited to 'ipc')
| -rw-r--r-- | ipc/ipc_sysctl.c | 32 | ||||
| -rw-r--r-- | ipc/util.c | 16 | ||||
| -rw-r--r-- | ipc/util.h | 1 | 
3 files changed, 45 insertions, 4 deletions
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c index 00fba2bab87..130dfece27a 100644 --- a/ipc/ipc_sysctl.c +++ b/ipc/ipc_sysctl.c @@ -158,6 +158,9 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,  static int zero;  static int one = 1; +#ifdef CONFIG_CHECKPOINT_RESTORE +static int int_max = INT_MAX; +#endif  static struct ctl_table ipc_kern_table[] = {  	{ @@ -227,6 +230,35 @@ static struct ctl_table ipc_kern_table[] = {  		.extra1		= &zero,  		.extra2		= &one,  	}, +#ifdef CONFIG_CHECKPOINT_RESTORE +	{ +		.procname	= "sem_next_id", +		.data		= &init_ipc_ns.ids[IPC_SEM_IDS].next_id, +		.maxlen		= sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id), +		.mode		= 0644, +		.proc_handler	= proc_ipc_dointvec_minmax, +		.extra1		= &zero, +		.extra2		= &int_max, +	}, +	{ +		.procname	= "msg_next_id", +		.data		= &init_ipc_ns.ids[IPC_MSG_IDS].next_id, +		.maxlen		= sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id), +		.mode		= 0644, +		.proc_handler	= proc_ipc_dointvec_minmax, +		.extra1		= &zero, +		.extra2		= &int_max, +	}, +	{ +		.procname	= "shm_next_id", +		.data		= &init_ipc_ns.ids[IPC_SHM_IDS].next_id, +		.maxlen		= sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id), +		.mode		= 0644, +		.proc_handler	= proc_ipc_dointvec_minmax, +		.extra1		= &zero, +		.extra2		= &int_max, +	}, +#endif  	{}  }; diff --git a/ipc/util.c b/ipc/util.c index 72fd0785ac9..74e1d9c7a98 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; diff --git a/ipc/util.h b/ipc/util.h index c8fe2f7631e..a61e0ca2bff 100644 --- a/ipc/util.h +++ b/ipc/util.h @@ -92,6 +92,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header,  #define IPC_SHM_IDS	2  #define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER) +#define ipcid_to_seqx(id) ((id) / SEQ_MULTIPLIER)  /* must be called with ids->rw_mutex acquired for writing */  int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);  |