Re: [Y2038] [PATCH 13/16] hfs/hfsplus: use 64-bit inode timestamps

2019-11-12 Thread Viacheslav Dubeyko


> 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

2019-11-12 Thread Darrick J. Wong
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

2019-11-12 Thread Ernesto A . Fernández
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

2019-11-12 Thread Dave Chinner
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

2019-11-12 Thread Cyrill Gorcunov
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

2019-11-12 Thread Takashi Iwai
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

2019-11-12 Thread Takashi Iwai
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

2019-11-12 Thread Takashi Iwai
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

2019-11-12 Thread Arnd Bergmann
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

2019-11-12 Thread Arnd Bergmann
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'

2019-11-12 Thread Jordan Crouse
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

2019-11-12 Thread Takashi Iwai
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

2019-11-12 Thread Arnd Bergmann
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

2019-11-12 Thread Arnd Bergmann
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

2019-11-12 Thread Arnd Bergmann
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

2019-11-12 Thread Arnd Bergmann
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

2019-11-12 Thread Arnd Bergmann
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

2019-11-12 Thread Arnd Bergmann
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

2019-11-12 Thread Arnd Bergmann
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

2019-11-12 Thread Arnd Bergmann
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

2019-11-12 Thread Arnd Bergmann
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

2019-11-12 Thread Arnd Bergmann
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

2019-11-12 Thread Amir Goldstein
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

2019-11-12 Thread Christoph Hellwig
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

2019-11-12 Thread Christoph Hellwig
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

2019-11-12 Thread Arnd Bergmann
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

2019-11-12 Thread Arnd Bergmann
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

2019-11-12 Thread Arnd Bergmann
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

2019-11-12 Thread Arnd Bergmann
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

2019-11-12 Thread Arnd Bergmann
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"