Re: [Y2038] [PATCH 13/16] hfs/hfsplus: use 64-bit inode timestamps
> On Nov 9, 2019, at 12:32 AM, Arnd Bergmann wrote: > > The interpretation of on-disk timestamps in HFS and HFS+ differs > between 32-bit and 64-bit kernels at the moment. Use 64-bit timestamps > consistently so apply the current 64-bit behavior everyhere. > > According to the official documentation for HFS+ [1], inode timestamps > are supposed to cover the time range from 1904 to 2040 as originally > used in classic MacOS. > > The traditional Linux usage is to convert the timestamps into an unsigned > 32-bit number based on the Unix epoch and from there to a time_t. On > 32-bit systems, that wraps the time from 2038 to 1902, so the last > two years of the valid time range become garbled. On 64-bit systems, > all times before 1970 get turned into timestamps between 2038 and 2106, > which is more convenient but also different from the documented behavior. > > Looking at the Darwin sources [2], it seems that MacOS is inconsistent in > yet another way: all timestamps are wrapped around to a 32-bit unsigned > number when written to the disk, but when read back, all numeric values > lower than 2082844800U are assumed to be invalid, so we cannot represent > the times before 1970 or the times after 2040. > > While all implementations seem to agree on the interpretation of values > between 1970 and 2038, they often differ on the exact range they support > when reading back values outside of the common range: > > MacOS (traditional): 1904-2040 > Apple Documentation: 1904-2040 > MacOS X source comments: 1970-2040 > MacOS X source code: 1970-2038 > 32-bit Linux: 1902-2038 > 64-bit Linux: 1970-2106 > hfsfuse: 1970-2040 > hfsutils (32 bit, old libc) 1902-2038 > hfsutils (32 bit, new libc) 1970-2106 > hfsutils (64 bit) 1904-2040 > hfsplus-utils 1904-2040 > hfsexplorer 1904-2040 > 7-zip 1904-2040 > > Out of the above, the range from 1970 to 2106 seems to be the most useful, > as it allows using HFS and HFS+ beyond year 2038, and this matches the > behavior that most users would see today on Linux, as few people run > 32-bit kernels any more. > > Link: [1] https://developer.apple.com/library/archive/technotes/tn/tn1150.html > Link: [2] > https://opensource.apple.com/source/hfs/hfs-407.30.1/core/MacOSStubs.c.auto.html > Link: https://lore.kernel.org/lkml/20180711224625.airwna6gzyatoowe@eaf/ > Cc: Viacheslav Dubeyko > Suggested-by: "Ernesto A. Fernández" > Signed-off-by: Arnd Bergmann > --- > v3: revert back to 1970-2106 time range >fix bugs found in review >merge both patches into one >drop cc:stable tag > v2: treat pre-1970 dates as invalid following MacOS X behavior, >reword and expand changelog text > --- > fs/hfs/hfs_fs.h | 26 -- > fs/hfs/inode.c | 4 ++-- > fs/hfsplus/hfsplus_fs.h | 26 +- > fs/hfsplus/inode.c | 12 ++-- > 4 files changed, 49 insertions(+), 19 deletions(-) > > diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h > index 6d0783e2e276..26733051ee50 100644 > --- a/fs/hfs/hfs_fs.h > +++ b/fs/hfs/hfs_fs.h > @@ -242,19 +242,33 @@ extern void hfs_mark_mdb_dirty(struct super_block *sb); > /* > * There are two time systems. Both are based on seconds since > * a particular time/date. > - * Unix: unsigned lil-endian since 00:00 GMT, Jan. 1, 1970 > + * Unix: signed little-endian since 00:00 GMT, Jan. 1, 1970 > *mac:unsigned big-endian since 00:00 GMT, Jan. 1, 1904 > * > + * HFS implementations are highly inconsistent, this one matches the > + * traditional behavior of 64-bit Linux, giving the most useful > + * time range between 1970 and 2106, by treating any on-disk timestamp > + * under 2082844800U (Jan 1 1970) as a time between 2040 and 2106. > */ > -#define __hfs_u_to_mtime(sec)cpu_to_be32(sec + 2082844800U - > sys_tz.tz_minuteswest * 60) > -#define __hfs_m_to_utime(sec)(be32_to_cpu(sec) - 2082844800U + > sys_tz.tz_minuteswest * 60) I believe it makes sense to introduce some constant instead of hardcoded value (2082844800U and 60). It will be easier to understand the code without necessity to take a look into the comments. What do you think? > +static inline time64_t __hfs_m_to_utime(__be32 mt) > +{ > + time64_t ut = (u32)(be32_to_cpu(mt) - 2082844800U); Ditto. > + > + return ut + sys_tz.tz_minuteswest * 60; > +} > > +static inline __be32 __hfs_u_to_mtime(time64_t ut) > +{ > + ut -= sys_tz.tz_minuteswest * 60; > + > + return cpu_to_be32(lower_32_bits(ut) + 2082844800U); Ditto. > +} > #define HFS_I(inode) (container_of(inode, struct hfs_inode_info, vfs_inode)) > #define HFS_SB(sb)((struct hfs_sb_info *)(sb)->s_fs_info) > > -#define hfs_m_to_utime(time) (struct timespec){ .tv_sec = > __hfs_m_to_utime(time) } > -#define hfs_u_to_mtime(time) __hfs_u_to_mtime((time).tv_sec) > -#define
Re: [Y2038] [RFC 1/5] xfs: [variant A] avoid time_t in user api
On Tue, Nov 12, 2019 at 03:16:00PM +0100, Christoph Hellwig wrote: > On Tue, Nov 12, 2019 at 01:09:06PM +0100, Arnd Bergmann wrote: > > However, as long as two observations are true, a much simpler solution > > can be used: > > > > 1. xfsprogs is the only user space project that has a copy of this header > > We can't guarantee that. > > > 2. xfsprogs already has a replacement for all three affected ioctl commands, > >based on the xfs_bulkstat structure to pass 64-bit timestamps > >regardless of the architecture > > XFS_IOC_BULKSTAT replaces XFS_IOC_FSBULKSTAT directly, and can replace > XFS_IOC_FSBULKSTAT_SINGLE indirectly, so that is easy. Most users > actually use the new one now through libfrog, although I found a user > of the direct ioctl in the xfs_io tool, which could easily be fixed as > well. Agreed, XFS_IOC_BULKSTAT is the replacement for the two FSBULKSTAT variants. The only question in my mind for the old ioctls is whether we should return EOVERFLOW if the timestamp would overflow? Or just truncate the results? > XFS_IOC_SWAPEXT does not have a direct replacement, but the timestamp > is only used to verify that the file did not change vs the previous > stat. So not being able to represent > 2038 times is not a real > problem anyway. Won't it become a problem when the tv_sec comparison in xfs_swap_extents is type-promoted to the larger type but lacks the upper bits? I guess we could force the check to the lower 32 bits on the assumption that those are the most likely to change due to a file write. I kinda want to do a SWAPEXT v5, fwiw > At some point we should probably look into a file system independent > defrag ioctl anyway, at which point we can deprecate XFS_IOC_SWAPEXT. > > > Based on those assumptions, changing xfs_bstime to use __kernel_long_t > > instead of time_t in both the kernel and in xfsprogs preserves the current > > ABI for any libc definition of time_t and solves the problem of passing > > 64-bit timestamps to 32-bit user space. > > As said above their are not entirely true, but I still think this patch > is the right thing to do, if only to get the time_t out of the ABI.. > > Reviewed-by: Christoph Hellwig Seconded, Reviewed-by: Darrick J. Wong --D ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [PATCH 13/16] hfs/hfsplus: use 64-bit inode timestamps
On Fri, Nov 08, 2019 at 10:32:51PM +0100, Arnd Bergmann wrote: > The interpretation of on-disk timestamps in HFS and HFS+ differs > between 32-bit and 64-bit kernels at the moment. Use 64-bit timestamps > consistently so apply the current 64-bit behavior everyhere. > > According to the official documentation for HFS+ [1], inode timestamps > are supposed to cover the time range from 1904 to 2040 as originally > used in classic MacOS. > > The traditional Linux usage is to convert the timestamps into an unsigned > 32-bit number based on the Unix epoch and from there to a time_t. On > 32-bit systems, that wraps the time from 2038 to 1902, so the last > two years of the valid time range become garbled. On 64-bit systems, > all times before 1970 get turned into timestamps between 2038 and 2106, > which is more convenient but also different from the documented behavior. > > Looking at the Darwin sources [2], it seems that MacOS is inconsistent in > yet another way: all timestamps are wrapped around to a 32-bit unsigned > number when written to the disk, but when read back, all numeric values > lower than 2082844800U are assumed to be invalid, so we cannot represent > the times before 1970 or the times after 2040. > > While all implementations seem to agree on the interpretation of values > between 1970 and 2038, they often differ on the exact range they support > when reading back values outside of the common range: > > MacOS (traditional): 1904-2040 > Apple Documentation: 1904-2040 > MacOS X source comments: 1970-2040 > MacOS X source code: 1970-2038 > 32-bit Linux: 1902-2038 > 64-bit Linux: 1970-2106 > hfsfuse: 1970-2040 > hfsutils (32 bit, old libc) 1902-2038 > hfsutils (32 bit, new libc) 1970-2106 > hfsutils (64 bit) 1904-2040 > hfsplus-utils 1904-2040 > hfsexplorer 1904-2040 > 7-zip 1904-2040 > > Out of the above, the range from 1970 to 2106 seems to be the most useful, > as it allows using HFS and HFS+ beyond year 2038, and this matches the > behavior that most users would see today on Linux, as few people run > 32-bit kernels any more. > > Link: [1] https://developer.apple.com/library/archive/technotes/tn/tn1150.html > Link: [2] > https://opensource.apple.com/source/hfs/hfs-407.30.1/core/MacOSStubs.c.auto.html > Link: https://lore.kernel.org/lkml/20180711224625.airwna6gzyatoowe@eaf/ > Cc: Viacheslav Dubeyko > Suggested-by: "Ernesto A. Fernández" > Signed-off-by: Arnd Bergmann > --- Reviewed-by: Ernesto A. Fernández ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [RFC 4/5] xfs: extend inode format for 40-bit timestamps
On Tue, Nov 12, 2019 at 01:09:09PM +0100, Arnd Bergmann wrote: > XFS is the only major file system that lacks timestamps beyond year 2038, > and is already being deployed in systems that may have to be supported > beyond that time. > > Fortunately, the inode format still has a few reserved bits that can be > used to extend the current format. There are two bits in the nanosecond > portion that could be used in the same way that ext4 does, extending > the timestamps until year 2378, as well as 12 unused bytes after the > already allocated fields. > > There are four timestamps that need to be extended, so using four > bytes out of the reserved space gets us all the way until year 36676, > by extending the current 1902-2036 with another 255 epochs, which > seems to be a reasonable range. > > I am not sure whether this change to the inode format requires a > new version for the inode. All existing file system images remain > compatible, while mounting a file systems with extended timestamps > beyond 2038 would report that timestamp incorrectly in the 1902 > through 2038 range, matching the traditional Linux behavior of > wrapping timestamps. > > Signed-off-by: Arnd Bergmann This is basically what I proposed ~5 years or so ago and posted a patch to implement it in an early y2038 discussion with you. I jsut mentioned that very patch in my reposnse to Amir's timestamp extension patchset, pointing out that this isn't the way we want to proceed with >y2038 on-disk support. https://lore.kernel.org/linux-xfs/20191112161242.ga19...@infradead.org/T/#maf6b2719ed561cc2865cc5e7eb82df206b971261 I'd suggest taking the discussion there Cheers, Dave. -- Dave Chinner da...@fromorbit.com ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [PATCH 11/23] y2038: rusage: use __kernel_old_timeval
On Fri, Nov 08, 2019 at 10:12:10PM +0100, Arnd Bergmann wrote: > There are two 'struct timeval' fields in 'struct rusage'. > > Unfortunately the definition of timeval is now ambiguous when used in > user space with a libc that has a 64-bit time_t, and this also changes > the 'rusage' definition in user space in a way that is incompatible with > the system call interface. > > While there is no good solution to avoid all ambiguity here, change > the definition in the kernel headers to be compatible with the kernel > ABI, using __kernel_old_timeval as an unambiguous base type. > > In previous discussions, there was also a plan to add a replacement > for rusage based on 64-bit timestamps and nanosecond resolution, > i.e. 'struct __kernel_timespec'. I have patches for that as well, > if anyone thinks we should do that. > > Signed-off-by: Arnd Bergmann > --- > Question: should we also rename 'struct rusage' into 'struct __kernel_rusage' > here, to make them completely unambiguous? The patch looks ok to me. I must confess I looked into rusage long ago so __kernel_timespec type used in uapi made me nervious at first, but then i found that we've this type defined in time_types.h uapi so userspace should be safe. I also like the idea of __kernel_rusage but definitely on top of the series. Reviewed-by: Cyrill Gorcunov ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [PATCH v6 0/8] Fix year 2038 issue for sound subsystem
On Tue, 12 Nov 2019 16:16:34 +0100, Arnd Bergmann wrote: > > This is a series I worked on with Baolin in 2017 and 2018, but we > never quite managed to finish up the last pieces. During the > ALSA developer meetup at ELC-E 2018 in Edinburgh, a decision was > made to go with this approach for keeping best compatibility > with existing source code, and then I failed to follow up by > resending the patches. > > Now I have patches for all remaining time_t uses in the kernel, > so it's absolutely time to revisit them. I have done more > review of the patches myself and found a couple of minor issues > that I have fixed up, otherwise the series is still the same as > before. > > Conceptually, the idea of these patches is: > > - 64-bit applications should see no changes at all, neither > compile-time nor run-time. > > - 32-bit code compiled with a 64-bit time_t currently > does not work with ALSA, and requires kernel changes and/or > sound/asound.h changes > > - Most 32-bit code using these interfaces will work correctly > on a modified kernel, with or without the uapi header changes. > > - 32-bit code using SNDRV_TIMER_IOCTL_TREAD requires the > updated header file for 64-bit time_t support > > - 32-bit i386 user space with 64-bit time_t is broken for > SNDRV_PCM_IOCTL_STATUS, SNDRV_RAWMIDI_IOCTL_STATUS and > SNDRV_PCM_IOCTL_SYNC_PTR because of i386 alignment. This is also > addressed by the updated uapi header. > > - PCM mmap is currently supported on native x86 kernels > (both 32-bit and 64-bit) but not for compat mode. This series breaks > the 32-bit native mmap support for 32-bit time_t, but instead allows > it for 64-bit time_t on both native and compat kernels. This seems to > be the best trade-off, as mmap support is optional already, and most > 32-bit code runs in compat mode anyway. > > - I've tried to avoid breaking compilation of 32-bit code > as much as possible. Anything that does break however is likely code > that is already broken on 64-bit time_t and needs source changes to > fix them. > > I would like to propose merging this into the alsa tree after > the v5.5 merge window for inclusion into v5.6, to allow a good > amount of testing, in particular for the header changes that > may cause problems for user space applications. Agreed, it's still no urgent problem. > A git branch with the same contents is available for testing at [1]. > > Please review and test! > > Arnd So now taking a quick look through the series, I find this approach is the way to go. Although one might get a bit more optimization after squeeze, it's already a good compromise between the readability and the efficiency. A slight uncertain implementation is the timer tread stuff, especially the conditional definition of SNDRV_TIMER_IOCTL_TREAD (IIRC, I already complained it in the past, too). But I have no other idea as well, so unless someone else gives a better option, we can live with that. Thanks! Takashi > > [1] https://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground.git > y2038-alsa > [2] > https://lore.kernel.org/lkml/cak8p3a2os66+iwqyf97qh05w2jp8rmwao8zmkohixqvhvyy...@mail.gmail.com/T/#m6519cb07cfda08adf1dedea6596bb98892b4d5dc > > Changes since v5 (Arnd): > - Rebased to linux-5.4-rc4 > - Updated to completely remove timespec and time_t references from alsa > - found and fixed a few bugs > > Changes since v4 (Baolin): > - Add patch 5 to change trigger_tstamp member of struct snd_pcm_runtime. > - Add patch 8 to change internal timespec. > - Add more explanation in commit message. > - Use ktime_get_real_ts64() in patch 6. > - Split common code out into a separate function in patch 6. > - Fix tu->tread bug in patch 6 and remove #if __BITS_PER_LONG == 64 macro. > > Changes since v3: > - Move struct snd_pcm_status32 to pcm.h file. > - Modify comments and commit message. > - Add new patch2 ~ patch6. > > Changes since v2: > - Renamed all structures to make clear. > - Remove CONFIG_X86_X32 macro and introduced new > compat_snd_pcm_status64_x86_32. > > Changes since v1: > - Add one macro for struct snd_pcm_status_32 which only active in 32bits > kernel. > - Convert pcm_compat.c to use struct snd_pcm_status_64. > - Convert pcm_native.c to use struct snd_pcm_status_64. > > --- > > Arnd Bergmann (2): > ALSA: move snd_pcm_ioctl_sync_ptr_compat into pcm_native.c > ALSA: add new 32-bit layout for snd_pcm_mmap_status/control > > Baolin Wang (6): > ALSA: Replace timespec with timespec64 > ALSA: Avoid using timespec for struct snd_timer_status > ALSA: Avoid using timespec for struct snd_ctl_elem_value > ALSA: Avoid using timespec for struct snd_pcm_status > ALSA: Avoid using timespec for struct snd_rawmidi_status > ALSA: Avoid using timespec for struct snd_timer_tread > > include/sound/pcm.h | 74 ++-- > include/sound/timer.h | 4 +- > include/uapi/sound/asound.h | 132 -- >
Re: [Y2038] [PATCH v6 2/8] ALSA: Avoid using timespec for struct snd_timer_status
On Tue, 12 Nov 2019 21:08:17 +0100, Arnd Bergmann wrote: > > On Tue, Nov 12, 2019 at 4:42 PM Takashi Iwai wrote: > > > > @@ -761,6 +761,7 @@ struct snd_timer_params { > > > unsigned char reserved[60]; /* reserved */ > > > }; > > > > > > +#ifndef __KERNEL__ > > > struct snd_timer_status { > > > struct timespec tstamp; /* Timestamp - last update */ > > > unsigned int resolution;/* current period resolution in ns > > > */ > > > > Do we need this ifndef? Is it for stopping the reference of struct > > snd_timer_status from the kernel code but only 32 and 64 variants? > > Well spotted, this is indeed a very recent change I did to the patch. > The idea here is to hide any use of 'time_t', 'timespec' and 'timeval' > from kernel compilation. These types are now defined in an incompatible > way by libc, so we have to remove them from the kernel's uapi headers. > I would prefer to remove them completely from the kernel (rather than > moving them from uapi to internal headers) to make it harder to write > y2038-incompatible code, and with the 90 patches I sent this week, > all users are gone from the kernel (this series was the last part). Could you put this trick in the changelog, too? > Interestingly, hiding snd_timer_status from the drivers /also/ caught > a but in a file when I had missed a reference that needed to be converted > to snd_timer_status64. Heh, that's no surprising, proving the usefulness :) thanks, Takashi ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [alsa-devel] [PATCH v6 5/8] ALSA: Avoid using timespec for struct snd_rawmidi_status
On Tue, 12 Nov 2019 21:04:10 +0100, Arnd Bergmann wrote: > > On Tue, Nov 12, 2019 at 5:38 PM Takashi Iwai wrote: > > On Tue, 12 Nov 2019 16:16:39 +0100, Arnd Bergmann wrote: > > > +#ifndef __KERNEL__ > > > struct snd_rawmidi_status { > > > int stream; > > > + unsigned char pad1[sizeof(time_t) - sizeof(int)]; > > > struct timespec tstamp; /* Timestamp */ > > > size_t avail; /* available bytes */ > > > size_t xruns; /* count of overruns since last > > > status (in bytes) */ > > > unsigned char reserved[16]; /* reserved for future use */ > > > }; > > > > Can we use union instead of padding? Something like: > > > > struct snd_rawmidi_status { > > union { > > int stream; > > time_t stream_alignment; > > }; > > struct timespec tstamp; /* Timestamp */ > > > > I think this would work most of the time, though I don't feel this is more > readable than the other version. > > More importantly, it requires compiling user applications with GNU extensions > (--std=gnu89 or higher) or C11, but not C99, so this could be a problem > for some applications. OK, fair enough. > If you feel there is a problem with the padding syntax, how about enclosing > it in a typedef like: > > typedef struct { char pad[sizeof(time_t) - sizeof(int)]; } __time_pad; > > This typedef could be used in several structures from the other patches > as well. Yes, that improves the readability. thanks, Takashi ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [PATCH v6 2/8] ALSA: Avoid using timespec for struct snd_timer_status
On Tue, Nov 12, 2019 at 4:42 PM Takashi Iwai wrote: > > @@ -761,6 +761,7 @@ struct snd_timer_params { > > unsigned char reserved[60]; /* reserved */ > > }; > > > > +#ifndef __KERNEL__ > > struct snd_timer_status { > > struct timespec tstamp; /* Timestamp - last update */ > > unsigned int resolution;/* current period resolution in ns */ > > Do we need this ifndef? Is it for stopping the reference of struct > snd_timer_status from the kernel code but only 32 and 64 variants? Well spotted, this is indeed a very recent change I did to the patch. The idea here is to hide any use of 'time_t', 'timespec' and 'timeval' from kernel compilation. These types are now defined in an incompatible way by libc, so we have to remove them from the kernel's uapi headers. I would prefer to remove them completely from the kernel (rather than moving them from uapi to internal headers) to make it harder to write y2038-incompatible code, and with the 90 patches I sent this week, all users are gone from the kernel (this series was the last part). Interestingly, hiding snd_timer_status from the drivers /also/ caught a but in a file when I had missed a reference that needed to be converted to snd_timer_status64. Arnd ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [alsa-devel] [PATCH v6 5/8] ALSA: Avoid using timespec for struct snd_rawmidi_status
On Tue, Nov 12, 2019 at 5:38 PM Takashi Iwai wrote: > On Tue, 12 Nov 2019 16:16:39 +0100, Arnd Bergmann wrote: > > +#ifndef __KERNEL__ > > struct snd_rawmidi_status { > > int stream; > > + unsigned char pad1[sizeof(time_t) - sizeof(int)]; > > struct timespec tstamp; /* Timestamp */ > > size_t avail; /* available bytes */ > > size_t xruns; /* count of overruns since last > > status (in bytes) */ > > unsigned char reserved[16]; /* reserved for future use */ > > }; > > Can we use union instead of padding? Something like: > > struct snd_rawmidi_status { > union { > int stream; > time_t stream_alignment; > }; > struct timespec tstamp; /* Timestamp */ > I think this would work most of the time, though I don't feel this is more readable than the other version. More importantly, it requires compiling user applications with GNU extensions (--std=gnu89 or higher) or C11, but not C99, so this could be a problem for some applications. If you feel there is a problem with the padding syntax, how about enclosing it in a typedef like: typedef struct { char pad[sizeof(time_t) - sizeof(int)]; } __time_pad; This typedef could be used in several structures from the other patches as well. Arnd ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [PATCH 14/16] drm/msm: avoid using 'timespec'
On Fri, Nov 08, 2019 at 10:32:52PM +0100, Arnd Bergmann wrote: > The timespec structure and associated interfaces are deprecated and will > be removed in the future because of the y2038 overflow. > > The use of ktime_to_timespec() in timeout_to_jiffies() does not > suffer from that overflow, but is easy to avoid by just converting > the ktime_t into jiffies directly. This seems good to me. y2038 changes are the best changes. Reviewed-by: Jordan Crouse > Signed-off-by: Arnd Bergmann > --- > drivers/gpu/drm/msm/msm_drv.h | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h > index 71547e756e29..740bf7c70d8f 100644 > --- a/drivers/gpu/drm/msm/msm_drv.h > +++ b/drivers/gpu/drm/msm/msm_drv.h > @@ -454,8 +454,7 @@ static inline unsigned long timeout_to_jiffies(const > ktime_t *timeout) > remaining_jiffies = 0; > } else { > ktime_t rem = ktime_sub(*timeout, now); > - struct timespec ts = ktime_to_timespec(rem); > - remaining_jiffies = timespec_to_jiffies(); > + remaining_jiffies = ktime_divns(rem, NSEC_PER_SEC / HZ); > } > > return remaining_jiffies; > -- > 2.20.0 > -- The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [PATCH v6 2/8] ALSA: Avoid using timespec for struct snd_timer_status
On Tue, 12 Nov 2019 16:16:36 +0100, Arnd Bergmann wrote: > > From: Baolin Wang > > struct snd_timer_status uses 'timespec' type variables to record > timestamp, which will be changed to an incompatible layout with > updated user space using 64-bit time_t. > > To handle both the old and the new layout on 32-bit architectures, > this patch introduces 'struct snd_timer_status32' and 'struct > snd_timer_status64' > to handle 32bit time_t and 64bit time_t in native mode and compat mode, > which replaces timespec with s64 type. > > When glibc changes time_t to 64-bit, any recompiled program will issue > ioctl commands that the kernel does not understand without this patch. > > Signed-off-by: Baolin Wang > Signed-off-by: Arnd Bergmann > --- > include/uapi/sound/asound.h | 2 ++ > sound/core/timer.c | 62 + > sound/core/timer_compat.c | 57 -- > 3 files changed, 64 insertions(+), 57 deletions(-) > > diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h > index df1153cea0b7..930854f67fd3 100644 > --- a/include/uapi/sound/asound.h > +++ b/include/uapi/sound/asound.h > @@ -761,6 +761,7 @@ struct snd_timer_params { > unsigned char reserved[60]; /* reserved */ > }; > > +#ifndef __KERNEL__ > struct snd_timer_status { > struct timespec tstamp; /* Timestamp - last update */ > unsigned int resolution;/* current period resolution in ns */ Do we need this ifndef? Is it for stopping the reference of struct snd_timer_status from the kernel code but only 32 and 64 variants? thanks, Takashi ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [RFC 4/5] xfs: extend inode format for 40-bit timestamps
On Tue, Nov 12, 2019 at 4:02 PM Amir Goldstein wrote: > > On Tue, Nov 12, 2019 at 4:16 PM Christoph Hellwig wrote: > > > > Amir just send another patch dealing with the time stamps. I'd suggest > > you chime into the discussion in that thread. > > That's right I just posted the ext4 style extend to 34bits yesterday [1], > but I like your version so much better, so I will withdraw mine. Thanks! I guess we probably want part of both in the end. I considered adding wrappers for encoding and decoding the timestamp like yours but in the end went with open-coding that part. The difference is pretty minimal, should we leave it with the open-coded addition? One part that I was missing (as described in my changelog) is any versioning or feature flag, including the dynamically set sb->s_time_max value. From looking at your patch, I guess this is something we want. > Sorry I did not CC you nor Deepa nor y2038 list. > I did not think you were going to actually deal with specific filesystems. I was not going to, but in the process of cleaning up the remaining ioctls I came to xfs last week and thought it would be silly to extend the uapi but not the file system ;-) > I'd also like to hear people's thoughts about migration process. > Should the new feature be ro_compat as I defined it or incompat? > > If all agree that Arnd's format change is preferred, I can assist with > xfsprogs patches, tests or whatnot. Awesome, that would be great indeed! Arnd ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v6 3/8] ALSA: Avoid using timespec for struct snd_ctl_elem_value
From: Baolin Wang The struct snd_ctl_elem_value will use 'timespec' type variables to record timestamp, which is not year 2038 safe on 32bits system. Since there are no drivers will implemented the tstamp member of the struct snd_ctl_elem_value, and also the stucture size will not be changed if we change timespec to s64 for tstamp member of struct snd_ctl_elem_value. From Takashi's comments, "In the library, applications are not expected to access to this structure directly. The applications get opaque pointer to the structure and must use any control APIs to operate it. Actually the library produce no API to handle 'struct snd_ctl_elem_value.tstamp'. This means that we can drop this member from alsa-lib without decline of functionality." Thus we can simply remove the tstamp member to avoid using the type which is not year 2038 safe on 32bits system. Signed-off-by: Baolin Wang Signed-off-by: Arnd Bergmann --- include/uapi/sound/asound.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index 930854f67fd3..40a23d8418fe 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h @@ -957,8 +957,7 @@ struct snd_ctl_elem_value { } bytes; struct snd_aes_iec958 iec958; } value;/* RO */ - struct timespec tstamp; - unsigned char reserved[128-sizeof(struct timespec)]; + unsigned char reserved[128]; }; struct snd_ctl_tlv { -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v6 2/8] ALSA: Avoid using timespec for struct snd_timer_status
From: Baolin Wang struct snd_timer_status uses 'timespec' type variables to record timestamp, which will be changed to an incompatible layout with updated user space using 64-bit time_t. To handle both the old and the new layout on 32-bit architectures, this patch introduces 'struct snd_timer_status32' and 'struct snd_timer_status64' to handle 32bit time_t and 64bit time_t in native mode and compat mode, which replaces timespec with s64 type. When glibc changes time_t to 64-bit, any recompiled program will issue ioctl commands that the kernel does not understand without this patch. Signed-off-by: Baolin Wang Signed-off-by: Arnd Bergmann --- include/uapi/sound/asound.h | 2 ++ sound/core/timer.c | 62 + sound/core/timer_compat.c | 57 -- 3 files changed, 64 insertions(+), 57 deletions(-) diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index df1153cea0b7..930854f67fd3 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h @@ -761,6 +761,7 @@ struct snd_timer_params { unsigned char reserved[60]; /* reserved */ }; +#ifndef __KERNEL__ struct snd_timer_status { struct timespec tstamp; /* Timestamp - last update */ unsigned int resolution;/* current period resolution in ns */ @@ -769,6 +770,7 @@ struct snd_timer_status { unsigned int queue; /* used queue size */ unsigned char reserved[64]; /* reserved */ }; +#endif #define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int) #define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id) diff --git a/sound/core/timer.c b/sound/core/timer.c index 29b99cfb5215..921f4ae2f9bf 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -65,6 +65,30 @@ struct snd_timer_user { struct mutex ioctl_lock; }; +struct snd_timer_status32 { + s32 tstamp_sec; /* Timestamp - last update */ + s32 tstamp_nsec; + unsigned int resolution;/* current period resolution in ns */ + unsigned int lost; /* counter of master tick lost */ + unsigned int overrun; /* count of read queue overruns */ + unsigned int queue; /* used queue size */ + unsigned char reserved[64]; /* reserved */ +}; + +#define SNDRV_TIMER_IOCTL_STATUS32 _IOR('T', 0x14, struct snd_timer_status32) + +struct snd_timer_status64 { + s64 tstamp_sec; /* Timestamp - last update */ + s64 tstamp_nsec; + unsigned int resolution;/* current period resolution in ns */ + unsigned int lost; /* counter of master tick lost */ + unsigned int overrun; /* count of read queue overruns */ + unsigned int queue; /* used queue size */ + unsigned char reserved[64]; /* reserved */ +}; + +#define SNDRV_TIMER_IOCTL_STATUS64 _IOR('T', 0x14, struct snd_timer_status64) + /* list of timers */ static LIST_HEAD(snd_timer_list); @@ -1861,17 +1885,41 @@ static int snd_timer_user_params(struct file *file, return err; } -static int snd_timer_user_status(struct file *file, -struct snd_timer_status __user *_status) +static int snd_timer_user_status32(struct file *file, + struct snd_timer_status32 __user *_status) + { + struct snd_timer_user *tu; + struct snd_timer_status32 status; + + tu = file->private_data; + if (!tu->timeri) + return -EBADFD; + memset(, 0, sizeof(status)); + status.tstamp_sec = tu->tstamp.tv_sec; + status.tstamp_nsec = tu->tstamp.tv_nsec; + status.resolution = snd_timer_resolution(tu->timeri); + status.lost = tu->timeri->lost; + status.overrun = tu->overrun; + spin_lock_irq(>qlock); + status.queue = tu->qused; + spin_unlock_irq(>qlock); + if (copy_to_user(_status, , sizeof(status))) + return -EFAULT; + return 0; +} + +static int snd_timer_user_status64(struct file *file, + struct snd_timer_status64 __user *_status) { struct snd_timer_user *tu; - struct snd_timer_status status; + struct snd_timer_status64 status; tu = file->private_data; if (!tu->timeri) return -EBADFD; memset(, 0, sizeof(status)); - status.tstamp = timespec64_to_timespec(tu->tstamp); + status.tstamp_sec = tu->tstamp.tv_sec; + status.tstamp_nsec = tu->tstamp.tv_nsec; status.resolution = snd_timer_resolution(tu->timeri); status.lost = tu->timeri->lost; status.overrun = tu->overrun; @@ -1995,8 +2043,10 @@ static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd, return snd_timer_user_info(file, argp); case SNDRV_TIMER_IOCTL_PARAMS: return
[Y2038] [PATCH v6 7/8] ALSA: move snd_pcm_ioctl_sync_ptr_compat into pcm_native.c
This is a preparation patch, moving the compat handler for snd_pcm_ioctl_sync_ptr_compat from pcm_compat.c to pcm_native.c. No other changes are indented. Signed-off-by: Baolin Wang Signed-off-by: Arnd Bergmann --- sound/core/pcm_compat.c | 98 -- sound/core/pcm_native.c | 101 2 files changed, 101 insertions(+), 98 deletions(-) diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 2671658442ea..6a2e5ea145e6 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -83,19 +83,6 @@ struct snd_pcm_sw_params32 { unsigned char reserved[56]; }; -/* recalcuate the boundary within 32bit */ -static snd_pcm_uframes_t recalculate_boundary(struct snd_pcm_runtime *runtime) -{ - snd_pcm_uframes_t boundary; - - if (! runtime->buffer_size) - return 0; - boundary = runtime->buffer_size; - while (boundary * 2 <= 0x7fffUL - runtime->buffer_size) - boundary *= 2; - return boundary; -} - static int snd_pcm_ioctl_sw_params_compat(struct snd_pcm_substream *substream, struct snd_pcm_sw_params32 __user *src) { @@ -388,91 +375,6 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream, return err; } - -struct snd_pcm_mmap_status32 { - s32 state; - s32 pad1; - u32 hw_ptr; - struct compat_timespec tstamp; - s32 suspended_state; - struct compat_timespec audio_tstamp; -} __attribute__((packed)); - -struct snd_pcm_mmap_control32 { - u32 appl_ptr; - u32 avail_min; -}; - -struct snd_pcm_sync_ptr32 { - u32 flags; - union { - struct snd_pcm_mmap_status32 status; - unsigned char reserved[64]; - } s; - union { - struct snd_pcm_mmap_control32 control; - unsigned char reserved[64]; - } c; -} __attribute__((packed)); - -static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream, -struct snd_pcm_sync_ptr32 __user *src) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - volatile struct snd_pcm_mmap_status *status; - volatile struct snd_pcm_mmap_control *control; - u32 sflags; - struct snd_pcm_mmap_control scontrol; - struct snd_pcm_mmap_status sstatus; - snd_pcm_uframes_t boundary; - int err; - - if (snd_BUG_ON(!runtime)) - return -EINVAL; - - if (get_user(sflags, >flags) || - get_user(scontrol.appl_ptr, >c.control.appl_ptr) || - get_user(scontrol.avail_min, >c.control.avail_min)) - return -EFAULT; - if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) { - err = snd_pcm_hwsync(substream); - if (err < 0) - return err; - } - status = runtime->status; - control = runtime->control; - boundary = recalculate_boundary(runtime); - if (! boundary) - boundary = 0x7fff; - snd_pcm_stream_lock_irq(substream); - /* FIXME: we should consider the boundary for the sync from app */ - if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) - control->appl_ptr = scontrol.appl_ptr; - else - scontrol.appl_ptr = control->appl_ptr % boundary; - if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) - control->avail_min = scontrol.avail_min; - else - scontrol.avail_min = control->avail_min; - sstatus.state = status->state; - sstatus.hw_ptr = status->hw_ptr % boundary; - sstatus.tstamp = status->tstamp; - sstatus.suspended_state = status->suspended_state; - sstatus.audio_tstamp = status->audio_tstamp; - snd_pcm_stream_unlock_irq(substream); - if (put_user(sstatus.state, >s.status.state) || - put_user(sstatus.hw_ptr, >s.status.hw_ptr) || - compat_put_timespec(, >s.status.tstamp) || - put_user(sstatus.suspended_state, >s.status.suspended_state) || - compat_put_timespec(_tstamp, - >s.status.audio_tstamp) || - put_user(scontrol.appl_ptr, >c.control.appl_ptr) || - put_user(scontrol.avail_min, >c.control.avail_min)) - return -EFAULT; - - return 0; -} - #ifdef CONFIG_X86_X32 /* X32 ABI has 64bit timespec and 64bit alignment */ struct snd_pcm_mmap_status_x32 { diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 2c8c9b91677a..cad90d9ce9da 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -4,6 +4,7 @@ * Copyright (c) by Jaroslav Kysela */ +#include #include #include #include @@ -2846,6 +2847,106 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream, return 0; } +#ifdef CONFIG_COMPAT +struct snd_pcm_mmap_status32 { + s32 state; + s32 pad1;
[Y2038] [PATCH v6 8/8] ALSA: add new 32-bit layout for snd_pcm_mmap_status/control
The snd_pcm_mmap_status and snd_pcm_mmap_control interfaces are one of the trickiest areas to get right when moving to 64-bit time_t in user space. The snd_pcm_mmap_status structure layout is incompatible with user space that uses a 64-bit time_t, so we need a new layout for it. Since the SNDRV_PCM_IOCTL_SYNC_PTR ioctl combines it with snd_pcm_mmap_control into snd_pcm_sync_ptr, we need to change those two as well. Both structures are also exported via an mmap() operation on certain architectures, and this suffers from incompatibility between 32-bit and 64-bit user space. As we have to change both structures anyway, this is a good opportunity to fix the mmap() problem as well, so let's standardize on the existing 64-bit layout of the structure where possible. The downside is that we lose mmap() support for existing 32-bit x86 and powerpc applications, adding that would introduce very noticeable runtime overhead and complexity. My assumption here is that not too many people will miss the removed feature, given that: - Almost all x86 and powerpc users these days are on 64-bit kernels, the majority of today's 32-bit users are on architectures that never supported mmap (ARM, MIPS, ...). - It never worked in compat mode (it was intentionally disabled there) - The application already needs to work with a fallback to SNDRV_PCM_IOCTL_SYNC_PTR, which will keep working with both the old and new structure layout. Both the ioctl() and mmap() based interfaces are changed at the same time, as they are based on the same structures. Unlike other interfaces, we change the uapi header to export both the traditional structure and a version that is portable between 32-bit and 64-bit user space code and that corresponds to the existing 64-bit layout. We further check the __USE_TIME_BITS64 macro that will be defined by future C library versions whenever we use the new time_t definition, so any existing user space source code will not see any changes until it gets rebuilt against a new C library. However, the new structures are all visible in addition to the old ones, allowing applications to explicitly request the new structures. In order to detect the difference between the old snd_pcm_mmap_status and the new __snd_pcm_mmap_status64 structure from the ioctl command number, we rely on one quirk in the structure definition: snd_pcm_mmap_status must be aligned to alignof(time_t), which leads the compiler to insert four bytes of padding in struct snd_pcm_sync_ptr after 'flags' and a corresponding change in the size of snd_pcm_sync_ptr itself. On x86-32 (and only there), the compiler doesn't use 64-bit alignment in structure, so I'm adding an explicit pad in the structure that has no effect on the existing 64-bit architectures but ensures that the layout matches for x86. The snd_pcm_uframes_t type compatibility requires another hack: we can't easily make that 64 bit wide, so I leave the type as 'unsigned long', but add padding before and after it, to ensure that the data is properly aligned to the respective 64-bit field in the in-kernel structure. For the SNDRV_PCM_MMAP_OFFSET_STATUS/CONTROL constants that are used as the virtual file offset in the mmap() function, we also have to introduce new constants that depend on hte __USE_TIME_BITS64 macro: The existing macros are renamed to SNDRV_PCM_MMAP_OFFSET_STATUS_OLD and SNDRV_PCM_MMAP_OFFSET_CONTROL_OLD, they continue to work fine on 64-bit architectures, but stop working on native 32-bit user space. The replacement _NEW constants are now used by default for user space built with __USE_TIME_BITS64, those now work on all new kernels for x86, ppc and alpha (32 and 64 bit, native and compat). It might be a good idea for a future alsa-lib to support both the _OLD and _NEW macros and use the corresponding structures directly. Unmodified alsa-lib source code will retain the current behavior, so it will no longer be able to use mmap() for the status/control structures on 32-bit systems, until either the C library gets updated to 64-bit time_t or alsa-lib gets updated to support both mmap() layouts. Co-developed-with: Baolin Wang Signed-off-by: Baolin Wang Signed-off-by: Arnd Bergmann --- include/uapi/sound/asound.h | 106 sound/core/pcm_compat.c | 30 +- sound/core/pcm_lib.c| 10 ++-- sound/core/pcm_native.c | 39 - 4 files changed, 143 insertions(+), 42 deletions(-) diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index 8ce73fb629e8..d26b70d0fb57 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h @@ -35,6 +35,8 @@ #include #endif +#include + /* * protocol version */ @@ -301,7 +303,9 @@ typedef int __bitwise snd_pcm_subformat_t; #define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x4000 /* internal kernel flag - trigger in drain */ #define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x8000 /* internal kernel flag - FIFO size is in frames
[Y2038] [PATCH v6 1/8] ALSA: Replace timespec with timespec64
From: Baolin Wang Since timespec is not year 2038 safe on 32bit system, and we need to convert all timespec variables to timespec64 type for sound subsystem. This patch is used to do preparation for following patches, that will convert all structures defined in uapi/sound/asound.h to use 64-bit time_t. Signed-off-by: Baolin Wang Signed-off-by: Arnd Bergmann --- include/sound/pcm.h | 18 include/sound/timer.h | 4 ++-- sound/core/pcm_lib.c | 36 +++ sound/core/pcm_native.c | 12 +++ sound/core/timer.c| 28 sound/pci/hda/hda_controller.c| 10 - sound/soc/intel/skylake/skl-pcm.c | 4 ++-- 7 files changed, 62 insertions(+), 50 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index bbe6eb1ff5d2..2665b3dc15e8 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -61,7 +61,7 @@ struct snd_pcm_ops { int (*trigger)(struct snd_pcm_substream *substream, int cmd); snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *substream); int (*get_time_info)(struct snd_pcm_substream *substream, - struct timespec *system_ts, struct timespec *audio_ts, + struct timespec64 *system_ts, struct timespec64 *audio_ts, struct snd_pcm_audio_tstamp_config *audio_tstamp_config, struct snd_pcm_audio_tstamp_report *audio_tstamp_report); int (*fill_silence)(struct snd_pcm_substream *substream, int channel, @@ -342,7 +342,7 @@ static inline void snd_pcm_pack_audio_tstamp_report(__u32 *data, __u32 *accuracy struct snd_pcm_runtime { /* -- Status -- */ struct snd_pcm_substream *trigger_master; - struct timespec trigger_tstamp; /* trigger timestamp */ + struct timespec64 trigger_tstamp; /* trigger timestamp */ bool trigger_tstamp_latched; /* trigger timestamp latched in low-level driver/hardware */ int overrange; snd_pcm_uframes_t avail_max; @@ -418,7 +418,7 @@ struct snd_pcm_runtime { /* -- audio timestamp config -- */ struct snd_pcm_audio_tstamp_config audio_tstamp_config; struct snd_pcm_audio_tstamp_report audio_tstamp_report; - struct timespec driver_tstamp; + struct timespec64 driver_tstamp; #if IS_ENABLED(CONFIG_SND_PCM_OSS) /* -- OSS things -- */ @@ -1151,22 +1151,22 @@ static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substrea } /** - * snd_pcm_gettime - Fill the timespec depending on the timestamp mode + * snd_pcm_gettime - Fill the timespec64 depending on the timestamp mode * @runtime: PCM runtime instance - * @tv: timespec to fill + * @tv: timespec64 to fill */ static inline void snd_pcm_gettime(struct snd_pcm_runtime *runtime, - struct timespec *tv) + struct timespec64 *tv) { switch (runtime->tstamp_type) { case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC: - ktime_get_ts(tv); + ktime_get_ts64(tv); break; case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW: - getrawmonotonic(tv); + ktime_get_raw_ts64(tv); break; default: - getnstimeofday(tv); + ktime_get_real_ts64(tv); break; } } diff --git a/include/sound/timer.h b/include/sound/timer.h index 199c36295a0d..357e30983284 100644 --- a/include/sound/timer.h +++ b/include/sound/timer.h @@ -89,7 +89,7 @@ struct snd_timer_instance { unsigned long ticks, unsigned long resolution); void (*ccallback) (struct snd_timer_instance * timeri, int event, - struct timespec * tstamp, + struct timespec64 * tstamp, unsigned long resolution); void (*disconnect)(struct snd_timer_instance *timeri); void *callback_data; @@ -113,7 +113,7 @@ struct snd_timer_instance { */ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, struct snd_timer **rtimer); -void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstamp); +void snd_timer_notify(struct snd_timer *timer, int event, struct timespec64 *tstamp); int snd_timer_global_new(char *id, int device, struct snd_timer **rtimer); int snd_timer_global_free(struct snd_timer *timer); int snd_timer_global_register(struct snd_timer *timer); diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index d80041ea4e01..42cc1b71d1e3 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -144,8 +144,12 @@ void __snd_pcm_xrun(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; trace_xrun(substream); - if (runtime->tstamp_mode ==
[Y2038] [PATCH v6 6/8] ALSA: Avoid using timespec for struct snd_timer_tread
From: Baolin Wang The struct snd_timer_tread will use 'timespec' type variables to record timestamp, which is not year 2038 safe on 32bits system. Since the struct snd_timer_tread is passed through read() rather than ioctl(), and the read syscall has no command number that lets us pick between the 32-bit or 64-bit version of this structure. Thus we introduced one new command SNDRV_TIMER_IOCTL_TREAD64 and new struct snd_timer_tread64 replacing timespec with s64 type to handle 64bit time_t. That means we will set tu->tread = TREAD_FORMAT_64BIT when user space has a 64bit time_t, then we will copy to user with struct snd_timer_tread64. Otherwise we will use 32bit time_t variables when copying to user. Moreover this patch replaces timespec type with timespec64 type and related y2038 safe APIs. Signed-off-by: Baolin Wang Signed-off-by: Arnd Bergmann --- include/uapi/sound/asound.h | 15 +++- sound/core/timer.c | 149 +++- sound/core/timer_compat.c | 5 +- 3 files changed, 130 insertions(+), 39 deletions(-) diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index cb830813da5d..8ce73fb629e8 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h @@ -780,7 +780,7 @@ struct snd_timer_status { #define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int) #define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id) -#define SNDRV_TIMER_IOCTL_TREAD_IOW('T', 0x02, int) +#define SNDRV_TIMER_IOCTL_TREAD_OLD_IOW('T', 0x02, int) #define SNDRV_TIMER_IOCTL_GINFO_IOWR('T', 0x03, struct snd_timer_ginfo) #define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams) #define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus) @@ -793,6 +793,15 @@ struct snd_timer_status { #define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1) #define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2) #define SNDRV_TIMER_IOCTL_PAUSE_IO('T', 0xa3) +#define SNDRV_TIMER_IOCTL_TREAD64 _IOW('T', 0xa4, int) + +#if __BITS_PER_LONG == 64 +#define SNDRV_TIMER_IOCTL_TREAD SNDRV_TIMER_IOCTL_TREAD_OLD +#else +#define SNDRV_TIMER_IOCTL_TREAD ((sizeof(__kernel_long_t) >= sizeof(time_t)) ? \ +SNDRV_TIMER_IOCTL_TREAD_OLD : \ +SNDRV_TIMER_IOCTL_TREAD64) +#endif struct snd_timer_read { unsigned int resolution; @@ -818,11 +827,15 @@ enum { SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10, }; +#ifndef __KERNEL__ struct snd_timer_tread { int event; + __u8 pad1[sizeof(time_t) - sizeof(int)]; struct timespec tstamp; unsigned int val; + __u8 pad2[sizeof(time_t) - sizeof(unsigned int)]; }; +#endif / * * diff --git a/sound/core/timer.c b/sound/core/timer.c index 921f4ae2f9bf..19a68cbbfbcb 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -44,6 +44,28 @@ MODULE_PARM_DESC(timer_tstamp_monotonic, "Use posix monotonic clock source for t MODULE_ALIAS_CHARDEV(CONFIG_SND_MAJOR, SNDRV_MINOR_TIMER); MODULE_ALIAS("devname:snd/timer"); +enum timer_tread_format { + TREAD_FORMAT_NONE = 0, + TREAD_FORMAT_TIME64, + TREAD_FORMAT_TIME32, +}; + +struct snd_timer_tread32 { + int event; + s32 tstamp_sec; + s32 tstamp_nsec; + unsigned int val; +}; + +struct snd_timer_tread64 { + int event; + u8 pad1[4]; + s64 tstamp_sec; + s64 tstamp_nsec; + unsigned int val; + u8 pad2[4]; +}; + struct snd_timer_user { struct snd_timer_instance *timeri; int tread; /* enhanced read with timestamps and events */ @@ -55,7 +77,7 @@ struct snd_timer_user { int queue_size; bool disconnected; struct snd_timer_read *queue; - struct snd_timer_tread *tqueue; + struct snd_timer_tread64 *tqueue; spinlock_t qlock; unsigned long last_resolution; unsigned int filter; @@ -1326,7 +1348,7 @@ static void snd_timer_user_interrupt(struct snd_timer_instance *timeri, } static void snd_timer_user_append_to_tqueue(struct snd_timer_user *tu, - struct snd_timer_tread *tread) + struct snd_timer_tread64 *tread) { if (tu->qused >= tu->queue_size) { tu->overrun++; @@ -1343,7 +1365,7 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri, unsigned long resolution) { struct snd_timer_user *tu = timeri->callback_data; - struct snd_timer_tread r1; + struct snd_timer_tread64 r1; unsigned long flags; if (event >= SNDRV_TIMER_EVENT_START && @@ -1353,7 +1375,8 @@ static
[Y2038] [PATCH v6 5/8] ALSA: Avoid using timespec for struct snd_rawmidi_status
From: Baolin Wang The struct snd_rawmidi_status will use 'timespec' type variables to record timestamp, which is not year 2038 safe on 32bits system. Thus we introduced 'struct snd_rawmidi_status32' and 'struct snd_rawmidi_status64' to handle 32bit time_t and 64bit time_t in native mode, which replace timespec with s64 type. In compat mode, we renamed or introduced new structures to handle 32bit/64bit time_t in compatible mode. The 'struct snd_rawmidi_status32' and snd_rawmidi_ioctl_status32() are used to handle 32bit time_t in compat mode. 'struct compat_snd_rawmidi_status64' is used to handle 64bit time_t. When glibc changes time_t to 64-bit, any recompiled program will issue ioctl commands that the kernel does not understand without this patch. Signed-off-by: Baolin Wang Signed-off-by: Arnd Bergmann --- include/uapi/sound/asound.h | 3 + sound/core/rawmidi.c| 132 sound/core/rawmidi_compat.c | 87 ++-- 3 files changed, 128 insertions(+), 94 deletions(-) diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index 7b74524f9406..cb830813da5d 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h @@ -651,13 +651,16 @@ struct snd_rawmidi_params { unsigned char reserved[16]; /* reserved for future use */ }; +#ifndef __KERNEL__ struct snd_rawmidi_status { int stream; + unsigned char pad1[sizeof(time_t) - sizeof(int)]; struct timespec tstamp; /* Timestamp */ size_t avail; /* available bytes */ size_t xruns; /* count of overruns since last status (in bytes) */ unsigned char reserved[16]; /* reserved for future use */ }; +#endif #define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int) #define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info) diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 8a12a7538d63..cd9bbb546846 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -50,6 +50,29 @@ static DEFINE_MUTEX(register_mutex); #define rmidi_dbg(rmidi, fmt, args...) \ dev_dbg(&(rmidi)->dev, fmt, ##args) +struct snd_rawmidi_status32 { + s32 stream; + s32 tstamp_sec; /* Timestamp */ + s32 tstamp_nsec; + u32 avail; /* available bytes */ + u32 xruns; /* count of overruns since last status (in bytes) */ + unsigned char reserved[16]; /* reserved for future use */ +}; + +#define SNDRV_RAWMIDI_IOCTL_STATUS32 _IOWR('W', 0x20, struct snd_rawmidi_status32) + +struct snd_rawmidi_status64 { + int stream; + u8 rsvd[4]; /* alignment */ + s64 tstamp_sec; /* Timestamp */ + s64 tstamp_nsec; + size_t avail; /* available bytes */ + size_t xruns; /* count of overruns since last status (in bytes) */ + unsigned char reserved[16]; /* reserved for future use */ +}; + +#define SNDRV_RAWMIDI_IOCTL_STATUS64 _IOWR('W', 0x20, struct snd_rawmidi_status64) + static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device) { struct snd_rawmidi *rawmidi; @@ -677,7 +700,7 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, EXPORT_SYMBOL(snd_rawmidi_input_params); static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream, -struct snd_rawmidi_status *status) +struct snd_rawmidi_status64 *status) { struct snd_rawmidi_runtime *runtime = substream->runtime; @@ -690,7 +713,7 @@ static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream, } static int snd_rawmidi_input_status(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_status *status) + struct snd_rawmidi_status64 *status) { struct snd_rawmidi_runtime *runtime = substream->runtime; @@ -704,6 +727,80 @@ static int snd_rawmidi_input_status(struct snd_rawmidi_substream *substream, return 0; } +static int snd_rawmidi_ioctl_status32(struct snd_rawmidi_file *rfile, + struct snd_rawmidi_status32 __user *argp) +{ + int err = 0; + struct snd_rawmidi_status32 __user *status = argp; + struct snd_rawmidi_status32 status32; + struct snd_rawmidi_status64 status64; + + if (copy_from_user(, argp, + sizeof(struct snd_rawmidi_status32))) + return -EFAULT; + + switch (status32.stream) { + case SNDRV_RAWMIDI_STREAM_OUTPUT: + if (rfile->output == NULL) + return -EINVAL; + err = snd_rawmidi_output_status(rfile->output, ); + break; + case
[Y2038] [PATCH v6 4/8] ALSA: Avoid using timespec for struct snd_pcm_status
From: Baolin Wang The struct snd_pcm_status will use 'timespec' type variables to record timestamp, which is not year 2038 safe on 32bits system. Userspace will use SNDRV_PCM_IOCTL_STATUS and SNDRV_PCM_IOCTL_STATUS_EXT as commands to issue ioctl() to fill the 'snd_pcm_status' structure in userspace. The command number is always defined through _IOR/_IOW/IORW, so when userspace changes the definition of 'struct timespec' to use 64-bit types, the command number also changes. Thus in the kernel, we now need to define two versions of each such ioctl and corresponding ioctl commands to handle 32bit time_t and 64bit time_t in native mode: struct snd_pcm_status32 { .. s32 trigger_tstamp_sec; s32 trigger_tstamp_nsec; .. s32 audio_tstamp_sec; s32 audio_tstamp_nsec; .. }; struct snd_pcm_status64 { .. s32 trigger_tstamp_sec; s32 trigger_tstamp_nsec; .. s32 audio_tstamp_sec; s32 audio_tstamp_nsec; .. }; Moreover in compat file, we renamed or introduced new structures to handle 32bit/64bit time_t in compatible mode. The 'struct snd_pcm_status32' and snd_pcm_status_user32() are used to handle 32bit time_t in compat mode. 'struct compat_snd_pcm_status64' and snd_pcm_status_user_compat64() are used to handle 64bit time_t. Finally we can replace SNDRV_PCM_IOCTL_STATUS and SNDRV_PCM_IOCTL_STATUS_EXT with new commands and introduce new functions to fill new 'struct snd_pcm_status64' instead of using unsafe 'struct snd_pcm_status'. Then in future, the new commands can be matched when userspace changes 'timespec' to 64bit type to make a size change of 'struct snd_pcm_status'. When glibc changes time_t to 64-bit, any recompiled program will issue ioctl commands that the kernel does not understand without this patch. Signed-off-by: Baolin Wang Signed-off-by: Arnd Bergmann --- include/sound/pcm.h | 56 - include/uapi/sound/asound.h | 3 + sound/core/pcm.c| 12 +-- sound/core/pcm_compat.c | 154 +--- sound/core/pcm_native.c | 96 ++ 5 files changed, 195 insertions(+), 126 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 2665b3dc15e8..3366128f42a2 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -44,6 +44,7 @@ struct snd_pcm_hardware { size_t fifo_size; /* fifo size in bytes */ }; +struct snd_pcm_status64; struct snd_pcm_substream; struct snd_pcm_audio_tstamp_config; /* definitions further down */ @@ -554,8 +555,8 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree); int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info); int snd_pcm_info_user(struct snd_pcm_substream *substream, struct snd_pcm_info __user *info); -int snd_pcm_status(struct snd_pcm_substream *substream, - struct snd_pcm_status *status); +int snd_pcm_status64(struct snd_pcm_substream *substream, +struct snd_pcm_status64 *status); int snd_pcm_start(struct snd_pcm_substream *substream); int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t status); int snd_pcm_drain_done(struct snd_pcm_substream *substream); @@ -1422,4 +1423,55 @@ static inline u64 pcm_format_to_bits(snd_pcm_format_t pcm_format) #define pcm_dbg(pcm, fmt, args...) \ dev_dbg((pcm)->card->dev, fmt, ##args) +struct snd_pcm_status64 { + snd_pcm_state_t state; /* stream state */ + u8 rsvd[4]; + s64 trigger_tstamp_sec; /* time when stream was started/stopped/paused */ + s64 trigger_tstamp_nsec; + s64 tstamp_sec; /* reference timestamp */ + s64 tstamp_nsec; + snd_pcm_uframes_t appl_ptr; /* appl ptr */ + snd_pcm_uframes_t hw_ptr; /* hw ptr */ + snd_pcm_sframes_t delay;/* current delay in frames */ + snd_pcm_uframes_t avail;/* number of frames available */ + snd_pcm_uframes_t avail_max;/* max frames available on hw since last status */ + snd_pcm_uframes_t overrange;/* count of ADC (capture) overrange detections from last status */ + snd_pcm_state_t suspended_state; /* suspended stream state */ + __u32 audio_tstamp_data; /* needed for 64-bit alignment, used for configs/report to/from userspace */ + s64 audio_tstamp_sec; /* sample counter, wall clock, PHC or on-demand sync'ed */ + s64 audio_tstamp_nsec; + s64 driver_tstamp_sec; /* useful in case reference system tstamp is reported with delay */ + s64 driver_tstamp_nsec; + __u32 audio_tstamp_accuracy;/* in ns units, only valid if indicated in audio_tstamp_data */ + unsigned char reserved[52-4*sizeof(s64)]; /* must be filled with zero */ +}; + +#define SNDRV_PCM_IOCTL_STATUS64 _IOR('A', 0x20,
[Y2038] [PATCH v6 0/8] Fix year 2038 issue for sound subsystem
This is a series I worked on with Baolin in 2017 and 2018, but we never quite managed to finish up the last pieces. During the ALSA developer meetup at ELC-E 2018 in Edinburgh, a decision was made to go with this approach for keeping best compatibility with existing source code, and then I failed to follow up by resending the patches. Now I have patches for all remaining time_t uses in the kernel, so it's absolutely time to revisit them. I have done more review of the patches myself and found a couple of minor issues that I have fixed up, otherwise the series is still the same as before. Conceptually, the idea of these patches is: - 64-bit applications should see no changes at all, neither compile-time nor run-time. - 32-bit code compiled with a 64-bit time_t currently does not work with ALSA, and requires kernel changes and/or sound/asound.h changes - Most 32-bit code using these interfaces will work correctly on a modified kernel, with or without the uapi header changes. - 32-bit code using SNDRV_TIMER_IOCTL_TREAD requires the updated header file for 64-bit time_t support - 32-bit i386 user space with 64-bit time_t is broken for SNDRV_PCM_IOCTL_STATUS, SNDRV_RAWMIDI_IOCTL_STATUS and SNDRV_PCM_IOCTL_SYNC_PTR because of i386 alignment. This is also addressed by the updated uapi header. - PCM mmap is currently supported on native x86 kernels (both 32-bit and 64-bit) but not for compat mode. This series breaks the 32-bit native mmap support for 32-bit time_t, but instead allows it for 64-bit time_t on both native and compat kernels. This seems to be the best trade-off, as mmap support is optional already, and most 32-bit code runs in compat mode anyway. - I've tried to avoid breaking compilation of 32-bit code as much as possible. Anything that does break however is likely code that is already broken on 64-bit time_t and needs source changes to fix them. I would like to propose merging this into the alsa tree after the v5.5 merge window for inclusion into v5.6, to allow a good amount of testing, in particular for the header changes that may cause problems for user space applications. A git branch with the same contents is available for testing at [1]. Please review and test! Arnd [1] https://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground.git y2038-alsa [2] https://lore.kernel.org/lkml/cak8p3a2os66+iwqyf97qh05w2jp8rmwao8zmkohixqvhvyy...@mail.gmail.com/T/#m6519cb07cfda08adf1dedea6596bb98892b4d5dc Changes since v5 (Arnd): - Rebased to linux-5.4-rc4 - Updated to completely remove timespec and time_t references from alsa - found and fixed a few bugs Changes since v4 (Baolin): - Add patch 5 to change trigger_tstamp member of struct snd_pcm_runtime. - Add patch 8 to change internal timespec. - Add more explanation in commit message. - Use ktime_get_real_ts64() in patch 6. - Split common code out into a separate function in patch 6. - Fix tu->tread bug in patch 6 and remove #if __BITS_PER_LONG == 64 macro. Changes since v3: - Move struct snd_pcm_status32 to pcm.h file. - Modify comments and commit message. - Add new patch2 ~ patch6. Changes since v2: - Renamed all structures to make clear. - Remove CONFIG_X86_X32 macro and introduced new compat_snd_pcm_status64_x86_32. Changes since v1: - Add one macro for struct snd_pcm_status_32 which only active in 32bits kernel. - Convert pcm_compat.c to use struct snd_pcm_status_64. - Convert pcm_native.c to use struct snd_pcm_status_64. --- Arnd Bergmann (2): ALSA: move snd_pcm_ioctl_sync_ptr_compat into pcm_native.c ALSA: add new 32-bit layout for snd_pcm_mmap_status/control Baolin Wang (6): ALSA: Replace timespec with timespec64 ALSA: Avoid using timespec for struct snd_timer_status ALSA: Avoid using timespec for struct snd_ctl_elem_value ALSA: Avoid using timespec for struct snd_pcm_status ALSA: Avoid using timespec for struct snd_rawmidi_status ALSA: Avoid using timespec for struct snd_timer_tread include/sound/pcm.h | 74 ++-- include/sound/timer.h | 4 +- include/uapi/sound/asound.h | 132 -- sound/core/pcm.c | 12 +- sound/core/pcm_compat.c | 282 -- sound/core/pcm_lib.c | 38 ++-- sound/core/pcm_native.c | 226 +--- sound/core/rawmidi.c | 132 +++--- sound/core/rawmidi_compat.c | 87 +++-- sound/core/timer.c| 229 ++-- sound/core/timer_compat.c | 62 +-- sound/pci/hda/hda_controller.c| 10 +- sound/soc/intel/skylake/skl-pcm.c | 4 +- 13 files changed, 804 insertions(+), 488 deletions(-) -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [RFC 4/5] xfs: extend inode format for 40-bit timestamps
On Tue, Nov 12, 2019 at 4:16 PM Christoph Hellwig wrote: > > Amir just send another patch dealing with the time stamps. I'd suggest > you chime into the discussion in that thread. That's right I just posted the ext4 style extend to 34bits yesterday [1], but I like your version so much better, so I will withdraw mine. Sorry I did not CC you nor Deepa nor y2038 list. I did not think you were going to actually deal with specific filesystems. I'd also like to hear people's thoughts about migration process. Should the new feature be ro_compat as I defined it or incompat? If all agree that Arnd's format change is preferred, I can assist with xfsprogs patches, tests or whatnot. Thanks, Amir. [1] https://lore.kernel.org/linux-xfs/20191112082524.ga18...@infradead.org/T/#mfa11ea3c035d4c21ec6a56b7c83a6dfa76e48068 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [RFC 4/5] xfs: extend inode format for 40-bit timestamps
Amir just send another patch dealing with the time stamps. I'd suggest you chime into the discussion in that thread. ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [RFC 1/5] xfs: [variant A] avoid time_t in user api
On Tue, Nov 12, 2019 at 01:09:06PM +0100, Arnd Bergmann wrote: > However, as long as two observations are true, a much simpler solution > can be used: > > 1. xfsprogs is the only user space project that has a copy of this header We can't guarantee that. > 2. xfsprogs already has a replacement for all three affected ioctl commands, >based on the xfs_bulkstat structure to pass 64-bit timestamps >regardless of the architecture XFS_IOC_BULKSTAT replaces XFS_IOC_FSBULKSTAT directly, and can replace XFS_IOC_FSBULKSTAT_SINGLE indirectly, so that is easy. Most users actually use the new one now through libfrog, although I found a user of the direct ioctl in the xfs_io tool, which could easily be fixed as well. XFS_IOC_SWAPEXT does not have a direct replacement, but the timestamp is only used to verify that the file did not change vs the previous stat. So not being able to represent > 2038 times is not a real problem anyway. At some point we should probably look into a file system independent defrag ioctl anyway, at which point we can deprecate XFS_IOC_SWAPEXT. > Based on those assumptions, changing xfs_bstime to use __kernel_long_t > instead of time_t in both the kernel and in xfsprogs preserves the current > ABI for any libc definition of time_t and solves the problem of passing > 64-bit timestamps to 32-bit user space. As said above their are not entirely true, but I still think this patch is the right thing to do, if only to get the time_t out of the ABI.. Reviewed-by: Christoph Hellwig ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [RFC 5/5] xfs: use 40-bit quota time limits
The quota handling in xfs is based around an in-memory representation of time_t, which overflows in year 2038 on 32-bit architectures, and an on-disk representation of __be32, which overflows in year 2106 based on interpreting the values as unsigned. Extend both to allow for much longer times: the in-memory representation should just use time64_t and the on-disk representation has to live with the spare bits in struct xfs_disk_dquot. As there is an unused 32-bit field, and three time limits in it, allocating 8 bits per timeout seems appropriate. Note: the quotactl() syscall is not affected by this, it has its own struct fs_disk_quota that may need a similar conversion. Signed-off-by: Arnd Bergmann --- fs/xfs/libxfs/xfs_dquot_buf.c | 6 +++--- fs/xfs/libxfs/xfs_format.h| 5 - fs/xfs/xfs_dquot.c| 29 - fs/xfs/xfs_qm.c | 18 -- fs/xfs/xfs_qm.h | 6 +++--- fs/xfs/xfs_qm_syscalls.c | 16 +++- fs/xfs/xfs_quotaops.c | 6 +++--- fs/xfs/xfs_trans_dquot.c | 17 +++-- 8 files changed, 67 insertions(+), 36 deletions(-) diff --git a/fs/xfs/libxfs/xfs_dquot_buf.c b/fs/xfs/libxfs/xfs_dquot_buf.c index e8bd688a4073..ee59c539f9ab 100644 --- a/fs/xfs/libxfs/xfs_dquot_buf.c +++ b/fs/xfs/libxfs/xfs_dquot_buf.c @@ -75,17 +75,17 @@ xfs_dquot_verify( if (ddq->d_blk_softlimit && be64_to_cpu(ddq->d_bcount) > be64_to_cpu(ddq->d_blk_softlimit) && - !ddq->d_btimer) + !ddq->d_btimer && !ddq->d_btimer_high) return __this_address; if (ddq->d_ino_softlimit && be64_to_cpu(ddq->d_icount) > be64_to_cpu(ddq->d_ino_softlimit) && - !ddq->d_itimer) + !ddq->d_itimer && !ddq->d_itimer_high) return __this_address; if (ddq->d_rtb_softlimit && be64_to_cpu(ddq->d_rtbcount) > be64_to_cpu(ddq->d_rtb_softlimit) && - !ddq->d_rtbtimer) + !ddq->d_rtbtimer && !ddq->d_rtbtimer_high) return __this_address; return NULL; diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index dc8d160775fb..83bd5166c0ee 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -1168,7 +1168,10 @@ typedef struct xfs_disk_dquot { __be32 d_btimer; /* similar to above; for disk blocks */ __be16 d_iwarns; /* warnings issued wrt num inodes */ __be16 d_bwarns; /* warnings issued wrt disk blocks */ - __be32 d_pad0; /* 64 bit align */ + __u8d_itimer_high; /* upper bits of d_itimer */ + __u8d_btimer_high; /* upper bits of d_btimer */ + __u8d_rtbtimer_high;/* upper bits of d_rtbtimer */ + __u8d_pad0; /* 64 bit align */ __be64 d_rtb_hardlimit;/* absolute limit on realtime blks */ __be64 d_rtb_softlimit;/* preferred limit on RT disk blks */ __be64 d_rtbcount; /* realtime blocks owned */ diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index aeb95e7391c1..15b5a339f6df 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -116,6 +116,8 @@ xfs_qm_adjust_dqtimers( xfs_mount_t *mp, xfs_disk_dquot_t*d) { + time64_t timer; + ASSERT(d->d_id); #ifdef DEBUG @@ -130,15 +132,17 @@ xfs_qm_adjust_dqtimers( be64_to_cpu(d->d_rtb_hardlimit)); #endif - if (!d->d_btimer) { + if (!d->d_btimer && !d->d_btimer_high) { if ((d->d_blk_softlimit && (be64_to_cpu(d->d_bcount) > be64_to_cpu(d->d_blk_softlimit))) || (d->d_blk_hardlimit && (be64_to_cpu(d->d_bcount) > be64_to_cpu(d->d_blk_hardlimit { - d->d_btimer = cpu_to_be32(get_seconds() + - mp->m_quotainfo->qi_btimelimit); + timer = ktime_get_real_seconds() + + mp->m_quotainfo->qi_btimelimit; + d->d_btimer = cpu_to_be32(lower_32_bits(timer)); + d->d_btimer_high = (u8)upper_32_bits(timer); } else { d->d_bwarns = 0; } @@ -150,18 +154,21 @@ xfs_qm_adjust_dqtimers( (be64_to_cpu(d->d_bcount) <= be64_to_cpu(d->d_blk_hardlimit { d->d_btimer = 0; + d->d_btimer_high = 0; } } - if (!d->d_itimer) { + if (!d->d_itimer && !d->d_itimer_high) { if ((d->d_ino_softlimit && (be64_to_cpu(d->d_icount) > be64_to_cpu(d->d_ino_softlimit))) || (d->d_ino_hardlimit &&
[Y2038] [RFC 4/5] xfs: extend inode format for 40-bit timestamps
XFS is the only major file system that lacks timestamps beyond year 2038, and is already being deployed in systems that may have to be supported beyond that time. Fortunately, the inode format still has a few reserved bits that can be used to extend the current format. There are two bits in the nanosecond portion that could be used in the same way that ext4 does, extending the timestamps until year 2378, as well as 12 unused bytes after the already allocated fields. There are four timestamps that need to be extended, so using four bytes out of the reserved space gets us all the way until year 36676, by extending the current 1902-2036 with another 255 epochs, which seems to be a reasonable range. I am not sure whether this change to the inode format requires a new version for the inode. All existing file system images remain compatible, while mounting a file systems with extended timestamps beyond 2038 would report that timestamp incorrectly in the 1902 through 2038 range, matching the traditional Linux behavior of wrapping timestamps. Signed-off-by: Arnd Bergmann --- fs/xfs/libxfs/xfs_format.h | 6 +- fs/xfs/libxfs/xfs_inode_buf.c | 28 fs/xfs/libxfs/xfs_inode_buf.h | 1 + fs/xfs/libxfs/xfs_log_format.h | 6 +- fs/xfs/libxfs/xfs_trans_inode.c | 3 ++- fs/xfs/xfs_inode.c | 3 ++- fs/xfs/xfs_inode_item.c | 10 +++--- fs/xfs/xfs_iops.c | 3 ++- fs/xfs/xfs_itable.c | 2 +- fs/xfs/xfs_super.c | 2 +- 10 files changed, 46 insertions(+), 18 deletions(-) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index c968b60cee15..dc8d160775fb 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -883,7 +883,11 @@ typedef struct xfs_dinode { __be64 di_lsn; /* flush sequence */ __be64 di_flags2; /* more random flags */ __be32 di_cowextsize; /* basic cow extent size for file */ - __u8di_pad2[12];/* more padding for future expansion */ + __u8di_atime_hi;/* upper 8 bits of di_atime */ + __u8di_mtime_hi;/* upper 8 bits of di_mtime */ + __u8di_ctime_hi;/* upper 8 bits of di_ctime */ + __u8di_crtime_hi; /* upper 8 bits of di_crtime */ + __u8di_pad2[8]; /* more padding for future expansion */ /* fields only written to during inode creation */ xfs_timestamp_t di_crtime; /* time created */ diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index 28ab3c5255e1..4989b6f1ac6f 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c @@ -228,16 +228,19 @@ xfs_inode_from_disk( to->di_flushiter = be16_to_cpu(from->di_flushiter); /* -* Time is signed, so need to convert to signed 32 bit before -* storing in inode timestamp which may be 64 bit. Otherwise -* a time before epoch is converted to a time long after epoch -* on 64 bit systems. +* The supported time range starts at INT_MIN, corresponding to +* year 1902. With the traditional low 32 bits, this ends in +* year 2038, the extra 8 bits extend it by another 255 epochs +* of 136.1 years each, up to year 36744. */ - inode->i_atime.tv_sec = (int)be32_to_cpu(from->di_atime.t_sec); + inode->i_atime.tv_sec = be32_to_cpu(from->di_atime.t_sec) + + ((u64)from->di_atime_hi << 32); inode->i_atime.tv_nsec = (int)be32_to_cpu(from->di_atime.t_nsec); - inode->i_mtime.tv_sec = (int)be32_to_cpu(from->di_mtime.t_sec); + inode->i_mtime.tv_sec = (int)be32_to_cpu(from->di_mtime.t_sec) + + ((u64)from->di_mtime_hi << 32); inode->i_mtime.tv_nsec = (int)be32_to_cpu(from->di_mtime.t_nsec); - inode->i_ctime.tv_sec = (int)be32_to_cpu(from->di_ctime.t_sec); + inode->i_ctime.tv_sec = (int)be32_to_cpu(from->di_ctime.t_sec) + + ((u64)from->di_ctime_hi << 32); inode->i_ctime.tv_nsec = (int)be32_to_cpu(from->di_ctime.t_nsec); inode->i_generation = be32_to_cpu(from->di_gen); inode->i_mode = be16_to_cpu(from->di_mode); @@ -256,7 +259,8 @@ xfs_inode_from_disk( if (to->di_version == 3) { inode_set_iversion_queried(inode, be64_to_cpu(from->di_changecount)); - to->di_crtime.t_sec = be32_to_cpu(from->di_crtime.t_sec); + to->di_crtime.t_sec = be32_to_cpu(from->di_crtime.t_sec) + + ((u64)from->di_crtime_hi << 32); to->di_crtime.t_nsec = be32_to_cpu(from->di_crtime.t_nsec); to->di_flags2 = be64_to_cpu(from->di_flags2); to->di_cowextsize = be32_to_cpu(from->di_cowextsize); @@ -284,10
[Y2038] [RFC 1/5] xfs: [variant A] avoid time_t in user api
The ioctl definitions for XFS_IOC_SWAPEXT, XFS_IOC_FSBULKSTAT and XFS_IOC_FSBULKSTAT_SINGLE are part of libxfs and based on time_t. The definition for time_t differs between current kernels and coming 32-bit libc variants that define it as 64-bit. For most ioctls, that means the kernel has to be able to handle two different command codes based on the different structure sizes. The same solution could be applied for XFS_IOC_SWAPEXT, but it would not work for XFS_IOC_FSBULKSTAT and XFS_IOC_FSBULKSTAT_SINGLE because the structure with the time_t is passed through an indirect pointer, and the command number itself is based on struct xfs_fsop_bulkreq, which does not differ based on time_t. This means any solution that can be applied requires a change of the ABI definition in the xfs_fs.h header file, as well as doing the same change in any user application that contains a copy of this header. The usual solution would be to define a replacement structure and use conditional compilation for the ioctl command codes to use one or the other, such as #define XFS_IOC_FSBULKSTAT_OLD _IOWR('X', 101, struct xfs_fsop_bulkreq) #define XFS_IOC_FSBULKSTAT_NEW _IOWR('X', 129, struct xfs_fsop_bulkreq) #define XFS_IOC_FSBULKSTAT ((sizeof(time_t) == sizeof(__kernel_long_t)) ? \ XFS_IOC_FSBULKSTAT_OLD : XFS_IOC_FSBULKSTAT_NEW) After this, the kernel would be able to implement both XFS_IOC_FSBULKSTAT_OLD and XFS_IOC_FSBULKSTAT_NEW handlers on 32-bit architectures with the correct ABI for either definition of time_t. However, as long as two observations are true, a much simpler solution can be used: 1. xfsprogs is the only user space project that has a copy of this header 2. xfsprogs already has a replacement for all three affected ioctl commands, based on the xfs_bulkstat structure to pass 64-bit timestamps regardless of the architecture Based on those assumptions, changing xfs_bstime to use __kernel_long_t instead of time_t in both the kernel and in xfsprogs preserves the current ABI for any libc definition of time_t and solves the problem of passing 64-bit timestamps to 32-bit user space. If either of the two assumptions is invalid, more discussion is needed for coming up with a way to fix as much of the affected user space code as possible. Signed-off-by: Arnd Bergmann --- fs/xfs/libxfs/xfs_fs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index e9371a8e0e26..4c4330f6e653 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -324,7 +324,7 @@ typedef struct xfs_growfs_rt { * Structures returned from ioctl XFS_IOC_FSBULKSTAT & XFS_IOC_FSBULKSTAT_SINGLE */ typedef struct xfs_bstime { - time_t tv_sec; /* seconds */ + __kernel_long_t tv_sec; /* seconds */ __s32 tv_nsec;/* and nanoseconds */ } xfs_bstime_t; -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [RFC 0/5] xfs: y2038 conversion
This is part of a longer set of changes to clean up the last remaining bits for the y2038 conversion. In XFS, three distinct problems need to be addressed: 1. The use of time_t in kernel sources -- I'm in the process of removing all of them so we can remove the definition itself, making it harder to write new y2038-unsafe code. This part is trivially done as a side-effect of the other two. 2. The use of time_t in a user API header for ioctls. When building against a new 32-bit libc with 64-bit time_t, the structures no longer match and we get incorrect data from ioctls. Unfortunately, there is no good way to fix XFS_IOC_FSBULKSTAT, I considered different approaches and in the end came up with three variants that are all part of this series. The idea is to pick just one of course. 3. On-disk timestamps hitting the y2038 limit. This applies to both inode timestamps and quota data. Both are extended to 40 bits, with the minimum timestamp still being year 1902, and the maximum getting extended from 2038 to 36744. Please review and let me know which of ioctl API changes makes the most sense. I have not done any actual runtime testing on the patches, so this is clearly too late for the next merge window, but I hope to get it all merged for v5.6. Arnd Arnd Bergmann (5): xfs: [variant A] avoid time_t in user api xfs: [variant B] add time64 version of xfs_bstat xfs: [variant C] avoid i386-misaligned xfs_bstat xfs: extend inode format for 40-bit timestamps xfs: use 40-bit quota time limits fs/xfs/libxfs/xfs_dquot_buf.c | 6 +- fs/xfs/libxfs/xfs_format.h | 11 +- fs/xfs/libxfs/xfs_fs.h | 37 +- fs/xfs/libxfs/xfs_inode_buf.c | 28 +++-- fs/xfs/libxfs/xfs_inode_buf.h | 1 + fs/xfs/libxfs/xfs_log_format.h | 6 +- fs/xfs/libxfs/xfs_trans_inode.c | 3 +- fs/xfs/xfs_dquot.c | 29 +++-- fs/xfs/xfs_inode.c | 3 +- fs/xfs/xfs_inode_item.c | 10 +- fs/xfs/xfs_ioctl.c | 195 +++- fs/xfs/xfs_ioctl.h | 12 ++ fs/xfs/xfs_ioctl32.c| 160 +- fs/xfs/xfs_ioctl32.h| 26 ++--- fs/xfs/xfs_iops.c | 3 +- fs/xfs/xfs_itable.c | 2 +- fs/xfs/xfs_qm.c | 18 ++- fs/xfs/xfs_qm.h | 6 +- fs/xfs/xfs_qm_syscalls.c| 16 ++- fs/xfs/xfs_quotaops.c | 6 +- fs/xfs/xfs_super.c | 2 +- fs/xfs/xfs_trans_dquot.c| 17 ++- 22 files changed, 387 insertions(+), 210 deletions(-) -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [RFC 2/5] xfs: [variant B] add time64 version of xfs_bstat
The ioctl definitions for XFS_IOC_SWAPEXT, XFS_IOC_FSBULKSTAT and XFS_IOC_FSBULKSTAT_SINGLE are part of libxfs and based on time_t. The definition for time_t differs between current kernels and coming 32-bit libc variants that define it as 64-bit. For most ioctls, that means the kernel has to be able to handle two different command codes based on the different structure sizes. The same solution is be applied for XFS_IOC_SWAPEXT, but it would does work for XFS_IOC_FSBULKSTAT and XFS_IOC_FSBULKSTAT_SINGLE because the structure with the time_t is passed through an indirect pointer, and the command number itself is based on struct xfs_fsop_bulkreq, which does not differ based on time_t. The best workaround I could come up with is to change the header file to define new command numbers with the same structure and have users pick one or the other at compile-time based on the time_t definition in the C library, like: #define XFS_IOC_FSBULKSTAT_OLD _IOWR('X', 101, struct xfs_fsop_bulkreq) #define XFS_IOC_FSBULKSTAT_NEW _IOWR('X', 129, struct xfs_fsop_bulkreq) #define XFS_IOC_FSBULKSTAT ((sizeof(time_t) == sizeof(__kernel_long_t)) ? \ XFS_IOC_FSBULKSTAT_OLD : XFS_IOC_FSBULKSTAT_NEW) The native xfs_ioctl now handles both the time32 and the time64 version of the xfs_bstat data structure, and this gets called indirectly by the compat code implementing the xfs_fsop_bulkreq commands. For x86, we still need another implementation to deal with the broken alignment, so the existing code is left in ioctl32 but changed to now handle the misaligned time64 structure. Based on the requirement to change the header file, a much simpler fix would be to change the time_t reference to 'long' and always keep passing the shorter timestamp as on 32-bit applications using the old ioctl, forcing code changes to use the v5 API to access post-y2038 timestamps, and still requiring the updated header when building with a new C library. Signed-off-by: Arnd Bergmann --- Note: I have not tested this patch beyond compiling it, for now this is for discussion, to decide which approach makes more sense. --- fs/xfs/libxfs/xfs_fs.h | 19 +++- fs/xfs/xfs_ioctl.c | 195 +++-- fs/xfs/xfs_ioctl.h | 12 +++ fs/xfs/xfs_ioctl32.c | 82 ++--- fs/xfs/xfs_ioctl32.h | 26 +++--- 5 files changed, 278 insertions(+), 56 deletions(-) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index 4c4330f6e653..9310576a45e5 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -324,8 +324,13 @@ typedef struct xfs_growfs_rt { * Structures returned from ioctl XFS_IOC_FSBULKSTAT & XFS_IOC_FSBULKSTAT_SINGLE */ typedef struct xfs_bstime { - __kernel_long_t tv_sec; /* seconds */ +#ifdef __KERNEL__ + __s64 tv_sec; /* seconds */ __s32 tv_nsec;/* and nanoseconds */ +#else + time_t tv_sec; /* seconds */ + __s32 tv_nsec;/* and nanoseconds */ +#endif } xfs_bstime_t; struct xfs_bstat { @@ -775,8 +780,8 @@ struct xfs_scrub_metadata { * ioctl commands that replace IRIX syssgi()'s */ #define XFS_IOC_FSGEOMETRY_V1 _IOR ('X', 100, struct xfs_fsop_geom_v1) -#define XFS_IOC_FSBULKSTAT _IOWR('X', 101, struct xfs_fsop_bulkreq) -#define XFS_IOC_FSBULKSTAT_SINGLE_IOWR('X', 102, struct xfs_fsop_bulkreq) +#define XFS_IOC_FSBULKSTAT_OLD _IOWR('X', 101, struct xfs_fsop_bulkreq) +#define XFS_IOC_FSBULKSTAT_SINGLE_OLD _IOWR('X', 102, struct xfs_fsop_bulkreq) #define XFS_IOC_FSINUMBERS _IOWR('X', 103, struct xfs_fsop_bulkreq) #define XFS_IOC_PATH_TO_FSHANDLE _IOWR('X', 104, struct xfs_fsop_handlereq) #define XFS_IOC_PATH_TO_HANDLE _IOWR('X', 105, struct xfs_fsop_handlereq) @@ -805,6 +810,14 @@ struct xfs_scrub_metadata { #define XFS_IOC_FSGEOMETRY _IOR ('X', 126, struct xfs_fsop_geom) #define XFS_IOC_BULKSTAT_IOR ('X', 127, struct xfs_bulkstat_req) #define XFS_IOC_INUMBERS_IOR ('X', 128, struct xfs_inumbers_req) +#define XFS_IOC_FSBULKSTAT_NEW _IOWR('X', 129, struct xfs_fsop_bulkreq) +#define XFS_IOC_FSBULKSTAT_SINGLE_NEW _IOWR('X', 130, struct xfs_fsop_bulkreq) + +#define XFS_IOC_FSBULKSTAT ((sizeof(time_t) == sizeof(__kernel_long_t)) ? \ + XFS_IOC_FSBULKSTAT_OLD : XFS_IOC_FSBULKSTAT_NEW) +#define XFS_IOC_FSBULKSTAT_SINGLE ((sizeof(time_t) == sizeof(__kernel_long_t)) ? \ + XFS_IOC_FSBULKSTAT_OLD : XFS_IOC_FSBULKSTAT_NEW) + /* XFS_IOC_GETFSUUID -- deprecated 140 */ diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index d58f0d6a699e..d50135760622 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -24,6 +24,7 @@ #include "xfs_export.h" #include "xfs_trace.h" #include "xfs_icache.h" +#include "xfs_ioctl.h"