aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
authorDavidlohr Bueso <dave@stgolabs.net>2017-11-17 18:31:08 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-11-17 19:10:04 -0500
commitb8fd99838435f9b420c3e848192bd43abc648b7f (patch)
tree793a6390f29e27fcd9b87ba8b65c2480627491af /ipc
parente35c4c64fe492b212f9c7d9e046626e48e89f863 (diff)
sysvipc: unteach ids->next_id for !CHECKPOINT_RESTORE
Patch series "sysvipc: ipc-key management improvements". Here are a few improvements I spotted while eyeballing Guillaume's rhashtable implementation for ipc keys. The first and fourth patches are the interesting ones, the middle two are trivial. This patch (of 4): The next_id object-allocation functionality was introduced in commit 03f595668017 ("ipc: add sysctl to specify desired next object id"). Given that these new entries are _only_ exported under the CONFIG_CHECKPOINT_RESTORE option, there is no point for the common case to even know about ->next_id. As such rewrite ipc_buildid() such that it can do away with the field as well as unnecessary branches when adding a new identifier. The end result also better differentiates both cases, so the code ends up being cleaner; albeit the small duplications regarding the default case. [akpm@linux-foundation.org: coding-style fixes] Link: http://lkml.kernel.org/r/20170831172049.14576-2-dave@stgolabs.net Signed-off-by: Davidlohr Bueso <dbueso@suse.de> Cc: Manfred Spraul <manfred@colorfullife.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc')
-rw-r--r--ipc/util.c60
-rw-r--r--ipc/util.h5
2 files changed, 45 insertions, 20 deletions
diff --git a/ipc/util.c b/ipc/util.c
index 79b30eee32cd..429c06bdb8ef 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -116,13 +116,15 @@ int ipc_init_ids(struct ipc_ids *ids)
116 int err; 116 int err;
117 ids->in_use = 0; 117 ids->in_use = 0;
118 ids->seq = 0; 118 ids->seq = 0;
119 ids->next_id = -1;
120 init_rwsem(&ids->rwsem); 119 init_rwsem(&ids->rwsem);
121 err = rhashtable_init(&ids->key_ht, &ipc_kht_params); 120 err = rhashtable_init(&ids->key_ht, &ipc_kht_params);
122 if (err) 121 if (err)
123 return err; 122 return err;
124 idr_init(&ids->ipcs_idr); 123 idr_init(&ids->ipcs_idr);
125 ids->tables_initialized = true; 124 ids->tables_initialized = true;
125#ifdef CONFIG_CHECKPOINT_RESTORE
126 ids->next_id = -1;
127#endif
126 return 0; 128 return 0;
127} 129}
128 130
@@ -216,6 +218,46 @@ int ipc_get_maxid(struct ipc_ids *ids)
216 return max_id; 218 return max_id;
217} 219}
218 220
221#ifdef CONFIG_CHECKPOINT_RESTORE
222/*
223 * Specify desired id for next allocated IPC object.
224 */
225#define ipc_idr_alloc(ids, new) \
226 idr_alloc(&(ids)->ipcs_idr, (new), \
227 (ids)->next_id < 0 ? 0 : ipcid_to_idx((ids)->next_id),\
228 0, GFP_NOWAIT)
229
230static inline int ipc_buildid(int id, struct ipc_ids *ids,
231 struct kern_ipc_perm *new)
232{
233 if (ids->next_id < 0) { /* default, behave as !CHECKPOINT_RESTORE */
234 new->seq = ids->seq++;
235 if (ids->seq > IPCID_SEQ_MAX)
236 ids->seq = 0;
237 } else {
238 new->seq = ipcid_to_seqx(ids->next_id);
239 ids->next_id = -1;
240 }
241
242 return SEQ_MULTIPLIER * new->seq + id;
243}
244
245#else
246#define ipc_idr_alloc(ids, new) \
247 idr_alloc(&(ids)->ipcs_idr, (new), 0, 0, GFP_NOWAIT)
248
249static inline int ipc_buildid(int id, struct ipc_ids *ids,
250 struct kern_ipc_perm *new)
251{
252 new->seq = ids->seq++;
253 if (ids->seq > IPCID_SEQ_MAX)
254 ids->seq = 0;
255
256 return SEQ_MULTIPLIER * new->seq + id;
257}
258
259#endif /* CONFIG_CHECKPOINT_RESTORE */
260
219/** 261/**
220 * ipc_addid - add an ipc identifier 262 * ipc_addid - add an ipc identifier
221 * @ids: ipc identifier set 263 * @ids: ipc identifier set
@@ -234,7 +276,6 @@ int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int size)
234 kuid_t euid; 276 kuid_t euid;
235 kgid_t egid; 277 kgid_t egid;
236 int id, err; 278 int id, err;
237 int next_id = ids->next_id;
238 279
239 if (size > IPCMNI) 280 if (size > IPCMNI)
240 size = IPCMNI; 281 size = IPCMNI;
@@ -254,9 +295,7 @@ int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int size)
254 new->cuid = new->uid = euid; 295 new->cuid = new->uid = euid;
255 new->gid = new->cgid = egid; 296 new->gid = new->cgid = egid;
256 297
257 id = idr_alloc(&ids->ipcs_idr, new, 298 id = ipc_idr_alloc(ids, new);
258 (next_id < 0) ? 0 : ipcid_to_idx(next_id), 0,
259 GFP_NOWAIT);
260 idr_preload_end(); 299 idr_preload_end();
261 300
262 if (id >= 0 && new->key != IPC_PRIVATE) { 301 if (id >= 0 && new->key != IPC_PRIVATE) {
@@ -274,17 +313,8 @@ int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int size)
274 } 313 }
275 314
276 ids->in_use++; 315 ids->in_use++;
316 new->id = ipc_buildid(id, ids, new);
277 317
278 if (next_id < 0) {
279 new->seq = ids->seq++;
280 if (ids->seq > IPCID_SEQ_MAX)
281 ids->seq = 0;
282 } else {
283 new->seq = ipcid_to_seqx(next_id);
284 ids->next_id = -1;
285 }
286
287 new->id = ipc_buildid(id, new->seq);
288 return id; 318 return id;
289} 319}
290 320
diff --git a/ipc/util.h b/ipc/util.h
index 579112d90016..0cd6201fe63a 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -146,11 +146,6 @@ extern struct msg_msg *load_msg(const void __user *src, size_t len);
146extern struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst); 146extern struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst);
147extern int store_msg(void __user *dest, struct msg_msg *msg, size_t len); 147extern int store_msg(void __user *dest, struct msg_msg *msg, size_t len);
148 148
149static inline int ipc_buildid(int id, int seq)
150{
151 return SEQ_MULTIPLIER * seq + id;
152}
153
154static inline int ipc_checkid(struct kern_ipc_perm *ipcp, int uid) 149static inline int ipc_checkid(struct kern_ipc_perm *ipcp, int uid)
155{ 150{
156 return uid / SEQ_MULTIPLIER != ipcp->seq; 151 return uid / SEQ_MULTIPLIER != ipcp->seq;