Recent changes (master)

Jens Axboe
2015-12-11T13:00:06Z

The following changes since commit c5103619279883ee9291ed4793bb6ad39b436101:

eta: use bool for forcing jobs_eta return (2015-12-09 12:44:09 -0700)

are available in the git repository at:

git://git.kernel.dk/fio.git master

for you to fetch changes up to 408e0b90d74196f173c2008bc0034b70e9b56ddf:

log: remove log_local_buf() (2015-12-10 15:31:02 -0700)

----------------------------------------------------------------
Jens Axboe (4):
Add exitall_on_error option
mutex: fixup fio_mutex_down_timeout()
Add backend related data
log: remove log_local_buf()

HOWTO | 3 +++
backend.c | 18 +++++++++++-------
cconv.c | 2 ++
fio.1 | 4 ++++
fio.c | 2 +-
fio.h | 11 ++++++++++-
init.c | 1 +
log.c | 30 ++++++++++++++----------------
log.h | 1 -
mutex.c | 27 ++++++++++++++++++---------
options.c | 9 +++++++++
server.c | 6 +++---
thread_options.h | 3 ++-
13 files changed, 78 insertions(+), 39 deletions(-)

---

Diff of recent changes:

diff --git a/HOWTO b/HOWTO
index eb9c824..b21d27e 100644
--- a/HOWTO
+++ b/HOWTO
@@ -1227,6 +1227,9 @@ exitall When one job finishes, terminate the rest. The default is
to wait for each job to finish, sometimes that is not the
desired action.

+exitall_on_error When one job finishes in error, terminate the rest. The
+ default is to wait for each job to finish.
+
bwavgtime=int Average the calculated bandwidth over the given time. Value
is specified in milliseconds.

diff --git a/backend.c b/backend.c
index 425b0ee..c8554bc 100644
--- a/backend.c
+++ b/backend.c
@@ -974,7 +974,7 @@ reap:

if (!in_ramp_time(td) && should_check_rate(td)) {
if (check_min_rate(td, &comp_time)) {
- if (exitall_on_terminate)
+ if (exitall_on_terminate || td->o.exitall_error)
fio_terminate_threads(td->groupid);
td_verror(td, EIO, "check_min_rate");
break;
@@ -1662,7 +1662,7 @@ static void *thread_main(void *data)
if (o->exec_postrun)
exec_string(o, o->exec_postrun, (const char *)"postrun");

- if (exitall_on_terminate)
+ if (exitall_on_terminate || (o->exitall_error && td->error))
fio_terminate_threads(td->groupid);

err:
@@ -2117,7 +2117,7 @@ reap:
*fio_debug_jobp = pid;
}
dprint(FD_MUTEX, "wait on startup_mutex\n");
- if (fio_mutex_down_timeout(startup_mutex, 10)) {
+ if (fio_mutex_down_timeout(startup_mutex, 10000)) {
log_err("fio: job startup hung? exiting.\n");
fio_terminate_threads(TERMINATE_ALL);
fio_abort = 1;
@@ -2220,8 +2220,12 @@ static void free_disk_util(void)

static void *helper_thread_main(void *data)
{
+ struct backend_data *d = data;
int ret = 0;

+ if (d)
+ pthread_setspecific(d->key, d->ptr);
+
fio_mutex_up(startup_mutex);

while (!ret) {
@@ -2255,7 +2259,7 @@ static void *helper_thread_main(void *data)
return NULL;
}

-static int create_helper_thread(void)
+static int create_helper_thread(struct backend_data *data)
{
int ret;

@@ -2264,7 +2268,7 @@ static int create_helper_thread(void)
pthread_cond_init(&helper_cond, NULL);
pthread_mutex_init(&helper_lock, NULL);

- ret = pthread_create(&helper_thread, NULL, helper_thread_main, NULL);
+ ret = pthread_create(&helper_thread, NULL, helper_thread_main, data);
if (ret) {
log_err("Can't create helper thread: %s\n", strerror(ret));
return 1;
@@ -2276,7 +2280,7 @@ static int create_helper_thread(void)
return 0;
}

-int fio_backend(void)
+int fio_backend(struct backend_data *data)
{
struct thread_data *td;
int i;
@@ -2306,7 +2310,7 @@ int fio_backend(void)

set_genesis_time();
stat_init();
- create_helper_thread();
+ create_helper_thread(data);

cgroup_list = smalloc(sizeof(*cgroup_list));
INIT_FLIST_HEAD(cgroup_list);
diff --git a/cconv.c b/cconv.c
index c0168c4..a476aad 100644
--- a/cconv.c
+++ b/cconv.c
@@ -167,6 +167,7 @@ void convert_thread_options_to_cpu(struct thread_options *o,
o->fsync_on_close = le32_to_cpu(top->fsync_on_close);
o->bs_is_seq_rand = le32_to_cpu(top->bs_is_seq_rand);
o->random_distribution = le32_to_cpu(top->random_distribution);
+ o->exitall_error = le32_to_cpu(top->exitall_error);
o->zipf_theta.u.f = fio_uint64_to_double(le64_to_cpu(top->zipf_theta.u.i));
o->pareto_h.u.f = fio_uint64_to_double(le64_to_cpu(top->pareto_h.u.i));
o->gauss_dev.u.f = fio_uint64_to_double(le64_to_cpu(top->gauss_dev.u.i));
@@ -353,6 +354,7 @@ void convert_thread_options_to_net(struct thread_options_pack *top,
top->fsync_on_close = cpu_to_le32(o->fsync_on_close);
top->bs_is_seq_rand = cpu_to_le32(o->bs_is_seq_rand);
top->random_distribution = cpu_to_le32(o->random_distribution);
+ top->exitall_error = cpu_to_le32(o->exitall_error);
top->zipf_theta.u.i = __cpu_to_le64(fio_double_to_uint64(o->zipf_theta.u.f));
top->pareto_h.u.i = __cpu_to_le64(fio_double_to_uint64(o->pareto_h.u.f));
top->gauss_dev.u.i = __cpu_to_le64(fio_double_to_uint64(o->gauss_dev.u.f));
diff --git a/fio.1 b/fio.1
index eab20d7..4fe1be2 100644
--- a/fio.1
+++ b/fio.1
@@ -1126,6 +1126,10 @@ Should be a multiple of 1MB. Default: 4MB.
.B exitall
Terminate all jobs when one finishes. Default: wait for each job to finish.
.TP
+.B exitall_on_error \fR=\fPbool
+Terminate all jobs if one job finishes in error. Default: wait for each job
+to finish.
+.TP
.BI bwavgtime \fR=\fPint
Average bandwidth calculations over the given time in milliseconds. Default:
500ms.
diff --git a/fio.c b/fio.c
index bafbd48..bd3e260 100644
--- a/fio.c
+++ b/fio.c
@@ -57,7 +57,7 @@ int main(int argc, char *argv[], char *envp[])
goto done;
ret = fio_handle_clients(&fio_client_ops);
} else
- ret = fio_backend();
+ ret = fio_backend(NULL);

done:
deinitialize_fio();
diff --git a/fio.h b/fio.h
index 6f85266..63778b6 100644
--- a/fio.h
+++ b/fio.h
@@ -108,6 +108,15 @@ enum {
};

/*
+ * Per-thread/process specific data. Only used for the network client
+ * for now.
+ */
+struct backend_data {
+ pthread_key_t key;
+ void *ptr;
+};
+
+/*
* This describes a single thread/process executing a fio job.
*/
struct thread_data {
@@ -468,7 +477,7 @@ extern int __must_check fio_init_options(void);
extern int __must_check parse_options(int, char **);
extern int parse_jobs_ini(char *, int, int, int);
extern int parse_cmd_line(int, char **, int);
-extern int fio_backend(void);
+extern int fio_backend(struct backend_data *);
extern void reset_fio_state(void);
extern void clear_io_state(struct thread_data *, int);
extern int fio_options_parse(struct thread_data *, char **, int, int);
diff --git a/init.c b/init.c
index 0100da2..63ba324 100644
--- a/init.c
+++ b/init.c
@@ -47,6 +47,7 @@ static char **job_sections;
static int nr_job_sections;

int exitall_on_terminate = 0;
+int exitall_on_terminate_error = 0;
int output_format = FIO_OUTPUT_NORMAL;
int eta_print = FIO_ETA_AUTO;
int eta_new_line = 0;
diff --git a/log.c b/log.c
index d508267..4eb4af5 100644
--- a/log.c
+++ b/log.c
@@ -8,9 +8,13 @@

size_t log_info_buf(const char *buf, size_t len)
{
- if (is_backend)
- return fio_server_text_output(FIO_LOG_INFO, buf, len);
- else if (log_syslog) {
+ if (is_backend) {
+ size_t ret = fio_server_text_output(FIO_LOG_INFO, buf, len);
+ if (ret != -1)
+ return ret;
+ }
+
+ if (log_syslog) {
syslog(LOG_INFO, "%s", buf);
return len;
} else
@@ -27,16 +31,6 @@ size_t log_valist(const char *str, va_list args)
return log_info_buf(buffer, min(len, sizeof(buffer) - 1));
}

-size_t log_local_buf(const char *buf, size_t len)
-{
- if (log_syslog)
- syslog(LOG_INFO, "%s", buf);
- else
- len = fwrite(buf, len, 1, f_out);
-
- return len;
-}
-
size_t log_info(const char *format, ...)
{
char buffer[1024];
@@ -82,9 +76,13 @@ size_t log_err(const char *format, ...)
va_end(args);
len = min(len, sizeof(buffer) - 1);

- if (is_backend)
- return fio_server_text_output(FIO_LOG_ERR, buffer, len);
- else if (log_syslog) {
+ if (is_backend) {
+ size_t ret = fio_server_text_output(FIO_LOG_ERR, buffer, len);
+ if (ret != -1)
+ return ret;
+ }
+
+ if (log_syslog) {
syslog(LOG_INFO, "%s", buffer);
return len;
} else {
diff --git a/log.h b/log.h
index f1cf003..a39dea6 100644
--- a/log.h
+++ b/log.h
@@ -13,7 +13,6 @@ extern size_t log_err(const char *format, ...) __attribute__ ((__format__ (__pri
extern size_t log_info(const char *format, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
extern size_t __log_buf(struct buf_output *, const char *format, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
extern size_t log_valist(const char *str, va_list);
-extern size_t log_local_buf(const char *buf, size_t);
extern size_t log_info_buf(const char *buf, size_t len);
extern int log_info_flush(void);

diff --git a/mutex.c b/mutex.c
index 7612b32..a48e37d 100644
--- a/mutex.c
+++ b/mutex.c
@@ -92,12 +92,15 @@ struct fio_mutex *fio_mutex_init(int value)
return NULL;
}

-static bool mutex_timed_out(struct timeval *t, unsigned int seconds)
+static bool mutex_timed_out(struct timeval *t, unsigned int msecs)
{
- return mtime_since_now(t) >= seconds * 1000;
+ struct timeval now;
+
+ gettimeofday(&now, NULL);
+ return mtime_since(t, &now) >= msecs;
}

-int fio_mutex_down_timeout(struct fio_mutex *mutex, unsigned int seconds)
+int fio_mutex_down_timeout(struct fio_mutex *mutex, unsigned int msecs)
{
struct timeval tv_s;
struct timespec t;
@@ -106,30 +109,36 @@ int fio_mutex_down_timeout(struct fio_mutex *mutex, unsigned int seconds)
assert(mutex->magic == FIO_MUTEX_MAGIC);

gettimeofday(&tv_s, NULL);
- t.tv_sec = tv_s.tv_sec + seconds;
+ t.tv_sec = tv_s.tv_sec;
t.tv_nsec = tv_s.tv_usec * 1000;

+ t.tv_sec += msecs / 1000;
+ t.tv_nsec += ((msecs * 1000000) % 1000000000);
+ if (t.tv_nsec >= 1000000000) {
+ t.tv_nsec -= 1000000000;
+ t.tv_sec++;
+ }
+
pthread_mutex_lock(&mutex->lock);

+ mutex->waiters++;
while (!mutex->value && !ret) {
- mutex->waiters++;
-
/*
* Some platforms (FreeBSD 9?) seems to return timed out
* way too early, double check.
*/
ret = pthread_cond_timedwait(&mutex->cond, &mutex->lock, &t);
- if (ret == ETIMEDOUT && !mutex_timed_out(&tv_s, seconds))
+ if (ret == ETIMEDOUT && !mutex_timed_out(&tv_s, msecs))
ret = 0;
-
- mutex->waiters--;
}
+ mutex->waiters--;

if (!ret) {
mutex->value--;
pthread_mutex_unlock(&mutex->lock);
}

+ pthread_mutex_unlock(&mutex->lock);
return ret;
}

diff --git a/options.c b/options.c
index 627029c..46d5fb9 100644
--- a/options.c
+++ b/options.c
@@ -3141,6 +3141,15 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
.group = FIO_OPT_G_PROCESS,
},
{
+ .name = "exitall_on_error",
+ .lname = "Exit-all on terminate in error",
+ .type = FIO_OPT_BOOL,
+ .off1 = td_var_offset(unlink),
+ .help = "Terminate all jobs when one exits in error",
+ .category = FIO_OPT_C_GENERAL,
+ .group = FIO_OPT_G_PROCESS,
+ },
+ {
.name = "stonewall",
.lname = "Wait for previous",
.alias = "wait_for_previous",
diff --git a/server.c b/server.c
index cf01733..27ea282 100644
--- a/server.c
+++ b/server.c
@@ -601,7 +601,7 @@ static int handle_run_cmd(struct flist_head *job_list, struct fio_net_cmd *cmd)
return 0;
}

- ret = fio_backend();
+ ret = fio_backend(NULL);
free_threads_shm();
_exit(ret);
}
@@ -1061,7 +1061,7 @@ int fio_server_text_output(int level, const char *buf, size_t len)
struct timeval tv;

if (server_fd == -1)
- return log_local_buf(buf, len);
+ return -1;

tlen = sizeof(*pdu) + len;
pdu = malloc(tlen);
@@ -1445,7 +1445,7 @@ int fio_server_get_verify_state(const char *name, int threadnumber,
/*
* Wait for the backend to receive the reply
*/
- if (fio_mutex_down_timeout(&rep->lock, 10)) {
+ if (fio_mutex_down_timeout(&rep->lock, 10000)) {
log_err("fio: timed out waiting for reply\n");
goto fail;
}
diff --git a/thread_options.h b/thread_options.h
index 02c867f..6ae0335 100644
--- a/thread_options.h
+++ b/thread_options.h
@@ -131,6 +131,7 @@ struct thread_options {
unsigned int verify_only;

unsigned int random_distribution;
+ unsigned int exitall_error;

fio_fp64_t zipf_theta;
fio_fp64_t pareto_h;
@@ -376,7 +377,7 @@ struct thread_options_pack {
uint32_t bs_is_seq_rand;

uint32_t random_distribution;
- uint32_t pad;
+ uint32_t exitall_error;

fio_fp64_t zipf_theta;
fio_fp64_t pareto_h;