Merge branch 'patch-1' of https://github.com/Nikratio/fio
[fio.git] / backend.c
index 399c299e14aa6f518502e02cf94f1def7e713403..c167f908625f39fd8e344c9f75c705f7fd71adf4 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -393,7 +393,7 @@ static bool break_on_this_error(struct thread_data *td, enum fio_ddir ddir,
                        td_clear_error(td);
                        *retptr = 0;
                        return false;
-               } else if (td->o.fill_device && err == ENOSPC) {
+               } else if (td->o.fill_device && (err == ENOSPC || err == EDQUOT)) {
                        /*
                         * We expect to hit this error if
                         * fill_device option is set.
@@ -837,7 +837,7 @@ static long long usec_for_io(struct thread_data *td, enum fio_ddir ddir)
        if (td->o.rate_process == RATE_PROCESS_POISSON) {
                uint64_t val, iops;
 
-               iops = bps / td->o.bs[ddir];
+               iops = bps / td->o.min_bs[ddir];
                val = (int64_t) (1000000 / iops) *
                                -logf(__rand_0_1(&td->poisson_state[ddir]));
                if (val) {
@@ -858,15 +858,47 @@ static long long usec_for_io(struct thread_data *td, enum fio_ddir ddir)
        return 0;
 }
 
+static void init_thinktime(struct thread_data *td)
+{
+       if (td->o.thinktime_blocks_type == THINKTIME_BLOCKS_TYPE_COMPLETE)
+               td->thinktime_blocks_counter = td->io_blocks;
+       else
+               td->thinktime_blocks_counter = td->io_issues;
+       td->last_thinktime = td->epoch;
+       td->last_thinktime_blocks = 0;
+}
+
 static void handle_thinktime(struct thread_data *td, enum fio_ddir ddir,
                             struct timespec *time)
 {
        unsigned long long b;
        uint64_t total;
        int left;
+       struct timespec now;
+       bool stall = false;
+
+       if (td->o.thinktime_iotime) {
+               fio_gettime(&now, NULL);
+               if (utime_since(&td->last_thinktime, &now)
+                   >= td->o.thinktime_iotime + td->o.thinktime) {
+                       stall = true;
+               } else if (!fio_option_is_set(&td->o, thinktime_blocks)) {
+                       /*
+                        * When thinktime_iotime is set and thinktime_blocks is
+                        * not set, skip the thinktime_blocks check, since
+                        * thinktime_blocks default value 1 does not work
+                        * together with thinktime_iotime.
+                        */
+                       return;
+               }
+
+       }
 
        b = ddir_rw_sum(td->thinktime_blocks_counter);
-       if (b % td->o.thinktime_blocks || !b)
+       if (b >= td->last_thinktime_blocks + td->o.thinktime_blocks)
+               stall = true;
+
+       if (!stall)
                return;
 
        io_u_quiesce(td);
@@ -902,6 +934,10 @@ static void handle_thinktime(struct thread_data *td, enum fio_ddir ddir,
 
        if (time && should_check_rate(td))
                fio_gettime(time, NULL);
+
+       td->last_thinktime_blocks = b;
+       if (td->o.thinktime_iotime)
+               td->last_thinktime = now;
 }
 
 /*
@@ -1105,7 +1141,7 @@ reap:
        if (td->trim_entries)
                log_err("fio: %lu trim entries leaked?\n", td->trim_entries);
 
-       if (td->o.fill_device && td->error == ENOSPC) {
+       if (td->o.fill_device && (td->error == ENOSPC || td->error == EDQUOT)) {
                td->error = 0;
                fio_mark_td_terminate(td);
        }
@@ -1120,7 +1156,8 @@ reap:
 
                if (i) {
                        ret = io_u_queued_complete(td, i);
-                       if (td->o.fill_device && td->error == ENOSPC)
+                       if (td->o.fill_device &&
+                           (td->error == ENOSPC || td->error == EDQUOT))
                                td->error = 0;
                }
 
@@ -1406,7 +1443,7 @@ static int set_ioscheduler(struct thread_data *td, struct fio_file *file)
 
        sprintf(tmp2, "[%s]", td->o.ioscheduler);
        if (!strstr(tmp, tmp2)) {
-               log_err("fio: io scheduler %s not found\n", td->o.ioscheduler);
+               log_err("fio: unable to set io scheduler to %s\n", td->o.ioscheduler);
                td_verror(td, EINVAL, "iosched_switch");
                fclose(f);
                return 1;
@@ -1759,6 +1796,7 @@ static void *thread_main(void *data)
                        td_verror(td, errno, "ioprio_set");
                        goto err;
                }
+               td->ioprio = ioprio_value(o->ioprio_class, o->ioprio);
        }
 
        if (o->cgroup && cgroup_setup(td, cgroup_list, &cgroup_mnt))
@@ -1790,17 +1828,14 @@ static void *thread_main(void *data)
        if (rate_submit_init(td, sk_out))
                goto err;
 
-       if (td->o.thinktime_blocks_type == THINKTIME_BLOCKS_TYPE_COMPLETE)
-               td->thinktime_blocks_counter = td->io_blocks;
-       else
-               td->thinktime_blocks_counter = td->io_issues;
-
        set_epoch_time(td, o->log_unix_epoch);
        fio_getrusage(&td->ru_start);
        memcpy(&td->bw_sample_time, &td->epoch, sizeof(td->epoch));
        memcpy(&td->iops_sample_time, &td->epoch, sizeof(td->epoch));
        memcpy(&td->ss.prev_time, &td->epoch, sizeof(td->epoch));
 
+       init_thinktime(td);
+
        if (o->ratemin[DDIR_READ] || o->ratemin[DDIR_WRITE] ||
                        o->ratemin[DDIR_TRIM]) {
                memcpy(&td->lastrate[DDIR_READ], &td->bw_sample_time,