Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

timerfd use waitqueue lock ...

The timerfd was using the unlocked waitqueue operations, but it was
using a different lock, so poll_wait() would race with it.

This makes timerfd directly use the waitqueue lock.

Signed-off-by: Davide Libenzi <davidel@xmailserver.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Davide Libenzi and committed by
Linus Torvalds
18963c01 d48eb233

+11 -13
+11 -13
fs/timerfd.c
··· 24 24 struct timerfd_ctx { 25 25 struct hrtimer tmr; 26 26 ktime_t tintv; 27 - spinlock_t lock; 28 27 wait_queue_head_t wqh; 29 28 int expired; 30 29 }; ··· 38 39 struct timerfd_ctx *ctx = container_of(htmr, struct timerfd_ctx, tmr); 39 40 unsigned long flags; 40 41 41 - spin_lock_irqsave(&ctx->lock, flags); 42 + spin_lock_irqsave(&ctx->wqh.lock, flags); 42 43 ctx->expired = 1; 43 44 wake_up_locked(&ctx->wqh); 44 - spin_unlock_irqrestore(&ctx->lock, flags); 45 + spin_unlock_irqrestore(&ctx->wqh.lock, flags); 45 46 46 47 return HRTIMER_NORESTART; 47 48 } ··· 82 83 83 84 poll_wait(file, &ctx->wqh, wait); 84 85 85 - spin_lock_irqsave(&ctx->lock, flags); 86 + spin_lock_irqsave(&ctx->wqh.lock, flags); 86 87 if (ctx->expired) 87 88 events |= POLLIN; 88 - spin_unlock_irqrestore(&ctx->lock, flags); 89 + spin_unlock_irqrestore(&ctx->wqh.lock, flags); 89 90 90 91 return events; 91 92 } ··· 100 101 101 102 if (count < sizeof(ticks)) 102 103 return -EINVAL; 103 - spin_lock_irq(&ctx->lock); 104 + spin_lock_irq(&ctx->wqh.lock); 104 105 res = -EAGAIN; 105 106 if (!ctx->expired && !(file->f_flags & O_NONBLOCK)) { 106 107 __add_wait_queue(&ctx->wqh, &wait); ··· 114 115 res = -ERESTARTSYS; 115 116 break; 116 117 } 117 - spin_unlock_irq(&ctx->lock); 118 + spin_unlock_irq(&ctx->wqh.lock); 118 119 schedule(); 119 - spin_lock_irq(&ctx->lock); 120 + spin_lock_irq(&ctx->wqh.lock); 120 121 } 121 122 __remove_wait_queue(&ctx->wqh, &wait); 122 123 __set_current_state(TASK_RUNNING); ··· 138 139 } else 139 140 ticks = 1; 140 141 } 141 - spin_unlock_irq(&ctx->lock); 142 + spin_unlock_irq(&ctx->wqh.lock); 142 143 if (ticks) 143 144 res = put_user(ticks, buf) ? -EFAULT: sizeof(ticks); 144 145 return res; ··· 175 176 return -ENOMEM; 176 177 177 178 init_waitqueue_head(&ctx->wqh); 178 - spin_lock_init(&ctx->lock); 179 179 180 180 timerfd_setup(ctx, clockid, flags, &ktmr); 181 181 ··· 200 202 * it to the new values. 201 203 */ 202 204 for (;;) { 203 - spin_lock_irq(&ctx->lock); 205 + spin_lock_irq(&ctx->wqh.lock); 204 206 if (hrtimer_try_to_cancel(&ctx->tmr) >= 0) 205 207 break; 206 - spin_unlock_irq(&ctx->lock); 208 + spin_unlock_irq(&ctx->wqh.lock); 207 209 cpu_relax(); 208 210 } 209 211 /* ··· 211 213 */ 212 214 timerfd_setup(ctx, clockid, flags, &ktmr); 213 215 214 - spin_unlock_irq(&ctx->lock); 216 + spin_unlock_irq(&ctx->wqh.lock); 215 217 fput(file); 216 218 } 217 219