• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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