1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2019 FUJITSU LIMITED. All rights reserved.
4 * Author: Yang Xu <xuyang2018.jy@fujitsu.com>
5 */
6
7 /*\
8 * [Description]
9 *
10 * This is not only a functional test but also a error test for Q_XQUOTARM.
11 *
12 * It is a regresstion test for kernel commit 3dd4d40b4208
13 * ("xfs: Sanity check flags of Q_XQUOTARM call").
14 */
15
16 #include <errno.h>
17 #include <unistd.h>
18 #include <stdio.h>
19 #include <sys/quota.h>
20 #include <sys/statvfs.h>
21 #include "tst_test.h"
22 #include "quotactl_syscall_var.h"
23
24 #ifdef HAVE_XFS_XQM_H
25 # include <xfs/xqm.h>
26
27 /* Include a valid quota type to avoid other EINVAL error */
28 static unsigned int invalid_type = XFS_GROUP_QUOTA << 1 | XFS_USER_QUOTA;
29 static unsigned int valid_type = XFS_USER_QUOTA;
30 static int mount_flag;
31
verify_quota(void)32 static void verify_quota(void)
33 {
34 struct statfs before, after;
35
36 SAFE_STATFS(MNTPOINT, &before);
37 TST_EXP_PASS(do_quotactl(fd, QCMD(Q_XQUOTARM, USRQUOTA), tst_device->dev, 0,
38 (void *)&valid_type), "do_quotactl(Q_XQUOTARM,valid_type)");
39 SAFE_STATFS(MNTPOINT, &after);
40 if (before.f_bavail <= after.f_bavail)
41 tst_res(TPASS, "Q_XQUOTARM to free space, delta(%lu)", after.f_bavail - before.f_bavail);
42 else
43 tst_res(TFAIL, "Q_XQUOTARM to free space, delta(-%lu)", before.f_bavail - after.f_bavail);
44
45 TST_EXP_FAIL(do_quotactl(fd, QCMD(Q_XQUOTARM, USRQUOTA), tst_device->dev, 0,
46 (void *)&invalid_type), EINVAL, "do_quotactl(Q_XQUOTARM, invalid_type)");
47 }
48
setup(void)49 static void setup(void)
50 {
51 quotactl_info();
52
53 /*
54 * Ensure superblock has quota data, but not running. In here, we must unmount
55 * completely and mount again with '-o no quota' because 'mount -o remount, noquota'
56 * isn't sufficient to disable accounting feature.
57 */
58 SAFE_MOUNT(tst_device->dev, MNTPOINT, tst_device->fs_type, 0, "usrquota");
59 mount_flag = 1;
60 SAFE_UMOUNT(MNTPOINT);
61 mount_flag = 0;
62 SAFE_MOUNT(tst_device->dev, MNTPOINT, tst_device->fs_type, 0, "noquota");
63 mount_flag = 1;
64
65 fd = SAFE_OPEN(MNTPOINT, O_RDONLY);
66 }
67
cleanup(void)68 static void cleanup(void)
69 {
70 if (fd > -1)
71 SAFE_CLOSE(fd);
72 if (mount_flag && tst_umount(MNTPOINT))
73 tst_res(TWARN | TERRNO, "umount(%s)", MNTPOINT);
74 }
75
76 static struct tst_test test = {
77 .setup = setup,
78 .cleanup = cleanup,
79 .needs_root = 1,
80 .needs_kconfigs = (const char *[]) {
81 "CONFIG_XFS_QUOTA",
82 NULL
83 },
84 .test_all = verify_quota,
85 .format_device = 1,
86 .dev_fs_type = "xfs",
87 .mntpoint = MNTPOINT,
88 .test_variants = QUOTACTL_SYSCALL_VARIANTS,
89 .tags = (const struct tst_tag[]) {
90 {"linux-git", "3dd4d40b4208"},
91 {}
92 }
93 };
94 #else
95 TST_TEST_TCONF("System doesn't have <xfs/xqm.h>");
96 #endif
97