--- /dev/null
+From 6d07b68ce16ae9535955ba2059dedba5309c3ca1 Mon Sep 17 00:00:00 2001
+From: Manfred Spraul <manfred@colorfullife.com>
+Date: Mon, 30 Sep 2013 13:45:06 -0700
+Subject: ipc/sem.c: optimize sem_lock()
+
+From: Manfred Spraul <manfred@colorfullife.com>
+
+commit 6d07b68ce16ae9535955ba2059dedba5309c3ca1 upstream.
+
+Operations that need access to the whole array must guarantee that there
+are no simple operations ongoing. Right now this is achieved by
+spin_unlock_wait(sem->lock) on all semaphores.
+
+If complex_count is nonzero, then this spin_unlock_wait() is not
+necessary, because it was already performed in the past by the thread
+that increased complex_count and even though sem_perm.lock was dropped
+inbetween, no simple operation could have started, because simple
+operations cannot start when complex_count is non-zero.
+
+Signed-off-by: Manfred Spraul <manfred@colorfullife.com>
+Cc: Mike Galbraith <bitbucket@online.de>
+Cc: Rik van Riel <riel@redhat.com>
+Reviewed-by: Davidlohr Bueso <davidlohr@hp.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/sem.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/ipc/sem.c
++++ b/ipc/sem.c
+@@ -248,12 +248,20 @@ static void merge_queues(struct sem_arra
+ * Caller must own sem_perm.lock.
+ * New simple ops cannot start, because simple ops first check
+ * that sem_perm.lock is free.
++ * that a) sem_perm.lock is free and b) complex_count is 0.
+ */
+ static void sem_wait_array(struct sem_array *sma)
+ {
+ int i;
+ struct sem *sem;
+
++ if (sma->complex_count) {
++ /* The thread that increased sma->complex_count waited on
++ * all sem->lock locks. Thus we don't need to wait again.
++ */
++ return;
++ }
++
+ for (i = 0; i < sma->sem_nsems; i++) {
+ sem = sma->sem_base + i;
+ spin_unlock_wait(&sem->lock);
--- /dev/null
+From d8c633766ad88527f25d9f81a5c2f083d78a2b39 Mon Sep 17 00:00:00 2001
+From: Manfred Spraul <manfred@colorfullife.com>
+Date: Mon, 30 Sep 2013 13:45:07 -0700
+Subject: ipc/sem.c: synchronize the proc interface
+
+From: Manfred Spraul <manfred@colorfullife.com>
+
+commit d8c633766ad88527f25d9f81a5c2f083d78a2b39 upstream.
+
+The proc interface is not aware of sem_lock(), it instead calls
+ipc_lock_object() directly. This means that simple semop() operations
+can run in parallel with the proc interface. Right now, this is
+uncritical, because the implementation doesn't do anything that requires
+a proper synchronization.
+
+But it is dangerous and therefore should be fixed.
+
+Signed-off-by: Manfred Spraul <manfred@colorfullife.com>
+Cc: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Cc: Mike Galbraith <efault@gmx.de>
+Cc: Rik van Riel <riel@redhat.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ ipc/sem.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/ipc/sem.c
++++ b/ipc/sem.c
+@@ -2103,6 +2103,14 @@ static int sysvipc_sem_proc_show(struct
+ struct sem_array *sma = it;
+ time_t sem_otime;
+
++ /*
++ * The proc interface isn't aware of sem_lock(), it calls
++ * ipc_lock_object() directly (in sysvipc_find_ipc).
++ * In order to stay compatible with sem_lock(), we must wait until
++ * all simple semop() calls have left their critical regions.
++ */
++ sem_wait_array(sma);
++
+ sem_otime = get_semotime(sma);
+
+ return seq_printf(s,
--- /dev/null
+From 0e8c665699e953fa58dc1b0b0d09e5dce7343cc7 Mon Sep 17 00:00:00 2001
+From: Manfred Spraul <manfred@colorfullife.com>
+Date: Mon, 30 Sep 2013 13:45:25 -0700
+Subject: ipc/sem.c: update sem_otime for all operations
+
+From: Manfred Spraul <manfred@colorfullife.com>
+
+commit 0e8c665699e953fa58dc1b0b0d09e5dce7343cc7 upstream.
+
+In commit 0a2b9d4c7967 ("ipc/sem.c: move wake_up_process out of the
+spinlock section"), the update of semaphore's sem_otime(last semop time)
+was moved to one central position (do_smart_update).
+
+But since do_smart_update() is only called for operations that modify
+the array, this means that wait-for-zero semops do not update sem_otime
+anymore.
+
+The fix is simple:
+Non-alter operations must update sem_otime.
+
+[akpm@linux-foundation.org: coding-style fixes]
+Signed-off-by: Manfred Spraul <manfred@colorfullife.com>
+Reported-by: Jia He <jiakernel@gmail.com>
+Tested-by: Jia He <jiakernel@gmail.com>
+Cc: Davidlohr Bueso <davidlohr.bueso@hp.com>
+Cc: Mike Galbraith <efault@gmx.de>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ ipc/sem.c | 42 +++++++++++++++++++++++++++++-------------
+ 1 file changed, 29 insertions(+), 13 deletions(-)
+
+--- a/ipc/sem.c
++++ b/ipc/sem.c
+@@ -918,6 +918,24 @@ again:
+ }
+
+ /**
++ * set_semotime(sma, sops) - set sem_otime
++ * @sma: semaphore array
++ * @sops: operations that modified the array, may be NULL
++ *
++ * sem_otime is replicated to avoid cache line trashing.
++ * This function sets one instance to the current time.
++ */
++static void set_semotime(struct sem_array *sma, struct sembuf *sops)
++{
++ if (sops == NULL) {
++ sma->sem_base[0].sem_otime = get_seconds();
++ } else {
++ sma->sem_base[sops[0].sem_num].sem_otime =
++ get_seconds();
++ }
++}
++
++/**
+ * do_smart_update(sma, sops, nsops, otime, pt) - optimized update_queue
+ * @sma: semaphore array
+ * @sops: operations that were performed
+@@ -967,17 +985,10 @@ static void do_smart_update(struct sem_a
+ }
+ }
+ }
+- if (otime) {
+- if (sops == NULL) {
+- sma->sem_base[0].sem_otime = get_seconds();
+- } else {
+- sma->sem_base[sops[0].sem_num].sem_otime =
+- get_seconds();
+- }
+- }
++ if (otime)
++ set_semotime(sma, sops);
+ }
+
+-
+ /* The following counts are associated to each semaphore:
+ * semncnt number of tasks waiting on semval being nonzero
+ * semzcnt number of tasks waiting on semval being zero
+@@ -1839,12 +1850,17 @@ SYSCALL_DEFINE4(semtimedop, int, semid,
+
+ error = perform_atomic_semop(sma, sops, nsops, un,
+ task_tgid_vnr(current));
+- if (error <= 0) {
+- if (alter && error == 0)
++ if (error == 0) {
++ /* If the operation was successful, then do
++ * the required updates.
++ */
++ if (alter)
+ do_smart_update(sma, sops, nsops, 1, &tasks);
+-
+- goto out_unlock_free;
++ else
++ set_semotime(sma, sops);
+ }
++ if (error <= 0)
++ goto out_unlock_free;
+
+ /* We need to sleep on this operation, so we put the current
+ * task into the pending queue and go to sleep.
ipc-drop-ipc_lock_by_ptr.patch
ipc-shm-drop-shm_lock_check.patch
ipc-drop-ipc_lock_check.patch
+ipc-sem.c-optimize-sem_lock.patch
+ipc-sem.c-synchronize-the-proc-interface.patch
+ipc-sem.c-update-sem_otime-for-all-operations.patch