In the patch series I posted recently [1], I introduce new system calls to deal
with modified data structures, but left the question open on how these should
be best accessed from libc. The patches introduce a new __kernel_time64_t type
and based on that five new data structured: struct __kernel_timespec,
struct __kernel_itimerspec, struct __kernel_stat, struct __kernel_rusage,
and struct __kernel_timex. This works fine for the case when all libc
implementations provide their own definitions to user space, but not for
the simplest case (e.g. klibc) where the user-visible structures come directly
from the kernel uapi headers.
I still don't know what model the various libc developers prefer, so here is
an alternative approach, as a patch on top of the previous series:
Now, we rename the original structures to struct __old_kernel_*, and use a
macro to define either the __old_kernel_* or the __kernel_* structure name
to the name we actually want in user space, based on a __KERNEL_TIME_BITS
macro that can be set to either 32 or 64 for 32-bit architectures by
the libc. Depending on that macro, the compiler will either see one
of these combinations (for each of the five structures):
a) __BITS_PER_LONG == 32 && __KERNEL_TIME_BITS == 32:
struct timespec based on 32-bit __kernel_time_t
struct __kernel_timespec based on 64-bit __kernel_time64_t
b) __BITS_PER_LONG == 64 && __KERNEL_TIME_BITS == 64:
struct timespec based on 64-bit __kernel_time_t
struct __kernel_timespec based on 64-bit __kernel_time64_t
c) __BITS_PER_LONG == 32 && __KERNEL_TIME_BITS == 64:
struct __old_kernel_timespec based on 32-bit __kernel_time_t
struct timespec based on 64-bit __kernel_time64_t
Would this work for everyone? Any alternative suggestions?
Arnd
[1] http://git.kernel.org/cgit/linux/kernel/git/arnd/playground.git/log/?h=y203…https://lwn.net/Articles/643407/
diff --git a/include/uapi/asm-generic/bitsperlong.h b/include/uapi/asm-generic/bitsperlong.h
index 23e6c416b85f..ecdaf4f77f35 100644
--- a/include/uapi/asm-generic/bitsperlong.h
+++ b/include/uapi/asm-generic/bitsperlong.h
@@ -12,4 +12,13 @@
#define __BITS_PER_LONG 32
#endif
+/*
+ * Traditionally we define defines 'time_t' as 'long', but we need to
+ * migrate to a 64-bit type until 2038. This one is designed to be
+ * overridden by user space if it's prepared to handle 64-bit time_t.
+ */
+#ifndef __KERNEL_TIME_BITS
+#define __KERNEL_TIME_BITS __BITS_PER_LONG
+#endif
+
#endif /* _UAPI__ASM_GENERIC_BITS_PER_LONG */
diff --git a/include/uapi/asm-generic/kernel_stat.h b/include/uapi/asm-generic/kernel_stat.h
index d1db22583046..3693496c78aa 100644
--- a/include/uapi/asm-generic/kernel_stat.h
+++ b/include/uapi/asm-generic/kernel_stat.h
@@ -1,6 +1,14 @@
#ifndef __ASM_GENERIC_KERNEL_STAT_H
#define __ASM_GENERIC_KERNEL_STAT_H
+#include <asm/bitsperlong.h>
+
+#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
+#define __old_kernel_stat2 stat
+#else
+#define __kernel_stat stat
+#endif
+
/*
* The new structure that works on both 32-bit and 64-bit and survives y2038
* The layout matches 'struct stat' from asm-generic/stat.h on 64-bit
diff --git a/include/uapi/asm-generic/stat.h b/include/uapi/asm-generic/stat.h
index 64c32ba7c1a9..f66b28b96c8d 100644
--- a/include/uapi/asm-generic/stat.h
+++ b/include/uapi/asm-generic/stat.h
@@ -22,7 +22,7 @@
#define STAT_HAVE_NSEC 1
-struct stat {
+struct __old_kernel_stat2 {
unsigned long st_dev; /* Device. */
unsigned long st_ino; /* File serial number. */
unsigned int st_mode; /* File mode. */
diff --git a/include/uapi/linux/resource.h b/include/uapi/linux/resource.h
index c4f3ba44db00..9a3876cc4436 100644
--- a/include/uapi/linux/resource.h
+++ b/include/uapi/linux/resource.h
@@ -3,10 +3,16 @@
#include <linux/time.h>
#include <linux/types.h>
+#include <asm/bitsperlong.h>
/*
* Resource control/accounting header file for linux
*/
+#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
+#define __old_kernel_rusage rusage
+#else
+#define __kernel_rusage rusage
+#endif
/*
* Definition of struct rusage taken from BSD 4.3 Reno
@@ -20,7 +26,7 @@
#define RUSAGE_BOTH (-2) /* sys_wait4() uses this */
#define RUSAGE_THREAD 1 /* only the calling thread */
-struct rusage {
+struct __old_kernel_rusage {
struct timeval ru_utime; /* user time used */
struct timeval ru_stime; /* system time used */
__kernel_long_t ru_maxrss; /* maximum resident set size */
diff --git a/include/uapi/linux/time.h b/include/uapi/linux/time.h
index 72d894df3013..b3988606128f 100644
--- a/include/uapi/linux/time.h
+++ b/include/uapi/linux/time.h
@@ -6,11 +6,24 @@
#ifndef _STRUCT_TIMESPEC
#define _STRUCT_TIMESPEC
-struct timespec {
+
+#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
+#define __old_kernel_timespec timespec
+#else
+#define __kernel_timespec timespec
+#endif
+#endif
+
+#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
+#define __old_kernel_itimerspec itimerspec
+#else
+#define __kernel_itimerspec itimerspec
+#endif
+
+struct __old_kernel_timespec {
__kernel_time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
-#endif
struct timeval {
__kernel_time_t tv_sec; /* seconds */
@@ -31,7 +44,7 @@ struct timezone {
#define ITIMER_VIRTUAL 1
#define ITIMER_PROF 2
-struct itimerspec {
+struct __old_kernel_itimerspec {
struct timespec it_interval; /* timer period */
struct timespec it_value; /* timer expiration */
};
diff --git a/include/uapi/linux/timex.h b/include/uapi/linux/timex.h
index 9b131f107ada..3cfa50caa77d 100644
--- a/include/uapi/linux/timex.h
+++ b/include/uapi/linux/timex.h
@@ -54,14 +54,22 @@
#define _UAPI_LINUX_TIMEX_H
#include <linux/time.h>
+#include <asm/bitsperlong.h>
+
+#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
+#define __old_kernel_timex timex
+#else
+#define __kernel_timex timex
+#endif
#define NTP_API 4 /* NTP API version */
+
/*
* syscall interface - used (mainly by NTP daemon)
* to discipline kernel clock oscillator
*/
-struct timex {
+struct __old_kernel_timex {
unsigned int modes; /* mode selector */
__kernel_long_t offset; /* time offset (usec) */
__kernel_long_t freq; /* frequency offset (scaled ppm) */
diff --git a/arch/arm/include/uapi/asm/stat.h b/arch/arm/include/uapi/asm/stat.h
index 537a12553dd8..18ff0e2383ad 100644
--- a/arch/arm/include/uapi/asm/stat.h
+++ b/arch/arm/include/uapi/asm/stat.h
@@ -19,7 +19,7 @@ struct __old_kernel_stat {
#define STAT_HAVE_NSEC
-struct stat {
+struct __old_kernel_stat2 {
#if defined(__ARMEB__)
unsigned short st_dev;
unsigned short __pad1;
diff --git a/arch/avr32/include/uapi/asm/stat.h b/arch/avr32/include/uapi/asm/stat.h
index 2b528ca17985..5df389890f8a 100644
--- a/arch/avr32/include/uapi/asm/stat.h
+++ b/arch/avr32/include/uapi/asm/stat.h
@@ -24,7 +24,7 @@ struct __old_kernel_stat {
unsigned long st_ctime;
};
-struct stat {
+struct __old_kernel_stat2 {
unsigned long st_dev;
unsigned long st_ino;
unsigned short st_mode;
diff --git a/arch/blackfin/include/uapi/asm/stat.h b/arch/blackfin/include/uapi/asm/stat.h
index 99ee343aec23..cd417baf51fc 100644
--- a/arch/blackfin/include/uapi/asm/stat.h
+++ b/arch/blackfin/include/uapi/asm/stat.h
@@ -9,7 +9,7 @@
#include <asm-generic/kernel_stat.h>
-struct stat {
+struct __old_kernel_stat2 {
unsigned short st_dev;
unsigned short __pad1;
unsigned long st_ino;
diff --git a/arch/cris/include/uapi/asm/stat.h b/arch/cris/include/uapi/asm/stat.h
index 4837884cd2d3..38d1dba3ea6a 100644
--- a/arch/cris/include/uapi/asm/stat.h
+++ b/arch/cris/include/uapi/asm/stat.h
@@ -22,7 +22,7 @@ struct __old_kernel_stat {
#define STAT_HAVE_NSEC 1
-struct stat {
+struct __old_kernel_stat2 {
unsigned long st_dev;
unsigned long st_ino;
unsigned short st_mode;
diff --git a/arch/frv/include/uapi/asm/stat.h b/arch/frv/include/uapi/asm/stat.h
index 5448b198fbb6..5ff15ccef6c3 100644
--- a/arch/frv/include/uapi/asm/stat.h
+++ b/arch/frv/include/uapi/asm/stat.h
@@ -18,7 +18,7 @@ struct __old_kernel_stat {
};
/* This matches struct stat in uClibc/glibc. */
-struct stat {
+struct __old_kernel_stat2 {
unsigned char __pad1[6];
unsigned short st_dev;
diff --git a/arch/m32r/include/uapi/asm/stat.h b/arch/m32r/include/uapi/asm/stat.h
index d0ffa70f73c0..03531561b8cd 100644
--- a/arch/m32r/include/uapi/asm/stat.h
+++ b/arch/m32r/include/uapi/asm/stat.h
@@ -20,7 +20,7 @@ struct __old_kernel_stat {
#define STAT_HAVE_NSEC 1
-struct stat {
+struct __old_kernel_stat2 {
unsigned short st_dev;
unsigned short __pad1;
unsigned long st_ino;
diff --git a/arch/m68k/include/uapi/asm/stat.h b/arch/m68k/include/uapi/asm/stat.h
index 6f455db47b4e..f7936ed51c09 100644
--- a/arch/m68k/include/uapi/asm/stat.h
+++ b/arch/m68k/include/uapi/asm/stat.h
@@ -17,7 +17,7 @@ struct __old_kernel_stat {
unsigned long st_ctime;
};
-struct stat {
+struct __old_kernel_stat2 {
unsigned short st_dev;
unsigned short __pad1;
unsigned long st_ino;
diff --git a/arch/mips/include/uapi/asm/stat.h b/arch/mips/include/uapi/asm/stat.h
index 53e58fbd83fa..c0b82a1ccf17 100644
--- a/arch/mips/include/uapi/asm/stat.h
+++ b/arch/mips/include/uapi/asm/stat.h
@@ -16,7 +16,7 @@
#if (_MIPS_SIM == _MIPS_SIM_ABI32) || (_MIPS_SIM == _MIPS_SIM_NABI32)
-struct stat {
+struct __old_kernel_stat2 {
unsigned st_dev;
long st_pad1[3]; /* Reserved for network id */
ino_t st_ino;
@@ -90,7 +90,7 @@ struct stat64 {
#if _MIPS_SIM == _MIPS_SIM_ABI64
/* The memory layout is the same as of struct stat64 of the 32-bit kernel. */
-struct stat {
+struct __old_kernel_stat2 {
unsigned int st_dev;
unsigned int st_pad0[3]; /* Reserved for st_dev expansion */
diff --git a/arch/mn10300/include/uapi/asm/stat.h b/arch/mn10300/include/uapi/asm/stat.h
index af3b4d6b7b7a..ab507885dd05 100644
--- a/arch/mn10300/include/uapi/asm/stat.h
+++ b/arch/mn10300/include/uapi/asm/stat.h
@@ -17,7 +17,7 @@ struct __old_kernel_stat {
unsigned long st_ctime;
};
-struct stat {
+struct __old_kernel_stat2 {
unsigned long st_dev;
unsigned long st_ino;
unsigned short st_mode;
diff --git a/arch/parisc/include/uapi/asm/stat.h b/arch/parisc/include/uapi/asm/stat.h
index f06ce7ba0115..d632b5453628 100644
--- a/arch/parisc/include/uapi/asm/stat.h
+++ b/arch/parisc/include/uapi/asm/stat.h
@@ -4,7 +4,7 @@
#include <linux/types.h>
#include <asm-generic/kernel_stat.h>
-struct stat {
+struct __old_kernel_stat2 {
unsigned int st_dev; /* dev_t is 32 bits on parisc */
unsigned int st_ino; /* 32 bits */
unsigned short st_mode; /* 16 bits */
diff --git a/arch/powerpc/include/uapi/asm/stat.h b/arch/powerpc/include/uapi/asm/stat.h
index 248d8072267f..4b62b30ed12c 100644
--- a/arch/powerpc/include/uapi/asm/stat.h
+++ b/arch/powerpc/include/uapi/asm/stat.h
@@ -7,6 +7,13 @@
* 2 of the License, or (at your option) any later version.
*/
#include <linux/types.h>
+#include <asm/bitsperlong.h>
+
+#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
+#define __old_kernel_stat2 stat
+#else
+#define __kernel_stat stat
+#endif
#define STAT_HAVE_NSEC 1
@@ -26,7 +33,7 @@ struct __old_kernel_stat {
};
#endif /* !__powerpc64__ */
-struct stat {
+struct __old_kernel_stat2 {
unsigned long st_dev;
ino_t st_ino;
#ifdef __powerpc64__
@@ -78,7 +85,7 @@ struct stat64 {
unsigned int __unused5;
};
-/* this matches the powerpc64 'struct stat' for compat tasks */
+/* this matches the powerpc64 'struct __old_kernel_stat2' for compat tasks */
struct __kernel_stat {
unsigned long long st_dev;
unsigned long long st_ino;
@@ -101,6 +107,5 @@ struct __kernel_stat {
unsigned long long __unused5;
unsigned long long __unused6;
};
#endif /* _ASM_POWERPC_STAT_H */
diff --git a/arch/s390/include/uapi/asm/stat.h b/arch/s390/include/uapi/asm/stat.h
index d4c2711249dd..5f40f51ecdab 100644
--- a/arch/s390/include/uapi/asm/stat.h
+++ b/arch/s390/include/uapi/asm/stat.h
@@ -7,6 +7,14 @@
#ifndef _S390_STAT_H
#define _S390_STAT_H
+#include <asm/bitsperlong.h>
+
+#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
+#define __old_kernel_stat2 stat
+#else
+#define __kernel_stat stat
+#endif
+
#ifndef __s390x__
struct __old_kernel_stat {
unsigned short st_dev;
@@ -22,7 +30,7 @@ struct __old_kernel_stat {
unsigned long st_ctime;
};
-struct stat {
+struct __old_kernel_stat2 {
unsigned short st_dev;
unsigned short __pad1;
unsigned long st_ino;
@@ -75,7 +83,7 @@ struct stat64 {
#else /* __s390x__ */
-struct stat {
+struct __old_kernel_stat {
unsigned long st_dev;
unsigned long st_ino;
unsigned long st_nlink;
diff --git a/arch/sh/include/uapi/asm/stat.h b/arch/sh/include/uapi/asm/stat.h
index a13ffbcccd50..0d3358037558 100644
--- a/arch/sh/include/uapi/asm/stat.h
+++ b/arch/sh/include/uapi/asm/stat.h
@@ -18,7 +18,7 @@ struct __old_kernel_stat {
};
#if defined(__SH5__) || defined(CONFIG_CPU_SH5)
-struct stat {
+struct __old_kernel_stat2 {
unsigned short st_dev;
unsigned short __pad1;
unsigned long st_ino;
@@ -77,7 +77,7 @@ struct stat64 {
unsigned long __unused2;
};
#else
-struct stat {
+struct __old_kernel_stat2 {
unsigned long st_dev;
unsigned long st_ino;
unsigned short st_mode;
diff --git a/arch/sparc/include/uapi/asm/stat.h b/arch/sparc/include/uapi/asm/stat.h
index 6d19c7bdc641..8ace4436a31f 100644
--- a/arch/sparc/include/uapi/asm/stat.h
+++ b/arch/sparc/include/uapi/asm/stat.h
@@ -2,6 +2,13 @@
#define __SPARC_STAT_H
#include <linux/types.h>
+#include <asm/bitsperlong.h>
+
+#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
+#define __old_kernel_stat2 stat
+#else
+#define __kernel_stat stat
+#endif
#if defined(__sparc__) && defined(__arch64__)
/* 64 bit sparc */
@@ -48,7 +55,8 @@ struct stat64 {
#else
/* 32 bit sparc */
-struct stat {
+
+struct __old_kernel_stat2 {
unsigned short st_dev;
ino_t st_ino;
mode_t st_mode;
diff --git a/arch/x86/include/uapi/asm/stat.h b/arch/x86/include/uapi/asm/stat.h
index 5d5754fc3d36..5fa5beeafd86 100644
--- a/arch/x86/include/uapi/asm/stat.h
+++ b/arch/x86/include/uapi/asm/stat.h
@@ -2,11 +2,18 @@
#define _ASM_X86_STAT_H
#include <asm/posix_types.h>
+#include <asm/bitsperlong.h>
#define STAT_HAVE_NSEC 1
+#if __KERNEL_TIME_BITS == 32 || __BITS_PER_LONG == 64
+#define __old_kernel_stat2 stat
+#else
+#define __kernel_stat stat
+#endif
+
#ifdef __i386__
-struct stat {
+struct __old_kernel_stat2 {
unsigned long st_dev;
unsigned long st_ino;
unsigned short st_mode;
@@ -73,7 +80,7 @@ struct stat64 {
#else /* __i386__ */
-struct stat {
+struct __old_kernel_stat2 {
__kernel_ulong_t st_dev;
__kernel_ulong_t st_ino;
__kernel_ulong_t st_nlink;
diff --git a/arch/xtensa/include/uapi/asm/stat.h b/arch/xtensa/include/uapi/asm/stat.h
index 8d9c1d9d82d0..94e40d22eb88 100644
--- a/arch/xtensa/include/uapi/asm/stat.h
+++ b/arch/xtensa/include/uapi/asm/stat.h
@@ -15,7 +15,7 @@
#define STAT_HAVE_NSEC 1
-struct stat {
+struct __old_kernel_stat2 {
unsigned long st_dev;
unsigned long st_ino;
unsigned int st_mode;
This patch series changes the 32-bit time types (timespec/itimerspec) to
the 64-bit types (timespec64/itimerspec64), since 32-bit time types will
break in the year 2038.
This patch series introduces new methods with timespec64/itimerspec64 type,
and removes the old ones with timespec/itimerspec type for posix_clock_operations
and k_clock structure.
timekeeping: Introduce struct itimerspec64.
timekeeping: Introduce current_kernel_time64().
timekeeping: Change timekeeping_clocktai() with timespec64 type.
hrtimer: Introduce hrtimer_get_res64().
security: Introduce security_settime64().
time: Introduce do_sys_settimeofday64().
time: Introduce jiffies_to_timespec64()/timespec64_to_jiffies().
cputime: Introduce cputime_to_timespec64()/timespec64_to_cputime().
posix-timers: Split up timer_gettime()/timer_settime()/clock_settime()/
clock_gettime()/clock_getres().
posix-timers: Convert timer_gettime()/timer_settime()/clock_settime()/
clock_gettime()/clock_getres() to timespec64/itimerspec64.
mmtimer: Convert to timespec64/itimerspec64.
alarmtimer: Convert to timespec64/itimerspec64.
posix-clock: Convert to timespec64/itimerspec64.
posix-cpu-timers: Convert to timespec64/itimerspec64.
Baolin Wang (24):
linux/time64.h:Introduce the 'struct itimerspec64' for 64bit
timekeeping:Introduce the current_kernel_time64() function with
timespec64 type
time/hrtimer:Introduce hrtimer_get_res64() with timespec64 type for
getting the timer resolution
security/security: Introduce security_settime64() function with
timespec64 type
time:Introduce the do_sys_settimeofday64() function with timespec64
type
posix-timers:Change the implementation for timer_gettime syscall
function
posix-timers:Convert to the 64bit methods for the timer_gettime
syscall function
posix-timers:Change the implementation for timer_settime syscall
posix-timers:Convert to the 64bit methods for the timer_settime
syscall function
posix-timers:Change the implementation for clock_settime syscall
function
posix-timers:Convert to the 64bit methods for the clock_settime
syscall function
posix-timers:Change the implementation for clock_gettime syscall
function
posix-timers:Convert to the 64bit methods for the clock_gettime
syscall function
posix-timers:Change the implementation for clock_getres syscall
function
posix-timers:Convert to the 64bit methods for the clock_getres
syscall function
timekeeping:Introduce the timekeeping_clocktai() function with
timespec64 type
time/posix-timers:Convert to the 64bit methods for k_clock callback
functions
char/mmtimer:Convert to the 64bit methods for k_clock callback
functions
time/alarmtimer:Convert to the new 64bit methods for k_clock
structure
time/posix-clock:Convert to the 64bit methods for k_clock and
posix_clock_operations structure
time/time:Introduce the
timespec64_to_jiffies()/jiffies_to_timespec64() function
cputime:Introduce the cputime_to_timespec64/timespec64_to_cputime
function
time/posix-cpu-timers:Convert to the 64bit methods for k_clock
structure
k_clock:Remove the 32bit methods with timespec/itimerspec type
arch/powerpc/include/asm/cputime.h | 6 +-
arch/s390/include/asm/cputime.h | 8 +-
drivers/char/mmtimer.c | 36 +++--
drivers/ptp/ptp_clock.c | 26 +---
include/asm-generic/cputime_jiffies.h | 10 +-
include/asm-generic/cputime_nsecs.h | 4 +-
include/linux/cputime.h | 15 ++
include/linux/hrtimer.h | 12 +-
include/linux/jiffies.h | 21 ++-
include/linux/posix-clock.h | 10 +-
include/linux/posix-timers.h | 18 +--
include/linux/security.h | 25 ++-
include/linux/time64.h | 35 +++++
include/linux/timekeeping.h | 26 +++-
kernel/time/alarmtimer.c | 43 +++---
kernel/time/hrtimer.c | 10 +-
kernel/time/posix-clock.c | 20 +--
kernel/time/posix-cpu-timers.c | 83 +++++-----
kernel/time/posix-timers.c | 270 ++++++++++++++++++++++-----------
kernel/time/time.c | 20 +--
kernel/time/timekeeping.c | 6 +-
kernel/time/timekeeping.h | 1 -
security/commoncap.c | 2 +-
security/security.c | 2 +-
24 files changed, 447 insertions(+), 262 deletions(-)
--
1.7.9.5
This is a follow-up to the series posted at [1]. To make review
a little easier, I'm focusing on just one class of system calls
here, and this is one that is handled differently from all the
others.
In particular, for sys_msgctl, sys_semctl and sys_shmctl, I do
not introduce a completely new set of replacement system calls,
but instead extend the existing ones to return data in the
reserved fields of the normal data structure.
This should be completely transparent to any existing user space,
and only after the 32-bit time_t wraps, it will make a difference
in the returned data.
libc implementations will consequently have to provide their own
data structures when they move to 64-bit time_t, and convert
the structures in user space from the ones returned by the kernel.
There are three cases here:
- little-endian architectures (except powerpc and mips) can use
the normal layout and just cast the data structure to the
user space type that contains 64-bit numbers.
- parisc and sparc can do the same thing with big-endian user
space
- little-endian powerpc and most big-endian architectures have
to flip the upper and lower 32-bit halves of the time_t value
in memory, but can otherwise keep using the normal layout
- mips and big-endian xtensa need to be more careful because
they are not consistent in their definitions, and they
have to provide custom libc implementations for the system
calls to use 64-bit time_t.
Please review.
Arnd
[1] http://lwn.net/Articles/643407/
Arnd Bergmann (8):
y2038: asm-generic: extend sysvipc data structures
y2038: mips: extend sysvipc data structures
y2038: x86: extend sysvipc data structures
y2038: parisc: extend sysvipc data structures
y2038: sparc: extend sysvipc data structures
y2038: powerpc: extend sysvipc data structures
y2038: xtensa: extend sysvipc data structures
y2038: ipc: report long times to user space
arch/arm64/include/asm/compat.h | 32 +++++++++----------
arch/mips/include/asm/compat.h | 38 +++++++++++-----------
arch/mips/include/uapi/asm/msgbuf.h | 56 +++++++++++++++++++++-----------
arch/mips/include/uapi/asm/sembuf.h | 15 +++++++--
arch/mips/include/uapi/asm/shmbuf.h | 23 ++++++++++++--
arch/parisc/include/asm/compat.h | 32 +++++++++----------
arch/parisc/include/uapi/asm/msgbuf.h | 32 +++++++++----------
arch/parisc/include/uapi/asm/sembuf.h | 13 ++++----
arch/parisc/include/uapi/asm/shmbuf.h | 18 +++++------
arch/powerpc/include/asm/compat.h | 32 +++++++++----------
arch/powerpc/include/uapi/asm/msgbuf.h | 18 +++++------
arch/powerpc/include/uapi/asm/sembuf.h | 14 ++++----
arch/powerpc/include/uapi/asm/shmbuf.h | 18 +++++------
arch/sparc/include/asm/compat.h | 32 +++++++++----------
arch/sparc/include/uapi/asm/msgbuf.h | 21 ++++++------
arch/sparc/include/uapi/asm/sembuf.h | 15 ++++-----
arch/sparc/include/uapi/asm/shmbuf.h | 20 ++++++------
arch/tile/include/asm/compat.h | 32 +++++++++----------
arch/x86/include/asm/compat.h | 32 +++++++++----------
arch/x86/include/uapi/asm/msgbuf.h | 41 +++++++++++++++++++++++-
arch/x86/include/uapi/asm/sembuf.h | 10 ++++++
arch/x86/include/uapi/asm/shmbuf.h | 58 +++++++++++++++++++++++++++++++++-
arch/xtensa/include/uapi/asm/msgbuf.h | 24 +++++++-------
arch/xtensa/include/uapi/asm/sembuf.h | 16 +++++-----
arch/xtensa/include/uapi/asm/shmbuf.h | 36 +++++----------------
include/linux/msg.h | 7 ++--
include/linux/sem.h | 3 +-
include/linux/shm.h | 7 ++--
include/uapi/asm-generic/msgbuf.h | 16 +++++-----
include/uapi/asm-generic/sembuf.h | 26 +++++++++------
include/uapi/asm-generic/shmbuf.h | 16 +++++-----
ipc/compat.c | 8 +++++
ipc/msg.c | 23 ++++++++------
ipc/sem.c | 32 +++++++++++--------
ipc/shm.c | 21 +++++++-----
35 files changed, 499 insertions(+), 338 deletions(-)
--
2.1.0.rc2
struct timeval uses a 32-bit seconds representation which will
overflow in the year 2038 and beyond. This patch replaces
the usage of struct timeval with ktime_t which is a 64-bit
timestamp and is year 2038 safe.
This patch is part of a larger attempt to remove all instances
of 32-bit timekeeping variables (timeval, timespec, time_t)
which are not year 2038 safe, from the kernel.
The patch is a work-in-progress - correctness of the following
changes is unclear:
(a) Usage of timeval_usec_diff - The function seems to subtract
usec values without caring about the difference of the seconds field.
There may be an implicit assumption in the original code that the
time delta is always of the order of microseconds.
The patch replaces the usage of timeval_usec_diff with
ktime_to_us(ktime_sub()) which computes the real timestamp difference,
not just the difference in the usec field.
(b) printk diffing the tv[i] and tv[i-1] values. The original
printk statement seems to get the order wrong. This patch preserves
that order.
Signed-off-by: Tina Ruchandani <ruchandani.tina(a)gmail.com>
Suggested-by: Arnd Bergmann <arnd(a)arndb.de>
--
Changes in v2:
- Use the more concise ktime_us_delta
- Preserve the waketime argument in dvb_frontend_sleep_until as
a pointer, fixes bug introduced in v1 of the patch where the caller
doesn't get its timestamp modified.
---
drivers/media/dvb-core/dvb_frontend.c | 40 +++++++++--------------------------
drivers/media/dvb-core/dvb_frontend.h | 3 +--
drivers/media/dvb-frontends/stv0299.c | 11 +++++-----
3 files changed, 17 insertions(+), 37 deletions(-)
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index 882ca41..c110e37 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -40,6 +40,7 @@
#include <linux/freezer.h>
#include <linux/jiffies.h>
#include <linux/kthread.h>
+#include <linux/ktime.h>
#include <asm/processor.h>
#include "dvb_frontend.h"
@@ -889,42 +890,21 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
fepriv->thread);
}
-s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime)
-{
- return ((curtime.tv_usec < lasttime.tv_usec) ?
- 1000000 - lasttime.tv_usec + curtime.tv_usec :
- curtime.tv_usec - lasttime.tv_usec);
-}
-EXPORT_SYMBOL(timeval_usec_diff);
-
-static inline void timeval_usec_add(struct timeval *curtime, u32 add_usec)
-{
- curtime->tv_usec += add_usec;
- if (curtime->tv_usec >= 1000000) {
- curtime->tv_usec -= 1000000;
- curtime->tv_sec++;
- }
-}
-
/*
* Sleep until gettimeofday() > waketime + add_usec
* This needs to be as precise as possible, but as the delay is
* usually between 2ms and 32ms, it is done using a scheduled msleep
* followed by usleep (normally a busy-wait loop) for the remainder
*/
-void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec)
+void dvb_frontend_sleep_until(ktime_t *waketime, u32 add_usec)
{
- struct timeval lasttime;
s32 delta, newdelta;
- timeval_usec_add(waketime, add_usec);
-
- do_gettimeofday(&lasttime);
- delta = timeval_usec_diff(lasttime, *waketime);
+ ktime_add_us(*waketime, add_usec);
+ delta = ktime_us_delta(ktime_get_real(), *waketime);
if (delta > 2500) {
msleep((delta - 1500) / 1000);
- do_gettimeofday(&lasttime);
- newdelta = timeval_usec_diff(lasttime, *waketime);
+ newdelta = ktime_us_delta(ktime_get_real(), *waketime);
delta = (newdelta > delta) ? 0 : newdelta;
}
if (delta > 0)
@@ -2458,13 +2438,13 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
* include the initialization or start bit
*/
unsigned long swcmd = ((unsigned long) parg) << 1;
- struct timeval nexttime;
- struct timeval tv[10];
+ ktime_t nexttime;
+ ktime_t tv[10];
int i;
u8 last = 1;
if (dvb_frontend_debug)
printk("%s switch command: 0x%04lx\n", __func__, swcmd);
- do_gettimeofday(&nexttime);
+ nexttime = ktime_get_real();
if (dvb_frontend_debug)
tv[0] = nexttime;
/* before sending a command, initialize by sending
@@ -2475,7 +2455,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
for (i = 0; i < 9; i++) {
if (dvb_frontend_debug)
- do_gettimeofday(&tv[i + 1]);
+ tv[i+1] = ktime_get_real();
if ((swcmd & 0x01) != last) {
/* set voltage to (last ? 13V : 18V) */
fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
@@ -2489,7 +2469,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
printk("%s(%d): switch delay (should be 32k followed by all 8k\n",
__func__, fe->dvb->num);
for (i = 1; i < 10; i++)
- printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
+ printk("%d: %d\n", i, (int) ktime_to_us(ktime_sub(tv[i-1], tv[i])));
}
err = 0;
fepriv->state = FESTATE_DISEQC;
diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h
index 816269e..5b64686 100644
--- a/drivers/media/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb-core/dvb_frontend.h
@@ -439,7 +439,6 @@ extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);
extern int dvb_frontend_suspend(struct dvb_frontend *fe);
extern int dvb_frontend_resume(struct dvb_frontend *fe);
-extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
-extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime);
+extern void dvb_frontend_sleep_until(ktime_t *waketime, u32 add_usec);
#endif
diff --git a/drivers/media/dvb-frontends/stv0299.c b/drivers/media/dvb-frontends/stv0299.c
index b57ecf4..70c8065 100644
--- a/drivers/media/dvb-frontends/stv0299.c
+++ b/drivers/media/dvb-frontends/stv0299.c
@@ -44,6 +44,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/ktime.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/slab.h>
@@ -404,8 +405,8 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
u8 lv_mask = 0x40;
u8 last = 1;
int i;
- struct timeval nexttime;
- struct timeval tv[10];
+ ktime_t nexttime;
+ ktime_t tv[10];
reg0x08 = stv0299_readreg (state, 0x08);
reg0x0c = stv0299_readreg (state, 0x0c);
@@ -418,7 +419,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
if (debug_legacy_dish_switch)
printk ("%s switch command: 0x%04lx\n",__func__, cmd);
- do_gettimeofday (&nexttime);
+ nexttime = ktime_get_real();
if (debug_legacy_dish_switch)
tv[0] = nexttime;
stv0299_writeregI (state, 0x0c, reg0x0c | 0x50); /* set LNB to 18V */
@@ -427,7 +428,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
for (i=0; i<9; i++) {
if (debug_legacy_dish_switch)
- do_gettimeofday (&tv[i+1]);
+ tv[i+1] = ktime_get_real();
if((cmd & 0x01) != last) {
/* set voltage to (last ? 13V : 18V) */
stv0299_writeregI (state, 0x0c, reg0x0c | (last ? lv_mask : 0x50));
@@ -443,7 +444,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
printk ("%s(%d): switch delay (should be 32k followed by all 8k\n",
__func__, fe->dvb->num);
for (i = 1; i < 10; i++)
- printk ("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
+ printk("%d: %d\n", i, (int) ktime_to_us(ktime_sub(tv[i-1], tv[i])));
}
return 0;
--
2.2.0.rc0.207.ga3a616c
This is my second draft of how we could modify the system call interface
in Linux to support user space with 64-bit time_t in addition to the
existing 32-bit time_t based interfaces. In order to avoid spamming people
too much, I've picked the first half of the patches only now, and left
some of the more complex ones for later.
If you are interested in the big picture, see
http://git.kernel.org/cgit/linux/kernel/git/arnd/playground.git/log/?h=y203…
with currently 42 patches. That number may go up a bit over time, but
only because I plan to split some of the patches into smaller chunks
for review purposes, as opposed to adding more system calls.
As part 1 of the series only switches over half the system calls,
I've left out the bits that changes the ARM and x86 architectures.
There are 24 additional architectures that need to moved over to
the new system calls once the basic patches get merged.
The main part I'm not sure about is how the header files should be
structured in order to make it easy for every libc implementation
to pick out the right definitions of the data structures I had to
modify. Hopefully, people on libc-alpha can help me out here.
The overall approach I have taken here is as follows:
* Since 64-bit architectures already support two versions of each system
call that passes a time value in order to run 32-bit user space,
I'm not adding new system calls for the most part, but instead make
32-bit architectures use the same compat handlers that 64-bit
architectures already use.
* The existing syscall numbers are modified to point to the compat_sys_*
functions, and new numbers are assigned to point to the existing handlers
that now deal with 64-bit time_t based structures
* This series does not touch any ioctl implementation, but should be
otherwise complete regarding the system calls. We are still trying
to find out exactly which ioctls are affected and have not come
up with a complete list at this point. It's probably a good idea
though to do at least the essential ioctls before merging the series,
so we can have a better understanding of how it will be done in the
end.
* Each data structure we need to modify gets a new definition with a
__kernel_ prefix, e.g. struct __kernel_timespec to replace struct
timespec. This keeps the new structures out of the user libc
namespace, but still allows the structure to be integrated into
other data structures, e.g. for ioctl.
* There is no #ifdef in the UAPI headers at this point that would
check for the kind of user space that is in use. Unfortunately,
I believe we will need to add that in order to do some of the
particularly tricky ioctls later.
* At first, all system call implementations are modified, but this
is done in a way that is not supposed to have any ABI-visible
effect on existing architectures.
* After all system calls are converted, we can change one architecture
at a time to select ARCH_HAS_COMPAT_TIME, and modify its system
call table accordingly. In this version, I do it for ARM32, x86-32,
and x86-64 for demonstration purposes.
* A follow-up series changes over all other architectures.
* The last patch in the series changes the CONFIG_COMPAT_TIME
Kconfig symbol to be user visible. Disabling this symbol will
get you a kernel that intentionally breaks support for old tasks
in order to provide an interface that will survive 2038.
This is meant mostly as a debugging help for now, to let people
build a y2038 safe distro, but at some point in the 2030s, we
should remove that option and all the compat handling.
Arnd Bergmann (19):
compat: remove compat_printk
initramfs: use vfs_stat/lstat directly
y2038: introduce linux/compat_time.h header
y2038: introduce CONFIG_COMPAT_TIME
y2038: make linux/compat_time.h usable on 32-bit
y2038: compile compat time code even when CONFIG_COMPAT is not set
y2038: add compat_sys_rt_sigtimedwait variants
y2038: introduce struct __kernel_timespec
y2038: introduce struct __kernel_stat
y2038: use __kernel_stat for sys_newstat syscalls
y2038: introduce and use struct __kernel_rusage
y2038: add compat_{get,put}_timespec64
y2038: add compat handling for sys_semtimedop
y2038: use __kernel_timespec for sys_mq_timed{send,receive}
y2038: introduce timespec64_to_jiffies
y2038: use __kernel_timespec in sys_rt_sigtimedwait
y2038: use __kernel_timespec in sys_futex
y2038: introduce jiffies_to_timespec64
y2038: use __kernel_timespec in sys_sched_rr_get_interval
arch/Kconfig | 11 ++
arch/alpha/include/uapi/asm/stat.h | 4 +
arch/alpha/kernel/osf_sys.c | 4 +-
arch/arm/include/uapi/asm/stat.h | 2 +
arch/arm64/include/asm/compat.h | 11 --
arch/avr32/include/uapi/asm/stat.h | 2 +
arch/blackfin/include/uapi/asm/stat.h | 2 +
arch/cris/include/uapi/asm/stat.h | 2 +
arch/frv/include/uapi/asm/stat.h | 2 +
arch/ia64/include/uapi/asm/stat.h | 4 +
arch/m32r/include/uapi/asm/stat.h | 1 +
arch/m68k/include/uapi/asm/stat.h | 2 +
arch/mips/include/asm/compat.h | 11 --
arch/mips/include/uapi/asm/stat.h | 1 +
arch/mn10300/include/uapi/asm/stat.h | 2 +
arch/parisc/include/asm/compat.h | 11 --
arch/parisc/include/uapi/asm/stat.h | 1 +
arch/powerpc/include/asm/compat.h | 11 --
arch/powerpc/include/uapi/asm/stat.h | 25 +++
arch/s390/include/asm/compat.h | 11 --
arch/s390/include/uapi/asm/stat.h | 24 +++
arch/sh/include/uapi/asm/stat.h | 2 +
arch/sparc/include/asm/compat.h | 11 --
arch/sparc/include/uapi/asm/stat.h | 28 ++++
arch/tile/include/asm/compat.h | 11 --
arch/x86/include/asm/compat.h | 12 +-
arch/x86/include/asm/ftrace.h | 2 +-
arch/x86/include/asm/sys_ia32.h | 2 +-
arch/x86/include/uapi/asm/stat.h | 49 ++++--
arch/x86/kernel/cpu/perf_event.c | 2 +-
arch/xtensa/include/uapi/asm/stat.h | 2 +
fs/Makefile | 1 +
fs/compat.c | 26 ++-
fs/stat.c | 12 +-
include/linux/audit.h | 4 +-
include/linux/compat.h | 232 +--------------------------
include/linux/compat_time.h | 285 +++++++++++++++++++++++++++++++++
include/linux/jiffies.h | 23 ++-
include/linux/resource.h | 8 +-
include/linux/signal.h | 3 +-
include/linux/stat.h | 3 +
include/linux/syscalls.h | 32 ++--
include/linux/thread_info.h | 2 +-
include/linux/time64.h | 17 +-
include/uapi/asm-generic/kernel_stat.h | 36 +++++
include/uapi/asm-generic/stat.h | 12 +-
include/uapi/linux/resource.h | 32 ++++
include/uapi/linux/time.h | 17 ++
init/do_mounts.h | 22 +--
init/initramfs.c | 12 +-
ipc/compat.c | 10 --
ipc/mqueue.c | 16 +-
ipc/sem.c | 60 +++++--
ipc/syscall.c | 7 +
kernel/Makefile | 1 +
kernel/audit.h | 2 +-
kernel/auditsc.c | 14 +-
kernel/compat.c | 184 ++++++++++++++++++---
kernel/exit.c | 6 +-
kernel/futex.c | 10 +-
kernel/sched/core.c | 35 +++-
kernel/signal.c | 13 +-
kernel/sys.c | 23 +--
kernel/sysctl.c | 10 --
kernel/time/time.c | 45 ++++--
65 files changed, 950 insertions(+), 530 deletions(-)
create mode 100644 include/linux/compat_time.h
create mode 100644 include/uapi/asm-generic/kernel_stat.h
--
2.1.0.rc2