<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html;charset=UTF-8" http-equiv="Content-Type">
</head>
<body bgcolor="#ffffcc" text="#000066">
<tt>Signed-off-by: Marcos Matsunaga <a class="moz-txt-link-rfc2396E" href="mailto:Marcos.Matsunaga@oracle.com">&lt;Marcos.Matsunaga@oracle.com&gt;</a></tt><br>
<pre class="moz-signature" cols="72">Regards,

Marcos Eduardo Matsunaga

Oracle USA
Linux Engineering

“The statements and opinions expressed here are my own and do not
necessarily represent those of Oracle Corporation.”
</pre>
<br>
<br>
Tristan Ye wrote:
<blockquote
 cite="mid:1229994000-32219-4-git-send-email-tristan.ye@oracle.com"
 type="cite">
  <pre wrap="">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 <a class="moz-txt-link-rfc2396E" href="mailto:tristan.ye@oracle.com">&lt;tristan.ye@oracle.com&gt;</a>
---
 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 (<a class="moz-txt-link-abbreviated" href="mailto:tristan.ye@oracle.com">tristan.ye@oracle.com</a>)
+ *
+ * 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 &lt;stdio.h&gt;
+#include &lt;stdlib.h&gt;
+#include &lt;unistd.h&gt;
+#include &lt;fcntl.h&gt;
+#include &lt;sys/types.h&gt;
+#include &lt;limits.h&gt;
+#include &lt;errno.h&gt;
+#include &lt;string.h&gt;
+#include &lt;sys/stat.h&gt;
+#include &lt;stdarg.h&gt;
+#include &lt;sys/xattr.h&gt;
+#include &lt;dirent.h&gt;
+#include &lt;sys/wait.h&gt;
+#include &lt;signal.h&gt;
+#include &lt;mpi.h&gt;
+#include &lt;pwd.h&gt;
+#include &lt;grp.h&gt;
+
+#include &lt;ocfs2/ocfs2.h&gt;
+
+#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] "
+               "&lt;-d device&gt; &lt;mount_point&gt;\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-&gt;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-&gt;gr_gid;
+                return ret;
+        }
+
+}
+
+static int name2id(int type, char *name)
+{
+        if (type &amp; USER)
+                return user2uid(name);
+        if (type &amp; 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, &amp;fs);
+        if (ret &lt; 0) {
+                fprintf(stderr, "%s is not a ocfs2 volume!\n", device_name);
+                return ret;
+        }
+
+        ocfs2_sb = OCFS2_RAW_SB(fs-&gt;fs_super);
+        blocksize = 1 &lt;&lt; ocfs2_sb-&gt;s_blocksize_bits;
+        clustersize = 1 &lt;&lt; ocfs2_sb-&gt;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 &amp; QUOTAUSER) &amp;&amp; !(type &amp; 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 &lt; 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 &amp; USER) {
+                        if (ad_or_rm &amp; ADD)
+                                strcpy(arg1, "-m");
+                        else
+                                strcpy(arg1, "-r");
+                        argv[1] = arg1;
+                        argv[2] = (char *)name;
+                        argv[3] = NULL;
+                        
+                } else if (usr_or_grp &amp; GROUP) {
+                        argv[1] = (char *)name;
+                        argv[2] = NULL;
+                } else if (usr_or_grp &amp; 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, &amp;child_status, 0);
+                if (ret &lt; 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 &lt; 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 &amp; QUOTAUSER)
+                        strcat(arg1, "u");
+                if (type &amp; 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, &amp;child_status, 0);
+                if (ret &lt; 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 &amp; QUOTAUSER)
+                q_type = USRQUOTA;
+        else
+                q_type = GRPQUOTA;
+
+        if (quotactl(QCMD(Q_SETINFO, q_type), device, id, (caddr_t) &amp; 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 &amp; QUOTAUSER)
+                q_type = USRQUOTA;
+        else
+                q_type = GRPQUOTA;
+
+        if (quotactl(QCMD(Q_SETQUOTA, q_type), device, id, (caddr_t) &amp; 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 &amp; 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 &amp; 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 &amp; 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 &amp; 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 &amp; 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 &amp; 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 &amp;&amp; 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), &amp;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 &lt; 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 &lt; 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 &lt; size; j++) {
+                        for (i = 0; i &lt; rm_nums; i++) {
+                                ret = MPI_Irecv(&amp;file_index, sizeof(long),
+                                                MPI_BYTE, j, 1, MPI_COMM_WORLD,
+                                                &amp;request);
+                                
+                                if (ret == MPI_SUCCESS) {
+                                        rm_counts++;
+                                        inodes_removed[file_index] = 1;
+                                }
+                                else
+                                        abort_printf("MPI_Irecv Failed.\n");
+                                MPI_Wait(&amp;request, &amp;status);
+                        }
+                }
+
+                getquota(QUOTAUSER, device, name2id(USER, username), &amp;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 &lt; 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 &lt; 0)
+                                continue;
+                        else {
+                                ret = MPI_Isend(&amp;i, sizeof(long), MPI_BYTE,
+                                                0, 1, MPI_COMM_WORLD, &amp;request);
+                                if (ret != MPI_SUCCESS)
+                                        abort_printf("MPI_Isend Failed.\n");
+                                MPI_Wait(&amp;request, &amp;status);
+                                rm_counts++;
+                        }
+                }
+        }
+
+        MPI_Barrier_Sync();
+        /* Cleanup */
+
+        if (!rank) {
+                file_index = 0;
+                while (file_index &lt; 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), &amp;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), &amp;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 &lt;= 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 &lt; 0) {
+                        ret = errno;
+                        abort_printf("Open file failed:%d:%s\n", ret, strerror(ret));
+                }
+
+                close(fd);
+                getquota(QUOTAUSER, device, name2id(USER, username), &amp;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)) &gt; 0) {
+                close(fd);
+                abort_printf("Not allowd to exceed the grace time limit of inodes.\n");
+        }
+
+        /*cleanup*/
+        seteuid(o_uid);
+
+        for (i = 0; i &lt;= isoftlimit; i++) {
+                snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%d",
+                         workplace, hostname, username, i);
+                ret = unlink(filename);
+                if (ret &lt; 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), &amp;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 &lt; 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 &lt;= bsoftlimit * 2 * 1024) {
+                writen_sz = write(fd, write_buf, clustersize);
+                if (writen_sz &lt; 0) {
+                        ret = errno;
+                        abort_printf("write failed:%d:%s.\n", ret, strerror(ret));
+                }
+                file_sz += writen_sz;
+        }
+
+        if ((ret = write(fd, write_buf, clustersize)) &gt; 0)
+                abort_printf("No allowed to exceed the hard limit of space");
+
+        if (fd)
+                close(fd);
+
+        ret = unlink(filename);
+        if (ret &lt; 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), &amp;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 &lt; 0) {
+                ret = errno;
+                abort_printf("Set euid failed:%d:%s.\n", ret, strerror(ret));
+        }
+
+        for (i = 0; i &lt; 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 &lt; 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), &amp;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)) &gt; 0) {
+                close(fd);
+                abort_printf("Not allowd to exceed the hard limit of inodes.\n");
+        }
+
+        /*cleanup*/
+        seteuid(o_uid);
+        for (i = 0; i &lt; isoftlimit * 2; i++) {
+                snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%d",
+                         workplace, hostname, username, i);
+                if (!(i % 2)) {
+                        ret = unlink(filename);
+                        if (ret &lt; 0) {
+                                ret =errno;
+                                abort_printf("Failed to unlink file(%s):%d:%s\n",
+                                             filename, ret, strerror(ret));
+                        }
+                } else {
+                        ret = rmdir(filename);
+                        if (ret &lt; 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), &amp;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 &lt; 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), &amp;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 &lt; 0)
+                        abort_printf("Create file failed:%d:%s.\n", ret, strerror(ret));
+                close(fd);
+                seteuid(o_uid);
+        }
+
+        while (file_sz + clustersize &lt;= 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 &lt; 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)) &gt; 0)
+                abort_printf("Not allowed to exceed space hard limit of group.");
+
+        close(fd);
+        seteuid(o_uid);
+        setegid(o_gid);
+
+        for (i = 0; i &lt; 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 &lt; 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), &amp;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 &lt; 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), &amp;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 &lt; 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 &lt; 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), &amp;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)) &gt; 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 &lt; 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 &lt; 0) {
+                        ret =errno;
+                        abort_printf("Failed to unlink file(%s):%d:%s\n",
+                                     filename, ret, strerror(ret));
+                }
+
+        }
+        
+        for (i = 0; i &lt; 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), &amp;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 &lt; 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 &lt; 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), &amp;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 &lt; isoftlimit; i++) {
+                snprintf(filename, PATH_SZ, "%s/%s-%s-quotafile-%d",
+                         workplace, hostname, username, i);
+                ret = unlink(filename);
+                if (ret &lt; 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), &amp;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 &lt; 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 &lt; size; i++) {
+                        ret = MPI_Irecv(&amp;writen_size, sizeof(long),
+                                        MPI_BYTE, i, 1, MPI_COMM_WORLD, &amp;request);
+                        if (ret != MPI_SUCCESS)
+                                abort_printf("MPI_Irecv faile.\n");
+                        MPI_Wait(&amp;request, &amp;status);
+                        printf("write_size = %ld, received.\n", writen_size);
+                        getquota(QUOTAUSER, device, name2id(USER, username), &amp;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 &lt; 0) {
+                        ret = errno;
+                        abort_printf("pwrite failed:%d:%s.\n", ret, strerror(ret));
+                }
+                printf("write_size = %ld, sent.\n", writen_size);
+                
+                ret = MPI_Isend(&amp;writen_size, sizeof(long), MPI_BYTE, 0, 1,
+                                MPI_COMM_WORLD, &amp;request);
+                if (ret != MPI_SUCCESS)
+                        abort_printf("MPI_Isend failed.\n");
+                MPI_Wait(&amp;request, &amp;status);
+                
+        }
+
+        MPI_Barrier_Sync();
+
+        if(!rank) {
+                ret = unlink(filename);
+                if (ret &lt; 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), &amp;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), &amp;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), &amp;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), &amp;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 &lt; 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 &lt; 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 &lt; 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(&amp;argc, &amp;argv);
+        if (ret != MPI_SUCCESS) {
+                log_printf(stderr, "MPI_Init failed: %d\n", ret);
+                exit(1);
+        }
+
+        if (gethostname(hostname, HOSTNAME_MAX_SZ) &lt; 0)
+                abort_printf("get hostname!\n");
+
+        ret = MPI_Comm_rank(MPI_COMM_WORLD, &amp;rank);
+        if (ret != MPI_SUCCESS)
+                abort_printf("MPI_Comm_rank failed: %d\n", ret);
+
+        ret = MPI_Comm_size(MPI_COMM_WORLD, &amp;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 &lt; iterations; i++)
+                run_tests();
+
+        teardown();
+        return 0;
+}
  </pre>
</blockquote>
</body>
</html>