diff options
Diffstat (limited to 'ipc/msg.c')
| -rw-r--r-- | ipc/msg.c | 188 | 
1 files changed, 92 insertions, 96 deletions
diff --git a/ipc/msg.c b/ipc/msg.c index 649853105a5d..c5d8e3749985 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -39,12 +39,10 @@  #include <linux/ipc_namespace.h>  #include <asm/current.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h>  #include "util.h" -/* - * one msg_receiver structure for each sleeping receiver: - */ +/* one msg_receiver structure for each sleeping receiver */  struct msg_receiver {  	struct list_head	r_list;  	struct task_struct	*r_tsk; @@ -53,6 +51,12 @@ struct msg_receiver {  	long			r_msgtype;  	long			r_maxsize; +	/* +	 * Mark r_msg volatile so that the compiler +	 * does not try to get smart and optimize +	 * it. We rely on this for the lockless +	 * receive algorithm. +	 */  	struct msg_msg		*volatile r_msg;  }; @@ -70,75 +74,6 @@ struct msg_sender {  #define msg_ids(ns)	((ns)->ids[IPC_MSG_IDS]) -static void freeque(struct ipc_namespace *, struct kern_ipc_perm *); -static int newque(struct ipc_namespace *, struct ipc_params *); -#ifdef CONFIG_PROC_FS -static int sysvipc_msg_proc_show(struct seq_file *s, void *it); -#endif - -/* - * Scale msgmni with the available lowmem size: the memory dedicated to msg - * queues should occupy at most 1/MSG_MEM_SCALE of lowmem. - * Also take into account the number of nsproxies created so far. - * This should be done staying within the (MSGMNI , IPCMNI/nr_ipc_ns) range. - */ -void recompute_msgmni(struct ipc_namespace *ns) -{ -	struct sysinfo i; -	unsigned long allowed; -	int nb_ns; - -	si_meminfo(&i); -	allowed = (((i.totalram - i.totalhigh) / MSG_MEM_SCALE) * i.mem_unit) -		/ MSGMNB; -	nb_ns = atomic_read(&nr_ipc_ns); -	allowed /= nb_ns; - -	if (allowed < MSGMNI) { -		ns->msg_ctlmni = MSGMNI; -		return; -	} - -	if (allowed > IPCMNI / nb_ns) { -		ns->msg_ctlmni = IPCMNI / nb_ns; -		return; -	} - -	ns->msg_ctlmni = allowed; -} - -void msg_init_ns(struct ipc_namespace *ns) -{ -	ns->msg_ctlmax = MSGMAX; -	ns->msg_ctlmnb = MSGMNB; - -	recompute_msgmni(ns); - -	atomic_set(&ns->msg_bytes, 0); -	atomic_set(&ns->msg_hdrs, 0); -	ipc_init_ids(&ns->ids[IPC_MSG_IDS]); -} - -#ifdef CONFIG_IPC_NS -void msg_exit_ns(struct ipc_namespace *ns) -{ -	free_ipcs(ns, &msg_ids(ns), freeque); -	idr_destroy(&ns->ids[IPC_MSG_IDS].ipcs_idr); -} -#endif - -void __init msg_init(void) -{ -	msg_init_ns(&init_ipc_ns); - -	printk(KERN_INFO "msgmni has been set to %d\n", -		init_ipc_ns.msg_ctlmni); - -	ipc_init_proc_interface("sysvipc/msg", -				"       key      msqid perms      cbytes       qnum lspid lrpid   uid   gid  cuid  cgid      stime      rtime      ctime\n", -				IPC_MSG_IDS, sysvipc_msg_proc_show); -} -  static inline struct msg_queue *msq_obtain_object(struct ipc_namespace *ns, int id)  {  	struct kern_ipc_perm *ipcp = ipc_obtain_object(&msg_ids(ns), id); @@ -227,7 +162,7 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)  static inline void ss_add(struct msg_queue *msq, struct msg_sender *mss)  {  	mss->tsk = current; -	current->state = TASK_INTERRUPTIBLE; +	__set_current_state(TASK_INTERRUPTIBLE);  	list_add_tail(&mss->list, &msq->q_senders);  } @@ -306,15 +241,14 @@ static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg)  SYSCALL_DEFINE2(msgget, key_t, key, int, msgflg)  {  	struct ipc_namespace *ns; -	struct ipc_ops msg_ops; +	static const struct ipc_ops msg_ops = { +		.getnew = newque, +		.associate = msg_security, +	};  	struct ipc_params msg_params;  	ns = current->nsproxy->ipc_ns; -	msg_ops.getnew = newque; -	msg_ops.associate = msg_security; -	msg_ops.more_checks = NULL; -  	msg_params.key = key;  	msg_params.flg = msgflg; @@ -612,23 +546,22 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)  static int testmsg(struct msg_msg *msg, long type, int mode)  { -	switch (mode) -	{ -		case SEARCH_ANY: -		case SEARCH_NUMBER: +	switch (mode) { +	case SEARCH_ANY: +	case SEARCH_NUMBER: +		return 1; +	case SEARCH_LESSEQUAL: +		if (msg->m_type <= type)  			return 1; -		case SEARCH_LESSEQUAL: -			if (msg->m_type <= type) -				return 1; -			break; -		case SEARCH_EQUAL: -			if (msg->m_type == type) -				return 1; -			break; -		case SEARCH_NOTEQUAL: -			if (msg->m_type != type) -				return 1; -			break; +		break; +	case SEARCH_EQUAL: +		if (msg->m_type == type) +			return 1; +		break; +	case SEARCH_NOTEQUAL: +		if (msg->m_type != type) +			return 1; +		break;  	}  	return 0;  } @@ -978,7 +911,7 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgfl  		else  			msr_d.r_maxsize = bufsz;  		msr_d.r_msg = ERR_PTR(-EAGAIN); -		current->state = TASK_INTERRUPTIBLE; +		__set_current_state(TASK_INTERRUPTIBLE);  		ipc_unlock_object(&msq->q_perm);  		rcu_read_unlock(); @@ -1056,6 +989,57 @@ SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,  	return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill);  } +/* + * Scale msgmni with the available lowmem size: the memory dedicated to msg + * queues should occupy at most 1/MSG_MEM_SCALE of lowmem. + * Also take into account the number of nsproxies created so far. + * This should be done staying within the (MSGMNI , IPCMNI/nr_ipc_ns) range. + */ +void recompute_msgmni(struct ipc_namespace *ns) +{ +	struct sysinfo i; +	unsigned long allowed; +	int nb_ns; + +	si_meminfo(&i); +	allowed = (((i.totalram - i.totalhigh) / MSG_MEM_SCALE) * i.mem_unit) +		/ MSGMNB; +	nb_ns = atomic_read(&nr_ipc_ns); +	allowed /= nb_ns; + +	if (allowed < MSGMNI) { +		ns->msg_ctlmni = MSGMNI; +		return; +	} + +	if (allowed > IPCMNI / nb_ns) { +		ns->msg_ctlmni = IPCMNI / nb_ns; +		return; +	} + +	ns->msg_ctlmni = allowed; +} + +void msg_init_ns(struct ipc_namespace *ns) +{ +	ns->msg_ctlmax = MSGMAX; +	ns->msg_ctlmnb = MSGMNB; + +	recompute_msgmni(ns); + +	atomic_set(&ns->msg_bytes, 0); +	atomic_set(&ns->msg_hdrs, 0); +	ipc_init_ids(&ns->ids[IPC_MSG_IDS]); +} + +#ifdef CONFIG_IPC_NS +void msg_exit_ns(struct ipc_namespace *ns) +{ +	free_ipcs(ns, &msg_ids(ns), freeque); +	idr_destroy(&ns->ids[IPC_MSG_IDS].ipcs_idr); +} +#endif +  #ifdef CONFIG_PROC_FS  static int sysvipc_msg_proc_show(struct seq_file *s, void *it)  { @@ -1080,3 +1064,15 @@ static int sysvipc_msg_proc_show(struct seq_file *s, void *it)  			msq->q_ctime);  }  #endif + +void __init msg_init(void) +{ +	msg_init_ns(&init_ipc_ns); + +	printk(KERN_INFO "msgmni has been set to %d\n", +		init_ipc_ns.msg_ctlmni); + +	ipc_init_proc_interface("sysvipc/msg", +				"       key      msqid perms      cbytes       qnum lspid lrpid   uid   gid  cuid  cgid      stime      rtime      ctime\n", +				IPC_MSG_IDS, sysvipc_msg_proc_show); +}  |