diff options
author | Davide Libenzi <davidel@xmailserver.org> | 2007-05-18 12:02:33 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-18 13:09:34 -0700 |
commit | 18963c01b8abf381f102752ce024c3582a716125 (patch) | |
tree | 6c7e594804608be82ec3988399e905e20d486f51 | |
parent | d48eb2331595224ffe89665e79721d44b40bb047 (diff) | |
download | lwn-18963c01b8abf381f102752ce024c3582a716125.tar.gz lwn-18963c01b8abf381f102752ce024c3582a716125.zip |
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>
-rw-r--r-- | fs/timerfd.c | 24 |
1 files changed, 11 insertions, 13 deletions
diff --git a/fs/timerfd.c b/fs/timerfd.c index e329e37f15a8..af9eca5c0230 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c @@ -24,7 +24,6 @@ struct timerfd_ctx { struct hrtimer tmr; ktime_t tintv; - spinlock_t lock; wait_queue_head_t wqh; int expired; }; @@ -39,10 +38,10 @@ static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr) struct timerfd_ctx *ctx = container_of(htmr, struct timerfd_ctx, tmr); unsigned long flags; - spin_lock_irqsave(&ctx->lock, flags); + spin_lock_irqsave(&ctx->wqh.lock, flags); ctx->expired = 1; wake_up_locked(&ctx->wqh); - spin_unlock_irqrestore(&ctx->lock, flags); + spin_unlock_irqrestore(&ctx->wqh.lock, flags); return HRTIMER_NORESTART; } @@ -83,10 +82,10 @@ static unsigned int timerfd_poll(struct file *file, poll_table *wait) poll_wait(file, &ctx->wqh, wait); - spin_lock_irqsave(&ctx->lock, flags); + spin_lock_irqsave(&ctx->wqh.lock, flags); if (ctx->expired) events |= POLLIN; - spin_unlock_irqrestore(&ctx->lock, flags); + spin_unlock_irqrestore(&ctx->wqh.lock, flags); return events; } @@ -101,7 +100,7 @@ static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count, if (count < sizeof(ticks)) return -EINVAL; - spin_lock_irq(&ctx->lock); + spin_lock_irq(&ctx->wqh.lock); res = -EAGAIN; if (!ctx->expired && !(file->f_flags & O_NONBLOCK)) { __add_wait_queue(&ctx->wqh, &wait); @@ -115,9 +114,9 @@ static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count, res = -ERESTARTSYS; break; } - spin_unlock_irq(&ctx->lock); + spin_unlock_irq(&ctx->wqh.lock); schedule(); - spin_lock_irq(&ctx->lock); + spin_lock_irq(&ctx->wqh.lock); } __remove_wait_queue(&ctx->wqh, &wait); __set_current_state(TASK_RUNNING); @@ -139,7 +138,7 @@ static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count, } else ticks = 1; } - spin_unlock_irq(&ctx->lock); + spin_unlock_irq(&ctx->wqh.lock); if (ticks) res = put_user(ticks, buf) ? -EFAULT: sizeof(ticks); return res; @@ -176,7 +175,6 @@ asmlinkage long sys_timerfd(int ufd, int clockid, int flags, return -ENOMEM; init_waitqueue_head(&ctx->wqh); - spin_lock_init(&ctx->lock); timerfd_setup(ctx, clockid, flags, &ktmr); @@ -202,10 +200,10 @@ asmlinkage long sys_timerfd(int ufd, int clockid, int flags, * it to the new values. */ for (;;) { - spin_lock_irq(&ctx->lock); + spin_lock_irq(&ctx->wqh.lock); if (hrtimer_try_to_cancel(&ctx->tmr) >= 0) break; - spin_unlock_irq(&ctx->lock); + spin_unlock_irq(&ctx->wqh.lock); cpu_relax(); } /* @@ -213,7 +211,7 @@ asmlinkage long sys_timerfd(int ufd, int clockid, int flags, */ timerfd_setup(ctx, clockid, flags, &ktmr); - spin_unlock_irq(&ctx->lock); + spin_unlock_irq(&ctx->wqh.lock); fput(file); } |