io/uring/Queue: add method RequireSubmitEntry()

Fixes assertion failure when the submit queue is empty.
This commit is contained in:
Max Kellermann 2021-12-02 16:33:59 +01:00 committed by Max Kellermann
parent c8f174ac92
commit 799032505e
3 changed files with 30 additions and 4 deletions

View File

@ -34,6 +34,8 @@
#include "CancellableOperation.hxx"
#include "util/DeleteDisposer.hxx"
#include <stdexcept>
namespace Uring {
Queue::Queue(unsigned entries, unsigned flags)
@ -46,6 +48,23 @@ Queue::~Queue() noexcept
operations.clear_and_dispose(DeleteDisposer{});
}
struct io_uring_sqe &
Queue::RequireSubmitEntry()
{
auto *sqe = GetSubmitEntry();
if (sqe == nullptr) {
/* the submit queue is full; submit it to the kernel
and try again */
Submit();
sqe = GetSubmitEntry();
if (sqe == nullptr)
throw std::runtime_error{"io_uring_get_sqe() failed"};
}
return *sqe;
}
void
Queue::AddPending(struct io_uring_sqe &sqe,
Operation &operation) noexcept

View File

@ -63,6 +63,14 @@ public:
return ring.GetSubmitEntry();
}
/**
* Like GetSubmitEntry(), but call Submit() if the submit
* queue is full.
*
* May throw exceptions if Submit() fails.
*/
struct io_uring_sqe &RequireSubmitEntry();
bool HasPending() const noexcept {
return !operations.empty();
}

View File

@ -45,14 +45,13 @@ ReadOperation::Start(Queue &queue, FileDescriptor fd, off_t offset,
buffer = std::make_unique<std::byte[]>(size);
auto *s = queue.GetSubmitEntry();
assert(s != nullptr); // TODO: what if the submit queue is full?
auto &s = queue.RequireSubmitEntry();
iov.iov_base = buffer.get();
iov.iov_len = size;
io_uring_prep_readv(s, fd.Get(), &iov, 1, offset);
queue.Push(*s, *this);
io_uring_prep_readv(&s, fd.Get(), &iov, 1, offset);
queue.Push(s, *this);
}
void