[Ocfs2-test-devel] [PATCH 4/5] Ocfs2-test: Add mpi binary for quota tests in multi-nodes mode.
Tristan Ye
tristan.ye at oracle.com
Mon Dec 22 16:59:59 PST 2008
It was a mpi compatible problem developed/tested under openmpi,
performed as a sanity checker and stress puncher for quota on ocfs2
among multiple nodes,currently it includes following testcases:
1.Set/Get quota for one user/group among nodes.
2.Quota inodes limit test for users/groups among nodes.
3.Quota space limit test for users/groups among nodes.
4.Quota grace time test among nodes.
5.Huge user/group number test among nodes.
6.Stress test with intensive quota operations for user/group.
7.Negative and positive quota test.
8.Concurrent file r/w test.
9.Quota corruption test.
Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
---
programs/quota_tests/quota_multi_tests.c | 1425 ++++++++++++++++++++++++++++++
1 files changed, 1425 insertions(+), 0 deletions(-)
create mode 100755 programs/quota_tests/quota_multi_tests.c
diff --git a/programs/quota_tests/quota_multi_tests.c b/programs/quota_tests/quota_multi_tests.c
new file mode 100755
index 0000000..fa31735
--- /dev/null
+++ b/programs/quota_tests/quota_multi_tests.c
@@ -0,0 +1,1425 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * quota_multi_tests.c
+ *
+ * A mpi compatible program to test quota among mutiple nodes by
+ * running a series of generic and stress tests.
+ *
+ * Author: Tristan Ye (tristan.ye at oracle.com)
+ *
+ * Copyright (C) 2008 Oracle. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include "quota.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <stdarg.h>
+#include <sys/xattr.h>
+#include <dirent.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <mpi.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <ocfs2/ocfs2.h>
+
+#define HOSTNAME_MAX_SZ 100
+#define PATH_SZ 255
+#define MAX_FILENAME_SZ 200
+#define DEFAULT_ITER_NUMS 1
+
+#define DEFAULT_USER_NUM 10
+#define DEFAULT_GROUP_NUM 10
+#define TEST_NODES_MAX_NUM 32
+#define USERNAME_SZ 100
+#define GROUPNAME_SZ 100
+
+#define QUOTAON_BIN "/usr/local/sbin/quotaon"
+#define USERADD_BIN "/usr/sbin/useradd"
+#define USERDEL_BIN "/usr/sbin/userdel"
+#define GROUPADD_BIN "/usr/sbin/groupadd"
+#define GROUPDEL_BIN "/usr/sbin/groupdel"
+
+#define WORKPLACE "quota-test"
+
+#define USER 1
+#define GROUP 2
+#define USER_IN_GROUP 4
+
+#define ADD 1
+#define REMOVE 2
+
+#define QUOTAUSER 1
+#define QUOTAGROUP 2
+
+#define ISOFT_LIMIT 1
+#define IHARD_LIMIT 2
+#define BSOFT_LIMIT 4
+#define BHARD_LIMIT 8
+
+#define FILE_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IROTH|\
+ S_IWOTH|S_IXOTH|S_IRGRP|S_IWGRP|S_IXGRP)
+
+static char *prog;
+static char mountpoint[PATH_SZ + 1];
+static char device[PATH_SZ + 1];
+static char workplace[PATH_SZ +1];
+static char filename[PATH_SZ +1];
+static long iterations = DEFAULT_ITER_NUMS;
+
+static long user_nums = DEFAULT_USER_NUM;
+static long group_nums = DEFAULT_GROUP_NUM;
+
+static int type = 0;
+
+static int testno = 1;
+static int rank, size;
+static char hostname[HOSTNAME_MAX_SZ];
+
+static unsigned int blocksize;
+static unsigned long clustersize;
+
+ocfs2_filesys *fs;
+struct ocfs2_super_block *ocfs2_sb;
+
+static int usage(void)
+{
+
+ printf("Usage: quota_multi_tests [-t iterations] [-u users] [-g groups] "
+ "<-d device> <mount_point>\n"
+ "Run a series of tests intended to verify quota functionality "
+ "among multiple nodes.\n\n"
+ "-i iterations specify the running times.\n"
+ "-u users,specify the number of users.\n"
+ "-g groups,specify the number of groups.\n"
+ "at least one of the -u or -g options shoud be selected.\n"
+ "device and mount_point are mandatory.\n");
+
+ MPI_Finalize();
+ exit(1);
+
+}
+
+static void abort_printf(const char *fmt, ...)
+{
+ va_list ap;
+
+ printf("%s (rank %d): ", hostname, rank);
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ MPI_Abort(MPI_COMM_WORLD, 1);
+}
+
+static void log_printf(FILE *stream, const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stream, "%s (rank %d): ", hostname, rank);
+ va_start(ap,fmt);
+ vprintf(fmt, ap);
+}
+
+static void root_printf(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (rank == 0) {
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ }
+}
+
+static uid_t user2uid(char *name)
+{
+ struct passwd *entry;
+ uid_t ret;
+
+ if (!(entry = getpwnam(name))) {
+ ret = errno;
+ log_printf(stderr, "user %s does not exist!\n", name);
+ return ret;
+ } else {
+ ret = entry->pw_uid;
+ return ret;
+
+ }
+}
+
+static uid_t group2gid(char *name)
+{
+ struct group *entry;
+ gid_t ret;
+
+ if (!(entry = getgrnam(name))) {
+ ret = errno;
+ log_printf(stderr, "group %s does not exist!\n", name);
+ return ret;
+ } else {
+ ret = entry->gr_gid;
+ return ret;
+ }
+
+}
+
+static int name2id(int type, char *name)
+{
+ if (type & USER)
+ return user2uid(name);
+ if (type & GROUP)
+ return group2gid(name);
+}
+
+static void MPI_Barrier_Sync(void)
+{
+ int ret;
+
+ ret = MPI_Barrier(MPI_COMM_WORLD);
+ if (ret != MPI_SUCCESS)
+ abort_printf("MPI_Barrier failed: %d\n", ret);
+}
+
+int open_ocfs2_volume(char *device_name)
+{
+ int open_flags = OCFS2_FLAG_HEARTBEAT_DEV_OK | OCFS2_FLAG_RO;
+ int ret;
+
+ ret = ocfs2_open(device_name, open_flags, 0, 0, &fs);
+ if (ret < 0) {
+ fprintf(stderr, "%s is not a ocfs2 volume!\n", device_name);
+ return ret;
+ }
+
+ ocfs2_sb = OCFS2_RAW_SB(fs->fs_super);
+ blocksize = 1 << ocfs2_sb->s_blocksize_bits;
+ clustersize = 1 << ocfs2_sb->s_clustersize_bits;
+
+ return 0;
+}
+
+static int parse_opts(int argc, char *argv[])
+{
+ char c;
+ while (1) {
+ c = getopt(argc, argv, "i:I:u:U:g:G:d:D:t:T:");
+ if (c == -1)
+ break;
+ switch (c) {
+ case 'i':
+ case 'I':
+ iterations = atol(optarg);
+ break;
+ case 'u':
+ case 'U':
+ type |= QUOTAUSER;
+ user_nums = atol(optarg);
+ break;
+ case 'g':
+ case 'G':
+ type |= QUOTAGROUP;
+ group_nums = atol(optarg);
+ break;
+ case 'd':
+ case 'D':
+ strcpy(device, optarg);
+ break;
+ case 't':
+ case 'T':
+ iterations = atol(optarg);
+ default:
+ return EINVAL;
+ }
+ }
+
+ if (argc - optind != 1)
+ return EINVAL;
+
+ if (!(type & QUOTAUSER) && !(type & QUOTAGROUP)) {
+ log_printf(stderr, "At least one of -u or -g options "
+ "should be specified!\n");
+ return EINVAL;
+ }
+
+ strcpy(mountpoint, argv[optind]);
+ if (mountpoint[strlen(mountpoint) - 1] == '/')
+ mountpoint[strlen(mountpoint) - 1] = '\0';
+
+ return 0;
+}
+
+static int add_rm_user_group(const char *bin_path, int ad_or_rm, int usr_or_grp,
+ const char *name, char *ex_name)
+{
+ int ret = 0;
+ int child_status;
+ char *argv[6];
+ char arg1[20];
+ pid_t child;
+
+ child = fork();
+ if (child < 0) {
+ ret = errno;
+ log_printf(stderr, "Failed to fork for user/group add/remove:%d:%s\n",
+ ret, strerror(ret));
+ goto bail;
+ }
+ if (!child) {
+ argv[0] = (char *)bin_path;
+
+ if (usr_or_grp & USER) {
+ if (ad_or_rm & ADD)
+ strcpy(arg1, "-m");
+ else
+ strcpy(arg1, "-r");
+ argv[1] = arg1;
+ argv[2] = (char *)name;
+ argv[3] = NULL;
+
+ } else if (usr_or_grp & GROUP) {
+ argv[1] = (char *)name;
+ argv[2] = NULL;
+ } else if (usr_or_grp & USER_IN_GROUP) {
+ strcpy(arg1, "-m");
+ argv[1] = arg1;
+ argv[2] = "-g";
+ argv[3] = (char *)ex_name;
+ argv[4] = (char *)name;
+ argv[5] = NULL;
+ }
+
+ ret = execv(argv[0], argv);
+ ret = errno;
+ exit(ret);
+
+ } else {
+ ret = waitpid(child, &child_status, 0);
+ if (ret < 0) {
+ ret = errno;
+ log_printf(stderr, "Failed to wait child for its completion"
+ ":%d:%s\n", ret, strerror(ret));
+ goto bail;
+ }
+
+ ret = WEXITSTATUS(child_status);
+ }
+
+bail:
+ return ret;
+}
+
+static int quota_on_off(const char *qbin_path, int on, int type,
+ const char *fsname)
+{
+ int ret = 0;
+ int child_status;
+ char *argv[4];
+ char arg1[20];
+ pid_t child;
+
+ child = fork();
+ if (child < 0) {
+ ret = errno;
+ log_printf(stderr, "Failed to fork for quota on or off:%d:%s\n",
+ ret, strerror(ret));
+ goto bail;
+ }
+
+ if (!child) {
+ argv[0] = (char *)qbin_path;
+ strcpy(arg1, "-");
+ if (type & QUOTAUSER)
+ strcat(arg1, "u");
+ if (type & QUOTAGROUP)
+ strcat(arg1, "g");
+ if (!on)
+ strcat(arg1, "f");
+
+ argv[1] = arg1;
+ argv[2] = (char *)fsname;
+ argv[3] = NULL;
+
+ ret = execv(argv[0], argv);
+ ret = errno;
+ exit(ret);
+
+ } else {
+ ret = waitpid(child, &child_status, 0);
+ if (ret < 0) {
+ ret = errno;
+ log_printf(stderr, "Failed to wait child for its completion"
+ ":%d:%s\n", ret, strerror(ret));
+ goto bail;
+ }
+
+ ret = WEXITSTATUS(child_status);
+ }
+
+bail:
+ return ret;
+}
+
+static int setquotainfo(int type, const char *device, int id, struct if_dqinfo dqi)
+{
+ int ret;
+ int q_type;
+
+ if (type & QUOTAUSER)
+ q_type = USRQUOTA;
+ else
+ q_type = GRPQUOTA;
+
+ if (quotactl(QCMD(Q_SETINFO, q_type), device, id, (caddr_t) & dqi)) {
+ ret = errno;
+ log_printf(stderr, "Set quota info failed,quotactl:%d:%s\n",
+ ret, strerror(ret));
+ } else
+ ret = 0;
+
+ return ret;
+}
+
+static int setquota(int type, const char *device, int id, struct if_dqblk dq)
+{
+ int ret;
+ int q_type;
+
+ if (type & QUOTAUSER)
+ q_type = USRQUOTA;
+ else
+ q_type = GRPQUOTA;
+
+ if (quotactl(QCMD(Q_SETQUOTA, q_type), device, id, (caddr_t) & dq)) {
+ ret = errno;
+ log_printf(stderr, "Set quota failed,quotactl:%d:%s\n",
+ ret, strerror(ret));
+ } else
+ ret = 0;
+
+ return ret;
+}
+
+static int getquotainfo(int type, const char *device, int id, struct if_dqinfo *dqi)
+{
+ int ret;
+ int q_type;
+
+ if (type & QUOTAUSER)
+ q_type = USRQUOTA;
+ else
+ q_type = GRPQUOTA;
+
+ if (quotactl(QCMD(Q_GETINFO, q_type), device, id, (caddr_t)dqi)) {
+ ret = errno;
+ log_printf(stderr, "Get quota info failed, quotactl:%d:%s\n",
+ ret, strerror(ret));
+ } else
+ ret = 0;
+
+ return ret;
+}
+
+static int getquota(int type, const char *deive, int id, struct if_dqblk *dq)
+{
+ int ret;
+ int q_type;
+
+ if (type & QUOTAUSER)
+ q_type = USRQUOTA;
+ else
+ q_type = GRPQUOTA;
+
+ if (quotactl(QCMD(Q_GETQUOTA, q_type), device, id, (caddr_t)dq)) {
+ ret = errno;
+ log_printf(stderr, "Get quota failed,quotactl:%d:%s\n",
+ ret, strerror(ret));
+ } else
+ ret = 0;
+
+ return ret;
+}
+
+static int verify_quota_items(const struct if_dqblk s_dq, const struct if_dqblk d_dq,
+ int limit_type)
+{
+ int ret = 1;
+
+ if (limit_type & ISOFT_LIMIT) {
+
+ if (s_dq.dqb_isoftlimit != d_dq.dqb_isoftlimit) {
+ log_printf(stderr, "Quota inconsistent match found,"
+ "expected isoftlimit = %d,actual isoftlimit = %d\n",
+ s_dq.dqb_isoftlimit, d_dq.dqb_isoftlimit);
+ ret = 0;
+ goto bail;
+ }
+ }
+
+ if (limit_type & IHARD_LIMIT) {
+ if (s_dq.dqb_ihardlimit != d_dq.dqb_ihardlimit) {
+ log_printf(stderr, "Quota inconsistent match found,"
+ "expected ihardlimit = %d,actual ihardlimit = %d\n",
+ s_dq.dqb_ihardlimit, d_dq.dqb_ihardlimit);
+ ret = 0;
+ goto bail;
+ }
+ }
+
+ if (limit_type & BSOFT_LIMIT) {
+
+ if (s_dq.dqb_bsoftlimit != d_dq.dqb_bsoftlimit) {
+ log_printf(stderr, "Quota inconsistent match found,"
+ "expected bsoftlimit = %d,actual bsoftlimit = %d\n",
+ s_dq.dqb_bsoftlimit, d_dq.dqb_bsoftlimit);
+ ret = 0;
+ goto bail;
+ }
+ }
+
+ if (limit_type & BHARD_LIMIT) {
+ if (s_dq.dqb_bhardlimit != d_dq.dqb_bhardlimit) {
+ log_printf(stderr, "Quota inconsistent match found,"
+ "expected bhardlimit = %d,actual bhardlimit = %d\n",
+ s_dq.dqb_bhardlimit, d_dq.dqb_bhardlimit);
+ ret = 0;
+ goto bail;
+ }
+ }
+
+bail:
+ return ret;
+
+}
+
+static unsigned long get_rand(unsigned long min, unsigned long max)
+{
+ if (min == 0 && max == 0)
+ return 0;
+
+ return min + (rand() % (max - min + 1));
+}
+
+static void negative_inodes_limit_test(long isoftlimit, long bsoftlimit,
+ long user_postfix, long rm_nums)
+{
+ int ret, fd, o_uid, j;
+ long i, file_index, rm_counts = 0;
+ struct if_dqblk s_dq, d_dq;
+ char username[USERNAME_SZ];
+ int *inodes_removed;
+
+ MPI_Request request;
+ MPI_Status status;
+
+ if (!rank) {
+
+ inodes_removed = (int *)malloc(sizeof(int) * isoftlimit * 2);
+ memset((void *)inodes_removed, 0, sizeof(int) * isoftlimit *2);
+ snprintf(username, USERNAME_SZ, "quota-user-rank%d-%d", rank,
+ user_postfix);
+
+ add_rm_user_group(USERADD_BIN, ADD, USER, username, NULL);
+ getquota(QUOTAUSER, device, name2id(USER, username), &s_dq);
+ s_dq.dqb_isoftlimit = isoftlimit;
+ s_dq.dqb_ihardlimit = isoftlimit * 2;
+ s_dq.dqb_bsoftlimit = bsoftlimit;
+ s_dq.dqb_bhardlimit = bsoftlimit * 2;
+ s_dq.dqb_curinodes = 0;
+ s_dq.dqb_curspace = 0;
+ setquota(QUOTAUSER, device, name2id(USER, username), s_dq);
+ } else
+ snprintf(username, USERNAME_SZ, "quota-user-rank0-%d",
+ user_postfix);
+
+ /*
+ * Rank0 creats the files,while other ranks take race to remove.
+ * Thus,the quota number should go negative.
+ */
+
+ if (!rank) {
+ o_uid = getuid();
+ seteuid(name2id(USER, username));
+ for (i = 0; i < isoftlimit * 2; i++) {
+ snprintf(filename, PATH_SZ, "%s/%s-quotafile-%d",
+ workplace, username, i);
+ fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE);
+ if (fd < 0) {
+ ret = errno;
+ abort_printf("Open file failed:%d:%s\n", ret, strerror(ret));
+ }
+
+ close(fd);
+ }
+
+ seteuid(o_uid);
+
+ rm_counts = 0;
+ for (j = 1; j < size; j++) {
+ for (i = 0; i < rm_nums; i++) {
+ ret = MPI_Irecv(&file_index, sizeof(long),
+ MPI_BYTE, j, 1, MPI_COMM_WORLD,
+ &request);
+
+ if (ret == MPI_SUCCESS) {
+ rm_counts++;
+ inodes_removed[file_index] = 1;
+ }
+ else
+ abort_printf("MPI_Irecv Failed.\n");
+ MPI_Wait(&request, &status);
+ }
+ }
+
+ getquota(QUOTAUSER, device, name2id(USER, username), &d_dq);
+ if (d_dq.dqb_curinodes != isoftlimit * 2 - rm_counts)
+ abort_printf("Negative inodes test failed among nodes,"
+ "Incorrect quota stats found,expected "
+ "inodes_num = %ld, queried inodes_num = "
+ "%ld.\n", isoftlimit * 2 - rm_counts,
+ d_dq.dqb_curinodes);
+
+ } else {
+ /*
+ * Other nodes perform a random deletion as root user
+ */
+ rm_counts = 0;
+
+ while (rm_counts < rm_nums) {
+ i = get_rand(0, isoftlimit * 2 - 1);
+ snprintf(filename, PATH_SZ, "%s/%s-quotafile-%d",
+ workplace, username, i);
+ ret = unlink(filename);
+ if (ret < 0)
+ continue;
+ else {
+ ret = MPI_Isend(&i, sizeof(long), MPI_BYTE,
+ 0, 1, MPI_COMM_WORLD, &request);
+ if (ret != MPI_SUCCESS)
+ abort_printf("MPI_Isend Failed.\n");
+ MPI_Wait(&request, &status);
+ rm_counts++;
+ }
+ }
+ }
+
+ MPI_Barrier_Sync();
+ /* Cleanup */
+
+ if (!rank) {
+ file_index = 0;
+ while (file_index < isoftlimit * 2) {
+ if (!inodes_removed[file_index]) {
+ snprintf(filename, PATH_SZ, "%s/%s-quotafile-%d",
+ workplace, username, file_index);
+ ret = unlink(filename);
+ }
+
+ file_index++;
+ }
+
+ snprintf(filename, PATH_SZ, "%s/%s-quotafile-%d", workplace, username, 0);
+ ret = access(filename, F_OK);
+ if (ret == 0)
+ unlink(filename);
+
+ add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL);
+
+ }
+}
+
+static void user_inodes_grace_time_test(long isoftlimit, long bsoftlimit,
+ long grace_seconds, long user_postfix)
+{
+ int ret, fd, o_uid;
+ long i;
+ struct if_dqblk s_dq, d_dq;
+ struct if_dqinfo s_dqi;
+
+ char username[USERNAME_SZ];
+
+ snprintf(username, USERNAME_SZ, "quota-user-rank%d-%d", rank,
+ user_postfix);
+
+ add_rm_user_group(USERADD_BIN, ADD, USER, username, NULL);
+ getquota(QUOTAUSER, device, name2id(USER, username), &s_dq);
+ s_dq.dqb_isoftlimit = isoftlimit;
+ s_dq.dqb_ihardlimit = isoftlimit * 2;
+ s_dq.dqb_bsoftlimit = bsoftlimit;
+ s_dq.dqb_bhardlimit = bsoftlimit * 2;
+ s_dq.dqb_curinodes = 0;
+ s_dq.dqb_curspace = 0;
+ setquota(QUOTAUSER, device, name2id(USER, username), s_dq);
+
+ getquotainfo(QUOTAUSER, device, name2id(USER, username), &s_dqi);
+ s_dqi.dqi_bgrace = 60000;
+ s_dqi.dqi_igrace = grace_seconds;
+ setquotainfo(QUOTAUSER, device, name2id(USER, username), s_dqi);
+
+ o_uid = getuid();
+ seteuid(name2id(USER, username));
+
+ for (i = 0; i <= isoftlimit ; i++) {
+ snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%d",
+ workplace, hostname, username, i);
+ fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE);
+ if (fd < 0) {
+ ret = errno;
+ abort_printf("Open file failed:%d:%s\n", ret, strerror(ret));
+ }
+
+ close(fd);
+ getquota(QUOTAUSER, device, name2id(USER, username), &d_dq);
+ if (d_dq.dqb_curinodes != i + 1)
+ abort_printf("Incorrect quota stats found,expected "
+ "inode_num = %d,queried inode_num = %d.\n",
+ i + 1, d_dq.dqb_curinodes);
+ }
+
+ /*Grace time take effect from now*/
+ sleep(grace_seconds);
+ /*grace time expires,so should hit failure here*/
+ snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%d",
+ workplace, hostname, username, isoftlimit + 1);
+ if ((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE)) > 0) {
+ close(fd);
+ abort_printf("Not allowd to exceed the grace time limit of inodes.\n");
+ }
+
+ /*cleanup*/
+ seteuid(o_uid);
+
+ for (i = 0; i <= isoftlimit; i++) {
+ snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%d",
+ workplace, hostname, username, i);
+ ret = unlink(filename);
+ if (ret < 0) {
+ ret =errno;
+ abort_printf("Failed to unlink file(%s):%d:%s\n",
+ filename, ret, strerror(ret));
+ }
+
+ }
+
+ add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL);
+}
+
+static void user_space_limit_test(long isoftlimit, long bsoftlimit, int user_postfix)
+{
+ int ret;
+ long i;
+ int fd;
+ int o_uid;
+ struct if_dqblk s_dq, d_dq;
+ char *write_buf;
+ int writen_sz = 0;
+ long file_sz = 0;
+ char username[USERNAME_SZ];
+
+ write_buf = (char *)malloc(clustersize);
+ memset(write_buf, 0, clustersize);
+
+ snprintf(username, USERNAME_SZ, "quotauser-rank%d-%d", rank,
+ user_postfix);
+ add_rm_user_group(USERADD_BIN, ADD, USER, username, NULL);
+ getquota(QUOTAUSER, device, name2id(USER, username), &s_dq);
+ s_dq.dqb_isoftlimit = isoftlimit;
+ s_dq.dqb_ihardlimit = isoftlimit * 2;
+ s_dq.dqb_bsoftlimit = bsoftlimit;
+ s_dq.dqb_bhardlimit = bsoftlimit * 2;
+ s_dq.dqb_curinodes = 0;
+ s_dq.dqb_curspace = 0;
+ setquota(QUOTAUSER, device, name2id(USER, username), s_dq);
+
+ o_uid = getuid();
+
+ ret = seteuid(name2id(USER, username));
+ if (ret < 0) {
+ ret = errno;
+ abort_printf("Set euid failed:%d:%s.\n", ret, strerror(ret));
+ }
+
+ snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-user-spacelimit", workplace,
+ hostname, username);
+
+ fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_APPEND, FILE_MODE);
+
+ while (file_sz + clustersize <= bsoftlimit * 2 * 1024) {
+ writen_sz = write(fd, write_buf, clustersize);
+ if (writen_sz < 0) {
+ ret = errno;
+ abort_printf("write failed:%d:%s.\n", ret, strerror(ret));
+ }
+ file_sz += writen_sz;
+ }
+
+ if ((ret = write(fd, write_buf, clustersize)) > 0)
+ abort_printf("No allowed to exceed the hard limit of space");
+
+ if (fd)
+ close(fd);
+
+ ret = unlink(filename);
+ if (ret < 0) {
+ ret =errno;
+ abort_printf("Failed to unlink file(%s):%d:%s\n",
+ filename, ret, strerror(ret));
+ }
+
+ sync();
+
+ seteuid(o_uid);
+
+ add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL);
+
+ if (write_buf)
+ free(write_buf);
+}
+
+static void user_inodes_limit_test(long isoftlimit, long bsoftlimit, int user_postfix)
+{
+ int ret;
+ long i;
+ int fd;
+ int o_uid;
+ struct if_dqblk s_dq, d_dq;
+
+ char username[USERNAME_SZ];
+
+ snprintf(username, USERNAME_SZ, "quotauser-rank%d-%d", rank,
+ user_postfix);
+ add_rm_user_group(USERADD_BIN, ADD, USER, username, NULL);
+ getquota(QUOTAUSER, device, name2id(USER, username), &s_dq);
+ s_dq.dqb_isoftlimit = isoftlimit;
+ s_dq.dqb_ihardlimit = isoftlimit * 2;
+ s_dq.dqb_bsoftlimit = bsoftlimit;
+ s_dq.dqb_bhardlimit = bsoftlimit * 2;
+ s_dq.dqb_curinodes = 0;
+ s_dq.dqb_curspace = 0;
+ setquota(QUOTAUSER, device, name2id(USER, username), s_dq);
+
+ o_uid = getuid();
+ ret = seteuid(name2id(USER, username));
+ if (ret < 0) {
+ ret = errno;
+ abort_printf("Set euid failed:%d:%s.\n", ret, strerror(ret));
+ }
+
+ for (i = 0; i < isoftlimit * 2; i++) {
+ snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%d",
+ workplace, hostname, username, i);
+ if (!(i % 2)) {
+ fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE);
+ if (fd < 0) {
+ ret = errno;
+ abort_printf("Open file failed:%d:%s\n", ret, strerror(ret));
+ }
+ close(fd);
+ } else
+ mkdir(filename, FILE_MODE);
+
+ getquota(QUOTAUSER, device, name2id(USER, username), &d_dq);
+ if (d_dq.dqb_curinodes != i + 1)
+ abort_printf("Incorrect quota stats found,expected "
+ "inode_num = %d,queried inode_num = %d.\n",
+ i + 1, d_dq.dqb_curinodes);
+ }
+
+ /*We definitely should hit falure here*/
+ snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%d",
+ workplace, hostname, username, isoftlimit * 2);
+
+ if ((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE)) > 0) {
+ close(fd);
+ abort_printf("Not allowd to exceed the hard limit of inodes.\n");
+ }
+
+ /*cleanup*/
+ seteuid(o_uid);
+ for (i = 0; i < isoftlimit * 2; i++) {
+ snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%d",
+ workplace, hostname, username, i);
+ if (!(i % 2)) {
+ ret = unlink(filename);
+ if (ret < 0) {
+ ret =errno;
+ abort_printf("Failed to unlink file(%s):%d:%s\n",
+ filename, ret, strerror(ret));
+ }
+ } else {
+ ret = rmdir(filename);
+ if (ret < 0) {
+ ret = errno;
+ abort_printf("Failed to remove dir(%s):%d:%s.\n",
+ filename, ret, strerror(ret));
+ }
+ }
+
+ }
+
+ add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL);
+}
+
+static void group_space_limit_test(long isoftlimit, long bsoftlimit,
+ long user_num, int grp_postfix)
+{
+ int ret, fd;
+ long i, j;
+ int o_uid, o_gid;
+ struct if_dqblk s_dq, d_dq;
+
+ char username[USERNAME_SZ], groupname[GROUPNAME_SZ];
+ char *write_buf;
+ int writen_sz, user_index;
+ long file_sz = 0, count = 0;
+
+ write_buf = (char *)malloc(clustersize);
+ memset(write_buf, 0, clustersize);
+
+ snprintf(groupname, GROUPNAME_SZ, "quotagroup-rank%d-%d", rank,
+ grp_postfix);
+ add_rm_user_group(GROUPADD_BIN, ADD, GROUP, groupname, NULL);
+ getquota(QUOTAGROUP, device, name2id(GROUP, groupname), &s_dq);
+ s_dq.dqb_isoftlimit = isoftlimit;
+ s_dq.dqb_ihardlimit = isoftlimit * 2;
+ s_dq.dqb_bsoftlimit = bsoftlimit;
+ s_dq.dqb_bhardlimit = bsoftlimit * 2;
+ s_dq.dqb_curinodes = 0;
+ s_dq.dqb_curspace = 0;
+ setquota(QUOTAGROUP, device, name2id(GROUP, groupname), s_dq);
+
+ o_gid = getgid();
+ setegid(name2id(GROUP, groupname));
+
+ for (i = 0; i < user_num; i++) {
+ snprintf(username, USERNAME_SZ, "%s-quotauser-%d", groupname, i);
+ add_rm_user_group(USERADD_BIN, ADD, USER_IN_GROUP, username,
+ groupname);
+ getquota(QUOTAUSER, device, name2id(USER, username), &s_dq);
+ s_dq.dqb_isoftlimit = isoftlimit;
+ s_dq.dqb_ihardlimit = isoftlimit * 2;
+ s_dq.dqb_bsoftlimit = bsoftlimit;
+ s_dq.dqb_bhardlimit = bsoftlimit * 2;
+ s_dq.dqb_curinodes = 0;
+ s_dq.dqb_curspace = 0;
+ setquota(QUOTAUSER, device, name2id(USER, username), s_dq);
+
+ o_uid = getuid();
+ seteuid(name2id(USER, username));
+
+ snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-group-spacelimit",
+ workplace, hostname, username);
+ fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE);
+ if (fd < 0)
+ abort_printf("Create file failed:%d:%s.\n", ret, strerror(ret));
+ close(fd);
+ seteuid(o_uid);
+ }
+
+ while (file_sz + clustersize <= bsoftlimit * 2 * 1024) {
+ user_index = count % user_num;
+ snprintf(username, USERNAME_SZ, "%s-quotauser-%d", groupname, user_index);
+ snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-group-spacelimit",
+ workplace, hostname, username);
+ o_uid = getuid();
+ seteuid(name2id(USER, username));
+ fd = open(filename, O_RDWR | O_APPEND, FILE_MODE);
+ writen_sz = write(fd, write_buf, clustersize);
+ if (writen_sz < 0) {
+ ret = errno;
+ abort_printf("write failed:%d:%s.\n", ret, strerror(ret));
+ }
+ close(fd);
+ seteuid(o_uid);
+ file_sz += writen_sz;
+ count++;
+ }
+
+ user_index = count % user_num;
+ snprintf(username, USERNAME_SZ, "%s-quotauser-%d", groupname, user_index);
+ snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-group-spacelimit",
+ workplace, hostname, username);
+ o_uid = getuid();
+ seteuid(name2id(USER, username));
+ fd = open(filename, O_RDWR | O_APPEND, FILE_MODE);
+ if ((writen_sz = write(fd, write_buf, clustersize)) > 0)
+ abort_printf("Not allowed to exceed space hard limit of group.");
+
+ close(fd);
+ seteuid(o_uid);
+ setegid(o_gid);
+
+ for (i = 0; i < user_num; i++) {
+ snprintf(username, USERNAME_SZ, "%s-quotauser-%d", groupname, i);
+ snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-group-spacelimit",
+ workplace, hostname, username);
+ ret = unlink(filename);
+ if (ret < 0) {
+ ret = errno;
+ abort_printf("Failed to unlink file %s:%d:%s.\n",
+ filename, ret, strerror(ret));
+ }
+ add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL);
+ }
+
+ sync();
+
+ add_rm_user_group(GROUPDEL_BIN, REMOVE, GROUP, groupname, NULL);
+
+ if (write_buf)
+ free(write_buf);
+}
+
+static void group_inodes_limit_test(long isoftlimit, long bsoftlimit,
+ long user_num, int grp_postfix)
+{
+ int ret, fd;
+ long i, j;
+ int o_uid, o_gid;
+ int user_index;
+ struct if_dqblk s_dq, d_dq;
+
+ char username[USERNAME_SZ], groupname[GROUPNAME_SZ];
+
+ snprintf(groupname, GROUPNAME_SZ, "quotagroup-rank%d-%d", rank,
+ grp_postfix);
+ add_rm_user_group(GROUPADD_BIN, ADD, GROUP, groupname, NULL);
+
+ getquota(QUOTAGROUP, device, name2id(GROUP, groupname), &s_dq);
+ s_dq.dqb_isoftlimit = isoftlimit;
+ s_dq.dqb_ihardlimit = isoftlimit * 2;
+ s_dq.dqb_bsoftlimit = bsoftlimit;
+ s_dq.dqb_bhardlimit = bsoftlimit * 2;
+ s_dq.dqb_curinodes = 0;
+ s_dq.dqb_curspace = 0;
+ setquota(QUOTAGROUP, device, name2id(GROUP, groupname), s_dq);
+
+ for (i = 0; i < user_num; i++) {
+ snprintf(username, USERNAME_SZ, "%s-quotauser-%d", groupname, i);
+ add_rm_user_group(USERADD_BIN, ADD, USER_IN_GROUP, username,
+ groupname);
+ getquota(QUOTAUSER, device, name2id(USER, username), &s_dq);
+ s_dq.dqb_isoftlimit = isoftlimit;
+ s_dq.dqb_ihardlimit = isoftlimit * 2;
+ s_dq.dqb_bsoftlimit = bsoftlimit;
+ s_dq.dqb_bhardlimit = bsoftlimit * 2;
+ s_dq.dqb_curinodes = 0;
+ s_dq.dqb_curspace = 0;
+ setquota(QUOTAUSER, device, name2id(USER, username), s_dq);
+ }
+
+ o_gid = getgid();
+ setegid(name2id(GROUP, groupname));
+
+ for (i = 0; i < isoftlimit * 2; i++) {
+ user_index = i % user_num;
+ snprintf(username, USERNAME_SZ, "%s-quotauser-%d", groupname,
+ user_index);
+ snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%d",
+ workplace, hostname, username, i);
+ o_uid = getuid();
+ seteuid(name2id(USER, username));
+ fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE);
+ if (fd < 0) {
+ ret = errno;
+ abort_printf("Open %d file failed:%d:%s\n", i, ret, strerror(ret));
+ }
+
+ close(fd);
+ seteuid(o_uid);
+
+ getquota(QUOTAGROUP, device, name2id(GROUP, groupname), &d_dq);
+ if (d_dq.dqb_curinodes != i + 1)
+ abort_printf("Incorrect quota stats found,expected "
+ "inode_num = %d,queried inode_num = %d.\n",
+ i + 1, d_dq.dqb_curinodes);
+ }
+
+ /*We definitely should hit falure here*/
+ user_index = (isoftlimit * 2) % user_num;
+ snprintf(username, USERNAME_SZ, "%s-quotauser-%d", groupname, user_index);
+ snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%d",
+ workplace, hostname, username, isoftlimit * 2);
+ o_uid = getuid();
+ seteuid(name2id(USER, username));
+ if ((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE)) > 0) {
+ close(fd);
+ abort_printf("Not allowd to exceed the hard limit of inodes.\n");
+ }
+
+ seteuid(o_uid);
+ setegid(o_gid);
+
+ /*cleanup*/
+ for (i = 0; i < isoftlimit * 2; i++) {
+ user_index = i % user_num;
+ snprintf(username, USERNAME_SZ, "%s-quotauser-%d", groupname,
+ user_index);
+ snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%d",
+ workplace, hostname, username, i);
+ ret = unlink(filename);
+ if (ret < 0) {
+ ret =errno;
+ abort_printf("Failed to unlink file(%s):%d:%s\n",
+ filename, ret, strerror(ret));
+ }
+
+ }
+
+ for (i = 0; i < user_num; i++) {
+ snprintf(username, USERNAME_SZ, "%s-quotauser-%d", groupname, i);
+ add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL);
+ }
+
+ add_rm_user_group(GROUPDEL_BIN, REMOVE, GROUP, groupname, NULL);
+}
+
+static int quota_corrupt_test(long isoftlimit, long bsoftlimit, int user_postfix)
+{
+ int ret, fd;
+ long i, j;
+ int o_uid, o_gid;
+ int user_index;
+ struct if_dqblk s_dq, d_dq;
+
+ char username[USERNAME_SZ], groupname[GROUPNAME_SZ];
+
+ snprintf(username, USERNAME_SZ, "quotauser-rank%d-%d", rank,
+ user_postfix);
+ add_rm_user_group(USERADD_BIN, ADD, USER, username, NULL);
+
+ getquota(QUOTAUSER, device, name2id(USER, username), &s_dq);
+ s_dq.dqb_isoftlimit = isoftlimit;
+ s_dq.dqb_ihardlimit = isoftlimit * 2;
+ s_dq.dqb_bsoftlimit = bsoftlimit;
+ s_dq.dqb_bhardlimit = bsoftlimit * 2;
+ s_dq.dqb_curinodes = 0xFFFFFFFFFFFFFFFF;
+ s_dq.dqb_curspace = 0xFFFFFFFFFFFFFFFF;
+ setquota(QUOTAUSER, device, name2id(USER, username), s_dq);
+
+ o_uid = getuid();
+ ret = seteuid(name2id(USER, username));
+
+ for (i = 0; i < isoftlimit; i++) {
+ snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%d",
+ workplace, hostname, username, i);
+
+ fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE);
+ if (fd < 0) {
+ ret = errno;
+ abort_printf("Open file failed:%d:%s\n", ret, strerror(ret));
+ }
+
+ close(fd);
+ }
+
+ /*
+ * After a while, we check if the curinodes and curspace
+ * get synced to be correct.
+ */
+ sleep(5);
+ seteuid(o_uid);
+ getquota(QUOTAUSER, device, name2id(USER, username), &d_dq);
+
+ if (d_dq.dqb_curinodes != isoftlimit)
+ abort_printf("Quota corrupt test failed.expected inode_nums = "
+ "%ld, while queried inode_nums = %ld.\n", isoftlimit,
+ d_dq.dqb_curinodes);
+
+ for (i = 0; i < isoftlimit; i++) {
+ snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%d",
+ workplace, hostname, username, i);
+ ret = unlink(filename);
+ if (ret < 0) {
+ ret = errno;
+ abort_printf("Unlink file %s failed:%d:%s.\n",
+ filename, ret, strerror(ret));
+ }
+ }
+
+ add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL);
+}
+
+static int concurrent_rw_test(long isoftlimit, long bsoftlimit,
+ long user_postfix)
+{
+ int ret, fd, o_uid, j;
+ long i, file_index, writen_size = 0;
+ struct if_dqblk s_dq, d_dq;
+ char username[USERNAME_SZ];
+ char *write_buf;
+
+ MPI_Request request;
+ MPI_Status status;
+
+ if (!rank) {
+
+ snprintf(username, USERNAME_SZ, "quota-user-rank%d-%d", rank,
+ user_postfix);
+
+ add_rm_user_group(USERADD_BIN, ADD, USER, username, NULL);
+ getquota(QUOTAUSER, device, name2id(USER, username), &s_dq);
+ s_dq.dqb_isoftlimit = isoftlimit;
+ s_dq.dqb_ihardlimit = isoftlimit * 2;
+ s_dq.dqb_bsoftlimit = bsoftlimit;
+ s_dq.dqb_bhardlimit = bsoftlimit * 2;
+ s_dq.dqb_curinodes = 0;
+ s_dq.dqb_curspace = 0;
+ setquota(QUOTAUSER, device, name2id(USER, username), s_dq);
+
+ } else
+ snprintf(username, USERNAME_SZ, "quota-user-rank0-%d",
+ user_postfix);
+ if (!rank) {
+ o_uid = getuid();
+ seteuid(name2id(USER, username));
+ snprintf(filename, PATH_SZ, "%s/%s-quotafile", workplace, username);
+ fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE);
+ if (fd < 0) {
+ ret = errno;
+ abort_printf("Open file failed:%d:%s\n", ret, strerror(ret));
+ }
+ close(fd);
+ seteuid(o_uid);
+ }
+
+ MPI_Barrier_Sync();
+
+ if (!rank) {
+ for (i = 1; i < size; i++) {
+ ret = MPI_Irecv(&writen_size, sizeof(long),
+ MPI_BYTE, i, 1, MPI_COMM_WORLD, &request);
+ if (ret != MPI_SUCCESS)
+ abort_printf("MPI_Irecv faile.\n");
+ MPI_Wait(&request, &status);
+ printf("write_size = %ld, received.\n", writen_size);
+ getquota(QUOTAUSER, device, name2id(USER, username), &d_dq);
+ if (d_dq.dqb_curspace != writen_size)
+ abort_printf("Concurrent test failed among nodes,"
+ "Incorrect space stats found, expected "
+ "space usage = %ld, queried space usage "
+ "= %ld.\n", writen_size, d_dq.dqb_curspace);
+ }
+ } else {
+ snprintf(filename, PATH_SZ, "%s/%s-quotafile", workplace,
+ username);
+ fd = open(filename, O_RDWR);
+ i = get_rand(0, rank);
+ write_buf = (char *)malloc(clustersize * i);
+ memset(write_buf, 0, clustersize * i);
+ writen_size = pwrite(fd, write_buf, clustersize * i, 0);
+ if (writen_size < 0) {
+ ret = errno;
+ abort_printf("pwrite failed:%d:%s.\n", ret, strerror(ret));
+ }
+ printf("write_size = %ld, sent.\n", writen_size);
+
+ ret = MPI_Isend(&writen_size, sizeof(long), MPI_BYTE, 0, 1,
+ MPI_COMM_WORLD, &request);
+ if (ret != MPI_SUCCESS)
+ abort_printf("MPI_Isend failed.\n");
+ MPI_Wait(&request, &status);
+
+ }
+
+ MPI_Barrier_Sync();
+
+ if(!rank) {
+ ret = unlink(filename);
+ if (ret < 0) {
+ ret = errno;
+ abort_printf("Unlink file failed:%d:%s\n", ret, strerror(ret));
+ }
+
+ add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL);
+ }
+}
+
+static int run_tests(void)
+{
+ int ret;
+ int i;
+ int fd;
+ int o_uid, o_gid;
+ struct if_dqblk s_dq, d_dq;
+
+ char username[USERNAME_SZ], groupname[GROUPNAME_SZ];
+
+ MPI_Barrier_Sync();
+ root_printf("Test %d:Set/Get quota for one user/group among nodes. \n", testno);
+ snprintf(username, USERNAME_SZ, "quotauser-%d", rank);
+ add_rm_user_group(USERADD_BIN, ADD, USER, username, NULL);
+
+ getquota(QUOTAUSER, device, name2id(USER, username), &s_dq);
+ s_dq.dqb_isoftlimit = 10000;
+ s_dq.dqb_ihardlimit = 20000;
+ s_dq.dqb_bsoftlimit = 1024 * 1024 * 10;
+ s_dq.dqb_bhardlimit = 1024 * 1024 * 20;
+ setquota(QUOTAUSER, device, name2id(USER, username), s_dq);
+ getquota(QUOTAUSER, device, name2id(USER, username), &d_dq);
+ verify_quota_items(s_dq, d_dq, ISOFT_LIMIT | IHARD_LIMIT | BSOFT_LIMIT | BHARD_LIMIT);
+ add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL);
+
+ snprintf(groupname, GROUPNAME_SZ, "quotagroup-%d", rank);
+ add_rm_user_group(GROUPADD_BIN, ADD, GROUP, groupname, NULL);
+
+ getquota(QUOTAGROUP, device, name2id(GROUP, groupname), &s_dq);
+ s_dq.dqb_isoftlimit = 20000;
+ s_dq.dqb_ihardlimit = 40000;
+ s_dq.dqb_bsoftlimit = 1024 * 1024 * 10;
+ s_dq.dqb_bhardlimit = 1024 * 1024 * 20;
+ setquota(QUOTAGROUP, device, name2id(GROUP, groupname), s_dq);
+ getquota(QUOTAGROUP, device, name2id(GROUP, groupname), &d_dq);
+ verify_quota_items(s_dq, d_dq, ISOFT_LIMIT | IHARD_LIMIT | BSOFT_LIMIT | BHARD_LIMIT);
+ add_rm_user_group(GROUPDEL_BIN, REMOVE, GROUP, groupname, NULL);
+ testno++;
+
+ MPI_Barrier_Sync();
+ root_printf("Test %d:Quota inodes limit test for users/groups among nodes.\n", testno);
+ user_inodes_limit_test(100, 1024 * 1024 * 10, 1);
+ MPI_Barrier_Sync();
+ group_inodes_limit_test(100, 1024 * 1024 * 10, 4, 1);
+ testno++;
+
+ MPI_Barrier_Sync();
+ root_printf("Test %d:Quota space limit test for users/groups among nodes.\n", testno);
+ user_space_limit_test(100, 1024 * 256, 1);
+ MPI_Barrier_Sync();
+ group_space_limit_test(100, 1024 * 256, 4, 1);
+ testno++;
+
+ MPI_Barrier_Sync();
+ root_printf("Test %d:Quota grace time test among nodes.\n", testno);
+ user_inodes_grace_time_test(100, 1024 * 256, 10, 1);
+ testno++;
+
+ MPI_Barrier_Sync();
+ root_printf("Test %d:Huge user number test among nodes.\n", testno);
+ for (i = 0; i < user_nums; i++)
+ user_inodes_limit_test(100, 1024 * 1024 * 2, i);
+ testno++;
+
+ MPI_Barrier_Sync();
+ root_printf("Test %d:Huge group number test among nodes.\n", testno);
+ for (i = 0; i < group_nums; i++)
+ group_inodes_limit_test(100, 1024 * 1024 * 2, 4, i);
+ testno++;
+
+ MPI_Barrier_Sync();
+ root_printf("Test %d:Stress test with intensive quota operations for user/group.\n", testno);
+ for (i = 0; i < user_nums; i++) {
+ user_inodes_limit_test(100, 1024 * 1024, i);
+ MPI_Barrier_Sync();
+ group_inodes_limit_test(100, 1024 *1024, 8, i);
+ }
+ testno++;
+
+ MPI_Barrier_Sync();
+ root_printf("Test %d:Negative and positive quota test.\n", testno);
+ negative_inodes_limit_test(100, 1024 * 1024, 1, 10);
+ testno++;
+
+ MPI_Barrier_Sync();
+ root_printf("Test %d:Concurrent file r/w test.\n", testno);
+ concurrent_rw_test(100, 1024 * 1024, 1);
+ testno++;
+
+ MPI_Barrier_Sync();
+ root_printf("Test %d:Quota corruption test.\n", testno);
+ quota_corrupt_test(100, 1024 * 1024, 1);
+ testno++;
+
+}
+
+static int setup(int argc, char *argv[])
+{
+ unsigned long i;
+ int ret;
+ int o_umask;
+
+ ret = MPI_Init(&argc, &argv);
+ if (ret != MPI_SUCCESS) {
+ log_printf(stderr, "MPI_Init failed: %d\n", ret);
+ exit(1);
+ }
+
+ if (gethostname(hostname, HOSTNAME_MAX_SZ) < 0)
+ abort_printf("get hostname!\n");
+
+ ret = MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+ if (ret != MPI_SUCCESS)
+ abort_printf("MPI_Comm_rank failed: %d\n", ret);
+
+ ret = MPI_Comm_size(MPI_COMM_WORLD, &size);
+ if (ret != MPI_SUCCESS)
+ abort_printf("MPI_Comm_size failed: %d\n", ret);
+
+
+ prog = strrchr(argv[0], '/');
+ if (prog == NULL)
+ prog = argv[0];
+ else
+ prog++;
+
+ if (parse_opts(argc, argv))
+ usage();
+
+ if (geteuid())
+ abort_printf("You have to be root to run this program.\n");
+
+ snprintf(workplace, PATH_SZ, "%s/%s", mountpoint, WORKPLACE);
+ if (rank == 0) {
+ o_umask = umask(0);
+ mkdir(workplace, FILE_MODE);
+ root_printf("Device:\t\t%s\nMountpoint:\t%s\n"
+ "Iterations:\t\t%d\nUsers:\t\t%d\nGroups:"
+ "\t\t%d\n\n", device, mountpoint,
+ iterations, user_nums, group_nums);
+ umask(o_umask);
+ }
+
+ open_ocfs2_volume(device);
+
+ MPI_Barrier_Sync();
+
+ quota_on_off(QUOTAON_BIN, 1, QUOTAUSER|QUOTAGROUP, mountpoint);
+}
+
+static int teardown(void)
+{
+ if (rank == 0)
+ rmdir(workplace);
+
+ MPI_Barrier_Sync();
+ quota_on_off(QUOTAON_BIN, 0, QUOTAUSER|QUOTAGROUP, mountpoint);
+
+ MPI_Finalize();
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int i;
+
+ setup(argc, argv);
+ for (i = 0; i < iterations; i++)
+ run_tests();
+
+ teardown();
+ return 0;
+}
--
1.5.5
More information about the Ocfs2-test-devel
mailing list