Branch data Line data Source code
1 : : /*
2 : : * fs/timerfd.c
3 : : *
4 : : * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org>
5 : : *
6 : : *
7 : : * Thanks to Thomas Gleixner for code reviews and useful comments.
8 : : *
9 : : */
10 : :
11 : : #include <linux/alarmtimer.h>
12 : : #include <linux/file.h>
13 : : #include <linux/poll.h>
14 : : #include <linux/init.h>
15 : : #include <linux/fs.h>
16 : : #include <linux/sched.h>
17 : : #include <linux/kernel.h>
18 : : #include <linux/slab.h>
19 : : #include <linux/list.h>
20 : : #include <linux/spinlock.h>
21 : : #include <linux/time.h>
22 : : #include <linux/hrtimer.h>
23 : : #include <linux/anon_inodes.h>
24 : : #include <linux/timerfd.h>
25 : : #include <linux/syscalls.h>
26 : : #include <linux/compat.h>
27 : : #include <linux/rcupdate.h>
28 : :
29 : : struct timerfd_ctx {
30 : : union {
31 : : struct hrtimer tmr;
32 : : struct alarm alarm;
33 : : } t;
34 : : ktime_t tintv;
35 : : ktime_t moffs;
36 : : wait_queue_head_t wqh;
37 : : u64 ticks;
38 : : int expired;
39 : : int clockid;
40 : : struct rcu_head rcu;
41 : : struct list_head clist;
42 : : bool might_cancel;
43 : : };
44 : :
45 : : static LIST_HEAD(cancel_list);
46 : : static DEFINE_SPINLOCK(cancel_lock);
47 : :
48 : : static inline bool isalarm(struct timerfd_ctx *ctx)
49 : : {
50 : 50 : return ctx->clockid == CLOCK_REALTIME_ALARM ||
51 : : ctx->clockid == CLOCK_BOOTTIME_ALARM;
52 : : }
53 : :
54 : : /*
55 : : * This gets called when the timer event triggers. We set the "expired"
56 : : * flag, but we do not re-arm the timer (in case it's necessary,
57 : : * tintv.tv64 != 0) until the timer is accessed.
58 : : */
59 : 0 : static void timerfd_triggered(struct timerfd_ctx *ctx)
60 : : {
61 : : unsigned long flags;
62 : :
63 : 10 : spin_lock_irqsave(&ctx->wqh.lock, flags);
64 : 10 : ctx->expired = 1;
65 : 10 : ctx->ticks++;
66 : 10 : wake_up_locked(&ctx->wqh);
67 : : spin_unlock_irqrestore(&ctx->wqh.lock, flags);
68 : 10 : }
69 : :
70 : 0 : static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr)
71 : : {
72 : : struct timerfd_ctx *ctx = container_of(htmr, struct timerfd_ctx,
73 : : t.tmr);
74 : 10 : timerfd_triggered(ctx);
75 : 10 : return HRTIMER_NORESTART;
76 : : }
77 : :
78 : 0 : static enum alarmtimer_restart timerfd_alarmproc(struct alarm *alarm,
79 : : ktime_t now)
80 : : {
81 : : struct timerfd_ctx *ctx = container_of(alarm, struct timerfd_ctx,
82 : : t.alarm);
83 : 0 : timerfd_triggered(ctx);
84 : 0 : return ALARMTIMER_NORESTART;
85 : : }
86 : :
87 : : /*
88 : : * Called when the clock was set to cancel the timers in the cancel
89 : : * list. This will wake up processes waiting on these timers. The
90 : : * wake-up requires ctx->ticks to be non zero, therefore we increment
91 : : * it before calling wake_up_locked().
92 : : */
93 : 0 : void timerfd_clock_was_set(void)
94 : : {
95 : 11 : ktime_t moffs = ktime_get_monotonic_offset();
96 : : struct timerfd_ctx *ctx;
97 : : unsigned long flags;
98 : :
99 : : rcu_read_lock();
100 [ - + ]: 22 : list_for_each_entry_rcu(ctx, &cancel_list, clist) {
101 [ # # ]: 0 : if (!ctx->might_cancel)
102 : 0 : continue;
103 : 0 : spin_lock_irqsave(&ctx->wqh.lock, flags);
104 [ # # ]: 0 : if (ctx->moffs.tv64 != moffs.tv64) {
105 : 0 : ctx->moffs.tv64 = KTIME_MAX;
106 : 0 : ctx->ticks++;
107 : 0 : wake_up_locked(&ctx->wqh);
108 : : }
109 : : spin_unlock_irqrestore(&ctx->wqh.lock, flags);
110 : : }
111 : : rcu_read_unlock();
112 : 11 : }
113 : :
114 : 0 : static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
115 : : {
116 [ - + ]: 6 : if (ctx->might_cancel) {
117 : 0 : ctx->might_cancel = false;
118 : : spin_lock(&cancel_lock);
119 : : list_del_rcu(&ctx->clist);
120 : : spin_unlock(&cancel_lock);
121 : : }
122 : 0 : }
123 : :
124 : 0 : static bool timerfd_canceled(struct timerfd_ctx *ctx)
125 : : {
126 [ - + ][ # # ]: 18 : if (!ctx->might_cancel || ctx->moffs.tv64 != KTIME_MAX)
127 : : return false;
128 : 0 : ctx->moffs = ktime_get_monotonic_offset();
129 : 0 : return true;
130 : : }
131 : :
132 : 0 : static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
133 : : {
134 [ + + ]: 8 : if ((ctx->clockid == CLOCK_REALTIME ||
135 : : ctx->clockid == CLOCK_REALTIME_ALARM) &&
136 [ - + ]: 4 : (flags & TFD_TIMER_ABSTIME) && (flags & TFD_TIMER_CANCEL_ON_SET)) {
137 [ # # ]: 0 : if (!ctx->might_cancel) {
138 : 0 : ctx->might_cancel = true;
139 : : spin_lock(&cancel_lock);
140 : 0 : list_add_rcu(&ctx->clist, &cancel_list);
141 : : spin_unlock(&cancel_lock);
142 : : }
143 [ - + ]: 8 : } else if (ctx->might_cancel) {
144 : 0 : timerfd_remove_cancel(ctx);
145 : : }
146 : 0 : }
147 : :
148 : 0 : static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx)
149 : : {
150 : : ktime_t remaining;
151 : :
152 [ - + ]: 10 : if (isalarm(ctx))
153 : 0 : remaining = alarm_expires_remaining(&ctx->t.alarm);
154 : : else
155 : : remaining = hrtimer_expires_remaining(&ctx->t.tmr);
156 : :
157 [ + + ]: 10 : return remaining.tv64 < 0 ? ktime_set(0, 0): remaining;
158 : : }
159 : :
160 : 0 : static int timerfd_setup(struct timerfd_ctx *ctx, int flags,
161 : : const struct itimerspec *ktmr)
162 : : {
163 : : enum hrtimer_mode htmode;
164 : : ktime_t texp;
165 : 8 : int clockid = ctx->clockid;
166 : :
167 : 16 : htmode = (flags & TFD_TIMER_ABSTIME) ?
168 : 8 : HRTIMER_MODE_ABS: HRTIMER_MODE_REL;
169 : :
170 : : texp = timespec_to_ktime(ktmr->it_value);
171 : 8 : ctx->expired = 0;
172 : 8 : ctx->ticks = 0;
173 : 8 : ctx->tintv = timespec_to_ktime(ktmr->it_interval);
174 : :
175 [ - + ]: 8 : if (isalarm(ctx)) {
176 : 0 : alarm_init(&ctx->t.alarm,
177 : : ctx->clockid == CLOCK_REALTIME_ALARM ?
178 : : ALARM_REALTIME : ALARM_BOOTTIME,
179 : : timerfd_alarmproc);
180 : : } else {
181 : 8 : hrtimer_init(&ctx->t.tmr, clockid, htmode);
182 : : hrtimer_set_expires(&ctx->t.tmr, texp);
183 : 8 : ctx->t.tmr.function = timerfd_tmrproc;
184 : : }
185 : :
186 [ + - ]: 16 : if (texp.tv64 != 0) {
187 [ - + ]: 8 : if (isalarm(ctx)) {
188 [ # # ]: 0 : if (flags & TFD_TIMER_ABSTIME)
189 : 0 : alarm_start(&ctx->t.alarm, texp);
190 : : else
191 : 0 : alarm_start_relative(&ctx->t.alarm, texp);
192 : : } else {
193 : 8 : hrtimer_start(&ctx->t.tmr, texp, htmode);
194 : : }
195 : :
196 [ + - ]: 8 : if (timerfd_canceled(ctx))
197 : : return -ECANCELED;
198 : : }
199 : : return 0;
200 : : }
201 : :
202 : 0 : static int timerfd_release(struct inode *inode, struct file *file)
203 : : {
204 : 12 : struct timerfd_ctx *ctx = file->private_data;
205 : :
206 : 6 : timerfd_remove_cancel(ctx);
207 : :
208 [ - + ]: 6 : if (isalarm(ctx))
209 : 0 : alarm_cancel(&ctx->t.alarm);
210 : : else
211 : 6 : hrtimer_cancel(&ctx->t.tmr);
212 : 6 : kfree_rcu(ctx, rcu);
213 : 6 : return 0;
214 : : }
215 : :
216 : 0 : static unsigned int timerfd_poll(struct file *file, poll_table *wait)
217 : : {
218 : 14 : struct timerfd_ctx *ctx = file->private_data;
219 : : unsigned int events = 0;
220 : : unsigned long flags;
221 : :
222 : 14 : poll_wait(file, &ctx->wqh, wait);
223 : :
224 : 14 : spin_lock_irqsave(&ctx->wqh.lock, flags);
225 [ + + ]: 14 : if (ctx->ticks)
226 : : events |= POLLIN;
227 : : spin_unlock_irqrestore(&ctx->wqh.lock, flags);
228 : :
229 : 14 : return events;
230 : : }
231 : :
232 : 0 : static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count,
233 : : loff_t *ppos)
234 : : {
235 : 12 : struct timerfd_ctx *ctx = file->private_data;
236 : : ssize_t res;
237 : : u64 ticks = 0;
238 : :
239 [ + - ]: 10 : if (count < sizeof(ticks))
240 : : return -EINVAL;
241 : : spin_lock_irq(&ctx->wqh.lock);
242 [ + + ]: 10 : if (file->f_flags & O_NONBLOCK)
243 : : res = -EAGAIN;
244 : : else
245 [ - + ][ # # ]: 8 : res = wait_event_interruptible_locked_irq(ctx->wqh, ctx->ticks);
[ # # # # ]
246 : :
247 : : /*
248 : : * If clock has changed, we do not care about the
249 : : * ticks and we do not rearm the timer. Userspace must
250 : : * reevaluate anyway.
251 : : */
252 [ - + ]: 10 : if (timerfd_canceled(ctx)) {
253 : 0 : ctx->ticks = 0;
254 : 0 : ctx->expired = 0;
255 : : res = -ECANCELED;
256 : : }
257 : :
258 [ + + ]: 10 : if (ctx->ticks) {
259 : : ticks = ctx->ticks;
260 : :
261 [ + - ][ + + ]: 8 : if (ctx->expired && ctx->tintv.tv64) {
262 : : /*
263 : : * If tintv.tv64 != 0, this is a periodic timer that
264 : : * needs to be re-armed. We avoid doing it in the timer
265 : : * callback to avoid DoS attacks specifying a very
266 : : * short timer period.
267 : : */
268 [ - + ]: 2 : if (isalarm(ctx)) {
269 : 0 : ticks += alarm_forward_now(
270 : : &ctx->t.alarm, ctx->tintv) - 1;
271 : 0 : alarm_restart(&ctx->t.alarm);
272 : : } else {
273 : 4 : ticks += hrtimer_forward_now(&ctx->t.tmr,
274 : : ctx->tintv) - 1;
275 : : hrtimer_restart(&ctx->t.tmr);
276 : : }
277 : : }
278 : 8 : ctx->expired = 0;
279 : 8 : ctx->ticks = 0;
280 : : }
281 : : spin_unlock_irq(&ctx->wqh.lock);
282 [ + + ]: 10 : if (ticks)
283 [ + - ]: 8 : res = put_user(ticks, (u64 __user *) buf) ? -EFAULT: sizeof(ticks);
284 : 10 : return res;
285 : : }
286 : :
287 : : static const struct file_operations timerfd_fops = {
288 : : .release = timerfd_release,
289 : : .poll = timerfd_poll,
290 : : .read = timerfd_read,
291 : : .llseek = noop_llseek,
292 : : };
293 : :
294 : 0 : static int timerfd_fget(int fd, struct fd *p)
295 : : {
296 : 10 : struct fd f = fdget(fd);
297 [ + ]: 10 : if (!f.file)
298 : : return -EBADF;
299 [ - + ]: 20 : if (f.file->f_op != &timerfd_fops) {
300 : : fdput(f);
301 : : return -EINVAL;
302 : : }
303 : 10 : *p = f;
304 : 10 : return 0;
305 : : }
306 : :
307 : 0 : SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
308 : : {
309 : : int ufd;
310 : : struct timerfd_ctx *ctx;
311 : :
312 : : /* Check the TFD_* constants for consistency. */
313 : : BUILD_BUG_ON(TFD_CLOEXEC != O_CLOEXEC);
314 : : BUILD_BUG_ON(TFD_NONBLOCK != O_NONBLOCK);
315 : :
316 [ + - ][ - + ]: 6 : if ((flags & ~TFD_CREATE_FLAGS) ||
317 : 6 : (clockid != CLOCK_MONOTONIC &&
318 : 6 : clockid != CLOCK_REALTIME &&
319 : 6 : clockid != CLOCK_REALTIME_ALARM &&
320 [ # # ]: 0 : clockid != CLOCK_BOOTTIME &&
321 : 0 : clockid != CLOCK_BOOTTIME_ALARM))
322 : : return -EINVAL;
323 : :
324 : : ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
325 [ + - ]: 6 : if (!ctx)
326 : : return -ENOMEM;
327 : :
328 : 6 : init_waitqueue_head(&ctx->wqh);
329 : 6 : ctx->clockid = clockid;
330 : :
331 [ - + ]: 6 : if (isalarm(ctx))
332 : 0 : alarm_init(&ctx->t.alarm,
333 : : ctx->clockid == CLOCK_REALTIME_ALARM ?
334 : : ALARM_REALTIME : ALARM_BOOTTIME,
335 : : timerfd_alarmproc);
336 : : else
337 : 6 : hrtimer_init(&ctx->t.tmr, clockid, HRTIMER_MODE_ABS);
338 : :
339 : 6 : ctx->moffs = ktime_get_monotonic_offset();
340 : :
341 : 6 : ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx,
342 : 6 : O_RDWR | (flags & TFD_SHARED_FCNTL_FLAGS));
343 [ - + ]: 6 : if (ufd < 0)
344 : 0 : kfree(ctx);
345 : :
346 : : return ufd;
347 : : }
348 : :
349 : 0 : static int do_timerfd_settime(int ufd, int flags,
350 : : const struct itimerspec *new,
351 : : struct itimerspec *old)
352 : : {
353 : : struct fd f;
354 : 8 : struct timerfd_ctx *ctx;
355 : : int ret;
356 : :
357 [ + - ][ + - ]: 16 : if ((flags & ~TFD_SETTIME_FLAGS) ||
358 [ + - ]: 8 : !timespec_valid(&new->it_value) ||
359 : : !timespec_valid(&new->it_interval))
360 : : return -EINVAL;
361 : :
362 : 8 : ret = timerfd_fget(ufd, &f);
363 [ + - ]: 8 : if (ret)
364 : : return ret;
365 : 8 : ctx = f.file->private_data;
366 : :
367 : 8 : timerfd_setup_cancel(ctx, flags);
368 : :
369 : : /*
370 : : * We need to stop the existing timer before reprogramming
371 : : * it to the new values.
372 : : */
373 : : for (;;) {
374 : : spin_lock_irq(&ctx->wqh.lock);
375 : :
376 [ - + ]: 8 : if (isalarm(ctx)) {
377 [ # # ]: 0 : if (alarm_try_to_cancel(&ctx->t.alarm) >= 0)
378 : : break;
379 : : } else {
380 [ - + ]: 8 : if (hrtimer_try_to_cancel(&ctx->t.tmr) >= 0)
381 : : break;
382 : : }
383 : : spin_unlock_irq(&ctx->wqh.lock);
384 : 0 : cpu_relax();
385 : 0 : }
386 : :
387 : : /*
388 : : * If the timer is expired and it's periodic, we need to advance it
389 : : * because the caller may want to know the previous expiration time.
390 : : * We do not update "ticks" and "expired" since the timer will be
391 : : * re-programmed again in the following timerfd_setup() call.
392 : : */
393 [ - + ][ # # ]: 8 : if (ctx->expired && ctx->tintv.tv64) {
394 [ # # ]: 0 : if (isalarm(ctx))
395 : 0 : alarm_forward_now(&ctx->t.alarm, ctx->tintv);
396 : : else
397 : 0 : hrtimer_forward_now(&ctx->t.tmr, ctx->tintv);
398 : : }
399 : :
400 : 8 : old->it_value = ktime_to_timespec(timerfd_get_remaining(ctx));
401 : 8 : old->it_interval = ktime_to_timespec(ctx->tintv);
402 : :
403 : : /*
404 : : * Re-program the timer to the new value ...
405 : : */
406 : 8 : ret = timerfd_setup(ctx, flags, new);
407 : :
408 : : spin_unlock_irq(&ctx->wqh.lock);
409 : : fdput(f);
410 : 8 : return ret;
411 : : }
412 : :
413 : 0 : static int do_timerfd_gettime(int ufd, struct itimerspec *t)
414 : : {
415 : : struct fd f;
416 : 2 : struct timerfd_ctx *ctx;
417 : 2 : int ret = timerfd_fget(ufd, &f);
418 [ + - ]: 2 : if (ret)
419 : : return ret;
420 : 2 : ctx = f.file->private_data;
421 : :
422 : : spin_lock_irq(&ctx->wqh.lock);
423 [ + - ][ + - ]: 2 : if (ctx->expired && ctx->tintv.tv64) {
424 : 2 : ctx->expired = 0;
425 : :
426 [ - + ]: 2 : if (isalarm(ctx)) {
427 : 0 : ctx->ticks +=
428 : 0 : alarm_forward_now(
429 : : &ctx->t.alarm, ctx->tintv) - 1;
430 : 0 : alarm_restart(&ctx->t.alarm);
431 : : } else {
432 : 4 : ctx->ticks +=
433 : 2 : hrtimer_forward_now(&ctx->t.tmr, ctx->tintv)
434 : : - 1;
435 : : hrtimer_restart(&ctx->t.tmr);
436 : : }
437 : : }
438 : 2 : t->it_value = ktime_to_timespec(timerfd_get_remaining(ctx));
439 : 2 : t->it_interval = ktime_to_timespec(ctx->tintv);
440 : : spin_unlock_irq(&ctx->wqh.lock);
441 : : fdput(f);
442 : : return 0;
443 : : }
444 : :
445 : 0 : SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
446 : : const struct itimerspec __user *, utmr,
447 : : struct itimerspec __user *, otmr)
448 : : {
449 : : struct itimerspec new, old;
450 : : int ret;
451 : :
452 [ + - ]: 8 : if (copy_from_user(&new, utmr, sizeof(new)))
453 : : return -EFAULT;
454 : 8 : ret = do_timerfd_settime(ufd, flags, &new, &old);
455 [ + - ]: 8 : if (ret)
456 : : return ret;
457 [ - + ][ # # ]: 16 : if (otmr && copy_to_user(otmr, &old, sizeof(old)))
458 : : return -EFAULT;
459 : :
460 : : return ret;
461 : : }
462 : :
463 : 0 : SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr)
464 : : {
465 : : struct itimerspec kotmr;
466 : 2 : int ret = do_timerfd_gettime(ufd, &kotmr);
467 [ + - ]: 2 : if (ret)
468 : : return ret;
469 [ + - ]: 4 : return copy_to_user(otmr, &kotmr, sizeof(kotmr)) ? -EFAULT: 0;
470 : : }
471 : :
472 : : #ifdef CONFIG_COMPAT
473 : : COMPAT_SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
474 : : const struct compat_itimerspec __user *, utmr,
475 : : struct compat_itimerspec __user *, otmr)
476 : : {
477 : : struct itimerspec new, old;
478 : : int ret;
479 : :
480 : : if (get_compat_itimerspec(&new, utmr))
481 : : return -EFAULT;
482 : : ret = do_timerfd_settime(ufd, flags, &new, &old);
483 : : if (ret)
484 : : return ret;
485 : : if (otmr && put_compat_itimerspec(otmr, &old))
486 : : return -EFAULT;
487 : : return ret;
488 : : }
489 : :
490 : : COMPAT_SYSCALL_DEFINE2(timerfd_gettime, int, ufd,
491 : : struct compat_itimerspec __user *, otmr)
492 : : {
493 : : struct itimerspec kotmr;
494 : : int ret = do_timerfd_gettime(ufd, &kotmr);
495 : : if (ret)
496 : : return ret;
497 : : return put_compat_itimerspec(otmr, &kotmr) ? -EFAULT: 0;
498 : : }
499 : : #endif
|