+static bool __check_trigger_file(void)
+{
+ struct stat sb;
+
+ if (!trigger_file)
+ return false;
+
+ if (stat(trigger_file, &sb))
+ return false;
+
+ if (unlink(trigger_file) < 0)
+ log_err("fio: failed to unlink %s: %s\n", trigger_file,
+ strerror(errno));
+
+ return true;
+}
+
+static bool trigger_timedout(void)
+{
+ if (trigger_timeout)
+ return time_since_genesis() >= trigger_timeout;
+
+ return false;
+}
+
+void exec_trigger(const char *cmd)
+{
+ int ret;
+
+ if (!cmd)
+ return;
+
+ ret = system(cmd);
+ if (ret == -1)
+ log_err("fio: failed executing %s trigger\n", cmd);
+}
+
+void check_trigger_file(void)
+{
+ if (__check_trigger_file() || trigger_timedout()) {
+ if (nr_clients)
+ fio_clients_send_trigger(trigger_remote_cmd);
+ else {
+ verify_save_state(IO_LIST_ALL);
+ fio_terminate_threads(TERMINATE_ALL);
+ exec_trigger(trigger_cmd);
+ }
+ }
+}
+
+static int fio_verify_load_state(struct thread_data *td)
+{
+ int ret;
+
+ if (!td->o.verify_state)
+ return 0;
+
+ if (is_backend) {
+ void *data;
+ int ver;
+
+ ret = fio_server_get_verify_state(td->o.name,
+ td->thread_number - 1, &data, &ver);
+ if (!ret)
+ verify_convert_assign_state(td, data, ver);
+ } else
+ ret = verify_load_state(td, "local");
+
+ return ret;
+}
+
+static void do_usleep(unsigned int usecs)
+{
+ check_for_running_stats();
+ check_trigger_file();
+ usleep(usecs);
+}
+
+static bool check_mount_writes(struct thread_data *td)
+{
+ struct fio_file *f;
+ unsigned int i;
+
+ if (!td_write(td) || td->o.allow_mounted_write)
+ return false;
+
+ for_each_file(td, f, i) {
+ if (f->filetype != FIO_TYPE_BD)
+ continue;
+ if (device_is_mounted(f->file_name))
+ goto mounted;
+ }
+
+ return false;
+mounted:
+ log_err("fio: %s appears mounted, and 'allow_mounted_write' isn't set. Aborting.", f->file_name);
+ return true;
+}
+
+static bool waitee_running(struct thread_data *me)
+{
+ const char *waitee = me->o.wait_for;
+ const char *self = me->o.name;
+ struct thread_data *td;
+ int i;
+
+ if (!waitee)
+ return false;
+
+ for_each_td(td, i) {
+ if (!strcmp(td->o.name, self) || strcmp(td->o.name, waitee))
+ continue;
+
+ if (td->runstate < TD_EXITED) {
+ dprint(FD_PROCESS, "%s fenced by %s(%s)\n",
+ self, td->o.name,
+ runstate_to_name(td->runstate));
+ return true;
+ }
+ }
+
+ dprint(FD_PROCESS, "%s: %s completed, can run\n", self, waitee);
+ return false;
+}
+