WoooHaaaa
WoooHaaaa

Reputation: 20470

PosixAIO: aio_error returns 38 (Not Implemented) but errno is 0 (Success)

My code works perfectly on a native Linux system, but when I run it on a WSL, it seems something is wrong.

Here's how I send the AsyncWrites:

Status PosixAIOEngine::AsyncWrite(int fd, uint64_t offset, const char* buffer, uint64_t size,
                                  char** cb) {
  if (requests_.size() >= io_depth_) {
    LOG(ERROR, "io depth full, please try again later, cur: {}", io_depth_);
    return Status::Busy();
  }

  requests_.push_back({.aio_req_ = {}, .type_ = kAsyncWrite});
  auto& request = requests_.back();
  memset(&request.aio_req_, 0, sizeof(struct aiocb));
  request.aio_req_.aio_offset = (off_t)offset;
  request.aio_req_.aio_buf = (void*)buffer;
  request.aio_req_.aio_nbytes = size;
  request.aio_req_.aio_fildes = fd;

  int ret = aio_write(&request.aio_req_);
  if (ret == -1) {
    auto msg = "aio_write failed, err msg: " + std::string(strerror(errno));
    LOG(ERROR, msg);
    requests_.pop_back();
    return Status::IOError(msg);
  }

  return Status::OK();
}

After I send out a few write requests, I Poll the result here:

uint32_t PosixAIOEngine::Poll() {
  uint32_t cnt = 0;
  auto it = requests_.begin();
  while (it != requests_.end()) {
    auto& req = *it;
    int err_value = aio_error(&req.aio_req_);

    // If the request was canceld, we remove & skip it.
    if (err_value == ECANCELED) {
      it = requests_.erase(it);
      continue;
    }

    // If the request is not yet completed, we skip it.
    if (err_value == EINPROGRESS) {
      ++it;
      continue;
    }

    // If the request has an error.
    if (err_value != 0) { <------------------- ERROR here <<<<<<<<<<<<<<<<<<
      LOG(ERROR, "I/O failed, aio_error: {}, errmsg: {}, offset: {}", err_value, strerror(errno),
          req.aio_req_.aio_offset);
      it = requests_.erase(it);
      continue;
    }

    // If there's no operation error occurs, we should check the return value.
    int ret_value = aio_return(&req.aio_req_);
    if (ret_value == -1) {
      LOG(ERROR, "I/O failed, aio_return: {}, errmsg: {}, offset: {}", ret_value, strerror(errno),
          req.aio_req_.aio_offset);
      it = requests_.erase(it);
      continue;
    }

    // Otherwise, the operation success
    it = requests_.erase(it);
    cnt++;
  }

I check the aio_error first to make sure the requests were send out correctly, but it has a 38 return value, which means Not Implemented. I suppose the errno would be changed too, but it turns out errno is still 0, which means Sucess.

Questions:

  1. Why errno was not changed after the aio_error returns non-zero value.
  2. How should I fixed my demo code?

According to the description of this API:, it seems it should has the same value of the errno? Or I mis-understand the description... (not a native speaker)

A positive error number, if the asynchronous I/O operation
              failed.  This is the same value that would have been
              stored in the errno variable in the case of a synchronous
              read(2), write(2), fsync(2), or fdatasync(2) call.

Upvotes: 0

Views: 37

Answers (1)

WoooHaaaa
WoooHaaaa

Reputation: 20470

OK, the solution is here:

It turns out that WSL1.0 is not able to process async aio correctly (under aio.h), so I upgraded it to WSL2.0, which works perfectly.

Upvotes: 0

Related Questions