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