blob: 18aecac7c18271900b6447ff8cfe945ee3a7c252 [file] [log] [blame]
DAN LIe11382a2013-09-03 10:17:09 +08001/*
2 * Copyright (c) 2013 Fujitsu Ltd.
3 * Author: DAN LI <li.dan@cn.fujitsu.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18/*
19 * Description:
20 * This tests basic flags of quotactl() syscall:
21 * 1) Q_XQUOTAOFF - Turn off quotas for an XFS file system.
22 * 2) Q_XQUOTAON - Turn on quotas for an XFS file system.
23 * 3) Q_XGETQUOTA - Get disk quota limits and current usage for user id.
24 * 4) Q_XSETQLIM - Set disk quota limits for user id.
25 * 5) Q_XGETQSTAT - Get XFS file system specific quota information.
26 */
27
28#define _GNU_SOURCE
29#include <fcntl.h>
30#include <unistd.h>
31#include <sys/syscall.h>
32#include <stdio.h>
33#include <errno.h>
34#include <sys/mount.h>
35#include <linux/fs.h>
36#include <sys/types.h>
37
38#include "config.h"
39#if defined(HAVE_XFS_QUOTA)
Cyril Hrubis47a114d2014-08-14 13:21:36 +020040# include <xfs/xqm.h>
DAN LIe11382a2013-09-03 10:17:09 +080041#endif
42#include "test.h"
DAN LIe11382a2013-09-03 10:17:09 +080043#include "linux_syscall_numbers.h"
44#include "safe_macros.h"
45
46#define USRQCMD(cmd) ((cmd) << 8)
47#define RTBLIMIT 2000
48
49char *TCID = "quotactl02";
50int TST_TOTAL = 5;
51
52#if defined(HAVE_XFS_QUOTA)
53static void check_qoff(void);
54static void check_qon(void);
55static void check_getq(void);
56static void setup_setqlim(void), check_setqlim(void);
57static void check_getqstat(void);
58
59static void setup(void);
60static void cleanup(void);
DAN LIe11382a2013-09-03 10:17:09 +080061
62static int i;
63static int uid;
Cyril Hrubis47a114d2014-08-14 13:21:36 +020064static const char *block_dev;
65static int mount_flag;
DAN LIe11382a2013-09-03 10:17:09 +080066static struct fs_disk_quota dquota;
67static struct fs_quota_stat qstat;
68static unsigned int qflag = XFS_QUOTA_UDQ_ENFD;
69static const char mntpoint[] = "mnt_point";
70
DAN LIe11382a2013-09-03 10:17:09 +080071static struct test_case_t {
72 int cmd;
73 void *addr;
74 void (*func_test) ();
75 void (*func_setup) ();
76} TC[] = {
77 {Q_XQUOTAOFF, &qflag, check_qoff, NULL},
78 {Q_XQUOTAON, &qflag, check_qon, NULL},
79 {Q_XGETQUOTA, &dquota, check_getq, NULL},
80 {Q_XSETQLIM, &dquota, check_setqlim, setup_setqlim},
81 {Q_XGETQSTAT, &qstat, check_getqstat, NULL},
82};
83
84int main(int argc, char *argv[])
85{
86 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020087 const char *msg;
DAN LIe11382a2013-09-03 10:17:09 +080088
Cyril Hrubis47a114d2014-08-14 13:21:36 +020089 msg = parse_opts(argc, argv, NULL, NULL);
DAN LIe11382a2013-09-03 10:17:09 +080090 if (msg != NULL)
91 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
92
DAN LIe11382a2013-09-03 10:17:09 +080093 setup();
94
95 for (lc = 0; TEST_LOOPING(lc); ++lc) {
96
97 tst_count = 0;
98
99 for (i = 0; i < TST_TOTAL; i++) {
100
101 if (TC[i].func_setup != NULL)
102 (*TC[i].func_setup) ();
103
104 TEST(ltp_syscall(__NR_quotactl,
105 USRQCMD(TC[i].cmd), block_dev,
106 uid, TC[i].addr));
107
108 if (TEST_RETURN != 0)
109 tst_resm(TFAIL | TERRNO,
110 "cmd=0x%x failed", TC[i].cmd);
111
Cyril Hrubise38b9612014-06-02 17:20:57 +0200112 (*TC[i].func_test) ();
DAN LIe11382a2013-09-03 10:17:09 +0800113 }
114 }
115 cleanup();
116 tst_exit();
117}
118
119static void check_qoff(void)
120{
121 int ret;
122
123 ret = ltp_syscall(__NR_quotactl, USRQCMD(Q_XGETQSTAT),
124 block_dev, uid, &qstat);
125 if (ret != 0)
126 tst_brkm(TBROK | TERRNO, cleanup, "fail to get quota stat");
127
128 if (qstat.qs_flags & XFS_QUOTA_UDQ_ENFD) {
129 tst_resm(TFAIL, "enforcement is not off");
130 return;
131 }
132
133 tst_resm(TPASS, "enforcement is off");
134}
135
136static void check_qon(void)
137{
138 int ret;
139 ret = ltp_syscall(__NR_quotactl, USRQCMD(Q_XGETQSTAT),
140 block_dev, uid, &qstat);
141 if (ret != 0)
142 tst_brkm(TBROK | TERRNO, cleanup, "fail to get quota stat");
143
144 if (!(qstat.qs_flags & XFS_QUOTA_UDQ_ENFD)) {
145 tst_resm(TFAIL, "enforcement is off");
146 return;
147 }
148
149 tst_resm(TPASS, "enforcement is on");
150}
151
152static void check_getq(void)
153{
154 if (!(dquota.d_flags & XFS_USER_QUOTA)) {
155 tst_resm(TFAIL, "get incorrect quota type");
156 return;
157 }
158
159 tst_resm(TPASS, "get the right quota type");
160}
161
162static void setup_setqlim(void)
163{
164 dquota.d_rtb_hardlimit = RTBLIMIT;
165 dquota.d_fieldmask = FS_DQ_LIMIT_MASK;
166}
167
168static void check_setqlim(void)
169{
170 int ret;
171 ret = ltp_syscall(__NR_quotactl, USRQCMD(Q_XGETQUOTA),
172 block_dev, uid, &dquota);
173 if (ret != 0)
174 tst_brkm(TFAIL | TERRNO, NULL,
175 "fail to get quota information");
176
177 if (dquota.d_rtb_hardlimit != RTBLIMIT) {
178 tst_resm(TFAIL, "limit on RTB, except %lu get %lu",
179 (uint64_t)RTBLIMIT,
180 (uint64_t)dquota.d_rtb_hardlimit);
181 return;
182 }
183
184 tst_resm(TPASS, "quotactl works fine with Q_XSETQLIM");
185}
186
187static void check_getqstat(void)
188{
189 if (qstat.qs_version != FS_QSTAT_VERSION) {
190 tst_resm(TFAIL, "get incorrect qstat version");
191 return;
192 }
193
194 tst_resm(TPASS, "get correct qstat version");
195}
196
197static void setup(void)
198{
199
200 tst_require_root(NULL);
201
202 TEST_PAUSE;
203
204 tst_tmpdir();
205
206 SAFE_MKDIR(cleanup, mntpoint, 0755);
207
Cyril Hrubis47a114d2014-08-14 13:21:36 +0200208 block_dev = tst_acquire_device(cleanup);
209
210 if (!block_dev)
211 tst_brkm(TCONF, cleanup, "Failed to obtain block device");
212
213 tst_mkfs(cleanup, block_dev, "xfs", NULL);
DAN LIe11382a2013-09-03 10:17:09 +0800214
215 if (mount(block_dev, mntpoint, "xfs", 0, "uquota") < 0)
216 tst_brkm(TFAIL | TERRNO, NULL, "mount(2) fail");
Cyril Hrubis47a114d2014-08-14 13:21:36 +0200217 mount_flag = 1;
DAN LIe11382a2013-09-03 10:17:09 +0800218}
219
220static void cleanup(void)
221{
Cyril Hrubisc60a2302015-01-29 16:28:24 +0100222 if (mount_flag && tst_umount(mntpoint) < 0)
Cyril Hrubis47a114d2014-08-14 13:21:36 +0200223 tst_resm(TWARN | TERRNO, "umount(2) failed");
224
225 if (block_dev)
226 tst_release_device(NULL, block_dev);
DAN LIe11382a2013-09-03 10:17:09 +0800227
DAN LIe11382a2013-09-03 10:17:09 +0800228 tst_rmdir();
229}
DAN LIe11382a2013-09-03 10:17:09 +0800230#else
231int main(void)
232{
233 tst_brkm(TCONF, NULL, "This system doesn't support xfs quota");
234}
235#endif