static void dotest(int testers, int me, int fd) { char *bits, *buf; char val, val0; int count, collide, chunk, whenmisc, xfr, i; /* Stuff for the readv call */ struct iovec r_iovec[MAXIOVCNT]; int r_ioveclen; /* Stuff for the writev call */ struct iovec val0_iovec[MAXIOVCNT]; struct iovec val_iovec[MAXIOVCNT]; int w_ioveclen; nchunks = max_size / (testers * csize); whenmisc = 0; if ((bits = malloc((nchunks + 7) / 8)) == NULL) { tst_resm(TBROK, "\tmalloc failed(bits)"); tst_exit(); } if ((buf = (malloc(csize))) == NULL) { tst_resm(TBROK, "\tmalloc failed(buf)"); tst_exit(); } /* Allocate memory for the iovec buffers and init the iovec arrays */ r_ioveclen = w_ioveclen = csize / MAXIOVCNT; /* Please note that the above statement implies that csize * be evenly divisible by MAXIOVCNT. */ for (i = 0; i < MAXIOVCNT; i++) { if ((r_iovec[i].iov_base = malloc(r_ioveclen)) == NULL) { tst_resm(TBROK, "\tmalloc failed(iov_base)"); tst_exit(); } r_iovec[i].iov_len = r_ioveclen; /* Allocate unused memory areas between all the buffers to * make things more diffult for the OS. */ if (malloc((i + 1) * 8) == NULL) { tst_resm(TBROK, "\tmalloc failed((i+1)*8)"); tst_exit(); } if ((val0_iovec[i].iov_base = malloc(w_ioveclen)) == NULL) { tst_resm(TBROK, "\tmalloc failed(val0_iovec)"); tst_exit(); } val0_iovec[i].iov_len = w_ioveclen; if (malloc((i + 1) * 8) == NULL) { tst_resm(TBROK, "\tmalloc failed((i+1)*8)"); tst_exit(); } if ((val_iovec[i].iov_base = malloc(w_ioveclen)) == NULL) { tst_resm(TBROK, "\tmalloc failed(iov_base)"); tst_exit(); } val_iovec[i].iov_len = w_ioveclen; if (malloc((i + 1) * 8) == NULL) { tst_resm(TBROK, "\tmalloc failed(((i+1)*8)"); tst_exit(); } } /* * No init sectors; file-sys makes 0 to start. */ val = (64 / testers) * me + 1; val0 = 0; /* * For each iteration: * zap bits array * loop: * pick random chunk, read it. * if corresponding bit off { * verify == 0. (sparse file) * ++count; * } else * verify == val. * write "val" on it. * repeat until count = nchunks. * ++val. */ srand(getpid()); if (misc_intvl) whenmisc = NEXTMISC; while (iterations-- > 0) { for (i = 0; i < NMISC; i++) misc_cnt[i] = 0; memset(bits, 0, (nchunks + 7) / 8); /* Have to fill the val0 and val iov buffers in a different manner */ for (i = 0; i < MAXIOVCNT; i++) { memset(val0_iovec[i].iov_base, val0, val0_iovec[i].iov_len); memset(val_iovec[i].iov_base, val, val_iovec[i].iov_len); } count = 0; collide = 0; while (count < nchunks) { chunk = rand() % nchunks; /* * Read it. */ if (lseek64(fd, CHUNK(chunk), 0) < 0) { tst_resm(TFAIL, "\tTest[%d]: lseek64(0) fail at %" PRIx64 "x, errno = %d.", me, CHUNK(chunk), errno); tst_exit(); } if ((xfr = readv(fd, &r_iovec[0], MAXIOVCNT)) < 0) { tst_resm(TFAIL, "\tTest[%d]: readv fail at %" PRIx64 "x, errno = %d.", me, CHUNK(chunk), errno); tst_exit(); } /* * If chunk beyond EOF just write on it. * Else if bit off, haven't seen it yet. * Else, have. Verify values. */ if (xfr == 0) { bits[chunk / 8] |= (1 << (chunk % 8)); } else if ((bits[chunk / 8] & (1 << (chunk % 8))) == 0) { if (xfr != csize) { tst_resm(TFAIL, "\tTest[%d]: xfr=%d != %d, zero read.", me, xfr, csize); tst_exit(); } for (i = 0; i < MAXIOVCNT; i++) { if (memcmp (r_iovec[i].iov_base, val0_iovec[i].iov_base, r_iovec[i].iov_len)) { tst_resm(TFAIL, "\tTest[%d] bad verify @ 0x%" PRIx64 " for val %d count %d xfr %d.", me, CHUNK(chunk), val0, count, xfr); ft_dumpiov(&r_iovec[i]); ft_dumpbits(bits, (nchunks + 7) / 8); tst_exit(); } } bits[chunk / 8] |= (1 << (chunk % 8)); ++count; } else { if (xfr != csize) { tst_resm(TFAIL, "\tTest[%d]: xfr=%d != %d, val read.", me, xfr, csize); tst_exit(); } ++collide; for (i = 0; i < MAXIOVCNT; i++) { if (memcmp (r_iovec[i].iov_base, val_iovec[i].iov_base, r_iovec[i].iov_len)) { tst_resm(TFAIL, "\tTest[%d] bad verify @ 0x%" PRIx64 " for val %d count %d xfr %d.", me, CHUNK(chunk), val, count, xfr); ft_dumpiov(&r_iovec[i]); ft_dumpbits(bits, (nchunks + 7) / 8); tst_exit(); } } } /* * Write it. */ if (lseek64(fd, -xfr, 1) < 0) { tst_resm(TFAIL, "\tTest[%d]: lseek64(1) fail at %" PRIx64 ", errno = %d.", me, CHUNK(chunk), errno); tst_exit(); } if ((xfr = writev(fd, &val_iovec[0], MAXIOVCNT)) < csize) { if (errno == ENOSPC) { tst_resm(TFAIL, "\tTest[%d]: no space, exiting.", me); fsync(fd); tst_exit(); } tst_resm(TFAIL, "\tTest[%d]: writev fail at %" PRIx64 "x xfr %d, errno = %d.", me, CHUNK(chunk), xfr, errno); tst_exit(); } /* * If hit "misc" interval, do it. */ if (misc_intvl && --whenmisc <= 0) { domisc(me, fd); whenmisc = NEXTMISC; } if (count + collide > 2 * nchunks) break; } /* * End of iteration, maybe before doing all chunks. */ if (count < nchunks) { //tst_resm(TINFO, "\tTest{%d} val %d stopping @ %d, collide = {%d}.", // me, val, count, collide); for (i = 0; i < nchunks; i++) { if ((bits[i / 8] & (1 << (i % 8))) == 0) { if (lseek64(fd, CHUNK(i), 0) < (off64_t) 0) { tst_resm(TFAIL, "\tTest[%d]: lseek64 fail at %" PRIx64 "x, errno = %d.", me, CHUNK(i), errno); tst_exit(); } if (writev(fd, &val_iovec[0], MAXIOVCNT) != csize) { tst_resm(TFAIL, "\tTest[%d]: writev fail at %" PRIx64 "x, errno = %d.", me, CHUNK(i), errno); tst_exit(); } } } } fsync(fd); ++misc_cnt[m_fsync]; //tst_resm(TINFO, "\tTest[%d] val %d done, count = %d, collide = %d.", // me, val, count, collide); //for (i = 0; i < NMISC; i++) // tst_resm(TINFO, "\t\tTest[%d]: %d %s's.", me, misc_cnt[i], m_str[i]); val0 = val++; } }
static void dotest(int testers, int me, int fd) { char *bits, *hold_bits; char val; int chunk, whenmisc, xfr, count, collide, i; /* Stuff for the readv call */ struct iovec r_iovec[MAXIOVCNT]; int r_ioveclen; /* Stuff for the writev call */ struct iovec val_iovec[MAXIOVCNT]; struct iovec zero_iovec[MAXIOVCNT]; int w_ioveclen; nchunks = max_size / csize; whenmisc = 0; if ((bits = malloc((nchunks + 7) / 8)) == 0) { tst_resm(TBROK, "\tmalloc failed"); tst_exit(); } if ((hold_bits = malloc((nchunks + 7) / 8)) == 0) { tst_resm(TBROK, "\tmalloc failed"); tst_exit(); } /*Allocate memory for the iovec buffers and init the iovec arrays */ r_ioveclen = w_ioveclen = csize / MAXIOVCNT; /* Please note that the above statement implies that csize * be evenly divisible by MAXIOVCNT. */ for (i = 0; i < MAXIOVCNT; i++) { if ((r_iovec[i].iov_base = calloc(r_ioveclen, 1)) == 0) { tst_brkm(TBROK, NULL, "\tmalloc failed"); /* tst_exit(); */ } r_iovec[i].iov_len = r_ioveclen; /* Allocate unused memory areas between all the buffers to * make things more diffult for the OS. */ if (malloc((i + 1) * 8) == NULL) { tst_brkm(TBROK, NULL, "\tmalloc failed"); } if ((val_iovec[i].iov_base = calloc(w_ioveclen, 1)) == 0) { tst_resm(TBROK, "\tmalloc failed"); tst_exit(); } val_iovec[i].iov_len = w_ioveclen; if (malloc((i + 1) * 8) == NULL) { tst_resm(TBROK, "\tmalloc failed"); tst_exit(); } if ((zero_iovec[i].iov_base = calloc(w_ioveclen, 1)) == 0) { tst_resm(TBROK, "\tmalloc failed"); tst_exit(); } zero_iovec[i].iov_len = w_ioveclen; if (malloc((i + 1) * 8) == NULL) { tst_resm(TBROK, "\tmalloc failed"); tst_exit(); } } /* * No init sectors; allow file to be sparse. */ val = (64 / testers) * me + 1; /* * For each iteration: * zap bits array * loop * pick random chunk, read it. * if corresponding bit off { * verify = 0. (sparse file) * ++count; * } else * verify = val. * write "val" on it. * repeat unitl count = nchunks. * ++val. */ srand(getpid()); if (misc_intvl) whenmisc = NEXTMISC; while (iterations-- > 0) { for (i = 0; i < NMISC; i++) misc_cnt[i] = 0; ftruncate(fd, 0); file_max = 0; memset(bits, 0, (nchunks + 7) / 8); memset(hold_bits, 0, (nchunks + 7) / 8); /* Have to fill the val and zero iov buffers in a different manner */ for (i = 0; i < MAXIOVCNT; i++) { memset(val_iovec[i].iov_base, val, val_iovec[i].iov_len); memset(zero_iovec[i].iov_base, 0, zero_iovec[i].iov_len); } count = 0; collide = 0; while (count < nchunks) { chunk = rand() % nchunks; /* * Read it. */ if (lseek(fd, CHUNK(chunk), 0) < 0) { tst_resm(TFAIL, "\tTest[%d]: lseek(0) fail at %x, errno = %d.", me, CHUNK(chunk), errno); tst_exit(); } if ((xfr = readv(fd, &r_iovec[0], MAXIOVCNT)) < 0) { tst_resm(TFAIL, "\tTest[%d]: readv fail at %x, errno = %d.", me, CHUNK(chunk), errno); tst_exit(); } /* * If chunk beyond EOF just write on it. * Else if bit off, haven't seen it yet. * Else, have. Verify values. */ if (CHUNK(chunk) >= file_max) { bits[chunk / 8] |= (1 << (chunk % 8)); ++count; } else if ((bits[chunk / 8] & (1 << (chunk % 8))) == 0) { if (xfr != csize) { tst_resm(TFAIL, "\tTest[%d]: xfr=%d != %d, zero read.", me, xfr, csize); tst_exit(); } for (i = 0; i < MAXIOVCNT; i++) { if (memcmp (r_iovec[i].iov_base, zero_iovec[i].iov_base, r_iovec[i].iov_len)) { tst_resm(TFAIL, "\tTest[%d] bad verify @ 0x%x for val %d count %d xfr %d file_max 0x%x, should be 0.", me, CHUNK(chunk), val, count, xfr, file_max); tst_resm(TINFO, "\tTest[%d]: last_trunc = 0x%x.", me, last_trunc); sync(); ft_dumpiov(&r_iovec[i]); ft_dumpbits(bits, (nchunks + 7) / 8); ft_orbits(hold_bits, bits, (nchunks + 7) / 8); tst_resm(TINFO, "\tHold "); ft_dumpbits(hold_bits, (nchunks + 7) / 8); tst_exit(); } } bits[chunk / 8] |= (1 << (chunk % 8)); ++count; } else { if (xfr != csize) { tst_resm(TFAIL, "\tTest[%d]: xfr=%d != %d, val read.", me, xfr, csize); tst_exit(); } ++collide; for (i = 0; i < MAXIOVCNT; i++) { if (memcmp (r_iovec[i].iov_base, val_iovec[i].iov_base, r_iovec[i].iov_len)) { tst_resm(TFAIL, "\tTest[%d] bad verify @ 0x%x for val %d count %d xfr %d file_max 0x%x.", me, CHUNK(chunk), val, count, xfr, file_max); tst_resm(TINFO, "\tTest[%d]: last_trunc = 0x%x.", me, last_trunc); sync(); ft_dumpiov(&r_iovec[i]); ft_dumpbits(bits, (nchunks + 7) / 8); ft_orbits(hold_bits, bits, (nchunks + 7) / 8); tst_resm(TINFO, "\tHold "); ft_dumpbits(hold_bits, (nchunks + 7) / 8); tst_exit(); } } } /* * Writev it. */ if (lseek(fd, -xfr, 1) < 0) { tst_resm(TFAIL, "\tTest[%d]: lseek(1) fail at %x, errno = %d.", me, CHUNK(chunk), errno); tst_exit(); } if ((xfr = writev(fd, &val_iovec[0], MAXIOVCNT)) < csize) { if (errno == ENOSPC) { tst_resm(TFAIL, "\tTest[%d]: no space, exiting.", me); fsync(fd); tst_exit(); } tst_resm(TFAIL, "\tTest[%d]: writev fail at %x xfr %d, errno = %d.", me, CHUNK(chunk), xfr, errno); tst_exit(); } if (CHUNK(chunk) + csize > file_max) file_max = CHUNK(chunk) + csize; /* * If hit "misc" interval, do it. */ if (misc_intvl && --whenmisc <= 0) { ft_orbits(hold_bits, bits, (nchunks + 7) / 8); domisc(me, fd, bits); whenmisc = NEXTMISC; } if (count + collide > 2 * nchunks) break; } /* * End of iteration, maybe before doing all chunks. */ fsync(fd); ++misc_cnt[m_fsync]; //tst_resm(TINFO, "\tTest{%d} val %d done, count = %d, collide = {%d}", // me, val, count, collide); //for (i = 0; i < NMISC; i++) // tst_resm(TINFO, "\t\tTest{%d}: {%d} %s's.", me, misc_cnt[i], m_str[i]); ++val; } }