engines/io_uring: Fully clear out previous SQE contents.
authorAndres Freund <andres@anarazel.de>
Fri, 13 Sep 2019 19:10:10 +0000 (12:10 -0700)
committerAndres Freund <andres@anarazel.de>
Fri, 13 Sep 2019 19:18:23 +0000 (12:18 -0700)
Without this change SQEs can contain data set in previous
submissions. E.g. a WRITE following an fdatasync would have still have
IORING_FSYNC_DATASYNC set in sync_flags, which shares storage with the
WRITE's rw_flags. Which was not reset, causing all writes to be
synchronous. Similarly, an fsync following a READ/WRITE would not
reset off/addr/len, which causes errors, because the kernel's
io_prep_fsync returns an error if e.g. addr is not 0.

While this could also be fixed by resetting only the unused fields in
the respective branches, it seems less failure prone to start with a
zeroed out sqe.

engines/io_uring.c

index 53cb60c5a50042fe7a33ff70c8f1f984adf8a586..e5edfcd25c60cd59062290e751fc7f5e877c064d 100644 (file)
@@ -152,15 +152,16 @@ static int fio_ioring_prep(struct thread_data *td, struct io_u *io_u)
        struct io_uring_sqe *sqe;
 
        sqe = &ld->sqes[io_u->index];
        struct io_uring_sqe *sqe;
 
        sqe = &ld->sqes[io_u->index];
+
+       /* zero out fields not used in this submission */
+       memset(sqe, 0, sizeof(*sqe));
+
        if (o->registerfiles) {
                sqe->fd = f->engine_pos;
                sqe->flags = IOSQE_FIXED_FILE;
        } else {
                sqe->fd = f->fd;
        if (o->registerfiles) {
                sqe->fd = f->engine_pos;
                sqe->flags = IOSQE_FIXED_FILE;
        } else {
                sqe->fd = f->fd;
-               sqe->flags = 0;
        }
        }
-       sqe->ioprio = 0;
-       sqe->buf_index = 0;
 
        if (io_u->ddir == DDIR_READ || io_u->ddir == DDIR_WRITE) {
                if (o->fixedbufs) {
 
        if (io_u->ddir == DDIR_READ || io_u->ddir == DDIR_WRITE) {
                if (o->fixedbufs) {
@@ -187,7 +188,6 @@ static int fio_ioring_prep(struct thread_data *td, struct io_u *io_u)
                        sqe->sync_range_flags = td->o.sync_file_range;
                        sqe->opcode = IORING_OP_SYNC_FILE_RANGE;
                } else {
                        sqe->sync_range_flags = td->o.sync_file_range;
                        sqe->opcode = IORING_OP_SYNC_FILE_RANGE;
                } else {
-                       sqe->fsync_flags = 0;
                        if (io_u->ddir == DDIR_DATASYNC)
                                sqe->fsync_flags |= IORING_FSYNC_DATASYNC;
                        sqe->opcode = IORING_OP_FSYNC;
                        if (io_u->ddir == DDIR_DATASYNC)
                                sqe->fsync_flags |= IORING_FSYNC_DATASYNC;
                        sqe->opcode = IORING_OP_FSYNC;