• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2017 Fujitsu Ltd.
3  * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program, if not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /*
20  * Test Name: quotactl03
21  *
22  * Description:
23  * quotactl(2) with XGETNEXTQUOTA looks for the next active quota for an user
24  * equal or higher to a given ID, in this test the ID is specified to a value
25  * close to UINT_MAX(max value of unsigned int). When reaching the upper limit
26  * and finding no active quota, it should return -1 and set errno to ENOENT.
27  * Actually, quotactl(2) overflows and and return 0 as the "next" active id.
28  *
29  * This kernel bug of xfs has been fixed in:
30  *
31  * commit 657bdfb7f5e68ca5e2ed009ab473c429b0d6af85
32  * Author: Eric Sandeen <sandeen@redhat.com>
33  * Date:   Tue Jan 17 11:43:38 2017 -0800
34  *
35  *     xfs: don't wrap ID in xfs_dq_get_next_id
36  */
37 
38 #define _GNU_SOURCE
39 #include <errno.h>
40 #include <unistd.h>
41 #include <stdio.h>
42 #include <sys/quota.h>
43 #include "config.h"
44 
45 #if defined(HAVE_QUOTAV2) || defined(HAVE_QUOTAV1)
46 # include <sys/quota.h>
47 #endif
48 
49 #if defined(HAVE_XFS_QUOTA)
50 # include <xfs/xqm.h>
51 #endif
52 
53 #include "tst_test.h"
54 #include "lapi/quotactl.h"
55 
56 #if defined(HAVE_XFS_QUOTA) && (defined(HAVE_QUOTAV2) || defined(HAVE_QUOTAV1))
57 
58 static const char mntpoint[] = "mnt_point";
59 static uint32_t test_id = 0xfffffffc;
60 
verify_quota(void)61 static void verify_quota(void)
62 {
63 	struct fs_disk_quota res_dquota;
64 
65 	res_dquota.d_id = 1;
66 
67 	TEST(quotactl(QCMD(Q_XGETNEXTQUOTA, USRQUOTA), tst_device->dev,
68 		test_id, (void *)&res_dquota));
69 	if (TST_RET != -1) {
70 		tst_res(TFAIL, "quotactl() found the next active ID:"
71 			" %u unexpectedly", res_dquota.d_id);
72 		return;
73 	}
74 
75 	if (TST_ERR == EINVAL) {
76 		tst_brk(TCONF | TTERRNO,
77 			"Q_XGETNEXTQUOTA wasn't supported in quotactl()");
78 	}
79 
80 	if (TST_ERR != ENOENT) {
81 		tst_res(TFAIL | TTERRNO, "quotactl() failed unexpectedly with"
82 			" %s expected ENOENT", tst_strerrno(TST_ERR));
83 	} else {
84 		tst_res(TPASS, "quotactl() failed with ENOENT as expected");
85 	}
86 }
87 
88 static struct tst_test test = {
89 	.needs_tmpdir = 1,
90 	.needs_root = 1,
91 	.test_all = verify_quota,
92 	.mount_device = 1,
93 	.dev_fs_type = "xfs",
94 	.mntpoint = mntpoint,
95 	.mnt_data = "usrquota",
96 };
97 
98 #else
99 	TST_TEST_TCONF("This system didn't support quota or xfs quota");
100 #endif
101