From: Greg Kroah-Hartman Date: Wed, 16 Oct 2013 00:10:41 +0000 (-0700) Subject: 3.11-stable patches X-Git-Tag: v3.10.17~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=23b10630503940f12cb4f5bcddfd1813dcda20c3;p=thirdparty%2Fkernel%2Fstable-queue.git 3.11-stable patches added patches: 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 --- diff --git a/queue-3.11/ipc-sem.c-optimize-sem_lock.patch b/queue-3.11/ipc-sem.c-optimize-sem_lock.patch new file mode 100644 index 00000000000..91422f8441d --- /dev/null +++ b/queue-3.11/ipc-sem.c-optimize-sem_lock.patch @@ -0,0 +1,55 @@ +From 6d07b68ce16ae9535955ba2059dedba5309c3ca1 Mon Sep 17 00:00:00 2001 +From: Manfred Spraul +Date: Mon, 30 Sep 2013 13:45:06 -0700 +Subject: ipc/sem.c: optimize sem_lock() + +From: Manfred Spraul + +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 +Cc: Mike Galbraith +Cc: Rik van Riel +Reviewed-by: Davidlohr Bueso +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Cc: Mike Galbraith +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-3.11/ipc-sem.c-synchronize-the-proc-interface.patch b/queue-3.11/ipc-sem.c-synchronize-the-proc-interface.patch new file mode 100644 index 00000000000..1ca7d808cbd --- /dev/null +++ b/queue-3.11/ipc-sem.c-synchronize-the-proc-interface.patch @@ -0,0 +1,46 @@ +From d8c633766ad88527f25d9f81a5c2f083d78a2b39 Mon Sep 17 00:00:00 2001 +From: Manfred Spraul +Date: Mon, 30 Sep 2013 13:45:07 -0700 +Subject: ipc/sem.c: synchronize the proc interface + +From: Manfred Spraul + +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 +Cc: Davidlohr Bueso +Cc: Mike Galbraith +Cc: Rik van Riel +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + 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, diff --git a/queue-3.11/ipc-sem.c-update-sem_otime-for-all-operations.patch b/queue-3.11/ipc-sem.c-update-sem_otime-for-all-operations.patch new file mode 100644 index 00000000000..d0046179e76 --- /dev/null +++ b/queue-3.11/ipc-sem.c-update-sem_otime-for-all-operations.patch @@ -0,0 +1,103 @@ +From 0e8c665699e953fa58dc1b0b0d09e5dce7343cc7 Mon Sep 17 00:00:00 2001 +From: Manfred Spraul +Date: Mon, 30 Sep 2013 13:45:25 -0700 +Subject: ipc/sem.c: update sem_otime for all operations + +From: Manfred Spraul + +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 +Reported-by: Jia He +Tested-by: Jia He +Cc: Davidlohr Bueso +Cc: Mike Galbraith +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + 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. diff --git a/queue-3.11/series b/queue-3.11/series index df3ee059fb0..76434158bb5 100644 --- a/queue-3.11/series +++ b/queue-3.11/series @@ -44,3 +44,6 @@ ipc-shm-guard-against-non-existant-vma-in-shmdt-2.patch 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