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.
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->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) {
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 {
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;