2015-06-12 08:14:18

by Baolin Wang

[permalink] [raw]
Subject: [PATCH v5 23/24] posix-cpu-timers: Convert to y2038 safe callbacks

The clock_getres()/clock_get()/clock_set()/timer_set()/timer_get()
callbacks in struct k_clock are not year 2038 safe on 32bit systems,
and it need convert to safe callbacks which use struct timespec64
or struct itimerspec64.

Signed-off-by: Baolin Wang <[email protected]>
---
kernel/time/posix-cpu-timers.c | 84 +++++++++++++++++++++-------------------
1 file changed, 45 insertions(+), 39 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 892e3da..1d4605c 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -52,7 +52,7 @@ static int check_clock(const clockid_t which_clock)
}

static inline unsigned long long
-timespec_to_sample(const clockid_t which_clock, const struct timespec *tp)
+timespec64_to_sample(const clockid_t which_clock, const struct timespec64 *tp)
{
unsigned long long ret;

@@ -60,19 +60,19 @@ timespec_to_sample(const clockid_t which_clock, const struct timespec *tp)
if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
ret = (unsigned long long)tp->tv_sec * NSEC_PER_SEC + tp->tv_nsec;
} else {
- ret = cputime_to_expires(timespec_to_cputime(tp));
+ ret = cputime_to_expires(timespec64_to_cputime(tp));
}
return ret;
}

-static void sample_to_timespec(const clockid_t which_clock,
+static void sample_to_timespec64(const clockid_t which_clock,
unsigned long long expires,
- struct timespec *tp)
+ struct timespec64 *tp)
{
if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED)
- *tp = ns_to_timespec(expires);
+ *tp = ns_to_timespec64(expires);
else
- cputime_to_timespec((__force cputime_t)expires, tp);
+ cputime_to_timespec64((__force cputime_t)expires, tp);
}

/*
@@ -141,7 +141,7 @@ static inline unsigned long long virt_ticks(struct task_struct *p)
}

static int
-posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp)
+posix_cpu_clock_getres(const clockid_t which_clock, struct timespec64 *tp)
{
int error = check_clock(which_clock);
if (!error) {
@@ -160,7 +160,7 @@ posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp)
}

static int
-posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *tp)
+posix_cpu_clock_set(const clockid_t which_clock, const struct timespec64 *tp)
{
/*
* You can never reset a CPU clock, but we check for other errors
@@ -286,7 +286,7 @@ static int cpu_clock_sample_group(const clockid_t which_clock,

static int posix_cpu_clock_get_task(struct task_struct *tsk,
const clockid_t which_clock,
- struct timespec *tp)
+ struct timespec64 *tp)
{
int err = -EINVAL;
unsigned long long rtn;
@@ -300,13 +300,14 @@ static int posix_cpu_clock_get_task(struct task_struct *tsk,
}

if (!err)
- sample_to_timespec(which_clock, rtn, tp);
+ sample_to_timespec64(which_clock, rtn, tp);

return err;
}


-static int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp)
+static int posix_cpu_clock_get(const clockid_t which_clock,
+ struct timespec64 *tp)
{
const pid_t pid = CPUCLOCK_PID(which_clock);
int err = -EINVAL;
@@ -622,7 +623,7 @@ static inline void posix_cpu_timer_kick_nohz(void) { }
* 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;
@@ -632,7 +633,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,

WARN_ON_ONCE(p == NULL);

- new_expires = timespec_to_sample(timer->it_clock, &new->it_value);
+ new_expires = timespec64_to_sample(timer->it_clock, &new->it_value);

/*
* Protect against sighand release/switch in exit/exec and p->cpu_timers
@@ -693,7 +694,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;
- sample_to_timespec(timer->it_clock,
+ sample_to_timespec64(timer->it_clock,
old_expires,
&old->it_value);
} else {
@@ -733,7 +734,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_sample(timer->it_clock,
+ timer->it.cpu.incr = timespec64_to_sample(timer->it_clock,
&new->it_interval);

/*
@@ -758,7 +759,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
ret = 0;
out:
if (old) {
- sample_to_timespec(timer->it_clock,
+ sample_to_timespec64(timer->it_clock,
old_incr, &old->it_interval);
}
if (!ret)
@@ -766,7 +767,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
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)
{
unsigned long long now;
struct task_struct *p = timer->it.cpu.task;
@@ -776,7 +777,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
/*
* Easy part: convert the reload time.
*/
- sample_to_timespec(timer->it_clock,
+ sample_to_timespec64(timer->it_clock,
timer->it.cpu.incr, &itp->it_interval);

if (timer->it.cpu.expires == 0) { /* Timer not armed at all. */
@@ -806,7 +807,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;
- sample_to_timespec(timer->it_clock, timer->it.cpu.expires,
+ sample_to_timespec64(timer->it_clock, timer->it.cpu.expires,
&itp->it_value);
} else {
cpu_timer_sample_group(timer->it_clock, p, &now);
@@ -815,7 +816,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
}

if (now < timer->it.cpu.expires) {
- sample_to_timespec(timer->it_clock,
+ sample_to_timespec64(timer->it_clock,
timer->it.cpu.expires - now,
&itp->it_value);
} else {
@@ -1269,6 +1270,8 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
struct timespec *rqtp, struct itimerspec *it)
{
struct k_itimer timer;
+ struct timespec64 ts64;
+ struct itimerspec64 it64;
int error;

/*
@@ -1281,13 +1284,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;
@@ -1316,13 +1320,15 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
/*
* We were interrupted by a signal.
*/
- sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp);
- error = posix_cpu_timer_set(&timer, 0, &zero_it, it);
+ sample_to_timespec64(which_clock, timer.it.cpu.expires, &ts64);
+ *rqtp = timespec64_to_timespec(ts64);
+ error = posix_cpu_timer_set(&timer, 0, &zero_it, &it64);
if (!error) {
/*
* Timer is now unarmed, deletion can not fail.
*/
posix_cpu_timer_del(&timer);
+ *it = itimerspec64_to_itimerspec(&it64);
}
spin_unlock_irq(&timer.it_lock);

@@ -1416,12 +1422,12 @@ static long posix_cpu_nsleep_restart(struct restart_block *restart_block)
#define THREAD_CLOCK MAKE_THREAD_CPUCLOCK(0, CPUCLOCK_SCHED)

static int process_cpu_clock_getres(const clockid_t which_clock,
- struct timespec *tp)
+ struct timespec64 *tp)
{
return posix_cpu_clock_getres(PROCESS_CLOCK, tp);
}
static int process_cpu_clock_get(const clockid_t which_clock,
- struct timespec *tp)
+ struct timespec64 *tp)
{
return posix_cpu_clock_get(PROCESS_CLOCK, tp);
}
@@ -1441,12 +1447,12 @@ static long process_cpu_nsleep_restart(struct restart_block *restart_block)
return -EINVAL;
}
static int thread_cpu_clock_getres(const clockid_t which_clock,
- struct timespec *tp)
+ struct timespec64 *tp)
{
return posix_cpu_clock_getres(THREAD_CLOCK, tp);
}
static int thread_cpu_clock_get(const clockid_t which_clock,
- struct timespec *tp)
+ struct timespec64 *tp)
{
return posix_cpu_clock_get(THREAD_CLOCK, tp);
}
@@ -1457,37 +1463,37 @@ static int thread_cpu_timer_create(struct k_itimer *timer)
}

struct k_clock clock_posix_cpu = {
- .clock_getres = posix_cpu_clock_getres,
- .clock_set = posix_cpu_clock_set,
- .clock_get = posix_cpu_clock_get,
+ .clock_getres64 = posix_cpu_clock_getres,
+ .clock_set64 = posix_cpu_clock_set,
+ .clock_get64 = posix_cpu_clock_get,
.timer_create = posix_cpu_timer_create,
.nsleep = posix_cpu_nsleep,
.nsleep_restart = posix_cpu_nsleep_restart,
- .timer_set = posix_cpu_timer_set,
+ .timer_set64 = posix_cpu_timer_set,
.timer_del = posix_cpu_timer_del,
- .timer_get = posix_cpu_timer_get,
+ .timer_get64 = posix_cpu_timer_get,
};

static __init int init_posix_cpu_timers(void)
{
struct k_clock process = {
- .clock_getres = process_cpu_clock_getres,
- .clock_get = process_cpu_clock_get,
+ .clock_getres64 = process_cpu_clock_getres,
+ .clock_get64 = process_cpu_clock_get,
.timer_create = process_cpu_timer_create,
.nsleep = process_cpu_nsleep,
.nsleep_restart = process_cpu_nsleep_restart,
};
struct k_clock thread = {
- .clock_getres = thread_cpu_clock_getres,
- .clock_get = thread_cpu_clock_get,
+ .clock_getres64 = thread_cpu_clock_getres,
+ .clock_get64 = thread_cpu_clock_get,
.timer_create = thread_cpu_timer_create,
};
- struct timespec ts;
+ struct timespec64 ts;

posix_timers_register_clock(CLOCK_PROCESS_CPUTIME_ID, &process);
posix_timers_register_clock(CLOCK_THREAD_CPUTIME_ID, &thread);

- cputime_to_timespec(cputime_one_jiffy, &ts);
+ cputime_to_timespec64(cputime_one_jiffy, &ts);
onecputick = ts.tv_nsec;
WARN_ON(ts.tv_sec != 0);

--
1.7.9.5


2015-06-12 08:14:30

by Baolin Wang

[permalink] [raw]
Subject: [PATCH v5 24/24] k_clock: Remove y2038 unsafe callbacks

All of the k_clock users have been converted to the y2038 safe methods,
this patch removes the older methods with timepsec/itimerspec type,
as a result the k_clock structure is ready for the year 2038.

Signed-off-by: Baolin Wang <[email protected]>
---
include/linux/posix-timers.h | 9 -----
kernel/time/posix-timers.c | 90 +++---------------------------------------
2 files changed, 5 insertions(+), 94 deletions(-)

diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 35786c5..7c3dae2 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -97,29 +97,20 @@ struct k_itimer {
};

struct k_clock {
- int (*clock_getres) (const clockid_t which_clock, struct timespec *tp);
int (*clock_getres64) (const clockid_t which_clock, struct timespec64 *tp);
- int (*clock_set) (const clockid_t which_clock,
- const struct timespec *tp);
int (*clock_set64) (const clockid_t which_clock,
const struct timespec64 *tp);
- int (*clock_get) (const clockid_t which_clock, struct timespec * tp);
int (*clock_get64) (const clockid_t which_clock, struct timespec64 *tp);
int (*clock_adj) (const clockid_t which_clock, struct timex *tx);
int (*timer_create) (struct k_itimer *timer);
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_set64) (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_get64) (struct k_itimer *timr,
struct itimerspec64 *cur_setting);
};
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 80f630a..e9e6e29 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -140,7 +140,6 @@ static int common_timer_del(struct k_itimer *timer);
static enum hrtimer_restart posix_timer_fn(struct hrtimer *data);

static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags);
-static struct k_clock *clockid_to_kclock(const clockid_t id);

#define lock_timer(tid, flags) \
({ struct k_itimer *__timr; \
@@ -550,73 +549,6 @@ static struct pid *good_sigevent(sigevent_t * event)
return task_pid(rtn);
}

-static void default_timer_get64(struct k_itimer *timr,
- struct itimerspec64 *cur_setting64)
-{
- struct itimerspec cur_setting;
- struct k_clock *kc = clockid_to_kclock(timr->it_clock);
-
- kc->timer_get(timr, &cur_setting);
- *cur_setting64 = itimerspec_to_itimerspec64(&cur_setting);
-}
-
-static int default_timer_set64(struct k_itimer *timr, int flags,
- struct itimerspec64 *new_setting64,
- struct itimerspec64 *old_setting64)
-{
- struct k_clock *kc = clockid_to_kclock(timr->it_clock);
- struct itimerspec new_setting, old_setting;
- struct itimerspec *rtn = old_setting64 ? &old_setting : NULL;
- int ret;
-
- new_setting = itimerspec64_to_itimerspec(new_setting64);
- ret = kc->timer_set(timr, flags, &new_setting, rtn);
- if (!ret && old_setting64)
- *old_setting64 = itimerspec_to_itimerspec64(&old_setting);
-
- return ret;
-}
-
-static int default_clock_set64(const clockid_t which_clock,
- const struct timespec64 *tp64)
-{
- struct k_clock *kc = clockid_to_kclock(which_clock);
- struct timespec tp;
- int ret;
-
- tp = timespec64_to_timespec(*tp64);
- ret = kc->clock_set(which_clock, &tp);
- return ret;
-}
-
-static int default_clock_get64(const clockid_t which_clock,
- struct timespec64 *tp64)
-{
- struct k_clock *kc = clockid_to_kclock(which_clock);
- struct timespec tp;
- int ret;
-
- ret = kc->clock_get(which_clock, &tp);
- if (!ret)
- *tp64 = timespec_to_timespec64(tp);
-
- return ret;
-}
-
-static int default_clock_getres64(const clockid_t which_clock,
- struct timespec64 *tp64)
-{
- struct k_clock *kc = clockid_to_kclock(which_clock);
- struct timespec tp;
- int ret;
-
- ret = kc->clock_getres(which_clock, &tp);
- if (!ret)
- *tp64 = timespec_to_timespec64(tp);
-
- return 0;
-}
-
void posix_timers_register_clock(const clockid_t clock_id,
struct k_clock *new_clock)
{
@@ -626,28 +558,17 @@ void posix_timers_register_clock(const clockid_t clock_id,
return;
}

- if (!new_clock->clock_get && !new_clock->clock_get64) {
- printk(KERN_WARNING "POSIX clock id %d lacks clock_get() and clock_get64()\n",
+ if (!new_clock->clock_get64) {
+ printk(KERN_WARNING "POSIX clock id %d lacks clock_get64()\n",
clock_id);
return;
}
- if (!new_clock->clock_getres && !new_clock->clock_getres64) {
- printk(KERN_WARNING "POSIX clock id %d lacks clock_getres() and clock_getres64()\n",
+ if (!new_clock->clock_getres64) {
+ printk(KERN_WARNING "POSIX clock id %d lacks clock_getres64()\n",
clock_id);
return;
}

- if (new_clock->timer_get && !new_clock->timer_get64)
- new_clock->timer_get64 = default_timer_get64;
- if (new_clock->timer_set && !new_clock->timer_set64)
- new_clock->timer_set64 = default_timer_set64;
- if (new_clock->clock_set && !new_clock->clock_set64)
- new_clock->clock_set64 = default_clock_set64;
- if (new_clock->clock_get && !new_clock->clock_get64)
- new_clock->clock_get64 = default_clock_get64;
- if (new_clock->clock_getres && !new_clock->clock_getres64)
- new_clock->clock_getres64 = default_clock_getres64;
-
posix_clocks[clock_id] = *new_clock;
}
EXPORT_SYMBOL_GPL(posix_timers_register_clock);
@@ -694,8 +615,7 @@ static struct k_clock *clockid_to_kclock(const clockid_t id)
return (id & CLOCKFD_MASK) == CLOCKFD ?
&clock_posix_dynamic : &clock_posix_cpu;

- if (id >= MAX_CLOCKS || (!posix_clocks[id].clock_getres
- && !posix_clocks[id].clock_getres64))
+ if (id >= MAX_CLOCKS || !posix_clocks[id].clock_getres64)
return NULL;
return &posix_clocks[id];
}
--
1.7.9.5