0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-12-28 00:14:07 +01:00

ircd::fs: Propagate EAGAIN without exception for !opts.blocking operations.

This commit is contained in:
Jason Volk 2019-04-20 18:23:52 -07:00
parent fbcd38fa17
commit 900fab1e79
2 changed files with 71 additions and 22 deletions

View file

@ -702,14 +702,23 @@ ircd::fs::_read(const fd &fd,
flags(opts) flags(opts)
}; };
const auto ret ssize_t ret; do
{ {
opts.interruptible? ret = ::preadv2(int(fd), iov.data(), iov.size(), opts.offset, flags_);
syscall(::preadv2, fd, iov.data(), iov.size(), opts.offset, flags_): }
syscall_nointr(::preadv2, fd, iov.data(), iov.size(), opts.offset, flags_) while(!opts.interruptible && unlikely(ret == -1 && errno == EINTR));
static_assert(EAGAIN == EWOULDBLOCK);
if(!opts.blocking && ret == -1 && errno == EAGAIN)
return 0UL;
if(unlikely(ret == -1))
throw std::system_error
{
errno, std::system_category()
}; };
return size_t(ret); return ret;
} }
#else #else
size_t size_t
@ -717,14 +726,23 @@ ircd::fs::_read(const fd &fd,
const const_iovec_view &iov, const const_iovec_view &iov,
const read_opts &opts) const read_opts &opts)
{ {
const auto ret ssize_t ret; do
{ {
opts.interruptible? ret = ::preadv(int(fd), iov.data(), iov.size(), opts.offset);
syscall(::preadv, fd, iov.data(), iov.size(), opts.offset): }
syscall_nointr(::preadv, fd, iov.data(), iov.size(), opts.offset) while(!opts.interruptible && unlikely(ret == -1 && errno == EINTR));
static_assert(EAGAIN == EWOULDBLOCK);
if(unlikely(!opts.blocking && ret == -1 && errno == EAGAIN))
return 0UL;
if(unlikely(ret == -1))
throw std::system_error
{
errno, std::system_category()
}; };
return size_t(ret); return ret;
} }
#endif // HAVE_PREADV2 #endif // HAVE_PREADV2
@ -1050,7 +1068,7 @@ ircd::fs::write(const fd &fd,
while(opts.all && opts_.offset >= 0 && off < buffers::size(bufs)); while(opts.all && opts_.offset >= 0 && off < buffers::size(bufs));
assert(opts.offset >= opts_.offset); assert(opts.offset >= opts_.offset);
assert(ssize_t(off) == opts.offset - opts_.offset); assert(ssize_t(off) == opts.offset - opts_.offset);
assert(!opts.all || off == buffers::size(bufs)); assert(!opts.all || !opts.blocking || off == buffers::size(bufs));
return off; return off;
} }
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
@ -1099,10 +1117,23 @@ ircd::fs::_write__pwritev1(const fd &fd,
const const_iovec_view &iov, const const_iovec_view &iov,
const write_opts &opts) const write_opts &opts)
{ {
return ssize_t ret; do
opts.interruptible? {
syscall(::pwritev, fd, iov.data(), iov.size(), opts.offset): ret = ::pwritev(int(fd), iov.data(), iov.size(), opts.offset);
syscall_nointr(::pwritev, fd, iov.data(), iov.size(), opts.offset); }
while(!opts.interruptible && unlikely(ret == -1 && errno == EINTR));
static_assert(EAGAIN == EWOULDBLOCK);
if(unlikely(!opts.blocking && ret == -1 && errno == EAGAIN))
return 0UL;
if(unlikely(ret == -1))
throw std::system_error
{
errno, std::system_category()
};
return ret;
} }
#ifdef HAVE_PWRITEV2 #ifdef HAVE_PWRITEV2
@ -1124,10 +1155,23 @@ ircd::fs::_write__pwritev2(const fd &fd,
flags(opts) flags(opts)
}; };
return ssize_t ret; do
opts.interruptible? {
syscall(::pwritev2, fd, iov.data(), iov.size(), offset, flags_): ret = ::pwritev2(int(fd), iov.data(), iov.size(), opts.offset, flags_);
syscall_nointr(::pwritev2, fd, iov.data(), iov.size(), offset, flags_); }
while(!opts.interruptible && unlikely(ret == -1 && errno == EINTR));
static_assert(EAGAIN == EWOULDBLOCK);
if(!opts.blocking && ret == -1 && errno == EAGAIN)
return 0UL;
if(unlikely(ret == -1))
throw std::system_error
{
errno, std::system_category()
};
return ret;
} }
#else #else
size_t size_t

View file

@ -279,7 +279,7 @@ ircd::fs::aio::write(const fd &fd,
}; };
// Does linux ever not complete all bytes for an AIO? // Does linux ever not complete all bytes for an AIO?
assert(bytes == req_bytes); assert(!opts.blocking || bytes == req_bytes);
stats.bytes_write += bytes; stats.bytes_write += bytes;
stats.writes++; stats.writes++;
@ -411,6 +411,11 @@ ircd::fs::aio::request::operator()()
if(likely(retval != -1)) if(likely(retval != -1))
return size_t(retval); return size_t(retval);
assert(opts);
static_assert(EAGAIN == EWOULDBLOCK);
if(!opts->blocking && retval == -1 && errcode == EAGAIN)
return 0UL;
stats.errors++; stats.errors++;
stats.bytes_errors += submitted_bytes; stats.bytes_errors += submitted_bytes;
thread_local char errbuf[512]; fmt::sprintf thread_local char errbuf[512]; fmt::sprintf