mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 01:10:04 +00:00
![Deepa Dinamani](/assets/img/avatar_default.png)
struct timex is not y2038 safe. Replace all uses of timex with y2038 safe __kernel_timex. Note that struct __kernel_timex is an ABI interface definition. We could define a new structure based on __kernel_timex that is only available internally instead. Right now, there isn't a strong motivation for this as the structure is isolated to a few defined struct timex interfaces and such a structure would be exactly the same as struct timex. The patch was generated by the following coccinelle script: virtual patch @depends on patch forall@ identifier ts; expression e; @@ ( - struct timex ts; + struct __kernel_timex ts; | - struct timex ts = {}; + struct __kernel_timex ts = {}; | - struct timex ts = e; + struct __kernel_timex ts = e; | - struct timex *ts; + struct __kernel_timex *ts; | (memset \| copy_from_user \| copy_to_user \)(..., - sizeof(struct timex)) + sizeof(struct __kernel_timex)) ) @depends on patch forall@ identifier ts; identifier fn; @@ fn(..., - struct timex *ts, + struct __kernel_timex *ts, ...) { ... } @depends on patch forall@ identifier ts; identifier fn; @@ fn(..., - struct timex *ts) { + struct __kernel_timex *ts) { ... } Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com> Cc: linux-alpha@vger.kernel.org Cc: netdev@vger.kernel.org Signed-off-by: Arnd Bergmann <arnd@arndb.de>
234 lines
5.8 KiB
C
234 lines
5.8 KiB
C
#ifndef _LINUX_TIME32_H
|
|
#define _LINUX_TIME32_H
|
|
/*
|
|
* These are all interfaces based on the old time_t definition
|
|
* that overflows in 2038 on 32-bit architectures. New code
|
|
* should use the replacements based on time64_t and timespec64.
|
|
*
|
|
* Any interfaces in here that become unused as we migrate
|
|
* code to time64_t should get removed.
|
|
*/
|
|
|
|
#include <linux/time64.h>
|
|
#include <linux/timex.h>
|
|
|
|
#define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
|
|
|
|
typedef s32 old_time32_t;
|
|
|
|
struct old_timespec32 {
|
|
old_time32_t tv_sec;
|
|
s32 tv_nsec;
|
|
};
|
|
|
|
struct old_timeval32 {
|
|
old_time32_t tv_sec;
|
|
s32 tv_usec;
|
|
};
|
|
|
|
struct old_itimerspec32 {
|
|
struct old_timespec32 it_interval;
|
|
struct old_timespec32 it_value;
|
|
};
|
|
|
|
struct old_utimbuf32 {
|
|
old_time32_t actime;
|
|
old_time32_t modtime;
|
|
};
|
|
|
|
struct old_timex32 {
|
|
u32 modes;
|
|
s32 offset;
|
|
s32 freq;
|
|
s32 maxerror;
|
|
s32 esterror;
|
|
s32 status;
|
|
s32 constant;
|
|
s32 precision;
|
|
s32 tolerance;
|
|
struct old_timeval32 time;
|
|
s32 tick;
|
|
s32 ppsfreq;
|
|
s32 jitter;
|
|
s32 shift;
|
|
s32 stabil;
|
|
s32 jitcnt;
|
|
s32 calcnt;
|
|
s32 errcnt;
|
|
s32 stbcnt;
|
|
s32 tai;
|
|
|
|
s32:32; s32:32; s32:32; s32:32;
|
|
s32:32; s32:32; s32:32; s32:32;
|
|
s32:32; s32:32; s32:32;
|
|
};
|
|
|
|
extern int get_old_timespec32(struct timespec64 *, const void __user *);
|
|
extern int put_old_timespec32(const struct timespec64 *, void __user *);
|
|
extern int get_old_itimerspec32(struct itimerspec64 *its,
|
|
const struct old_itimerspec32 __user *uits);
|
|
extern int put_old_itimerspec32(const struct itimerspec64 *its,
|
|
struct old_itimerspec32 __user *uits);
|
|
struct __kernel_timex;
|
|
int get_old_timex32(struct __kernel_timex *, const struct old_timex32 __user *);
|
|
int put_old_timex32(struct old_timex32 __user *, const struct __kernel_timex *);
|
|
|
|
#if __BITS_PER_LONG == 64
|
|
|
|
/* timespec64 is defined as timespec here */
|
|
static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64)
|
|
{
|
|
return *(const struct timespec *)&ts64;
|
|
}
|
|
|
|
static inline struct timespec64 timespec_to_timespec64(const struct timespec ts)
|
|
{
|
|
return *(const struct timespec64 *)&ts;
|
|
}
|
|
|
|
#else
|
|
static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64)
|
|
{
|
|
struct timespec ret;
|
|
|
|
ret.tv_sec = (time_t)ts64.tv_sec;
|
|
ret.tv_nsec = ts64.tv_nsec;
|
|
return ret;
|
|
}
|
|
|
|
static inline struct timespec64 timespec_to_timespec64(const struct timespec ts)
|
|
{
|
|
struct timespec64 ret;
|
|
|
|
ret.tv_sec = ts.tv_sec;
|
|
ret.tv_nsec = ts.tv_nsec;
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
static inline int timespec_equal(const struct timespec *a,
|
|
const struct timespec *b)
|
|
{
|
|
return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
|
|
}
|
|
|
|
/*
|
|
* lhs < rhs: return <0
|
|
* lhs == rhs: return 0
|
|
* lhs > rhs: return >0
|
|
*/
|
|
static inline int timespec_compare(const struct timespec *lhs, const struct timespec *rhs)
|
|
{
|
|
if (lhs->tv_sec < rhs->tv_sec)
|
|
return -1;
|
|
if (lhs->tv_sec > rhs->tv_sec)
|
|
return 1;
|
|
return lhs->tv_nsec - rhs->tv_nsec;
|
|
}
|
|
|
|
/*
|
|
* Returns true if the timespec is norm, false if denorm:
|
|
*/
|
|
static inline bool timespec_valid(const struct timespec *ts)
|
|
{
|
|
/* Dates before 1970 are bogus */
|
|
if (ts->tv_sec < 0)
|
|
return false;
|
|
/* Can't have more nanoseconds then a second */
|
|
if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* timespec_to_ns - Convert timespec to nanoseconds
|
|
* @ts: pointer to the timespec variable to be converted
|
|
*
|
|
* Returns the scalar nanosecond representation of the timespec
|
|
* parameter.
|
|
*/
|
|
static inline s64 timespec_to_ns(const struct timespec *ts)
|
|
{
|
|
return ((s64) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
|
|
}
|
|
|
|
/**
|
|
* ns_to_timespec - Convert nanoseconds to timespec
|
|
* @nsec: the nanoseconds value to be converted
|
|
*
|
|
* Returns the timespec representation of the nsec parameter.
|
|
*/
|
|
extern struct timespec ns_to_timespec(const s64 nsec);
|
|
|
|
/**
|
|
* timespec_add_ns - Adds nanoseconds to a timespec
|
|
* @a: pointer to timespec to be incremented
|
|
* @ns: unsigned nanoseconds value to be added
|
|
*
|
|
* This must always be inlined because its used from the x86-64 vdso,
|
|
* which cannot call other kernel functions.
|
|
*/
|
|
static __always_inline void timespec_add_ns(struct timespec *a, u64 ns)
|
|
{
|
|
a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, NSEC_PER_SEC, &ns);
|
|
a->tv_nsec = ns;
|
|
}
|
|
|
|
static inline unsigned long mktime(const unsigned int year,
|
|
const unsigned int mon, const unsigned int day,
|
|
const unsigned int hour, const unsigned int min,
|
|
const unsigned int sec)
|
|
{
|
|
return mktime64(year, mon, day, hour, min, sec);
|
|
}
|
|
|
|
static inline bool timeval_valid(const struct timeval *tv)
|
|
{
|
|
/* Dates before 1970 are bogus */
|
|
if (tv->tv_sec < 0)
|
|
return false;
|
|
|
|
/* Can't have more microseconds then a second */
|
|
if (tv->tv_usec < 0 || tv->tv_usec >= USEC_PER_SEC)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* timeval_to_ns - Convert timeval to nanoseconds
|
|
* @ts: pointer to the timeval variable to be converted
|
|
*
|
|
* Returns the scalar nanosecond representation of the timeval
|
|
* parameter.
|
|
*/
|
|
static inline s64 timeval_to_ns(const struct timeval *tv)
|
|
{
|
|
return ((s64) tv->tv_sec * NSEC_PER_SEC) +
|
|
tv->tv_usec * NSEC_PER_USEC;
|
|
}
|
|
|
|
/**
|
|
* ns_to_timeval - Convert nanoseconds to timeval
|
|
* @nsec: the nanoseconds value to be converted
|
|
*
|
|
* Returns the timeval representation of the nsec parameter.
|
|
*/
|
|
extern struct timeval ns_to_timeval(const s64 nsec);
|
|
extern struct __kernel_old_timeval ns_to_kernel_old_timeval(s64 nsec);
|
|
|
|
/*
|
|
* Old names for the 32-bit time_t interfaces, these will be removed
|
|
* when everything uses the new names.
|
|
*/
|
|
#define compat_time_t old_time32_t
|
|
#define compat_timeval old_timeval32
|
|
#define compat_timespec old_timespec32
|
|
#define compat_itimerspec old_itimerspec32
|
|
#define ns_to_compat_timeval ns_to_old_timeval32
|
|
#define get_compat_itimerspec64 get_old_itimerspec32
|
|
#define put_compat_itimerspec64 put_old_itimerspec32
|
|
#define compat_get_timespec64 get_old_timespec32
|
|
#define compat_put_timespec64 put_old_timespec32
|
|
|
|
#endif
|