Skip to content

Commit

Permalink
io_u: make rate-submit in inline mode even
Browse files Browse the repository at this point in the history
In `inline` submit mode, threads wait until all previous IOs finish upon
reaching rate limits, which may exceed the expected wait time and result
in batch or uneven submissions.

Handle completion events in usec_sleep() when necessary and no longer call
io_u_quiesce() before sleeping in rate_ddir() to achieve smoother fix-rate
submission as in `offload` mode.

Signed-off-by: wanghonghao <wanghonghao@bytedance.com>
  • Loading branch information
qsqx committed Apr 17, 2024
1 parent 4eef23f commit 2363117
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 25 deletions.
12 changes: 6 additions & 6 deletions backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ static void cleanup_pending_aio(struct thread_data *td)
/*
* get immediately available events, if any
*/
r = io_u_queued_complete(td, 0);
r = io_u_queued_complete(td, 0, NULL);

/*
* now cancel remaining active events
Expand All @@ -252,7 +252,7 @@ static void cleanup_pending_aio(struct thread_data *td)
}

if (td->cur_depth)
r = io_u_queued_complete(td, td->cur_depth);
r = io_u_queued_complete(td, td->cur_depth, NULL);
}

/*
Expand Down Expand Up @@ -281,7 +281,7 @@ static bool fio_io_sync(struct thread_data *td, struct fio_file *f)
switch (ret) {
case FIO_Q_QUEUED:
td_io_commit(td);
if (io_u_queued_complete(td, 1) < 0)
if (io_u_queued_complete(td, 1, NULL) < 0)
return true;
break;
case FIO_Q_COMPLETED:
Expand Down Expand Up @@ -433,7 +433,7 @@ static int wait_for_completions(struct thread_data *td, struct timespec *time)
fio_gettime(time, NULL);

do {
ret = io_u_queued_complete(td, min_evts);
ret = io_u_queued_complete(td, min_evts, NULL);
if (ret < 0)
break;
} while (full && (td->cur_depth > td->o.iodepth_low));
Expand Down Expand Up @@ -753,7 +753,7 @@ static void do_verify(struct thread_data *td, uint64_t verify_bytes)
min_events = td->cur_depth;

if (min_events)
ret = io_u_queued_complete(td, min_events);
ret = io_u_queued_complete(td, min_events, NULL);
} else
cleanup_pending_aio(td);

Expand Down Expand Up @@ -1175,7 +1175,7 @@ static void do_io(struct thread_data *td, uint64_t *bytes_done)
i = td->cur_depth;

if (i) {
ret = io_u_queued_complete(td, i);
ret = io_u_queued_complete(td, i, NULL);
if (td->o.fill_device &&
(td->error == ENOSPC || td->error == EDQUOT))
td->error = 0;
Expand Down
22 changes: 7 additions & 15 deletions io_u.c
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,7 @@ int io_u_quiesce(struct thread_data *td)
td_io_commit(td);

while (td->io_u_in_flight) {
ret = io_u_queued_complete(td, 1);
ret = io_u_queued_complete(td, 1, NULL);
if (ret > 0)
completed += ret;
else if (ret < 0)
Expand Down Expand Up @@ -709,24 +709,17 @@ static enum fio_ddir rate_ddir(struct thread_data *td, enum fio_ddir ddir)
} else
usec = td->rate_next_io_time[ddir] - now;

if (td->o.io_submit_mode == IO_MODE_INLINE)
io_u_quiesce(td);

if (td->o.timeout && ((usec + now) > td->o.timeout)) {
/*
* check if the usec is capable of taking negative values
*/
if (now > td->o.timeout) {
ddir = DDIR_TIMEOUT;
return ddir;
if (now < td->o.timeout) {
usec_sleep(td, td->o.timeout - now);
}
usec = td->o.timeout - now;
}
usec_sleep(td, usec);

now = utime_since_now(&td->epoch);
if ((td->o.timeout && (now > td->o.timeout)) || td->terminate)
ddir = DDIR_TIMEOUT;
} else {
usec_sleep(td, usec);
}

return ddir;
}
Expand Down Expand Up @@ -2251,10 +2244,9 @@ int io_u_sync_complete(struct thread_data *td, struct io_u *io_u)
/*
* Called to complete min_events number of io for the async engines.
*/
int io_u_queued_complete(struct thread_data *td, int min_evts)
int io_u_queued_complete(struct thread_data *td, int min_evts, struct timespec *tvp)
{
struct io_completion_data icd;
struct timespec *tvp = NULL;
int ret;
struct timespec ts = { .tv_sec = 0, .tv_nsec = 0, };

Expand Down
2 changes: 1 addition & 1 deletion io_u.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ extern void put_io_u(struct thread_data *, struct io_u *);
extern void clear_io_u(struct thread_data *, struct io_u *);
extern void requeue_io_u(struct thread_data *, struct io_u **);
extern int __must_check io_u_sync_complete(struct thread_data *, struct io_u *);
extern int __must_check io_u_queued_complete(struct thread_data *, int);
extern int __must_check io_u_queued_complete(struct thread_data *, int, struct timespec *);
extern void io_u_queued(struct thread_data *, struct io_u *);
extern int io_u_quiesce(struct thread_data *);
extern void io_u_log_error(struct thread_data *, struct io_u *);
Expand Down
2 changes: 1 addition & 1 deletion iolog.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ static void iolog_delay(struct thread_data *td, unsigned long delay)
fio_gettime(&ts, NULL);

while (delay && !td->terminate) {
ret = io_u_queued_complete(td, 0);
ret = io_u_queued_complete(td, 0, NULL);
if (ret < 0)
td_verror(td, -ret, "io_u_queued_complete");
if (td->flags & TD_F_REGROW_LOGS)
Expand Down
4 changes: 2 additions & 2 deletions rate-submit.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ static int io_workqueue_fn(struct submit_worker *sw,
ret = td_io_queue(td, io_u);
if (ret != FIO_Q_BUSY)
break;
ret = io_u_queued_complete(td, 1);
ret = io_u_queued_complete(td, 1, NULL);
if (ret > 0)
td->cur_depth -= ret;
else if (ret < 0)
Expand All @@ -103,7 +103,7 @@ static int io_workqueue_fn(struct submit_worker *sw,
else
min_evts = 0;

ret = io_u_queued_complete(td, min_evts);
ret = io_u_queued_complete(td, min_evts, NULL);
if (ret > 0)
td->cur_depth -= ret;
}
Expand Down
21 changes: 21 additions & 0 deletions time.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,27 @@ uint64_t usec_sleep(struct thread_data *td, unsigned long usec)
struct timespec tv;
uint64_t t = 0;

if (td->o.io_submit_mode == IO_MODE_INLINE) {
struct timespec ts;
int err = 0;

fio_gettime(&tv, NULL);
if (td->io_u_queued || td->cur_depth)
td_io_commit(td);

while ((t = utime_since_now(&tv)) < usec &&
td->io_u_in_flight && err == 0) {
ts.tv_sec = (usec - t) / 1000000;
ts.tv_nsec = (usec - t) % 1000000 * 1000;
err = io_u_queued_complete(td, 1, &ts);
}

if (td->flags & TD_F_REGROW_LOGS)
regrow_logs(td);

usec = t < usec ? usec - t : 0;
}

do {
unsigned long ts = usec;

Expand Down

0 comments on commit 2363117

Please sign in to comment.