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