1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) Crackerjack Project., 2007
4*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2016-2021 FUJITSU LIMITED. All rights reserved
5*49cdfc7eSAndroid Build Coastguard Worker * Author: Xiao Yang <[email protected]>
6*49cdfc7eSAndroid Build Coastguard Worker * Author: Yang Xu <[email protected]>
7*49cdfc7eSAndroid Build Coastguard Worker */
8*49cdfc7eSAndroid Build Coastguard Worker
9*49cdfc7eSAndroid Build Coastguard Worker /*\
10*49cdfc7eSAndroid Build Coastguard Worker * [Description]
11*49cdfc7eSAndroid Build Coastguard Worker * This testcases checks that quotactl(2) on ext4 filesystem succeeds to:
12*49cdfc7eSAndroid Build Coastguard Worker *
13*49cdfc7eSAndroid Build Coastguard Worker * - turn on quota with Q_QUOTAON flag for user
14*49cdfc7eSAndroid Build Coastguard Worker * - set disk quota limits with Q_SETQUOTA flag for user
15*49cdfc7eSAndroid Build Coastguard Worker * - get disk quota limits with Q_GETQUOTA flag for user
16*49cdfc7eSAndroid Build Coastguard Worker * - set information about quotafile with Q_SETINFO flag for user
17*49cdfc7eSAndroid Build Coastguard Worker * - get information about quotafile with Q_GETINFO flag for user
18*49cdfc7eSAndroid Build Coastguard Worker * - get quota format with Q_GETFMT flag for user
19*49cdfc7eSAndroid Build Coastguard Worker * - update quota usages with Q_SYNC flag for user
20*49cdfc7eSAndroid Build Coastguard Worker * - get disk quota limit greater than or equal to ID with Q_GETNEXTQUOTA flag for user
21*49cdfc7eSAndroid Build Coastguard Worker * - turn off quota with Q_QUOTAOFF flag for user
22*49cdfc7eSAndroid Build Coastguard Worker * - turn on quota with Q_QUOTAON flag for group
23*49cdfc7eSAndroid Build Coastguard Worker * - set disk quota limits with Q_SETQUOTA flag for group
24*49cdfc7eSAndroid Build Coastguard Worker * - get disk quota limits with Q_GETQUOTA flag for group
25*49cdfc7eSAndroid Build Coastguard Worker * - set information about quotafile with Q_SETINFO flag for group
26*49cdfc7eSAndroid Build Coastguard Worker * - get information about quotafile with Q_GETINFO flag for group
27*49cdfc7eSAndroid Build Coastguard Worker * - get quota format with Q_GETFMT flag for group
28*49cdfc7eSAndroid Build Coastguard Worker * - update quota usages with Q_SYNC flag for group
29*49cdfc7eSAndroid Build Coastguard Worker * - get disk quota limit greater than or equal to ID with Q_GETNEXTQUOTA flag for group
30*49cdfc7eSAndroid Build Coastguard Worker * - turn off quota with Q_QUOTAOFF flag for group
31*49cdfc7eSAndroid Build Coastguard Worker */
32*49cdfc7eSAndroid Build Coastguard Worker
33*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
34*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
35*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
36*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
37*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
38*49cdfc7eSAndroid Build Coastguard Worker #include "quotactl_fmt_var.h"
39*49cdfc7eSAndroid Build Coastguard Worker
40*49cdfc7eSAndroid Build Coastguard Worker #define USRPATH MNTPOINT "/aquota.user"
41*49cdfc7eSAndroid Build Coastguard Worker #define GRPPATH MNTPOINT "/aquota.group"
42*49cdfc7eSAndroid Build Coastguard Worker #define MNTPOINT "mntpoint"
43*49cdfc7eSAndroid Build Coastguard Worker
44*49cdfc7eSAndroid Build Coastguard Worker static int32_t fmt_id;
45*49cdfc7eSAndroid Build Coastguard Worker static int test_id;
46*49cdfc7eSAndroid Build Coastguard Worker static char usrpath[] = USRPATH;
47*49cdfc7eSAndroid Build Coastguard Worker static char grppath[] = GRPPATH;
48*49cdfc7eSAndroid Build Coastguard Worker static struct dqblk set_dq = {
49*49cdfc7eSAndroid Build Coastguard Worker .dqb_bsoftlimit = 100,
50*49cdfc7eSAndroid Build Coastguard Worker .dqb_valid = QIF_BLIMITS
51*49cdfc7eSAndroid Build Coastguard Worker };
52*49cdfc7eSAndroid Build Coastguard Worker static struct dqblk res_dq;
53*49cdfc7eSAndroid Build Coastguard Worker
54*49cdfc7eSAndroid Build Coastguard Worker static struct dqinfo set_qf = {
55*49cdfc7eSAndroid Build Coastguard Worker .dqi_bgrace = 80,
56*49cdfc7eSAndroid Build Coastguard Worker .dqi_valid = IIF_BGRACE
57*49cdfc7eSAndroid Build Coastguard Worker };
58*49cdfc7eSAndroid Build Coastguard Worker static struct dqinfo res_qf;
59*49cdfc7eSAndroid Build Coastguard Worker static int32_t fmt_buf;
60*49cdfc7eSAndroid Build Coastguard Worker static int getnextquota_nsup;
61*49cdfc7eSAndroid Build Coastguard Worker
62*49cdfc7eSAndroid Build Coastguard Worker static struct if_nextdqblk res_ndq;
63*49cdfc7eSAndroid Build Coastguard Worker
64*49cdfc7eSAndroid Build Coastguard Worker static struct tcase {
65*49cdfc7eSAndroid Build Coastguard Worker int cmd;
66*49cdfc7eSAndroid Build Coastguard Worker int *id;
67*49cdfc7eSAndroid Build Coastguard Worker void *addr;
68*49cdfc7eSAndroid Build Coastguard Worker void *set_data;
69*49cdfc7eSAndroid Build Coastguard Worker void *res_data;
70*49cdfc7eSAndroid Build Coastguard Worker int sz;
71*49cdfc7eSAndroid Build Coastguard Worker char *des;
72*49cdfc7eSAndroid Build Coastguard Worker char *tname;
73*49cdfc7eSAndroid Build Coastguard Worker } tcases[] = {
74*49cdfc7eSAndroid Build Coastguard Worker {QCMD(Q_QUOTAON, USRQUOTA), &fmt_id, usrpath,
75*49cdfc7eSAndroid Build Coastguard Worker NULL, NULL, 0, "turn on quota for user",
76*49cdfc7eSAndroid Build Coastguard Worker "QCMD(Q_QUOTAON, USRQUOTA)"},
77*49cdfc7eSAndroid Build Coastguard Worker
78*49cdfc7eSAndroid Build Coastguard Worker {QCMD(Q_SETQUOTA, USRQUOTA), &test_id, &set_dq,
79*49cdfc7eSAndroid Build Coastguard Worker NULL, NULL, 0, "set disk quota limit for user",
80*49cdfc7eSAndroid Build Coastguard Worker "QCMD(Q_SETQUOTA, USRQUOTA)"},
81*49cdfc7eSAndroid Build Coastguard Worker
82*49cdfc7eSAndroid Build Coastguard Worker {QCMD(Q_GETQUOTA, USRQUOTA), &test_id, &res_dq,
83*49cdfc7eSAndroid Build Coastguard Worker &set_dq.dqb_bsoftlimit, &res_dq.dqb_bsoftlimit,
84*49cdfc7eSAndroid Build Coastguard Worker sizeof(res_dq.dqb_bsoftlimit), "get disk quota limit for user",
85*49cdfc7eSAndroid Build Coastguard Worker "QCMD(Q_GETQUOTA, USRQUOTA)"},
86*49cdfc7eSAndroid Build Coastguard Worker
87*49cdfc7eSAndroid Build Coastguard Worker {QCMD(Q_SETINFO, USRQUOTA), &test_id, &set_qf,
88*49cdfc7eSAndroid Build Coastguard Worker NULL, NULL, 0, "set information about quotafile for user",
89*49cdfc7eSAndroid Build Coastguard Worker "QCMD(Q_SETINFO, USRQUOTA)"},
90*49cdfc7eSAndroid Build Coastguard Worker
91*49cdfc7eSAndroid Build Coastguard Worker {QCMD(Q_GETINFO, USRQUOTA), &test_id, &res_qf,
92*49cdfc7eSAndroid Build Coastguard Worker &set_qf.dqi_bgrace, &res_qf.dqi_bgrace, sizeof(res_qf.dqi_bgrace),
93*49cdfc7eSAndroid Build Coastguard Worker "get information about quotafile for user",
94*49cdfc7eSAndroid Build Coastguard Worker "QCMD(Q_GETINFO, USRQUOTA)"},
95*49cdfc7eSAndroid Build Coastguard Worker
96*49cdfc7eSAndroid Build Coastguard Worker {QCMD(Q_GETFMT, USRQUOTA), &test_id, &fmt_buf,
97*49cdfc7eSAndroid Build Coastguard Worker &fmt_id, &fmt_buf, sizeof(fmt_buf),
98*49cdfc7eSAndroid Build Coastguard Worker "get quota format for user",
99*49cdfc7eSAndroid Build Coastguard Worker "QCMD(Q_GETFMT, USRQUOTA)"},
100*49cdfc7eSAndroid Build Coastguard Worker
101*49cdfc7eSAndroid Build Coastguard Worker {QCMD(Q_SYNC, USRQUOTA), &test_id, &res_dq,
102*49cdfc7eSAndroid Build Coastguard Worker NULL, NULL, 0, "update quota usages for user",
103*49cdfc7eSAndroid Build Coastguard Worker "QCMD(Q_SYNC, USRQUOTA)"},
104*49cdfc7eSAndroid Build Coastguard Worker
105*49cdfc7eSAndroid Build Coastguard Worker {QCMD(Q_GETNEXTQUOTA, USRQUOTA), &test_id, &res_ndq,
106*49cdfc7eSAndroid Build Coastguard Worker &test_id, &res_ndq.dqb_id, sizeof(res_ndq.dqb_id),
107*49cdfc7eSAndroid Build Coastguard Worker "get next disk quota limit for user",
108*49cdfc7eSAndroid Build Coastguard Worker "QCMD(Q_GETNEXTQUOTA, USRQUOTA)"},
109*49cdfc7eSAndroid Build Coastguard Worker
110*49cdfc7eSAndroid Build Coastguard Worker {QCMD(Q_QUOTAOFF, USRQUOTA), &test_id, usrpath,
111*49cdfc7eSAndroid Build Coastguard Worker NULL, NULL, 0, "turn off quota for user",
112*49cdfc7eSAndroid Build Coastguard Worker "QCMD(Q_QUOTAOFF, USRQUOTA)"},
113*49cdfc7eSAndroid Build Coastguard Worker
114*49cdfc7eSAndroid Build Coastguard Worker {QCMD(Q_QUOTAON, GRPQUOTA), &fmt_id, grppath,
115*49cdfc7eSAndroid Build Coastguard Worker NULL, NULL, 0, "turn on quota for group",
116*49cdfc7eSAndroid Build Coastguard Worker "QCMD(Q_QUOTAON, GRPQUOTA)"},
117*49cdfc7eSAndroid Build Coastguard Worker
118*49cdfc7eSAndroid Build Coastguard Worker {QCMD(Q_SETQUOTA, GRPQUOTA), &test_id, &set_dq,
119*49cdfc7eSAndroid Build Coastguard Worker NULL, NULL, 0, "set disk quota limit for group",
120*49cdfc7eSAndroid Build Coastguard Worker "QCMD(Q_SETQUOTA, GRPQUOTA)"},
121*49cdfc7eSAndroid Build Coastguard Worker
122*49cdfc7eSAndroid Build Coastguard Worker {QCMD(Q_GETQUOTA, GRPQUOTA), &test_id, &res_dq, &set_dq.dqb_bsoftlimit,
123*49cdfc7eSAndroid Build Coastguard Worker &res_dq.dqb_bsoftlimit, sizeof(res_dq.dqb_bsoftlimit),
124*49cdfc7eSAndroid Build Coastguard Worker "set disk quota limit for group",
125*49cdfc7eSAndroid Build Coastguard Worker "QCMD(Q_GETQUOTA, GRPQUOTA)"},
126*49cdfc7eSAndroid Build Coastguard Worker
127*49cdfc7eSAndroid Build Coastguard Worker {QCMD(Q_SETINFO, GRPQUOTA), &test_id, &set_qf,
128*49cdfc7eSAndroid Build Coastguard Worker NULL, NULL, 0, "set information about quotafile for group",
129*49cdfc7eSAndroid Build Coastguard Worker "QCMD(Q_SETINFO, GRPQUOTA)"},
130*49cdfc7eSAndroid Build Coastguard Worker
131*49cdfc7eSAndroid Build Coastguard Worker {QCMD(Q_GETINFO, GRPQUOTA), &test_id, &res_qf, &set_qf.dqi_bgrace,
132*49cdfc7eSAndroid Build Coastguard Worker &res_qf.dqi_bgrace, sizeof(res_qf.dqi_bgrace),
133*49cdfc7eSAndroid Build Coastguard Worker "get information about quotafile for group",
134*49cdfc7eSAndroid Build Coastguard Worker "QCMD(Q_GETINFO, GRPQUOTA)"},
135*49cdfc7eSAndroid Build Coastguard Worker
136*49cdfc7eSAndroid Build Coastguard Worker {QCMD(Q_GETFMT, GRPQUOTA), &test_id, &fmt_buf,
137*49cdfc7eSAndroid Build Coastguard Worker &fmt_id, &fmt_buf, sizeof(fmt_buf), "get quota format for group",
138*49cdfc7eSAndroid Build Coastguard Worker "QCMD(Q_GETFMT, GRPQUOTA)"},
139*49cdfc7eSAndroid Build Coastguard Worker
140*49cdfc7eSAndroid Build Coastguard Worker {QCMD(Q_SYNC, GRPQUOTA), &test_id, &res_dq,
141*49cdfc7eSAndroid Build Coastguard Worker NULL, NULL, 0, "update quota usages for group",
142*49cdfc7eSAndroid Build Coastguard Worker "QCMD(Q_SYNC, GRPQUOTA)"},
143*49cdfc7eSAndroid Build Coastguard Worker
144*49cdfc7eSAndroid Build Coastguard Worker {QCMD(Q_GETNEXTQUOTA, GRPQUOTA), &test_id, &res_ndq,
145*49cdfc7eSAndroid Build Coastguard Worker &test_id, &res_ndq.dqb_id, sizeof(res_ndq.dqb_id),
146*49cdfc7eSAndroid Build Coastguard Worker "get next disk quota limit for group",
147*49cdfc7eSAndroid Build Coastguard Worker "QCMD(Q_GETNEXTQUOTA, GRPQUOTA)"},
148*49cdfc7eSAndroid Build Coastguard Worker
149*49cdfc7eSAndroid Build Coastguard Worker {QCMD(Q_QUOTAOFF, GRPQUOTA), &test_id, grppath,
150*49cdfc7eSAndroid Build Coastguard Worker NULL, NULL, 0, "turn off quota for group",
151*49cdfc7eSAndroid Build Coastguard Worker "QCMD(Q_QUOTAOFF, GRPQUOTA)"},
152*49cdfc7eSAndroid Build Coastguard Worker };
153*49cdfc7eSAndroid Build Coastguard Worker
setup(void)154*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
155*49cdfc7eSAndroid Build Coastguard Worker {
156*49cdfc7eSAndroid Build Coastguard Worker const struct quotactl_fmt_variant *var = &fmt_variants[tst_variant];
157*49cdfc7eSAndroid Build Coastguard Worker const char *const cmd[] = {"quotacheck", "-ugF", var->fmt_name, MNTPOINT, NULL};
158*49cdfc7eSAndroid Build Coastguard Worker
159*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "quotactl() with %s format", var->fmt_name);
160*49cdfc7eSAndroid Build Coastguard Worker SAFE_CMD(cmd, NULL, NULL);
161*49cdfc7eSAndroid Build Coastguard Worker fmt_id = var->fmt_id;
162*49cdfc7eSAndroid Build Coastguard Worker
163*49cdfc7eSAndroid Build Coastguard Worker SAFE_ACCESS(USRPATH, F_OK);
164*49cdfc7eSAndroid Build Coastguard Worker
165*49cdfc7eSAndroid Build Coastguard Worker SAFE_ACCESS(GRPPATH, F_OK);
166*49cdfc7eSAndroid Build Coastguard Worker
167*49cdfc7eSAndroid Build Coastguard Worker TEST(quotactl(QCMD(Q_GETNEXTQUOTA, USRQUOTA), tst_device->dev,
168*49cdfc7eSAndroid Build Coastguard Worker test_id, (void *) &res_ndq));
169*49cdfc7eSAndroid Build Coastguard Worker if (TST_ERR == EINVAL || TST_ERR == ENOSYS)
170*49cdfc7eSAndroid Build Coastguard Worker getnextquota_nsup = 1;
171*49cdfc7eSAndroid Build Coastguard Worker }
172*49cdfc7eSAndroid Build Coastguard Worker
cleanup(void)173*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
174*49cdfc7eSAndroid Build Coastguard Worker {
175*49cdfc7eSAndroid Build Coastguard Worker SAFE_UNLINK(USRPATH);
176*49cdfc7eSAndroid Build Coastguard Worker SAFE_UNLINK(GRPPATH);
177*49cdfc7eSAndroid Build Coastguard Worker }
178*49cdfc7eSAndroid Build Coastguard Worker
verify_quota(unsigned int n)179*49cdfc7eSAndroid Build Coastguard Worker static void verify_quota(unsigned int n)
180*49cdfc7eSAndroid Build Coastguard Worker {
181*49cdfc7eSAndroid Build Coastguard Worker struct tcase *tc = &tcases[n];
182*49cdfc7eSAndroid Build Coastguard Worker
183*49cdfc7eSAndroid Build Coastguard Worker res_dq.dqb_bsoftlimit = 0;
184*49cdfc7eSAndroid Build Coastguard Worker res_qf.dqi_igrace = 0;
185*49cdfc7eSAndroid Build Coastguard Worker fmt_buf = 0;
186*49cdfc7eSAndroid Build Coastguard Worker res_ndq.dqb_id = -1;
187*49cdfc7eSAndroid Build Coastguard Worker
188*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "Test #%d: %s", n, tc->tname);
189*49cdfc7eSAndroid Build Coastguard Worker if ((tc->cmd == QCMD(Q_GETNEXTQUOTA, USRQUOTA) ||
190*49cdfc7eSAndroid Build Coastguard Worker tc->cmd == QCMD(Q_GETNEXTQUOTA, GRPQUOTA)) &&
191*49cdfc7eSAndroid Build Coastguard Worker getnextquota_nsup) {
192*49cdfc7eSAndroid Build Coastguard Worker tst_res(TCONF, "current system doesn't support this cmd");
193*49cdfc7eSAndroid Build Coastguard Worker return;
194*49cdfc7eSAndroid Build Coastguard Worker }
195*49cdfc7eSAndroid Build Coastguard Worker TST_EXP_PASS_SILENT(quotactl(tc->cmd, tst_device->dev, *tc->id, tc->addr),
196*49cdfc7eSAndroid Build Coastguard Worker "quotactl to %s", tc->des);
197*49cdfc7eSAndroid Build Coastguard Worker if (!TST_PASS)
198*49cdfc7eSAndroid Build Coastguard Worker return;
199*49cdfc7eSAndroid Build Coastguard Worker
200*49cdfc7eSAndroid Build Coastguard Worker if (memcmp(tc->res_data, tc->set_data, tc->sz)) {
201*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "quotactl failed to %s", tc->des);
202*49cdfc7eSAndroid Build Coastguard Worker tst_res_hexd(TINFO, tc->res_data, tc->sz, "retval: ");
203*49cdfc7eSAndroid Build Coastguard Worker tst_res_hexd(TINFO, tc->set_data, tc->sz, "expected: ");
204*49cdfc7eSAndroid Build Coastguard Worker return;
205*49cdfc7eSAndroid Build Coastguard Worker }
206*49cdfc7eSAndroid Build Coastguard Worker
207*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "quotactl succeeded to %s", tc->des);
208*49cdfc7eSAndroid Build Coastguard Worker }
209*49cdfc7eSAndroid Build Coastguard Worker
210*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
211*49cdfc7eSAndroid Build Coastguard Worker .needs_root = 1,
212*49cdfc7eSAndroid Build Coastguard Worker .needs_drivers = (const char *const []) {
213*49cdfc7eSAndroid Build Coastguard Worker "quota_v2",
214*49cdfc7eSAndroid Build Coastguard Worker NULL
215*49cdfc7eSAndroid Build Coastguard Worker },
216*49cdfc7eSAndroid Build Coastguard Worker .test = verify_quota,
217*49cdfc7eSAndroid Build Coastguard Worker .tcnt = ARRAY_SIZE(tcases),
218*49cdfc7eSAndroid Build Coastguard Worker .mount_device = 1,
219*49cdfc7eSAndroid Build Coastguard Worker .dev_fs_type = "ext4",
220*49cdfc7eSAndroid Build Coastguard Worker .mntpoint = MNTPOINT,
221*49cdfc7eSAndroid Build Coastguard Worker .mnt_data = "usrquota,grpquota",
222*49cdfc7eSAndroid Build Coastguard Worker .needs_cmds = (const char *const []) {
223*49cdfc7eSAndroid Build Coastguard Worker "quotacheck",
224*49cdfc7eSAndroid Build Coastguard Worker NULL
225*49cdfc7eSAndroid Build Coastguard Worker },
226*49cdfc7eSAndroid Build Coastguard Worker .setup = setup,
227*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup,
228*49cdfc7eSAndroid Build Coastguard Worker .test_variants = QUOTACTL_FMT_VARIANTS,
229*49cdfc7eSAndroid Build Coastguard Worker };
230