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