linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] diskquota: 32bit quota tools on 64bit architectures
@ 2007-06-18  8:21 Vasily Tarasov
  2007-06-19 19:33 ` Andrew Morton
  0 siblings, 1 reply; 31+ messages in thread
From: Vasily Tarasov @ 2007-06-18  8:21 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Kirill Korotaev, Vasily Averin, OpenVZ Developers ML,
	Linux Kernel ML, Natalie Protasevich, Jan Kara

From: Vasily Tarasov <vtaras@openvz.org>

This patch should be applied after Arnd Bergmann's patch,
that intoduces new compat types: 
http://lkml.org/lkml/2007/6/15/98

OpenVZ Linux kernel team has discovered the problem 
with 32bit quota tools working on 64bit architectures.
In 2.6.10 kernel sys32_quotactl() function was replaced by sys_quotactl() with
the comment "sys_quotactl seems to be 32/64bit clean, enable it for 32bit"
However this isn't right. Look at if_dqblk structure:

struct if_dqblk {
        __u64 dqb_bhardlimit;
        __u64 dqb_bsoftlimit;
        __u64 dqb_curspace;
        __u64 dqb_ihardlimit;
        __u64 dqb_isoftlimit;
        __u64 dqb_curinodes;
        __u64 dqb_btime;
        __u64 dqb_itime;
        __u32 dqb_valid;
};

For 32 bit quota tools sizeof(if_dqblk) == 0x44.
But for 64 bit kernel its size is 0x48, 'cause of alignment!
Thus we got a problem. Attached patch reintroduce sys32_quotactl() function,
that handles this and related situations.

Signed-off-by: Vasily Tarasov <vtaras@openvz.org>

---

In OpenVZ technology 32 bit Virtual Environments over 
64 bit OS are common, hence we have customers, that complains on this bad quota
behaviour: 

# /usr/bin/quota
quota: error while getting quota from /dev/sda1 for 0: Success

The reason is caused above.

--- linux-2.6.22-rc4-fixed/arch/x86_64/ia32/ia32entry.S.orig	2007-06-14 15:55:24.000000000 +0400
+++ linux-2.6.22-rc4-fixed/arch/x86_64/ia32/ia32entry.S	2007-06-14 16:22:52.000000000 +0400
@@ -526,7 +526,7 @@ ia32_sys_call_table:
 	.quad sys_init_module
 	.quad sys_delete_module
 	.quad quiet_ni_syscall		/* 130  get_kernel_syms */
-	.quad sys_quotactl
+	.quad sys32_quotactl
 	.quad sys_getpgid
 	.quad sys_fchdir
 	.quad quiet_ni_syscall	/* bdflush */
--- linux-2.6.22-rc4-fixed/arch/ia64/ia32/ia32_entry.S.orig	2007-06-14 15:55:24.000000000 +0400
+++ linux-2.6.22-rc4-fixed/arch/ia64/ia32/ia32_entry.S	2007-06-14 16:22:52.000000000 +0400
@@ -304,7 +304,7 @@ ia32_syscall_table:
 	data8 sys_ni_syscall	/* init_module */
 	data8 sys_ni_syscall	/* delete_module */
 	data8 sys_ni_syscall	/* get_kernel_syms */  /* 130 */
-	data8 sys_quotactl
+	data8 sys32_quotactl
 	data8 sys_getpgid
 	data8 sys_fchdir
 	data8 sys_ni_syscall	/* sys_bdflush */
--- linux-2.6.22-rc4-fixed/fs/quota.c.orig	2007-06-14 15:55:26.000000000 +0400
+++ linux-2.6.22-rc4-fixed/fs/quota.c	2007-06-18 12:00:56.000000000 +0400
@@ -10,12 +10,14 @@
 #include <linux/slab.h>
 #include <asm/current.h>
 #include <asm/uaccess.h>
+#include <asm/compat.h>
 #include <linux/kernel.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/buffer_head.h>
 #include <linux/capability.h>
 #include <linux/quotaops.h>
+#include <linux/types.h>
 
 /* Check validity of generic quotactl commands */
 static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
@@ -384,3 +386,119 @@ asmlinkage long sys_quotactl(unsigned in
 
 	return ret;
 }
+
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+/*
+ * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
+ * and is necessary due to alignment problems.
+ */
+struct compat_if_dqblk {
+	compat_u64 dqb_bhardlimit;
+	compat_u64 dqb_bsoftlimit;
+	compat_u64 dqb_curspace;
+	compat_u64 dqb_ihardlimit;
+	compat_u64 dqb_isoftlimit;
+	compat_u64 dqb_curinodes;
+	compat_u64 dqb_btime;
+	compat_u64 dqb_itime;
+	compat_uint_t dqb_valid;
+};
+
+/* XFS structures */
+struct compat_fs_qfilestat {
+	compat_u64 dqb_bhardlimit;
+	compat_u64 qfs_nblks;
+	compat_uint_t qfs_nextents;
+};
+
+struct compat_fs_quota_stat {
+	__s8		qs_version;
+	__u16		qs_flags;
+	__s8		qs_pad;
+	struct compat_fs_qfilestat	qs_uquota;
+	struct compat_fs_qfilestat	qs_gquota;
+	compat_uint_t	qs_incoredqs;
+	compat_int_t	qs_btimelimit;
+	compat_int_t	qs_itimelimit;
+	compat_int_t	qs_rtbtimelimit;
+	__u16		qs_bwarnlimit;
+	__u16		qs_iwarnlimit;
+};
+
+asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
+						qid_t id, void __user *addr)
+{
+	unsigned int cmds;
+	struct if_dqblk __user *dqblk;
+	struct compat_if_dqblk __user *compat_dqblk;
+	struct fs_quota_stat __user *fsqstat;
+	struct compat_fs_quota_stat __user *compat_fsqstat;
+	compat_uint_t data;
+	u16 xdata;
+	long ret;
+
+	cmds = cmd >> SUBCMDSHIFT;
+
+	switch (cmds) {
+	case Q_GETQUOTA:
+		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
+		compat_dqblk = addr;
+		ret = sys_quotactl(cmd, special, id, dqblk);
+		if (ret)
+			break;
+		if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) ||
+			get_user(data, &dqblk->dqb_valid) ||
+			put_user(data, &compat_dqblk->dqb_valid))
+			ret = -EFAULT;
+		break;
+	case Q_SETQUOTA:
+		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
+		compat_dqblk = addr;
+		ret = -EFAULT;
+		if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) ||
+			get_user(data, &compat_dqblk->dqb_valid) ||
+			put_user(data, &dqblk->dqb_valid))
+			break;
+		ret = sys_quotactl(cmd, special, id, dqblk);
+		break;
+	case Q_XGETQSTAT:
+		fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat));
+		compat_fsqstat = addr;
+		ret = sys_quotactl(cmd, special, id, fsqstat);
+		if (ret)
+			break;
+		ret = -EFAULT;
+		/* Copying qs_version, qs_flags, qs_pad */
+		if (copy_in_user(compat_fsqstat, fsqstat,
+			offsetof(struct compat_fs_quota_stat, qs_uquota)))
+			break;
+		/* Copying qs_uquota */
+		if (copy_in_user(&compat_fsqstat->qs_uquota,
+			&fsqstat->qs_uquota,
+			sizeof(compat_fsqstat->qs_uquota)) ||
+			get_user(data, &fsqstat->qs_uquota.qfs_nextents) ||
+			put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents))
+			break;
+		/* Copying qs_gquota */
+		if (copy_in_user(&compat_fsqstat->qs_gquota,
+			&fsqstat->qs_gquota,
+			sizeof(compat_fsqstat->qs_gquota)) ||
+			get_user(data, &fsqstat->qs_gquota.qfs_nextents) ||
+			put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents))
+			break;
+		/* Copying the rest */
+		if (copy_in_user(&compat_fsqstat->qs_incoredqs,
+			&fsqstat->qs_incoredqs,
+			sizeof(struct compat_fs_quota_stat) -
+			offsetof(struct compat_fs_quota_stat, qs_incoredqs)) ||
+			get_user(xdata, &fsqstat->qs_iwarnlimit) ||
+			put_user(xdata, &compat_fsqstat->qs_iwarnlimit))
+			break;
+		ret = 0;
+		break;
+	default:
+		ret = sys_quotactl(cmd, special, id, addr);
+	}
+	return ret;
+}
+#endif

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2007-06-18  8:21 [PATCH] diskquota: 32bit quota tools on 64bit architectures Vasily Tarasov
@ 2007-06-19 19:33 ` Andrew Morton
  2007-06-19 20:09   ` Mikael Pettersson
  2007-06-19 22:34   ` David Miller
  0 siblings, 2 replies; 31+ messages in thread
From: Andrew Morton @ 2007-06-19 19:33 UTC (permalink / raw)
  To: Vasily Tarasov
  Cc: Kirill Korotaev, Vasily Averin, OpenVZ Developers ML,
	Linux Kernel ML, Natalie Protasevich, Jan Kara, linux-arch

On Mon, 18 Jun 2007 12:21:47 +0400
Vasily Tarasov <vtaras@openvz.org> wrote:

> From: Vasily Tarasov <vtaras@openvz.org>
> 
> This patch should be applied after Arnd Bergmann's patch,
> that intoduces new compat types: 
> http://lkml.org/lkml/2007/6/15/98
> 
> OpenVZ Linux kernel team has discovered the problem 
> with 32bit quota tools working on 64bit architectures.
> In 2.6.10 kernel sys32_quotactl() function was replaced by sys_quotactl() with
> the comment "sys_quotactl seems to be 32/64bit clean, enable it for 32bit"
> However this isn't right. Look at if_dqblk structure:
> 
> struct if_dqblk {
>         __u64 dqb_bhardlimit;
>         __u64 dqb_bsoftlimit;
>         __u64 dqb_curspace;
>         __u64 dqb_ihardlimit;
>         __u64 dqb_isoftlimit;
>         __u64 dqb_curinodes;
>         __u64 dqb_btime;
>         __u64 dqb_itime;
>         __u32 dqb_valid;
> };
> 
> For 32 bit quota tools sizeof(if_dqblk) == 0x44.
> But for 64 bit kernel its size is 0x48, 'cause of alignment!
> Thus we got a problem. Attached patch reintroduce sys32_quotactl() function,
> that handles this and related situations.
> 
> Signed-off-by: Vasily Tarasov <vtaras@openvz.org>
> 
> ---
> 
> In OpenVZ technology 32 bit Virtual Environments over 
> 64 bit OS are common, hence we have customers, that complains on this bad quota
> behaviour: 
> 
> # /usr/bin/quota
> quota: error while getting quota from /dev/sda1 for 0: Success
> 
> The reason is caused above.

Only x86_64 and ia64 are fixed.  Would it be correct to assume that the
other CONFIG_COMPAT architectures also need to be fixed?


> --- linux-2.6.22-rc4-fixed/arch/x86_64/ia32/ia32entry.S.orig	2007-06-14 15:55:24.000000000 +0400
> +++ linux-2.6.22-rc4-fixed/arch/x86_64/ia32/ia32entry.S	2007-06-14 16:22:52.000000000 +0400
> @@ -526,7 +526,7 @@ ia32_sys_call_table:
>  	.quad sys_init_module
>  	.quad sys_delete_module
>  	.quad quiet_ni_syscall		/* 130  get_kernel_syms */
> -	.quad sys_quotactl
> +	.quad sys32_quotactl
>  	.quad sys_getpgid
>  	.quad sys_fchdir
>  	.quad quiet_ni_syscall	/* bdflush */
> --- linux-2.6.22-rc4-fixed/arch/ia64/ia32/ia32_entry.S.orig	2007-06-14 15:55:24.000000000 +0400
> +++ linux-2.6.22-rc4-fixed/arch/ia64/ia32/ia32_entry.S	2007-06-14 16:22:52.000000000 +0400
> @@ -304,7 +304,7 @@ ia32_syscall_table:
>  	data8 sys_ni_syscall	/* init_module */
>  	data8 sys_ni_syscall	/* delete_module */
>  	data8 sys_ni_syscall	/* get_kernel_syms */  /* 130 */
> -	data8 sys_quotactl
> +	data8 sys32_quotactl
>  	data8 sys_getpgid
>  	data8 sys_fchdir
>  	data8 sys_ni_syscall	/* sys_bdflush */
> --- linux-2.6.22-rc4-fixed/fs/quota.c.orig	2007-06-14 15:55:26.000000000 +0400
> +++ linux-2.6.22-rc4-fixed/fs/quota.c	2007-06-18 12:00:56.000000000 +0400
> @@ -10,12 +10,14 @@
>  #include <linux/slab.h>
>  #include <asm/current.h>
>  #include <asm/uaccess.h>
> +#include <asm/compat.h>
>  #include <linux/kernel.h>
>  #include <linux/security.h>
>  #include <linux/syscalls.h>
>  #include <linux/buffer_head.h>
>  #include <linux/capability.h>
>  #include <linux/quotaops.h>
> +#include <linux/types.h>
>  
>  /* Check validity of generic quotactl commands */
>  static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
> @@ -384,3 +386,119 @@ asmlinkage long sys_quotactl(unsigned in
>  
>  	return ret;
>  }
> +
> +#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
> +/*
> + * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
> + * and is necessary due to alignment problems.
> + */
> +struct compat_if_dqblk {
> +	compat_u64 dqb_bhardlimit;
> +	compat_u64 dqb_bsoftlimit;
> +	compat_u64 dqb_curspace;
> +	compat_u64 dqb_ihardlimit;
> +	compat_u64 dqb_isoftlimit;
> +	compat_u64 dqb_curinodes;
> +	compat_u64 dqb_btime;
> +	compat_u64 dqb_itime;
> +	compat_uint_t dqb_valid;
> +};
> +
> +/* XFS structures */
> +struct compat_fs_qfilestat {
> +	compat_u64 dqb_bhardlimit;
> +	compat_u64 qfs_nblks;
> +	compat_uint_t qfs_nextents;
> +};
> +
> +struct compat_fs_quota_stat {
> +	__s8		qs_version;
> +	__u16		qs_flags;
> +	__s8		qs_pad;
> +	struct compat_fs_qfilestat	qs_uquota;
> +	struct compat_fs_qfilestat	qs_gquota;
> +	compat_uint_t	qs_incoredqs;
> +	compat_int_t	qs_btimelimit;
> +	compat_int_t	qs_itimelimit;
> +	compat_int_t	qs_rtbtimelimit;
> +	__u16		qs_bwarnlimit;
> +	__u16		qs_iwarnlimit;
> +};
> +
> +asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
> +						qid_t id, void __user *addr)
> +{
> +	unsigned int cmds;
> +	struct if_dqblk __user *dqblk;
> +	struct compat_if_dqblk __user *compat_dqblk;
> +	struct fs_quota_stat __user *fsqstat;
> +	struct compat_fs_quota_stat __user *compat_fsqstat;
> +	compat_uint_t data;
> +	u16 xdata;
> +	long ret;
> +
> +	cmds = cmd >> SUBCMDSHIFT;
> +
> +	switch (cmds) {
> +	case Q_GETQUOTA:
> +		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
> +		compat_dqblk = addr;
> +		ret = sys_quotactl(cmd, special, id, dqblk);
> +		if (ret)
> +			break;
> +		if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) ||
> +			get_user(data, &dqblk->dqb_valid) ||
> +			put_user(data, &compat_dqblk->dqb_valid))
> +			ret = -EFAULT;
> +		break;
> +	case Q_SETQUOTA:
> +		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
> +		compat_dqblk = addr;
> +		ret = -EFAULT;
> +		if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) ||
> +			get_user(data, &compat_dqblk->dqb_valid) ||
> +			put_user(data, &dqblk->dqb_valid))
> +			break;
> +		ret = sys_quotactl(cmd, special, id, dqblk);
> +		break;
> +	case Q_XGETQSTAT:
> +		fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat));
> +		compat_fsqstat = addr;
> +		ret = sys_quotactl(cmd, special, id, fsqstat);
> +		if (ret)
> +			break;
> +		ret = -EFAULT;
> +		/* Copying qs_version, qs_flags, qs_pad */
> +		if (copy_in_user(compat_fsqstat, fsqstat,
> +			offsetof(struct compat_fs_quota_stat, qs_uquota)))
> +			break;
> +		/* Copying qs_uquota */
> +		if (copy_in_user(&compat_fsqstat->qs_uquota,
> +			&fsqstat->qs_uquota,
> +			sizeof(compat_fsqstat->qs_uquota)) ||
> +			get_user(data, &fsqstat->qs_uquota.qfs_nextents) ||
> +			put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents))
> +			break;
> +		/* Copying qs_gquota */
> +		if (copy_in_user(&compat_fsqstat->qs_gquota,
> +			&fsqstat->qs_gquota,
> +			sizeof(compat_fsqstat->qs_gquota)) ||
> +			get_user(data, &fsqstat->qs_gquota.qfs_nextents) ||
> +			put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents))
> +			break;
> +		/* Copying the rest */
> +		if (copy_in_user(&compat_fsqstat->qs_incoredqs,
> +			&fsqstat->qs_incoredqs,
> +			sizeof(struct compat_fs_quota_stat) -
> +			offsetof(struct compat_fs_quota_stat, qs_incoredqs)) ||
> +			get_user(xdata, &fsqstat->qs_iwarnlimit) ||
> +			put_user(xdata, &compat_fsqstat->qs_iwarnlimit))
> +			break;
> +		ret = 0;
> +		break;
> +	default:
> +		ret = sys_quotactl(cmd, special, id, addr);
> +	}
> +	return ret;
> +}
> +#endif

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2007-06-19 19:33 ` Andrew Morton
@ 2007-06-19 20:09   ` Mikael Pettersson
  2007-06-19 22:34   ` David Miller
  1 sibling, 0 replies; 31+ messages in thread
From: Mikael Pettersson @ 2007-06-19 20:09 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Vasily Tarasov, Kirill Korotaev, Vasily Averin,
	OpenVZ Developers ML, Linux Kernel ML, Natalie Protasevich,
	Jan Kara, linux-arch

Andrew Morton writes:
 > On Mon, 18 Jun 2007 12:21:47 +0400
 > Vasily Tarasov <vtaras@openvz.org> wrote:
 > 
 > > From: Vasily Tarasov <vtaras@openvz.org>
 > > 
 > > This patch should be applied after Arnd Bergmann's patch,
 > > that intoduces new compat types: 
 > > http://lkml.org/lkml/2007/6/15/98
 > > 
 > > OpenVZ Linux kernel team has discovered the problem 
 > > with 32bit quota tools working on 64bit architectures.
 > > In 2.6.10 kernel sys32_quotactl() function was replaced by sys_quotactl() with
 > > the comment "sys_quotactl seems to be 32/64bit clean, enable it for 32bit"
 > > However this isn't right. Look at if_dqblk structure:
 > > 
 > > struct if_dqblk {
 > >         __u64 dqb_bhardlimit;
 > >         __u64 dqb_bsoftlimit;
 > >         __u64 dqb_curspace;
 > >         __u64 dqb_ihardlimit;
 > >         __u64 dqb_isoftlimit;
 > >         __u64 dqb_curinodes;
 > >         __u64 dqb_btime;
 > >         __u64 dqb_itime;
 > >         __u32 dqb_valid;
 > > };
 > > 
 > > For 32 bit quota tools sizeof(if_dqblk) == 0x44.
 > > But for 64 bit kernel its size is 0x48, 'cause of alignment!
 > > Thus we got a problem. Attached patch reintroduce sys32_quotactl() function,
 > > that handles this and related situations.
 > > 
 > > Signed-off-by: Vasily Tarasov <vtaras@openvz.org>
 > > 
 > > ---
 > > 
 > > In OpenVZ technology 32 bit Virtual Environments over 
 > > 64 bit OS are common, hence we have customers, that complains on this bad quota
 > > behaviour: 
 > > 
 > > # /usr/bin/quota
 > > quota: error while getting quota from /dev/sda1 for 0: Success
 > > 
 > > The reason is caused above.
 > 
 > Only x86_64 and ia64 are fixed.  Would it be correct to assume that the
 > other CONFIG_COMPAT architectures also need to be fixed?

I complained about this very issue when a previous version of
this patch was submitted last week, and Arnd explained that
non-x86 doesn't have a problem here because alignof(u64) is the
same in 32- and 64-bit modes.

However, the fact that the patch description talks about 32-
and 64-bit machines _in_general_, while the patch clearly only
handles x86-32 on x86-64 and ia64, is itself a bug. A more
precise patch description and a better comment in the code
is in order, I think.

/Mikael

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2007-06-19 19:33 ` Andrew Morton
  2007-06-19 20:09   ` Mikael Pettersson
@ 2007-06-19 22:34   ` David Miller
  1 sibling, 0 replies; 31+ messages in thread
From: David Miller @ 2007-06-19 22:34 UTC (permalink / raw)
  To: akpm; +Cc: vtaras, dev, vvs, devel, linux-kernel, nataliep, jack, linux-arch

From: Andrew Morton <akpm@linux-foundation.org>
Date: Tue, 19 Jun 2007 12:33:16 -0700

> Only x86_64 and ia64 are fixed.  Would it be correct to assume that the
> other CONFIG_COMPAT architectures also need to be fixed?

Only platforms which compat to "i386" have the issue wrt.
the alignment of "u64" types, which is "4" on i386 and
"8" on the platforms that compat to them.

This has been mentioned at least 3 times in this thread.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2007-06-15 15:24     ` Arnd Bergmann
@ 2007-06-18  7:41       ` Vasily Tarasov
  0 siblings, 0 replies; 31+ messages in thread
From: Vasily Tarasov @ 2007-06-18  7:41 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Mikael Pettersson, akpm, dev, devel, jack, linux-kernel, nataliep, vvs

On Fri, 2007-06-15 at 17:24 +0200, Arnd Bergmann wrote:
> On Friday 15 June 2007, Vasily Tarasov wrote:
> > I just noticed that we can not avoid the addition of packed attribute.
> > Look, for example:
> > 
> > struct if_dqblk {
> >         __u64 dqb_bhardlimit; 
> >         __u64 dqb_bsoftlimit;
> >         __u64 dqb_curspace;
> >         __u64 dqb_ihardlimit;
> >         __u64 dqb_isoftlimit;
> >         __u64 dqb_curinodes; 
> >         __u64 dqb_btime;
> >         __u64 dqb_itime;
> >         __u32 dqb_valid;
> > };
> > 
> > sizeof(if_dqblk) = 0x48
> > On 32 bit: 0x44
> > 
> > If I replace __u64/__u32 with compat equivalents - it will not help!
> > alligned attribute can _only_ _increase_ the size of structure, but not
> > decrease it.
> 
> No, the gcc documentation isn't quite clear there, see the discussion about
> compat_u64 and compat_s64 types. It actually does the right thing when
> you use 'typedef __u64 __attribute__((aligned(64))) compat_64', as my
> patch does.
> 
> 	Arnd <><
> 

Wow!... Thank you for the explanation.
I'll resend the patch soon.

Vasily


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2007-06-15 14:48   ` Vasily Tarasov
@ 2007-06-15 15:24     ` Arnd Bergmann
  2007-06-18  7:41       ` Vasily Tarasov
  0 siblings, 1 reply; 31+ messages in thread
From: Arnd Bergmann @ 2007-06-15 15:24 UTC (permalink / raw)
  To: vtaras
  Cc: Mikael Pettersson, akpm, dev, devel, jack, linux-kernel, nataliep, vvs

On Friday 15 June 2007, Vasily Tarasov wrote:
> I just noticed that we can not avoid the addition of packed attribute.
> Look, for example:
> 
> struct if_dqblk {
>         __u64 dqb_bhardlimit; 
>         __u64 dqb_bsoftlimit;
>         __u64 dqb_curspace;
>         __u64 dqb_ihardlimit;
>         __u64 dqb_isoftlimit;
>         __u64 dqb_curinodes; 
>         __u64 dqb_btime;
>         __u64 dqb_itime;
>         __u32 dqb_valid;
> };
> 
> sizeof(if_dqblk) = 0x48
> On 32 bit: 0x44
> 
> If I replace __u64/__u32 with compat equivalents - it will not help!
> alligned attribute can _only_ _increase_ the size of structure, but not
> decrease it.

No, the gcc documentation isn't quite clear there, see the discussion about
compat_u64 and compat_s64 types. It actually does the right thing when
you use 'typedef __u64 __attribute__((aligned(64))) compat_64', as my
patch does.

	Arnd <><

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2007-06-15 10:43 ` Arnd Bergmann
  2007-06-15 11:00   ` Vasily Tarasov
@ 2007-06-15 14:48   ` Vasily Tarasov
  2007-06-15 15:24     ` Arnd Bergmann
  1 sibling, 1 reply; 31+ messages in thread
From: Vasily Tarasov @ 2007-06-15 14:48 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Mikael Pettersson, akpm, dev, devel, jack, linux-kernel, nataliep, vvs

On Fri, 2007-06-15 at 12:43 +0200, Arnd Bergmann wrote:
> On Friday 15 June 2007, Mikael Pettersson wrote:
> > > --- linux-2.6.22-rc4-fixed/fs/quota.c.orig    2007-06-14 15:55:26.000000000 +0400
> > > +++ linux-2.6.22-rc4-fixed/fs/quota.c 2007-06-14 19:50:13.000000000 +0400
> > ...
> > > +#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
> > > +/*
> > > + * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
> > > + * and is necessary due to alignment problems.
> > > + */
> > 
> > The #ifdef looks way too arch-specific. And isn't there a shared
> > compat.c module somewhere that this should go into?
> > 
> 
> Only x86_64 and ia64 have this particular problem, the other architectures,
> and hopefully all future 64 bit platforms with 32 bit user space use
> the same alignment rules in elf32 and elf64.
> 
> Still, the patch should be converted to use the compat_u64 type and not
> add an 'attribute((packed))' so that you _can_ use the same code on all
> architectures. See my 'Introduce compat_u64 and compat_s64 types' patch
> that I just posted in another thread.
> 
> 	Arnd <><
> 

Hello, 

I just noticed that we can not avoid the addition of packed attribute.
Look, for example:

struct if_dqblk {
        __u64 dqb_bhardlimit; 
        __u64 dqb_bsoftlimit;
        __u64 dqb_curspace;
        __u64 dqb_ihardlimit;
        __u64 dqb_isoftlimit;
        __u64 dqb_curinodes; 
        __u64 dqb_btime;
        __u64 dqb_itime;
        __u32 dqb_valid;
};

sizeof(if_dqblk) = 0x48
On 32 bit: 0x44

If I replace __u64/__u32 with compat equivalents - it will not help!
alligned attribute can _only_ _increase_ the size of structure, but not
decrease it.

So we should use packed or just use the array of ints: int[2].

Vasily




^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
@ 2007-06-15 11:08 Mikael Pettersson
  0 siblings, 0 replies; 31+ messages in thread
From: Mikael Pettersson @ 2007-06-15 11:08 UTC (permalink / raw)
  To: arnd, mikpe; +Cc: akpm, dev, devel, jack, linux-kernel, nataliep, vtaras, vvs

On Fri, 15 Jun 2007 12:43:01 +0200, Arnd Bergmann wrote:
> On Friday 15 June 2007, Mikael Pettersson wrote:
> > > --- linux-2.6.22-rc4-fixed/fs/quota.c.orig=A0=A0=A0=A02007-06-14 15:55:=
> 26.000000000 +0400
> > > +++ linux-2.6.22-rc4-fixed/fs/quota.c=A02007-06-14 19:50:13.000000000 +=
> 0400
> > ...
> > > +#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
> > > +/*
> > > + * This code works only for 32 bit quota tools over 64 bit OS (x86_64,=
>  ia64)
> > > + * and is necessary due to alignment problems.
> > > + */
> >=20
> > The #ifdef looks way too arch-specific. And isn't there a shared
> > compat.c module somewhere that this should go into?
> >=20
> 
> Only x86_64 and ia64 have this particular problem, the other architectures,
> and hopefully all future 64 bit platforms with 32 bit user space use
> the same alignment rules in elf32 and elf64.

Ah yes, alignof(u64) is the same in 32- and 64-bit modes on !x86,
thus they don't have a problem here.

Thanks for explaining that. I consider this is an essential
piece of information that should be included in the patch.
(In a comment in the code, not buried in some commit log.)

/Mikael

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2007-06-15 10:43 ` Arnd Bergmann
@ 2007-06-15 11:00   ` Vasily Tarasov
  2007-06-15 14:48   ` Vasily Tarasov
  1 sibling, 0 replies; 31+ messages in thread
From: Vasily Tarasov @ 2007-06-15 11:00 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Mikael Pettersson, akpm, dev, devel, jack, linux-kernel, nataliep, vvs

On Fri, 2007-06-15 at 12:43 +0200, Arnd Bergmann wrote:
> On Friday 15 June 2007, Mikael Pettersson wrote:
> > > --- linux-2.6.22-rc4-fixed/fs/quota.c.orig    2007-06-14 15:55:26.000000000 +0400
> > > +++ linux-2.6.22-rc4-fixed/fs/quota.c 2007-06-14 19:50:13.000000000 +0400
> > ...
> > > +#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
> > > +/*
> > > + * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
> > > + * and is necessary due to alignment problems.
> > > + */
> > 
> > The #ifdef looks way too arch-specific. And isn't there a shared
> > compat.c module somewhere that this should go into?
> > 
> 
> Only x86_64 and ia64 have this particular problem, the other architectures,
> and hopefully all future 64 bit platforms with 32 bit user space use
> the same alignment rules in elf32 and elf64.
> 
> Still, the patch should be converted to use the compat_u64 type and not
> add an 'attribute((packed))' so that you _can_ use the same code on all
> architectures. See my 'Introduce compat_u64 and compat_s64 types' patch
> that I just posted in another thread.
> 
> 	Arnd <><
> 

Agree, it'll be the most clean solution.

Is it ok, if I'll send a patch against (current kernel + Arnd's patch)?

Thanks,
Vasily


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2007-06-15 10:03 Mikael Pettersson
  2007-06-15 10:41 ` Vasily Tarasov
@ 2007-06-15 10:43 ` Arnd Bergmann
  2007-06-15 11:00   ` Vasily Tarasov
  2007-06-15 14:48   ` Vasily Tarasov
  1 sibling, 2 replies; 31+ messages in thread
From: Arnd Bergmann @ 2007-06-15 10:43 UTC (permalink / raw)
  To: Mikael Pettersson
  Cc: akpm, vtaras, dev, devel, jack, linux-kernel, nataliep, vvs

On Friday 15 June 2007, Mikael Pettersson wrote:
> > --- linux-2.6.22-rc4-fixed/fs/quota.c.orig    2007-06-14 15:55:26.000000000 +0400
> > +++ linux-2.6.22-rc4-fixed/fs/quota.c 2007-06-14 19:50:13.000000000 +0400
> ...
> > +#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
> > +/*
> > + * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
> > + * and is necessary due to alignment problems.
> > + */
> 
> The #ifdef looks way too arch-specific. And isn't there a shared
> compat.c module somewhere that this should go into?
> 

Only x86_64 and ia64 have this particular problem, the other architectures,
and hopefully all future 64 bit platforms with 32 bit user space use
the same alignment rules in elf32 and elf64.

Still, the patch should be converted to use the compat_u64 type and not
add an 'attribute((packed))' so that you _can_ use the same code on all
architectures. See my 'Introduce compat_u64 and compat_s64 types' patch
that I just posted in another thread.

	Arnd <><

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2007-06-15 10:03 Mikael Pettersson
@ 2007-06-15 10:41 ` Vasily Tarasov
  2007-06-15 10:43 ` Arnd Bergmann
  1 sibling, 0 replies; 31+ messages in thread
From: Vasily Tarasov @ 2007-06-15 10:41 UTC (permalink / raw)
  To: Mikael Pettersson; +Cc: akpm, dev, devel, jack, linux-kernel, nataliep, vvs

You can find a half-year back discussions of this patch:

First attempt: http://lkml.org/lkml/2006/10/19/123
Second attempt: http://lkml.org/lkml/2006/10/25/57

I think they will answer your questions.

Thank you,
Vasily


On Fri, 2007-06-15 at 12:03 +0200, Mikael Pettersson wrote:
> On Fri, 15 Jun 2007 13:01:48 +0400, Vasily Tarasov wrote:
> > OpenVZ Linux kernel team has discovered the problem 
> > with 32bit quota tools working on 64bit architectures.
> > In 2.6.10 kernel sys32_quotactl() function was replaced by sys_quotactl() with
> > the comment "sys_quotactl seems to be 32/64bit clean, enable it for 32bit"
> > However this isn't right. Look at if_dqblk structure:
> 
> Your patch only converts ia32 on x86-64 or ia64.
> What about ppc32-on-ppc64 and sparc32-on-sparc64?
> And, I guess, mips32-on-mips64?
> 
> > --- linux-2.6.22-rc4-fixed/fs/quota.c.orig	2007-06-14 15:55:26.000000000 +0400
> > +++ linux-2.6.22-rc4-fixed/fs/quota.c	2007-06-14 19:50:13.000000000 +0400
> ...
> > +#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
> > +/*
> > + * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
> > + * and is necessary due to alignment problems.
> > + */
> 
> The #ifdef looks way too arch-specific. And isn't there a shared
> compat.c module somewhere that this should go into?
> 
> /Mikael


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
@ 2007-06-15 10:03 Mikael Pettersson
  2007-06-15 10:41 ` Vasily Tarasov
  2007-06-15 10:43 ` Arnd Bergmann
  0 siblings, 2 replies; 31+ messages in thread
From: Mikael Pettersson @ 2007-06-15 10:03 UTC (permalink / raw)
  To: akpm, vtaras; +Cc: dev, devel, jack, linux-kernel, nataliep, vvs

On Fri, 15 Jun 2007 13:01:48 +0400, Vasily Tarasov wrote:
> OpenVZ Linux kernel team has discovered the problem 
> with 32bit quota tools working on 64bit architectures.
> In 2.6.10 kernel sys32_quotactl() function was replaced by sys_quotactl() with
> the comment "sys_quotactl seems to be 32/64bit clean, enable it for 32bit"
> However this isn't right. Look at if_dqblk structure:

Your patch only converts ia32 on x86-64 or ia64.
What about ppc32-on-ppc64 and sparc32-on-sparc64?
And, I guess, mips32-on-mips64?

> --- linux-2.6.22-rc4-fixed/fs/quota.c.orig	2007-06-14 15:55:26.000000000 +0400
> +++ linux-2.6.22-rc4-fixed/fs/quota.c	2007-06-14 19:50:13.000000000 +0400
...
> +#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
> +/*
> + * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
> + * and is necessary due to alignment problems.
> + */

The #ifdef looks way too arch-specific. And isn't there a shared
compat.c module somewhere that this should go into?

/Mikael

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH] diskquota: 32bit quota tools on 64bit architectures
@ 2007-06-15  9:01 Vasily Tarasov
  0 siblings, 0 replies; 31+ messages in thread
From: Vasily Tarasov @ 2007-06-15  9:01 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Kirill Korotaev, Vasily Averin, OpenVZ Developers ML,
	Linux Kernel ML, Natalie Protasevich, Jan Kara

From: Vasily Tarasov <vtaras@openvz.org>

OpenVZ Linux kernel team has discovered the problem 
with 32bit quota tools working on 64bit architectures.
In 2.6.10 kernel sys32_quotactl() function was replaced by sys_quotactl() with
the comment "sys_quotactl seems to be 32/64bit clean, enable it for 32bit"
However this isn't right. Look at if_dqblk structure:

struct if_dqblk {
        __u64 dqb_bhardlimit;
        __u64 dqb_bsoftlimit;
        __u64 dqb_curspace;
        __u64 dqb_ihardlimit;
        __u64 dqb_isoftlimit;
        __u64 dqb_curinodes;
        __u64 dqb_btime;
        __u64 dqb_itime;
        __u32 dqb_valid;
};

For 32 bit quota tools sizeof(if_dqblk) == 0x44.
But for 64 bit kernel its size is 0x48, 'cause of alignment!
Thus we got a problem. Attached patch reintroduce sys32_quotactl() function,
that handles this and related situations.

Signed-off-by: Vasily Tarasov <vtaras@openvz.org>

---

In OpenVZ technology 32 bit Virtual Environments over 
64 bit OS are common, hence we have customers, that complains on this bad quota
behaviour: 

# /usr/bin/quota
quota: error while getting quota from /dev/sda1 for 0: Success

The reason is caused above.

--- linux-2.6.22-rc4-fixed/arch/x86_64/ia32/ia32entry.S.orig	2007-06-14 15:55:24.000000000 +0400
+++ linux-2.6.22-rc4-fixed/arch/x86_64/ia32/ia32entry.S	2007-06-14 16:22:52.000000000 +0400
@@ -526,7 +526,7 @@ ia32_sys_call_table:
 	.quad sys_init_module
 	.quad sys_delete_module
 	.quad quiet_ni_syscall		/* 130  get_kernel_syms */
-	.quad sys_quotactl
+	.quad sys32_quotactl
 	.quad sys_getpgid
 	.quad sys_fchdir
 	.quad quiet_ni_syscall	/* bdflush */
--- linux-2.6.22-rc4-fixed/arch/ia64/ia32/ia32_entry.S.orig	2007-06-14 15:55:24.000000000 +0400
+++ linux-2.6.22-rc4-fixed/arch/ia64/ia32/ia32_entry.S	2007-06-14 16:22:52.000000000 +0400
@@ -304,7 +304,7 @@ ia32_syscall_table:
 	data8 sys_ni_syscall	/* init_module */
 	data8 sys_ni_syscall	/* delete_module */
 	data8 sys_ni_syscall	/* get_kernel_syms */  /* 130 */
-	data8 sys_quotactl
+	data8 sys32_quotactl
 	data8 sys_getpgid
 	data8 sys_fchdir
 	data8 sys_ni_syscall	/* sys_bdflush */
--- linux-2.6.22-rc4-fixed/fs/quota.c.orig	2007-06-14 15:55:26.000000000 +0400
+++ linux-2.6.22-rc4-fixed/fs/quota.c	2007-06-14 19:50:13.000000000 +0400
@@ -10,12 +10,14 @@
 #include <linux/slab.h>
 #include <asm/current.h>
 #include <asm/uaccess.h>
+#include <asm/compat.h>
 #include <linux/kernel.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/buffer_head.h>
 #include <linux/capability.h>
 #include <linux/quotaops.h>
+#include <linux/types.h>
 
 /* Check validity of generic quotactl commands */
 static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
@@ -384,3 +386,119 @@ asmlinkage long sys_quotactl(unsigned in
 
 	return ret;
 }
+
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+/*
+ * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
+ * and is necessary due to alignment problems.
+ */
+struct compat_if_dqblk {
+	__u64 dqb_bhardlimit;
+	__u64 dqb_bsoftlimit;
+	__u64 dqb_curspace;
+	__u64 dqb_ihardlimit;
+	__u64 dqb_isoftlimit;
+	__u64 dqb_curinodes;
+	__u64 dqb_btime;
+	__u64 dqb_itime;
+	__u32 dqb_valid;
+} __attribute__ ((__packed__));
+
+/* XFS structures */
+struct compat_fs_qfilestat {
+	__u64 dqb_bhardlimit;
+	__u64 qfs_nblks;
+	__u32 qfs_nextents;
+} __attribute__ ((__packed__));
+
+struct compat_fs_quota_stat {
+	__s8		qs_version;
+	__u16		qs_flags;
+	__s8		qs_pad;
+	struct compat_fs_qfilestat	qs_uquota;
+	struct compat_fs_qfilestat	qs_gquota;
+	__u32		qs_incoredqs;
+	__s32		qs_btimelimit;
+	__s32		qs_itimelimit;
+	__s32		qs_rtbtimelimit;
+	__u16		qs_bwarnlimit;
+	__u16		qs_iwarnlimit;
+};
+
+asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
+						qid_t id, void __user *addr)
+{
+	unsigned int cmds;
+	struct if_dqblk __user *dqblk;
+	struct compat_if_dqblk __user *compat_dqblk;
+	struct fs_quota_stat __user *fsqstat;
+	struct compat_fs_quota_stat __user *compat_fsqstat;
+	u32 data;
+	u16 xdata;
+	long ret;
+
+	cmds = cmd >> SUBCMDSHIFT;
+
+	switch (cmds) {
+	case Q_GETQUOTA:
+		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
+		compat_dqblk = addr;
+		ret = sys_quotactl(cmd, special, id, dqblk);
+		if (ret)
+			break;
+		if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) ||
+			get_user(data, &dqblk->dqb_valid) ||
+			put_user(data, &compat_dqblk->dqb_valid))
+			ret = -EFAULT;
+		break;
+	case Q_SETQUOTA:
+		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
+		compat_dqblk = addr;
+		ret = -EFAULT;
+		if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) ||
+			get_user(data, &compat_dqblk->dqb_valid) ||
+			put_user(data, &dqblk->dqb_valid))
+			break;
+		ret = sys_quotactl(cmd, special, id, dqblk);
+		break;
+	case Q_XGETQSTAT:
+		fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat));
+		compat_fsqstat = addr;
+		ret = sys_quotactl(cmd, special, id, fsqstat);
+		if (ret)
+			break;
+		ret = -EFAULT;
+		/* Copying qs_version, qs_flags, qs_pad */
+		if (copy_in_user(compat_fsqstat, fsqstat,
+			offsetof(struct compat_fs_quota_stat, qs_uquota)))
+			break;
+		/* Copying qs_uquota */
+		if (copy_in_user(&compat_fsqstat->qs_uquota,
+			&fsqstat->qs_uquota,
+			sizeof(compat_fsqstat->qs_uquota)) ||
+			get_user(data, &fsqstat->qs_uquota.qfs_nextents) ||
+			put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents))
+			break;
+		/* Copying qs_gquota */
+		if (copy_in_user(&compat_fsqstat->qs_gquota,
+			&fsqstat->qs_gquota,
+			sizeof(compat_fsqstat->qs_gquota)) ||
+			get_user(data, &fsqstat->qs_gquota.qfs_nextents) ||
+			put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents))
+			break;
+		/* Copying the rest */
+		if (copy_in_user(&compat_fsqstat->qs_incoredqs,
+			&fsqstat->qs_incoredqs,
+			sizeof(struct compat_fs_quota_stat) -
+			offsetof(struct compat_fs_quota_stat, qs_incoredqs)) ||
+			get_user(xdata, &fsqstat->qs_iwarnlimit) ||
+			put_user(xdata, &compat_fsqstat->qs_iwarnlimit))
+			break;
+		ret = 0;
+		break;
+	default:
+		ret = sys_quotactl(cmd, special, id, addr);
+	}
+	return ret;
+}
+#endif

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH] diskquota: 32bit quota tools on 64bit architectures
@ 2007-06-15  8:59 Vasily Tarasov
  0 siblings, 0 replies; 31+ messages in thread
From: Vasily Tarasov @ 2007-06-15  8:59 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Kirill Korotaev, Vasily Averin, OpenVZ Developers ML,
	Linux Kernel ML, Natalie Protasevich, Jan Kara

From: Vasily Tarasov <vtaras@openvz.org>

OpenVZ Linux kernel team has discovered the problem 
with 32bit quota tools working on 64bit architectures.
In 2.6.10 kernel sys32_quotactl() function was replaced by sys_quotactl() with
the comment "sys_quotactl seems to be 32/64bit clean, enable it for 32bit"
However this isn't right. Look at if_dqblk structure:

struct if_dqblk {
        __u64 dqb_bhardlimit;
        __u64 dqb_bsoftlimit;
        __u64 dqb_curspace;
        __u64 dqb_ihardlimit;
        __u64 dqb_isoftlimit;
        __u64 dqb_curinodes;
        __u64 dqb_btime;
        __u64 dqb_itime;
        __u32 dqb_valid;
};

For 32 bit quota tools sizeof(if_dqblk) == 0x44.
But for 64 bit kernel its size is 0x48, 'cause of alignment!
Thus we got a problem. Attached patch reintroduce sys32_quotactl() function,
that handles this and related situations.

Signed-off-by: Vasily Tarasov <vtaras@openvz.org>

---

In OpenVZ technology 32 bit Virtual Environments over 
64 bit OS are common, hence we have customers, that complains on this bad quota
behaviour: 

# /usr/bin/quota
quota: error while getting quota from /dev/sda1 for 0: Success

The reason is caused above.

--- linux-2.6.22-rc4-fixed/arch/x86_64/ia32/ia32entry.S.orig	2007-06-14 15:55:24.000000000 +0400
+++ linux-2.6.22-rc4-fixed/arch/x86_64/ia32/ia32entry.S	2007-06-14 16:22:52.000000000 +0400
@@ -526,7 +526,7 @@ ia32_sys_call_table:
 	.quad sys_init_module
 	.quad sys_delete_module
 	.quad quiet_ni_syscall		/* 130  get_kernel_syms */
-	.quad sys_quotactl
+	.quad sys32_quotactl
 	.quad sys_getpgid
 	.quad sys_fchdir
 	.quad quiet_ni_syscall	/* bdflush */
--- linux-2.6.22-rc4-fixed/arch/ia64/ia32/ia32_entry.S.orig	2007-06-14 15:55:24.000000000 +0400
+++ linux-2.6.22-rc4-fixed/arch/ia64/ia32/ia32_entry.S	2007-06-14 16:22:52.000000000 +0400
@@ -304,7 +304,7 @@ ia32_syscall_table:
 	data8 sys_ni_syscall	/* init_module */
 	data8 sys_ni_syscall	/* delete_module */
 	data8 sys_ni_syscall	/* get_kernel_syms */  /* 130 */
-	data8 sys_quotactl
+	data8 sys32_quotactl
 	data8 sys_getpgid
 	data8 sys_fchdir
 	data8 sys_ni_syscall	/* sys_bdflush */
--- linux-2.6.22-rc4-fixed/fs/quota.c.orig	2007-06-14 15:55:26.000000000 +0400
+++ linux-2.6.22-rc4-fixed/fs/quota.c	2007-06-14 19:50:13.000000000 +0400
@@ -10,12 +10,14 @@
 #include <linux/slab.h>
 #include <asm/current.h>
 #include <asm/uaccess.h>
+#include <asm/compat.h>
 #include <linux/kernel.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/buffer_head.h>
 #include <linux/capability.h>
 #include <linux/quotaops.h>
+#include <linux/types.h>
 
 /* Check validity of generic quotactl commands */
 static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
@@ -384,3 +386,119 @@ asmlinkage long sys_quotactl(unsigned in
 
 	return ret;
 }
+
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+/*
+ * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
+ * and is necessary due to alignment problems.
+ */
+struct compat_if_dqblk {
+	__u64 dqb_bhardlimit;
+	__u64 dqb_bsoftlimit;
+	__u64 dqb_curspace;
+	__u64 dqb_ihardlimit;
+	__u64 dqb_isoftlimit;
+	__u64 dqb_curinodes;
+	__u64 dqb_btime;
+	__u64 dqb_itime;
+	__u32 dqb_valid;
+} __attribute__ ((__packed__));
+
+/* XFS structures */
+struct compat_fs_qfilestat {
+	__u64 dqb_bhardlimit;
+	__u64 qfs_nblks;
+	__u32 qfs_nextents;
+} __attribute__ ((__packed__));
+
+struct compat_fs_quota_stat {
+	__s8		qs_version;
+	__u16		qs_flags;
+	__s8		qs_pad;
+	struct compat_fs_qfilestat	qs_uquota;
+	struct compat_fs_qfilestat	qs_gquota;
+	__u32		qs_incoredqs;
+	__s32		qs_btimelimit;
+	__s32		qs_itimelimit;
+	__s32		qs_rtbtimelimit;
+	__u16		qs_bwarnlimit;
+	__u16		qs_iwarnlimit;
+};
+
+asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
+						qid_t id, void __user *addr)
+{
+	unsigned int cmds;
+	struct if_dqblk __user *dqblk;
+	struct compat_if_dqblk __user *compat_dqblk;
+	struct fs_quota_stat __user *fsqstat;
+	struct compat_fs_quota_stat __user *compat_fsqstat;
+	u32 data;
+	u16 xdata;
+	long ret;
+
+	cmds = cmd >> SUBCMDSHIFT;
+
+	switch (cmds) {
+	case Q_GETQUOTA:
+		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
+		compat_dqblk = addr;
+		ret = sys_quotactl(cmd, special, id, dqblk);
+		if (ret)
+			break;
+		if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) ||
+			get_user(data, &dqblk->dqb_valid) ||
+			put_user(data, &compat_dqblk->dqb_valid))
+			ret = -EFAULT;
+		break;
+	case Q_SETQUOTA:
+		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
+		compat_dqblk = addr;
+		ret = -EFAULT;
+		if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) ||
+			get_user(data, &compat_dqblk->dqb_valid) ||
+			put_user(data, &dqblk->dqb_valid))
+			break;
+		ret = sys_quotactl(cmd, special, id, dqblk);
+		break;
+	case Q_XGETQSTAT:
+		fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat));
+		compat_fsqstat = addr;
+		ret = sys_quotactl(cmd, special, id, fsqstat);
+		if (ret)
+			break;
+		ret = -EFAULT;
+		/* Copying qs_version, qs_flags, qs_pad */
+		if (copy_in_user(compat_fsqstat, fsqstat,
+			offsetof(struct compat_fs_quota_stat, qs_uquota)))
+			break;
+		/* Copying qs_uquota */
+		if (copy_in_user(&compat_fsqstat->qs_uquota,
+			&fsqstat->qs_uquota,
+			sizeof(compat_fsqstat->qs_uquota)) ||
+			get_user(data, &fsqstat->qs_uquota.qfs_nextents) ||
+			put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents))
+			break;
+		/* Copying qs_gquota */
+		if (copy_in_user(&compat_fsqstat->qs_gquota,
+			&fsqstat->qs_gquota,
+			sizeof(compat_fsqstat->qs_gquota)) ||
+			get_user(data, &fsqstat->qs_gquota.qfs_nextents) ||
+			put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents))
+			break;
+		/* Copying the rest */
+		if (copy_in_user(&compat_fsqstat->qs_incoredqs,
+			&fsqstat->qs_incoredqs,
+			sizeof(struct compat_fs_quota_stat) -
+			offsetof(struct compat_fs_quota_stat, qs_incoredqs)) ||
+			get_user(xdata, &fsqstat->qs_iwarnlimit) ||
+			put_user(xdata, &compat_fsqstat->qs_iwarnlimit))
+			break;
+		ret = 0;
+		break;
+	default:
+		ret = sys_quotactl(cmd, special, id, addr);
+	}
+	return ret;
+}
+#endif

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2006-10-25 11:25   ` Vasily Tarasov
@ 2006-10-25 11:50     ` Arnd Bergmann
  0 siblings, 0 replies; 31+ messages in thread
From: Arnd Bergmann @ 2006-10-25 11:50 UTC (permalink / raw)
  To: Vasily Tarasov
  Cc: Linux Kernel Mailing List, Andrew Morton, Jan Kara, Alan Cox,
	Roman Kagan, Randy Dunlap, Dmitry Mishin, Andi Kleen,
	Vasily Averin, Christoph Hellwig, Kirill Korotaev,
	OpenVZ Developers List

On Wednesday 25 October 2006 13:25, Vasily Tarasov wrote:
> Actually I didn't use __attribute__, 'case I'v heard,  that this isn't
> encouraged now to use __attribute__((...)) in kernel. But if you think it
> is ok, and even preferable, I will definitely redo it!

You shouldn't use attributes in ABI headers, because they are
not interpreted correctly by every compiler. For stuff inside
of the kernel, I don't see a reason against it.

	Arnd <><

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2006-10-25 11:03 ` Arnd Bergmann
@ 2006-10-25 11:25   ` Vasily Tarasov
  2006-10-25 11:50     ` Arnd Bergmann
  0 siblings, 1 reply; 31+ messages in thread
From: Vasily Tarasov @ 2006-10-25 11:25 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Linux Kernel Mailing List, Andrew Morton, Jan Kara, Alan Cox,
	Roman Kagan, Randy Dunlap, Dmitry Mishin, Andi Kleen,
	Vasily Averin, Christoph Hellwig, Kirill Korotaev,
	OpenVZ Developers List

Arnd Bergmann wrote:

> > +struct compat_if_dqblk {
> > +       compat_uint_t dqb_bhardlimit[2];
> > +       compat_uint_t dqb_bsoftlimit[2];
> > +       compat_uint_t dqb_curspace[2];
> > +       compat_uint_t dqb_ihardlimit[2];
> > +       compat_uint_t dqb_isoftlimit[2];
> > +       compat_uint_t dqb_curinodes[2];
> > +       compat_uint_t dqb_btime[2];
> > +       compat_uint_t dqb_itime[2];
> > +       compat_uint_t dqb_valid;
> > +};
> > +
> > +/* XFS structures */
> > +struct compat_fs_qfilestat {
> > +       compat_uint_t dqb_bhardlimit[2];
> > +       compat_uint_t   qfs_nblks[2];
> > +       compat_uint_t   qfs_nextents;
> > +};
> > +
> 
> The patch looks technically correct, but you have defined the structures
> in a somewhat unusual way. I'd have defined them with 
> attribute((packed, aligned(4))) in the end.
> 
> Or even better, we should probably add a 
> 
> typedef unsigned long long __attribute__((aligned(4))) compat_u64;
> 
> for x86 compat and use that instead of compat_uint_t foo[2].

Actually I didn't use __attribute__, 'case I'v heard,  that this isn't
encouraged now to use __attribute__((...)) in kernel. But if you think it
is ok, and even preferable, I will definitely redo it!

Thanks!

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2006-10-25 10:03 Vasily Tarasov
@ 2006-10-25 11:03 ` Arnd Bergmann
  2006-10-25 11:25   ` Vasily Tarasov
  0 siblings, 1 reply; 31+ messages in thread
From: Arnd Bergmann @ 2006-10-25 11:03 UTC (permalink / raw)
  To: Vasily Tarasov
  Cc: Linux Kernel Mailing List, Andrew Morton, Jan Kara, Alan Cox,
	Roman Kagan, Randy Dunlap, Dmitry Mishin, Andi Kleen,
	Vasily Averin, Christoph Hellwig, Kirill Korotaev,
	OpenVZ Developers List

On Wednesday 25 October 2006 12:03, Vasily Tarasov wrote:
> + * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
> + * and is necessary due to alignment problems.
> + */
> +struct compat_if_dqblk {
> +       compat_uint_t dqb_bhardlimit[2];
> +       compat_uint_t dqb_bsoftlimit[2];
> +       compat_uint_t dqb_curspace[2];
> +       compat_uint_t dqb_ihardlimit[2];
> +       compat_uint_t dqb_isoftlimit[2];
> +       compat_uint_t dqb_curinodes[2];
> +       compat_uint_t dqb_btime[2];
> +       compat_uint_t dqb_itime[2];
> +       compat_uint_t dqb_valid;
> +};
> +
> +/* XFS structures */
> +struct compat_fs_qfilestat {
> +       compat_uint_t dqb_bhardlimit[2];
> +       compat_uint_t   qfs_nblks[2];
> +       compat_uint_t   qfs_nextents;
> +};
> +

The patch looks technically correct, but you have defined the structures
in a somewhat unusual way. I'd have defined them with 
attribute((packed, aligned(4))) in the end.

Or even better, we should probably add a 

typedef unsigned long long __attribute__((aligned(4))) compat_u64;

for x86 compat and use that instead of compat_uint_t foo[2].

	Arnd <><

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH] diskquota: 32bit quota tools on 64bit architectures
@ 2006-10-25 10:03 Vasily Tarasov
  2006-10-25 11:03 ` Arnd Bergmann
  0 siblings, 1 reply; 31+ messages in thread
From: Vasily Tarasov @ 2006-10-25 10:03 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Andrew Morton, Jan Kara, Alan Cox, Roman Kagan, Randy Dunlap,
	Dmitry Mishin, Andi Kleen, Vasily Averin, Christoph Hellwig,
	Kirill Korotaev, Arnd Bergmann, OpenVZ Developers List

OpenVZ Linux kernel team has discovered the problem 
with 32bit quota tools working on 64bit architectures.
In 2.6.10 kernel sys32_quotactl() function was replaced by sys_quotactl() with
the comment "sys_quotactl seems to be 32/64bit clean, enable it for 32bit"
However this isn't right. Look at if_dqblk structure:

struct if_dqblk {
        __u64 dqb_bhardlimit;
        __u64 dqb_bsoftlimit;
        __u64 dqb_curspace;
        __u64 dqb_ihardlimit;
        __u64 dqb_isoftlimit;
        __u64 dqb_curinodes;
        __u64 dqb_btime;
        __u64 dqb_itime;
        __u32 dqb_valid;
};

For 32 bit quota tools sizeof(if_dqblk) == 0x44.
But for 64 bit kernel its size is 0x48, 'cause of alignment!
Thus we got a problem.

Also XFS quota structures fs_qfilestat and fs_quota_stat
have the same problem.

Attached patch reintroduce sys32_quotactl() function,
that handles the situation.

Signed-off-by: Vasily Tarasov <vtaras@openvz.org>

---

In OpenVZ technology 32 bit Virtual Environments over 
64 bit OS are common, hence we have customers, that complains 
on this bad quota behaviour: 

# /usr/bin/quota
quota: error while getting quota from /dev/sda1 for 0: Success

The reason is caused above.

--- linux-2.6.18/fs/quota.c.quota32	2006-09-20 07:42:06.000000000 +0400
+++ linux-2.6.18/fs/quota.c	2006-10-24 16:20:21.000000000 +0400
@@ -10,6 +10,7 @@
 #include <linux/slab.h>
 #include <asm/current.h>
 #include <asm/uaccess.h>
+#include <asm/compat.h>
 #include <linux/kernel.h>
 #include <linux/smp_lock.h>
 #include <linux/security.h>
@@ -17,6 +18,7 @@
 #include <linux/buffer_head.h>
 #include <linux/capability.h>
 #include <linux/quotaops.h>
+#include <linux/types.h>
 
 /* Check validity of generic quotactl commands */
 static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
@@ -376,3 +378,119 @@
 
 	return ret;
 }
+
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+/*
+ * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
+ * and is necessary due to alignment problems.
+ */
+struct compat_if_dqblk {
+	compat_uint_t dqb_bhardlimit[2];
+	compat_uint_t dqb_bsoftlimit[2];
+	compat_uint_t dqb_curspace[2];
+	compat_uint_t dqb_ihardlimit[2];
+	compat_uint_t dqb_isoftlimit[2];
+	compat_uint_t dqb_curinodes[2];
+	compat_uint_t dqb_btime[2];
+	compat_uint_t dqb_itime[2];
+	compat_uint_t dqb_valid;
+};
+
+/* XFS structures */
+struct compat_fs_qfilestat {
+	compat_uint_t dqb_bhardlimit[2];
+	compat_uint_t	qfs_nblks[2];
+	compat_uint_t	qfs_nextents;
+};
+
+struct compat_fs_quota_stat {
+	__s8		qs_version;
+	__u16		qs_flags;
+	__s8		qs_pad;
+	struct compat_fs_qfilestat	qs_uquota;
+	struct compat_fs_qfilestat	qs_gquota;
+	compat_uint_t	qs_incoredqs;
+	compat_int_t	qs_btimelimit;
+	compat_int_t	qs_itimelimit;
+	compat_int_t	qs_rtbtimelimit;
+	__u16		qs_bwarnlimit;
+	__u16		qs_iwarnlimit;
+};
+
+asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
+						qid_t id, void __user *addr)
+{
+	unsigned int cmds;
+	struct if_dqblk __user *dqblk;
+	struct compat_if_dqblk __user *compat_dqblk;
+	struct fs_quota_stat __user *fsqstat;
+	struct compat_fs_quota_stat __user *compat_fsqstat;
+	compat_uint_t data;
+	u16 xdata;
+	long ret;
+
+	cmds = cmd >> SUBCMDSHIFT;
+
+	switch (cmds) {
+	case Q_GETQUOTA:
+		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
+		compat_dqblk = addr;
+		ret = sys_quotactl(cmd, special, id, dqblk);
+		if (ret)
+			break;
+		if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) ||
+			get_user(data, &dqblk->dqb_valid) ||
+			put_user(data, &compat_dqblk->dqb_valid))
+			ret = -EFAULT;
+		break;
+	case Q_SETQUOTA:
+		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
+		compat_dqblk = addr;
+		ret = -EFAULT;
+		if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) ||
+			get_user(data, &compat_dqblk->dqb_valid) ||
+			put_user(data, &dqblk->dqb_valid))
+			break;
+		ret = sys_quotactl(cmd, special, id, dqblk);
+		break;
+	case Q_XGETQSTAT:
+		fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat));
+		compat_fsqstat = addr;
+		ret = sys_quotactl(cmd, special, id, fsqstat);
+		if (ret)
+			break;
+		ret = -EFAULT;
+		/* Copying qs_version, qs_flags, qs_pad */
+		if (copy_in_user(compat_fsqstat, fsqstat,
+			offsetof(struct compat_fs_quota_stat, qs_uquota)))
+			break;
+		/* Copying qs_uquota */
+		if (copy_in_user(&compat_fsqstat->qs_uquota,
+			&fsqstat->qs_uquota,
+			sizeof(compat_fsqstat->qs_uquota)) ||
+			get_user(data, &fsqstat->qs_uquota.qfs_nextents) ||
+			put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents))
+			break;
+		/* Copying qs_gquota */
+		if (copy_in_user(&compat_fsqstat->qs_gquota,
+			&fsqstat->qs_gquota,
+			sizeof(compat_fsqstat->qs_gquota)) ||
+			get_user(data, &fsqstat->qs_gquota.qfs_nextents) ||
+			put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents))
+			break;
+		/* Copying the rest */
+		if (copy_in_user(&compat_fsqstat->qs_incoredqs,
+			&fsqstat->qs_incoredqs,
+			sizeof(struct compat_fs_quota_stat) -
+			offsetof(struct compat_fs_quota_stat, qs_incoredqs)) ||
+			get_user(xdata, &fsqstat->qs_iwarnlimit) ||
+			put_user(xdata, &compat_fsqstat->qs_iwarnlimit))
+			break;
+		ret = 0;
+		break;
+	default:
+		ret = sys_quotactl(cmd, special, id, addr);
+	}
+	return ret;
+}
+#endif
--- linux-2.6.18/arch/ia64/ia32/ia32_entry.S.quota32	2006-09-20 07:42:06.000000000 +0400
+++ linux-2.6.18/arch/ia64/ia32/ia32_entry.S	2006-10-23 17:35:38.000000000 +0400
@@ -341,7 +341,7 @@
 	data8 sys_ni_syscall	/* init_module */
 	data8 sys_ni_syscall	/* delete_module */
 	data8 sys_ni_syscall	/* get_kernel_syms */  /* 130 */
-	data8 sys_quotactl
+	data8 sys32_quotactl
 	data8 sys_getpgid
 	data8 sys_fchdir
 	data8 sys_ni_syscall	/* sys_bdflush */
--- linux-2.6.18/arch/x86_64/ia32/ia32entry.S.quota32	2006-09-20 07:42:06.000000000 +0400
+++ linux-2.6.18/arch/x86_64/ia32/ia32entry.S	2006-10-23 17:35:38.000000000 +0400
@@ -526,7 +526,7 @@
 	.quad sys_init_module
 	.quad sys_delete_module
 	.quad quiet_ni_syscall		/* 130  get_kernel_syms */
-	.quad sys_quotactl
+	.quad sys32_quotactl
 	.quad sys_getpgid
 	.quad sys_fchdir
 	.quad quiet_ni_syscall	/* bdflush */

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2006-10-21 16:28     ` Arnd Bergmann
  2006-10-23  2:12       ` David Chinner
@ 2006-10-23 10:51       ` Vasily Tarasov
  1 sibling, 0 replies; 31+ messages in thread
From: Vasily Tarasov @ 2006-10-23 10:51 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Christoph Hellwig, Linux Kernel Mailing List, Andrew Morton,
	Jan Kara, Dmitry Mishin, Vasily Averin, Kirill Korotaev,
	OpenVZ Developers List, David Chinner

Hello,

Arnd Bergmann wrote:

<snip>
> On a related topic, I just noticed 
> 
> typedef struct fs_qfilestat {
> 	__u64		qfs_ino;	/* inode number */
> 	__u64		qfs_nblks;	/* number of BBs 512-byte-blks */
>  	__u32		qfs_nextents;	/* number of extents */
> } fs_qfilestat_t;
> 
> typedef struct fs_quota_stat {
> 	__s8		qs_version;	/* version number for future changes */
> 	__u16		qs_flags;	/* XFS_QUOTA_{U,P,G}DQ_{ACCT,ENFD} */
> 	__s8		qs_pad;		/* unused */
> 	fs_qfilestat_t	qs_uquota;	/* user quota storage information */
> 	fs_qfilestat_t	qs_gquota;	/* group quota storage information */
> 	__u32		qs_incoredqs;	/* number of dquots incore */
> 	__s32		qs_btimelimit;  /* limit for blks timer */	
> 	__s32		qs_itimelimit;  /* limit for inodes timer */	
> 	__s32		qs_rtbtimelimit;/* limit for rt blks timer */	
> 	__u16		qs_bwarnlimit;	/* limit for num warnings */
> 	__u16		qs_iwarnlimit;	/* limit for num warnings */
> } fs_quota_stat_t;
> 
> This one seems to have a more severe problem in x86_64 compat
> mode. I haven't tried it, but isn't everything down from
> gs_gquota aligned differently on i386?
<snip>

The problem indeed exists:

ia32:
sizeof(fs_qfilestat) = 0x14
sizeof(fs_quota_stat) = 0x44

x86_64:
sizeof(fs_qfilestat) = 0x18
sizeof(fs_quota_stat) = 0x50

Note, that the difference between sizes of fs_qfilestat on ia32 and 
on x86_64 doesn't equal 8 bytes, as was expected (by me :)), but equals 12 bytes: 
'cause of padding at the end of fs_quota_stat structure on x86_64.

I will add support of 32-bit XFS quotactl over 64bit OS in next patch.

Thank you!

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2006-10-21 16:28     ` Arnd Bergmann
@ 2006-10-23  2:12       ` David Chinner
  2006-10-23 10:51       ` Vasily Tarasov
  1 sibling, 0 replies; 31+ messages in thread
From: David Chinner @ 2006-10-23  2:12 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Vasily Tarasov, Christoph Hellwig, Linux Kernel Mailing List,
	Andrew Morton, Jan Kara, Dmitry Mishin, Vasily Averin,
	Kirill Korotaev, OpenVZ Developers List, xfs

On Sat, Oct 21, 2006 at 06:28:32PM +0200, Arnd Bergmann wrote:
> On a related topic, I just noticed 
> 
> typedef struct fs_qfilestat {
> 	__u64		qfs_ino;	/* inode number */
> 	__u64		qfs_nblks;	/* number of BBs 512-byte-blks */
> 	__u32		qfs_nextents;	/* number of extents */
> } fs_qfilestat_t;
> 
> typedef struct fs_quota_stat {
> 	__s8		qs_version;	/* version number for future changes */
> 	__u16		qs_flags;	/* XFS_QUOTA_{U,P,G}DQ_{ACCT,ENFD} */
> 	__s8		qs_pad;		/* unused */
> 	fs_qfilestat_t	qs_uquota;	/* user quota storage information */
> 	fs_qfilestat_t	qs_gquota;	/* group quota storage information */
> 	__u32		qs_incoredqs;	/* number of dquots incore */
> 	__s32		qs_btimelimit;  /* limit for blks timer */	
> 	__s32		qs_itimelimit;  /* limit for inodes timer */	
> 	__s32		qs_rtbtimelimit;/* limit for rt blks timer */	
> 	__u16		qs_bwarnlimit;	/* limit for num warnings */
> 	__u16		qs_iwarnlimit;	/* limit for num warnings */
> } fs_quota_stat_t;

Ah, the XFS quota structures.....

> This one seems to have a more severe problem in x86_64 compat
> mode. I haven't tried it, but isn't everything down from
> gs_gquota aligned differently on i386?

Yes - this is just one of several interfaces into XFS that need compat
handling that don't have them right now.

Cheers,

Dave.
-- 
Dave Chinner
Principal Engineer
SGI Australian Software Group

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2006-10-20  6:10   ` Vasily Tarasov
@ 2006-10-21 16:28     ` Arnd Bergmann
  2006-10-23  2:12       ` David Chinner
  2006-10-23 10:51       ` Vasily Tarasov
  0 siblings, 2 replies; 31+ messages in thread
From: Arnd Bergmann @ 2006-10-21 16:28 UTC (permalink / raw)
  To: Vasily Tarasov
  Cc: Christoph Hellwig, Linux Kernel Mailing List, Andrew Morton,
	Jan Kara, Dmitry Mishin, Vasily Averin, Kirill Korotaev,
	OpenVZ Developers List

On Friday 20 October 2006 08:10, Vasily Tarasov wrote:
> Christoph Hellwig wrote:
>
> <snip>
>
> > Please allocate the structure using compat_alloc_userspace and copy
> > with copy_in_user instead of the set_fs trick.
>
> <snip>
>
> Good idea, thank you for your tip, I'll do it.

I think it would be even better to integrate this into fs/quota.c
and get rid of the extra copy entirely. The only thing you need
to do differently in case of 32 bit Q_GETQUOTA is the size
of the copy_{from,to}_user.

On a related topic, I just noticed 

typedef struct fs_qfilestat {
	__u64		qfs_ino;	/* inode number */
	__u64		qfs_nblks;	/* number of BBs 512-byte-blks */
	__u32		qfs_nextents;	/* number of extents */
} fs_qfilestat_t;

typedef struct fs_quota_stat {
	__s8		qs_version;	/* version number for future changes */
	__u16		qs_flags;	/* XFS_QUOTA_{U,P,G}DQ_{ACCT,ENFD} */
	__s8		qs_pad;		/* unused */
	fs_qfilestat_t	qs_uquota;	/* user quota storage information */
	fs_qfilestat_t	qs_gquota;	/* group quota storage information */
	__u32		qs_incoredqs;	/* number of dquots incore */
	__s32		qs_btimelimit;  /* limit for blks timer */	
	__s32		qs_itimelimit;  /* limit for inodes timer */	
	__s32		qs_rtbtimelimit;/* limit for rt blks timer */	
	__u16		qs_bwarnlimit;	/* limit for num warnings */
	__u16		qs_iwarnlimit;	/* limit for num warnings */
} fs_quota_stat_t;

This one seems to have a more severe problem in x86_64 compat
mode. I haven't tried it, but isn't everything down from
gs_gquota aligned differently on i386?

	Arnd <><

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2006-10-20  6:30   ` Vasily Tarasov
  2006-10-20  7:12     ` Christoph Hellwig
@ 2006-10-20 12:21     ` Andi Kleen
  1 sibling, 0 replies; 31+ messages in thread
From: Andi Kleen @ 2006-10-20 12:21 UTC (permalink / raw)
  To: Vasily Tarasov
  Cc: Linux Kernel Mailing List, Andrew Morton, Jan Kara,
	Dmitry Mishin, Vasily Averin, Kirill Korotaev,
	OpenVZ Developers List

On Friday 20 October 2006 08:30, Vasily Tarasov wrote:
> Andi Kleen wrote:
> 
> <snip>
> > Thanks. But the code should be probably common somewhere in fs/*, not
> > duplicated.
> <snip>
> 
> Thank you for the comment!
> I'm not sure we should do it. If we move the code in fs/quota.c for example,
> than this code will be compiled for _all_ arhitectures, not only for x86_64 and ia64.
> Of course, we can surround this code by #ifdefs <ARCH>, but I thought this is 
> a bad style... Moreover looking through current kernel code, I found out that
> usually code is duplicated in such cases.

Well it doesn't hurt them even if not strictly needed and it's better to have common code for 
this. BTW you have to convert over to compat_alloc_* for this as Christoph stated
because set_fs doesn't work on all architectures. Best you use the compat_* types too.

-Andi

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2006-10-20  6:30   ` Vasily Tarasov
@ 2006-10-20  7:12     ` Christoph Hellwig
  2006-10-20 12:21     ` Andi Kleen
  1 sibling, 0 replies; 31+ messages in thread
From: Christoph Hellwig @ 2006-10-20  7:12 UTC (permalink / raw)
  To: Vasily Tarasov
  Cc: Andi Kleen, Linux Kernel Mailing List, Andrew Morton, Jan Kara,
	Dmitry Mishin, Vasily Averin, Kirill Korotaev,
	OpenVZ Developers List

On Fri, Oct 20, 2006 at 10:30:04AM +0400, Vasily Tarasov wrote:
> Andi Kleen wrote:
> 
> <snip>
> > Thanks. But the code should be probably common somewhere in fs/*, not
> > duplicated.
> <snip>
> 
> Thank you for the comment!
> I'm not sure we should do it. If we move the code in fs/quota.c for example,
> than this code will be compiled for _all_ arhitectures, not only for x86_64 and ia64.
> Of course, we can surround this code by #ifdefs <ARCH>, but I thought this is 
> a bad style... Moreover looking through current kernel code, I found out that
> usually code is duplicated in such cases.
> 
> However, if you insist I'll modify the code! :)

I suspect a compat_x86.c file somehwere might make sense, as only x86 has
the wierd alignment rules, but we have two architectures that allow to run
x86 binaries with the compat subszstem.  Now the big question:  where should
we put this file?

> 
> Thank you.
> 
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
---end quoted text---

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2006-10-19 16:09 ` Andi Kleen
@ 2006-10-20  6:30   ` Vasily Tarasov
  2006-10-20  7:12     ` Christoph Hellwig
  2006-10-20 12:21     ` Andi Kleen
  0 siblings, 2 replies; 31+ messages in thread
From: Vasily Tarasov @ 2006-10-20  6:30 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Linux Kernel Mailing List, Andrew Morton, Jan Kara,
	Dmitry Mishin, Vasily Averin, Kirill Korotaev,
	OpenVZ Developers List

Andi Kleen wrote:

<snip>
> Thanks. But the code should be probably common somewhere in fs/*, not
> duplicated.
<snip>

Thank you for the comment!
I'm not sure we should do it. If we move the code in fs/quota.c for example,
than this code will be compiled for _all_ arhitectures, not only for x86_64 and ia64.
Of course, we can surround this code by #ifdefs <ARCH>, but I thought this is 
a bad style... Moreover looking through current kernel code, I found out that
usually code is duplicated in such cases.

However, if you insist I'll modify the code! :)

Thank you.


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2006-10-19 17:29 ` Christoph Hellwig
@ 2006-10-20  6:10   ` Vasily Tarasov
  2006-10-21 16:28     ` Arnd Bergmann
  0 siblings, 1 reply; 31+ messages in thread
From: Vasily Tarasov @ 2006-10-20  6:10 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Linux Kernel Mailing List, Andrew Morton, Jan Kara,
	Dmitry Mishin, Vasily Averin, Kirill Korotaev,
	OpenVZ Developers List

Christoph Hellwig wrote:

<snip>
> Please allocate the structure using compat_alloc_userspace and copy
> with copy_in_user instead of the set_fs trick.
<snip>

Good idea, thank you for your tip, I'll do it.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
@ 2006-10-20  5:59 Vasily Tarasov
  0 siblings, 0 replies; 31+ messages in thread
From: Vasily Tarasov @ 2006-10-20  5:59 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Linux Kernel Mailing List, Andrew Morton, Jan Kara,
	Dmitry Mishin, Vasily Averin, Kirill Korotaev,
	OpenVZ Developers List

Randy Dunlap wrote:

<snip>
> Please align the switch and case/default source lines.
> We prefer not to "double-indent" each case block inside a switch.
>
> I suppose I should try to add this to CodingStyle since it's
> not there.
>   
> ---
> ~Randy
<snip>

Thank you, I'll  do it!

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2006-10-19 12:32 Vasily Tarasov
                   ` (2 preceding siblings ...)
  2006-10-19 16:09 ` Andi Kleen
@ 2006-10-19 17:29 ` Christoph Hellwig
  2006-10-20  6:10   ` Vasily Tarasov
  3 siblings, 1 reply; 31+ messages in thread
From: Christoph Hellwig @ 2006-10-19 17:29 UTC (permalink / raw)
  To: Vasily Tarasov
  Cc: Linux Kernel Mailing List, Andrew Morton, Jan Kara,
	Dmitry Mishin, Vasily Averin, Kirill Korotaev,
	OpenVZ Developers List

On Thu, Oct 19, 2006 at 04:32:07PM +0400, Vasily Tarasov wrote:
> +asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
> +						qid_t id, void __user *addr)
> +{
> +	long ret;
> +	unsigned int cmds;
> +	mm_segment_t old_fs;
> +	struct if_dqblk dqblk;
> +	struct if32_dqblk {
> +		__u32 dqb_bhardlimit[2];
> +		__u32 dqb_bsoftlimit[2];
> +		__u32 dqb_curspace[2];
> +		__u32 dqb_ihardlimit[2];
> +		__u32 dqb_isoftlimit[2];
> +		__u32 dqb_curinodes[2];
> +		__u32 dqb_btime[2];
> +		__u32 dqb_itime[2];
> +		__u32 dqb_valid;
> +	} dqblk32;
> +
> +	cmds = cmd >> SUBCMDSHIFT;
> +
> +	switch (cmds) {
> +		case Q_GETQUOTA:
> +			old_fs = get_fs();
> +			set_fs(KERNEL_DS);
> +			ret = sys_quotactl(cmd, special, id, &dqblk);
> +			set_fs(old_fs);

Please allocate the structure using compat_alloc_userspace and copy
with copy_in_user instead of the set_fs trick.


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2006-10-19 12:32 Vasily Tarasov
  2006-10-19 13:06 ` Alan Cox
  2006-10-19 15:22 ` Randy Dunlap
@ 2006-10-19 16:09 ` Andi Kleen
  2006-10-20  6:30   ` Vasily Tarasov
  2006-10-19 17:29 ` Christoph Hellwig
  3 siblings, 1 reply; 31+ messages in thread
From: Andi Kleen @ 2006-10-19 16:09 UTC (permalink / raw)
  To: Vasily Tarasov; +Cc: Andrew Morton, linux-kernel

Vasily Tarasov <vtaras@openvz.org> writes:

> OpenVZ Linux kernel team has discovered the problem 
> with 32bit quota tools working on 64bit architectures.
> In 2.6.10 kernel sys32_quotactl() function was replaced by sys_quotactl() with
> the comment "sys_quotactl seems to be 32/64bit clean, enable it for 32bit"
> However this isn't right. Look at if_dqblk structure:
> 
> struct if_dqblk {
>         __u64 dqb_bhardlimit;
>         __u64 dqb_bsoftlimit;
>         __u64 dqb_curspace;
>         __u64 dqb_ihardlimit;
>         __u64 dqb_isoftlimit;
>         __u64 dqb_curinodes;
>         __u64 dqb_btime;
>         __u64 dqb_itime;
>         __u32 dqb_valid;
> };
> 
> For 32 bit quota tools sizeof(if_dqblk) == 0x44.
> But for 64 bit kernel its size is 0x48, 'cause of alignment!
> Thus we got a problem.
> Attached patch reintroduce sys32_quotactl() function,
> that handles the situation.

Thanks. But the code should be probably common somewhere in fs/*, not 
duplicated.

-Andi

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2006-10-19 12:32 Vasily Tarasov
  2006-10-19 13:06 ` Alan Cox
@ 2006-10-19 15:22 ` Randy Dunlap
  2006-10-19 16:09 ` Andi Kleen
  2006-10-19 17:29 ` Christoph Hellwig
  3 siblings, 0 replies; 31+ messages in thread
From: Randy Dunlap @ 2006-10-19 15:22 UTC (permalink / raw)
  To: Vasily Tarasov
  Cc: Linux Kernel Mailing List, Andrew Morton, Jan Kara,
	Dmitry Mishin, Vasily Averin, Kirill Korotaev,
	OpenVZ Developers List

On Thu, 19 Oct 2006 16:32:07 +0400 Vasily Tarasov wrote:

> --- linux-2.6.18/arch/ia64/ia32/sys_ia32.c.quot32	2006-09-20 07:42:06.000000000 +0400
> +++ linux-2.6.18/arch/ia64/ia32/sys_ia32.c	2006-10-19 11:17:50.000000000 +0400
> @@ -2545,6 +2545,54 @@ long sys32_fadvise64_64(int fd, __u32 of
>  			       advice); 
>  } 
>  
> +asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
> +						qid_t id, void __user *addr)
> +{
> +
> +	switch (cmds) {
> +		case Q_GETQUOTA:
> +			old_fs = get_fs();
> +			set_fs(KERNEL_DS);
> +			ret = sys_quotactl(cmd, special, id, &dqblk);
> +			set_fs(old_fs);
> +			memcpy(&dqblk32, &dqblk, sizeof(dqblk32));
> +			dqblk32.dqb_valid = dqblk.dqb_valid;
> +			if (copy_to_user(addr, &dqblk32, sizeof(dqblk32)))
> +				return -EFAULT;
> +			break;
> +		case Q_SETQUOTA:
> +			if (copy_from_user(&dqblk32, addr, sizeof(dqblk32)))
> +				return -EFAULT;
> +			memcpy(&dqblk, &dqblk32, sizeof(dqblk32));
> +			dqblk.dqb_valid = dqblk32.dqb_valid;
> +			old_fs = get_fs();
> +			set_fs(KERNEL_DS);
> +			ret = sys_quotactl(cmd, special, id, &dqblk);
> +			set_fs(old_fs);
> +			break;
> +		default:
> +			return sys_quotactl(cmd, special, id, addr);
> +	}
> +	return ret;
> +}

Please align the switch and case/default source lines.
We prefer not to "double-indent" each case block inside a switch.

I suppose I should try to add this to CodingStyle since it's
not there.

> --- linux-2.6.18/arch/x86_64/ia32/sys_ia32.c.quot32	2006-09-20 07:42:06.000000000 +0400
> +++ linux-2.6.18/arch/x86_64/ia32/sys_ia32.c	2006-10-19 11:00:18.000000000 +0400
> @@ -915,3 +915,50 @@ long sys32_lookup_dcookie(u32 addr_low, 
>  	return sys_lookup_dcookie(((u64)addr_high << 32) | addr_low, buf, len);
>  }
>  
> +asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
> +						qid_t id, void __user *addr)
> +{
> +
> +	switch (cmds) {
> +		case Q_GETQUOTA:
> +			old_fs = get_fs();
> +			set_fs(KERNEL_DS);
> +			ret = sys_quotactl(cmd, special, id, &dqblk);
> +			set_fs(old_fs);
> +			memcpy(&dqblk32, &dqblk, sizeof(dqblk32));
> +			dqblk32.dqb_valid = dqblk.dqb_valid;
> +			if (copy_to_user(addr, &dqblk32, sizeof(dqblk32)))
> +				return -EFAULT;
> +			break;
> +		case Q_SETQUOTA:
> +			if (copy_from_user(&dqblk32, addr, sizeof(dqblk32)))
> +				return -EFAULT;
> +			memcpy(&dqblk, &dqblk32, sizeof(dqblk32));
> +			dqblk.dqb_valid = dqblk32.dqb_valid;
> +			old_fs = get_fs();
> +			set_fs(KERNEL_DS);
> +			ret = sys_quotactl(cmd, special, id, &dqblk);
> +			set_fs(old_fs);
> +			break;
> +		default:
> +			return sys_quotactl(cmd, special, id, addr);
> +	}


---
~Randy

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] diskquota: 32bit quota tools on 64bit architectures
  2006-10-19 12:32 Vasily Tarasov
@ 2006-10-19 13:06 ` Alan Cox
  2006-10-19 15:22 ` Randy Dunlap
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 31+ messages in thread
From: Alan Cox @ 2006-10-19 13:06 UTC (permalink / raw)
  To: Vasily Tarasov
  Cc: Linux Kernel Mailing List, Andrew Morton, Jan Kara,
	Dmitry Mishin, Vasily Averin, Kirill Korotaev,
	OpenVZ Developers List

Ar Iau, 2006-10-19 am 16:32 +0400, ysgrifennodd Vasily Tarasov:
> OpenVZ Linux kernel team has discovered the problem 
> Signed-off-by: Vasily Tarasov <vtaras@openvz.org>
> Acked-by: Dmitry Mishin <dim@openvz.org>

Acked-by: Alan Cox <alan@redhat.com>



^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH] diskquota: 32bit quota tools on 64bit architectures
@ 2006-10-19 12:32 Vasily Tarasov
  2006-10-19 13:06 ` Alan Cox
                   ` (3 more replies)
  0 siblings, 4 replies; 31+ messages in thread
From: Vasily Tarasov @ 2006-10-19 12:32 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Andrew Morton, Jan Kara, Dmitry Mishin, Vasily Averin,
	Kirill Korotaev, OpenVZ Developers List

OpenVZ Linux kernel team has discovered the problem 
with 32bit quota tools working on 64bit architectures.
In 2.6.10 kernel sys32_quotactl() function was replaced by sys_quotactl() with
the comment "sys_quotactl seems to be 32/64bit clean, enable it for 32bit"
However this isn't right. Look at if_dqblk structure:

struct if_dqblk {
        __u64 dqb_bhardlimit;
        __u64 dqb_bsoftlimit;
        __u64 dqb_curspace;
        __u64 dqb_ihardlimit;
        __u64 dqb_isoftlimit;
        __u64 dqb_curinodes;
        __u64 dqb_btime;
        __u64 dqb_itime;
        __u32 dqb_valid;
};

For 32 bit quota tools sizeof(if_dqblk) == 0x44.
But for 64 bit kernel its size is 0x48, 'cause of alignment!
Thus we got a problem.
Attached patch reintroduce sys32_quotactl() function,
that handles the situation.

Signed-off-by: Vasily Tarasov <vtaras@openvz.org>
Acked-by: Dmitry Mishin <dim@openvz.org>

---

In OpenVZ technology 32 bit Virtual Environments over 
64 bit OS are common, hence we have customers, that complains on this bad quota
behaviour: 

# /usr/bin/quota
quota: error while getting quota from /dev/sda1 for 0: Success

The reason is caused above.

--- linux-2.6.18/arch/ia64/ia32/sys_ia32.c.quot32	2006-09-20 07:42:06.000000000 +0400
+++ linux-2.6.18/arch/ia64/ia32/sys_ia32.c	2006-10-19 11:17:50.000000000 +0400
@@ -2545,6 +2545,54 @@ long sys32_fadvise64_64(int fd, __u32 of
 			       advice); 
 } 
 
+asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
+						qid_t id, void __user *addr)
+{
+	long ret;
+	unsigned int cmds;
+	mm_segment_t old_fs;
+	struct if_dqblk dqblk;
+	struct if32_dqblk {
+		__u32 dqb_bhardlimit[2];
+		__u32 dqb_bsoftlimit[2];
+		__u32 dqb_curspace[2];
+		__u32 dqb_ihardlimit[2];
+		__u32 dqb_isoftlimit[2];
+		__u32 dqb_curinodes[2];
+		__u32 dqb_btime[2];
+		__u32 dqb_itime[2];
+		__u32 dqb_valid;
+	} dqblk32;
+
+	cmds = cmd >> SUBCMDSHIFT;
+
+	switch (cmds) {
+		case Q_GETQUOTA:
+			old_fs = get_fs();
+			set_fs(KERNEL_DS);
+			ret = sys_quotactl(cmd, special, id, &dqblk);
+			set_fs(old_fs);
+			memcpy(&dqblk32, &dqblk, sizeof(dqblk32));
+			dqblk32.dqb_valid = dqblk.dqb_valid;
+			if (copy_to_user(addr, &dqblk32, sizeof(dqblk32)))
+				return -EFAULT;
+			break;
+		case Q_SETQUOTA:
+			if (copy_from_user(&dqblk32, addr, sizeof(dqblk32)))
+				return -EFAULT;
+			memcpy(&dqblk, &dqblk32, sizeof(dqblk32));
+			dqblk.dqb_valid = dqblk32.dqb_valid;
+			old_fs = get_fs();
+			set_fs(KERNEL_DS);
+			ret = sys_quotactl(cmd, special, id, &dqblk);
+			set_fs(old_fs);
+			break;
+		default:
+			return sys_quotactl(cmd, special, id, addr);
+	}
+	return ret;
+}
+
 #ifdef	NOTYET  /* UNTESTED FOR IA64 FROM HERE DOWN */
 
 asmlinkage long sys32_setreuid(compat_uid_t ruid, compat_uid_t euid)
--- linux-2.6.18/arch/ia64/ia32/ia32_entry.S.quot32	2006-09-20 07:42:06.000000000 +0400
+++ linux-2.6.18/arch/ia64/ia32/ia32_entry.S	2006-10-19 11:15:52.000000000 +0400
@@ -341,7 +341,7 @@ ia32_syscall_table:
 	data8 sys_ni_syscall	/* init_module */
 	data8 sys_ni_syscall	/* delete_module */
 	data8 sys_ni_syscall	/* get_kernel_syms */  /* 130 */
-	data8 sys_quotactl
+	data8 sys32_quotactl
 	data8 sys_getpgid
 	data8 sys_fchdir
 	data8 sys_ni_syscall	/* sys_bdflush */
--- linux-2.6.18/arch/x86_64/ia32/ia32entry.S.quot32	2006-09-20 07:42:06.000000000 +0400
+++ linux-2.6.18/arch/x86_64/ia32/ia32entry.S	2006-10-18 10:05:53.000000000 +0400
@@ -526,7 +526,7 @@ ia32_sys_call_table:
 	.quad sys_init_module
 	.quad sys_delete_module
 	.quad quiet_ni_syscall		/* 130  get_kernel_syms */
-	.quad sys_quotactl
+	.quad sys32_quotactl
 	.quad sys_getpgid
 	.quad sys_fchdir
 	.quad quiet_ni_syscall	/* bdflush */
--- linux-2.6.18/arch/x86_64/ia32/sys_ia32.c.quot32	2006-09-20 07:42:06.000000000 +0400
+++ linux-2.6.18/arch/x86_64/ia32/sys_ia32.c	2006-10-19 11:00:18.000000000 +0400
@@ -915,3 +915,50 @@ long sys32_lookup_dcookie(u32 addr_low, 
 	return sys_lookup_dcookie(((u64)addr_high << 32) | addr_low, buf, len);
 }
 
+asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
+						qid_t id, void __user *addr)
+{
+	long ret;
+	unsigned int cmds;
+	mm_segment_t old_fs;
+	struct if_dqblk dqblk;
+	struct if32_dqblk {
+		__u32 dqb_bhardlimit[2];
+		__u32 dqb_bsoftlimit[2];
+		__u32 dqb_curspace[2];
+		__u32 dqb_ihardlimit[2];
+		__u32 dqb_isoftlimit[2];
+		__u32 dqb_curinodes[2];
+		__u32 dqb_btime[2];
+		__u32 dqb_itime[2];
+		__u32 dqb_valid;
+	} dqblk32;
+
+	cmds = cmd >> SUBCMDSHIFT;
+
+	switch (cmds) {
+		case Q_GETQUOTA:
+			old_fs = get_fs();
+			set_fs(KERNEL_DS);
+			ret = sys_quotactl(cmd, special, id, &dqblk);
+			set_fs(old_fs);
+			memcpy(&dqblk32, &dqblk, sizeof(dqblk32));
+			dqblk32.dqb_valid = dqblk.dqb_valid;
+			if (copy_to_user(addr, &dqblk32, sizeof(dqblk32)))
+				return -EFAULT;
+			break;
+		case Q_SETQUOTA:
+			if (copy_from_user(&dqblk32, addr, sizeof(dqblk32)))
+				return -EFAULT;
+			memcpy(&dqblk, &dqblk32, sizeof(dqblk32));
+			dqblk.dqb_valid = dqblk32.dqb_valid;
+			old_fs = get_fs();
+			set_fs(KERNEL_DS);
+			ret = sys_quotactl(cmd, special, id, &dqblk);
+			set_fs(old_fs);
+			break;
+		default:
+			return sys_quotactl(cmd, special, id, addr);
+	}
+	return ret;
+}

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2007-06-19 22:34 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-06-18  8:21 [PATCH] diskquota: 32bit quota tools on 64bit architectures Vasily Tarasov
2007-06-19 19:33 ` Andrew Morton
2007-06-19 20:09   ` Mikael Pettersson
2007-06-19 22:34   ` David Miller
  -- strict thread matches above, loose matches on Subject: below --
2007-06-15 11:08 Mikael Pettersson
2007-06-15 10:03 Mikael Pettersson
2007-06-15 10:41 ` Vasily Tarasov
2007-06-15 10:43 ` Arnd Bergmann
2007-06-15 11:00   ` Vasily Tarasov
2007-06-15 14:48   ` Vasily Tarasov
2007-06-15 15:24     ` Arnd Bergmann
2007-06-18  7:41       ` Vasily Tarasov
2007-06-15  9:01 Vasily Tarasov
2007-06-15  8:59 Vasily Tarasov
2006-10-25 10:03 Vasily Tarasov
2006-10-25 11:03 ` Arnd Bergmann
2006-10-25 11:25   ` Vasily Tarasov
2006-10-25 11:50     ` Arnd Bergmann
2006-10-20  5:59 Vasily Tarasov
2006-10-19 12:32 Vasily Tarasov
2006-10-19 13:06 ` Alan Cox
2006-10-19 15:22 ` Randy Dunlap
2006-10-19 16:09 ` Andi Kleen
2006-10-20  6:30   ` Vasily Tarasov
2006-10-20  7:12     ` Christoph Hellwig
2006-10-20 12:21     ` Andi Kleen
2006-10-19 17:29 ` Christoph Hellwig
2006-10-20  6:10   ` Vasily Tarasov
2006-10-21 16:28     ` Arnd Bergmann
2006-10-23  2:12       ` David Chinner
2006-10-23 10:51       ` Vasily Tarasov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).