aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Peiffer <pierre.peiffer@bull.net>2008-02-08 07:18:57 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-08 12:22:26 -0500
commited2ddbf88c0ddeeae4c78bb306a116dfd867c55c (patch)
treede6d6828c03f98be6fc41e8acf3b3e52df28be9b
parent4b9fcb0ec60584d639ad105c42b75a3447071e47 (diff)
IPC: make struct ipc_ids static in ipc_namespace
Each ipc_namespace contains a table of 3 pointers to struct ipc_ids (3 for msg, sem and shm, structure used to store all ipcs) These 'struct ipc_ids' are dynamically allocated for each icp_namespace as the ipc_namespace itself (for the init namespace, they are initialized with pointers to static variables instead) It is so for historical reason: in fact, before the use of idr to store the ipcs, the ipcs were stored in tables of variable length, depending of the maximum number of ipc allowed. Now, these 'struct ipc_ids' have a fixed size. As they are allocated in any cases for each new ipc_namespace, there is no gain of memory in having them allocated separately of the struct ipc_namespace. This patch proposes to make this table static in the struct ipc_namespace. Thus, we can allocate all in once and get rid of all the code needed to allocate and free these ipc_ids separately. Signed-off-by: Pierre Peiffer <pierre.peiffer@bull.net> Acked-by: Cedric Le Goater <clg@fr.ibm.com> Cc: Pavel Emelyanov <xemul@openvz.org> Cc: Nadia Derbey <Nadia.Derbey@bull.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/ipc_namespace.h13
-rw-r--r--ipc/msg.c26
-rw-r--r--ipc/namespace.c25
-rw-r--r--ipc/sem.c26
-rw-r--r--ipc/shm.c26
-rw-r--r--ipc/util.c6
-rw-r--r--ipc/util.h16
7 files changed, 34 insertions, 104 deletions
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index a491fc9dd231..6db5522eef51 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -2,11 +2,20 @@
2#define __IPC_NAMESPACE_H__ 2#define __IPC_NAMESPACE_H__
3 3
4#include <linux/err.h> 4#include <linux/err.h>
5#include <linux/idr.h>
6#include <linux/rwsem.h>
7
8struct ipc_ids {
9 int in_use;
10 unsigned short seq;
11 unsigned short seq_max;
12 struct rw_semaphore rw_mutex;
13 struct idr ipcs_idr;
14};
5 15
6struct ipc_ids;
7struct ipc_namespace { 16struct ipc_namespace {
8 struct kref kref; 17 struct kref kref;
9 struct ipc_ids *ids[3]; 18 struct ipc_ids ids[3];
10 19
11 int sem_ctls[4]; 20 int sem_ctls[4];
12 int used_sems; 21 int used_sems;
diff --git a/ipc/msg.c b/ipc/msg.c
index 5879bfeb79ca..ab0c38b29533 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -67,9 +67,7 @@ struct msg_sender {
67#define SEARCH_NOTEQUAL 3 67#define SEARCH_NOTEQUAL 3
68#define SEARCH_LESSEQUAL 4 68#define SEARCH_LESSEQUAL 4
69 69
70static struct ipc_ids init_msg_ids; 70#define msg_ids(ns) ((ns)->ids[IPC_MSG_IDS])
71
72#define msg_ids(ns) (*((ns)->ids[IPC_MSG_IDS]))
73 71
74#define msg_unlock(msq) ipc_unlock(&(msq)->q_perm) 72#define msg_unlock(msq) ipc_unlock(&(msq)->q_perm)
75#define msg_buildid(id, seq) ipc_buildid(id, seq) 73#define msg_buildid(id, seq) ipc_buildid(id, seq)
@@ -80,30 +78,17 @@ static int newque(struct ipc_namespace *, struct ipc_params *);
80static int sysvipc_msg_proc_show(struct seq_file *s, void *it); 78static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
81#endif 79#endif
82 80
83static void __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids) 81void msg_init_ns(struct ipc_namespace *ns)
84{ 82{
85 ns->ids[IPC_MSG_IDS] = ids;
86 ns->msg_ctlmax = MSGMAX; 83 ns->msg_ctlmax = MSGMAX;
87 ns->msg_ctlmnb = MSGMNB; 84 ns->msg_ctlmnb = MSGMNB;
88 ns->msg_ctlmni = MSGMNI; 85 ns->msg_ctlmni = MSGMNI;
89 atomic_set(&ns->msg_bytes, 0); 86 atomic_set(&ns->msg_bytes, 0);
90 atomic_set(&ns->msg_hdrs, 0); 87 atomic_set(&ns->msg_hdrs, 0);
91 ipc_init_ids(ids); 88 ipc_init_ids(&ns->ids[IPC_MSG_IDS]);
92} 89}
93 90
94#ifdef CONFIG_IPC_NS 91#ifdef CONFIG_IPC_NS
95int msg_init_ns(struct ipc_namespace *ns)
96{
97 struct ipc_ids *ids;
98
99 ids = kmalloc(sizeof(struct ipc_ids), GFP_KERNEL);
100 if (ids == NULL)
101 return -ENOMEM;
102
103 __msg_init_ns(ns, ids);
104 return 0;
105}
106
107void msg_exit_ns(struct ipc_namespace *ns) 92void msg_exit_ns(struct ipc_namespace *ns)
108{ 93{
109 struct msg_queue *msq; 94 struct msg_queue *msq;
@@ -126,15 +111,12 @@ void msg_exit_ns(struct ipc_namespace *ns)
126 } 111 }
127 112
128 up_write(&msg_ids(ns).rw_mutex); 113 up_write(&msg_ids(ns).rw_mutex);
129
130 kfree(ns->ids[IPC_MSG_IDS]);
131 ns->ids[IPC_MSG_IDS] = NULL;
132} 114}
133#endif 115#endif
134 116
135void __init msg_init(void) 117void __init msg_init(void)
136{ 118{
137 __msg_init_ns(&init_ipc_ns, &init_msg_ids); 119 msg_init_ns(&init_ipc_ns);
138 ipc_init_proc_interface("sysvipc/msg", 120 ipc_init_proc_interface("sysvipc/msg",
139 " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n", 121 " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n",
140 IPC_MSG_IDS, sysvipc_msg_proc_show); 122 IPC_MSG_IDS, sysvipc_msg_proc_show);
diff --git a/ipc/namespace.c b/ipc/namespace.c
index cef1139e6c96..1fed8922d475 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -14,35 +14,18 @@
14 14
15static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns) 15static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns)
16{ 16{
17 int err;
18 struct ipc_namespace *ns; 17 struct ipc_namespace *ns;
19 18
20 err = -ENOMEM;
21 ns = kmalloc(sizeof(struct ipc_namespace), GFP_KERNEL); 19 ns = kmalloc(sizeof(struct ipc_namespace), GFP_KERNEL);
22 if (ns == NULL) 20 if (ns == NULL)
23 goto err_mem; 21 return ERR_PTR(-ENOMEM);
24 22
25 err = sem_init_ns(ns); 23 sem_init_ns(ns);
26 if (err) 24 msg_init_ns(ns);
27 goto err_sem; 25 shm_init_ns(ns);
28 err = msg_init_ns(ns);
29 if (err)
30 goto err_msg;
31 err = shm_init_ns(ns);
32 if (err)
33 goto err_shm;
34 26
35 kref_init(&ns->kref); 27 kref_init(&ns->kref);
36 return ns; 28 return ns;
37
38err_shm:
39 msg_exit_ns(ns);
40err_msg:
41 sem_exit_ns(ns);
42err_sem:
43 kfree(ns);
44err_mem:
45 return ERR_PTR(err);
46} 29}
47 30
48struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns) 31struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns)
diff --git a/ipc/sem.c b/ipc/sem.c
index 7836edb0cf96..1f7e28d1d25d 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -87,14 +87,12 @@
87#include <asm/uaccess.h> 87#include <asm/uaccess.h>
88#include "util.h" 88#include "util.h"
89 89
90#define sem_ids(ns) (*((ns)->ids[IPC_SEM_IDS])) 90#define sem_ids(ns) ((ns)->ids[IPC_SEM_IDS])
91 91
92#define sem_unlock(sma) ipc_unlock(&(sma)->sem_perm) 92#define sem_unlock(sma) ipc_unlock(&(sma)->sem_perm)
93#define sem_checkid(sma, semid) ipc_checkid(&sma->sem_perm, semid) 93#define sem_checkid(sma, semid) ipc_checkid(&sma->sem_perm, semid)
94#define sem_buildid(id, seq) ipc_buildid(id, seq) 94#define sem_buildid(id, seq) ipc_buildid(id, seq)
95 95
96static struct ipc_ids init_sem_ids;
97
98static int newary(struct ipc_namespace *, struct ipc_params *); 96static int newary(struct ipc_namespace *, struct ipc_params *);
99static void freeary(struct ipc_namespace *, struct sem_array *); 97static void freeary(struct ipc_namespace *, struct sem_array *);
100#ifdef CONFIG_PROC_FS 98#ifdef CONFIG_PROC_FS
@@ -118,30 +116,17 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it);
118#define sc_semopm sem_ctls[2] 116#define sc_semopm sem_ctls[2]
119#define sc_semmni sem_ctls[3] 117#define sc_semmni sem_ctls[3]
120 118
121static void __sem_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids) 119void sem_init_ns(struct ipc_namespace *ns)
122{ 120{
123 ns->ids[IPC_SEM_IDS] = ids;
124 ns->sc_semmsl = SEMMSL; 121 ns->sc_semmsl = SEMMSL;
125 ns->sc_semmns = SEMMNS; 122 ns->sc_semmns = SEMMNS;
126 ns->sc_semopm = SEMOPM; 123 ns->sc_semopm = SEMOPM;
127 ns->sc_semmni = SEMMNI; 124 ns->sc_semmni = SEMMNI;
128 ns->used_sems = 0; 125 ns->used_sems = 0;
129 ipc_init_ids(ids); 126 ipc_init_ids(&ns->ids[IPC_SEM_IDS]);
130} 127}
131 128
132#ifdef CONFIG_IPC_NS 129#ifdef CONFIG_IPC_NS
133int sem_init_ns(struct ipc_namespace *ns)
134{
135 struct ipc_ids *ids;
136
137 ids = kmalloc(sizeof(struct ipc_ids), GFP_KERNEL);
138 if (ids == NULL)
139 return -ENOMEM;
140
141 __sem_init_ns(ns, ids);
142 return 0;
143}
144
145void sem_exit_ns(struct ipc_namespace *ns) 130void sem_exit_ns(struct ipc_namespace *ns)
146{ 131{
147 struct sem_array *sma; 132 struct sem_array *sma;
@@ -163,15 +148,12 @@ void sem_exit_ns(struct ipc_namespace *ns)
163 total++; 148 total++;
164 } 149 }
165 up_write(&sem_ids(ns).rw_mutex); 150 up_write(&sem_ids(ns).rw_mutex);
166
167 kfree(ns->ids[IPC_SEM_IDS]);
168 ns->ids[IPC_SEM_IDS] = NULL;
169} 151}
170#endif 152#endif
171 153
172void __init sem_init (void) 154void __init sem_init (void)
173{ 155{
174 __sem_init_ns(&init_ipc_ns, &init_sem_ids); 156 sem_init_ns(&init_ipc_ns);
175 ipc_init_proc_interface("sysvipc/sem", 157 ipc_init_proc_interface("sysvipc/sem",
176 " key semid perms nsems uid gid cuid cgid otime ctime\n", 158 " key semid perms nsems uid gid cuid cgid otime ctime\n",
177 IPC_SEM_IDS, sysvipc_sem_proc_show); 159 IPC_SEM_IDS, sysvipc_sem_proc_show);
diff --git a/ipc/shm.c b/ipc/shm.c
index 07f4b7abc80a..fe92471e19c7 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -56,9 +56,7 @@ struct shm_file_data {
56static const struct file_operations shm_file_operations; 56static const struct file_operations shm_file_operations;
57static struct vm_operations_struct shm_vm_ops; 57static struct vm_operations_struct shm_vm_ops;
58 58
59static struct ipc_ids init_shm_ids; 59#define shm_ids(ns) ((ns)->ids[IPC_SHM_IDS])
60
61#define shm_ids(ns) (*((ns)->ids[IPC_SHM_IDS]))
62 60
63#define shm_unlock(shp) \ 61#define shm_unlock(shp) \
64 ipc_unlock(&(shp)->shm_perm) 62 ipc_unlock(&(shp)->shm_perm)
@@ -72,14 +70,13 @@ static void shm_destroy (struct ipc_namespace *ns, struct shmid_kernel *shp);
72static int sysvipc_shm_proc_show(struct seq_file *s, void *it); 70static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
73#endif 71#endif
74 72
75static void __shm_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids) 73void shm_init_ns(struct ipc_namespace *ns)
76{ 74{
77 ns->ids[IPC_SHM_IDS] = ids;
78 ns->shm_ctlmax = SHMMAX; 75 ns->shm_ctlmax = SHMMAX;
79 ns->shm_ctlall = SHMALL; 76 ns->shm_ctlall = SHMALL;
80 ns->shm_ctlmni = SHMMNI; 77 ns->shm_ctlmni = SHMMNI;
81 ns->shm_tot = 0; 78 ns->shm_tot = 0;
82 ipc_init_ids(ids); 79 ipc_init_ids(&ns->ids[IPC_SHM_IDS]);
83} 80}
84 81
85/* 82/*
@@ -98,18 +95,6 @@ static void do_shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *shp)
98} 95}
99 96
100#ifdef CONFIG_IPC_NS 97#ifdef CONFIG_IPC_NS
101int shm_init_ns(struct ipc_namespace *ns)
102{
103 struct ipc_ids *ids;
104
105 ids = kmalloc(sizeof(struct ipc_ids), GFP_KERNEL);
106 if (ids == NULL)
107 return -ENOMEM;
108
109 __shm_init_ns(ns, ids);
110 return 0;
111}
112
113void shm_exit_ns(struct ipc_namespace *ns) 98void shm_exit_ns(struct ipc_namespace *ns)
114{ 99{
115 struct shmid_kernel *shp; 100 struct shmid_kernel *shp;
@@ -131,15 +116,12 @@ void shm_exit_ns(struct ipc_namespace *ns)
131 total++; 116 total++;
132 } 117 }
133 up_write(&shm_ids(ns).rw_mutex); 118 up_write(&shm_ids(ns).rw_mutex);
134
135 kfree(ns->ids[IPC_SHM_IDS]);
136 ns->ids[IPC_SHM_IDS] = NULL;
137} 119}
138#endif 120#endif
139 121
140void __init shm_init (void) 122void __init shm_init (void)
141{ 123{
142 __shm_init_ns(&init_ipc_ns, &init_shm_ids); 124 shm_init_ns(&init_ipc_ns);
143 ipc_init_proc_interface("sysvipc/shm", 125 ipc_init_proc_interface("sysvipc/shm",
144 " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime\n", 126 " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime\n",
145 IPC_SHM_IDS, sysvipc_shm_proc_show); 127 IPC_SHM_IDS, sysvipc_shm_proc_show);
diff --git a/ipc/util.c b/ipc/util.c
index 910db7748199..fd1b50da9db8 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -833,7 +833,7 @@ static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)
833 if (ipc && ipc != SEQ_START_TOKEN) 833 if (ipc && ipc != SEQ_START_TOKEN)
834 ipc_unlock(ipc); 834 ipc_unlock(ipc);
835 835
836 return sysvipc_find_ipc(iter->ns->ids[iface->ids], *pos, pos); 836 return sysvipc_find_ipc(&iter->ns->ids[iface->ids], *pos, pos);
837} 837}
838 838
839/* 839/*
@@ -846,7 +846,7 @@ static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
846 struct ipc_proc_iface *iface = iter->iface; 846 struct ipc_proc_iface *iface = iter->iface;
847 struct ipc_ids *ids; 847 struct ipc_ids *ids;
848 848
849 ids = iter->ns->ids[iface->ids]; 849 ids = &iter->ns->ids[iface->ids];
850 850
851 /* 851 /*
852 * Take the lock - this will be released by the corresponding 852 * Take the lock - this will be released by the corresponding
@@ -877,7 +877,7 @@ static void sysvipc_proc_stop(struct seq_file *s, void *it)
877 if (ipc && ipc != SEQ_START_TOKEN) 877 if (ipc && ipc != SEQ_START_TOKEN)
878 ipc_unlock(ipc); 878 ipc_unlock(ipc);
879 879
880 ids = iter->ns->ids[iface->ids]; 880 ids = &iter->ns->ids[iface->ids];
881 /* Release the lock we took in start() */ 881 /* Release the lock we took in start() */
882 up_read(&ids->rw_mutex); 882 up_read(&ids->rw_mutex);
883} 883}
diff --git a/ipc/util.h b/ipc/util.h
index ca245fae2f98..f37d160c98fe 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -10,7 +10,6 @@
10#ifndef _IPC_UTIL_H 10#ifndef _IPC_UTIL_H
11#define _IPC_UTIL_H 11#define _IPC_UTIL_H
12 12
13#include <linux/idr.h>
14#include <linux/err.h> 13#include <linux/err.h>
15 14
16#define USHRT_MAX 0xffff 15#define USHRT_MAX 0xffff
@@ -22,22 +21,14 @@ void shm_init (void);
22 21
23struct ipc_namespace; 22struct ipc_namespace;
24 23
25int sem_init_ns(struct ipc_namespace *ns); 24void sem_init_ns(struct ipc_namespace *ns);
26int msg_init_ns(struct ipc_namespace *ns); 25void msg_init_ns(struct ipc_namespace *ns);
27int shm_init_ns(struct ipc_namespace *ns); 26void shm_init_ns(struct ipc_namespace *ns);
28 27
29void sem_exit_ns(struct ipc_namespace *ns); 28void sem_exit_ns(struct ipc_namespace *ns);
30void msg_exit_ns(struct ipc_namespace *ns); 29void msg_exit_ns(struct ipc_namespace *ns);
31void shm_exit_ns(struct ipc_namespace *ns); 30void shm_exit_ns(struct ipc_namespace *ns);
32 31
33struct ipc_ids {
34 int in_use;
35 unsigned short seq;
36 unsigned short seq_max;
37 struct rw_semaphore rw_mutex;
38 struct idr ipcs_idr;
39};
40
41/* 32/*
42 * Structure that holds the parameters needed by the ipc operations 33 * Structure that holds the parameters needed by the ipc operations
43 * (see after) 34 * (see after)
@@ -68,6 +59,7 @@ struct ipc_ops {
68}; 59};
69 60
70struct seq_file; 61struct seq_file;
62struct ipc_ids;
71 63
72void ipc_init_ids(struct ipc_ids *); 64void ipc_init_ids(struct ipc_ids *);
73#ifdef CONFIG_PROC_FS 65#ifdef CONFIG_PROC_FS