The year 2038 problem
All 32-bit kernels to date use a signed 32-bit time_t type, which can only represent time until January 2038. Since embedded systems running 32-bit Linux are going to survive beyond that date, we have to change all current uses, in a backwards compatible way.
User space interfaces
We will likely keep the 32-bit time_t in all user space interfaces that currently use it, but add new interfaces with a 64-bit timespec or another type that can represent later times. Most importantly that impacts system calls, but also specific ioctl commands and a few other interfaces. User space programs have to be recompiled to use the new interfaces, and the policy whether to use the old or the time time is left to the C library. While that policy is a complex topic itself, we don't cover it here.
https://docs.google.com/spreadsheets/d/1HCYwHXxs48TsTb6IGUduNjQnmfRvMPzCN6T_0YiQwis has a table of all affected system calls, here are some explanations:
clocks and timers
these should be done consistently, either using timespec64 or 64-bit nanoseconds, either one works. 64-bit nanoseconds would simplify the kernel internally quite a bit by avoiding the double timekeeping (we keep track of both nanoseconds and timespec in the timekeeper struct). the downside of nanoseconds-only is that each existing caller would need a conversion in user space, where currently we can avoid the expensive ktime_to_ts() for some cases. Current patches use 64-bit timespec.
These get an *absolute* timeout, so we have to change them. Internally they use ktime_t, so that would be the natural interface, but timespec64 would work as well. The patches currently use a 64-bit timespec.
This uses a relative timeout that is converted to jiffies internally, so using ktime_t would not be as natural, unless we rewrite the function to use hrtimers. The current patches simply use a 64-bit timespec.
These have an output, which is a time_t that stores the absolute seconds value of the last time something happened. Internally this comes from get_seconds(), which has to be efficient anyway. There is sufficient padding available on all architectures (except MIPS) to extend the structure in a backwards-compatible way to 64 bit time values. Because of endianess concerns, we cannot simply replace time_t with time64_t unfortunately, but have to pass the low and high 32-bit components separately. On MIPS, we can only use 48-bit times for some structures, but that should be good enough as well.
inodes and filesystems
inode timestamps need to represent times before 1970 and way into the future, so we need 64-bit time_t here, I see no other alternatives here, so we have to pass struct timespec64 into utimensat, and create version 4 of 'struct stat' to pass into the future fstat and fstatat. I would use a version that matches the 64-bit layout of 'struct stat', as posted in v1 of the patch set.
We could change rusage to contain a new 'struct relative_timeval' instead, with an unchanged layout, which makes the format incompatible with a standard libc that uses a 64-bit based timeval. There will be no y2038 overflow, but the ru_utime may overflow on systems with many cores when the total runtime of a task exceeds 68 years, e.g. after running on continuously for 259 days on a 96-core machine that is getting affordable now.
This passes a relative timespec value in back out, so we could keep the current layout and have glibc convert it, or change it to something else. The kernel internally converts to jiffies to call schedule_timeout.
memory mapped packet sockets
Socket timestamps are exported to user space using a memory mapped interface defined in include/uapi/linux/if_packet.h. There are currently three versions of this interface, all use a 32-bit time type. We will likely need a version 4 to solve this.
Audit of include/uapi for time_t impact
time_t struct msqid64_ds (has 2038 padding!) struct semid64_ds (has 2038 padding!) struct cyclades_idle_stats struct video_event VIDEO_GET_EVENT struct msqid_ds struct ppp_idle PPPIOCGIDLE struct semid_ds union semun struct timespec SIOCGSTAMPNS struct coda_vattr ... struct scm_timestamping struct som_hdr struct itimerspec struct v4l2_event VIDIOC_DQEVENT struct snd_pcm_status SNDRV_PCM_IOCTL_STATUS struct snd_pcm_mmap_status struct snd_pcm_sync_ptr SNDRV_PCM_IOCTL_SYNC_PTR struct snd_rawmidi_status SNDRV_RAWMIDI_IOCTL_STATUS struct snd_timer_status SNDRV_TIMER_IOCTL_STATUS struct snd_timer_tread struct snd_ctl_elem_value SNDRV_CTL_IOCTL_ELEM_READ SNDRV_CTL_IOCTL_ELEM_WRITE struct timeval SIOCGSTAMP struct zatm_t_hist struct bcm_msg_head struct elf_prstatus struct input_event struct omap3isp_stat_data VIDIOC_OMAP3ISP_STAT_REQ PPGETTIME PPSETTIME struct rusage struct itimerval struct timex struct v4l2_buffer VIDIOC_QUERYBUF VIDIOC_QBUF VIDIOC_DQBUF VIDIOC_PREPARE_BUF struct utimbuf
The task list is for people that want to get involved, there will be many more tasks over time, so this is just a starting point. In the end, we should remove all instances of 'time_t', 'timespec' and 'timeval' from the kernel.
drivers/staging/bcm/LeakyBucket.c (timeval, slightly tricky)