Skip to content

Commit cb41d92

Browse files
author
gd.zhou
committed
When async_io is enabled, invoking abortIO may leave pending asynchronous requests
unprocessed, leading to the inability to handle subsequent normal requests. This can ultimately result in thread blocking. This commit ensures that new requests are properly scheduled and processed even during or after an abortIO operation, preventing potential deadlocks or stalls.
1 parent 61cd706 commit cb41d92

2 files changed

Lines changed: 40 additions & 26 deletions

File tree

env/fs_posix.cc

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,31 @@ class PosixFileSystem : public FileSystem {
995995
return false;
996996
}
997997
}
998+
void HandleFinishedIO(struct io_uring_cqe* cqe,
999+
Posix_IOHandle* posix_handle) {
1000+
FSReadRequest req;
1001+
1002+
req.scratch = posix_handle->scratch;
1003+
req.offset = posix_handle->offset;
1004+
req.len = posix_handle->len;
1005+
1006+
size_t finished_len = 0;
1007+
size_t bytes_read = 0;
1008+
bool read_again = false;
1009+
UpdateResult(cqe, "", req.len, posix_handle->iov.iov_len,
1010+
true /*async_read*/, posix_handle->use_direct_io,
1011+
posix_handle->alignment, finished_len, &req, bytes_read,
1012+
read_again);
1013+
posix_handle->is_finished = true;
1014+
// Reset cqe data to catch any stray reuse of it
1015+
static_cast<struct io_uring_cqe*>(cqe)->user_data = 0xd5d5d5d5d5d5d5d5;
1016+
io_uring_cqe_seen(posix_handle->iu, cqe);
1017+
posix_handle->cb(req, posix_handle->cb_arg);
1018+
1019+
(void)finished_len;
1020+
(void)bytes_read;
1021+
(void)read_again;
1022+
}
9981023
#endif // ROCKSDB_IOURING_PRESENT
9991024

10001025
// EXPERIMENTAL
@@ -1043,28 +1068,7 @@ class PosixFileSystem : public FileSystem {
10431068
if (posix_handle->iu != iu) {
10441069
return IOStatus::IOError("");
10451070
}
1046-
// Reset cqe data to catch any stray reuse of it
1047-
static_cast<struct io_uring_cqe*>(cqe)->user_data = 0xd5d5d5d5d5d5d5d5;
1048-
1049-
FSReadRequest req;
1050-
req.scratch = posix_handle->scratch;
1051-
req.offset = posix_handle->offset;
1052-
req.len = posix_handle->len;
1053-
1054-
size_t finished_len = 0;
1055-
size_t bytes_read = 0;
1056-
bool read_again = false;
1057-
UpdateResult(cqe, "", req.len, posix_handle->iov.iov_len,
1058-
true /*async_read*/, posix_handle->use_direct_io,
1059-
posix_handle->alignment, finished_len, &req, bytes_read,
1060-
read_again);
1061-
posix_handle->is_finished = true;
1062-
io_uring_cqe_seen(iu, cqe);
1063-
posix_handle->cb(req, posix_handle->cb_arg);
1064-
1065-
(void)finished_len;
1066-
(void)bytes_read;
1067-
(void)read_again;
1071+
HandleFinishedIO(cqe, posix_handle);
10681072

10691073
if (static_cast<Posix_IOHandle*>(io_handles[i]) == posix_handle) {
10701074
break;
@@ -1121,6 +1125,7 @@ class PosixFileSystem : public FileSystem {
11211125
return IOStatus::IOError("io_uring_submit() requested but returned " +
11221126
std::to_string(ret));
11231127
}
1128+
posix_handle->is_aborted = true;
11241129
}
11251130

11261131
// After submitting the requests, wait for the requests.
@@ -1146,6 +1151,12 @@ class PosixFileSystem : public FileSystem {
11461151
if (posix_handle->iu != iu) {
11471152
return IOStatus::IOError("");
11481153
}
1154+
// If the request is not aborted, it means the request is completed
1155+
// successfully.
1156+
if (!posix_handle->is_aborted) {
1157+
HandleFinishedIO(cqe, posix_handle);
1158+
continue;
1159+
}
11491160
posix_handle->req_count++;
11501161

11511162
// Reset cqe data to catch any stray reuse of it
@@ -1163,14 +1174,15 @@ class PosixFileSystem : public FileSystem {
11631174
//
11641175
// Every handle has to wait for 2 requests completion: original one and
11651176
// the cancel request which is tracked by PosixHandle::req_count.
1166-
if (posix_handle->req_count == 2 &&
1167-
static_cast<Posix_IOHandle*>(io_handles[i]) == posix_handle) {
1177+
if (posix_handle->req_count == 2) {
1178+
// io_uring cancel requests return out of order
11681179
posix_handle->is_finished = true;
11691180
FSReadRequest req;
11701181
req.status = IOStatus::Aborted();
11711182
posix_handle->cb(req, posix_handle->cb_arg);
1172-
1173-
break;
1183+
if (static_cast<Posix_IOHandle*>(io_handles[i]) == posix_handle) {
1184+
break;
1185+
}
11741186
}
11751187
}
11761188
}

env/io_posix.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ struct Posix_IOHandle {
8787
use_direct_io(_use_direct_io),
8888
alignment(_alignment),
8989
is_finished(false),
90+
is_aborted(false),
9091
req_count(0) {}
9192

9293
struct iovec iov;
@@ -100,6 +101,7 @@ struct Posix_IOHandle {
100101
size_t alignment;
101102
bool is_finished;
102103
// req_count is used by AbortIO API to keep track of number of requests.
104+
bool is_aborted;
103105
uint32_t req_count;
104106
};
105107

0 commit comments

Comments
 (0)