Commit 7488256f authored by Iaroslav Tverdokhlib's avatar Iaroslav Tverdokhlib Committed by facebook-github-bot-0

Fix wrapvFull for the case when iovec* has size more than 1024

Summary: `folly::wrapvFull` fail if the passed in `iovec*` has more than 1024 (`IOV_MAX`) elements. In particular, it returns -1 with errno 22 [Invalid argument]. The fix is to limit maximum size of iovec* to IOV_MAX that is passed in to `readv/writev/...` in a single iteration of outer loop.

Reviewed By: yfeldblum

Differential Revision: D2935540

fb-gh-sync-id: 6c0a073ac0b59db3d53fb4269b13ddfcc479efb1
shipit-source-id: 6c0a073ac0b59db3d53fb4269b13ddfcc479efb1
parent e2fe17ae
...@@ -76,7 +76,7 @@ ssize_t wrapvFull(F f, int fd, iovec* iov, int count, Offset... offset) { ...@@ -76,7 +76,7 @@ ssize_t wrapvFull(F f, int fd, iovec* iov, int count, Offset... offset) {
ssize_t totalBytes = 0; ssize_t totalBytes = 0;
size_t r; size_t r;
do { do {
r = f(fd, iov, count, offset...); r = f(fd, iov, std::min(count, IOV_MAX), offset...);
if (r == (size_t)-1) { if (r == (size_t)-1) {
if (errno == EINTR) { if (errno == EINTR) {
continue; continue;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <folly/FileUtil.h> #include <folly/FileUtil.h>
#include <folly/detail/FileUtilDetail.h> #include <folly/detail/FileUtilDetail.h>
#include <folly/experimental/TestUtil.h>
#include <deque> #include <deque>
...@@ -179,6 +180,7 @@ TEST_F(FileUtilTest, pread) { ...@@ -179,6 +180,7 @@ TEST_F(FileUtilTest, pread) {
class IovecBuffers { class IovecBuffers {
public: public:
explicit IovecBuffers(std::initializer_list<size_t> sizes); explicit IovecBuffers(std::initializer_list<size_t> sizes);
explicit IovecBuffers(std::vector<size_t> sizes);
std::vector<iovec> iov() const { return iov_; } // yes, make a copy std::vector<iovec> iov() const { return iov_; } // yes, make a copy
std::string join() const { return folly::join("", buffers_); } std::string join() const { return folly::join("", buffers_); }
...@@ -202,6 +204,19 @@ IovecBuffers::IovecBuffers(std::initializer_list<size_t> sizes) { ...@@ -202,6 +204,19 @@ IovecBuffers::IovecBuffers(std::initializer_list<size_t> sizes) {
} }
} }
IovecBuffers::IovecBuffers(std::vector<size_t> sizes) {
iov_.reserve(sizes.size());
for (auto s : sizes) {
buffers_.push_back(std::string(s, '\0'));
}
for (auto& b : buffers_) {
iovec iov;
iov.iov_base = &b[0];
iov.iov_len = b.size();
iov_.push_back(iov);
}
}
size_t IovecBuffers::size() const { size_t IovecBuffers::size() const {
size_t s = 0; size_t s = 0;
for (auto& b : buffers_) { for (auto& b : buffers_) {
...@@ -223,6 +238,20 @@ TEST_F(FileUtilTest, readv) { ...@@ -223,6 +238,20 @@ TEST_F(FileUtilTest, readv) {
} }
} }
TEST(FileUtilTest2, wrapv) {
TemporaryFile tempFile("file-util-test");
std::vector<size_t> sizes;
size_t sum = 0;
for (int32_t i = 0; i < 1500; ++i) {
sizes.push_back(i % 3 + 1);
sum += sizes.back();
}
IovecBuffers buf(sizes);
ASSERT_EQ(sum, buf.size());
auto iov = buf.iov();
EXPECT_EQ(sum, wrapvFull(writev, tempFile.fd(), iov.data(), iov.size()));
}
#if FOLLY_HAVE_PREADV #if FOLLY_HAVE_PREADV
TEST_F(FileUtilTest, preadv) { TEST_F(FileUtilTest, preadv) {
for (auto& p : readers_) { for (auto& p : readers_) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment