diff options
Diffstat (limited to 'fs/timerfd.c')
| -rw-r--r-- | fs/timerfd.c | 82 |
1 files changed, 28 insertions, 54 deletions
diff --git a/fs/timerfd.c b/fs/timerfd.c index 4bf2f8bfec11..9fcea7860ddf 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c @@ -79,13 +79,11 @@ static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr) return HRTIMER_NORESTART; } -static enum alarmtimer_restart timerfd_alarmproc(struct alarm *alarm, - ktime_t now) +static void timerfd_alarmproc(struct alarm *alarm, ktime_t now) { struct timerfd_ctx *ctx = container_of(alarm, struct timerfd_ctx, t.alarm); timerfd_triggered(ctx); - return ALARMTIMER_NORESTART; } /* @@ -207,9 +205,8 @@ static int timerfd_setup(struct timerfd_ctx *ctx, int flags, ALARM_REALTIME : ALARM_BOOTTIME, timerfd_alarmproc); } else { - hrtimer_init(&ctx->t.tmr, clockid, htmode); + hrtimer_setup(&ctx->t.tmr, timerfd_tmrproc, clockid, htmode); hrtimer_set_expires(&ctx->t.tmr, texp); - ctx->t.tmr.function = timerfd_tmrproc; } if (texp != 0) { @@ -394,24 +391,10 @@ static const struct file_operations timerfd_fops = { .unlocked_ioctl = timerfd_ioctl, }; -static int timerfd_fget(int fd, struct fd *p) -{ - struct fd f = fdget(fd); - if (!f.file) - return -EBADF; - if (f.file->f_op != &timerfd_fops) { - fdput(f); - return -EINVAL; - } - *p = f; - return 0; -} - SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags) { - int ufd; - struct timerfd_ctx *ctx; - struct file *file; + struct timerfd_ctx *ctx __free(kfree) = NULL; + int ret; /* Check the TFD_* constants for consistency. */ BUILD_BUG_ON(TFD_CLOEXEC != O_CLOEXEC); @@ -444,34 +427,23 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags) ALARM_REALTIME : ALARM_BOOTTIME, timerfd_alarmproc); else - hrtimer_init(&ctx->t.tmr, clockid, HRTIMER_MODE_ABS); + hrtimer_setup(&ctx->t.tmr, timerfd_tmrproc, clockid, HRTIMER_MODE_ABS); ctx->moffs = ktime_mono_to_real(0); - ufd = get_unused_fd_flags(flags & TFD_SHARED_FCNTL_FLAGS); - if (ufd < 0) { - kfree(ctx); - return ufd; - } - - file = anon_inode_getfile("[timerfd]", &timerfd_fops, ctx, - O_RDWR | (flags & TFD_SHARED_FCNTL_FLAGS)); - if (IS_ERR(file)) { - put_unused_fd(ufd); - kfree(ctx); - return PTR_ERR(file); - } - - file->f_mode |= FMODE_NOWAIT; - fd_install(ufd, file); - return ufd; + ret = FD_ADD(flags & TFD_SHARED_FCNTL_FLAGS, + anon_inode_getfile_fmode("[timerfd]", &timerfd_fops, ctx, + O_RDWR | (flags & TFD_SHARED_FCNTL_FLAGS), + FMODE_NOWAIT)); + if (ret >= 0) + retain_and_null_ptr(ctx); + return ret; } static int do_timerfd_settime(int ufd, int flags, const struct itimerspec64 *new, struct itimerspec64 *old) { - struct fd f; struct timerfd_ctx *ctx; int ret; @@ -479,15 +451,17 @@ static int do_timerfd_settime(int ufd, int flags, !itimerspec64_valid(new)) return -EINVAL; - ret = timerfd_fget(ufd, &f); - if (ret) - return ret; - ctx = f.file->private_data; + CLASS(fd, f)(ufd); + if (fd_empty(f)) + return -EBADF; + + if (fd_file(f)->f_op != &timerfd_fops) + return -EINVAL; + + ctx = fd_file(f)->private_data; - if (isalarm(ctx) && !capable(CAP_WAKE_ALARM)) { - fdput(f); + if (isalarm(ctx) && !capable(CAP_WAKE_ALARM)) return -EPERM; - } timerfd_setup_cancel(ctx, flags); @@ -535,18 +509,19 @@ static int do_timerfd_settime(int ufd, int flags, ret = timerfd_setup(ctx, flags, new); spin_unlock_irq(&ctx->wqh.lock); - fdput(f); return ret; } static int do_timerfd_gettime(int ufd, struct itimerspec64 *t) { - struct fd f; struct timerfd_ctx *ctx; - int ret = timerfd_fget(ufd, &f); - if (ret) - return ret; - ctx = f.file->private_data; + CLASS(fd, f)(ufd); + + if (fd_empty(f)) + return -EBADF; + if (fd_file(f)->f_op != &timerfd_fops) + return -EINVAL; + ctx = fd_file(f)->private_data; spin_lock_irq(&ctx->wqh.lock); if (ctx->expired && ctx->tintv) { @@ -567,7 +542,6 @@ static int do_timerfd_gettime(int ufd, struct itimerspec64 *t) t->it_value = ktime_to_timespec64(timerfd_get_remaining(ctx)); t->it_interval = ktime_to_timespec64(ctx->tintv); spin_unlock_irq(&ctx->wqh.lock); - fdput(f); return 0; } |
