static void verify_pwritev2(unsigned int n) { int i; char preadbuf[CHUNK]; struct tcase *tc = &tcases[n]; SAFE_PWRITE(1, fd, initbuf, sizeof(initbuf), 0); SAFE_LSEEK(fd, tc->seek_off, SEEK_SET); TEST(pwritev2(fd, wr_iovec, tc->count, tc->write_off, 0)); if (TST_RET < 0) { tst_res(TFAIL | TTERRNO, "pwritev2() failed"); return; } if (TST_RET != tc->size) { tst_res(TFAIL, "pwritev2() wrote %li bytes, expected %zi", TST_RET, tc->size); return; } if (SAFE_LSEEK(fd, 0, SEEK_CUR) != tc->exp_off) { tst_res(TFAIL, "pwritev2() had changed file offset"); return; } memset(preadbuf, 0, CHUNK); if (tc->write_off != -1) SAFE_PREAD(1, fd, preadbuf, tc->size, tc->write_off); else SAFE_PREAD(1, fd, preadbuf, tc->size, tc->seek_off); for (i = 0; i < tc->size; i++) { if (preadbuf[i] != 0x61) break; } if (i != tc->size) { tst_res(TFAIL, "buffer wrong at %i have %c expected 'a'", i, preadbuf[i]); return; } tst_res(TPASS, "pwritev2() wrote %zi bytes successfully " "with content 'a' expectedly ", tc->size); }
void verify_preadv(unsigned int n) { int i; char *vec; struct tcase *tc = &tcases[n]; vec = rd_iovec[0].iov_base; memset(vec, 0x00, CHUNK); SAFE_LSEEK(fd, 0, SEEK_SET); TEST(preadv(fd, rd_iovec, tc->count, tc->offset)); if (TST_RET < 0) { tst_res(TFAIL | TTERRNO, "Preadv(2) failed"); return; } if (TST_RET != tc->size) { tst_res(TFAIL, "Preadv(2) read %li bytes, expected %zi", TST_RET, tc->size); return; } for (i = 0; i < tc->size; i++) { if (vec[i] != tc->content) break; } if (i < tc->size) { tst_res(TFAIL, "Buffer wrong at %i have %02x expected %02x", i, vec[i], tc->content); return; } if (SAFE_LSEEK(fd, 0, SEEK_CUR) != 0) { tst_res(TFAIL, "Preadv(2) has changed file offset"); return; } tst_res(TPASS, "Preadv(2) read %zi bytes successfully " "with content '%c' expectedly", tc->size, tc->content); }
static void verify_read(void) { SAFE_LSEEK(fd, 0, SEEK_SET); TEST(read(fd, buf, SIZE)); if (TEST_RETURN == -1) tst_res(TFAIL | TTERRNO, "read(2) failed"); else tst_res(TPASS, "read(2) returned %ld", TEST_RETURN); }
static void test_append(void) { off_t len1, len2; TEST(open(TEST_FILE, O_RDWR | O_APPEND, 0777)); if (TEST_RETURN == -1) { tst_resm(TFAIL | TTERRNO, "open failed"); return; } len1 = SAFE_LSEEK(cleanup, TEST_RETURN, 0, SEEK_CUR); SAFE_WRITE(cleanup, 1, TEST_RETURN, TEST_FILE, sizeof(TEST_FILE)); len2 = SAFE_LSEEK(cleanup, TEST_RETURN, 0, SEEK_CUR); SAFE_CLOSE(cleanup, TEST_RETURN); if (len2 > len1) tst_resm(TPASS, "test O_APPEND for open success"); else tst_resm(TFAIL, "test O_APPEND for open failed"); }
int main(void) { int fd, stdout_fd; char msg[4096], *pos; FILE *f; setup(); /* redirect stdout to file */ stdout_fd = dup(fileno(stdout)); fd = SAFE_OPEN(NULL, OUTPUT_FNAME, O_RDWR | O_CREAT, 0666); TEST(dup2(fd, fileno(stdout))); if (TEST_RETURN == -1) tst_brkm(TBROK | TTERRNO, cleanup, "dup2"); errno = EPERM; TEST_ERRNO = EPERM; TEST_RETURN = EINVAL; tst_resm(TINFO | TRERRNO, "test"); tst_old_flush(); /* restore stdout */ TEST(dup2(stdout_fd, fileno(stdout))); if (TEST_RETURN == -1) tst_brkm(TBROK | TTERRNO, cleanup, "dup2"); /* read file and verify that output is as expected */ SAFE_LSEEK(cleanup, fd, 0, SEEK_SET); f = fdopen(fd, "r"); if (!f) tst_brkm(TBROK | TERRNO, cleanup, "fdopen"); if (!fgets(msg, sizeof(msg), f)) tst_brkm(TBROK, cleanup, "fgets"); fclose(f); pos = strchr(msg, '\n'); if (pos != NULL) *pos = '\0'; tst_resm(TINFO, "%s", msg); if (strstr(msg, "EPERM")) tst_resm(TFAIL, "EPERM shouldn't be in TRERRNO output"); if (strstr(msg, "EINVAL")) tst_resm(TPASS, "EINVAL should be in TRERRNO output"); else tst_resm(TFAIL, "EINVAL not found in TRERRNO output"); cleanup(); tst_exit(); }
static void check_file_data(const char exp_buf[], size_t size) { char rbuf[size]; tst_resm(TINFO, "reading the file, compare with expected buffer"); SAFE_LSEEK(cleanup, fd, 0, SEEK_SET); SAFE_READ(cleanup, 1, fd, rbuf, size); if (memcmp(exp_buf, rbuf, size)) { if (verbose) { tst_resm_hexd(TINFO, exp_buf, size, "expected:"); tst_resm_hexd(TINFO, rbuf, size, "but read:"); } tst_brkm(TFAIL, cleanup, "not expected file data"); } }
int main(int ac, char **av) { int lc, i, fail; char *msg, *vec; if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); setup(); for (lc = 0; TEST_LOOPING(lc); lc++) { tst_count = 0; SAFE_LSEEK(cleanup, fd, 0, SEEK_SET); if (readv(fd, rd_iovec, 0) == -1) tst_resm(TFAIL | TERRNO, "readv failed unexpectedly"); else tst_resm(TPASS, "readv read 0 io vectors"); memset(rd_iovec[0].iov_base, 0x00, CHUNK); if (readv(fd, rd_iovec, 3) != CHUNK) { tst_resm(TFAIL, "readv failed reading %d bytes, " "followed by two NULL vectors", CHUNK); } else { fail = 0; vec = rd_iovec[0].iov_base; for (i = 0; i < CHUNK; i++) { if (vec[i] != 0x42) fail++; } if (fail) tst_resm(TFAIL, "Wrong buffer content"); else tst_resm(TPASS, "readv passed reading %d bytes " "followed by two NULL vectors", CHUNK); } } cleanup(); tst_exit(); }
void testfunc_append(void) { off_t file_offset; SAFE_FILE_PRINTF(cleanup, TEST_FILE, "test file"); TEST(openat(AT_FDCWD, TEST_FILE, O_APPEND | O_RDWR, 0777)); if (TEST_RETURN == -1) { tst_resm(TFAIL | TTERRNO, "openat failed"); return; } SAFE_WRITE(cleanup, 1, TEST_RETURN, STR, sizeof(STR) - 1); file_offset = SAFE_LSEEK(cleanup, TEST_RETURN, 0, SEEK_CUR); if (file_offset > (off_t)(sizeof(STR) - 1)) tst_resm(TPASS, "test O_APPEND for openat success"); else tst_resm(TFAIL, "test O_APPEND for openat failed"); SAFE_CLOSE(cleanup, TEST_RETURN); }
int main(int ac, char **av) { int lc, i; int len, stop; tst_parse_opts(ac, av, NULL, NULL); setup(); for (lc = 0; TEST_LOOPING(lc); lc++) { /* * generate events */ fd = SAFE_OPEN(cleanup, fname, O_RDWR); for (i = 0; i < max_events; i++) { SAFE_LSEEK(cleanup, fd, 0, SEEK_SET); SAFE_READ(cleanup, 1, fd, buf, BUF_SIZE); SAFE_LSEEK(cleanup, fd, 0, SEEK_SET); SAFE_WRITE(cleanup, 1, fd, buf, BUF_SIZE); } SAFE_CLOSE(cleanup, fd); stop = 0; while (!stop) { /* * get list on events */ len = read(fd_notify, event_buf, EVENT_BUF_LEN); if (len < 0) { tst_brkm(TBROK | TERRNO, cleanup, "read(%d, buf, %zu) failed", fd_notify, EVENT_BUF_LEN); } /* * check events */ i = 0; while (i < len) { struct inotify_event *event; event = (struct inotify_event *)&event_buf[i]; if (event->mask != IN_ACCESS && event->mask != IN_MODIFY && event->mask != IN_OPEN && event->mask != IN_Q_OVERFLOW) { tst_resm(TFAIL, "get event: wd=%d mask=%x " "cookie=%u (expected 0) len=%u", event->wd, event->mask, event->cookie, event->len); stop = 1; break; } if (event->mask == IN_Q_OVERFLOW) { if (event->len != 0 || event->cookie != 0 || event->wd != -1) { tst_resm(TFAIL, "invalid overflow event: " "wd=%d mask=%x " "cookie=%u len=%u", event->wd, event->mask, event->cookie, event->len); stop = 1; break; } if ((int)(i + EVENT_SIZE) != len) { tst_resm(TFAIL, "overflow event is not last"); stop = 1; break; } tst_resm(TPASS, "get event: wd=%d " "mask=%x cookie=%u len=%u", event->wd, event->mask, event->cookie, event->len); stop = 1; break; } i += EVENT_SIZE + event->len; } } } cleanup(); tst_exit(); }
void *thread_fn_01(void *arg) { int i; unsigned char buf[write_size]; int fd = SAFE_OPEN(fname, O_RDWR); memset(buf, (intptr_t)arg, write_size); struct flock64 lck = { .l_whence = SEEK_SET, .l_start = 0, .l_len = 1, }; for (i = 0; i < writes_num; ++i) { lck.l_type = F_WRLCK; my_fcntl(fd, F_OFD_SETLKW, &lck); SAFE_LSEEK(fd, 0, SEEK_END); SAFE_WRITE(1, fd, buf, write_size); lck.l_type = F_UNLCK; my_fcntl(fd, F_OFD_SETLKW, &lck); sched_yield(); } SAFE_CLOSE(fd); return NULL; } static void test01(void) { intptr_t i; int k; pthread_t id[thread_cnt]; int res[thread_cnt]; unsigned char buf[write_size]; tst_res(TINFO, "write to a file inside threads with OFD locks"); int fd = SAFE_OPEN(fname, O_CREAT | O_TRUNC | O_RDWR, 0600); memset(res, 0, sizeof(res)); spawn_threads(id, thread_fn_01); wait_threads(id); tst_res(TINFO, "verifying file's data"); SAFE_LSEEK(fd, 0, SEEK_SET); for (i = 0; i < writes_num * thread_cnt; ++i) { SAFE_READ(1, fd, buf, write_size); if (buf[0] >= thread_cnt) { tst_res(TFAIL, "unexpected data read"); return; } ++res[buf[0]]; for (k = 1; k < write_size; ++k) { if (buf[0] != buf[k]) { tst_res(TFAIL, "unexpected data read"); return; } } } for (i = 0; i < thread_cnt; ++i) { if (res[i] != writes_num) { tst_res(TFAIL, "corrupted data found"); return; } } SAFE_CLOSE(fd); tst_res(TPASS, "OFD locks synchronized access between threads"); }
static void test_partially_valid_iovec(int initial_file_offset) { int i, fd; unsigned char buffer[BUFSIZE], fpattern[BUFSIZE], tmp[BUFSIZE]; long off_after; struct iovec wr_iovec[] = { { buffer, CHUNK }, { bad_addr, CHUNK }, { buffer + CHUNK, CHUNK }, { buffer + CHUNK * 2, CHUNK }, }; tst_res(TINFO, "starting test with initial file offset: %d ", initial_file_offset); for (i = 0; i < BUFSIZE; i++) buffer[i] = i % (CHUNK - 1); memset(fpattern, 0xff, BUFSIZE); tst_fill_file(TESTFILE, 0xff, CHUNK, BUFSIZE / CHUNK); fd = SAFE_OPEN(TESTFILE, O_RDWR, 0644); SAFE_LSEEK(fd, initial_file_offset, SEEK_SET); TEST(writev(fd, wr_iovec, ARRAY_SIZE(wr_iovec))); off_after = (long) SAFE_LSEEK(fd, 0, SEEK_CUR); /* bad errno */ if (TEST_RETURN == -1 && TEST_ERRNO != EFAULT) { tst_res(TFAIL | TTERRNO, "unexpected errno"); SAFE_CLOSE(fd); return; } /* nothing has been written */ if (TEST_RETURN == -1 && TEST_ERRNO == EFAULT) { tst_res(TINFO, "got EFAULT"); /* initial file content remains untouched */ SAFE_LSEEK(fd, 0, SEEK_SET); SAFE_READ(1, fd, tmp, BUFSIZE); if (memcmp(tmp, fpattern, BUFSIZE)) tst_res(TFAIL, "file was written to"); else tst_res(TPASS, "file stayed untouched"); /* offset hasn't changed */ if (off_after == initial_file_offset) tst_res(TPASS, "offset stayed unchanged"); else tst_res(TFAIL, "offset changed to %ld", off_after); SAFE_CLOSE(fd); return; } /* writev() wrote more bytes than bytes preceding invalid iovec */ tst_res(TINFO, "writev() has written %ld bytes", TEST_RETURN); if (TEST_RETURN > (long) wr_iovec[0].iov_len) { tst_res(TFAIL, "writev wrote more than expected"); SAFE_CLOSE(fd); return; } /* file content matches written bytes */ SAFE_LSEEK(fd, initial_file_offset, SEEK_SET); SAFE_READ(1, fd, tmp, TEST_RETURN); if (memcmp(tmp, wr_iovec[0].iov_base, TEST_RETURN) == 0) { tst_res(TPASS, "file has expected content"); } else { tst_res(TFAIL, "file has unexpected content"); tst_res_hexd(TFAIL, wr_iovec[0].iov_base, TEST_RETURN, "expected:"); tst_res_hexd(TFAIL, tmp, TEST_RETURN, "actual file content:"); } /* file offset has been updated according to written bytes */ if (off_after == initial_file_offset + TEST_RETURN) tst_res(TPASS, "offset at %ld as expected", off_after); else tst_res(TFAIL, "offset unexpected %ld", off_after); SAFE_CLOSE(fd); }
/* read_testfile - mmap testfile and read every page. * This functions measures how many I/O and time it takes to fully * read contents of test file. * * @do_readahead: call readahead prior to reading file content? * @fname: name of file to test * @fsize: how many bytes to read/mmap * @read_bytes: returns difference of bytes read, parsed from /proc/<pid>/io * @usec: returns how many microsecond it took to go over fsize bytes * @cached: returns cached kB from /proc/meminfo */ static int read_testfile(struct tcase *tc, int do_readahead, const char *fname, size_t fsize, unsigned long *read_bytes, long long *usec, unsigned long *cached) { int fd; size_t i = 0; long read_bytes_start; unsigned char *p, tmp; off_t offset = 0; fd = SAFE_OPEN(fname, O_RDONLY); if (do_readahead) { do { TEST(tc->readahead(fd, offset, fsize - offset)); if (TST_RET != 0) { SAFE_CLOSE(fd); return TST_ERR; } i++; offset += readahead_length; } while ((size_t)offset < fsize); tst_res(TINFO, "readahead calls made: %zu", i); *cached = get_cached_size(); /* offset of file shouldn't change after readahead */ offset = SAFE_LSEEK(fd, 0, SEEK_CUR); if (offset == 0) tst_res(TPASS, "offset is still at 0 as expected"); else tst_res(TFAIL, "offset has changed to: %lu", offset); } tst_timer_start(CLOCK_MONOTONIC); read_bytes_start = get_bytes_read(); p = SAFE_MMAP(NULL, fsize, PROT_READ, MAP_SHARED | MAP_POPULATE, fd, 0); /* for old kernels, where MAP_POPULATE doesn't work, touch each page */ tmp = 0; for (i = 0; i < fsize; i += pagesize) tmp = tmp ^ p[i]; /* prevent gcc from optimizing out loop above */ if (tmp != 0) tst_brk(TBROK, "This line should not be reached"); if (!do_readahead) *cached = get_cached_size(); SAFE_MUNMAP(p, fsize); *read_bytes = get_bytes_read() - read_bytes_start; tst_timer_stop(); *usec = tst_timer_elapsed_us(); SAFE_CLOSE(fd); return 0; }