aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavide Libenzi <davidel@xmailserver.org>2007-05-18 15:02:33 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-18 16:09:34 -0400
commit18963c01b8abf381f102752ce024c3582a716125 (patch)
tree6c7e594804608be82ec3988399e905e20d486f51
parentd48eb2331595224ffe89665e79721d44b40bb047 (diff)
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.c24
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 @@
24struct timerfd_ctx { 24struct timerfd_ctx {
25 struct hrtimer tmr; 25 struct hrtimer tmr;
26 ktime_t tintv; 26 ktime_t tintv;
27 spinlock_t lock;
28 wait_queue_head_t wqh; 27 wait_queue_head_t wqh;
29 int expired; 28 int expired;
30}; 29};
@@ -39,10 +38,10 @@ static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr)
39 struct timerfd_ctx *ctx = container_of(htmr, struct timerfd_ctx, tmr); 38 struct timerfd_ctx *ctx = container_of(htmr, struct timerfd_ctx, tmr);
40 unsigned long flags; 39 unsigned long flags;
41 40
42 spin_lock_irqsave(&ctx->lock, flags); 41 spin_lock_irqsave(&ctx->wqh.lock, flags);
43 ctx->expired = 1; 42 ctx->expired = 1;
44 wake_up_locked(&ctx->wqh); 43 wake_up_locked(&ctx->wqh);
45 spin_unlock_irqrestore(&ctx->lock, flags); 44 spin_unlock_irqrestore(&ctx->wqh.lock, flags);
46 45
47 return HRTIMER_NORESTART; 46 return HRTIMER_NORESTART;
48} 47}
@@ -83,10 +82,10 @@ static unsigned int timerfd_poll(struct file *file, poll_table *wait)
83 82
84 poll_wait(file, &ctx->wqh, wait); 83 poll_wait(file, &ctx->wqh, wait);
85 84
86 spin_lock_irqsave(&ctx->lock, flags); 85 spin_lock_irqsave(&ctx->wqh.lock, flags);
87 if (ctx->expired) 86 if (ctx->expired)
88 events |= POLLIN; 87 events |= POLLIN;
89 spin_unlock_irqrestore(&ctx->lock, flags); 88 spin_unlock_irqrestore(&ctx->wqh.lock, flags);
90 89
91 return events; 90 return events;
92} 91}
@@ -101,7 +100,7 @@ static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count,
101 100
102 if (count < sizeof(ticks)) 101 if (count < sizeof(ticks))
103 return -EINVAL; 102 return -EINVAL;
104 spin_lock_irq(&ctx->lock); 103 spin_lock_irq(&ctx->wqh.lock);
105 res = -EAGAIN; 104 res = -EAGAIN;
106 if (!ctx->expired && !(file->f_flags & O_NONBLOCK)) { 105 if (!ctx->expired && !(file->f_flags & O_NONBLOCK)) {
107 __add_wait_queue(&ctx->wqh, &wait); 106 __add_wait_queue(&ctx->wqh, &wait);
@@ -115,9 +114,9 @@ static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count,
115 res = -ERESTARTSYS; 114 res = -ERESTARTSYS;
116 break; 115 break;
117 } 116 }
118 spin_unlock_irq(&ctx->lock); 117 spin_unlock_irq(&ctx->wqh.lock);
119 schedule(); 118 schedule();
120 spin_lock_irq(&ctx->lock); 119 spin_lock_irq(&ctx->wqh.lock);
121 } 120 }
122 __remove_wait_queue(&ctx->wqh, &wait); 121 __remove_wait_queue(&ctx->wqh, &wait);
123 __set_current_state(TASK_RUNNING); 122 __set_current_state(TASK_RUNNING);
@@ -139,7 +138,7 @@ static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count,
139 } else 138 } else
140 ticks = 1; 139 ticks = 1;
141 } 140 }
142 spin_unlock_irq(&ctx->lock); 141 spin_unlock_irq(&ctx->wqh.lock);
143 if (ticks) 142 if (ticks)
144 res = put_user(ticks, buf) ? -EFAULT: sizeof(ticks); 143 res = put_user(ticks, buf) ? -EFAULT: sizeof(ticks);
145 return res; 144 return res;
@@ -176,7 +175,6 @@ asmlinkage long sys_timerfd(int ufd, int clockid, int flags,
176 return -ENOMEM; 175 return -ENOMEM;
177 176
178 init_waitqueue_head(&ctx->wqh); 177 init_waitqueue_head(&ctx->wqh);
179 spin_lock_init(&ctx->lock);
180 178
181 timerfd_setup(ctx, clockid, flags, &ktmr); 179 timerfd_setup(ctx, clockid, flags, &ktmr);
182 180
@@ -202,10 +200,10 @@ asmlinkage long sys_timerfd(int ufd, int clockid, int flags,
202 * it to the new values. 200 * it to the new values.
203 */ 201 */
204 for (;;) { 202 for (;;) {
205 spin_lock_irq(&ctx->lock); 203 spin_lock_irq(&ctx->wqh.lock);
206 if (hrtimer_try_to_cancel(&ctx->tmr) >= 0) 204 if (hrtimer_try_to_cancel(&ctx->tmr) >= 0)
207 break; 205 break;
208 spin_unlock_irq(&ctx->lock); 206 spin_unlock_irq(&ctx->wqh.lock);
209 cpu_relax(); 207 cpu_relax();
210 } 208 }
211 /* 209 /*
@@ -213,7 +211,7 @@ asmlinkage long sys_timerfd(int ufd, int clockid, int flags,
213 */ 211 */
214 timerfd_setup(ctx, clockid, flags, &ktmr); 212 timerfd_setup(ctx, clockid, flags, &ktmr);
215 213
216 spin_unlock_irq(&ctx->lock); 214 spin_unlock_irq(&ctx->wqh.lock);
217 fput(file); 215 fput(file);
218 } 216 }
219 217