Fix broken requeue of io_us
authorJens Axboe <axboe@kernel.dk>
Mon, 9 Sep 2013 21:16:28 +0000 (15:16 -0600)
committerJens Axboe <axboe@kernel.dk>
Mon, 9 Sep 2013 21:16:28 +0000 (15:16 -0600)
Suresh reports:

-----

Does a requeued io_u work get submitted again through __get_io_u() ? If
so, the io_u item is taken out of requeue list & then the io_u->file is
set to NULL. We don't make a distinction about item being already setup
Vs a new io_u in __get_io_u(). In get_io_u(), when an io_u may come out
of requeue list, we depend on io_u->file to be non NULL to detect the
work as old pending one.

Am I missing something here or is this a bug?

1274         io_u = __get_io_u(td);
1275         if (!io_u) {
1276                 dprint(FD_IO, "__get_io_u failed\n");
1277                 return NULL;
1278         }
1279
1280         if (check_get_verify(td, io_u))
1281                 goto out;
1282         if (check_get_trim(td, io_u))
1283                 goto out;
1284
1285         /*
1286          * from a requeue, io_u already setup
1287          */
1288         if (io_u->file)
1289                 goto out;
1290
"io_u.c" line 1286 of 1667 --77%-- col 3-10

1130 struct io_u *__get_io_u(struct thread_data *td)
1131 {
1132         struct io_u *io_u;
1133
1134         td_io_u_lock(td);
1135
1136 again:
1137         if (!io_u_rempty(&td->io_u_requeues))
1138                 io_u = io_u_rpop(&td->io_u_requeues);
1139         else if (!io_u_qempty(&td->io_u_freelist))
1140                 io_u = io_u_qpop(&td->io_u_freelist);
1141
1142         if (io_u) {
1143                 io_u->buflen = 0;
1144                 io_u->resid = 0;
1145                 io_u->file = NULL;
1146                 io_u->end_io = NULL;
1147         }
"io_u.c" line 1130 of 1667 --67%-- col 1

-----

We want a retry of a requeue to be identical, not some
new chunk (and drop the latter one on the floor). This got broken with
the introduction of the rings instead of lists, where a single if
section was split into two.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_u.c

diff --git a/io_u.c b/io_u.c
index c50a17dfb8d5580a1fd7f646aec37a076c27821f..7df57aa804316a01efe1422e0d924dfa77b82f65 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -1136,10 +1136,9 @@ struct io_u *__get_io_u(struct thread_data *td)
 again:
        if (!io_u_rempty(&td->io_u_requeues))
                io_u = io_u_rpop(&td->io_u_requeues);
 again:
        if (!io_u_rempty(&td->io_u_requeues))
                io_u = io_u_rpop(&td->io_u_requeues);
-       else if (!io_u_qempty(&td->io_u_freelist))
+       else if (!io_u_qempty(&td->io_u_freelist)) {
                io_u = io_u_qpop(&td->io_u_freelist);
 
                io_u = io_u_qpop(&td->io_u_freelist);
 
-       if (io_u) {
                io_u->buflen = 0;
                io_u->resid = 0;
                io_u->file = NULL;
                io_u->buflen = 0;
                io_u->resid = 0;
                io_u->file = NULL;