+int t16(char *name)
+{
+ char file[MAX_PATH_LENGTH] = "";
+ ENTER("small-write-read");
+ snprintf(file, MAX_PATH_LENGTH, "%s/test_t16_file", lustre_path);
+
+ t_echo_create(file, "aaaaaaaaaaaaaaaaaaaaaa");
+ t_grep(file, "aaaaaaaaaaaaaaaaaaaaaa");
+ t_unlink(file);
+ LEAVE();
+}
+
+int t17(char *name)
+{
+ char file[MAX_PATH_LENGTH] = "";
+ int fd;
+ ENTER("open-unlink without close");
+ snprintf(file, MAX_PATH_LENGTH, "%s/test_t17_file", lustre_path);
+
+ fd = open(file, O_WRONLY | O_CREAT, 0666);
+ if (fd < 0) {
+ printf("failed to create file: %s\n", strerror(errno));
+ return(-1);
+ }
+ t_unlink(file);
+ LEAVE();
+}
+
+int t18(char *name)
+{
+ char file[MAX_PATH_LENGTH] = "";
+ char buf[128];
+ int fd, i;
+ struct stat statbuf[3];
+ ENTER("write should change mtime/ctime");
+ snprintf(file, MAX_PATH_LENGTH, "%s/test_t18_file", lustre_path);
+
+ for (i = 0; i < 3; i++) {
+ fd = open(file, O_RDWR|O_CREAT|O_APPEND, (mode_t)0666);
+ if (fd < 0) {
+ printf("error open file: %s\n", strerror(errno));
+ return(-1);
+ }
+ if (write(fd, buf, sizeof(buf)) != sizeof(buf)) {
+ printf("error write file\n");
+ return(-1);
+ }
+ close(fd);
+ if(stat(file, &statbuf[i]) != 0) {
+ printf("Error stat\n");
+ return(1);
+ }
+ printf("ctime %lu, mtime %lu\n",
+ statbuf[i].st_ctime, statbuf[i].st_mtime);
+ sleep(2);
+ }
+
+ for (i = 1; i < 3; i++) {
+ if ((statbuf[i].st_ctime <= statbuf[i-1].st_ctime) ||
+ (statbuf[i].st_mtime <= statbuf[i-1].st_mtime)) {
+ printf("time error\n");
+ return(-1);
+ }
+ }
+ t_unlink(file);
+ LEAVE();
+}
+
+int t18b(char *name)
+{
+ char file[MAX_PATH_LENGTH] = "";
+ int i;
+ struct stat statbuf[3];
+ ENTER("utime should change mtime/atime/ctime");
+ snprintf(file, MAX_PATH_LENGTH, "%s/test_t18b_file", lustre_path);
+ t_touch(file);
+
+ for (i = 0; i < 3; i++) {
+ t_utime(file, NULL);
+ if(stat(file, &statbuf[i]) != 0) {
+ printf("Error stat\n");
+ return(1);
+ }
+ printf("atime %lu, mtime %lu, ctime %lu\n",
+ statbuf[i].st_atime, statbuf[i].st_mtime,
+ statbuf[i].st_ctime);
+ sleep(2);
+ }
+
+ for (i = 1; i < 3; i++) {
+ if ((statbuf[i].st_atime <= statbuf[i-1].st_atime) ||
+ (statbuf[i].st_mtime <= statbuf[i-1].st_mtime) ||
+ (statbuf[i].st_ctime <= statbuf[i-1].st_ctime)) {
+ printf("time error\n");
+ return(-1);
+ }
+ }
+ t_unlink(file);
+ LEAVE();
+}
+
+static int check_file_size(char *file, long long size)
+{
+ struct stat statbuf;
+
+ if (stat(file, &statbuf) != 0) {
+ printf("Error stat(%s)\n", file);
+ return(1);
+ }
+ if (statbuf.st_size != size) {
+ printf("size of %s: %lld != %lld\n", file,
+ (long long)statbuf.st_size, (long long )size);
+ return(-1);
+ }
+ return 0;
+}
+
+int t19(char *name)
+{
+ char file[MAX_PATH_LENGTH] = "";
+ int fd;
+ int result;
+ ENTER("open(O_TRUNC) should truncate file to 0-length");
+ snprintf(file, MAX_PATH_LENGTH, "%s/test_t19_file", lustre_path);
+
+ t_echo_create(file, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+
+ fd = open(file, O_RDWR|O_CREAT|O_TRUNC, (mode_t)0666);
+ if (fd < 0) {
+ printf("error open file: %s\n", strerror(errno));
+ return(-1);
+ }
+ close(fd);
+ result = check_file_size(file, 0);
+ if (result != 0)
+ return result;
+ t_unlink(file);
+ LEAVE();
+}
+
+int t20(char *name)
+{
+ char file[MAX_PATH_LENGTH] = "";
+ int fd;
+ struct iovec iov[2];
+ char buf[100];
+ long ret;
+ ENTER("trap app's general bad pointer for file i/o");
+ snprintf(file, MAX_PATH_LENGTH, "%s/test_t20_file", lustre_path);
+
+ fd = open(file, O_RDWR|O_CREAT, (mode_t)0666);
+ if (fd < 0) {
+ printf("error open file: %s\n", strerror(errno));
+ return(-1);
+ }
+
+ ret = write(fd, NULL, 20);
+ if (ret != -1 || errno != EFAULT) {
+ printf("write 1: ret %lld, errno %d\n", (long long)ret, errno);
+ return(1);
+ }
+ ret = write(fd, (void *)-1, 20);
+ if (ret != -1 || errno != EFAULT) {
+ printf("write 2: ret %lld, errno %d\n", (long long)ret, errno);
+ return(1);
+ }
+ iov[0].iov_base = NULL;
+ iov[0].iov_len = 10;
+ iov[1].iov_base = (void *)-1;
+ iov[1].iov_len = 10;
+ ret = writev(fd, iov, 2);
+ if (ret != -1 || errno != EFAULT) {
+ printf("writev 1: ret %lld, errno %d\n", (long long)ret, errno);
+ return(1);
+ }
+ iov[0].iov_base = NULL;
+ iov[0].iov_len = 0;
+ iov[1].iov_base = buf;
+ iov[1].iov_len = sizeof(buf);
+ ret = writev(fd, iov, 2);
+ if (ret != sizeof(buf)) {
+ printf("writev 2: ret %lld, error %d\n", (long long)ret, errno);
+ return(1);
+ }
+ lseek(fd, 0, SEEK_SET);
+
+ ret = read(fd, NULL, 20);
+ if (ret != -1 || errno != EFAULT) {
+ printf("read 1: ret %lld, errno %d\n", (long long)ret, errno);
+ return(1);
+ }
+ ret = read(fd, (void *)-1, 20);
+ if (ret != -1 || errno != EFAULT) {
+ printf("read 2: ret %lld, error %d\n", (long long)ret, errno);
+ return(1);
+ }
+ iov[0].iov_base = NULL;
+ iov[0].iov_len = 10;
+ iov[1].iov_base = (void *)-1;
+ iov[1].iov_len = 10;
+ ret = readv(fd, iov, 2);
+ if (ret != -1 || errno != EFAULT) {
+ printf("readv 1: ret %lld, error %d\n", (long long)ret, errno);
+ return(1);
+ }
+ iov[0].iov_base = NULL;
+ iov[0].iov_len = 0;
+ iov[1].iov_base = buf;
+ iov[1].iov_len = sizeof(buf);
+ ret = readv(fd, iov, 2);
+ if (ret != sizeof(buf)) {
+ printf("readv 2: ret %lld, error %d\n", (long long)ret, errno);
+ return(1);
+ }
+
+ close(fd);
+ t_unlink(file);
+ LEAVE();
+}
+
+int t21(char *name)
+{
+ char file[MAX_PATH_LENGTH] = "";
+ int fd, ret;
+ struct flock lock = {
+ .l_type = F_RDLCK,
+ .l_whence = SEEK_SET,
+ };
+
+ ENTER("basic fcntl support");
+ snprintf(file, MAX_PATH_LENGTH, "%s/test_t21_file", lustre_path);
+
+ fd = open(file, O_RDWR|O_CREAT, (mode_t)0666);
+ if (fd < 0) {
+ printf("error open file: %s\n", file);
+ return(-1);
+ }
+
+ t_fcntl(fd, F_SETFL, O_APPEND);
+ ret = t_fcntl(fd, F_GETFL);
+ if ((ret & O_APPEND) == 0) {
+ printf("error get flag: ret %o\n", ret);
+ return(-1);
+ }
+
+ t_fcntl(fd, F_SETLK, &lock);
+ t_fcntl(fd, F_GETLK, &lock);
+ lock.l_type = F_WRLCK;
+ t_fcntl(fd, F_SETLKW, &lock);
+ t_fcntl(fd, F_GETLK, &lock);
+ lock.l_type = F_UNLCK;
+ t_fcntl(fd, F_SETLK, &lock);
+
+ close(fd);
+ t_unlink(file);
+ LEAVE();
+}
+
+int t22(char *name)
+{
+ char file[MAX_PATH_LENGTH] = "";
+ int fd;
+ char *str = "1234567890";
+ char buf[100];
+ long ret;
+ ENTER("make sure O_APPEND take effect");
+ snprintf(file, MAX_PATH_LENGTH, "%s/test_t22_file", lustre_path);
+
+ fd = open(file, O_TRUNC|O_RDWR|O_CREAT|O_APPEND, (mode_t)0666);
+ if (fd < 0) {
+ printf("error open file: %s\n", strerror(errno));
+ return(-1);
+ }
+
+ lseek(fd, 100, SEEK_SET);
+ ret = write(fd, str, strlen(str));
+ if (ret != strlen(str)) {
+ printf("write 1: ret %lld, errno %d\n", (long long)ret, errno);
+ return(1);
+ }
+
+ lseek(fd, 0, SEEK_SET);
+ ret = read(fd, buf, sizeof(buf));
+ if (ret != strlen(str)) {
+ printf("read 1: ret %lld\n", (long long)ret);
+ return(1);
+ }
+
+ if (memcmp(buf, str, strlen(str))) {
+ printf("read 1 data err\n");
+ return(1);
+ }
+
+ if (fcntl(fd, F_SETFL, 0)) {
+ printf("fcntl err: %s\n", strerror(errno));
+ return(1);
+ }
+
+ lseek(fd, 100, SEEK_SET);
+ ret = write(fd, str, strlen(str));
+ if (ret != strlen(str)) {
+ printf("write 2: ret %lld, errno %d\n", (long long)ret, errno);
+ return(1);
+ }
+
+ lseek(fd, 100, SEEK_SET);
+ ret = read(fd, buf, sizeof(buf));
+ if (ret != strlen(str)) {
+ printf("read 2: ret %lld\n", (long long)ret);
+ return(1);
+ }
+
+ if (memcmp(buf, str, strlen(str))) {
+ printf("read 2 data err\n");
+ return(1);
+ }
+
+ close(fd);
+ t_unlink(file);
+ LEAVE();
+}
+
+int t23(char *name)
+{
+ char path[MAX_PATH_LENGTH];
+ int fd;
+ long long ret;
+ loff_t off;
+
+ ENTER("handle seek > 2GB");
+ snprintf(path, MAX_PATH_LENGTH, "%s/f%s", lustre_path, name);
+
+ fd = open(path, O_WRONLY | O_CREAT | O_LARGEFILE, 0666);
+ if (fd < 0) {
+ printf("failed to create file %s: %s\n", path, strerror(errno));
+ return(-1);
+ }
+
+ off = 2048ULL * 1024 * 1024 - buf_size / 2;
+ ret = lseek(fd, off, SEEK_SET);
+ if (ret != off) {
+ printf("seek error for initial %llu != %llu\n",
+ ret, (long long)off);
+ return -1;
+ }
+
+ ret = write(fd, buf_alloc, buf_size);
+ if (ret != buf_size) {
+ printf("write error for %d != %llubytes @ %llu\n",
+ buf_size, ret, (long long)off);
+ if (ret == -1)
+ perror("write");
+ return -1;
+ }
+
+ ret = lseek(fd, off, SEEK_SET);
+ if (ret != off) {
+ printf("seek < 2GB error for %llu != %llu\n",
+ ret, (long long)off);
+ if (ret == -1)
+ perror("seek < 2GB");
+ return -1;
+ }
+
+ ret = lseek(fd, off + buf_size - 2, SEEK_SET);
+ if (ret != off + buf_size - 2) {
+ printf("seek > 2GB error for %llu != %llu\n",
+ ret, (long long)off);
+ if (ret == -1)
+ perror("seek > 2GB");
+ return -1;
+ }
+
+ ret = lseek(fd, -buf_size + 2, SEEK_CUR);
+ if (ret != off) {
+ printf("relative seek error for %d %llu != %llu\n",
+ -buf_size + 2, ret, (unsigned long long) off);
+ if (ret == -1)
+ perror("relative seek");
+ return -1;
+ }
+
+ ret = lseek(fd, 0, SEEK_END);
+ if (ret != off + buf_size) {
+ printf("end seek error for %llu != %llu\n",
+ ret, (long long)off + buf_size);
+ if (ret == -1)
+ perror("end seek");
+ return -1;
+ }
+
+ ret = lseek(fd, 0, SEEK_SET);
+ if (ret != 0) {
+ printf("seek 0 error for %llu != 0\n", ret);
+ if (ret == -1)
+ perror("seek 0");
+ return -1;
+ }
+
+ off = 2048ULL * 1024 * 1024, SEEK_SET;
+ ret = lseek(fd, off, SEEK_SET);
+ if (ret != off) {
+ printf("seek 2GB error for %llu != %llu\n", ret, (unsigned long long) off);
+ if (ret == -1)
+ perror("seek 2GB");
+ return -1;
+ }
+
+ close(fd);
+ t_unlink(path);
+ LEAVE();
+}
+
+/* pos: i/o start from
+ * xfer: npages per transfer
+ */
+static int pages_io(int xfer, loff_t pos)
+{
+ char path[MAX_PATH_LENGTH] = "";
+
+ int check_sum[_npages] = {0,}, *buf;
+ int fd, rc, i, j, data_error = 0;
+ struct timeval tw1, tw2, tr1, tr2;
+ double tw, tr;
+ loff_t ret;
+
+ snprintf(path, MAX_PATH_LENGTH, "%s/test_t50", lustre_path);
+
+ memset(buf_alloc, 0, buf_size);
+
+ /* create sample data */
+ for (i = 0, buf = buf_alloc; i < _npages; i++) {
+ for (j = 0; j < PAGE_CACHE_SIZE/sizeof(int); j++, buf++) {
+ *buf = rand();
+ }
+ }
+
+ /* compute checksum */
+ for (i = 0, buf = buf_alloc; i < _npages; i++) {
+ for (j = 0; j < PAGE_CACHE_SIZE/sizeof(int); j++, buf++) {
+ check_sum[i] += *buf;
+ }
+ }
+
+ unlink(path);
+ t_touch(path);
+
+ fd = t_open(path);
+
+ /* write */
+ ret = lseek(fd, pos, SEEK_SET);
+ if (ret != pos) {
+ perror("write seek");
+ return 1;
+ }
+ gettimeofday(&tw1, NULL);
+ for (i = 0, buf = buf_alloc; i < _npages;
+ i += xfer, buf += xfer * PAGE_CACHE_SIZE / sizeof(int)) {
+ rc = write(fd, buf, PAGE_CACHE_SIZE * xfer);
+ if (rc != PAGE_CACHE_SIZE * xfer) {
+ printf("write error (i %d, rc %d): %s\n", i, rc,
+ strerror(errno));
+ return(1);
+ }
+ }
+ gettimeofday(&tw2, NULL);
+
+ memset(buf_alloc, 0, buf_size);
+
+ /* read */
+ ret = lseek(fd, pos, SEEK_SET);
+ if (ret != pos) {
+ perror("read seek");
+ return 1;
+ }
+ gettimeofday(&tr1, NULL);
+ for (i = 0, buf = buf_alloc; i < _npages;
+ i += xfer, buf += xfer * PAGE_CACHE_SIZE / sizeof(int)) {
+ rc = read(fd, buf, PAGE_CACHE_SIZE * xfer);
+ if (rc != PAGE_CACHE_SIZE * xfer) {
+ printf("read error (i %d, rc %d): %s\n", i, rc,
+ strerror(errno));
+ return(1);
+ }
+ }
+ gettimeofday(&tr2, NULL);
+
+ /* compute checksum */
+ for (i = 0, buf = buf_alloc; i < _npages; i++) {
+ int sum = 0;
+ for (j = 0; j < PAGE_CACHE_SIZE/sizeof(int); j++, buf++) {
+ sum += *buf;
+ }
+ if (sum != check_sum[i]) {
+ data_error = 1;
+ printf("chunk %d checksum error expected %#x got %#x\n",
+ i, check_sum[i], sum);
+ }
+ }
+
+ t_close(fd);
+ t_unlink(path);
+ tw = (tw2.tv_sec - tw1.tv_sec) * 1000000 + (tw2.tv_usec - tw1.tv_usec);
+ tr = (tr2.tv_sec - tr1.tv_sec) * 1000000 + (tr2.tv_usec - tr1.tv_usec);
+ printf(" (R:%.3fM/s, W:%.3fM/s)\n",
+ (_npages * PAGE_CACHE_SIZE) / (tw / 1000000.0) / (1024 * 1024),
+ (_npages * PAGE_CACHE_SIZE) / (tr / 1000000.0) / (1024 * 1024));
+
+ if (data_error)
+ return 1;
+
+ return 0;
+}
+
+int t50(char *name)
+{
+ int np = 1;
+ loff_t offset = 0;
+
+ ENTER("4k aligned i/o sanity");
+ while (np <= _npages) {
+ printf("%3d per xfer(total %d)...\t", np, _npages);
+ fflush(stdout);
+ if (pages_io(np, offset) != 0)
+ return 1;
+ np += np;
+ }
+ LEAVE();
+}
+
+int t50b(char *name)
+{
+ loff_t off_array[] = {1, 17, 255, 258, 4095, 4097, 8191,
+ 1024*1024*1024*1024ULL};
+ int i;
+ long long offset;
+
+ ENTER("4k un-aligned i/o sanity");
+ for (i = 0; i < sizeof(off_array)/sizeof(loff_t); i++) {
+ offset = off_array[i];
+ printf("16 per xfer(total %d), offset %10lld...\t",
+ _npages, offset);
+ if (pages_io(16, offset) != 0)
+ return 1;
+ }
+
+ LEAVE();
+}
+
+enum {
+ T51_STEP = 42,
+ T51_NR = 1000
+};
+
+/*
+ * truncate(2) checks.
+ */
+int t51(char *name)
+{
+ char file[MAX_PATH_LENGTH] = "";
+ int fd;
+ long long size;
+ int result;
+
+ ENTER("truncate() should truncate file to proper length");
+ snprintf(file, MAX_PATH_LENGTH, "%s/test_t51_file", lustre_path);
+
+ for (size = 0; size < T51_NR * T51_STEP; size += T51_STEP) {
+ t_echo_create(file, "");
+ if (truncate(file, size) != 0) {
+ printf("\nerror truncating file: %s\n",strerror(errno));
+ return(-1);
+ }
+ result = check_file_size(file, size);
+ if (result != 0)
+ return result;
+ t_unlink(file);
+
+ t_echo_create(file, "");
+ fd = open(file, O_RDWR|O_CREAT, (mode_t)0666);
+ if (fd < 0) {
+ printf("\nerror open file: %s\n", strerror(errno));
+ return(-1);
+ }
+ if (ftruncate(fd, size) != 0) {
+ printf("\nerror ftruncating file:%s\n",strerror(errno));
+ return(-1);
+ }
+ close(fd);
+ result = check_file_size(file, size);
+ if (result != 0)
+ return result;
+ t_unlink(file);
+ if (size % (T51_STEP * (T51_NR / 75)) == 0) {
+ printf(".");
+ fflush(stdout);
+ }
+ }
+ printf("\n");
+ LEAVE();
+}
+/*
+ * check atime update during read
+ */
+int t52(char *name)
+{
+ char file[MAX_PATH_LENGTH] = "";
+ char buf[16];
+ struct stat statbuf;
+ time_t atime;
+ time_t diff;
+ int fd, i;
+
+ ENTER("atime should be updated during read");
+ snprintf(file, MAX_PATH_LENGTH, "%s/test_t52_file", lustre_path);
+
+ t_echo_create(file, "check atime update during read");
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
+ printf("\nerror open file: %s\n", strerror(errno));
+ return(-1);
+ }
+ stat(file, &statbuf);
+ printf("st_atime=%s", ctime(&statbuf.st_atime));
+ atime = statbuf.st_atime;
+ for (i = 0; i < 3; i++) {
+ ssize_t num_read;
+ sleep(2);
+ /* should not ignore read(2)'s return value */
+ num_read = read(fd, buf, sizeof(buf));
+ if (num_read < 0 ) {
+ printf("read from %s: %s\n", file, strerror(errno));
+ return -1;
+ }
+ stat(file, &statbuf);
+ printf("st_atime=%s", ctime(&statbuf.st_atime));
+ diff = statbuf.st_atime - atime;
+ if (diff <= 0) {
+ printf("atime doesn't updated! failed!\n");
+ close(fd);
+ t_unlink(file);
+ return -1;
+ }
+ atime = statbuf.st_atime;
+ }
+ close(fd);
+ t_unlink(file);
+ LEAVE();
+}
+
+#define NEW_TIME 10000
+int t53(char *name)
+{
+ char file[MAX_PATH_LENGTH] = "";
+ struct utimbuf times; /* struct. buffer for utime() */
+ struct stat stat_buf; /* struct buffer to hold file info. */
+ time_t mtime, atime;
+
+ ENTER("mtime/atime should be updated by utime() call");
+ snprintf(file, MAX_PATH_LENGTH, "%s/test_t53_file", lustre_path);
+
+ t_echo_create(file, "check mtime/atime update by utime() call");
+
+ /* Initialize the modification and access time in the times arg */
+ times.actime = NEW_TIME+10;
+ times.modtime = NEW_TIME;
+
+ /* file modification/access time */
+ utime(file, ×);
+
+ if (stat(file, &stat_buf) < 0) {
+ printf("stat(2) of %s failed, error:%d %s\n",
+ file, errno, strerror(errno));
+ }
+ mtime = stat_buf.st_mtime;
+ atime = stat_buf.st_atime;
+
+ if ((mtime == NEW_TIME) && (atime == NEW_TIME + 10)) {
+ t_unlink(file);
+ LEAVE();
+ }
+
+ printf("mod time %ld, expected %ld\n", mtime, (long)NEW_TIME);
+ printf("acc time %ld, expected %ld\n", atime, (long)NEW_TIME + 10);
+
+ t_unlink(file);
+ return (-1);
+}
+
+int t54(char *name)
+{
+ char file[MAX_PATH_LENGTH] = "";
+ struct flock lock;
+ int fd, err;
+
+ ENTER("fcntl should return 0 when succeed in getting flock");
+ snprintf(file, MAX_PATH_LENGTH, "%s/test_t54_file", lustre_path);
+
+ t_echo_create(file, "fcntl should return 0 when succeed");
+
+ fd = open(file, O_RDWR);
+ if (fd < 0) {
+ printf("\nerror open file: %s\n", strerror(errno));
+ return(-1);
+ }
+ lock.l_type = F_WRLCK;
+ lock.l_start = 0;
+ lock.l_whence = 0;
+ lock.l_len = 1;
+ if ((err = t_fcntl(fd, F_SETLKW, &lock)) != 0) {
+ fprintf(stderr, "fcntl returned: %d (%s)\n",
+ err, strerror(err));
+ close(fd);
+ t_unlink(file);
+ return (-1);
+ }
+
+ lock.l_type = F_UNLCK;
+ t_fcntl(fd, F_SETLKW, &lock);
+ close(fd);
+ t_unlink(file);
+ LEAVE();
+}
+
+/* for O_DIRECTORY */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#define STRIPE_SIZE (2048 * 2048)
+#define STRIPE_OFFSET 0
+#define STRIPE_COUNT 1
+int t55(char *name)
+{
+ char path[MAX_PATH_LENGTH] = "";
+ char file[MAX_PATH_LENGTH] = "";
+ struct lov_user_md *lum = NULL;
+ struct lov_user_ost_data *lo = NULL;
+ int index, fd, buflen, rc;
+
+ ENTER("setstripe/getstripe");
+ snprintf(path, MAX_PATH_LENGTH, "%s/test_t55", lustre_path);
+ snprintf(file, MAX_PATH_LENGTH, "%s/test_t55/file_t55", lustre_path);
+
+ buflen = sizeof(struct lov_user_md);
+ buflen += STRIPE_COUNT * sizeof(struct lov_user_ost_data);
+ lum = (struct lov_user_md *)malloc(buflen);
+ if (!lum) {
+ printf("out of memory!\n");
+ return -1;
+ }
+ memset(lum, 0, buflen);
+
+ t_mkdir(path);
+ rc = llapi_file_create(path, STRIPE_SIZE, STRIPE_OFFSET,
+ STRIPE_COUNT, LOV_PATTERN_RAID0);
+ if (rc) {
+ printf("llapi_file_create failed: rc = %d (%s) \n",
+ rc, strerror(-rc));
+ t_rmdir(path);
+ free(lum);
+ return -1;
+ }
+
+ fd = open(file, O_CREAT | O_RDWR, 0644);
+ if (fd < 0) {
+ printf("open file(%s) failed: rc = %d (%s) \n)",
+ file, fd, strerror(errno));
+ t_rmdir(path);
+ free(lum);
+ return -1;
+ }
+
+ lum->lmm_magic = LOV_USER_MAGIC;
+ lum->lmm_stripe_count = STRIPE_COUNT;
+ rc = ioctl(fd, LL_IOC_LOV_GETSTRIPE, lum);
+ if (rc) {
+ printf("dir:ioctl(LL_IOC_LOV_GETSTRIPE) failed: rc = %d(%s)\n",
+ rc, strerror(errno));
+ close(fd);
+ t_unlink(file);
+ t_rmdir(path);
+ free(lum);
+ return -1;
+ }
+
+ close(fd);
+
+ if (opt_verbose) {
+ printf("lmm_magic: 0x%08X\n", lum->lmm_magic);
+ printf("lmm_object_id: "LPX64"\n",
+ lmm_oi_id(&lum->lmm_oi));
+ printf("lmm_object_seq: "LPX64"\n",
+ lmm_oi_seq(&lum->lmm_oi));
+ printf("lmm_stripe_count: %u\n", (int)lum->lmm_stripe_count);
+ printf("lmm_stripe_size: %u\n", lum->lmm_stripe_size);
+ printf("lmm_stripe_pattern: %x\n", lum->lmm_pattern);
+
+ for (index = 0; index < lum->lmm_stripe_count; index++) {
+ lo = lum->lmm_objects + index;
+ printf("object %d:\n", index);
+ printf("\tobject_oid: "DOSTID"\n",
+ POSTID(&lo->l_ost_oi));
+ printf("\tost_gen: %#x\n", lo->l_ost_gen);
+ printf("\tost_idx: %u\n", lo->l_ost_idx);
+ }
+ }
+
+ if (lum->lmm_magic != LOV_USER_MAGIC ||
+ lum->lmm_pattern != LOV_PATTERN_RAID0 ||
+ lum->lmm_stripe_size != STRIPE_SIZE ||
+ lum->lmm_objects[0].l_ost_idx != STRIPE_OFFSET ||
+ lum->lmm_stripe_count != STRIPE_COUNT) {
+ printf("incorrect striping information!\n");
+ t_unlink(file);
+ t_rmdir(path);
+ free(lum);
+ return -1;
+ }
+ t_unlink(file);
+
+ /* setstripe on regular file */
+ rc = llapi_file_create(file, STRIPE_SIZE, STRIPE_OFFSET,
+ STRIPE_COUNT, LOV_PATTERN_RAID0);
+ if (rc) {
+ printf("llapi_file_create failed: rc = %d (%s) \n",
+ rc, strerror(-rc));
+ t_unlink(file);
+ t_rmdir(path);
+ free(lum);
+ return -1;
+ }
+ fd = open(file, O_RDWR, 0644);
+ if (fd < 0) {
+ printf("failed to open(%s): rc = %d (%s)\n",
+ file, fd, strerror(errno));
+ t_unlink(file);
+ t_rmdir(path);
+ free(lum);
+ return -1;
+ }
+
+ lum->lmm_magic = LOV_USER_MAGIC;
+ lum->lmm_stripe_count = STRIPE_COUNT;
+ rc = ioctl(fd, LL_IOC_LOV_GETSTRIPE, lum);
+ if (rc) {
+ printf("file:ioctl(LL_IOC_LOV_GETSTRIPE) failed: rc = %d(%s)\n",
+ rc, strerror(errno));
+ close(fd);
+ t_unlink(file);
+ t_rmdir(path);
+ free(lum);
+ return -1;
+ }
+ close(fd);
+
+ if (opt_verbose) {
+ printf("lmm_magic: 0x%08X\n", lum->lmm_magic);
+ printf("lmm_object_id: "LPX64"\n",
+ lmm_oi_id(&lum->lmm_oi));
+ printf("lmm_object_seq: "LPX64"\n",
+ lmm_oi_seq(&lum->lmm_oi));
+ printf("lmm_stripe_count: %u\n", (int)lum->lmm_stripe_count);
+ printf("lmm_stripe_size: %u\n", lum->lmm_stripe_size);
+ printf("lmm_stripe_pattern: %x\n", lum->lmm_pattern);
+
+ for (index = 0; index < lum->lmm_stripe_count; index++) {
+ lo = lum->lmm_objects + index;
+ printf("object %d:\n", index);
+ printf("\tobject_oid: "DOSTID"\n",
+ POSTID(&lo->l_ost_oi));
+ printf("\tost_gen: %#x\n", lo->l_ost_gen);
+ printf("\tost_idx: %u\n", lo->l_ost_idx);
+ }
+ }
+
+ if (lum->lmm_magic != LOV_USER_MAGIC ||
+ lum->lmm_pattern != LOV_PATTERN_RAID0 ||
+ lum->lmm_stripe_size != STRIPE_SIZE ||
+ lum->lmm_objects[0].l_ost_idx != STRIPE_OFFSET ||
+ lum->lmm_stripe_count != STRIPE_COUNT) {
+ printf("incorrect striping information!\n");
+ t_unlink(file);
+ t_rmdir(path);
+ free(lum);
+ return -1;
+ }
+
+ t_unlink(file);
+ t_rmdir(path);
+ free(lum);
+ LEAVE();
+}
+
+/*
+ * getdirentries should return -1 and set errno to EINVAL when the size
+ * specified as an argument is too small to contain at least one entry
+ * (see bugzilla ticket 12229)
+ */
+int t56(char *name)
+{
+ int fd;
+ size_t nbytes;
+ off_t basep = 0;
+ long rc = 0;
+ struct dirent64 dir;
+
+ ENTER("getdirentries should fail if nbytes is too small");
+
+ /* Set count to be very small. The result should be EINVAL */
+ nbytes = 8;
+
+ /* open the directory and call getdirentries */
+ fd = t_opendir(lustre_path);
+
+ rc = getdirentries(fd, (char *)&dir, nbytes, &basep);
+
+ if (rc != -1) {
+ printf("Test failed: getdirentries returned %lld\n",
+ (long long)rc);
+ t_close(fd);
+ return -1;
+ }
+ if (errno != EINVAL) {
+ printf("Test failed: getdirentries returned %lld but errno is "
+ "set to %d (should be EINVAL)\n", (long long)rc, errno);
+ t_close(fd);
+ return -1;
+ }
+ t_close(fd);
+
+ LEAVE();
+}
+