time: Change k_clock timer_set() and timer_get() to use timespec64
authorDeepa Dinamani <deepa.kernel@gmail.com>
Sun, 26 Mar 2017 19:04:17 +0000 (12:04 -0700)
committerThomas Gleixner <tglx@linutronix.de>
Fri, 14 Apr 2017 19:49:56 +0000 (21:49 +0200)
struct timespec is not y2038 safe on 32 bit machines.  Replace uses of
struct timespec with struct timespec64 in the kernel.

struct itimerspec internally uses struct timespec.  Use struct itimerspec64
which uses struct timespec64.

The syscall interfaces themselves will be changed in a separate series.

Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
Cc: y2038@lists.linaro.org
Cc: john.stultz@linaro.org
Cc: arnd@arndb.de
Link: http://lkml.kernel.org/r/1490555058-4603-7-git-send-email-deepa.kernel@gmail.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
drivers/char/mmtimer.c
include/linux/posix-timers.h
kernel/time/alarmtimer.c
kernel/time/posix-clock.c
kernel/time/posix-cpu-timers.c
kernel/time/posix-timers.c

index ba1b8925c4c8ca16ef8e7f3ca25002be1ac17746..0e7fcb04f01e74639ba01bd3f7a205d71fb3bcc8 100644 (file)
@@ -657,7 +657,7 @@ static int sgi_timer_del(struct k_itimer *timr)
 }
 
 /* Assumption: it_lock is already held with irq's disabled */
-static void sgi_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
+static void sgi_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)
 {
 
        if (timr->it.mmtimer.clock == TIMER_OFF) {
@@ -668,14 +668,14 @@ static void sgi_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
                return;
        }
 
-       cur_setting->it_interval = ns_to_timespec(timr->it.mmtimer.incr * sgi_clock_period);
-       cur_setting->it_value = ns_to_timespec((timr->it.mmtimer.expires - rtc_time()) * sgi_clock_period);
+       cur_setting->it_interval = ns_to_timespec64(timr->it.mmtimer.incr * sgi_clock_period);
+       cur_setting->it_value = ns_to_timespec64((timr->it.mmtimer.expires - rtc_time()) * sgi_clock_period);
 }
 
 
 static int sgi_timer_set(struct k_itimer *timr, int flags,
-       struct itimerspec * new_setting,
-       struct itimerspec * old_setting)
+       struct itimerspec64 *new_setting,
+       struct itimerspec64 *old_setting)
 {
        unsigned long when, period, irqflags;
        int err = 0;
@@ -687,8 +687,8 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
                sgi_timer_get(timr, old_setting);
 
        sgi_timer_del(timr);
-       when = timespec_to_ns(&new_setting->it_value);
-       period = timespec_to_ns(&new_setting->it_interval);
+       when = timespec64_to_ns(&new_setting->it_value);
+       period = timespec64_to_ns(&new_setting->it_interval);
 
        if (when == 0)
                /* Clear timer */
@@ -699,11 +699,11 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
                return -ENOMEM;
 
        if (flags & TIMER_ABSTIME) {
-               struct timespec n;
+               struct timespec64 n;
                unsigned long now;
 
-               getnstimeofday(&n);
-               now = timespec_to_ns(&n);
+               getnstimeofday64(&n);
+               now = timespec64_to_ns(&n);
                if (when > now)
                        when -= now;
                else
index 7825e242b128a8d199e043f23ee5e2e03c26e5ed..ebc4c49453396411777ae3fc0d9fbdd64ebfb401 100644 (file)
@@ -96,13 +96,13 @@ struct k_clock {
        int (*nsleep) (const clockid_t which_clock, int flags,
                       struct timespec *, struct timespec __user *);
        long (*nsleep_restart) (struct restart_block *restart_block);
-       int (*timer_set) (struct k_itimer * timr, int flags,
-                         struct itimerspec * new_setting,
-                         struct itimerspec * old_setting);
-       int (*timer_del) (struct k_itimer * timr);
+       int (*timer_set) (struct k_itimer *timr, int flags,
+                         struct itimerspec64 *new_setting,
+                         struct itimerspec64 *old_setting);
+       int (*timer_del) (struct k_itimer *timr);
 #define TIMER_RETRY 1
-       void (*timer_get) (struct k_itimer * timr,
-                          struct itimerspec * cur_setting);
+       void (*timer_get) (struct k_itimer *timr,
+                          struct itimerspec64 *cur_setting);
 };
 
 extern struct k_clock clock_posix_cpu;
index e8a45e2c3d953d2a3607efdd07096512a2b65c12..e069f94999a80be078067c7678f9745ad802bd51 100644 (file)
@@ -598,19 +598,19 @@ static int alarm_timer_create(struct k_itimer *new_timer)
  * Copies out the current itimerspec data
  */
 static void alarm_timer_get(struct k_itimer *timr,
-                               struct itimerspec *cur_setting)
+                           struct itimerspec64 *cur_setting)
 {
        ktime_t relative_expiry_time =
                alarm_expires_remaining(&(timr->it.alarm.alarmtimer));
 
        if (ktime_to_ns(relative_expiry_time) > 0) {
-               cur_setting->it_value = ktime_to_timespec(relative_expiry_time);
+               cur_setting->it_value = ktime_to_timespec64(relative_expiry_time);
        } else {
                cur_setting->it_value.tv_sec = 0;
                cur_setting->it_value.tv_nsec = 0;
        }
 
-       cur_setting->it_interval = ktime_to_timespec(timr->it.alarm.interval);
+       cur_setting->it_interval = ktime_to_timespec64(timr->it.alarm.interval);
 }
 
 /**
@@ -640,8 +640,8 @@ static int alarm_timer_del(struct k_itimer *timr)
  * Sets the timer to new_setting, and starts the timer.
  */
 static int alarm_timer_set(struct k_itimer *timr, int flags,
-                               struct itimerspec *new_setting,
-                               struct itimerspec *old_setting)
+                          struct itimerspec64 *new_setting,
+                          struct itimerspec64 *old_setting)
 {
        ktime_t exp;
 
@@ -659,8 +659,8 @@ static int alarm_timer_set(struct k_itimer *timr, int flags,
                return TIMER_RETRY;
 
        /* start the timer */
-       timr->it.alarm.interval = timespec_to_ktime(new_setting->it_interval);
-       exp = timespec_to_ktime(new_setting->it_value);
+       timr->it.alarm.interval = timespec64_to_ktime(new_setting->it_interval);
+       exp = timespec64_to_ktime(new_setting->it_value);
        /* Convert (if necessary) to absolute time */
        if (flags != TIMER_ABSTIME) {
                ktime_t now;
index 3807a34519c4939b6661865b8f1c2632c8886500..31d588d37a173ae6fc65ab7d956736982e381991 100644 (file)
@@ -399,40 +399,33 @@ static int pc_timer_delete(struct k_itimer *kit)
        return err;
 }
 
-static void pc_timer_gettime(struct k_itimer *kit, struct itimerspec *ts)
+static void pc_timer_gettime(struct k_itimer *kit, struct itimerspec64 *ts)
 {
        clockid_t id = kit->it_clock;
        struct posix_clock_desc cd;
-       struct itimerspec64 ts64;
 
        if (get_clock_desc(id, &cd))
                return;
 
-       if (cd.clk->ops.timer_gettime) {
-               cd.clk->ops.timer_gettime(cd.clk, kit, &ts64);
-               *ts = itimerspec64_to_itimerspec(&ts64);
-       }
+       if (cd.clk->ops.timer_gettime)
+               cd.clk->ops.timer_gettime(cd.clk, kit, ts);
+
        put_clock_desc(&cd);
 }
 
 static int pc_timer_settime(struct k_itimer *kit, int flags,
-                           struct itimerspec *ts, struct itimerspec *old)
+                           struct itimerspec64 *ts, struct itimerspec64 *old)
 {
-       struct itimerspec64 ts64 = itimerspec_to_itimerspec64(ts);
        clockid_t id = kit->it_clock;
        struct posix_clock_desc cd;
-       struct itimerspec64 old64;
        int err;
 
        err = get_clock_desc(id, &cd);
        if (err)
                return err;
 
-       if (cd.clk->ops.timer_settime) {
-               err = cd.clk->ops.timer_settime(cd.clk, kit, flags, &ts64, &old64);
-               if (old)
-                       *old = itimerspec64_to_itimerspec(&old64);
-       }
+       if (cd.clk->ops.timer_settime)
+               err = cd.clk->ops.timer_settime(cd.clk, kit, flags, ts, old);
        else
                err = -EOPNOTSUPP;
 
index 2cd4428c81f03d6d826719cb4fe3829fc2d58d41..441064d1216fff4ce18e5b3ecdbc7a971b084cef 100644 (file)
@@ -562,7 +562,7 @@ static int cpu_timer_sample_group(const clockid_t which_clock,
  * and try again.  (This happens when the timer is in the middle of firing.)
  */
 static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
-                              struct itimerspec *new, struct itimerspec *old)
+                              struct itimerspec64 *new, struct itimerspec64 *old)
 {
        unsigned long flags;
        struct sighand_struct *sighand;
@@ -572,7 +572,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
 
        WARN_ON_ONCE(p == NULL);
 
-       new_expires = timespec_to_ns(&new->it_value);
+       new_expires = timespec64_to_ns(&new->it_value);
 
        /*
         * Protect against sighand release/switch in exit/exec and p->cpu_timers
@@ -633,7 +633,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
                        bump_cpu_timer(timer, val);
                        if (val < timer->it.cpu.expires) {
                                old_expires = timer->it.cpu.expires - val;
-                               old->it_value = ns_to_timespec(old_expires);
+                               old->it_value = ns_to_timespec64(old_expires);
                        } else {
                                old->it_value.tv_nsec = 1;
                                old->it_value.tv_sec = 0;
@@ -671,7 +671,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
         * Install the new reload setting, and
         * set up the signal and overrun bookkeeping.
         */
-       timer->it.cpu.incr = timespec_to_ns(&new->it_interval);
+       timer->it.cpu.incr = timespec64_to_ns(&new->it_interval);
 
        /*
         * This acts as a modification timestamp for the timer,
@@ -695,12 +695,12 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
        ret = 0;
  out:
        if (old)
-               old->it_interval = ns_to_timespec(old_incr);
+               old->it_interval = ns_to_timespec64(old_incr);
 
        return ret;
 }
 
-static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
+static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp)
 {
        u64 now;
        struct task_struct *p = timer->it.cpu.task;
@@ -710,7 +710,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
        /*
         * Easy part: convert the reload time.
         */
-       itp->it_interval = ns_to_timespec(timer->it.cpu.incr);
+       itp->it_interval = ns_to_timespec64(timer->it.cpu.incr);
 
        if (timer->it.cpu.expires == 0) {       /* Timer not armed at all.  */
                itp->it_value.tv_sec = itp->it_value.tv_nsec = 0;
@@ -739,7 +739,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
                         * Call the timer disarmed, nothing else to do.
                         */
                        timer->it.cpu.expires = 0;
-                       itp->it_value = ns_to_timespec(timer->it.cpu.expires);
+                       itp->it_value = ns_to_timespec64(timer->it.cpu.expires);
                        return;
                } else {
                        cpu_timer_sample_group(timer->it_clock, p, &now);
@@ -748,7 +748,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
        }
 
        if (now < timer->it.cpu.expires) {
-               itp->it_value = ns_to_timespec(timer->it.cpu.expires - now);
+               itp->it_value = ns_to_timespec64(timer->it.cpu.expires - now);
        } else {
                /*
                 * The timer should have expired already, but the firing
@@ -1221,6 +1221,7 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
 static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
                            struct timespec *rqtp, struct itimerspec *it)
 {
+       struct itimerspec64 it64;
        struct k_itimer timer;
        int error;
 
@@ -1234,13 +1235,14 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
        error = posix_cpu_timer_create(&timer);
        timer.it_process = current;
        if (!error) {
-               static struct itimerspec zero_it;
+               static struct itimerspec64 zero_it;
 
                memset(it, 0, sizeof *it);
                it->it_value = *rqtp;
 
                spin_lock_irq(&timer.it_lock);
-               error = posix_cpu_timer_set(&timer, flags, it, NULL);
+               it64 = itimerspec_to_itimerspec64(it);
+               error = posix_cpu_timer_set(&timer, flags, &it64, NULL);
                if (error) {
                        spin_unlock_irq(&timer.it_lock);
                        return error;
@@ -1270,7 +1272,9 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
                 * We were interrupted by a signal.
                 */
                *rqtp = ns_to_timespec(timer.it.cpu.expires);
-               error = posix_cpu_timer_set(&timer, 0, &zero_it, it);
+               it64 = itimerspec_to_itimerspec64(it);
+               error = posix_cpu_timer_set(&timer, 0, &zero_it, &it64);
+               *it = itimerspec64_to_itimerspec(&it64);
                if (!error) {
                        /*
                         * Timer is now unarmed, deletion can not fail.
index 7742da826f02700fb811ea60a1d802304c515ab4..9da4797d0c63eed2c935244c628cc668fb05d312 100644 (file)
@@ -133,9 +133,9 @@ static struct k_clock posix_clocks[MAX_CLOCKS];
 static int common_nsleep(const clockid_t, int flags, struct timespec *t,
                         struct timespec __user *rmtp);
 static int common_timer_create(struct k_itimer *new_timer);
-static void common_timer_get(struct k_itimer *, struct itimerspec *);
+static void common_timer_get(struct k_itimer *, struct itimerspec64 *);
 static int common_timer_set(struct k_itimer *, int,
-                           struct itimerspec *, struct itimerspec *);
+                           struct itimerspec64 *, struct itimerspec64 *);
 static int common_timer_del(struct k_itimer *timer);
 
 static enum hrtimer_restart posix_timer_fn(struct hrtimer *data);
@@ -734,18 +734,18 @@ static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags)
  * report.
  */
 static void
-common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
+common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)
 {
        ktime_t now, remaining, iv;
        struct hrtimer *timer = &timr->it.real.timer;
 
-       memset(cur_setting, 0, sizeof(struct itimerspec));
+       memset(cur_setting, 0, sizeof(*cur_setting));
 
        iv = timr->it.real.interval;
 
        /* interval timer ? */
        if (iv)
-               cur_setting->it_interval = ktime_to_timespec(iv);
+               cur_setting->it_interval = ktime_to_timespec64(iv);
        else if (!hrtimer_active(timer) &&
                 (timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE)
                return;
@@ -771,13 +771,14 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
                if ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE)
                        cur_setting->it_value.tv_nsec = 1;
        } else
-               cur_setting->it_value = ktime_to_timespec(remaining);
+               cur_setting->it_value = ktime_to_timespec64(remaining);
 }
 
 /* Get the time remaining on a POSIX.1b interval timer. */
 SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
                struct itimerspec __user *, setting)
 {
+       struct itimerspec64 cur_setting64;
        struct itimerspec cur_setting;
        struct k_itimer *timr;
        struct k_clock *kc;
@@ -792,10 +793,11 @@ SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
        if (WARN_ON_ONCE(!kc || !kc->timer_get))
                ret = -EINVAL;
        else
-               kc->timer_get(timr, &cur_setting);
+               kc->timer_get(timr, &cur_setting64);
 
        unlock_timer(timr, flags);
 
+       cur_setting = itimerspec64_to_itimerspec(&cur_setting64);
        if (!ret && copy_to_user(setting, &cur_setting, sizeof (cur_setting)))
                return -EFAULT;
 
@@ -831,7 +833,7 @@ SYSCALL_DEFINE1(timer_getoverrun, timer_t, timer_id)
 /* timr->it_lock is taken. */
 static int
 common_timer_set(struct k_itimer *timr, int flags,
-                struct itimerspec *new_setting, struct itimerspec *old_setting)
+                struct itimerspec64 *new_setting, struct itimerspec64 *old_setting)
 {
        struct hrtimer *timer = &timr->it.real.timer;
        enum hrtimer_mode mode;
@@ -860,10 +862,10 @@ common_timer_set(struct k_itimer *timr, int flags,
        hrtimer_init(&timr->it.real.timer, timr->it_clock, mode);
        timr->it.real.timer.function = posix_timer_fn;
 
-       hrtimer_set_expires(timer, timespec_to_ktime(new_setting->it_value));
+       hrtimer_set_expires(timer, timespec64_to_ktime(new_setting->it_value));
 
        /* Convert interval */
-       timr->it.real.interval = timespec_to_ktime(new_setting->it_interval);
+       timr->it.real.interval = timespec64_to_ktime(new_setting->it_interval);
 
        /* SIGEV_NONE timers are not queued ! See common_timer_get */
        if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) {
@@ -883,21 +885,23 @@ SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
                const struct itimerspec __user *, new_setting,
                struct itimerspec __user *, old_setting)
 {
-       struct k_itimer *timr;
+       struct itimerspec64 new_spec64, old_spec64;
+       struct itimerspec64 *rtn = old_setting ? &old_spec64 : NULL;
        struct itimerspec new_spec, old_spec;
-       int error = 0;
+       struct k_itimer *timr;
        unsigned long flag;
-       struct itimerspec *rtn = old_setting ? &old_spec : NULL;
        struct k_clock *kc;
+       int error = 0;
 
        if (!new_setting)
                return -EINVAL;
 
        if (copy_from_user(&new_spec, new_setting, sizeof (new_spec)))
                return -EFAULT;
+       new_spec64 = itimerspec_to_itimerspec64(&new_spec);
 
-       if (!timespec_valid(&new_spec.it_interval) ||
-           !timespec_valid(&new_spec.it_value))
+       if (!timespec64_valid(&new_spec64.it_interval) ||
+           !timespec64_valid(&new_spec64.it_value))
                return -EINVAL;
 retry:
        timr = lock_timer(timer_id, &flag);
@@ -908,7 +912,7 @@ retry:
        if (WARN_ON_ONCE(!kc || !kc->timer_set))
                error = -EINVAL;
        else
-               error = kc->timer_set(timr, flags, &new_spec, rtn);
+               error = kc->timer_set(timr, flags, &new_spec64, rtn);
 
        unlock_timer(timr, flag);
        if (error == TIMER_RETRY) {
@@ -916,6 +920,7 @@ retry:
                goto retry;
        }
 
+       old_spec = itimerspec64_to_itimerspec(&old_spec64);
        if (old_setting && !error &&
            copy_to_user(old_setting, &old_spec, sizeof (old_spec)))
                error = -EFAULT;