1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2019 FUJITSU LIMITED. All rights reserved.
4 * Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
5 *
6 * This testcase checks basic flags of quotactl(2) for project on an XFS file
7 * system:
8 * 1) quotactl(2) succeeds to turn off xfs quota and get xfs quota off status
9 * for project.
10 * 2) quotactl(2) succeeds to turn on xfs quota and get xfs quota on status
11 * for project.
12 * 3) quotactl(2) succeeds to set and use Q_XGETQUOTA to get xfs disk quota
13 * limits for project.
14 * 4) quotactl(2) succeeds to set and use Q_XGETNEXTQUOTA to get xfs disk
15 * quota limits Cgreater than or equal to ID for project.
16 * 5) quotactl(2) succeeds to turn off xfs quota and get xfs quota off statv
17 * for project.
18 * 6) quotactl(2) succeeds to turn on xfs quota and get xfs quota on statv
19 * for project.
20 */
21 #include "quotactl02.h"
22 #if defined(HAVE_XFS_XQM_H)
23
24 static uint32_t qflagp = XFS_QUOTA_PDQ_ENFD;
25 static struct t_case {
26 int cmd;
27 void *addr;
28 void (*func_check)();
29 int check_subcmd;
30 int flag;
31 char *des;
32 char *tname;
33 } tcases[] = {
34 {QCMD(Q_XQUOTAOFF, PRJQUOTA), &qflagp, check_qoff,
35 QCMD(Q_XGETQSTAT, PRJQUOTA), 1,
36 "turn off xfs quota and get xfs quota off status for project",
37 "QCMD(Q_XGETQSTAT, PRJQUOTA) off"},
38
39 {QCMD(Q_XQUOTAON, PRJQUOTA), &qflagp, check_qon,
40 QCMD(Q_XGETQSTAT, PRJQUOTA), 1,
41 "turn on xfs quota and get xfs quota on status for project",
42 "QCMD(Q_XGETQSTAT, PRJQUOTA) on"},
43
44 {QCMD(Q_XSETQLIM, PRJQUOTA), &set_dquota, check_qlim,
45 QCMD(Q_XGETQUOTA, PRJQUOTA), 0,
46 "Q_XGETQUOTA for project", "QCMD(Q_XGETQUOTA, PRJQUOTA) qlim"},
47
48 {QCMD(Q_XSETQLIM, PRJQUOTA), &set_dquota, check_qlim,
49 QCMD(Q_XGETNEXTQUOTA, PRJQUOTA), 0,
50 "Q_XGETNEXTQUOTA for project", "QCMD(Q_XGETNEXTQUOTA, PRJQUOTA)"},
51
52 {QCMD(Q_XQUOTAOFF, PRJQUOTA), &qflagp, check_qoffv,
53 QCMD(Q_XGETQSTATV, PRJQUOTA), 1,
54 "turn off xfs quota and get xfs quota off statv for project",
55 "QCMD(Q_XGETQSTATV, PRJQUOTA) off"},
56
57 {QCMD(Q_XQUOTAON, PRJQUOTA), &qflagp, check_qonv,
58 QCMD(Q_XGETQSTATV, PRJQUOTA), 1,
59 "turn on xfs quota and get xfs quota on statv for project",
60 "QCMD(Q_XGETQSTATV, PRJQUOTA) on"},
61 };
62
setup(void)63 static void setup(void)
64 {
65 test_id = geteuid();
66 check_support_cmd(PRJQUOTA);
67 }
68
verify_quota(unsigned int n)69 static void verify_quota(unsigned int n)
70 {
71 struct t_case *tc = &tcases[n];
72
73 tst_res(TINFO, "Test #%d: %s", n, tc->tname);
74
75 if ((tc->check_subcmd == QCMD(Q_XGETNEXTQUOTA, PRJQUOTA))
76 && x_getnextquota_nsup) {
77 tst_res(TCONF,
78 "current system doesn't support this cmd");
79 return;
80 }
81 if ((tc->check_subcmd == QCMD(Q_XGETQSTATV, PRJQUOTA))
82 && x_getstatv_nsup) {
83 tst_res(TCONF,
84 "current system doesn't support this cmd");
85 return;
86 }
87
88 TEST(quotactl(tc->cmd, tst_device->dev, test_id, tc->addr));
89 if (TST_RET == -1) {
90 tst_res(TFAIL | TTERRNO, "quotactl() failed to %s", tc->des);
91 return;
92 }
93
94 if (tc->flag)
95 tc->func_check(tc->check_subcmd, tc->des, *(int *)(tc->addr));
96 else
97 tc->func_check(tc->check_subcmd, tc->des);
98 }
99
100 static struct tst_test test = {
101 .needs_root = 1,
102 .needs_kconfigs = kconfigs,
103 .test = verify_quota,
104 .tcnt = ARRAY_SIZE(tcases),
105 .mount_device = 1,
106 .dev_fs_type = "xfs",
107 .mntpoint = mntpoint,
108 .mnt_data = "prjquota",
109 .setup = setup,
110 };
111
112 #else
113 TST_TEST_TCONF("This system didn't have <xfs/xqm.h>");
114 #endif
115