diff mbox series

[v4,1/5] syscalls/quotactl01: Add Q_GETNEXTQUOTA test

Message ID 1574241216-15168-2-git-send-email-xuyang2018.jy@cn.fujitsu.com
State Accepted
Delegated to: Petr Vorel
Headers show
Series optimize quotactl test code | expand

Commit Message

Yang Xu Nov. 20, 2019, 9:13 a.m. UTC
Q_GETNEXTQUOTA was introduced since linux 4.6, this operation is the
same as Q_GETQUOTA, but it returns quota information for the next ID
greater than or equal to id that has a quota set.

Signed-off-by: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
---
 configure.ac                                  |   1 +
 include/lapi/quotactl.h                       |  43 ++++---
 m4/ltp-quota.m4                               |   7 ++
 .../kernel/syscalls/quotactl/quotactl01.c     | 107 +++++++++++++-----
 4 files changed, 115 insertions(+), 43 deletions(-)
 create mode 100644 m4/ltp-quota.m4

Comments

Petr Vorel Nov. 20, 2019, 3:12 p.m. UTC | #1
Hi Jan, Cyril, Xu,

> Q_GETNEXTQUOTA was introduced since linux 4.6, this operation is the
> same as Q_GETQUOTA, but it returns quota information for the next ID
> greater than or equal to id that has a quota set.

> Signed-off-by: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
Reviewed-by: Petr Vorel <pvorel@suse.cz>

LGTM, with 2 questions.

>  #ifndef LAPI_QUOTACTL_H__
>  # define LAPI_QUOTACTL_H__

> +#include <sys/quota.h>
> +
> +#ifdef HAVE_STRUCT_IF_NEXTDQBLK
> +# include <linux/quota.h>
> +#else
> +# ifdef HAVE_LINUX_TYPES_H
> +# include <linux/types.h>
@Jan, @Cyril: Do we want to generally avoid loading <linux/types.h> if not really needed?
__u64 can be uint64_t etc (as it's also visible in struct dqblk in <sys/quota.h>
in various libc headers).
We used this approach for /usr/include/linux/bpf.h and for fanotify fixes for
musl (testcases/kernel/syscalls/fanotify/fanotify.h).

So unless you're against this approach here I'll change it before merge
(and add this info to next version of library API writing guidelines patch
https://patchwork.ozlabs.org/patch/1166786/).

> +struct if_nextdqblk {
> +	__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;
> +	__u32 dqb_id;
> +};

...
> +++ b/testcases/kernel/syscalls/quotactl/quotactl01.c
> @@ -1,7 +1,7 @@
>  // SPDX-License-Identifier: GPL-2.0-or-later
>  /*
>  * Copyright (c) Crackerjack Project., 2007
> -* Copyright (c) 2016 Fujitsu Ltd.
> +* Copyright (c) 2016-2019 FUJITSU LIMITED. All rights reserved
BTW correct formatting is
/*
 *
 */
Not
/*
*
*/
I'll change it during merge (nit, the code is what matters, not formatting, of course).

...
> +static int getnextquota_nsup;
...
>  static void setup(void)
>  {
>  	const char *const cmd[] = {"quotacheck", "-ugF", "vfsv0", MNTPOINT, NULL};
>  	int ret;
> +	getnextquota_nsup = 0;
This is not needed (getnextquota_nsup is static and it's called just once, I'll
remove it before merge).

>  	ret = tst_run_cmd(cmd, NULL, NULL, 1);
>  	switch (ret) {
> @@ -146,6 +183,11 @@ static void setup(void)

>  	if (access(GRPPATH, F_OK) == -1)
>  		tst_brk(TFAIL | TERRNO, "group quotafile didn't exist");
> +
> +	TEST(quotactl(QCMD(Q_GETNEXTQUOTA, USRQUOTA), tst_device->dev,
> +		test_id, (void *) &res_ndq));
> +	if (TST_ERR == EINVAL || TST_ERR == ENOSYS)
Does EINVAL really mans not supported? Shouldn't be just for ENOSYS
> +		getnextquota_nsup = 1;
>  }

Looking at kernel sources - this does not look as not supported, but rather a
failure (we might want to add some test for EINVAL):
	if (!qid_has_mapping(sb->s_user_ns, qid))
		return -EINVAL;

kernel fs/quota/quota.c
/*
 * Return quota for next active quota >= this id, if any exists,
 * otherwise return -ENOENT via ->get_nextdqblk
 */
static int quota_getnextquota(struct super_block *sb, int type, qid_t id,
			  void __user *addr)
{
	struct kqid qid;
	struct qc_dqblk fdq;
	struct if_nextdqblk idq;
	int ret;

	if (!sb->s_qcop->get_nextdqblk)
		return -ENOSYS;
	qid = make_kqid(current_user_ns(), type, id);
	if (!qid_has_mapping(sb->s_user_ns, qid))
		return -EINVAL;
	ret = sb->s_qcop->get_nextdqblk(sb, &qid, &fdq);
	if (ret)
		return ret;
	/* struct if_nextdqblk is a superset of struct if_dqblk */
	copy_to_if_dqblk((struct if_dqblk *)&idq, &fdq);
	idq.dqb_id = from_kqid(current_user_ns(), qid);
	if (copy_to_user(addr, &idq, sizeof(idq)))
		return -EFAULT;
	return 0;
}

Kind regards,
Petr
Petr Vorel Nov. 20, 2019, 3:16 p.m. UTC | #2
Hi Jan, Cyril, Xu,

> > +#ifdef HAVE_STRUCT_IF_NEXTDQBLK
> > +# include <linux/quota.h>
> > +#else
> > +# ifdef HAVE_LINUX_TYPES_H
> > +# include <linux/types.h>
> @Jan, @Cyril: Do we want to generally avoid loading <linux/types.h> if not really needed?
> __u64 can be uint64_t etc (as it's also visible in struct dqblk in <sys/quota.h>
> in various libc headers).
> We used this approach for /usr/include/linux/bpf.h and for fanotify fixes for
> musl (testcases/kernel/syscalls/fanotify/fanotify.h).

> So unless you're against this approach here I'll change it before merge
> (and add this info to next version of library API writing guidelines patch
> https://patchwork.ozlabs.org/patch/1166786/).
+ general question: do we want always test against kernel headers or libc
headers? Libc is often outdated, so mostly it'd be our fallback to be tested.
Ideally both kernel and libc header should be tested, but that's not easily
achievable.

Kind regards,
Petr
Yang Xu Nov. 21, 2019, 2:29 a.m. UTC | #3
on 2019/11/20 23:12, Petr Vorel wrote:

> Hi Jan, Cyril, Xu,
>
>> Q_GETNEXTQUOTA was introduced since linux 4.6, this operation is the
>> same as Q_GETQUOTA, but it returns quota information for the next ID
>> greater than or equal to id that has a quota set.
>> Signed-off-by: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
> Reviewed-by: Petr Vorel <pvorel@suse.cz>
>
> LGTM, with 2 questions.
>
>>   #ifndef LAPI_QUOTACTL_H__
>>   # define LAPI_QUOTACTL_H__
>> +#include <sys/quota.h>
>> +
>> +#ifdef HAVE_STRUCT_IF_NEXTDQBLK
>> +# include <linux/quota.h>
>> +#else
>> +# ifdef HAVE_LINUX_TYPES_H
>> +# include <linux/types.h>
> @Jan, @Cyril: Do we want to generally avoid loading <linux/types.h> if not really needed?
> __u64 can be uint64_t etc (as it's also visible in struct dqblk in <sys/quota.h>
> in various libc headers).
> We used this approach for /usr/include/linux/bpf.h and for fanotify fixes for
> musl (testcases/kernel/syscalls/fanotify/fanotify.h).
>
> So unless you're against this approach here I'll change it before merge
> (and add this info to next version of library API writing guidelines patch
> https://patchwork.ozlabs.org/patch/1166786/).

I have no objection about using uint64_t becuase Q_GETNEXTQUOTA man-pages also uses it.
I used  struct if_nextdqblk as same as <linux/quota.h> defined. But I don't know why we can't use
<linux/type.h> in lapi/quotactl.h and I also use it in lapi/seccomp.h. IMHO, they affected nothing.
Or, they have some redefined errors or not having this headers files in special linux distribution.

>> +struct if_nextdqblk {
>> +	__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;
>> +	__u32 dqb_id;
>> +};
> ...
>> +++ b/testcases/kernel/syscalls/quotactl/quotactl01.c
>> @@ -1,7 +1,7 @@
>>   // SPDX-License-Identifier: GPL-2.0-or-later
>>   /*
>>   * Copyright (c) Crackerjack Project., 2007
>> -* Copyright (c) 2016 Fujitsu Ltd.
>> +* Copyright (c) 2016-2019 FUJITSU LIMITED. All rights reserved
> BTW correct formatting is
> /*
>   *
>   */
> Not
> /*
> *
> */
> I'll change it during merge (nit, the code is what matters, not formatting, of course).
>
> ...
>> +static int getnextquota_nsup;
> ...
>>   static void setup(void)
>>   {
>>   	const char *const cmd[] = {"quotacheck", "-ugF", "vfsv0", MNTPOINT, NULL};
>>   	int ret;
>> +	getnextquota_nsup = 0;
> This is not needed (getnextquota_nsup is static and it's called just once, I'll
> remove it before merge).

Yes.

>
>>   	ret = tst_run_cmd(cmd, NULL, NULL, 1);
>>   	switch (ret) {
>> @@ -146,6 +183,11 @@ static void setup(void)
>>   	if (access(GRPPATH, F_OK) == -1)
>>   		tst_brk(TFAIL | TERRNO, "group quotafile didn't exist");
>> +
>> +	TEST(quotactl(QCMD(Q_GETNEXTQUOTA, USRQUOTA), tst_device->dev,
>> +		test_id, (void *) &res_ndq));
>> +	if (TST_ERR == EINVAL || TST_ERR == ENOSYS)
> Does EINVAL really mans not supported? Shouldn't be just for ENOSYS.

EINVAL can mean non-supported  by using correct argument.

>> +		getnextquota_nsup = 1;
>>   }
> Looking at kernel sources - this does not look as not supported, but rather a
> failure (we might want to add some test for EINVAL):
> 	if (!qid_has_mapping(sb->s_user_ns, qid))
> 		return -EINVAL;
>
> kernel fs/quota/quota.c
> /*
>   * Return quota for next active quota >= this id, if any exists,
>   * otherwise return -ENOENT via ->get_nextdqblk
>   */
> static int quota_getnextquota(struct super_block *sb, int type, qid_t id,
> 			  void __user *addr)
> {
> 	struct kqid qid;
> 	struct qc_dqblk fdq;
> 	struct if_nextdqblk idq;
> 	int ret;
>
> 	if (!sb->s_qcop->get_nextdqblk)
> 		return -ENOSYS;
> 	qid = make_kqid(current_user_ns(), type, id);
> 	if (!qid_has_mapping(sb->s_user_ns, qid))
> 		return -EINVAL;
> 	ret = sb->s_qcop->get_nextdqblk(sb, &qid, &fdq);
> 	if (ret)
> 		return ret;
> 	/* struct if_nextdqblk is a superset of struct if_dqblk */
> 	copy_to_if_dqblk((struct if_dqblk *)&idq, &fdq);
> 	idq.dqb_id = from_kqid(current_user_ns(), qid);
> 	if (copy_to_user(addr, &idq, sizeof(idq)))
> 		return -EFAULT;
> 	return 0;
> }

Hi Petr

look do_quotactl function in fs/quota/quota.c.

static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
                        void __user *addr, const struct path *path)
{

     switch (cmd) {
         case Q_QUOTAON:
                 return quota_quotaon(sb, type, id, path);
         case Q_QUOTAOFF:
                 return quota_quotaoff(sb, type);
         case Q_GETFMT:
                 return quota_getfmt(sb, type, addr);
         case Q_GETINFO:
         ......

          default:
                 return -EINVAL;
         }
}

So if it doesn't have Q_GETNEXTQUOTA cmd, it should report EINVAL(we use correct argument and correct environment, so there is no failure).

> Kind regards,
> Petr
>
>
Yang Xu Nov. 21, 2019, 3:37 a.m. UTC | #4
on 2019/11/20 23:16, Petr Vorel wrote:

> Hi Jan, Cyril, Xu,
>
>>> +#ifdef HAVE_STRUCT_IF_NEXTDQBLK
>>> +# include <linux/quota.h>
>>> +#else
>>> +# ifdef HAVE_LINUX_TYPES_H
>>> +# include <linux/types.h>
>> @Jan, @Cyril: Do we want to generally avoid loading <linux/types.h> if not really needed?
>> __u64 can be uint64_t etc (as it's also visible in struct dqblk in <sys/quota.h>
>> in various libc headers).
>> We used this approach for /usr/include/linux/bpf.h and for fanotify fixes for
>> musl (testcases/kernel/syscalls/fanotify/fanotify.h).
>> So unless you're against this approach here I'll change it before merge
>> (and add this info to next version of library API writing guidelines patch
>> https://patchwork.ozlabs.org/patch/1166786/).
> + general question: do we want always test against kernel headers or libc
> headers? Libc is often outdated, so mostly it'd be our fallback to be tested.
> Ideally both kernel and libc header should be tested, but that's not easily
> achievable.

IMHO, We often test libc and it usually includes kernel headers ie. 
<sys/quota.h> <sys/prctl.h>. I perfet to check one except that glibc and 
kernel they have themselves implementation . If the struct or variable 
is not defined, we can define it in ltp lapi headers. Then we can avoid 
build error and increase coverage(because kernel may implement it).   

>
> Kind regards,
> Petr
>
Petr Vorel Nov. 21, 2019, 5:10 a.m. UTC | #5
Hi Xu,

> > + general question: do we want always test against kernel headers or libc
> > headers? Libc is often outdated, so mostly it'd be our fallback to be tested.
> > Ideally both kernel and libc header should be tested, but that's not easily
> > achievable.

> IMHO, We often test libc and it usually includes kernel headers ie.
> <sys/quota.h> <sys/prctl.h>. I perfet to check one except that glibc and
> kernel they have themselves implementation . If the struct or variable is
> not defined, we can define it in ltp lapi headers. Then we can avoid build
> error and increase coverage(because kernel may implement it).

Yep. I'm ok with using libc headers (increased coverage), but we need good
checks anyway for other libc (at least for musl; bionic also like glibc uses
internally kernel headers, uclibc-ng usually embeds kernel header parts and
strives to be glibc compatible anyway).

Kind regards,
Petr
Petr Vorel Nov. 21, 2019, 5:45 a.m. UTC | #6
Hi Xu,

> > @Jan, @Cyril: Do we want to generally avoid loading <linux/types.h> if not really needed?
> > __u64 can be uint64_t etc (as it's also visible in struct dqblk in <sys/quota.h>
> > in various libc headers).
> > We used this approach for /usr/include/linux/bpf.h and for fanotify fixes for
> > musl (testcases/kernel/syscalls/fanotify/fanotify.h).

> > So unless you're against this approach here I'll change it before merge
> > (and add this info to next version of library API writing guidelines patch
> > https://patchwork.ozlabs.org/patch/1166786/).

> I have no objection about using uint64_t becuase Q_GETNEXTQUOTA man-pages also uses it.
> I used  struct if_nextdqblk as same as <linux/quota.h> defined. But I don't know why we can't use
> <linux/type.h> in lapi/quotactl.h and I also use it in lapi/seccomp.h. IMHO, they affected nothing.
> Or, they have some redefined errors or not having this headers files in special linux distribution.

Based on Jan's comment [1], maybe he meant it specifically for __kernel_fsid_t in
fanotify.h, not as a general approach. __kernel_fsid_t is more complicated than
uint64_t. That's why I'm asking whether there is a general approach we want to
take.

> > > +	TEST(quotactl(QCMD(Q_GETNEXTQUOTA, USRQUOTA), tst_device->dev,
> > > +		test_id, (void *) &res_ndq));
> > > +	if (TST_ERR == EINVAL || TST_ERR == ENOSYS)
> > Does EINVAL really mans not supported? Shouldn't be just for ENOSYS.

> EINVAL can mean non-supported  by using correct argument.

> look do_quotactl function in fs/quota/quota.c.

> static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
>                        void __user *addr, const struct path *path)
> {

>     switch (cmd) {
>         case Q_QUOTAON:
>                 return quota_quotaon(sb, type, id, path);
>         case Q_QUOTAOFF:
>                 return quota_quotaoff(sb, type);
>         case Q_GETFMT:
>                 return quota_getfmt(sb, type, addr);
>         case Q_GETINFO:
>         ......

>          default:
>                 return -EINVAL;
>         }
> }

> So if it doesn't have Q_GETNEXTQUOTA cmd, it should report EINVAL(we use correct argument and correct environment, so there is no failure).
OK, you're right, thanks for info :).

Kind regards,
Petr

[1] https://patchwork.ozlabs.org/patch/1178182/#2281586
Yang Xu Nov. 21, 2019, 7:07 a.m. UTC | #7
on 2019/11/21 13:10, Petr Vorel wrote:

> Hi Xu,
>
>>> + general question: do we want always test against kernel headers or libc
>>> headers? Libc is often outdated, so mostly it'd be our fallback to be tested.
>>> Ideally both kernel and libc header should be tested, but that's not easily
>>> achievable.
>> IMHO, We often test libc and it usually includes kernel headers ie.
>> <sys/quota.h> <sys/prctl.h>. I perfet to check one except that glibc and
>> kernel they have themselves implementation . If the struct or variable is
>> not defined, we can define it in ltp lapi headers. Then we can avoid build
>> error and increase coverage(because kernel may implement it).
> Yep. I'm ok with using libc headers (increased coverage), but we need good
> checks anyway for other libc (at least for musl; bionic also like glibc uses
> internally kernel headers, uclibc-ng usually embeds kernel header parts and
> strives to be glibc compatible anyway).

Hi Petr

Yes. I check <sys/quota.h> and <sys/prctl.h> on musl libc[1] and they don't include linux header files.
So I think checking both kernel and libc headers on other libc(musl,bionic) is meaningful.

ps: If our travis-ci has a target with musl, I think it will be better. I don't know whether possible.

[1]http://git.musl-libc.org/cgit/musl/tree/include/sys/quota.h

Thanks
Yang Xu

>
> Kind regards,
> Petr
>
>
Yang Xu Nov. 21, 2019, 7:45 a.m. UTC | #8
on 2019/11/21 13:45, Petr Vorel wrote:

> Based on Jan's comment [1], maybe he meant it specifically for __kernel_fsid_t in
> fanotify.h, not as a general approach. __kernel_fsid_t is more complicated than
> uint64_t. That's why I'm asking whether there is a general approach we want to
> take.

Hi Petr

I see. Now, I think we should avoid to use <linux/types.h>   because on musl  libc doesn't have it.

Also ,If we use uint64_t, they still failed on 2.6.32-754.el6.x86_64 with undefined  . Or, we should use TST_ABI to define uint64_t them

on myself.

Thanks
Yang Xu
Petr Vorel Nov. 21, 2019, 8:21 a.m. UTC | #9
Hi Xu,

> Yes. I check <sys/quota.h> and <sys/prctl.h> on musl libc[1] and they don't include linux header files.
> So I think checking both kernel and libc headers on other libc(musl,bionic) is meaningful.
But in single C file we decide only on one of these two.
It's a similar problem as testing raw syscall or libc wrapper (which we already
solved with .test_variants).
NOTE: Bionic has generate it's headers from linux headers.

> ps: If our travis-ci has a target with musl, I think it will be better. I don't know whether possible.
It's here. But it requires some more fixes (in a meantime files are deleted),
so I'll post it once it's everything fixed
https://github.com/pevik/ltp/commits/travis/musl
https://travis-ci.org/pevik/ltp/builds/614575796

There is also CI on LTP on all glibc/uclibc-ng/musl in Buildroot
http://autobuild.buildroot.net/index.php?reason=ltp-testsuite-20190930

+ There are other CI based on yocto/openembedded on glibc/uclibc-ng/musl

> [1]http://git.musl-libc.org/cgit/musl/tree/include/sys/quota.h

Kind regards,
Petr
Petr Vorel Nov. 21, 2019, 8:32 a.m. UTC | #10
Hi Xu,

> I see. Now, I think we should avoid to use <linux/types.h>   because on musl  libc doesn't have it.
IMHO <linux/types.h> are always installed from kernel, not from libc
(packaged result of make headers_install run from kernel sources).

> Also ,If we use uint64_t, they still failed on 2.6.32-754.el6.x86_64 with undefined  . Or, we should use TST_ABI to define uint64_t them
Hm, that what I said: using kernel headers is imho easier that using libc
headers (fewer problems with compatibility).
Anyway, I don't want to block this patchset.
We can always merge it as it is and sort/fix this problem later.

Kind regards,
Petr
Yang Xu Nov. 21, 2019, 8:38 a.m. UTC | #11
on 2019/11/21 16:32, Petr Vorel wrote:

> Hi Xu,
>
>> I see. Now, I think we should avoid to use <linux/types.h>   because on musl  libc doesn't have it.
> IMHO <linux/types.h> are always installed from kernel, not from libc
> (packaged result of make headers_install run from kernel sources).

Oh, you are right. For this case, using <linux/types.h> is right that we don't have situation such as fanotify .

>
>> Also ,If we use uint64_t, they still failed on 2.6.32-754.el6.x86_64 with undefined  . Or, we should use TST_ABI to define uint64_t them
> Hm, that what I said: using kernel headers is imho easier that using libc
> headers (fewer problems with compatibility).
> Anyway, I don't want to block this patchset.
> We can always merge it as it is and sort/fix this problem later.

Yes. kernel header is more eaiser that libc. Thanks.

>
> Kind regards,
> Petr
>
>
Jan Stancek Nov. 21, 2019, 9:01 a.m. UTC | #12
----- Original Message -----
> @Jan, @Cyril: Do we want to generally avoid loading <linux/types.h> if not
> really needed?

Yes, we generally try to avoid including kernel headers. Our style-guide says
"Don't use +linux/+ headers if at all possible". uapi on older distros
was more prone to cause LTP build errors.
Yang Xu Nov. 21, 2019, 9:01 a.m. UTC | #13
on 2019/11/21 16:21, Petr Vorel wrote:

> Hi Xu,
>
>> Yes. I check <sys/quota.h> and <sys/prctl.h> on musl libc[1] and they don't include linux header files.
>> So I think checking both kernel and libc headers on other libc(musl,bionic) is meaningful.
> But in single C file we decide only on one of these two.
> It's a similar problem as testing raw syscall or libc wrapper (which we already
> solved with .test_variants).
> NOTE: Bionic has generate it's headers from linux headers.

I see.

Thanks again for reminding Bionic like glibc uses linux headers.

>
>> ps: If our travis-ci has a target with musl, I think it will be better. I don't know whether possible.
> It's here. But it requires some more fixes (in a meantime files are deleted),
> so I'll post it once it's everything fixed
> https://github.com/pevik/ltp/commits/travis/musl
> https://travis-ci.org/pevik/ltp/builds/614575796
>
> There is also CI on LTP on all glibc/uclibc-ng/musl in Buildroot
> http://autobuild.buildroot.net/index.php?reason=ltp-testsuite-20190930
>
> + There are other CI based on yocto/openembedded on glibc/uclibc-ng/musl

It is so cool.  And I think I  can move your musl patches to my ltp fork, so that I can also test them on musl
when I contribute my patches to ltp.

ps: I also think we should not block this patchset.

>
>> [1]http://git.musl-libc.org/cgit/musl/tree/include/sys/quota.h
> Kind regards,
> Petr
>
>
Petr Vorel Nov. 21, 2019, 10:30 a.m. UTC | #14
Hi Jan, Li,

> ----- Original Message -----
> > @Jan, @Cyril: Do we want to generally avoid loading <linux/types.h> if not
> > really needed?

> Yes, we generally try to avoid including kernel headers. Our style-guide says
> "Don't use +linux/+ headers if at all possible". uapi on older distros
> was more prone to cause LTP build errors.
Thank you for pointing out docs, I completely forgot on this page.
BTW it needs some update (examples use old API, linux_syscall_numbers.h).
Also not sure if everything else still applies (4. Call APIs that don't require
freeing up resources on failure first, 2. Sort headers).

> > Also ,If we use uint64_t, they still failed on 2.6.32-754.el6.x86_64 with undefined  . Or, we should use TST_ABI to define uint64_t them
Jan, are you aware of this problem?
Xu, I'm not sure if you're talking about uint64_t problematic in <linux/types.h>
(as you mention kernel) or problem in glibc <sys/types.h> / <stdint.h> / <inttypes.h>?
We have lots of code which is using some of these 3 libc headers, does it fail
on 2.6.32?

Does anybody compile for 2.6.32?
I know we want to keep support for 2.6.x (we had some discussion in the past).
Than it'd be good to have travis build for kernel 2.6.x.

Back to patchset. I suggest to merge it as it is and I'll prepare patches, which
use <sys/types.h> in our tests.

Kind regards,
Petr
Jan Stancek Nov. 21, 2019, 11:08 a.m. UTC | #15
----- Original Message -----
> > > Also ,If we use uint64_t, they still failed on 2.6.32-754.el6.x86_64 with
> > > undefined  . Or, we should use TST_ABI to define uint64_t them
> Jan, are you aware of this problem?

I'm not, it should be defined in stdint.h.

# cat /etc/redhat-release 
Red Hat Enterprise Linux Server release 6.10 (Santiago)

# grep uint64_t -r /usr/include/ | grep stdint
/usr/include/stdint.h:typedef unsigned long int	uint64_t;

> Xu, I'm not sure if you're talking about uint64_t problematic in
> <linux/types.h>
> (as you mention kernel) or problem in glibc <sys/types.h> / <stdint.h> /
> <inttypes.h>?
> We have lots of code which is using some of these 3 libc headers, does it
> fail
> on 2.6.32?
> 
> Does anybody compile for 2.6.32?

[CC Li]
I think RH still does compile latest for regression tests. RHEL6 will be in
sustaining for couple more years.
Petr Vorel Nov. 21, 2019, 3:19 p.m. UTC | #16
Hi Jan,

> ----- Original Message -----
> > > > Also ,If we use uint64_t, they still failed on 2.6.32-754.el6.x86_64 with
> > > > undefined  . Or, we should use TST_ABI to define uint64_t them
> > Jan, are you aware of this problem?

> I'm not, it should be defined in stdint.h.

> # cat /etc/redhat-release 
> Red Hat Enterprise Linux Server release 6.10 (Santiago)

> # grep uint64_t -r /usr/include/ | grep stdint
> /usr/include/stdint.h:typedef unsigned long int	uint64_t;

> > Xu, I'm not sure if you're talking about uint64_t problematic in
> > <linux/types.h>
> > (as you mention kernel) or problem in glibc <sys/types.h> / <stdint.h> /
> > <inttypes.h>?
> > We have lots of code which is using some of these 3 libc headers, does it
> > fail
> > on 2.6.32?

> > Does anybody compile for 2.6.32?

> [CC Li]
> I think RH still does compile latest for regression tests. RHEL6 will be in
> sustaining for couple more years. 
Thanks for info. Sorry I forgot, we have CentOS 6.10 in travis, that should be
enough for testing build in old toolchain.
diff mbox series

Patch

diff --git a/configure.ac b/configure.ac
index c8c0db2dc..50d14967d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -251,6 +251,7 @@  AC_DEFINE_UNQUOTED(NUMA_ERROR_MSG, ["$numa_error_msg"], [Error message when no N
 
 
 LTP_CHECK_SYSCALL_PERF_EVENT_OPEN
+LTP_CHECK_SYSCALL_QUOTACTL
 LTP_CHECK_SYSCALL_SIGNALFD
 LTP_CHECK_SYSCALL_UTIMENSAT
 LTP_CHECK_TASKSTATS
diff --git a/include/lapi/quotactl.h b/include/lapi/quotactl.h
index 729472f69..5c49cedce 100644
--- a/include/lapi/quotactl.h
+++ b/include/lapi/quotactl.h
@@ -1,26 +1,41 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
- * Copyright (c) 2017 Fujitsu Ltd.
+ * Copyright (c) 2017-2019 Fujitsu Ltd.
  * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * Author: Yang Xu <xuyang2018.jy@cn.jujitsu.com>
  */
 
 #ifndef LAPI_QUOTACTL_H__
 # define LAPI_QUOTACTL_H__
 
+#include <sys/quota.h>
+
+#ifdef HAVE_STRUCT_IF_NEXTDQBLK
+# include <linux/quota.h>
+#else
+# ifdef HAVE_LINUX_TYPES_H
+# include <linux/types.h>
+struct if_nextdqblk {
+	__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;
+	__u32 dqb_id;
+};
+#endif
+#endif
+
 # ifndef Q_XGETNEXTQUOTA
 #  define Q_XGETNEXTQUOTA XQM_CMD(9)
 # endif
 
+# ifndef Q_GETNEXTQUOTA
+#  define Q_GETNEXTQUOTA 0x800009 /* get disk limits and usage >= ID */
+# endif
+
 #endif /* LAPI_QUOTACTL_H__ */
diff --git a/m4/ltp-quota.m4 b/m4/ltp-quota.m4
new file mode 100644
index 000000000..e8d08c6b7
--- /dev/null
+++ b/m4/ltp-quota.m4
@@ -0,0 +1,7 @@ 
+dnl SPDX-License-Identifier: GPL-2.0-or-later
+dnl Copyright (c) 2019 Fujitsu Ltd.
+dnl Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
+
+AC_DEFUN([LTP_CHECK_SYSCALL_QUOTACTL],[
+AC_CHECK_TYPES([struct if_nextdqblk],,,[#include <linux/quota.h>])
+])
diff --git a/testcases/kernel/syscalls/quotactl/quotactl01.c b/testcases/kernel/syscalls/quotactl/quotactl01.c
index 2f563515d..41662a818 100644
--- a/testcases/kernel/syscalls/quotactl/quotactl01.c
+++ b/testcases/kernel/syscalls/quotactl/quotactl01.c
@@ -1,7 +1,7 @@ 
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
 * Copyright (c) Crackerjack Project., 2007
-* Copyright (c) 2016 Fujitsu Ltd.
+* Copyright (c) 2016-2019 FUJITSU LIMITED. All rights reserved
 * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
 *
 * This testcase checks the basic flag of quotactl(2) for non-XFS filesystems:
@@ -16,19 +16,23 @@ 
 *    flag for user.
 * 6) quotactl(2) succeeds to get quota format with Q_GETFMT flag for user.
 * 7) quotactl(2) succeeds to update quota usages with Q_SYNC flag for user.
-* 8) quotactl(2) succeeds to turn off quota with Q_QUOTAOFF flag for user.
-* 9) quotactl(2) succeeds to turn on quota with Q_QUOTAON flag for group.
-* 10) quotactl(2) succeeds to set disk quota limits with Q_SETQUOTA flag
+* 8) quotactl(2) succeeds to get disk quota limit greater than or equal to
+*    ID with Q_GETNEXTQUOTA flag for user.
+* 9) quotactl(2) succeeds to turn off quota with Q_QUOTAOFF flag for user.
+* 10) quotactl(2) succeeds to turn on quota with Q_QUOTAON flag for group.
+* 11) quotactl(2) succeeds to set disk quota limits with Q_SETQUOTA flag
 *     for group.
-* 11) quotactl(2) succeeds to get disk quota limits with Q_GETQUOTA flag
+* 12) quotactl(2) succeeds to get disk quota limits with Q_GETQUOTA flag
 *     for group.
-* 12) quotactl(2) succeeds to set information about quotafile with Q_SETINFO
+* 13) quotactl(2) succeeds to set information about quotafile with Q_SETINFO
 *     flag for group.
-* 13) quotactl(2) succeeds to get information about quotafile with Q_GETINFO
+* 14) quotactl(2) succeeds to get information about quotafile with Q_GETINFO
 *     flag for group.
-* 14) quotactl(2) succeeds to get quota format with Q_GETFMT flag for group.
-* 15) quotactl(2) succeeds to update quota usages with Q_SYNC flag for group.
-* 16) quotactl(2) succeeds to turn off quota with Q_QUOTAOFF flag for group.
+* 15) quotactl(2) succeeds to get quota format with Q_GETFMT flag for group.
+* 16) quotactl(2) succeeds to update quota usages with Q_SYNC flag for group.
+* 17) quotactl(2) succeeds to get disk quota limit greater than or equal to
+*     ID with Q_GETNEXTQUOTA flag for group.
+* 18) quotactl(2) succeeds to turn off quota with Q_QUOTAOFF flag for group.
 */
 
 #include "config.h"
@@ -36,11 +40,13 @@ 
 #include <string.h>
 #include <unistd.h>
 #include <stdio.h>
-#include <sys/quota.h>
+#include "lapi/quotactl.h"
 
 #include "tst_test.h"
 
-#define QFMT_VFS_V0	2
+#ifndef QFMT_VFS_V0
+# define QFMT_VFS_V0	2
+#endif
 #define USRPATH MNTPOINT "/aquota.user"
 #define GRPPATH MNTPOINT "/aquota.group"
 #define FMTID	QFMT_VFS_V0
@@ -60,6 +66,9 @@  static struct dqinfo set_qf = {
 };
 static struct dqinfo res_qf;
 static int32_t fmt_buf;
+static int getnextquota_nsup;
+
+static struct if_nextdqblk res_ndq;
 
 static struct tcase {
 	int cmd;
@@ -69,65 +78,93 @@  static struct tcase {
 	void *res_data;
 	int sz;
 	char *des;
+	char *tname;
 } tcases[] = {
 	{QCMD(Q_QUOTAON, USRQUOTA), &fmt_id, USRPATH,
-	NULL, NULL, 0, "turn on quota for user"},
+	NULL, NULL, 0, "turn on quota for user",
+	"QCMD(Q_QUOTAON, USRQUOTA)"},
 
 	{QCMD(Q_SETQUOTA, USRQUOTA), &test_id, &set_dq,
-	NULL, NULL, 0, "set disk quota limit for user"},
+	NULL, NULL, 0, "set disk quota limit for user",
+	"QCMD(Q_SETQUOTA, USRQUOTA)"},
 
 	{QCMD(Q_GETQUOTA, USRQUOTA), &test_id, &res_dq,
 	&set_dq.dqb_bsoftlimit, &res_dq.dqb_bsoftlimit,
-	sizeof(res_dq.dqb_bsoftlimit), "get disk quota limit for user"},
+	sizeof(res_dq.dqb_bsoftlimit), "get disk quota limit for user",
+	"QCMD(Q_GETQUOTA, USRQUOTA)"},
 
 	{QCMD(Q_SETINFO, USRQUOTA), &test_id, &set_qf,
-	NULL, NULL, 0, "set information about quotafile for user"},
+	NULL, NULL, 0, "set information about quotafile for user",
+	"QCMD(Q_SETINFO, USRQUOTA)"},
 
 	{QCMD(Q_GETINFO, USRQUOTA), &test_id, &res_qf,
 	&set_qf.dqi_bgrace, &res_qf.dqi_bgrace, sizeof(res_qf.dqi_bgrace),
-	"get information about quotafile for user"},
+	"get information about quotafile for user",
+	"QCMD(Q_GETINFO, USRQUOTA)"},
 
 	{QCMD(Q_GETFMT, USRQUOTA), &test_id, &fmt_buf,
 	&fmt_id, &fmt_buf, sizeof(fmt_buf),
-	"get quota format for user"},
+	"get quota format for user",
+	"QCMD(Q_GETFMT, USRQUOTA)"},
 
 	{QCMD(Q_SYNC, USRQUOTA), &test_id, &res_dq,
-	NULL, NULL, 0, "update quota usages for user"},
+	NULL, NULL, 0, "update quota usages for user",
+	"QCMD(Q_SYNC, USRQUOTA)"},
+
+	{QCMD(Q_GETNEXTQUOTA, USRQUOTA), &test_id, &res_ndq,
+	&test_id, &res_ndq.dqb_id, sizeof(res_ndq.dqb_id),
+	"get next disk quota limit for user",
+	"QCMD(Q_GETNEXTQUOTA, USRQUOTA)"},
 
 	{QCMD(Q_QUOTAOFF, USRQUOTA), &test_id, USRPATH,
-	NULL, NULL, 0, "turn off quota for user"},
+	NULL, NULL, 0, "turn off quota for user",
+	"QCMD(Q_QUOTAOFF, USRQUOTA)"},
 
 	{QCMD(Q_QUOTAON, GRPQUOTA), &fmt_id, GRPPATH,
-	NULL, NULL, 0, "turn on quota for group"},
+	NULL, NULL, 0, "turn on quota for group",
+	"QCMD(Q_QUOTAON, GRPQUOTA)"},
 
 	{QCMD(Q_SETQUOTA, GRPQUOTA), &test_id, &set_dq,
-	NULL, NULL, 0, "set disk quota limit for group"},
+	NULL, NULL, 0, "set disk quota limit for group",
+	"QCMD(Q_SETQUOTA, GRPQUOTA)"},
 
 	{QCMD(Q_GETQUOTA, GRPQUOTA), &test_id, &res_dq, &set_dq.dqb_bsoftlimit,
 	&res_dq.dqb_bsoftlimit, sizeof(res_dq.dqb_bsoftlimit),
-	"set disk quota limit for group"},
+	"set disk quota limit for group",
+	"QCMD(Q_GETQUOTA, GRPQUOTA)"},
 
 	{QCMD(Q_SETINFO, GRPQUOTA), &test_id, &set_qf,
-	NULL, NULL, 0, "set information about quotafile for group"},
+	NULL, NULL, 0, "set information about quotafile for group",
+	"QCMD(Q_SETINFO, GRPQUOTA)"},
 
 	{QCMD(Q_GETINFO, GRPQUOTA), &test_id, &res_qf, &set_qf.dqi_bgrace,
 	&res_qf.dqi_bgrace, sizeof(res_qf.dqi_bgrace),
-	"get information about quotafile for group"},
+	"get information about quotafile for group",
+	"QCMD(Q_GETINFO, GRPQUOTA)"},
 
 	{QCMD(Q_GETFMT, GRPQUOTA), &test_id, &fmt_buf,
-	&fmt_id, &fmt_buf, sizeof(fmt_buf), "get quota format for group"},
+	&fmt_id, &fmt_buf, sizeof(fmt_buf), "get quota format for group",
+	"QCMD(Q_GETFMT, GRPQUOTA)"},
 
 	{QCMD(Q_SYNC, GRPQUOTA), &test_id, &res_dq,
-	NULL, NULL, 0, "update quota usages for group"},
+	NULL, NULL, 0, "update quota usages for group",
+	"QCMD(Q_SYNC, GRPQUOTA)"},
+
+	{QCMD(Q_GETNEXTQUOTA, GRPQUOTA), &test_id, &res_ndq,
+	&test_id, &res_ndq.dqb_id, sizeof(res_ndq.dqb_id),
+	"get next disk quota limit for group",
+	"QCMD(Q_GETNEXTQUOTA, GRPQUOTA)"},
 
 	{QCMD(Q_QUOTAOFF, GRPQUOTA), &test_id, GRPPATH,
-	NULL, NULL, 0, "turn off quota for group"}
+	NULL, NULL, 0, "turn off quota for group",
+	"QCMD(Q_QUOTAOFF, GRPQUOTA)"},
 };
 
 static void setup(void)
 {
 	const char *const cmd[] = {"quotacheck", "-ugF", "vfsv0", MNTPOINT, NULL};
 	int ret;
+	getnextquota_nsup = 0;
 
 	ret = tst_run_cmd(cmd, NULL, NULL, 1);
 	switch (ret) {
@@ -146,6 +183,11 @@  static void setup(void)
 
 	if (access(GRPPATH, F_OK) == -1)
 		tst_brk(TFAIL | TERRNO, "group quotafile didn't exist");
+
+	TEST(quotactl(QCMD(Q_GETNEXTQUOTA, USRQUOTA), tst_device->dev,
+		test_id, (void *) &res_ndq));
+	if (TST_ERR == EINVAL || TST_ERR == ENOSYS)
+		getnextquota_nsup = 1;
 }
 
 static void verify_quota(unsigned int n)
@@ -155,7 +197,15 @@  static void verify_quota(unsigned int n)
 	res_dq.dqb_bsoftlimit = 0;
 	res_qf.dqi_igrace = 0;
 	fmt_buf = 0;
+	res_ndq.dqb_id = -1;
 
+	tst_res(TINFO, "Test #%d: %s", n, tc->tname);
+	if ((tc->cmd == QCMD(Q_GETNEXTQUOTA, USRQUOTA) ||
+		tc->cmd == QCMD(Q_GETNEXTQUOTA, GRPQUOTA)) &&
+		getnextquota_nsup) {
+		tst_res(TCONF, "current system doesn't support this cmd, skip it");
+		return;
+	}
 	TEST(quotactl(tc->cmd, tst_device->dev, *tc->id, tc->addr));
 	if (TST_RET == -1) {
 		tst_res(TFAIL | TTERRNO, "quotactl failed to %s", tc->des);
@@ -189,4 +239,3 @@  static struct tst_test test = {
 	.mnt_data = "usrquota,grpquota",
 	.setup = setup,
 };
-