Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 03f59566 authored by Stanislav Kinsbursky's avatar Stanislav Kinsbursky Committed by Linus Torvalds
Browse files

ipc: add sysctl to specify desired next object id



Add 3 new variables and sysctls to tune them (by one "next_id" variable
for messages, semaphores and shared memory respectively).  This variable
can be used to set desired id for next allocated IPC object.  By default
it's equal to -1 and old behaviour is preserved.  If this variable is
non-negative, then desired idr will be extracted from it and used as a
start value to search for free IDR slot.

Notes:

1) this patch doesn't guarantee that the new object will have desired
   id.  So it's up to user space how to handle new object with wrong id.

2) After a sucessful id allocation attempt, "next_id" will be set back
   to -1 (if it was non-negative).

[akpm@linux-foundation.org: checkpatch fixes]
Signed-off-by: default avatarStanislav Kinsbursky <skinsbursky@parallels.com>
Cc: Serge Hallyn <serge.hallyn@canonical.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 9afdacda
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ show up in /proc/sys/kernel:
- l2cr                        [ PPC only ]
- modprobe                    ==> Documentation/debugging-modules.txt
- modules_disabled
- msg_next_id		      [ sysv ipc ]
- msgmax
- msgmnb
- msgmni
@@ -62,7 +63,9 @@ show up in /proc/sys/kernel:
- rtsig-max
- rtsig-nr
- sem
- sem_next_id		      [ sysv ipc ]
- sg-big-buff                 [ generic SCSI device (sg) ]
- shm_next_id		      [ sysv ipc ]
- shm_rmid_forced
- shmall
- shmmax                      [ sysv ipc ]
@@ -320,6 +323,22 @@ to false.

==============================================================

msg_next_id, sem_next_id, and shm_next_id:

These three toggles allows to specify desired id for next allocated IPC
object: message, semaphore or shared memory respectively.

By default they are equal to -1, which means generic allocation logic.
Possible values to set are in range {0..INT_MAX}.

Notes:
1) kernel doesn't guarantee, that new object will have desired id. So,
it's up to userspace, how to handle an object with "wrong" id.
2) Toggle with non-default value will be set back to -1 by kernel after
successful IPC object allocation.

==============================================================

nmi_watchdog:

Enables/Disables the NMI watchdog on x86 systems. When the value is
+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ struct ipc_ids {
	unsigned short seq_max;
	struct rw_semaphore rw_mutex;
	struct idr ipcs_idr;
	int next_id;
};

struct ipc_namespace {
+32 −0
Original line number Diff line number Diff line
@@ -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
	{}
};

+12 −4
Original line number Diff line number Diff line
@@ -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;

	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;
+1 −0
Original line number Diff line number Diff line
@@ -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);