diff options
author | Pierre Peiffer <pierre.peiffer@bull.net> | 2008-02-08 07:18:57 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-08 12:22:26 -0500 |
commit | ed2ddbf88c0ddeeae4c78bb306a116dfd867c55c (patch) | |
tree | de6d6828c03f98be6fc41e8acf3b3e52df28be9b | |
parent | 4b9fcb0ec60584d639ad105c42b75a3447071e47 (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.h | 13 | ||||
-rw-r--r-- | ipc/msg.c | 26 | ||||
-rw-r--r-- | ipc/namespace.c | 25 | ||||
-rw-r--r-- | ipc/sem.c | 26 | ||||
-rw-r--r-- | ipc/shm.c | 26 | ||||
-rw-r--r-- | ipc/util.c | 6 | ||||
-rw-r--r-- | ipc/util.h | 16 |
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 | |||
8 | struct 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 | ||
6 | struct ipc_ids; | ||
7 | struct ipc_namespace { | 16 | struct 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; |
@@ -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 | ||
70 | static 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 *); | |||
80 | static int sysvipc_msg_proc_show(struct seq_file *s, void *it); | 78 | static int sysvipc_msg_proc_show(struct seq_file *s, void *it); |
81 | #endif | 79 | #endif |
82 | 80 | ||
83 | static void __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids) | 81 | void 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 |
95 | int 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 | |||
107 | void msg_exit_ns(struct ipc_namespace *ns) | 92 | void 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 | ||
135 | void __init msg_init(void) | 117 | void __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 | ||
15 | static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns) | 15 | static 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 | |||
38 | err_shm: | ||
39 | msg_exit_ns(ns); | ||
40 | err_msg: | ||
41 | sem_exit_ns(ns); | ||
42 | err_sem: | ||
43 | kfree(ns); | ||
44 | err_mem: | ||
45 | return ERR_PTR(err); | ||
46 | } | 29 | } |
47 | 30 | ||
48 | struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns) | 31 | struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns) |
@@ -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 | ||
96 | static struct ipc_ids init_sem_ids; | ||
97 | |||
98 | static int newary(struct ipc_namespace *, struct ipc_params *); | 96 | static int newary(struct ipc_namespace *, struct ipc_params *); |
99 | static void freeary(struct ipc_namespace *, struct sem_array *); | 97 | static 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 | ||
121 | static void __sem_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids) | 119 | void 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 |
133 | int 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 | |||
145 | void sem_exit_ns(struct ipc_namespace *ns) | 130 | void 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 | ||
172 | void __init sem_init (void) | 154 | void __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); |
@@ -56,9 +56,7 @@ struct shm_file_data { | |||
56 | static const struct file_operations shm_file_operations; | 56 | static const struct file_operations shm_file_operations; |
57 | static struct vm_operations_struct shm_vm_ops; | 57 | static struct vm_operations_struct shm_vm_ops; |
58 | 58 | ||
59 | static 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); | |||
72 | static int sysvipc_shm_proc_show(struct seq_file *s, void *it); | 70 | static int sysvipc_shm_proc_show(struct seq_file *s, void *it); |
73 | #endif | 71 | #endif |
74 | 72 | ||
75 | static void __shm_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids) | 73 | void 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 |
101 | int 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 | |||
113 | void shm_exit_ns(struct ipc_namespace *ns) | 98 | void 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 | ||
140 | void __init shm_init (void) | 122 | void __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 | ||
23 | struct ipc_namespace; | 22 | struct ipc_namespace; |
24 | 23 | ||
25 | int sem_init_ns(struct ipc_namespace *ns); | 24 | void sem_init_ns(struct ipc_namespace *ns); |
26 | int msg_init_ns(struct ipc_namespace *ns); | 25 | void msg_init_ns(struct ipc_namespace *ns); |
27 | int shm_init_ns(struct ipc_namespace *ns); | 26 | void shm_init_ns(struct ipc_namespace *ns); |
28 | 27 | ||
29 | void sem_exit_ns(struct ipc_namespace *ns); | 28 | void sem_exit_ns(struct ipc_namespace *ns); |
30 | void msg_exit_ns(struct ipc_namespace *ns); | 29 | void msg_exit_ns(struct ipc_namespace *ns); |
31 | void shm_exit_ns(struct ipc_namespace *ns); | 30 | void shm_exit_ns(struct ipc_namespace *ns); |
32 | 31 | ||
33 | struct 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 | ||
70 | struct seq_file; | 61 | struct seq_file; |
62 | struct ipc_ids; | ||
71 | 63 | ||
72 | void ipc_init_ids(struct ipc_ids *); | 64 | void ipc_init_ids(struct ipc_ids *); |
73 | #ifdef CONFIG_PROC_FS | 65 | #ifdef CONFIG_PROC_FS |