diff mbox series

[V7,03/20] compat: consolidate the compat_flock{, 64} definition

Message ID 20220227162831.674483-4-guoren@kernel.org (mailing list archive)
State New, archived
Headers show
Series riscv: compat: Add COMPAT mode support for rv64 | expand

Commit Message

Guo Ren Feb. 27, 2022, 4:28 p.m. UTC
From: Christoph Hellwig <hch@lst.de>

Provide a single common definition for the compat_flock and
compat_flock64 structures using the same tricks as for the native
variants.  Another extra define is added for the packing required on
x86.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Guo Ren <guoren@kernel.org>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm64/include/asm/compat.h   | 16 ----------------
 arch/mips/include/asm/compat.h    | 19 ++-----------------
 arch/parisc/include/asm/compat.h  | 16 ----------------
 arch/powerpc/include/asm/compat.h | 16 ----------------
 arch/s390/include/asm/compat.h    | 16 ----------------
 arch/sparc/include/asm/compat.h   | 18 +-----------------
 arch/x86/include/asm/compat.h     | 20 +++-----------------
 include/linux/compat.h            | 31 +++++++++++++++++++++++++++++++
 8 files changed, 37 insertions(+), 115 deletions(-)

Comments

David Laight Feb. 28, 2022, 6:40 a.m. UTC | #1
From: guoren@kernel.org
> Sent: 27 February 2022 16:28
> 
> From: Christoph Hellwig <hch@lst.de>
> 
> Provide a single common definition for the compat_flock and
> compat_flock64 structures using the same tricks as for the native
> variants.  Another extra define is added for the packing required on
> x86.
...
> diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
...
>  /*
> - * IA32 uses 4 byte alignment for 64 bit quantities,
> - * so we need to pack this structure.
> + * IA32 uses 4 byte alignment for 64 bit quantities, so we need to pack the
> + * compat flock64 structure.
>   */
...
> +#define __ARCH_NEED_COMPAT_FLOCK64_PACKED
> 
>  struct compat_statfs {
>  	int		f_type;
> diff --git a/include/linux/compat.h b/include/linux/compat.h
> index 1c758b0e0359..a0481fe6c5d5 100644
> --- a/include/linux/compat.h
> +++ b/include/linux/compat.h
> @@ -258,6 +258,37 @@ struct compat_rlimit {
>  	compat_ulong_t	rlim_max;
>  };
> 
> +#ifdef __ARCH_NEED_COMPAT_FLOCK64_PACKED
> +#define __ARCH_COMPAT_FLOCK64_PACK	__attribute__((packed))
> +#else
> +#define __ARCH_COMPAT_FLOCK64_PACK
> +#endif
...
> +struct compat_flock64 {
> +	short		l_type;
> +	short		l_whence;
> +	compat_loff_t	l_start;
> +	compat_loff_t	l_len;
> +	compat_pid_t	l_pid;
> +#ifdef __ARCH_COMPAT_FLOCK64_PAD
> +	__ARCH_COMPAT_FLOCK64_PAD
> +#endif
> +} __ARCH_COMPAT_FLOCK64_PACK;
> +

Provided compat_loff_t are correctly defined with __aligned__(4)
marking the structure packed isn't needed.
I believe compat_u64 and compat_s64 both have aligned(4).
It is also wrong, consider:

struct foo {
	char x;
	struct compat_flock64 fl64;
};

There should be 3 bytes of padding after 'x'.
But you've removed it.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
Guo Ren Feb. 28, 2022, 11:51 a.m. UTC | #2
On Mon, Feb 28, 2022 at 2:40 PM David Laight <David.Laight@aculab.com> wrote:
>
> From: guoren@kernel.org
> > Sent: 27 February 2022 16:28
> >
> > From: Christoph Hellwig <hch@lst.de>
> >
> > Provide a single common definition for the compat_flock and
> > compat_flock64 structures using the same tricks as for the native
> > variants.  Another extra define is added for the packing required on
> > x86.
> ...
> > diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
> ...
> >  /*
> > - * IA32 uses 4 byte alignment for 64 bit quantities,
> > - * so we need to pack this structure.
> > + * IA32 uses 4 byte alignment for 64 bit quantities, so we need to pack the
> > + * compat flock64 structure.
> >   */
> ...
> > +#define __ARCH_NEED_COMPAT_FLOCK64_PACKED
> >
> >  struct compat_statfs {
> >       int             f_type;
> > diff --git a/include/linux/compat.h b/include/linux/compat.h
> > index 1c758b0e0359..a0481fe6c5d5 100644
> > --- a/include/linux/compat.h
> > +++ b/include/linux/compat.h
> > @@ -258,6 +258,37 @@ struct compat_rlimit {
> >       compat_ulong_t  rlim_max;
> >  };
> >
> > +#ifdef __ARCH_NEED_COMPAT_FLOCK64_PACKED
> > +#define __ARCH_COMPAT_FLOCK64_PACK   __attribute__((packed))
> > +#else
> > +#define __ARCH_COMPAT_FLOCK64_PACK
> > +#endif
> ...
> > +struct compat_flock64 {
> > +     short           l_type;
> > +     short           l_whence;
> > +     compat_loff_t   l_start;
> > +     compat_loff_t   l_len;
> > +     compat_pid_t    l_pid;
> > +#ifdef __ARCH_COMPAT_FLOCK64_PAD
> > +     __ARCH_COMPAT_FLOCK64_PAD
> > +#endif
> > +} __ARCH_COMPAT_FLOCK64_PACK;
> > +
>
> Provided compat_loff_t are correctly defined with __aligned__(4)
See include/asm-generic/compat.h

typedef s64 compat_loff_t;

Only:
#ifdef CONFIG_COMPAT_FOR_U64_ALIGNMENT
typedef s64 __attribute__((aligned(4))) compat_s64;

So how do you think compat_loff_t could be defined with __aligned__(4)?

> marking the structure packed isn't needed.
> I believe compat_u64 and compat_s64 both have aligned(4).
> It is also wrong, consider:
>
> struct foo {
>         char x;
>         struct compat_flock64 fl64;
> };
>
> There should be 3 bytes of padding after 'x'.
> But you've removed it.
>
>         David
>
> -
> Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
> Registration No: 1397386 (Wales)
>
David Laight Feb. 28, 2022, 12:02 p.m. UTC | #3
From: Guo Ren
> Sent: 28 February 2022 11:52
> 
> On Mon, Feb 28, 2022 at 2:40 PM David Laight <David.Laight@aculab.com> wrote:
> >
> > From: guoren@kernel.org
> > > Sent: 27 February 2022 16:28
> > >
> > > From: Christoph Hellwig <hch@lst.de>
> > >
> > > Provide a single common definition for the compat_flock and
> > > compat_flock64 structures using the same tricks as for the native
> > > variants.  Another extra define is added for the packing required on
> > > x86.
> > ...
> > > diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
> > ...
> > >  /*
> > > - * IA32 uses 4 byte alignment for 64 bit quantities,
> > > - * so we need to pack this structure.
> > > + * IA32 uses 4 byte alignment for 64 bit quantities, so we need to pack the
> > > + * compat flock64 structure.
> > >   */
> > ...
> > > +#define __ARCH_NEED_COMPAT_FLOCK64_PACKED
> > >
> > >  struct compat_statfs {
> > >       int             f_type;
> > > diff --git a/include/linux/compat.h b/include/linux/compat.h
> > > index 1c758b0e0359..a0481fe6c5d5 100644
> > > --- a/include/linux/compat.h
> > > +++ b/include/linux/compat.h
> > > @@ -258,6 +258,37 @@ struct compat_rlimit {
> > >       compat_ulong_t  rlim_max;
> > >  };
> > >
> > > +#ifdef __ARCH_NEED_COMPAT_FLOCK64_PACKED
> > > +#define __ARCH_COMPAT_FLOCK64_PACK   __attribute__((packed))
> > > +#else
> > > +#define __ARCH_COMPAT_FLOCK64_PACK
> > > +#endif
> > ...
> > > +struct compat_flock64 {
> > > +     short           l_type;
> > > +     short           l_whence;
> > > +     compat_loff_t   l_start;
> > > +     compat_loff_t   l_len;
> > > +     compat_pid_t    l_pid;
> > > +#ifdef __ARCH_COMPAT_FLOCK64_PAD
> > > +     __ARCH_COMPAT_FLOCK64_PAD
> > > +#endif
> > > +} __ARCH_COMPAT_FLOCK64_PACK;
> > > +
> >
> > Provided compat_loff_t are correctly defined with __aligned__(4)
> See include/asm-generic/compat.h
> 
> typedef s64 compat_loff_t;
> 
> Only:
> #ifdef CONFIG_COMPAT_FOR_U64_ALIGNMENT
> typedef s64 __attribute__((aligned(4))) compat_s64;
> 
> So how do you think compat_loff_t could be defined with __aligned__(4)?

compat_loff_t should be compat_s64 not s64.

The same should be done for all 64bit 'compat' types.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
Guo Ren Feb. 28, 2022, 12:13 p.m. UTC | #4
On Mon, Feb 28, 2022 at 8:02 PM David Laight <David.Laight@aculab.com> wrote:
>
> From: Guo Ren
> > Sent: 28 February 2022 11:52
> >
> > On Mon, Feb 28, 2022 at 2:40 PM David Laight <David.Laight@aculab.com> wrote:
> > >
> > > From: guoren@kernel.org
> > > > Sent: 27 February 2022 16:28
> > > >
> > > > From: Christoph Hellwig <hch@lst.de>
> > > >
> > > > Provide a single common definition for the compat_flock and
> > > > compat_flock64 structures using the same tricks as for the native
> > > > variants.  Another extra define is added for the packing required on
> > > > x86.
> > > ...
> > > > diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
> > > ...
> > > >  /*
> > > > - * IA32 uses 4 byte alignment for 64 bit quantities,
> > > > - * so we need to pack this structure.
> > > > + * IA32 uses 4 byte alignment for 64 bit quantities, so we need to pack the
> > > > + * compat flock64 structure.
> > > >   */
> > > ...
> > > > +#define __ARCH_NEED_COMPAT_FLOCK64_PACKED
> > > >
> > > >  struct compat_statfs {
> > > >       int             f_type;
> > > > diff --git a/include/linux/compat.h b/include/linux/compat.h
> > > > index 1c758b0e0359..a0481fe6c5d5 100644
> > > > --- a/include/linux/compat.h
> > > > +++ b/include/linux/compat.h
> > > > @@ -258,6 +258,37 @@ struct compat_rlimit {
> > > >       compat_ulong_t  rlim_max;
> > > >  };
> > > >
> > > > +#ifdef __ARCH_NEED_COMPAT_FLOCK64_PACKED
> > > > +#define __ARCH_COMPAT_FLOCK64_PACK   __attribute__((packed))
> > > > +#else
> > > > +#define __ARCH_COMPAT_FLOCK64_PACK
> > > > +#endif
> > > ...
> > > > +struct compat_flock64 {
> > > > +     short           l_type;
> > > > +     short           l_whence;
> > > > +     compat_loff_t   l_start;
> > > > +     compat_loff_t   l_len;
> > > > +     compat_pid_t    l_pid;
> > > > +#ifdef __ARCH_COMPAT_FLOCK64_PAD
> > > > +     __ARCH_COMPAT_FLOCK64_PAD
> > > > +#endif
> > > > +} __ARCH_COMPAT_FLOCK64_PACK;
> > > > +
> > >
> > > Provided compat_loff_t are correctly defined with __aligned__(4)
> > See include/asm-generic/compat.h
> >
> > typedef s64 compat_loff_t;
> >
> > Only:
> > #ifdef CONFIG_COMPAT_FOR_U64_ALIGNMENT
> > typedef s64 __attribute__((aligned(4))) compat_s64;
> >
> > So how do you think compat_loff_t could be defined with __aligned__(4)?
>
> compat_loff_t should be compat_s64 not s64.
>
> The same should be done for all 64bit 'compat' types.
Changing
typedef s64 compat_loff_t;
to
typedef compat_s64 compat_loff_t;

should be another patch and it affects all architectures, I don't
think we should involve it in this series.

look at kernel/power/user.c:
struct compat_resume_swap_area {
        compat_loff_t offset;
        u32 dev;
} __packed;

I thnk keep "typedef s64 compat_loff_t;" is a sensible choice for
COMPAT support patchset series.

>
>         David
>
> -
> Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
> Registration No: 1397386 (Wales)
--
Best Regards
 Guo Ren

ML: https://lore.kernel.org/linux-csky/
David Laight Feb. 28, 2022, 12:36 p.m. UTC | #5
From: Guo Ren
> Sent: 28 February 2022 12:13
> 
> On Mon, Feb 28, 2022 at 8:02 PM David Laight <David.Laight@aculab.com> wrote:
> >
> > From: Guo Ren
> > > Sent: 28 February 2022 11:52
> > >
> > > On Mon, Feb 28, 2022 at 2:40 PM David Laight <David.Laight@aculab.com> wrote:
> > > >
> > > > From: guoren@kernel.org
> > > > > Sent: 27 February 2022 16:28
> > > > >
> > > > > From: Christoph Hellwig <hch@lst.de>
> > > > >
> > > > > Provide a single common definition for the compat_flock and
> > > > > compat_flock64 structures using the same tricks as for the native
> > > > > variants.  Another extra define is added for the packing required on
> > > > > x86.
> > > > ...
> > > > > diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
> > > > ...
> > > > >  /*
> > > > > - * IA32 uses 4 byte alignment for 64 bit quantities,
> > > > > - * so we need to pack this structure.
> > > > > + * IA32 uses 4 byte alignment for 64 bit quantities, so we need to pack the
> > > > > + * compat flock64 structure.
> > > > >   */
> > > > ...
> > > > > +#define __ARCH_NEED_COMPAT_FLOCK64_PACKED
> > > > >
> > > > >  struct compat_statfs {
> > > > >       int             f_type;
> > > > > diff --git a/include/linux/compat.h b/include/linux/compat.h
> > > > > index 1c758b0e0359..a0481fe6c5d5 100644
> > > > > --- a/include/linux/compat.h
> > > > > +++ b/include/linux/compat.h
> > > > > @@ -258,6 +258,37 @@ struct compat_rlimit {
> > > > >       compat_ulong_t  rlim_max;
> > > > >  };
> > > > >
> > > > > +#ifdef __ARCH_NEED_COMPAT_FLOCK64_PACKED
> > > > > +#define __ARCH_COMPAT_FLOCK64_PACK   __attribute__((packed))
> > > > > +#else
> > > > > +#define __ARCH_COMPAT_FLOCK64_PACK
> > > > > +#endif
> > > > ...
> > > > > +struct compat_flock64 {
> > > > > +     short           l_type;
> > > > > +     short           l_whence;
> > > > > +     compat_loff_t   l_start;
> > > > > +     compat_loff_t   l_len;
> > > > > +     compat_pid_t    l_pid;
> > > > > +#ifdef __ARCH_COMPAT_FLOCK64_PAD
> > > > > +     __ARCH_COMPAT_FLOCK64_PAD
> > > > > +#endif
> > > > > +} __ARCH_COMPAT_FLOCK64_PACK;
> > > > > +
> > > >
> > > > Provided compat_loff_t are correctly defined with __aligned__(4)
> > > See include/asm-generic/compat.h
> > >
> > > typedef s64 compat_loff_t;
> > >
> > > Only:
> > > #ifdef CONFIG_COMPAT_FOR_U64_ALIGNMENT
> > > typedef s64 __attribute__((aligned(4))) compat_s64;
> > >
> > > So how do you think compat_loff_t could be defined with __aligned__(4)?
> >
> > compat_loff_t should be compat_s64 not s64.
> >
> > The same should be done for all 64bit 'compat' types.
> Changing
> typedef s64 compat_loff_t;
> to
> typedef compat_s64 compat_loff_t;
> 
> should be another patch and it affects all architectures, I don't
> think we should involve it in this series.

Except that I think only x86 sets CONFIG_COMPAT_FOR_U64_ALIGNMENT.

> look at kernel/power/user.c:
> struct compat_resume_swap_area {
>         compat_loff_t offset;
>         u32 dev;
> } __packed;

That is a bug!
The size should be 16 bytes on most 32bit architectures.
So the compat code won't fault if the last 4 bytes aren't mapped
whereas the native 32bit version will fault.

Hopefully the compiler realises the on-stack item is actually
aligned and doesn't use byte loads and shifts on (eg) sparc64.

> I thnk keep "typedef s64 compat_loff_t;" is a sensible choice for
> COMPAT support patchset series.

But it is wrong :-)

compat_[su]64 exist so that compat syscalls that contain 64bit
values get the correct alignment.
Which is exactly what you have here.

AFAICT most of the uses of __packed in the kernel are wrong.
It should only be used (on a structure) if the structure might
be on a misaligned address.
This can happen in data for some network protocols.
It should not be used because the structure should have no holes.
(Especially in ones that don't have any holes.)

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
Arnd Bergmann Feb. 28, 2022, 12:51 p.m. UTC | #6
On Mon, Feb 28, 2022 at 1:13 PM Guo Ren <guoren@kernel.org> wrote:
> On Mon, Feb 28, 2022 at 8:02 PM David Laight <David.Laight@aculab.com> wrote:
> > From: Guo Ren Sent: 28 February 2022 11:52
> > > On Mon, Feb 28, 2022 at 2:40 PM David Laight <David.Laight@aculab.com> wrote:
> > > > ...
> > > > > +struct compat_flock64 {
> > > > > +     short           l_type;
> > > > > +     short           l_whence;
> > > > > +     compat_loff_t   l_start;
> > > > > +     compat_loff_t   l_len;
> > > > > +     compat_pid_t    l_pid;
> > > > > +#ifdef __ARCH_COMPAT_FLOCK64_PAD
> > > > > +     __ARCH_COMPAT_FLOCK64_PAD
> > > > > +#endif
> > > > > +} __ARCH_COMPAT_FLOCK64_PACK;
> > > > > +
> > > >
> > > > Provided compat_loff_t are correctly defined with __aligned__(4)
> > > See include/asm-generic/compat.h
> > >
> > > typedef s64 compat_loff_t;
> > >
> > > Only:
> > > #ifdef CONFIG_COMPAT_FOR_U64_ALIGNMENT
> > > typedef s64 __attribute__((aligned(4))) compat_s64;
> > >
> > > So how do you think compat_loff_t could be defined with __aligned__(4)?
> >
> > compat_loff_t should be compat_s64 not s64.
> >
> > The same should be done for all 64bit 'compat' types.
> Changing
> typedef s64 compat_loff_t;
> to
> typedef compat_s64 compat_loff_t;
>
> should be another patch and it affects all architectures, I don't
> think we should involve it in this series.

Agreed, your patch (originally from Christoph) looks fine, it correctly
transforms the seven copies of the structure into a shared version.

There is always more that can be improved, but for this series,
I think you have already done enough.

> look at kernel/power/user.c:
> struct compat_resume_swap_area {
>         compat_loff_t offset;
>         u32 dev;
> } __packed;
>
> I thnk keep "typedef s64 compat_loff_t;" is a sensible choice for
> COMPAT support patchset series.

The only references to compat_loff_t that we have in the kernel
could all be simplified by defining compat_loff_t as compat_s64
instead of s64, but it has no impact on correctness here.

Let's make sure you get your series into 5.18, and then David can
follow-up with any further cleanups after that.

         Arnd
diff mbox series

Patch

diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
index 276328765408..e0faec1984a1 100644
--- a/arch/arm64/include/asm/compat.h
+++ b/arch/arm64/include/asm/compat.h
@@ -65,22 +65,6 @@  struct compat_stat {
 	compat_ulong_t	__unused4[2];
 };
 
-struct compat_flock {
-	short		l_type;
-	short		l_whence;
-	compat_off_t	l_start;
-	compat_off_t	l_len;
-	compat_pid_t	l_pid;
-};
-
-struct compat_flock64 {
-	short		l_type;
-	short		l_whence;
-	compat_loff_t	l_start;
-	compat_loff_t	l_len;
-	compat_pid_t	l_pid;
-};
-
 struct compat_statfs {
 	int		f_type;
 	int		f_bsize;
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h
index 6a350c1f70d7..6d6e5a451f4d 100644
--- a/arch/mips/include/asm/compat.h
+++ b/arch/mips/include/asm/compat.h
@@ -55,23 +55,8 @@  struct compat_stat {
 	s32		st_pad4[14];
 };
 
-struct compat_flock {
-	short		l_type;
-	short		l_whence;
-	compat_off_t	l_start;
-	compat_off_t	l_len;
-	s32		l_sysid;
-	compat_pid_t	l_pid;
-	s32		pad[4];
-};
-
-struct compat_flock64 {
-	short		l_type;
-	short		l_whence;
-	compat_loff_t	l_start;
-	compat_loff_t	l_len;
-	compat_pid_t	l_pid;
-};
+#define __ARCH_COMPAT_FLOCK_EXTRA_SYSID		s32 l_sysid;
+#define __ARCH_COMPAT_FLOCK_PAD			s32 pad[4];
 
 struct compat_statfs {
 	int		f_type;
diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h
index c04f5a637c39..a1e4534d8050 100644
--- a/arch/parisc/include/asm/compat.h
+++ b/arch/parisc/include/asm/compat.h
@@ -53,22 +53,6 @@  struct compat_stat {
 	u32			st_spare4[3];
 };
 
-struct compat_flock {
-	short			l_type;
-	short			l_whence;
-	compat_off_t		l_start;
-	compat_off_t		l_len;
-	compat_pid_t		l_pid;
-};
-
-struct compat_flock64 {
-	short			l_type;
-	short			l_whence;
-	compat_loff_t		l_start;
-	compat_loff_t		l_len;
-	compat_pid_t		l_pid;
-};
-
 struct compat_statfs {
 	s32		f_type;
 	s32		f_bsize;
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h
index 83d8f70779cb..5ef3c7c83c34 100644
--- a/arch/powerpc/include/asm/compat.h
+++ b/arch/powerpc/include/asm/compat.h
@@ -44,22 +44,6 @@  struct compat_stat {
 	u32		__unused4[2];
 };
 
-struct compat_flock {
-	short		l_type;
-	short		l_whence;
-	compat_off_t	l_start;
-	compat_off_t	l_len;
-	compat_pid_t	l_pid;
-};
-
-struct compat_flock64 {
-	short		l_type;
-	short		l_whence;
-	compat_loff_t	l_start;
-	compat_loff_t	l_len;
-	compat_pid_t	l_pid;
-};
-
 struct compat_statfs {
 	int		f_type;
 	int		f_bsize;
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
index 0f14b3188b1b..07f04d37068b 100644
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/include/asm/compat.h
@@ -102,22 +102,6 @@  struct compat_stat {
 	u32		__unused5;
 };
 
-struct compat_flock {
-	short		l_type;
-	short		l_whence;
-	compat_off_t	l_start;
-	compat_off_t	l_len;
-	compat_pid_t	l_pid;
-};
-
-struct compat_flock64 {
-	short		l_type;
-	short		l_whence;
-	compat_loff_t	l_start;
-	compat_loff_t	l_len;
-	compat_pid_t	l_pid;
-};
-
 struct compat_statfs {
 	u32		f_type;
 	u32		f_bsize;
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h
index 108078751bb5..d78fb44942e0 100644
--- a/arch/sparc/include/asm/compat.h
+++ b/arch/sparc/include/asm/compat.h
@@ -75,23 +75,7 @@  struct compat_stat64 {
 	unsigned int	__unused5;
 };
 
-struct compat_flock {
-	short		l_type;
-	short		l_whence;
-	compat_off_t	l_start;
-	compat_off_t	l_len;
-	compat_pid_t	l_pid;
-	short		__unused;
-};
-
-struct compat_flock64 {
-	short		l_type;
-	short		l_whence;
-	compat_loff_t	l_start;
-	compat_loff_t	l_len;
-	compat_pid_t	l_pid;
-	short		__unused;
-};
+#define __ARCH_COMPAT_FLOCK_PAD		short __unused;
 
 struct compat_statfs {
 	int		f_type;
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
index 8d19a212f4f2..de794d895866 100644
--- a/arch/x86/include/asm/compat.h
+++ b/arch/x86/include/asm/compat.h
@@ -50,25 +50,11 @@  struct compat_stat {
 	u32		__unused5;
 };
 
-struct compat_flock {
-	short		l_type;
-	short		l_whence;
-	compat_off_t	l_start;
-	compat_off_t	l_len;
-	compat_pid_t	l_pid;
-};
-
 /*
- * IA32 uses 4 byte alignment for 64 bit quantities,
- * so we need to pack this structure.
+ * IA32 uses 4 byte alignment for 64 bit quantities, so we need to pack the
+ * compat flock64 structure.
  */
-struct compat_flock64 {
-	short		l_type;
-	short		l_whence;
-	compat_loff_t	l_start;
-	compat_loff_t	l_len;
-	compat_pid_t	l_pid;
-} __attribute__((packed));
+#define __ARCH_NEED_COMPAT_FLOCK64_PACKED
 
 struct compat_statfs {
 	int		f_type;
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 1c758b0e0359..a0481fe6c5d5 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -258,6 +258,37 @@  struct compat_rlimit {
 	compat_ulong_t	rlim_max;
 };
 
+#ifdef __ARCH_NEED_COMPAT_FLOCK64_PACKED
+#define __ARCH_COMPAT_FLOCK64_PACK	__attribute__((packed))
+#else
+#define __ARCH_COMPAT_FLOCK64_PACK
+#endif
+
+struct compat_flock {
+	short			l_type;
+	short			l_whence;
+	compat_off_t		l_start;
+	compat_off_t		l_len;
+#ifdef __ARCH_COMPAT_FLOCK_EXTRA_SYSID
+	__ARCH_COMPAT_FLOCK_EXTRA_SYSID
+#endif
+	compat_pid_t		l_pid;
+#ifdef __ARCH_COMPAT_FLOCK_PAD
+	__ARCH_COMPAT_FLOCK_PAD
+#endif
+};
+
+struct compat_flock64 {
+	short		l_type;
+	short		l_whence;
+	compat_loff_t	l_start;
+	compat_loff_t	l_len;
+	compat_pid_t	l_pid;
+#ifdef __ARCH_COMPAT_FLOCK64_PAD
+	__ARCH_COMPAT_FLOCK64_PAD
+#endif
+} __ARCH_COMPAT_FLOCK64_PACK;
+
 struct compat_rusage {
 	struct old_timeval32 ru_utime;
 	struct old_timeval32 ru_stime;