--- /dev/null
+From 3b1c4ad37741e53804ffe0a30dd01e08b2ab6241 Mon Sep 17 00:00:00 2001
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Date: Wed, 11 Sep 2013 14:26:17 -0700
+Subject: ipc: drop ipcctl_pre_down
+
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+
+commit 3b1c4ad37741e53804ffe0a30dd01e08b2ab6241 upstream.
+
+Now that sem, msgque and shm, through *_down(), all use the lockless
+variant of ipcctl_pre_down(), go ahead and delete it.
+
+[akpm@linux-foundation.org: fix function name in kerneldoc, cleanups]
+Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ ipc/util.c | 24 ++++--------------------
+ ipc/util.h | 3 ---
+ 2 files changed, 4 insertions(+), 23 deletions(-)
+
+--- a/ipc/util.c
++++ b/ipc/util.c
+@@ -725,7 +725,7 @@ int ipc_update_perm(struct ipc64_perm *i
+ }
+
+ /**
+- * ipcctl_pre_down - retrieve an ipc and check permissions for some IPC_XXX cmd
++ * ipcctl_pre_down_nolock - retrieve an ipc and check permissions for some IPC_XXX cmd
+ * @ns: the ipc namespace
+ * @ids: the table of ids where to look for the ipc
+ * @id: the id of the ipc to retrieve
+@@ -738,29 +738,13 @@ int ipc_update_perm(struct ipc64_perm *i
+ * It must be called without any lock held and
+ * - retrieves the ipc with the given id in the given table.
+ * - performs some audit and permission check, depending on the given cmd
+- * - returns the ipc with the ipc lock held in case of success
+- * or an err-code without any lock held otherwise.
++ * - returns a pointer to the ipc object or otherwise, the corresponding error.
+ *
+ * Call holding the both the rw_mutex and the rcu read lock.
+ */
+-struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,
+- struct ipc_ids *ids, int id, int cmd,
+- struct ipc64_perm *perm, int extra_perm)
+-{
+- struct kern_ipc_perm *ipcp;
+-
+- ipcp = ipcctl_pre_down_nolock(ns, ids, id, cmd, perm, extra_perm);
+- if (IS_ERR(ipcp))
+- goto out;
+-
+- spin_lock(&ipcp->lock);
+-out:
+- return ipcp;
+-}
+-
+ struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns,
+- struct ipc_ids *ids, int id, int cmd,
+- struct ipc64_perm *perm, int extra_perm)
++ struct ipc_ids *ids, int id, int cmd,
++ struct ipc64_perm *perm, int extra_perm)
+ {
+ kuid_t euid;
+ int err = -EPERM;
+--- a/ipc/util.h
++++ b/ipc/util.h
+@@ -139,9 +139,6 @@ int ipc_update_perm(struct ipc64_perm *i
+ struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns,
+ struct ipc_ids *ids, int id, int cmd,
+ struct ipc64_perm *perm, int extra_perm);
+-struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,
+- struct ipc_ids *ids, int id, int cmd,
+- struct ipc64_perm *perm, int extra_perm);
+
+ #ifndef CONFIG_ARCH_WANT_IPC_PARSE_VERSION
+ /* On IA-64, we always use the "64-bit version" of the IPC structures. */
--- /dev/null
+From f42569b1388b1408b574a5e93a23a663647d4181 Mon Sep 17 00:00:00 2001
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Date: Wed, 11 Sep 2013 14:26:22 -0700
+Subject: ipc,shm: cleanup do_shmat pasta
+
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+
+commit f42569b1388b1408b574a5e93a23a663647d4181 upstream.
+
+Clean up some of the messy do_shmat() spaghetti code, getting rid of
+out_free and out_put_dentry labels. This makes shortening the critical
+region of this function in the next patch a little easier to do and read.
+
+Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ ipc/shm.c | 26 ++++++++++++--------------
+ 1 file changed, 12 insertions(+), 14 deletions(-)
+
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -1115,16 +1115,21 @@ long do_shmat(int shmid, char __user *sh
+
+ err = -ENOMEM;
+ sfd = kzalloc(sizeof(*sfd), GFP_KERNEL);
+- if (!sfd)
+- goto out_put_dentry;
++ if (!sfd) {
++ path_put(&path);
++ goto out_nattch;
++ }
+
+ file = alloc_file(&path, f_mode,
+ is_file_hugepages(shp->shm_file) ?
+ &shm_file_operations_huge :
+ &shm_file_operations);
+ err = PTR_ERR(file);
+- if (IS_ERR(file))
+- goto out_free;
++ if (IS_ERR(file)) {
++ kfree(sfd);
++ path_put(&path);
++ goto out_nattch;
++ }
+
+ file->private_data = sfd;
+ file->f_mapping = shp->shm_file->f_mapping;
+@@ -1150,7 +1155,7 @@ long do_shmat(int shmid, char __user *sh
+ addr > current->mm->start_stack - size - PAGE_SIZE * 5)
+ goto invalid;
+ }
+-
++
+ addr = do_mmap_pgoff(file, addr, size, prot, flags, 0, &populate);
+ *raddr = addr;
+ err = 0;
+@@ -1174,19 +1179,12 @@ out_nattch:
+ else
+ shm_unlock(shp);
+ up_write(&shm_ids(ns).rw_mutex);
+-
+-out:
+ return err;
+
+ out_unlock:
+ shm_unlock(shp);
+- goto out;
+-
+-out_free:
+- kfree(sfd);
+-out_put_dentry:
+- path_put(&path);
+- goto out_nattch;
++out:
++ return err;
+ }
+
+ SYSCALL_DEFINE3(shmat, int, shmid, char __user *, shmaddr, int, shmflg)
--- /dev/null
+From 8b8d52ac382b17a19906b930cd69e2edb0aca8ba Mon Sep 17 00:00:00 2001
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Date: Wed, 11 Sep 2013 14:26:15 -0700
+Subject: ipc,shm: introduce lockless functions to obtain the ipc object
+
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+
+commit 8b8d52ac382b17a19906b930cd69e2edb0aca8ba upstream.
+
+This is the third and final patchset that deals with reducing the amount
+of contention we impose on the ipc lock (kern_ipc_perm.lock). These
+changes mostly deal with shared memory, previous work has already been
+done for semaphores and message queues:
+
+ http://lkml.org/lkml/2013/3/20/546 (sems)
+ http://lkml.org/lkml/2013/5/15/584 (mqueues)
+
+With these patches applied, a custom shm microbenchmark stressing shmctl
+doing IPC_STAT with 4 threads a million times, reduces the execution
+time by 50%. A similar run, this time with IPC_SET, reduces the
+execution time from 3 mins and 35 secs to 27 seconds.
+
+Patches 1-8: replaces blindly taking the ipc lock for a smarter
+combination of rcu and ipc_obtain_object, only acquiring the spinlock
+when updating.
+
+Patch 9: renames the ids rw_mutex to rwsem, which is what it already was.
+
+Patch 10: is a trivial mqueue leftover cleanup
+
+Patch 11: adds a brief lock scheme description, requested by Andrew.
+
+This patch:
+
+Add shm_obtain_object() and shm_obtain_object_check(), which will allow us
+to get the ipc object without acquiring the lock. Just as with other
+forms of ipc, these functions are basically wrappers around
+ipc_obtain_object*().
+
+Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ ipc/shm.c | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -124,6 +124,26 @@ void __init shm_init (void)
+ IPC_SHM_IDS, sysvipc_shm_proc_show);
+ }
+
++static inline struct shmid_kernel *shm_obtain_object(struct ipc_namespace *ns, int id)
++{
++ struct kern_ipc_perm *ipcp = ipc_obtain_object(&shm_ids(ns), id);
++
++ if (IS_ERR(ipcp))
++ return ERR_CAST(ipcp);
++
++ return container_of(ipcp, struct shmid_kernel, shm_perm);
++}
++
++static inline struct shmid_kernel *shm_obtain_object_check(struct ipc_namespace *ns, int id)
++{
++ struct kern_ipc_perm *ipcp = ipc_obtain_object_check(&shm_ids(ns), id);
++
++ if (IS_ERR(ipcp))
++ return ERR_CAST(ipcp);
++
++ return container_of(ipcp, struct shmid_kernel, shm_perm);
++}
++
+ /*
+ * shm_lock_(check_) routines are called in the paths where the rw_mutex
+ * is not necessarily held.
--- /dev/null
+From 68eccc1dc345539d589ae78ee43b835c1a06a134 Mon Sep 17 00:00:00 2001
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Date: Wed, 11 Sep 2013 14:26:18 -0700
+Subject: ipc,shm: introduce shmctl_nolock
+
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+
+commit 68eccc1dc345539d589ae78ee43b835c1a06a134 upstream.
+
+Similar to semctl and msgctl, when calling msgctl, the *_INFO and *_STAT
+commands can be performed without acquiring the ipc object.
+
+Add a shmctl_nolock() function and move the logic of *_INFO and *_STAT out
+of msgctl(). Since we are just moving functionality, this change still
+takes the lock and it will be properly lockless in the next patch.
+
+Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ ipc/shm.c | 57 +++++++++++++++++++++++++++++++++++++++------------------
+ 1 file changed, 39 insertions(+), 18 deletions(-)
+
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -827,29 +827,24 @@ out_up:
+ return err;
+ }
+
+-SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
++static int shmctl_nolock(struct ipc_namespace *ns, int shmid,
++ int cmd, int version, void __user *buf)
+ {
++ int err;
+ struct shmid_kernel *shp;
+- int err, version;
+- struct ipc_namespace *ns;
+
+- if (cmd < 0 || shmid < 0) {
+- err = -EINVAL;
+- goto out;
++ /* preliminary security checks for *_INFO */
++ if (cmd == IPC_INFO || cmd == SHM_INFO) {
++ err = security_shm_shmctl(NULL, cmd);
++ if (err)
++ return err;
+ }
+
+- version = ipc_parse_version(&cmd);
+- ns = current->nsproxy->ipc_ns;
+-
+- switch (cmd) { /* replace with proc interface ? */
++ switch (cmd) {
+ case IPC_INFO:
+ {
+ struct shminfo64 shminfo;
+
+- err = security_shm_shmctl(NULL, cmd);
+- if (err)
+- return err;
+-
+ memset(&shminfo, 0, sizeof(shminfo));
+ shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni;
+ shminfo.shmmax = ns->shm_ctlmax;
+@@ -871,10 +866,6 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int,
+ {
+ struct shm_info shm_info;
+
+- err = security_shm_shmctl(NULL, cmd);
+- if (err)
+- return err;
+-
+ memset(&shm_info, 0, sizeof(shm_info));
+ down_read(&shm_ids(ns).rw_mutex);
+ shm_info.used_ids = shm_ids(ns).in_use;
+@@ -935,6 +926,36 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int,
+ err = result;
+ goto out;
+ }
++ default:
++ return -EINVAL;
++ }
++
++out_unlock:
++ shm_unlock(shp);
++out:
++ return err;
++}
++
++SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
++{
++ struct shmid_kernel *shp;
++ int err, version;
++ struct ipc_namespace *ns;
++
++ if (cmd < 0 || shmid < 0) {
++ err = -EINVAL;
++ goto out;
++ }
++
++ version = ipc_parse_version(&cmd);
++ ns = current->nsproxy->ipc_ns;
++
++ switch (cmd) {
++ case IPC_INFO:
++ case SHM_INFO:
++ case SHM_STAT:
++ case IPC_STAT:
++ return shmctl_nolock(ns, shmid, cmd, version, buf);
+ case SHM_LOCK:
+ case SHM_UNLOCK:
+ {
--- /dev/null
+From c97cb9ccab8c85428ec21eff690642ad2ce1fa8a Mon Sep 17 00:00:00 2001
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Date: Wed, 11 Sep 2013 14:26:20 -0700
+Subject: ipc,shm: make shmctl_nolock lockless
+
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+
+commit c97cb9ccab8c85428ec21eff690642ad2ce1fa8a upstream.
+
+While the INFO cmd doesn't take the ipc lock, the STAT commands do acquire
+it unnecessarily. We can do the permissions and security checks only
+holding the rcu lock.
+
+[akpm@linux-foundation.org: coding-style fixes]
+Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ ipc/shm.c | 19 ++++++++++++-------
+ 1 file changed, 12 insertions(+), 7 deletions(-)
+
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -889,27 +889,31 @@ static int shmctl_nolock(struct ipc_name
+ struct shmid64_ds tbuf;
+ int result;
+
++ rcu_read_lock();
+ if (cmd == SHM_STAT) {
+- shp = shm_lock(ns, shmid);
++ shp = shm_obtain_object(ns, shmid);
+ if (IS_ERR(shp)) {
+ err = PTR_ERR(shp);
+- goto out;
++ goto out_unlock;
+ }
+ result = shp->shm_perm.id;
+ } else {
+- shp = shm_lock_check(ns, shmid);
++ shp = shm_obtain_object_check(ns, shmid);
+ if (IS_ERR(shp)) {
+ err = PTR_ERR(shp);
+- goto out;
++ goto out_unlock;
+ }
+ result = 0;
+ }
++
+ err = -EACCES;
+ if (ipcperms(ns, &shp->shm_perm, S_IRUGO))
+ goto out_unlock;
++
+ err = security_shm_shmctl(shp, cmd);
+ if (err)
+ goto out_unlock;
++
+ memset(&tbuf, 0, sizeof(tbuf));
+ kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm);
+ tbuf.shm_segsz = shp->shm_segsz;
+@@ -919,8 +923,9 @@ static int shmctl_nolock(struct ipc_name
+ tbuf.shm_cpid = shp->shm_cprid;
+ tbuf.shm_lpid = shp->shm_lprid;
+ tbuf.shm_nattch = shp->shm_nattch;
+- shm_unlock(shp);
+- if(copy_shmid_to_user (buf, &tbuf, version))
++ rcu_read_unlock();
++
++ if (copy_shmid_to_user(buf, &tbuf, version))
+ err = -EFAULT;
+ else
+ err = result;
+@@ -931,7 +936,7 @@ static int shmctl_nolock(struct ipc_name
+ }
+
+ out_unlock:
+- shm_unlock(shp);
++ rcu_read_unlock();
+ out:
+ return err;
+ }
--- /dev/null
+From c2c737a0461e61a34676bd0bd1bc1a70a1b4e396 Mon Sep 17 00:00:00 2001
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Date: Wed, 11 Sep 2013 14:26:23 -0700
+Subject: ipc,shm: shorten critical region for shmat
+
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+
+commit c2c737a0461e61a34676bd0bd1bc1a70a1b4e396 upstream.
+
+Similar to other system calls, acquire the kern_ipc_perm lock after doing
+the initial permission and security checks.
+
+[sasha.levin@oracle.com: dont leave do_shmat with rcu lock held]
+Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ ipc/shm.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -19,6 +19,9 @@
+ * namespaces support
+ * OpenVZ, SWsoft Inc.
+ * Pavel Emelianov <xemul@openvz.org>
++ *
++ * Better ipc lock (kern_ipc_perm.lock) handling
++ * Davidlohr Bueso <davidlohr.bueso@hp.com>, June 2013.
+ */
+
+ #include <linux/slab.h>
+@@ -1093,10 +1096,11 @@ long do_shmat(int shmid, char __user *sh
+ * additional creator id...
+ */
+ ns = current->nsproxy->ipc_ns;
+- shp = shm_lock_check(ns, shmid);
++ rcu_read_lock();
++ shp = shm_obtain_object_check(ns, shmid);
+ if (IS_ERR(shp)) {
+ err = PTR_ERR(shp);
+- goto out;
++ goto out_unlock;
+ }
+
+ err = -EACCES;
+@@ -1107,11 +1111,13 @@ long do_shmat(int shmid, char __user *sh
+ if (err)
+ goto out_unlock;
+
++ ipc_lock_object(&shp->shm_perm);
+ path = shp->shm_file->f_path;
+ path_get(&path);
+ shp->shm_nattch++;
+ size = i_size_read(path.dentry->d_inode);
+- shm_unlock(shp);
++ ipc_unlock_object(&shp->shm_perm);
++ rcu_read_unlock();
+
+ err = -ENOMEM;
+ sfd = kzalloc(sizeof(*sfd), GFP_KERNEL);
+@@ -1182,7 +1188,7 @@ out_nattch:
+ return err;
+
+ out_unlock:
+- shm_unlock(shp);
++ rcu_read_unlock();
+ out:
+ return err;
+ }
--- /dev/null
+From 2caacaa82a51b78fc0c800e206473874094287ed Mon Sep 17 00:00:00 2001
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Date: Wed, 11 Sep 2013 14:26:21 -0700
+Subject: ipc,shm: shorten critical region for shmctl
+
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+
+commit 2caacaa82a51b78fc0c800e206473874094287ed upstream.
+
+With the *_INFO, *_STAT, IPC_RMID and IPC_SET commands already optimized,
+deal with the remaining SHM_LOCK and SHM_UNLOCK commands. Take the
+shm_perm lock after doing the initial auditing and security checks. The
+rest of the logic remains unchanged.
+
+Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ ipc/shm.c | 49 +++++++++++++++++++++++++------------------------
+ 1 file changed, 25 insertions(+), 24 deletions(-)
+
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -947,10 +947,8 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int,
+ int err, version;
+ struct ipc_namespace *ns;
+
+- if (cmd < 0 || shmid < 0) {
+- err = -EINVAL;
+- goto out;
+- }
++ if (cmd < 0 || shmid < 0)
++ return -EINVAL;
+
+ version = ipc_parse_version(&cmd);
+ ns = current->nsproxy->ipc_ns;
+@@ -961,36 +959,40 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int,
+ case SHM_STAT:
+ case IPC_STAT:
+ return shmctl_nolock(ns, shmid, cmd, version, buf);
++ case IPC_RMID:
++ case IPC_SET:
++ return shmctl_down(ns, shmid, cmd, buf, version);
+ case SHM_LOCK:
+ case SHM_UNLOCK:
+ {
+ struct file *shm_file;
+
+- shp = shm_lock_check(ns, shmid);
++ rcu_read_lock();
++ shp = shm_obtain_object_check(ns, shmid);
+ if (IS_ERR(shp)) {
+ err = PTR_ERR(shp);
+- goto out;
++ goto out_unlock1;
+ }
+
+ audit_ipc_obj(&(shp->shm_perm));
++ err = security_shm_shmctl(shp, cmd);
++ if (err)
++ goto out_unlock1;
+
++ ipc_lock_object(&shp->shm_perm);
+ if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) {
+ kuid_t euid = current_euid();
+ err = -EPERM;
+ if (!uid_eq(euid, shp->shm_perm.uid) &&
+ !uid_eq(euid, shp->shm_perm.cuid))
+- goto out_unlock;
++ goto out_unlock0;
+ if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK))
+- goto out_unlock;
++ goto out_unlock0;
+ }
+
+- err = security_shm_shmctl(shp, cmd);
+- if (err)
+- goto out_unlock;
+-
+ shm_file = shp->shm_file;
+ if (is_file_hugepages(shm_file))
+- goto out_unlock;
++ goto out_unlock0;
+
+ if (cmd == SHM_LOCK) {
+ struct user_struct *user = current_user();
+@@ -999,32 +1001,31 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int,
+ shp->shm_perm.mode |= SHM_LOCKED;
+ shp->mlock_user = user;
+ }
+- goto out_unlock;
++ goto out_unlock0;
+ }
+
+ /* SHM_UNLOCK */
+ if (!(shp->shm_perm.mode & SHM_LOCKED))
+- goto out_unlock;
++ goto out_unlock0;
+ shmem_lock(shm_file, 0, shp->mlock_user);
+ shp->shm_perm.mode &= ~SHM_LOCKED;
+ shp->mlock_user = NULL;
+ get_file(shm_file);
+- shm_unlock(shp);
++ ipc_unlock_object(&shp->shm_perm);
++ rcu_read_unlock();
+ shmem_unlock_mapping(shm_file->f_mapping);
++
+ fput(shm_file);
+- goto out;
+- }
+- case IPC_RMID:
+- case IPC_SET:
+- err = shmctl_down(ns, shmid, cmd, buf, version);
+ return err;
++ }
+ default:
+ return -EINVAL;
+ }
+
+-out_unlock:
+- shm_unlock(shp);
+-out:
++out_unlock0:
++ ipc_unlock_object(&shp->shm_perm);
++out_unlock1:
++ rcu_read_unlock();
+ return err;
+ }
+
--- /dev/null
+From 79ccf0f8c8e04e8b9eda6645ba0f63b0915a3075 Mon Sep 17 00:00:00 2001
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Date: Wed, 11 Sep 2013 14:26:16 -0700
+Subject: ipc,shm: shorten critical region in shmctl_down
+
+From: Davidlohr Bueso <davidlohr.bueso@hp.com>
+
+commit 79ccf0f8c8e04e8b9eda6645ba0f63b0915a3075 upstream.
+
+Instead of holding the ipc lock for the entire function, use the
+ipcctl_pre_down_nolock and only acquire the lock for specific commands:
+RMID and SET.
+
+Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ ipc/shm.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -787,11 +787,10 @@ static int shmctl_down(struct ipc_namesp
+ down_write(&shm_ids(ns).rw_mutex);
+ rcu_read_lock();
+
+- ipcp = ipcctl_pre_down(ns, &shm_ids(ns), shmid, cmd,
+- &shmid64.shm_perm, 0);
++ ipcp = ipcctl_pre_down_nolock(ns, &shm_ids(ns), shmid, cmd,
++ &shmid64.shm_perm, 0);
+ if (IS_ERR(ipcp)) {
+ err = PTR_ERR(ipcp);
+- /* the ipc lock is not held upon failure */
+ goto out_unlock1;
+ }
+
+@@ -799,14 +798,16 @@ static int shmctl_down(struct ipc_namesp
+
+ err = security_shm_shmctl(shp, cmd);
+ if (err)
+- goto out_unlock0;
++ goto out_unlock1;
+
+ switch (cmd) {
+ case IPC_RMID:
++ ipc_lock_object(&shp->shm_perm);
+ /* do_shm_rmid unlocks the ipc object and rcu */
+ do_shm_rmid(ns, ipcp);
+ goto out_up;
+ case IPC_SET:
++ ipc_lock_object(&shp->shm_perm);
+ err = ipc_update_perm(&shmid64.shm_perm, ipcp);
+ if (err)
+ goto out_unlock0;
+@@ -814,6 +815,7 @@ static int shmctl_down(struct ipc_namesp
+ break;
+ default:
+ err = -EINVAL;
++ goto out_unlock1;
+ }
+
+ out_unlock0:
drm-radeon-forever-loop-on-error-in-radeon_do_test_moves.patch
drm-radeon-fix-typo-in-cp-dma-register-headers.patch
drm-radeon-fix-hw-contexts-for-sumo2-asics.patch
+ipc-shm-introduce-lockless-functions-to-obtain-the-ipc-object.patch
+ipc-shm-shorten-critical-region-in-shmctl_down.patch
+ipc-drop-ipcctl_pre_down.patch
+ipc-shm-introduce-shmctl_nolock.patch
+ipc-shm-make-shmctl_nolock-lockless.patch
+ipc-shm-shorten-critical-region-for-shmctl.patch
+ipc-shm-cleanup-do_shmat-pasta.patch
+ipc-shm-shorten-critical-region-for-shmat.patch