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