summaryrefslogtreecommitdiffstats
path: root/ipc/shm.c
diff options
context:
space:
mode:
authorManfred Spraul <manfred@colorfullife.com>2017-07-12 17:34:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-12 19:26:01 -0400
commitdba4cdd39e698d8dcdad0656825423052ac90ccd (patch)
tree908f984f4652a42f603aac8f2db4edd059d11256 /ipc/shm.c
parent1a23395672658969a4035dcc518ea6cab835c579 (diff)
ipc: merge ipc_rcu and kern_ipc_perm
ipc has two management structures that exist for every id: - struct kern_ipc_perm, it contains e.g. the permissions. - struct ipc_rcu, it contains the rcu head for rcu handling and the refcount. The patch merges both structures. As a bonus, we may save one cacheline, because both structures are cacheline aligned. In addition, it reduces the number of casts, instead most codepaths can use container_of. To simplify code, the ipc_rcu_alloc initializes the allocation to 0. [manfred@colorfullife.com: really include the memset() into ipc_alloc_rcu()] Link: http://lkml.kernel.org/r/564f8612-0601-b267-514f-a9f650ec9b32@colorfullife.com Link: http://lkml.kernel.org/r/20170525185107.12869-3-manfred@colorfullife.com Signed-off-by: Manfred Spraul <manfred@colorfullife.com> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: Kees Cook <keescook@chromium.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc/shm.c')
-rw-r--r--ipc/shm.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/ipc/shm.c b/ipc/shm.c
index f45c7959b264..5ef6d31a52c5 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -174,9 +174,10 @@ static inline void shm_lock_by_ptr(struct shmid_kernel *ipcp)
174 174
175static void shm_rcu_free(struct rcu_head *head) 175static void shm_rcu_free(struct rcu_head *head)
176{ 176{
177 struct ipc_rcu *p = container_of(head, struct ipc_rcu, rcu); 177 struct kern_ipc_perm *ptr = container_of(head, struct kern_ipc_perm,
178 struct shmid_kernel *shp = ipc_rcu_to_struct(p); 178 rcu);
179 179 struct shmid_kernel *shp = container_of(ptr, struct shmid_kernel,
180 shm_perm);
180 security_shm_free(shp); 181 security_shm_free(shp);
181 ipc_rcu_free(head); 182 ipc_rcu_free(head);
182} 183}
@@ -241,7 +242,7 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
241 user_shm_unlock(i_size_read(file_inode(shm_file)), 242 user_shm_unlock(i_size_read(file_inode(shm_file)),
242 shp->mlock_user); 243 shp->mlock_user);
243 fput(shm_file); 244 fput(shm_file);
244 ipc_rcu_putref(shp, shm_rcu_free); 245 ipc_rcu_putref(&shp->shm_perm, shm_rcu_free);
245} 246}
246 247
247/* 248/*
@@ -542,7 +543,10 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
542 ns->shm_tot + numpages > ns->shm_ctlall) 543 ns->shm_tot + numpages > ns->shm_ctlall)
543 return -ENOSPC; 544 return -ENOSPC;
544 545
545 shp = ipc_rcu_alloc(sizeof(*shp)); 546 BUILD_BUG_ON(offsetof(struct shmid_kernel, shm_perm) != 0);
547
548 shp = container_of(ipc_rcu_alloc(sizeof(*shp)), struct shmid_kernel,
549 shm_perm);
546 if (!shp) 550 if (!shp)
547 return -ENOMEM; 551 return -ENOMEM;
548 552
@@ -553,7 +557,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
553 shp->shm_perm.security = NULL; 557 shp->shm_perm.security = NULL;
554 error = security_shm_alloc(shp); 558 error = security_shm_alloc(shp);
555 if (error) { 559 if (error) {
556 ipc_rcu_putref(shp, ipc_rcu_free); 560 ipc_rcu_putref(&shp->shm_perm, ipc_rcu_free);
557 return error; 561 return error;
558 } 562 }
559 563
@@ -624,7 +628,7 @@ no_id:
624 user_shm_unlock(size, shp->mlock_user); 628 user_shm_unlock(size, shp->mlock_user);
625 fput(file); 629 fput(file);
626no_file: 630no_file:
627 ipc_rcu_putref(shp, shm_rcu_free); 631 ipc_rcu_putref(&shp->shm_perm, shm_rcu_free);
628 return error; 632 return error;
629} 633}
630 634