time: Change k_clock timer_set() and timer_get() to use timespec64

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>
This commit is contained in:
Deepa Dinamani 2017-03-26 12:04:17 -07:00 committed by Thomas Gleixner
parent 0fe6afe383
commit 5f252b3256
6 changed files with 67 additions and 65 deletions

View 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

View 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;

View 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;

View 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;

View 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.

View 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;