]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - fs/timerfd.c
KVM: PPC: Use preregistered memory API to access TCE list
[mirror_ubuntu-zesty-kernel.git] / fs / timerfd.c
index 9ae4abb4110b84ef286facc88e66be9d954a021d..384fa759a563341b309df47537f9c94da0ee9ebb 100644 (file)
@@ -40,6 +40,7 @@ struct timerfd_ctx {
        short unsigned settime_flags;   /* to show in fdinfo */
        struct rcu_head rcu;
        struct list_head clist;
+       spinlock_t cancel_lock;
        bool might_cancel;
 };
 
@@ -55,7 +56,7 @@ static inline bool isalarm(struct timerfd_ctx *ctx)
 /*
  * This gets called when the timer event triggers. We set the "expired"
  * flag, but we do not re-arm the timer (in case it's necessary,
- * tintv.tv64 != 0) until the timer is accessed.
+ * tintv != 0) until the timer is accessed.
  */
 static void timerfd_triggered(struct timerfd_ctx *ctx)
 {
@@ -93,7 +94,7 @@ static enum alarmtimer_restart timerfd_alarmproc(struct alarm *alarm,
  */
 void timerfd_clock_was_set(void)
 {
-       ktime_t moffs = ktime_mono_to_real((ktime_t){ .tv64 = 0 });
+       ktime_t moffs = ktime_mono_to_real(0);
        struct timerfd_ctx *ctx;
        unsigned long flags;
 
@@ -102,8 +103,8 @@ void timerfd_clock_was_set(void)
                if (!ctx->might_cancel)
                        continue;
                spin_lock_irqsave(&ctx->wqh.lock, flags);
-               if (ctx->moffs.tv64 != moffs.tv64) {
-                       ctx->moffs.tv64 = KTIME_MAX;
+               if (ctx->moffs != moffs) {
+                       ctx->moffs = KTIME_MAX;
                        ctx->ticks++;
                        wake_up_locked(&ctx->wqh);
                }
@@ -112,7 +113,7 @@ void timerfd_clock_was_set(void)
        rcu_read_unlock();
 }
 
-static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
+static void __timerfd_remove_cancel(struct timerfd_ctx *ctx)
 {
        if (ctx->might_cancel) {
                ctx->might_cancel = false;
@@ -122,16 +123,24 @@ static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
        }
 }
 
+static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
+{
+       spin_lock(&ctx->cancel_lock);
+       __timerfd_remove_cancel(ctx);
+       spin_unlock(&ctx->cancel_lock);
+}
+
 static bool timerfd_canceled(struct timerfd_ctx *ctx)
 {
-       if (!ctx->might_cancel || ctx->moffs.tv64 != KTIME_MAX)
+       if (!ctx->might_cancel || ctx->moffs != KTIME_MAX)
                return false;
-       ctx->moffs = ktime_mono_to_real((ktime_t){ .tv64 = 0 });
+       ctx->moffs = ktime_mono_to_real(0);
        return true;
 }
 
 static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
 {
+       spin_lock(&ctx->cancel_lock);
        if ((ctx->clockid == CLOCK_REALTIME ||
             ctx->clockid == CLOCK_REALTIME_ALARM) &&
            (flags & TFD_TIMER_ABSTIME) && (flags & TFD_TIMER_CANCEL_ON_SET)) {
@@ -141,9 +150,10 @@ static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
                        list_add_rcu(&ctx->clist, &cancel_list);
                        spin_unlock(&cancel_lock);
                }
-       } else if (ctx->might_cancel) {
-               timerfd_remove_cancel(ctx);
+       } else {
+               __timerfd_remove_cancel(ctx);
        }
+       spin_unlock(&ctx->cancel_lock);
 }
 
 static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx)
@@ -155,7 +165,7 @@ static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx)
        else
                remaining = hrtimer_expires_remaining_adjusted(&ctx->t.tmr);
 
-       return remaining.tv64 < 0 ? ktime_set(0, 0): remaining;
+       return remaining < 0 ? 0: remaining;
 }
 
 static int timerfd_setup(struct timerfd_ctx *ctx, int flags,
@@ -184,7 +194,7 @@ static int timerfd_setup(struct timerfd_ctx *ctx, int flags,
                ctx->t.tmr.function = timerfd_tmrproc;
        }
 
-       if (texp.tv64 != 0) {
+       if (texp != 0) {
                if (isalarm(ctx)) {
                        if (flags & TFD_TIMER_ABSTIME)
                                alarm_start(&ctx->t.alarm, texp);
@@ -261,9 +271,9 @@ static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count,
        if (ctx->ticks) {
                ticks = ctx->ticks;
 
-               if (ctx->expired && ctx->tintv.tv64) {
+               if (ctx->expired && ctx->tintv) {
                        /*
-                        * If tintv.tv64 != 0, this is a periodic timer that
+                        * If tintv != 0, this is a periodic timer that
                         * needs to be re-armed. We avoid doing it in the timer
                         * callback to avoid DoS attacks specifying a very
                         * short timer period.
@@ -400,6 +410,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
                return -ENOMEM;
 
        init_waitqueue_head(&ctx->wqh);
+       spin_lock_init(&ctx->cancel_lock);
        ctx->clockid = clockid;
 
        if (isalarm(ctx))
@@ -410,7 +421,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
        else
                hrtimer_init(&ctx->t.tmr, clockid, HRTIMER_MODE_ABS);
 
-       ctx->moffs = ktime_mono_to_real((ktime_t){ .tv64 = 0 });
+       ctx->moffs = ktime_mono_to_real(0);
 
        ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx,
                               O_RDWR | (flags & TFD_SHARED_FCNTL_FLAGS));
@@ -469,7 +480,7 @@ static int do_timerfd_settime(int ufd, int flags,
         * We do not update "ticks" and "expired" since the timer will be
         * re-programmed again in the following timerfd_setup() call.
         */
-       if (ctx->expired && ctx->tintv.tv64) {
+       if (ctx->expired && ctx->tintv) {
                if (isalarm(ctx))
                        alarm_forward_now(&ctx->t.alarm, ctx->tintv);
                else
@@ -499,7 +510,7 @@ static int do_timerfd_gettime(int ufd, struct itimerspec *t)
        ctx = f.file->private_data;
 
        spin_lock_irq(&ctx->wqh.lock);
-       if (ctx->expired && ctx->tintv.tv64) {
+       if (ctx->expired && ctx->tintv) {
                ctx->expired = 0;
 
                if (isalarm(ctx)) {