static void group_inodes_limit_test(long isoftlimit, long bsoftlimit, long user_num, int grp_postfix) { int ret, fd; long i; 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-%ld", 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-%ld", 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-%ld", 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-%ld", 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-%ld", groupname, i); add_rm_user_group(USERDEL_BIN, REMOVE, USER, username, NULL); } add_rm_user_group(GROUPDEL_BIN, REMOVE, GROUP, groupname, NULL); }
/* * Do operations associated with quotas */ int ufs_quotactl(struct mount *mp, int cmds, uid_t uid, void *arg) { struct lwp *l = curlwp; #ifndef QUOTA (void) mp; (void) cmds; (void) uid; (void) arg; (void) l; return (EOPNOTSUPP); #else int cmd, type, error; if (uid == -1) uid = kauth_cred_getuid(l->l_cred); cmd = cmds >> SUBCMDSHIFT; switch (cmd) { case Q_SYNC: break; case Q_GETQUOTA: if (uid == kauth_cred_getuid(l->l_cred)) break; /* fall through */ default: if ((error = kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, NULL)) != 0) return (error); } type = cmds & SUBCMDMASK; if ((u_int)type >= MAXQUOTAS) return (EINVAL); error = vfs_busy(mp, NULL); if (error != 0) return (error); mutex_enter(&mp->mnt_updating); switch (cmd) { case Q_QUOTAON: error = quotaon(l, mp, type, arg); break; case Q_QUOTAOFF: error = quotaoff(l, mp, type); break; case Q_SETQUOTA: error = setquota(mp, uid, type, arg); break; case Q_SETUSE: error = setuse(mp, uid, type, arg); break; case Q_GETQUOTA: error = getquota(mp, uid, type, arg); break; case Q_SYNC: error = qsync(mp); break; default: error = EINVAL; } mutex_exit(&mp->mnt_updating); vfs_unbusy(mp, false, NULL); return (error); #endif }
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-%ld", 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 = %ld,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-%ld", 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-%ld", 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 = 0, fd; long i; int o_uid, o_gid; struct if_dqblk s_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-%ld", 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-%ld", 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 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-%ld", 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-%ld", 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-%ld", 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-%ld", 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, fd; int o_uid; struct if_dqblk s_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 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 = NULL; 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-%ld", 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-%ld", 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-%ld", 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-%ld", 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-%ld", 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 run_tests(void) { int i; 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 void concurrent_rw_test(long isoftlimit, long bsoftlimit, long user_postfix) { int ret, fd, o_uid; long i, 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-%ld", 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-%ld", 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 void quota_corrupt_test(long isoftlimit, long bsoftlimit, int user_postfix) { int ret, fd; long i; 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 = 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-%ld", 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-%ld", 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); }
/*ARGSUSED*/ int quotactl(struct vnode *vp, intptr_t arg, int flag, struct cred *cr) { struct quotctl quot; struct ufsvfs *ufsvfsp; int error = 0; if ((flag & DATAMODEL_MASK) == DATAMODEL_NATIVE) { if (copyin((caddr_t)arg, ", sizeof (struct quotctl))) return (EFAULT); } #ifdef _SYSCALL32_IMPL else { /* quotctl struct from ILP32 callers */ struct quotctl32 quot32; if (copyin((caddr_t)arg, "32, sizeof (struct quotctl32))) return (EFAULT); quot.op = quot32.op; quot.uid = quot32.uid; quot.addr = (caddr_t)(uintptr_t)quot32.addr; } #endif /* _SYSCALL32_IMPL */ if (quot.uid < 0) quot.uid = crgetruid(cr); if (quot.op == Q_SYNC && vp == NULL) { ufsvfsp = NULL; } else if (quot.op != Q_ALLSYNC) { ufsvfsp = (struct ufsvfs *)(vp->v_vfsp->vfs_data); } switch (quot.op) { case Q_QUOTAON: rw_enter(&dq_rwlock, RW_WRITER); if (quotas_initialized == 0) { qtinit2(); quotas_initialized = 1; } rw_exit(&dq_rwlock); error = opendq(ufsvfsp, vp, cr); break; case Q_QUOTAOFF: error = closedq(ufsvfsp, cr); if (!error) { invalidatedq(ufsvfsp); } break; case Q_SETQUOTA: case Q_SETQLIM: error = setquota(quot.op, (uid_t)quot.uid, ufsvfsp, quot.addr, cr); break; case Q_GETQUOTA: error = getquota((uid_t)quot.uid, ufsvfsp, (caddr_t)quot.addr, cr); break; case Q_SYNC: error = qsync(ufsvfsp); break; case Q_ALLSYNC: (void) qsync(NULL); break; default: error = EINVAL; break; } return (error); }