Message ID | 1571821231-3846-4-git-send-email-xuyang2018.jy@cn.fujitsu.com |
---|---|
State | Changes Requested |
Delegated to: | Petr Vorel |
Headers | show |
Series | optimize quotactl test code | expand |
On Wed 23-10-19 17:00:28, Yang Xu wrote: > 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> I was thinking about how much these tests are actually needed. The thing is that fstests have also quota tests. And as part of these tests we do run e.g. repquota(8) and verify its output and that uses Q_GETNEXTQUOTA inside. So Q_GETNEXTQUOTA gets testing as part of fstests. On the other hand fstests are focused on testing the general quota functionality as user would use it so we don't really try to make sure all quotactl calls are covered. So there's still some value in low level testing of each quotactl like you do here. Honza > --- > include/lapi/quotactl.h | 23 ++--- > m4/ltp-quota.m4 | 36 +------- > .../kernel/syscalls/quotactl/quotactl01.c | 86 ++++++++++++------- > 3 files changed, 67 insertions(+), 78 deletions(-) > > diff --git a/include/lapi/quotactl.h b/include/lapi/quotactl.h > index 729472f69..99f4e5fc5 100644 > --- a/include/lapi/quotactl.h > +++ b/include/lapi/quotactl.h > @@ -1,26 +1,21 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > /* > - * Copyright (c) 2017 Fujitsu Ltd. > + * Copyright (c) 2016-2019 FUJITSU LIMITED. All rights reserved. > * 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 <linux/quota.h> > + > # 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 > index c5e233ca1..964c34925 100644 > --- a/m4/ltp-quota.m4 > +++ b/m4/ltp-quota.m4 > @@ -1,39 +1,7 @@ > dnl SPDX-License-Identifier: GPL-2.0-or-later > dnl Copyright (c) Cisco Systems, Inc, 2008 > +dnl Copyright (c) 2019 Fujitsu Ltd. > > AC_DEFUN([LTP_CHECK_SYSCALL_QUOTACTL],[ > - AC_LINK_IFELSE([AC_LANG_SOURCE([ > -#define _LINUX_QUOTA_VERSION 2 > -#include <sys/types.h> > -#include <sys/quota.h> > -#include <unistd.h> > -int main(void) { > - struct dqblk dq; > - return quotactl(QCMD(Q_GETINFO, USRQUOTA), (const char *) "/dev/null", > - geteuid(), (caddr_t) &dq); > -}])],[has_quotav2="yes"]) > - > -if test "x$has_quotav2" = xyes; then > - AC_DEFINE(HAVE_QUOTAV2,1,[Define to 1 if you have quota v2]) > -else > - > - # got quota v1? > - AC_LINK_IFELSE([AC_LANG_SOURCE([ > -#define _LINUX_QUOTA_VERSION 1 > -#include <sys/types.h> > -#include <sys/quota.h> > -#include <unistd.h> > -int main(void) { > - struct dqblk dq; > - return quotactl(QCMD(Q_GETQUOTA, USRQUOTA), (const char *) "/dev/null", > - geteuid(), (caddr_t) &dq); > -}])],[has_quotav1="yes"]) > - > - if test "x$has_quotav1" = xyes; then > - AC_DEFINE(HAVE_QUOTAV1,1,[Define to 1 if you have quota v1]) > - else > - AC_MSG_WARN(Couldn't determine quota version (please submit config.log and manpage to ltp@lists.linux.it)) > - fi > - > -fi > +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 b0be525d6..af78646e4 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_GETNEXTSTAT 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_GETNEXTSTAT flag for group. > +* 18) quotactl(2) succeeds to turn off quota with Q_QUOTAOFF flag for group. > */ > > #include <errno.h> > @@ -36,10 +40,9 @@ > #include <unistd.h> > #include <stdio.h> > #include "config.h" > - > +#include <sys/quota.h> > #include "tst_test.h" > - > -# include <sys/quota.h> > +#include "lapi/quotactl.h" > > # define QFMT_VFS_V0 2 > # define USRPATH MNTPOINT "/aquota.user" > @@ -63,6 +66,10 @@ static struct dqinfo set_qf = { > static struct dqinfo res_qf; > static int32_t fmt_buf; > > +#if defined(HAVE_STRUCT_IF_NEXTDQBLK) > +static struct if_nextdqblk res_ndq; > +#endif > + > static struct tcase { > int cmd; > int *id; > @@ -70,60 +77,73 @@ static struct tcase { > void *set_data; > void *res_data; > int sz; > + int nflag; > char *des; > } tcases[] = { > {QCMD(Q_QUOTAON, USRQUOTA), &fmt_id, USRPATH, > - NULL, NULL, 0, "turn on quota for user"}, > + NULL, NULL, 0, 0, "turn on quota for user"}, > > {QCMD(Q_SETQUOTA, USRQUOTA), &test_id, &set_dq, > - NULL, NULL, 0, "set disk quota limit for user"}, > + NULL, NULL, 0, 0, "set disk quota limit for user"}, > > {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), 0, "get disk quota limit for user"}, > > {QCMD(Q_SETINFO, USRQUOTA), &test_id, &set_qf, > - NULL, NULL, 0, "set information about quotafile for user"}, > + NULL, NULL, 0, 0, "set information about quotafile for user"}, > > {QCMD(Q_GETINFO, USRQUOTA), &test_id, &res_qf, > - &set_qf.dqi_bgrace, &res_qf.dqi_bgrace, sizeof(res_qf.dqi_bgrace), > + &set_qf.dqi_bgrace, &res_qf.dqi_bgrace, sizeof(res_qf.dqi_bgrace), 0, > "get information about quotafile for user"}, > > {QCMD(Q_GETFMT, USRQUOTA), &test_id, &fmt_buf, > - &fmt_id, &fmt_buf, sizeof(fmt_buf), > + &fmt_id, &fmt_buf, sizeof(fmt_buf), 0, > "get quota format for user"}, > > {QCMD(Q_SYNC, USRQUOTA), &test_id, &res_dq, > - NULL, NULL, 0, "update quota usages for user"}, > + NULL, NULL, 0, 0, "update quota usages for user"}, > + > +#if defined(HAVE_STRUCT_IF_NEXTDQBLK) > + {QCMD(Q_GETNEXTQUOTA, USRQUOTA), &test_id, &res_ndq, > + &test_id, &res_ndq.dqb_id, sizeof(res_ndq.dqb_id), 1, > + "get next disk quota limit for user"}, > +#endif > > {QCMD(Q_QUOTAOFF, USRQUOTA), &test_id, USRPATH, > - NULL, NULL, 0, "turn off quota for user"}, > + NULL, NULL, 0, 0, "turn off quota for user"}, > > {QCMD(Q_QUOTAON, GRPQUOTA), &fmt_id, GRPPATH, > - NULL, NULL, 0, "turn on quota for group"}, > + NULL, NULL, 0, 0, "turn on quota for group"}, > > {QCMD(Q_SETQUOTA, GRPQUOTA), &test_id, &set_dq, > - NULL, NULL, 0, "set disk quota limit for group"}, > + NULL, NULL, 0, 0, "set disk quota limit for group"}, > > {QCMD(Q_GETQUOTA, GRPQUOTA), &test_id, &res_dq, &set_dq.dqb_bsoftlimit, > - &res_dq.dqb_bsoftlimit, sizeof(res_dq.dqb_bsoftlimit), > + &res_dq.dqb_bsoftlimit, sizeof(res_dq.dqb_bsoftlimit), 0, > "set disk quota limit for group"}, > > {QCMD(Q_SETINFO, GRPQUOTA), &test_id, &set_qf, > - NULL, NULL, 0, "set information about quotafile for group"}, > + NULL, NULL, 0, 0, "set information about quotafile for group"}, > > {QCMD(Q_GETINFO, GRPQUOTA), &test_id, &res_qf, &set_qf.dqi_bgrace, > - &res_qf.dqi_bgrace, sizeof(res_qf.dqi_bgrace), > + &res_qf.dqi_bgrace, sizeof(res_qf.dqi_bgrace), 0, > "get information about quotafile for group"}, > > {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), 0, "get quota format for group"}, > > {QCMD(Q_SYNC, GRPQUOTA), &test_id, &res_dq, > - NULL, NULL, 0, "update quota usages for group"}, > + NULL, NULL, 0, 0, "update quota usages for group"}, > + > +#if defined(HAVE_STRUCT_IF_NEXTDQBLK) > + {QCMD(Q_GETNEXTQUOTA, GRPQUOTA), &test_id, &res_ndq, > + &test_id, &res_ndq.dqb_id, sizeof(res_ndq.dqb_id), 1, > + "get next disk quota limit for group"}, > +#endif > > {QCMD(Q_QUOTAOFF, GRPQUOTA), &test_id, GRPPATH, > - NULL, NULL, 0, "turn off quota for group"} > + NULL, NULL, 0, 0, "turn off quota for group"} > }; > > static void setup(void) > @@ -156,9 +176,15 @@ static void verify_quota(unsigned int n) > > res_dq.dqb_bsoftlimit = 0; > res_qf.dqi_igrace = 0; > +#if defined(HAVE_STRUCT_IF_NEXTDQBLK) > + res_ndq.dqb_id = -1; > +#endif > fmt_buf = 0; > - > TEST(quotactl(tc->cmd, tst_device->dev, *tc->id, tc->addr)); > + if (TST_ERR == ENOSYS && tc->nflag) { > + tst_res(TCONF, "Current system doesn't support Q_GETNEXTQUOTA, it needs kernel>=4.6!"); > + return; > + } > if (TST_RET == -1) { > tst_res(TFAIL | TTERRNO, "quotactl failed to %s", tc->des); > return; > -- > 2.18.0 > > >
on 2019/10/24 16:25, Jan Kara wrote: > On Wed 23-10-19 17:00:28, Yang Xu wrote: >> 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> > > I was thinking about how much these tests are actually needed. The thing is > that fstests have also quota tests. And as part of these tests we do run > e.g. repquota(8) and verify its output and that uses Q_GETNEXTQUOTA inside. > So Q_GETNEXTQUOTA gets testing as part of fstests. On the other hand > fstests are focused on testing the general quota functionality as user > would use it so we don't really try to make sure all quotactl calls are > covered. So there's still some value in low level testing of each > quotactl like you do here. IMO, fstests tests quota more deeply and it coverS more user scenes(also some regresstion tests). But in ltp, in syscalls/quotactl, I try my best to test various subcmds (it may stay in API level but not actual quota actions) and three quota types(user,group,project). In addition, I am writing quotactl error tests as man-pages mentioned. > > Honza > >> --- >> include/lapi/quotactl.h | 23 ++--- >> m4/ltp-quota.m4 | 36 +------- >> .../kernel/syscalls/quotactl/quotactl01.c | 86 ++++++++++++------- >> 3 files changed, 67 insertions(+), 78 deletions(-) >> >> diff --git a/include/lapi/quotactl.h b/include/lapi/quotactl.h >> index 729472f69..99f4e5fc5 100644 >> --- a/include/lapi/quotactl.h >> +++ b/include/lapi/quotactl.h >> @@ -1,26 +1,21 @@ >> +// SPDX-License-Identifier: GPL-2.0-or-later >> /* >> - * Copyright (c) 2017 Fujitsu Ltd. >> + * Copyright (c) 2016-2019 FUJITSU LIMITED. All rights reserved. >> * 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 <linux/quota.h> >> + >> # 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 >> index c5e233ca1..964c34925 100644 >> --- a/m4/ltp-quota.m4 >> +++ b/m4/ltp-quota.m4 >> @@ -1,39 +1,7 @@ >> dnl SPDX-License-Identifier: GPL-2.0-or-later >> dnl Copyright (c) Cisco Systems, Inc, 2008 >> +dnl Copyright (c) 2019 Fujitsu Ltd. >> >> AC_DEFUN([LTP_CHECK_SYSCALL_QUOTACTL],[ >> - AC_LINK_IFELSE([AC_LANG_SOURCE([ >> -#define _LINUX_QUOTA_VERSION 2 >> -#include <sys/types.h> >> -#include <sys/quota.h> >> -#include <unistd.h> >> -int main(void) { >> - struct dqblk dq; >> - return quotactl(QCMD(Q_GETINFO, USRQUOTA), (const char *) "/dev/null", >> - geteuid(), (caddr_t) &dq); >> -}])],[has_quotav2="yes"]) >> - >> -if test "x$has_quotav2" = xyes; then >> - AC_DEFINE(HAVE_QUOTAV2,1,[Define to 1 if you have quota v2]) >> -else >> - >> - # got quota v1? >> - AC_LINK_IFELSE([AC_LANG_SOURCE([ >> -#define _LINUX_QUOTA_VERSION 1 >> -#include <sys/types.h> >> -#include <sys/quota.h> >> -#include <unistd.h> >> -int main(void) { >> - struct dqblk dq; >> - return quotactl(QCMD(Q_GETQUOTA, USRQUOTA), (const char *) "/dev/null", >> - geteuid(), (caddr_t) &dq); >> -}])],[has_quotav1="yes"]) >> - >> - if test "x$has_quotav1" = xyes; then >> - AC_DEFINE(HAVE_QUOTAV1,1,[Define to 1 if you have quota v1]) >> - else >> - AC_MSG_WARN(Couldn't determine quota version (please submit config.log and manpage to ltp@lists.linux.it)) >> - fi >> - >> -fi >> +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 b0be525d6..af78646e4 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_GETNEXTSTAT 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_GETNEXTSTAT flag for group. >> +* 18) quotactl(2) succeeds to turn off quota with Q_QUOTAOFF flag for group. >> */ >> >> #include <errno.h> >> @@ -36,10 +40,9 @@ >> #include <unistd.h> >> #include <stdio.h> >> #include "config.h" >> - >> +#include <sys/quota.h> >> #include "tst_test.h" >> - >> -# include <sys/quota.h> >> +#include "lapi/quotactl.h" >> >> # define QFMT_VFS_V0 2 >> # define USRPATH MNTPOINT "/aquota.user" >> @@ -63,6 +66,10 @@ static struct dqinfo set_qf = { >> static struct dqinfo res_qf; >> static int32_t fmt_buf; >> >> +#if defined(HAVE_STRUCT_IF_NEXTDQBLK) >> +static struct if_nextdqblk res_ndq; >> +#endif >> + >> static struct tcase { >> int cmd; >> int *id; >> @@ -70,60 +77,73 @@ static struct tcase { >> void *set_data; >> void *res_data; >> int sz; >> + int nflag; >> char *des; >> } tcases[] = { >> {QCMD(Q_QUOTAON, USRQUOTA), &fmt_id, USRPATH, >> - NULL, NULL, 0, "turn on quota for user"}, >> + NULL, NULL, 0, 0, "turn on quota for user"}, >> >> {QCMD(Q_SETQUOTA, USRQUOTA), &test_id, &set_dq, >> - NULL, NULL, 0, "set disk quota limit for user"}, >> + NULL, NULL, 0, 0, "set disk quota limit for user"}, >> >> {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), 0, "get disk quota limit for user"}, >> >> {QCMD(Q_SETINFO, USRQUOTA), &test_id, &set_qf, >> - NULL, NULL, 0, "set information about quotafile for user"}, >> + NULL, NULL, 0, 0, "set information about quotafile for user"}, >> >> {QCMD(Q_GETINFO, USRQUOTA), &test_id, &res_qf, >> - &set_qf.dqi_bgrace, &res_qf.dqi_bgrace, sizeof(res_qf.dqi_bgrace), >> + &set_qf.dqi_bgrace, &res_qf.dqi_bgrace, sizeof(res_qf.dqi_bgrace), 0, >> "get information about quotafile for user"}, >> >> {QCMD(Q_GETFMT, USRQUOTA), &test_id, &fmt_buf, >> - &fmt_id, &fmt_buf, sizeof(fmt_buf), >> + &fmt_id, &fmt_buf, sizeof(fmt_buf), 0, >> "get quota format for user"}, >> >> {QCMD(Q_SYNC, USRQUOTA), &test_id, &res_dq, >> - NULL, NULL, 0, "update quota usages for user"}, >> + NULL, NULL, 0, 0, "update quota usages for user"}, >> + >> +#if defined(HAVE_STRUCT_IF_NEXTDQBLK) >> + {QCMD(Q_GETNEXTQUOTA, USRQUOTA), &test_id, &res_ndq, >> + &test_id, &res_ndq.dqb_id, sizeof(res_ndq.dqb_id), 1, >> + "get next disk quota limit for user"}, >> +#endif >> >> {QCMD(Q_QUOTAOFF, USRQUOTA), &test_id, USRPATH, >> - NULL, NULL, 0, "turn off quota for user"}, >> + NULL, NULL, 0, 0, "turn off quota for user"}, >> >> {QCMD(Q_QUOTAON, GRPQUOTA), &fmt_id, GRPPATH, >> - NULL, NULL, 0, "turn on quota for group"}, >> + NULL, NULL, 0, 0, "turn on quota for group"}, >> >> {QCMD(Q_SETQUOTA, GRPQUOTA), &test_id, &set_dq, >> - NULL, NULL, 0, "set disk quota limit for group"}, >> + NULL, NULL, 0, 0, "set disk quota limit for group"}, >> >> {QCMD(Q_GETQUOTA, GRPQUOTA), &test_id, &res_dq, &set_dq.dqb_bsoftlimit, >> - &res_dq.dqb_bsoftlimit, sizeof(res_dq.dqb_bsoftlimit), >> + &res_dq.dqb_bsoftlimit, sizeof(res_dq.dqb_bsoftlimit), 0, >> "set disk quota limit for group"}, >> >> {QCMD(Q_SETINFO, GRPQUOTA), &test_id, &set_qf, >> - NULL, NULL, 0, "set information about quotafile for group"}, >> + NULL, NULL, 0, 0, "set information about quotafile for group"}, >> >> {QCMD(Q_GETINFO, GRPQUOTA), &test_id, &res_qf, &set_qf.dqi_bgrace, >> - &res_qf.dqi_bgrace, sizeof(res_qf.dqi_bgrace), >> + &res_qf.dqi_bgrace, sizeof(res_qf.dqi_bgrace), 0, >> "get information about quotafile for group"}, >> >> {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), 0, "get quota format for group"}, >> >> {QCMD(Q_SYNC, GRPQUOTA), &test_id, &res_dq, >> - NULL, NULL, 0, "update quota usages for group"}, >> + NULL, NULL, 0, 0, "update quota usages for group"}, >> + >> +#if defined(HAVE_STRUCT_IF_NEXTDQBLK) >> + {QCMD(Q_GETNEXTQUOTA, GRPQUOTA), &test_id, &res_ndq, >> + &test_id, &res_ndq.dqb_id, sizeof(res_ndq.dqb_id), 1, >> + "get next disk quota limit for group"}, >> +#endif >> >> {QCMD(Q_QUOTAOFF, GRPQUOTA), &test_id, GRPPATH, >> - NULL, NULL, 0, "turn off quota for group"} >> + NULL, NULL, 0, 0, "turn off quota for group"} >> }; >> >> static void setup(void) >> @@ -156,9 +176,15 @@ static void verify_quota(unsigned int n) >> >> res_dq.dqb_bsoftlimit = 0; >> res_qf.dqi_igrace = 0; >> +#if defined(HAVE_STRUCT_IF_NEXTDQBLK) >> + res_ndq.dqb_id = -1; >> +#endif >> fmt_buf = 0; >> - >> TEST(quotactl(tc->cmd, tst_device->dev, *tc->id, tc->addr)); >> + if (TST_ERR == ENOSYS && tc->nflag) { >> + tst_res(TCONF, "Current system doesn't support Q_GETNEXTQUOTA, it needs kernel>=4.6!"); >> + return; >> + } >> if (TST_RET == -1) { >> tst_res(TFAIL | TTERRNO, "quotactl failed to %s", tc->des); >> return; >> -- >> 2.18.0 >> >> >>
Hi Jan, > On Wed 23-10-19 17:00:28, Yang Xu wrote: > > 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> > I was thinking about how much these tests are actually needed. The thing is > that fstests have also quota tests. And as part of these tests we do run > e.g. repquota(8) and verify its output and that uses Q_GETNEXTQUOTA inside. > So Q_GETNEXTQUOTA gets testing as part of fstests. On the other hand > fstests are focused on testing the general quota functionality as user > would use it so we don't really try to make sure all quotactl calls are > covered. So there's still some value in low level testing of each > quotactl like you do here. Agree that testing quotactl as syscall in LTP makes sense (unlike testing filesystem features or performance, that was the reason why we deleted "New ext4 features" tests). Thank you for the review! Kind regards, Petr
Hi 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> > --- > include/lapi/quotactl.h | 23 ++--- > m4/ltp-quota.m4 | 36 +------- > .../kernel/syscalls/quotactl/quotactl01.c | 86 ++++++++++++------- > 3 files changed, 67 insertions(+), 78 deletions(-) > diff --git a/include/lapi/quotactl.h b/include/lapi/quotactl.h ... > #ifndef LAPI_QUOTACTL_H__ > # define LAPI_QUOTACTL_H__ > +#include <linux/quota.h> I'd prefer to add autotools check for <linux/quota.h configure.ac (I guess we ignore include/config.h.default atm). But, more important, I'd prefer to include <sys/quota.h> here as well: #ifdef HAVE_LINUX_QUOTA_H # include <linux/quota.h> #else # include <sys/quota.h> #endif => move it from quotactl0*.c (there is not yet agreement to include headers in lapi files, but later lapi files does it). The reason is that old distros fail when both headers are included at the same time (probably <linux/quota.h> got fixed later, maybe there is an workaround, but the easiest way is to handle this in header anyway). Kind regards, Petr [1] https://travis-ci.org/pevik/ltp/jobs/605507690 [2] https://api.travis-ci.org/v3/job/605507690/log.txt
on 2019/10/31 22:31, Petr Vorel wrote: > Hi 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> >> --- >> include/lapi/quotactl.h | 23 ++--- >> m4/ltp-quota.m4 | 36 +------- >> .../kernel/syscalls/quotactl/quotactl01.c | 86 ++++++++++++------- >> 3 files changed, 67 insertions(+), 78 deletions(-) >> diff --git a/include/lapi/quotactl.h b/include/lapi/quotactl.h > ... >> #ifndef LAPI_QUOTACTL_H__ >> # define LAPI_QUOTACTL_H__ >> +#include <linux/quota.h> > I'd prefer to add autotools check for <linux/quota.h configure.ac > (I guess we ignore include/config.h.default atm). > > But, more important, I'd prefer to include <sys/quota.h> here as well: > > #ifdef HAVE_LINUX_QUOTA_H > # include <linux/quota.h> > #else > # include <sys/quota.h> > #endif Hi Petr It still has problems that sys/quota.h has some struct defintion as struct dqblk ,struct dqinfo. Also, now linux/quota.h doesn't have quotactl function declaration. I think we can use HAVE_STRUCT_IF_NEXTDQBLK macro in lapi/quotactl.h to decide whether include <linux/quota.h> because I add <linux/quota.h> for finding struct if_netxdqblk defintion. ps: In my ltp fork, it passed. [1]https://travis-ci.org/xuyang0410/ltp/builds/605963472?utm_medium=notification&utm_source=github_status Thanks Yang Xu > > => move it from quotactl0*.c (there is not yet agreement to include headers in > lapi files, but later lapi files does it). > > The reason is that old distros fail when both headers are included at the same > time (probably <linux/quota.h> got fixed later, maybe there is an workaround, > but the easiest way is to handle this in header anyway). > > Kind regards, > Petr > > [1] https://travis-ci.org/pevik/ltp/jobs/605507690 > [2] https://api.travis-ci.org/v3/job/605507690/log.txt > >
diff --git a/include/lapi/quotactl.h b/include/lapi/quotactl.h index 729472f69..99f4e5fc5 100644 --- a/include/lapi/quotactl.h +++ b/include/lapi/quotactl.h @@ -1,26 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) 2017 Fujitsu Ltd. + * Copyright (c) 2016-2019 FUJITSU LIMITED. All rights reserved. * 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 <linux/quota.h> + # 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 index c5e233ca1..964c34925 100644 --- a/m4/ltp-quota.m4 +++ b/m4/ltp-quota.m4 @@ -1,39 +1,7 @@ dnl SPDX-License-Identifier: GPL-2.0-or-later dnl Copyright (c) Cisco Systems, Inc, 2008 +dnl Copyright (c) 2019 Fujitsu Ltd. AC_DEFUN([LTP_CHECK_SYSCALL_QUOTACTL],[ - AC_LINK_IFELSE([AC_LANG_SOURCE([ -#define _LINUX_QUOTA_VERSION 2 -#include <sys/types.h> -#include <sys/quota.h> -#include <unistd.h> -int main(void) { - struct dqblk dq; - return quotactl(QCMD(Q_GETINFO, USRQUOTA), (const char *) "/dev/null", - geteuid(), (caddr_t) &dq); -}])],[has_quotav2="yes"]) - -if test "x$has_quotav2" = xyes; then - AC_DEFINE(HAVE_QUOTAV2,1,[Define to 1 if you have quota v2]) -else - - # got quota v1? - AC_LINK_IFELSE([AC_LANG_SOURCE([ -#define _LINUX_QUOTA_VERSION 1 -#include <sys/types.h> -#include <sys/quota.h> -#include <unistd.h> -int main(void) { - struct dqblk dq; - return quotactl(QCMD(Q_GETQUOTA, USRQUOTA), (const char *) "/dev/null", - geteuid(), (caddr_t) &dq); -}])],[has_quotav1="yes"]) - - if test "x$has_quotav1" = xyes; then - AC_DEFINE(HAVE_QUOTAV1,1,[Define to 1 if you have quota v1]) - else - AC_MSG_WARN(Couldn't determine quota version (please submit config.log and manpage to ltp@lists.linux.it)) - fi - -fi +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 b0be525d6..af78646e4 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_GETNEXTSTAT 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_GETNEXTSTAT flag for group. +* 18) quotactl(2) succeeds to turn off quota with Q_QUOTAOFF flag for group. */ #include <errno.h> @@ -36,10 +40,9 @@ #include <unistd.h> #include <stdio.h> #include "config.h" - +#include <sys/quota.h> #include "tst_test.h" - -# include <sys/quota.h> +#include "lapi/quotactl.h" # define QFMT_VFS_V0 2 # define USRPATH MNTPOINT "/aquota.user" @@ -63,6 +66,10 @@ static struct dqinfo set_qf = { static struct dqinfo res_qf; static int32_t fmt_buf; +#if defined(HAVE_STRUCT_IF_NEXTDQBLK) +static struct if_nextdqblk res_ndq; +#endif + static struct tcase { int cmd; int *id; @@ -70,60 +77,73 @@ static struct tcase { void *set_data; void *res_data; int sz; + int nflag; char *des; } tcases[] = { {QCMD(Q_QUOTAON, USRQUOTA), &fmt_id, USRPATH, - NULL, NULL, 0, "turn on quota for user"}, + NULL, NULL, 0, 0, "turn on quota for user"}, {QCMD(Q_SETQUOTA, USRQUOTA), &test_id, &set_dq, - NULL, NULL, 0, "set disk quota limit for user"}, + NULL, NULL, 0, 0, "set disk quota limit for user"}, {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), 0, "get disk quota limit for user"}, {QCMD(Q_SETINFO, USRQUOTA), &test_id, &set_qf, - NULL, NULL, 0, "set information about quotafile for user"}, + NULL, NULL, 0, 0, "set information about quotafile for user"}, {QCMD(Q_GETINFO, USRQUOTA), &test_id, &res_qf, - &set_qf.dqi_bgrace, &res_qf.dqi_bgrace, sizeof(res_qf.dqi_bgrace), + &set_qf.dqi_bgrace, &res_qf.dqi_bgrace, sizeof(res_qf.dqi_bgrace), 0, "get information about quotafile for user"}, {QCMD(Q_GETFMT, USRQUOTA), &test_id, &fmt_buf, - &fmt_id, &fmt_buf, sizeof(fmt_buf), + &fmt_id, &fmt_buf, sizeof(fmt_buf), 0, "get quota format for user"}, {QCMD(Q_SYNC, USRQUOTA), &test_id, &res_dq, - NULL, NULL, 0, "update quota usages for user"}, + NULL, NULL, 0, 0, "update quota usages for user"}, + +#if defined(HAVE_STRUCT_IF_NEXTDQBLK) + {QCMD(Q_GETNEXTQUOTA, USRQUOTA), &test_id, &res_ndq, + &test_id, &res_ndq.dqb_id, sizeof(res_ndq.dqb_id), 1, + "get next disk quota limit for user"}, +#endif {QCMD(Q_QUOTAOFF, USRQUOTA), &test_id, USRPATH, - NULL, NULL, 0, "turn off quota for user"}, + NULL, NULL, 0, 0, "turn off quota for user"}, {QCMD(Q_QUOTAON, GRPQUOTA), &fmt_id, GRPPATH, - NULL, NULL, 0, "turn on quota for group"}, + NULL, NULL, 0, 0, "turn on quota for group"}, {QCMD(Q_SETQUOTA, GRPQUOTA), &test_id, &set_dq, - NULL, NULL, 0, "set disk quota limit for group"}, + NULL, NULL, 0, 0, "set disk quota limit for group"}, {QCMD(Q_GETQUOTA, GRPQUOTA), &test_id, &res_dq, &set_dq.dqb_bsoftlimit, - &res_dq.dqb_bsoftlimit, sizeof(res_dq.dqb_bsoftlimit), + &res_dq.dqb_bsoftlimit, sizeof(res_dq.dqb_bsoftlimit), 0, "set disk quota limit for group"}, {QCMD(Q_SETINFO, GRPQUOTA), &test_id, &set_qf, - NULL, NULL, 0, "set information about quotafile for group"}, + NULL, NULL, 0, 0, "set information about quotafile for group"}, {QCMD(Q_GETINFO, GRPQUOTA), &test_id, &res_qf, &set_qf.dqi_bgrace, - &res_qf.dqi_bgrace, sizeof(res_qf.dqi_bgrace), + &res_qf.dqi_bgrace, sizeof(res_qf.dqi_bgrace), 0, "get information about quotafile for group"}, {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), 0, "get quota format for group"}, {QCMD(Q_SYNC, GRPQUOTA), &test_id, &res_dq, - NULL, NULL, 0, "update quota usages for group"}, + NULL, NULL, 0, 0, "update quota usages for group"}, + +#if defined(HAVE_STRUCT_IF_NEXTDQBLK) + {QCMD(Q_GETNEXTQUOTA, GRPQUOTA), &test_id, &res_ndq, + &test_id, &res_ndq.dqb_id, sizeof(res_ndq.dqb_id), 1, + "get next disk quota limit for group"}, +#endif {QCMD(Q_QUOTAOFF, GRPQUOTA), &test_id, GRPPATH, - NULL, NULL, 0, "turn off quota for group"} + NULL, NULL, 0, 0, "turn off quota for group"} }; static void setup(void) @@ -156,9 +176,15 @@ static void verify_quota(unsigned int n) res_dq.dqb_bsoftlimit = 0; res_qf.dqi_igrace = 0; +#if defined(HAVE_STRUCT_IF_NEXTDQBLK) + res_ndq.dqb_id = -1; +#endif fmt_buf = 0; - TEST(quotactl(tc->cmd, tst_device->dev, *tc->id, tc->addr)); + if (TST_ERR == ENOSYS && tc->nflag) { + tst_res(TCONF, "Current system doesn't support Q_GETNEXTQUOTA, it needs kernel>=4.6!"); + return; + } if (TST_RET == -1) { tst_res(TFAIL | TTERRNO, "quotactl failed to %s", tc->des); return;
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> --- include/lapi/quotactl.h | 23 ++--- m4/ltp-quota.m4 | 36 +------- .../kernel/syscalls/quotactl/quotactl01.c | 86 ++++++++++++------- 3 files changed, 67 insertions(+), 78 deletions(-)