There are two options here. One option is to use an "eventfd", a file descriptor that can wake up a sleeping epoll when an aio event happens. The other option is to not sleep at all, and continue a polling loop. The function aio_storage_context::can_sleep() supports both options.
The _aio_eventfd reactor field chooses between these two options (its value is the file object of that eventfd). It is determined by configuration options:
if (!vm["poll-aio"].as<bool>()
|| (vm["poll-aio"].defaulted() && vm.count("overprovisioned"))) {
_aio_eventfd = pollable_fd(file_desc::eventfd(0, 0));
}
So for example, in "overprovisioned" mode if the only thing we're waiting for is IO, we go to sleep knowing full well that this is more expensive than continuing to busy-loop for this IO's completion, because we know that there are other processes who want to run on this CPU (that's the point of the overprovisioned mode). In "normal" mode, Seastar fully owns this CPU, and continuing to poll is more efficient than going to sleep.