Commit 5f252b32 authored by Deepa Dinamani's avatar Deepa Dinamani Committed by Thomas Gleixner

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: default avatarDeepa 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.comSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 0fe6afe3
...@@ -657,7 +657,7 @@ static int sgi_timer_del(struct k_itimer *timr) ...@@ -657,7 +657,7 @@ static int sgi_timer_del(struct k_itimer *timr)
} }
/* Assumption: it_lock is already held with irq's disabled */ /* 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) { if (timr->it.mmtimer.clock == TIMER_OFF) {
...@@ -668,14 +668,14 @@ static void sgi_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) ...@@ -668,14 +668,14 @@ static void sgi_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
return; return;
} }
cur_setting->it_interval = ns_to_timespec(timr->it.mmtimer.incr * sgi_clock_period); cur_setting->it_interval = ns_to_timespec64(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_value = ns_to_timespec64((timr->it.mmtimer.expires - rtc_time()) * sgi_clock_period);
} }
static int sgi_timer_set(struct k_itimer *timr, int flags, static int sgi_timer_set(struct k_itimer *timr, int flags,
struct itimerspec * new_setting, struct itimerspec64 *new_setting,
struct itimerspec * old_setting) struct itimerspec64 *old_setting)
{ {
unsigned long when, period, irqflags; unsigned long when, period, irqflags;
int err = 0; int err = 0;
...@@ -687,8 +687,8 @@ static int sgi_timer_set(struct k_itimer *timr, int flags, ...@@ -687,8 +687,8 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
sgi_timer_get(timr, old_setting); sgi_timer_get(timr, old_setting);
sgi_timer_del(timr); sgi_timer_del(timr);
when = timespec_to_ns(&new_setting->it_value); when = timespec64_to_ns(&new_setting->it_value);
period = timespec_to_ns(&new_setting->it_interval); period = timespec64_to_ns(&new_setting->it_interval);
if (when == 0) if (when == 0)
/* Clear timer */ /* Clear timer */
...@@ -699,11 +699,11 @@ static int sgi_timer_set(struct k_itimer *timr, int flags, ...@@ -699,11 +699,11 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
return -ENOMEM; return -ENOMEM;
if (flags & TIMER_ABSTIME) { if (flags & TIMER_ABSTIME) {
struct timespec n; struct timespec64 n;
unsigned long now; unsigned long now;
getnstimeofday(&n); getnstimeofday64(&n);
now = timespec_to_ns(&n); now = timespec64_to_ns(&n);
if (when > now) if (when > now)
when -= now; when -= now;
else else
......
...@@ -96,13 +96,13 @@ struct k_clock { ...@@ -96,13 +96,13 @@ struct k_clock {
int (*nsleep) (const clockid_t which_clock, int flags, int (*nsleep) (const clockid_t which_clock, int flags,
struct timespec *, struct timespec __user *); struct timespec *, struct timespec __user *);
long (*nsleep_restart) (struct restart_block *restart_block); long (*nsleep_restart) (struct restart_block *restart_block);
int (*timer_set) (struct k_itimer * timr, int flags, int (*timer_set) (struct k_itimer *timr, int flags,
struct itimerspec * new_setting, struct itimerspec64 *new_setting,
struct itimerspec * old_setting); struct itimerspec64 *old_setting);
int (*timer_del) (struct k_itimer * timr); int (*timer_del) (struct k_itimer *timr);
#define TIMER_RETRY 1 #define TIMER_RETRY 1
void (*timer_get) (struct k_itimer * timr, void (*timer_get) (struct k_itimer *timr,
struct itimerspec * cur_setting); struct itimerspec64 *cur_setting);
}; };
extern struct k_clock clock_posix_cpu; extern struct k_clock clock_posix_cpu;
......
...@@ -598,19 +598,19 @@ static int alarm_timer_create(struct k_itimer *new_timer) ...@@ -598,19 +598,19 @@ static int alarm_timer_create(struct k_itimer *new_timer)
* Copies out the current itimerspec data * Copies out the current itimerspec data
*/ */
static void alarm_timer_get(struct k_itimer *timr, static void alarm_timer_get(struct k_itimer *timr,
struct itimerspec *cur_setting) struct itimerspec64 *cur_setting)
{ {
ktime_t relative_expiry_time = ktime_t relative_expiry_time =
alarm_expires_remaining(&(timr->it.alarm.alarmtimer)); alarm_expires_remaining(&(timr->it.alarm.alarmtimer));
if (ktime_to_ns(relative_expiry_time) > 0) { 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 { } else {
cur_setting->it_value.tv_sec = 0; cur_setting->it_value.tv_sec = 0;
cur_setting->it_value.tv_nsec = 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) ...@@ -640,8 +640,8 @@ static int alarm_timer_del(struct k_itimer *timr)
* Sets the timer to new_setting, and starts the timer. * Sets the timer to new_setting, and starts the timer.
*/ */
static int alarm_timer_set(struct k_itimer *timr, int flags, static int alarm_timer_set(struct k_itimer *timr, int flags,
struct itimerspec *new_setting, struct itimerspec64 *new_setting,
struct itimerspec *old_setting) struct itimerspec64 *old_setting)
{ {
ktime_t exp; ktime_t exp;
...@@ -659,8 +659,8 @@ static int alarm_timer_set(struct k_itimer *timr, int flags, ...@@ -659,8 +659,8 @@ static int alarm_timer_set(struct k_itimer *timr, int flags,
return TIMER_RETRY; return TIMER_RETRY;
/* start the timer */ /* start the timer */
timr->it.alarm.interval = timespec_to_ktime(new_setting->it_interval); timr->it.alarm.interval = timespec64_to_ktime(new_setting->it_interval);
exp = timespec_to_ktime(new_setting->it_value); exp = timespec64_to_ktime(new_setting->it_value);
/* Convert (if necessary) to absolute time */ /* Convert (if necessary) to absolute time */
if (flags != TIMER_ABSTIME) { if (flags != TIMER_ABSTIME) {
ktime_t now; ktime_t now;
......
...@@ -399,40 +399,33 @@ static int pc_timer_delete(struct k_itimer *kit) ...@@ -399,40 +399,33 @@ static int pc_timer_delete(struct k_itimer *kit)
return err; 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; clockid_t id = kit->it_clock;
struct posix_clock_desc cd; struct posix_clock_desc cd;
struct itimerspec64 ts64;
if (get_clock_desc(id, &cd)) if (get_clock_desc(id, &cd))
return; return;
if (cd.clk->ops.timer_gettime) { if (cd.clk->ops.timer_gettime)
cd.clk->ops.timer_gettime(cd.clk, kit, &ts64); cd.clk->ops.timer_gettime(cd.clk, kit, ts);
*ts = itimerspec64_to_itimerspec(&ts64);
}
put_clock_desc(&cd); put_clock_desc(&cd);
} }
static int pc_timer_settime(struct k_itimer *kit, int flags, 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; clockid_t id = kit->it_clock;
struct posix_clock_desc cd; struct posix_clock_desc cd;
struct itimerspec64 old64;
int err; int err;
err = get_clock_desc(id, &cd); err = get_clock_desc(id, &cd);
if (err) if (err)
return err; return err;
if (cd.clk->ops.timer_settime) { if (cd.clk->ops.timer_settime)
err = cd.clk->ops.timer_settime(cd.clk, kit, flags, &ts64, &old64); err = cd.clk->ops.timer_settime(cd.clk, kit, flags, ts, old);
if (old)
*old = itimerspec64_to_itimerspec(&old64);
}
else else
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
......
...@@ -562,7 +562,7 @@ static int cpu_timer_sample_group(const clockid_t which_clock, ...@@ -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.) * 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, 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; unsigned long flags;
struct sighand_struct *sighand; struct sighand_struct *sighand;
...@@ -572,7 +572,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags, ...@@ -572,7 +572,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
WARN_ON_ONCE(p == NULL); 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 * 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, ...@@ -633,7 +633,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
bump_cpu_timer(timer, val); bump_cpu_timer(timer, val);
if (val < timer->it.cpu.expires) { if (val < timer->it.cpu.expires) {
old_expires = timer->it.cpu.expires - val; old_expires = timer->it.cpu.expires - val;
old->it_value = ns_to_timespec(old_expires); old->it_value = ns_to_timespec64(old_expires);
} else { } else {
old->it_value.tv_nsec = 1; old->it_value.tv_nsec = 1;
old->it_value.tv_sec = 0; old->it_value.tv_sec = 0;
...@@ -671,7 +671,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags, ...@@ -671,7 +671,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
* Install the new reload setting, and * Install the new reload setting, and
* set up the signal and overrun bookkeeping. * 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, * 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, ...@@ -695,12 +695,12 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
ret = 0; ret = 0;
out: out:
if (old) if (old)
old->it_interval = ns_to_timespec(old_incr); old->it_interval = ns_to_timespec64(old_incr);
return ret; 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; u64 now;
struct task_struct *p = timer->it.cpu.task; 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) ...@@ -710,7 +710,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
/* /*
* Easy part: convert the reload time. * 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. */ if (timer->it.cpu.expires == 0) { /* Timer not armed at all. */
itp->it_value.tv_sec = itp->it_value.tv_nsec = 0; 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) ...@@ -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. * Call the timer disarmed, nothing else to do.
*/ */
timer->it.cpu.expires = 0; 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; return;
} else { } else {
cpu_timer_sample_group(timer->it_clock, p, &now); 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) ...@@ -748,7 +748,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
} }
if (now < timer->it.cpu.expires) { 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 { } else {
/* /*
* The timer should have expired already, but the firing * 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, ...@@ -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, static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
struct timespec *rqtp, struct itimerspec *it) struct timespec *rqtp, struct itimerspec *it)
{ {
struct itimerspec64 it64;
struct k_itimer timer; struct k_itimer timer;
int error; int error;
...@@ -1234,13 +1235,14 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags, ...@@ -1234,13 +1235,14 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
error = posix_cpu_timer_create(&timer); error = posix_cpu_timer_create(&timer);
timer.it_process = current; timer.it_process = current;
if (!error) { if (!error) {
static struct itimerspec zero_it; static struct itimerspec64 zero_it;
memset(it, 0, sizeof *it); memset(it, 0, sizeof *it);
it->it_value = *rqtp; it->it_value = *rqtp;
spin_lock_irq(&timer.it_lock); 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) { if (error) {
spin_unlock_irq(&timer.it_lock); spin_unlock_irq(&timer.it_lock);
return error; return error;
...@@ -1270,7 +1272,9 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags, ...@@ -1270,7 +1272,9 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
* We were interrupted by a signal. * We were interrupted by a signal.
*/ */
*rqtp = ns_to_timespec(timer.it.cpu.expires); *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) { if (!error) {
/* /*
* Timer is now unarmed, deletion can not fail. * Timer is now unarmed, deletion can not fail.
......
...@@ -133,9 +133,9 @@ static struct k_clock posix_clocks[MAX_CLOCKS]; ...@@ -133,9 +133,9 @@ static struct k_clock posix_clocks[MAX_CLOCKS];
static int common_nsleep(const clockid_t, int flags, struct timespec *t, static int common_nsleep(const clockid_t, int flags, struct timespec *t,
struct timespec __user *rmtp); struct timespec __user *rmtp);
static int common_timer_create(struct k_itimer *new_timer); 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, 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 int common_timer_del(struct k_itimer *timer);
static enum hrtimer_restart posix_timer_fn(struct hrtimer *data); 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) ...@@ -734,18 +734,18 @@ static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags)
* report. * report.
*/ */
static void 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; ktime_t now, remaining, iv;
struct hrtimer *timer = &timr->it.real.timer; 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; iv = timr->it.real.interval;
/* interval timer ? */ /* interval timer ? */
if (iv) if (iv)
cur_setting->it_interval = ktime_to_timespec(iv); cur_setting->it_interval = ktime_to_timespec64(iv);
else if (!hrtimer_active(timer) && else if (!hrtimer_active(timer) &&
(timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) (timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE)
return; return;
...@@ -771,13 +771,14 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) ...@@ -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) if ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE)
cur_setting->it_value.tv_nsec = 1; cur_setting->it_value.tv_nsec = 1;
} else } 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. */ /* Get the time remaining on a POSIX.1b interval timer. */
SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id, SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
struct itimerspec __user *, setting) struct itimerspec __user *, setting)
{ {
struct itimerspec64 cur_setting64;
struct itimerspec cur_setting; struct itimerspec cur_setting;
struct k_itimer *timr; struct k_itimer *timr;
struct k_clock *kc; struct k_clock *kc;
...@@ -792,10 +793,11 @@ SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id, ...@@ -792,10 +793,11 @@ SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
if (WARN_ON_ONCE(!kc || !kc->timer_get)) if (WARN_ON_ONCE(!kc || !kc->timer_get))
ret = -EINVAL; ret = -EINVAL;
else else
kc->timer_get(timr, &cur_setting); kc->timer_get(timr, &cur_setting64);
unlock_timer(timr, flags); unlock_timer(timr, flags);
cur_setting = itimerspec64_to_itimerspec(&cur_setting64);
if (!ret && copy_to_user(setting, &cur_setting, sizeof (cur_setting))) if (!ret && copy_to_user(setting, &cur_setting, sizeof (cur_setting)))
return -EFAULT; return -EFAULT;
...@@ -831,7 +833,7 @@ SYSCALL_DEFINE1(timer_getoverrun, timer_t, timer_id) ...@@ -831,7 +833,7 @@ SYSCALL_DEFINE1(timer_getoverrun, timer_t, timer_id)
/* timr->it_lock is taken. */ /* timr->it_lock is taken. */
static int static int
common_timer_set(struct k_itimer *timr, int flags, 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; struct hrtimer *timer = &timr->it.real.timer;
enum hrtimer_mode mode; enum hrtimer_mode mode;
...@@ -860,10 +862,10 @@ common_timer_set(struct k_itimer *timr, int flags, ...@@ -860,10 +862,10 @@ common_timer_set(struct k_itimer *timr, int flags,
hrtimer_init(&timr->it.real.timer, timr->it_clock, mode); hrtimer_init(&timr->it.real.timer, timr->it_clock, mode);
timr->it.real.timer.function = posix_timer_fn; 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 */ /* 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 */ /* SIGEV_NONE timers are not queued ! See common_timer_get */
if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) { if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) {
...@@ -883,21 +885,23 @@ SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags, ...@@ -883,21 +885,23 @@ SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
const struct itimerspec __user *, new_setting, const struct itimerspec __user *, new_setting,
struct itimerspec __user *, old_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; struct itimerspec new_spec, old_spec;
int error = 0; struct k_itimer *timr;
unsigned long flag; unsigned long flag;
struct itimerspec *rtn = old_setting ? &old_spec : NULL;
struct k_clock *kc; struct k_clock *kc;
int error = 0;
if (!new_setting) if (!new_setting)
return -EINVAL; return -EINVAL;
if (copy_from_user(&new_spec, new_setting, sizeof (new_spec))) if (copy_from_user(&new_spec, new_setting, sizeof (new_spec)))
return -EFAULT; return -EFAULT;
new_spec64 = itimerspec_to_itimerspec64(&new_spec);
if (!timespec_valid(&new_spec.it_interval) || if (!timespec64_valid(&new_spec64.it_interval) ||
!timespec_valid(&new_spec.it_value)) !timespec64_valid(&new_spec64.it_value))
return -EINVAL; return -EINVAL;
retry: retry:
timr = lock_timer(timer_id, &flag); timr = lock_timer(timer_id, &flag);
...@@ -908,7 +912,7 @@ SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags, ...@@ -908,7 +912,7 @@ SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
if (WARN_ON_ONCE(!kc || !kc->timer_set)) if (WARN_ON_ONCE(!kc || !kc->timer_set))
error = -EINVAL; error = -EINVAL;
else else
error = kc->timer_set(timr, flags, &new_spec, rtn); error = kc->timer_set(timr, flags, &new_spec64, rtn);
unlock_timer(timr, flag); unlock_timer(timr, flag);
if (error == TIMER_RETRY) { if (error == TIMER_RETRY) {
...@@ -916,6 +920,7 @@ SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags, ...@@ -916,6 +920,7 @@ SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
goto retry; goto retry;
} }
old_spec = itimerspec64_to_itimerspec(&old_spec64);
if (old_setting && !error && if (old_setting && !error &&
copy_to_user(old_setting, &old_spec, sizeof (old_spec))) copy_to_user(old_setting, &old_spec, sizeof (old_spec)))
error = -EFAULT; error = -EFAULT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment