From b4c489e551cdd166bc5b5c5232d174abca02b83f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Jun 2023 08:30:55 +0000 Subject: [PATCH] Revert "posix-cpu-timers: Implement the missing timer_wait_running callback" This reverts commit bccf9fe2963e89b389fd3f31d3935d09b76859f3. It breaks the Android ABI and will be brought back at the next ABI-break. Bug: 161946584 Change-Id: Ibf7f678c89ab7c0ecc9e9e3f358b19263b0df31c Signed-off-by: Greg Kroah-Hartman --- include/linux/posix-timers.h | 17 +++---- kernel/time/posix-cpu-timers.c | 81 ++++++---------------------------- kernel/time/posix-timers.c | 4 -- 3 files changed, 20 insertions(+), 82 deletions(-) diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index d607f51404fc..2c6e99ca48af 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -4,7 +4,6 @@ #include #include -#include #include #include @@ -63,18 +62,16 @@ static inline int clockid_to_fd(const clockid_t clk) * cpu_timer - Posix CPU timer representation for k_itimer * @node: timerqueue node to queue in the task/sig * @head: timerqueue head on which this timer is queued - * @pid: Pointer to target task PID + * @task: Pointer to target task * @elist: List head for the expiry list * @firing: Timer is currently firing - * @handling: Pointer to the task which handles expiry */ struct cpu_timer { - struct timerqueue_node node; - struct timerqueue_head *head; - struct pid *pid; - struct list_head elist; - int firing; - struct task_struct __rcu *handling; + struct timerqueue_node node; + struct timerqueue_head *head; + struct pid *pid; + struct list_head elist; + int firing; }; static inline bool cpu_timer_enqueue(struct timerqueue_head *head, @@ -138,12 +135,10 @@ struct posix_cputimers { /** * posix_cputimers_work - Container for task work based posix CPU timer expiry * @work: The task work to be scheduled - * @mutex: Mutex held around expiry in context of this task work * @scheduled: @work has been scheduled already, no further processing */ struct posix_cputimers_work { struct callback_head work; - struct mutex mutex; unsigned int scheduled; }; diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c index 44b25ff35d28..cb925e8ef9a8 100644 --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -847,8 +847,6 @@ static u64 collect_timerqueue(struct timerqueue_head *head, return expires; ctmr->firing = 1; - /* See posix_cpu_timer_wait_running() */ - rcu_assign_pointer(ctmr->handling, current); cpu_timer_dequeue(ctmr); list_add_tail(&ctmr->elist, firing); } @@ -1164,49 +1162,7 @@ static void handle_posix_cpu_timers(struct task_struct *tsk); #ifdef CONFIG_POSIX_CPU_TIMERS_TASK_WORK static void posix_cpu_timers_work(struct callback_head *work) { - struct posix_cputimers_work *cw = container_of(work, typeof(*cw), work); - - mutex_lock(&cw->mutex); handle_posix_cpu_timers(current); - mutex_unlock(&cw->mutex); -} - -/* - * Invoked from the posix-timer core when a cancel operation failed because - * the timer is marked firing. The caller holds rcu_read_lock(), which - * protects the timer and the task which is expiring it from being freed. - */ -static void posix_cpu_timer_wait_running(struct k_itimer *timr) -{ - struct task_struct *tsk = rcu_dereference(timr->it.cpu.handling); - - /* Has the handling task completed expiry already? */ - if (!tsk) - return; - - /* Ensure that the task cannot go away */ - get_task_struct(tsk); - /* Now drop the RCU protection so the mutex can be locked */ - rcu_read_unlock(); - /* Wait on the expiry mutex */ - mutex_lock(&tsk->posix_cputimers_work.mutex); - /* Release it immediately again. */ - mutex_unlock(&tsk->posix_cputimers_work.mutex); - /* Drop the task reference. */ - put_task_struct(tsk); - /* Relock RCU so the callsite is balanced */ - rcu_read_lock(); -} - -static void posix_cpu_timer_wait_running_nsleep(struct k_itimer *timr) -{ - /* Ensure that timr->it.cpu.handling task cannot go away */ - rcu_read_lock(); - spin_unlock_irq(&timr->it_lock); - posix_cpu_timer_wait_running(timr); - rcu_read_unlock(); - /* @timr is on stack and is valid */ - spin_lock_irq(&timr->it_lock); } /* @@ -1222,7 +1178,6 @@ void clear_posix_cputimers_work(struct task_struct *p) sizeof(p->posix_cputimers_work.work)); init_task_work(&p->posix_cputimers_work.work, posix_cpu_timers_work); - mutex_init(&p->posix_cputimers_work.mutex); p->posix_cputimers_work.scheduled = false; } @@ -1301,18 +1256,6 @@ static inline void __run_posix_cpu_timers(struct task_struct *tsk) lockdep_posixtimer_exit(); } -static void posix_cpu_timer_wait_running(struct k_itimer *timr) -{ - cpu_relax(); -} - -static void posix_cpu_timer_wait_running_nsleep(struct k_itimer *timr) -{ - spin_unlock_irq(&timr->it_lock); - cpu_relax(); - spin_lock_irq(&timr->it_lock); -} - static inline bool posix_cpu_timers_work_scheduled(struct task_struct *tsk) { return false; @@ -1421,8 +1364,6 @@ static void handle_posix_cpu_timers(struct task_struct *tsk) */ if (likely(cpu_firing >= 0)) cpu_timer_fire(timer); - /* See posix_cpu_timer_wait_running() */ - rcu_assign_pointer(timer->it.cpu.handling, NULL); spin_unlock(&timer->it_lock); } } @@ -1557,17 +1498,24 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags, expires = cpu_timer_getexpires(&timer.it.cpu); error = posix_cpu_timer_set(&timer, 0, &zero_it, &it); if (!error) { - /* Timer is now unarmed, deletion can not fail. */ + /* + * Timer is now unarmed, deletion can not fail. + */ posix_cpu_timer_del(&timer); - } else { - while (error == TIMER_RETRY) { - posix_cpu_timer_wait_running_nsleep(&timer); - error = posix_cpu_timer_del(&timer); - } } - spin_unlock_irq(&timer.it_lock); + while (error == TIMER_RETRY) { + /* + * We need to handle case when timer was or is in the + * middle of firing. In other cases we already freed + * resources. + */ + spin_lock_irq(&timer.it_lock); + error = posix_cpu_timer_del(&timer); + spin_unlock_irq(&timer.it_lock); + } + if ((it.it_value.tv_sec | it.it_value.tv_nsec) == 0) { /* * It actually did fire already. @@ -1676,7 +1624,6 @@ const struct k_clock clock_posix_cpu = { .timer_del = posix_cpu_timer_del, .timer_get = posix_cpu_timer_get, .timer_rearm = posix_cpu_timer_rearm, - .timer_wait_running = posix_cpu_timer_wait_running, }; const struct k_clock clock_process = { diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 808a247205a9..0c8a87a11b39 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -846,10 +846,6 @@ static struct k_itimer *timer_wait_running(struct k_itimer *timer, rcu_read_lock(); unlock_timer(timer, *flags); - /* - * kc->timer_wait_running() might drop RCU lock. So @timer - * cannot be touched anymore after the function returns! - */ if (!WARN_ON_ONCE(!kc->timer_wait_running)) kc->timer_wait_running(timer);