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

Commit 7ca7e564 authored by Nadia Derbey's avatar Nadia Derbey Committed by Linus Torvalds
Browse files

ipc: store ipcs into IDRs



This patch introduces ipcs storage into IDRs. The main changes are:
  . This ipc_ids structure is changed: the entries array is changed into a
    root idr structure.
  . The grow_ary() routine is removed: it is not needed anymore when adding
    an ipc structure, since we are now using the IDR facility.
  . The ipc_rmid() routine interface is changed:
       . there is no need for this routine to return the pointer passed in as
         argument: it is now declared as a void
       . since the id is now part of the kern_ipc_perm structure, no need to
         have it as an argument to the routine

Signed-off-by: default avatarNadia Derbey <Nadia.Derbey@bull.net>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent d2b20b11
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ struct kern_ipc_perm
{
	spinlock_t	lock;
	int		deleted;
	int		id;
	key_t		key;
	uid_t		uid;
	gid_t		gid;
+0 −1
Original line number Diff line number Diff line
@@ -77,7 +77,6 @@ struct msg_msg {
/* one msq_queue structure for each present queue on the system */
struct msg_queue {
	struct kern_ipc_perm q_perm;
	int q_id;
	time_t q_stime;			/* last msgsnd time */
	time_t q_rtime;			/* last msgrcv time */
	time_t q_ctime;			/* last change time */
+0 −1
Original line number Diff line number Diff line
@@ -90,7 +90,6 @@ struct sem {
/* One sem_array data structure for each set of semaphores in the system. */
struct sem_array {
	struct kern_ipc_perm	sem_perm;	/* permissions .. see ipc.h */
	int			sem_id;
	time_t			sem_otime;	/* last semop time */
	time_t			sem_ctime;	/* last change time */
	struct sem		*sem_base;	/* ptr to first semaphore in array */
+0 −1
Original line number Diff line number Diff line
@@ -79,7 +79,6 @@ struct shmid_kernel /* private to the kernel */
{	
	struct kern_ipc_perm	shm_perm;
	struct file *		shm_file;
	int			id;
	unsigned long		shm_nattch;
	unsigned long		shm_segsz;
	time_t			shm_atim;
+70 −45
Original line number Diff line number Diff line
@@ -75,13 +75,12 @@ static struct ipc_ids init_msg_ids;

#define msg_lock(ns, id)	((struct msg_queue*)ipc_lock(&msg_ids(ns), id))
#define msg_unlock(msq)		ipc_unlock(&(msq)->q_perm)
#define msg_rmid(ns, id)	((struct msg_queue*)ipc_rmid(&msg_ids(ns), id))
#define msg_checkid(ns, msq, msgid)	\
	ipc_checkid(&msg_ids(ns), &msq->q_perm, msgid)
#define msg_buildid(ns, id, seq) \
	ipc_buildid(&msg_ids(ns), id, seq)

static void freeque (struct ipc_namespace *ns, struct msg_queue *msq, int id);
static void freeque(struct ipc_namespace *, struct msg_queue *);
static int newque (struct ipc_namespace *ns, key_t key, int msgflg);
#ifdef CONFIG_PROC_FS
static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
@@ -93,7 +92,7 @@ static void __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
	ns->msg_ctlmax = MSGMAX;
	ns->msg_ctlmnb = MSGMNB;
	ns->msg_ctlmni = MSGMNI;
	ipc_init_ids(ids, ns->msg_ctlmni);
	ipc_init_ids(ids);
}

int msg_init_ns(struct ipc_namespace *ns)
@@ -110,20 +109,24 @@ int msg_init_ns(struct ipc_namespace *ns)

void msg_exit_ns(struct ipc_namespace *ns)
{
	int i;
	struct msg_queue *msq;
	int next_id;
	int total, in_use;

	mutex_lock(&msg_ids(ns).mutex);
	for (i = 0; i <= msg_ids(ns).max_id; i++) {
		msq = msg_lock(ns, i);

	in_use = msg_ids(ns).in_use;

	for (total = 0, next_id = 0; total < in_use; next_id++) {
		msq = idr_find(&msg_ids(ns).ipcs_idr, next_id);
		if (msq == NULL)
			continue;

		freeque(ns, msq, i);
		ipc_lock_by_ptr(&msq->q_perm);
		freeque(ns, msq);
		total++;
	}
	mutex_unlock(&msg_ids(ns).mutex);

	ipc_fini_ids(ns->ids[IPC_MSG_IDS]);
	kfree(ns->ids[IPC_MSG_IDS]);
	ns->ids[IPC_MSG_IDS] = NULL;
}
@@ -136,6 +139,11 @@ void __init msg_init(void)
				IPC_MSG_IDS, sysvipc_msg_proc_show);
}

static inline void msg_rmid(struct ipc_namespace *ns, struct msg_queue *s)
{
	ipc_rmid(&msg_ids(ns), &s->q_perm);
}

static int newque (struct ipc_namespace *ns, key_t key, int msgflg)
{
	struct msg_queue *msq;
@@ -155,6 +163,9 @@ static int newque (struct ipc_namespace *ns, key_t key, int msgflg)
		return retval;
	}

	/*
	 * ipc_addid() locks msq
	 */
	id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni);
	if (id == -1) {
		security_msg_queue_free(msq);
@@ -162,7 +173,7 @@ static int newque (struct ipc_namespace *ns, key_t key, int msgflg)
		return -ENOSPC;
	}

	msq->q_id = msg_buildid(ns, id, msq->q_perm.seq);
	msq->q_perm.id = msg_buildid(ns, id, msq->q_perm.seq);
	msq->q_stime = msq->q_rtime = 0;
	msq->q_ctime = get_seconds();
	msq->q_cbytes = msq->q_qnum = 0;
@@ -171,9 +182,10 @@ static int newque (struct ipc_namespace *ns, key_t key, int msgflg)
	INIT_LIST_HEAD(&msq->q_messages);
	INIT_LIST_HEAD(&msq->q_receivers);
	INIT_LIST_HEAD(&msq->q_senders);

	msg_unlock(msq);

	return msq->q_id;
	return msq->q_perm.id;
}

static inline void ss_add(struct msg_queue *msq, struct msg_sender *mss)
@@ -225,18 +237,18 @@ static void expunge_all(struct msg_queue *msq, int res)
/*
 * freeque() wakes up waiters on the sender and receiver waiting queue,
 * removes the message queue from message queue ID
 * array, and cleans up all the messages associated with this queue.
 * IDR, and cleans up all the messages associated with this queue.
 *
 * msg_ids.mutex and the spinlock for this message queue is hold
 * msg_ids.mutex and the spinlock for this message queue are held
 * before freeque() is called. msg_ids.mutex remains locked on exit.
 */
static void freeque(struct ipc_namespace *ns, struct msg_queue *msq, int id)
static void freeque(struct ipc_namespace *ns, struct msg_queue *msq)
{
	struct list_head *tmp;

	expunge_all(msq, -EIDRM);
	ss_wakeup(&msq->q_senders, 1);
	msq = msg_rmid(ns, id);
	msg_rmid(ns, msq);
	msg_unlock(msq);

	tmp = msq->q_messages.next;
@@ -255,36 +267,51 @@ static void freeque(struct ipc_namespace *ns, struct msg_queue *msq, int id)
asmlinkage long sys_msgget(key_t key, int msgflg)
{
	struct msg_queue *msq;
	int id, ret = -EPERM;
	int ret;
	struct ipc_namespace *ns;

	ns = current->nsproxy->ipc_ns;

	ret = idr_pre_get(&msg_ids(ns).ipcs_idr, GFP_KERNEL);

	if (key == IPC_PRIVATE)  {
		if (!ret)
			ret = -ENOMEM;
		else {
			mutex_lock(&msg_ids(ns).mutex);
	if (key == IPC_PRIVATE) 
			ret = newque(ns, key, msgflg);
	else if ((id = ipc_findkey(&msg_ids(ns), key)) == -1) { /* key not used */
			mutex_unlock(&msg_ids(ns).mutex);
		}
	} else {
		mutex_lock(&msg_ids(ns).mutex);
		msq = (struct msg_queue *) ipc_findkey(&msg_ids(ns), key);
		if (msq == NULL) {
			/* key not used */
			if (!(msgflg & IPC_CREAT))
				ret = -ENOENT;
			else if (!ret)
				ret = -ENOMEM;
			else
				ret = newque(ns, key, msgflg);
	} else if (msgflg & IPC_CREAT && msgflg & IPC_EXCL) {
		ret = -EEXIST;
		} else {
		msq = msg_lock(ns, id);
		BUG_ON(msq == NULL);
			/* msq has been locked by ipc_findkey() */

			if (msgflg & IPC_CREAT && msgflg & IPC_EXCL)
				ret = -EEXIST;
			else {
				if (ipcperms(&msq->q_perm, msgflg))
					ret = -EACCES;
				else {
			int qid = msg_buildid(ns, id, msq->q_perm.seq);

			ret = security_msg_queue_associate(msq, msgflg);
					ret = security_msg_queue_associate(
								msq, msgflg);
					if (!ret)
				ret = qid;
						ret = msq->q_perm.id;
				}
			}
			msg_unlock(msq);
		}
		mutex_unlock(&msg_ids(ns).mutex);
	}

	return ret;
}
@@ -430,13 +457,13 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
			msginfo.msgpool = MSGPOOL;
			msginfo.msgtql = MSGTQL;
		}
		max_id = msg_ids(ns).max_id;
		max_id = ipc_get_maxid(&msg_ids(ns));
		mutex_unlock(&msg_ids(ns).mutex);
		if (copy_to_user(buf, &msginfo, sizeof(struct msginfo)))
			return -EFAULT;
		return (max_id < 0) ? 0 : max_id;
	}
	case MSG_STAT:
	case MSG_STAT:	/* msqid is an index rather than a msg queue id */
	case IPC_STAT:
	{
		struct msqid64_ds tbuf;
@@ -444,8 +471,6 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)

		if (!buf)
			return -EFAULT;
		if (cmd == MSG_STAT && msqid >= msg_ids(ns).entries->size)
			return -EINVAL;

		memset(&tbuf, 0, sizeof(tbuf));

@@ -454,7 +479,7 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
			return -EINVAL;

		if (cmd == MSG_STAT) {
			success_return = msg_buildid(ns, msqid, msq->q_perm.seq);
			success_return = msq->q_perm.id;
		} else {
			err = -EIDRM;
			if (msg_checkid(ns, msq, msqid))
@@ -552,7 +577,7 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
		break;
	}
	case IPC_RMID:
		freeque(ns, msq, msqid);
		freeque(ns, msq);
		break;
	}
	err = 0;
@@ -926,7 +951,7 @@ static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
	return seq_printf(s,
			"%10d %10d  %4o  %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n",
			msq->q_perm.key,
			msq->q_id,
			msq->q_perm.id,
			msq->q_perm.mode,
			msq->q_cbytes,
			msq->q_qnum,
Loading