2013-05-09 04:00:55

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH] x86: make stat/statfs 64-bit for x86_64 kernels

When including these headers in the x32 ABI, the structs get declared
with 32bit sizes which is incorrect. Use long long and such to make
it work both with x32 and x86_64.

Signed-off-by: Mike Frysinger <[email protected]>
---
arch/x86/include/uapi/asm/stat.h | 38 +++++++++++++++++++-------------------
arch/x86/include/uapi/asm/statfs.h | 5 +++++
2 files changed, 24 insertions(+), 19 deletions(-)

diff --git a/arch/x86/include/uapi/asm/stat.h b/arch/x86/include/uapi/asm/stat.h
index 7b3ddc3..e9d6951 100644
--- a/arch/x86/include/uapi/asm/stat.h
+++ b/arch/x86/include/uapi/asm/stat.h
@@ -78,26 +78,26 @@ struct stat64 {
#else /* __i386__ */

struct stat {
- unsigned long st_dev;
- unsigned long st_ino;
- unsigned long st_nlink;
-
- unsigned int st_mode;
- unsigned int st_uid;
- unsigned int st_gid;
- unsigned int __pad0;
- unsigned long st_rdev;
- long st_size;
- long st_blksize;
- long st_blocks; /* Number 512-byte blocks allocated. */
+ unsigned long long st_dev;
+ unsigned long long st_ino;
+ unsigned long long st_nlink;

- unsigned long st_atime;
- unsigned long st_atime_nsec;
- unsigned long st_mtime;
- unsigned long st_mtime_nsec;
- unsigned long st_ctime;
- unsigned long st_ctime_nsec;
- long __unused[3];
+ unsigned int st_mode;
+ unsigned int st_uid;
+ unsigned int st_gid;
+ unsigned int __pad0;
+ unsigned long long st_rdev;
+ long long st_size;
+ long long st_blksize;
+ long long st_blocks; /* Number 512-byte blocks allocated. */
+
+ unsigned long long st_atime;
+ unsigned long long st_atime_nsec;
+ unsigned long long st_mtime;
+ unsigned long long st_mtime_nsec;
+ unsigned long long st_ctime;
+ unsigned long long st_ctime_nsec;
+ long long __unused[3];
};

/* We don't need to memset the whole thing just to initialize the padding */
diff --git a/arch/x86/include/uapi/asm/statfs.h b/arch/x86/include/uapi/asm/statfs.h
index 2d0adbf..3cb5744 100644
--- a/arch/x86/include/uapi/asm/statfs.h
+++ b/arch/x86/include/uapi/asm/statfs.h
@@ -8,5 +8,10 @@
*/
#define ARCH_PACK_COMPAT_STATFS64 __attribute__((packed,aligned(4)))

+/* For x86-64, both the 64bit and x32 ABIs have 64bit fields. */
+#ifdef __x86_64__
+#define __statfs_word __u64
+#endif
+
#include <asm-generic/statfs.h>
#endif /* _ASM_X86_STATFS_H */
--
1.8.2.1


2013-05-09 04:04:23

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH] x86: make stat/statfs 64-bit for x86_64 kernels

On 05/08/2013 09:00 PM, Mike Frysinger wrote:
> When including these headers in the x32 ABI, the structs get declared
> with 32bit sizes which is incorrect. Use long long and such to make
> it work both with x32 and x86_64.
>
> Signed-off-by: Mike Frysinger <[email protected]>

I'm not sure if it is okay to change the types, even within the same
size. Perhaps use __u64/__s64?

-hpa

2013-05-09 04:04:35

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH] x86: make stat/statfs 64-bit for x86_64 kernels

On 05/08/2013 09:00 PM, Mike Frysinger wrote:
> diff --git a/arch/x86/include/uapi/asm/statfs.h b/arch/x86/include/uapi/asm/statfs.h
> index 2d0adbf..3cb5744 100644
> --- a/arch/x86/include/uapi/asm/statfs.h
> +++ b/arch/x86/include/uapi/asm/statfs.h
> @@ -8,5 +8,10 @@
> */
> #define ARCH_PACK_COMPAT_STATFS64 __attribute__((packed,aligned(4)))
>
> +/* For x86-64, both the 64bit and x32 ABIs have 64bit fields. */
> +#ifdef __x86_64__
> +#define __statfs_word __u64
> +#endif
> +
> #include <asm-generic/statfs.h>
> #endif /* _ASM_X86_STATFS_H */
>

... or is this what you meant to use?

-hpa

2013-05-09 04:08:43

by Mike Frysinger

[permalink] [raw]
Subject: Re: [PATCH] x86: make stat/statfs 64-bit for x86_64 kernels

On Thursday 09 May 2013 00:04:03 H. Peter Anvin wrote:
> On 05/08/2013 09:00 PM, Mike Frysinger wrote:
> > When including these headers in the x32 ABI, the structs get declared
> > with 32bit sizes which is incorrect. Use long long and such to make
> > it work both with x32 and x86_64.
>
> I'm not sure if it is okay to change the types, even within the same
> size. Perhaps use __u64/__s64?

sorry, i don't follow. changing types isn't ok (unsigned long to unsigned
long long), but changing to __u64 is ok (unsigned long to __u64 which is
typedefed to unsigned long long) ?

i don't have a problem using __u64/__s64, i just don't understand your logic.
-mike


Attachments:
signature.asc (836.00 B)
This is a digitally signed message part.

2013-05-09 04:10:41

by Mike Frysinger

[permalink] [raw]
Subject: Re: [PATCH] x86: make stat/statfs 64-bit for x86_64 kernels

On Thursday 09 May 2013 00:04:28 H. Peter Anvin wrote:
> On 05/08/2013 09:00 PM, Mike Frysinger wrote:
> > --- a/arch/x86/include/uapi/asm/statfs.h
> > +++ b/arch/x86/include/uapi/asm/statfs.h
> > +/* For x86-64, both the 64bit and x32 ABIs have 64bit fields. */
> > +#ifdef __x86_64__
> > +#define __statfs_word __u64
> > +#endif
> > +
> >
> > #include <asm-generic/statfs.h>
> > #endif /* _ASM_X86_STATFS_H */
>
> ... or is this what you meant to use?

i didn't intend to use this for stat. that macro is a hook the common asm-
generic/statfs.h header provides for arches.

although maybe the better fix for statfs.h is to do:
--- a/include/uapi/asm-generic/statfs.h
+++ b/include/uapi/asm-generic/statfs.h
@@ -13,7 +13,7 @@
*/
#ifndef __statfs_word
#if __BITS_PER_LONG == 64
-#define __statfs_word long
+#define __statfs_word __u64
#else
#define __statfs_word __u32
#endif
-mike


Attachments:
signature.asc (836.00 B)
This is a digitally signed message part.

2013-05-09 04:18:23

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH] x86: make stat/statfs 64-bit for x86_64 kernels

On 05/08/2013 09:08 PM, Mike Frysinger wrote:
> On Thursday 09 May 2013 00:04:03 H. Peter Anvin wrote:
>> On 05/08/2013 09:00 PM, Mike Frysinger wrote:
>>> When including these headers in the x32 ABI, the structs get
>>> declared with 32bit sizes which is incorrect. Use long long
>>> and such to make it work both with x32 and x86_64.
>>
>> I'm not sure if it is okay to change the types, even within the
>> same size. Perhaps use __u64/__s64?
>
> sorry, i don't follow. changing types isn't ok (unsigned long to
> unsigned long long), but changing to __u64 is ok (unsigned long to
> __u64 which is typedefed to unsigned long long) ?
>
> i don't have a problem using __u64/__s64, i just don't understand
> your logic.
>

In userspace, __u64 is often defined as "unsigned long" on 64 bits.

-hpa

2013-05-09 05:13:14

by Mike Frysinger

[permalink] [raw]
Subject: Re: [PATCH] x86: make stat/statfs 64-bit for x86_64 kernels

On Thursday 09 May 2013 00:18:15 H. Peter Anvin wrote:
> On 05/08/2013 09:08 PM, Mike Frysinger wrote:
> > On Thursday 09 May 2013 00:04:03 H. Peter Anvin wrote:
> >> On 05/08/2013 09:00 PM, Mike Frysinger wrote:
> >>> When including these headers in the x32 ABI, the structs get
> >>> declared with 32bit sizes which is incorrect. Use long long
> >>> and such to make it work both with x32 and x86_64.
> >>
> >> I'm not sure if it is okay to change the types, even within the
> >> same size. Perhaps use __u64/__s64?
> >
> > sorry, i don't follow. changing types isn't ok (unsigned long to
> > unsigned long long), but changing to __u64 is ok (unsigned long to
> > __u64 which is typedefed to unsigned long long) ?
> >
> > i don't have a problem using __u64/__s64, i just don't understand
> > your logic.
>
> In userspace, __u64 is often defined as "unsigned long" on 64 bits.

my tests would seem to indicate otherwise, at least for x86:
$ gcc -E - <<<"#include <linux/types.h>" | grep '__u64;'
__extension__ typedef unsigned long long __u64;

$ gcc -m32 -E - <<<"#include <linux/types.h>" | grep '__u64;'
__extension__ typedef unsigned long long __u64;

$ gcc -mx32 -E - <<<"#include <linux/types.h>" | grep '__u64;'
__extension__ typedef unsigned long long __u64;

and doing a printf("%i\n", sizeof(__u64)) shows 8 for each of the above builds
-mike


Attachments:
signature.asc (836.00 B)
This is a digitally signed message part.

2013-05-09 05:45:13

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH] x86: make stat/statfs 64-bit for x86_64 kernels

Hm... Okay, I'm mistaken then. I guess it doesn't matter.

Mike Frysinger <[email protected]> wrote:

>On Thursday 09 May 2013 00:18:15 H. Peter Anvin wrote:
>> On 05/08/2013 09:08 PM, Mike Frysinger wrote:
>> > On Thursday 09 May 2013 00:04:03 H. Peter Anvin wrote:
>> >> On 05/08/2013 09:00 PM, Mike Frysinger wrote:
>> >>> When including these headers in the x32 ABI, the structs get
>> >>> declared with 32bit sizes which is incorrect. Use long long
>> >>> and such to make it work both with x32 and x86_64.
>> >>
>> >> I'm not sure if it is okay to change the types, even within the
>> >> same size. Perhaps use __u64/__s64?
>> >
>> > sorry, i don't follow. changing types isn't ok (unsigned long to
>> > unsigned long long), but changing to __u64 is ok (unsigned long to
>> > __u64 which is typedefed to unsigned long long) ?
>> >
>> > i don't have a problem using __u64/__s64, i just don't understand
>> > your logic.
>>
>> In userspace, __u64 is often defined as "unsigned long" on 64 bits.
>
>my tests would seem to indicate otherwise, at least for x86:
>$ gcc -E - <<<"#include <linux/types.h>" | grep '__u64;'
>__extension__ typedef unsigned long long __u64;
>
>$ gcc -m32 -E - <<<"#include <linux/types.h>" | grep '__u64;'
>__extension__ typedef unsigned long long __u64;
>
>$ gcc -mx32 -E - <<<"#include <linux/types.h>" | grep '__u64;'
>__extension__ typedef unsigned long long __u64;
>
>and doing a printf("%i\n", sizeof(__u64)) shows 8 for each of the above
>builds
>-mike

--
Sent from my mobile phone. Please excuse brevity and lack of formatting.