The following changes since commit 479471c409a61d01290ac9444042357b03f8d0b0:
server: make the connect code fully IPv6 (2014-01-23 20:42:06 -0800)
are available in the git repository at:
git://git.kernel.dk/fio.git master
Jens Axboe (2):
engine: more checks on IPv6 and multicast
Add verify_only to man page
Juan Casse (3):
Adds check for numberio during verify phase.
Adds verify_only option
Adds check for rand_seed during verify phase.
HOWTO | 11 ++++++++-
backend.c | 43 ++++++++++++++++++++++++++++++++++++-
engines/net.c | 8 ++++++-
fio.1 | 7 ++++++
ioengine.h | 1 +
iolog.c | 1 +
iolog.h | 1 +
libfio.c | 1 -
options.c | 9 +++++++
thread_options.h | 2 +
verify.c | 63 +++++++++++++++++++++++++++++++++++++++++++++--------
11 files changed, 133 insertions(+), 14 deletions(-)
---
Diff of recent changes:
diff --git a/HOWTO b/HOWTO
index e69cf41..9830fa1 100644
--- a/HOWTO
+++ b/HOWTO
@@ -1068,6 +1068,13 @@ loops=int Run the specified number of iterations
of this job. Used
to repeat the same workload a given number of times. Defaults
to 1.
+verify_only Do not perform specified workload---only verify data still
+ matches previous invocation of this workload. This option
+ allows one to check data multiple times at a later date
+ without overwriting it. This option makes sense only for
+ workloads that write data, and does not support workloads
+ with the time_based option set.
+
do_verify=bool Run the verify phase after a write phase. Only makes sense if
verify is set. Defaults to 1.
@@ -1106,7 +1113,9 @@ verify=str If writing to a file, fio can verify
the file contents
meta Write extra information about each io
(timestamp, block number etc.). The block
- number is verified. See also verify_pattern.
+ number is verified. The io sequence number is
+ verified for workloads that write data.
+ See also verify_pattern.
null Only pretend to verify. Useful for testing
internals with ioengine=null, not for much
diff --git a/backend.c b/backend.c
index c9a20a3..93e6632 100644
--- a/backend.c
+++ b/backend.c
@@ -1120,6 +1120,44 @@ static int exec_string(struct thread_options *o, const
char *string, const char
}
/*
+ * Dry run to compute correct state of numberio for verification.
+ */
+static uint64_t do_dry_run(struct thread_data *td)
+{
+ uint64_t bytes_done[DDIR_RWDIR_CNT] = { 0, 0, 0 };
+
+ td_set_runstate(td, TD_RUNNING);
+
+ while ((td->o.read_iolog_file && !flist_empty(&td->io_log_list)) ||
+ (!flist_empty(&td->trim_list)) || !io_bytes_exceeded(td)) {
+ struct io_u *io_u;
+ int ret;
+
+ if (td->terminate || td->done)
+ break;
+
+ io_u = get_io_u(td);
+ if (!io_u)
+ break;
+
+ io_u->flags |= IO_U_F_FLIGHT;
+ io_u->error = 0;
+ io_u->resid = 0;
+ if (ddir_rw(acct_ddir(io_u)))
+ td->io_issues[acct_ddir(io_u)]++;
+ if (ddir_rw(io_u->ddir)) {
+ io_u_mark_depth(td, 1);
+ td->ts.total_io_u[io_u->ddir]++;
+ }
+
+ ret = io_u_sync_complete(td, io_u, bytes_done);
+ (void) ret;
+ }
+
+ return bytes_done[DDIR_WRITE] + bytes_done[DDIR_TRIM];
+}
+
+/*
* Entry point for the thread based jobs. The process based jobs end up
* here as well, after a little setup.
*/
@@ -1332,7 +1370,10 @@ static void *thread_main(void *data)
prune_io_piece_log(td);
- verify_bytes = do_io(td);
+ if (td->o.verify_only && (td_write(td) || td_rw(td)))
+ verify_bytes = do_dry_run(td);
+ else
+ verify_bytes = do_io(td);
clear_state = 1;
diff --git a/engines/net.c b/engines/net.c
index 5fdc88c..4be106a 100644
--- a/engines/net.c
+++ b/engines/net.c
@@ -1039,12 +1039,17 @@ static int fio_netio_setup_listen_inet(struct
thread_data *td, short port)
}
#endif
- if (td->o.filename){
+ if (td->o.filename) {
if (!is_udp(o) || !fio_netio_is_multicast(td->o.filename)) {
log_err("fio: hostname not valid for non-multicast
inbound network IO\n");
close(fd);
return 1;
}
+ if (is_ipv6(o)) {
+ log_err("fio: IPv6 not supported for multicast network
IO");
+ close(fd);
+ return 1;
+ }
inet_aton(td->o.filename, &sin.sin_addr);
@@ -1058,6 +1063,7 @@ static int fio_netio_setup_listen_inet(struct thread_data
*td, short port)
} else {
mr.imr_interface.s_addr = htonl(INADDR_ANY);
}
+
if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const
char*)&mr, sizeof(mr)) < 0) {
td_verror(td, errno, "setsockopt IP_ADD_MEMBERSHIP");
close(fd);
diff --git a/fio.1 b/fio.1
index b5ff80c..3cdfd27 100644
--- a/fio.1
+++ b/fio.1
@@ -934,6 +934,13 @@ Unlink job files when done. Default: false.
Specifies the number of iterations (runs of the same workload) of this job.
Default: 1.
.TP
+.BI verify_only \fR=\fPbool
+Do not perform the specified workload, only verify data still matches previous
+invocation of this workload. This option allows one to check data multiple
+times at a later date without overwriting it. This option makes sense only for
+workloads that write data, and does not support workloads with the
+\fBtime_based\fR option set.
+.TP
.BI do_verify \fR=\fPbool
Run the verify phase after a write phase. Only valid if \fBverify\fR is set.
Default: true.
diff --git a/ioengine.h b/ioengine.h
index 6dd2aa4..949af91 100644
--- a/ioengine.h
+++ b/ioengine.h
@@ -50,6 +50,7 @@ struct io_u {
*/
unsigned long buflen;
unsigned long long offset;
+ unsigned short numberio;
void *buf;
/*
diff --git a/iolog.c b/iolog.c
index 6593367..ec29971 100644
--- a/iolog.c
+++ b/iolog.c
@@ -188,6 +188,7 @@ void log_io_piece(struct thread_data *td, struct io_u *io_u)
ipo->file = io_u->file;
ipo->offset = io_u->offset;
ipo->len = io_u->buflen;
+ ipo->numberio = io_u->numberio;
if (io_u_should_trim(td, io_u)) {
flist_add_tail(&ipo->trim_list, &td->trim_list);
diff --git a/iolog.h b/iolog.h
index 6503acf..321576d 100644
--- a/iolog.h
+++ b/iolog.h
@@ -83,6 +83,7 @@ struct io_piece {
struct fio_file *file;
};
unsigned long long offset;
+ unsigned short numberio;
unsigned long len;
unsigned int flags;
enum fio_ddir ddir;
diff --git a/libfio.c b/libfio.c
index 7eb4576..222cd16 100644
--- a/libfio.c
+++ b/libfio.c
@@ -85,7 +85,6 @@ static void reset_io_counters(struct thread_data *td)
td->this_io_blocks[ddir] = 0;
td->rate_bytes[ddir] = 0;
td->rate_blocks[ddir] = 0;
- td->io_issues[ddir] = 0;
}
td->zone_bytes = 0;
diff --git a/options.c b/options.c
index b1b6c8e..525d318 100644
--- a/options.c
+++ b/options.c
@@ -2018,6 +2018,15 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
.group = FIO_OPT_G_RUNTIME,
},
{
+ .name = "verify_only",
+ .lname = "Verify only",
+ .type = FIO_OPT_STR_SET,
+ .off1 = td_var_offset(verify_only),
+ .help = "Verifies previously written data is still valid",
+ .category = FIO_OPT_C_GENERAL,
+ .group = FIO_OPT_G_RUNTIME,
+ },
+ {
.name = "ramp_time",
.lname = "Ramp time",
.type = FIO_OPT_STR_VAL_TIME,
diff --git a/thread_options.h b/thread_options.h
index f40a992..2f807cd 100644
--- a/thread_options.h
+++ b/thread_options.h
@@ -109,6 +109,8 @@ struct thread_options {
unsigned int fsync_on_close;
unsigned int bs_is_seq_rand;
+ unsigned int verify_only;
+
unsigned int random_distribution;
fio_fp64_t zipf_theta;
diff --git a/verify.c b/verify.c
index 721aeb4..568bae8 100644
--- a/verify.c
+++ b/verify.c
@@ -383,6 +383,19 @@ static int verify_io_u_meta(struct verify_header *hdr,
struct vcont *vc)
if (td->o.verify_pattern_bytes)
ret |= verify_io_u_pattern(hdr, vc);
+ /*
+ * For read-only workloads, the program cannot be certain of the
+ * last numberio written to a block. Checking of numberio will be done
+ * only for workloads that write data.
+ * For verify_only, numberio will be checked in the last iteration when
+ * the correct state of numberio, that would have been written to each
+ * block in a previous run of fio, has been reached.
+ */
+ if (td_write(td) || td_rw(td))
+ if (!td->o.verify_only || td->o.loops == 0)
+ if (vh->numberio != io_u->numberio)
+ ret = EILSEQ;
+
if (!ret)
return 0;
@@ -658,18 +671,17 @@ static int verify_header(struct io_u *io_u, struct
verify_header *hdr)
uint32_t crc;
if (hdr->magic != FIO_HDR_MAGIC)
- return 0;
- if (hdr->len > io_u->buflen) {
- log_err("fio: verify header exceeds buffer length (%u >
%lu)\n", hdr->len, io_u->buflen);
- return 0;
- }
+ return 1;
+ if (hdr->len > io_u->buflen)
+ return 2;
+ if (hdr->rand_seed != io_u->rand_seed)
+ return 3;
crc = fio_crc32c(p, offsetof(struct verify_header, crc32));
if (crc == hdr->crc32)
- return 1;
-
+ return 0;
log_err("fio: verify header crc %x, calculated %x\n", hdr->crc32, crc);
- return 0;
+ return 4;
}
int verify_io_u(struct thread_data *td, struct io_u *io_u)
@@ -706,13 +718,41 @@ int verify_io_u(struct thread_data *td, struct io_u *io_u)
memswp(p, p + td->o.verify_offset, header_size);
hdr = p;
- if (!verify_header(io_u, hdr)) {
+ ret = verify_header(io_u, hdr);
+ switch (ret) {
+ case 0:
+ break;
+ case 1:
log_err("verify: bad magic header %x, wanted %x at "
"file %s offset %llu, length %u\n",
hdr->magic, FIO_HDR_MAGIC,
io_u->file->file_name,
io_u->offset + hdr_num * hdr->len, hdr->len);
return EILSEQ;
+ break;
+ case 2:
+ log_err("fio: verify header exceeds buffer length (%u "
+ "> %lu)\n", hdr->len, io_u->buflen);
+ return EILSEQ;
+ break;
+ case 3:
+ log_err("verify: bad header rand_seed %"PRIu64
+ ", wanted %"PRIu64" at file %s offset %llu, "
+ "length %u\n",
+ hdr->rand_seed, io_u->rand_seed,
+ io_u->file->file_name,
+ io_u->offset + hdr_num * hdr->len, hdr->len);
+ return EILSEQ;
+ break;
+ case 4:
+ return EILSEQ;
+ break;
+ default:
+ log_err("verify: unknown header error at file %s "
+ "offset %llu, length %u\n",
+ io_u->file->file_name,
+ io_u->offset + hdr_num * hdr->len, hdr->len);
+ return EILSEQ;
}
if (td->o.verify != VERIFY_NONE)
@@ -782,7 +822,7 @@ static void fill_meta(struct verify_header *hdr, struct
thread_data *td,
vh->time_sec = io_u->start_time.tv_sec;
vh->time_usec = io_u->start_time.tv_usec;
- vh->numberio = td->io_issues[DDIR_WRITE];
+ vh->numberio = io_u->numberio;
vh->offset = io_u->offset + header_num * td->o.verify_interval;
}
@@ -956,6 +996,8 @@ void populate_verify_io_u(struct thread_data *td, struct
io_u *io_u)
if (td->o.verify == VERIFY_NULL)
return;
+ io_u->numberio = td->io_issues[io_u->ddir];
+
fill_pattern_headers(td, io_u, 0, 0);
}
@@ -988,6 +1030,7 @@ int get_next_verify(struct thread_data *td, struct io_u
*io_u)
io_u->offset = ipo->offset;
io_u->buflen = ipo->len;
+ io_u->numberio = ipo->numberio;
io_u->file = ipo->file;
io_u->flags |= IO_U_F_VER_LIST;
--
To unsubscribe from this list: send the line "unsubscribe fio" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html