1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2013-2019 FUJITSU LIMITED. All rights reserved
4 * Author: DAN LI <li.dan@cn.fujitsu.com>
5 * Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
6 *
7 * This testcase checks basic flags of quotactl(2) for an XFS file system:
8 * 1) quotactl(2) succeeds to turn off xfs quota and get xfs quota off status
9 * for user.
10 * 2) quotactl(2) succeeds to turn on xfs quota and get xfs quota on status
11 * for usr.
12 * 3) quotactl(2) succeeds to set and use Q_XGETQUOTA to get xfs disk quota
13 * limits for user.
14 * 4) quotactl(2) succeeds to set and use Q_XGETNEXTQUOTA to get xfs disk
15 * quota limits greater than or equal to ID for user.
16 * 5) quotactl(2) succeeds to turn off xfs quota and get xfs quota off statv
17 * for user.
18 * 6) quotactl(2) succeeds to turn on xfs quota and get xfs quota on statv
19 * for user.
20 * 7) quotactl(2) succeeds to turn off xfs quota and get xfs quota off status
21 * for group.
22 * 8) quotactl(2) succeeds to turn on xfs quota and get xfs quota on status
23 * for group.
24 * 9) quotactl(2) succeeds to set and use Q_XGETQUOTA to get xfs disk quota
25 * limits for group.
26 * 10)quotactl(2) succeeds to set and use Q_XGETNEXTQUOTA to get xfs disk
27 * quota limits for group.
28 * 11)quotactl(2) succeeds to turn off xfs quota and get xfs quota off statv
29 * for group.
30 * 12)quotactl(2) succeeds to turn on xfs quota and get xfs quota on statv
31 * for group.
32 */
33
34 #include "quotactl02.h"
35
36 #ifdef HAVE_XFS_XQM_H
37 static uint32_t qflagu = XFS_QUOTA_UDQ_ENFD;
38 static uint32_t qflagg = XFS_QUOTA_GDQ_ENFD;
39
40 static struct t_case {
41 int cmd;
42 void *addr;
43 void (*func_check)();
44 int check_subcmd;
45 int flag;
46 char *des;
47 char *tname;
48 } tcases[] = {
49 {QCMD(Q_XQUOTAOFF, USRQUOTA), &qflagu, check_qoff,
50 QCMD(Q_XGETQSTAT, USRQUOTA), 1,
51 "turn off xfs quota and get xfs quota off status for user",
52 "QCMD(Q_XGETQSTAT, USRQUOTA) off"},
53
54 {QCMD(Q_XQUOTAON, USRQUOTA), &qflagu, check_qon,
55 QCMD(Q_XGETQSTAT, USRQUOTA), 1,
56 "turn on xfs quota and get xfs quota on status for user",
57 "QCMD(Q_XGETQSTAT, USRQUOTA) on"},
58
59 {QCMD(Q_XSETQLIM, USRQUOTA), &set_dquota, check_qlim,
60 QCMD(Q_XGETQUOTA, USRQUOTA), 0, "Q_XGETQUOTA for user",
61 "QCMD(Q_XGETQUOTA, USRQUOTA) qlim"},
62
63 {QCMD(Q_XSETQLIM, USRQUOTA), &set_dquota, check_qlim,
64 QCMD(Q_XGETNEXTQUOTA, USRQUOTA), 0, "Q_XGETNEXTQUOTA for user",
65 "QCMD(Q_XGETNEXTQUOTA, USRQUOTA)"},
66
67 {QCMD(Q_XQUOTAOFF, USRQUOTA), &qflagu, check_qoffv,
68 QCMD(Q_XGETQSTATV, USRQUOTA), 1,
69 "turn off xfs quota and get xfs quota off statv for user",
70 "QCMD(Q_XGETQSTATV, USRQUOTA) off"},
71
72 {QCMD(Q_XQUOTAON, USRQUOTA), &qflagu, check_qonv,
73 QCMD(Q_XGETQSTATV, USRQUOTA), 1,
74 "turn on xfs quota and get xfs quota on statv for user",
75 "QCMD(Q_XGETQSTATV, USRQUOTA) on"},
76
77 {QCMD(Q_XQUOTAOFF, GRPQUOTA), &qflagg, check_qoff,
78 QCMD(Q_XGETQSTAT, GRPQUOTA), 1,
79 "turn off xfs quota and get xfs quota off status for group",
80 "QCMD(Q_XGETQSTAT, GRPQUOTA) off"},
81
82 {QCMD(Q_XQUOTAON, GRPQUOTA), &qflagg, check_qon,
83 QCMD(Q_XGETQSTAT, GRPQUOTA), 1,
84 "turn on xfs quota and get xfs quota on status for group",
85 "QCMD(Q_XGETQSTAT, GRPQUOTA) on"},
86
87 {QCMD(Q_XSETQLIM, GRPQUOTA), &set_dquota, check_qlim,
88 QCMD(Q_XGETQUOTA, GRPQUOTA), 0, "Q_XGETQUOTA for group",
89 "QCMD(Q_XGETQUOTA, GRPQUOTA) qlim"},
90
91 {QCMD(Q_XSETQLIM, GRPQUOTA), &set_dquota, check_qlim,
92 QCMD(Q_XGETNEXTQUOTA, GRPQUOTA), 0, "Q_XGETNEXTQUOTA for group",
93 "QCMD(Q_XGETNEXTQUOTA, GRPQUOTA)"},
94
95 {QCMD(Q_XQUOTAOFF, GRPQUOTA), &qflagg, check_qoffv,
96 QCMD(Q_XGETQSTATV, GRPQUOTA), 1,
97 "turn off xfs quota and get xfs quota off statv for group",
98 "QCMD(Q_XGETQSTATV, GRPQUOTA) off"},
99
100 {QCMD(Q_XQUOTAON, GRPQUOTA), &qflagg, check_qonv,
101 QCMD(Q_XGETQSTATV, GRPQUOTA), 1,
102 "turn on xfs quota and get xfs quota on statv for group",
103 "QCMD(Q_XGETQSTATV, GRPQUOTA) on"},
104 };
105
setup(void)106 static void setup(void)
107 {
108 test_id = geteuid();
109 check_support_cmd(USRQUOTA);
110 check_support_cmd(GRPQUOTA);
111 }
112
verify_quota(unsigned int n)113 static void verify_quota(unsigned int n)
114 {
115 struct t_case *tc = &tcases[n];
116
117 tst_res(TINFO, "Test #%d: %s", n, tc->tname);
118 if ((tc->check_subcmd == QCMD(Q_XGETNEXTQUOTA, USRQUOTA)
119 || tc->check_subcmd == QCMD(Q_XGETNEXTQUOTA, GRPQUOTA))
120 && x_getnextquota_nsup) {
121 tst_res(TCONF, "current system doesn't support this cmd");
122 return;
123 }
124 if ((tc->check_subcmd == QCMD(Q_XGETQSTATV, USRQUOTA)
125 || tc->check_subcmd == QCMD(Q_XGETQSTATV, GRPQUOTA))
126 && x_getstatv_nsup) {
127 tst_res(TCONF, "current system doesn't support this cmd");
128 return;
129 }
130
131 TEST(quotactl(tc->cmd, tst_device->dev, test_id, tc->addr));
132 if (TST_RET == -1) {
133 tst_res(TFAIL | TTERRNO, "quotactl() failed to %s", tc->des);
134 return;
135 }
136
137 if (tc->flag)
138 tc->func_check(tc->check_subcmd, tc->des, *(int *)(tc->addr));
139 else
140 tc->func_check(tc->check_subcmd, tc->des);
141 }
142
143 static struct tst_test test = {
144 .needs_root = 1,
145 .needs_kconfigs = kconfigs,
146 .test = verify_quota,
147 .tcnt = ARRAY_SIZE(tcases),
148 .mount_device = 1,
149 .dev_fs_type = "xfs",
150 .mntpoint = mntpoint,
151 .mnt_data = "usrquota,grpquota",
152 .setup = setup,
153 };
154 #else
155 TST_TEST_TCONF("System doesn't have <xfs/xqm.h>");
156 #endif
157