From: Davide Libenzi Make hrtimer_forward() return a u64 instead of unsigned long. Since timerfd returns the number of timer ticks in a u64 variable, and hrtimer_forward() is used to calculate the timer ticks, the patch allow full 64 bit usage even on 32 bit platforms. The core of the hrtimer_forward() ticks calculation, ktime_divns(), was already having the result in u64 and it was chopping it to unsigned long. Signed-off-by: Davide Libenzi Cc: Michael Kerrisk Cc: Thomas Gleixner Cc: Ingo Molnar Signed-off-by: Andrew Morton --- fs/timerfd.c | 6 +++--- include/linux/hrtimer.h | 10 +++++----- kernel/hrtimer.c | 9 ++++----- kernel/posix-timers.c | 9 +++++---- 4 files changed, 17 insertions(+), 17 deletions(-) diff -puN fs/timerfd.c~timerfd-v3-new-timerfd-api-make-hrtimer_forward-to-return-a-u64 fs/timerfd.c --- a/fs/timerfd.c~timerfd-v3-new-timerfd-api-make-hrtimer_forward-to-return-a-u64 +++ a/fs/timerfd.c @@ -134,8 +134,8 @@ static ssize_t timerfd_read(struct file * callback to avoid DoS attacks specifying a very * short timer period. */ - ticks += (u64) hrtimer_forward_now(&ctx->tmr, - ctx->tintv) - 1; + ticks += hrtimer_forward_now(&ctx->tmr, + ctx->tintv) - 1; hrtimer_restart(&ctx->tmr); } ctx->expired = 0; @@ -270,7 +270,7 @@ asmlinkage long sys_timerfd_gettime(int spin_lock_irq(&ctx->wqh.lock); if (ctx->expired && ctx->tintv.tv64) { ctx->expired = 0; - ctx->ticks += (u64) + ctx->ticks += hrtimer_forward_now(&ctx->tmr, ctx->tintv) - 1; hrtimer_restart(&ctx->tmr); } diff -puN include/linux/hrtimer.h~timerfd-v3-new-timerfd-api-make-hrtimer_forward-to-return-a-u64 include/linux/hrtimer.h --- a/include/linux/hrtimer.h~timerfd-v3-new-timerfd-api-make-hrtimer_forward-to-return-a-u64 +++ a/include/linux/hrtimer.h @@ -302,12 +302,12 @@ static inline int hrtimer_is_queued(stru } /* Forward a hrtimer so it expires after now: */ -extern unsigned long +extern u64 hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval); /* Forward a hrtimer so it expires after the hrtimer's current now */ -static inline unsigned long hrtimer_forward_now(struct hrtimer *timer, - ktime_t interval) +static inline u64 hrtimer_forward_now(struct hrtimer *timer, + ktime_t interval) { return hrtimer_forward(timer, timer->base->get_time(), interval); } @@ -330,9 +330,9 @@ extern void hrtimer_run_pending(void); extern void __init hrtimers_init(void); #if BITS_PER_LONG < 64 -extern unsigned long ktime_divns(const ktime_t kt, s64 div); +extern u64 ktime_divns(const ktime_t kt, s64 div); #else /* BITS_PER_LONG < 64 */ -# define ktime_divns(kt, div) (unsigned long)((kt).tv64 / (div)) +# define ktime_divns(kt, div) (u64)((kt).tv64 / (div)) #endif /* Show pending timers: */ diff -puN kernel/hrtimer.c~timerfd-v3-new-timerfd-api-make-hrtimer_forward-to-return-a-u64 kernel/hrtimer.c --- a/kernel/hrtimer.c~timerfd-v3-new-timerfd-api-make-hrtimer_forward-to-return-a-u64 +++ a/kernel/hrtimer.c @@ -306,7 +306,7 @@ EXPORT_SYMBOL_GPL(ktime_sub_ns); /* * Divide a ktime value by a nanosecond value */ -unsigned long ktime_divns(const ktime_t kt, s64 div) +u64 ktime_divns(const ktime_t kt, s64 div) { u64 dclc, inc, dns; int sft = 0; @@ -321,7 +321,7 @@ unsigned long ktime_divns(const ktime_t dclc >>= sft; do_div(dclc, (unsigned long) div); - return (unsigned long) dclc; + return dclc; } #endif /* BITS_PER_LONG >= 64 */ @@ -656,10 +656,9 @@ void unlock_hrtimer_base(const struct hr * Forward the timer expiry so it will expire in the future. * Returns the number of overruns. */ -unsigned long -hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval) +u64 hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval) { - unsigned long orun = 1; + u64 orun = 1; ktime_t delta; delta = ktime_sub(now, timer->expires); diff -puN kernel/posix-timers.c~timerfd-v3-new-timerfd-api-make-hrtimer_forward-to-return-a-u64 kernel/posix-timers.c --- a/kernel/posix-timers.c~timerfd-v3-new-timerfd-api-make-hrtimer_forward-to-return-a-u64 +++ a/kernel/posix-timers.c @@ -256,8 +256,9 @@ static void schedule_next_timer(struct k if (timr->it.real.interval.tv64 == 0) return; - timr->it_overrun += hrtimer_forward(timer, timer->base->get_time(), - timr->it.real.interval); + timr->it_overrun += (unsigned int) hrtimer_forward(timer, + timer->base->get_time(), + timr->it.real.interval); timr->it_overrun_last = timr->it_overrun; timr->it_overrun = -1; @@ -386,7 +387,7 @@ static enum hrtimer_restart posix_timer_ now = ktime_add(now, kj); } #endif - timr->it_overrun += + timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, timr->it.real.interval); ret = HRTIMER_RESTART; @@ -662,7 +663,7 @@ common_timer_get(struct k_itimer *timr, */ if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING || (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) - timr->it_overrun += hrtimer_forward(timer, now, iv); + timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv); remaining = ktime_sub(timer->expires, now); /* Return 0 only, when the timer is expired and not pending */ _