#include <string>
#include <fmt/format.h>
+#include <sys/statvfs.h>
#include "test/client/TestClient.h"
client->ll_release(fh);
ASSERT_EQ(0, client->ll_unlink(root, filename, myperm));
}
+
+TEST_F(TestClient, LlreadvLlwritevLargeBuffers) {
+ /* Test that async I/O code paths handle large buffers (total len >= 4GiB)*/
+ int mypid = getpid();
+ char filename[256];
+
+ client->unmount();
+ TearDown();
+ SetUp();
+
+ sprintf(filename, "test_llreadvllwritevlargebuffers%u", mypid);
+
+ Inode *root, *file;
+ root = client->get_root();
+ ASSERT_NE(root, (Inode *)NULL);
+
+ Fh *fh;
+ struct ceph_statx stx;
+
+ ASSERT_EQ(0, client->ll_createx(root, filename, 0666,
+ O_RDWR | O_CREAT | O_TRUNC,
+ &file, &fh, &stx, 0, 0, myperm));
+
+ struct statvfs stbuf;
+ int64_t rc;
+ rc = client->ll_statfs(root, &stbuf, myperm);
+ ASSERT_EQ(rc, 0);
+ int64_t fs_available_space = stbuf.f_bfree * stbuf.f_bsize;
+ ASSERT_GT(fs_available_space, 0);
+
+ const size_t BUFSIZE = (size_t)INT_MAX + 1;
+ int64_t bytes_written = 0, bytes_read = 0;
+
+ C_SaferCond writefinish;
+ C_SaferCond readfinish;
+
+ auto out_buf_0 = std::make_unique<char[]>(BUFSIZE);
+ memset(out_buf_0.get(), 0xDD, BUFSIZE);
+ auto out_buf_1 = std::make_unique<char[]>(BUFSIZE);
+ memset(out_buf_1.get(), 0xFF, BUFSIZE);
+
+ struct iovec iov_out[2] = {
+ {out_buf_0.get(), BUFSIZE},
+ {out_buf_1.get(), BUFSIZE}
+ };
+
+ bufferlist bl;
+ auto in_buf_0 = std::make_unique<char[]>(BUFSIZE);
+ auto in_buf_1 = std::make_unique<char[]>(BUFSIZE);
+
+ struct iovec iov_in[2] = {
+ {in_buf_0.get(), BUFSIZE},
+ {in_buf_1.get(), BUFSIZE}
+ };
+
+ rc = client->ll_preadv_pwritev(fh, iov_out, 2, 0, true, &writefinish,
+ nullptr);
+ ASSERT_EQ(rc, 0);
+ bytes_written = writefinish.wait();
+ // total write length is clamped to INT_MAX in write paths
+ ASSERT_EQ(bytes_written, INT_MAX);
+
+ rc = client->ll_preadv_pwritev(fh, iov_in, 2, 0, false, &readfinish, &bl);
+ ASSERT_EQ(rc, 0);
+ bytes_read = readfinish.wait();
+ // total read length is clamped to INT_MAX in read paths
+ ASSERT_EQ(bytes_read, INT_MAX);
+
+ client->ll_release(fh);
+ ASSERT_EQ(0, client->ll_unlink(root, filename, myperm));
+}
\ No newline at end of file
#include <string>
#include <fmt/format.h>
+#include <sys/statvfs.h>
#include "test/client/TestClient.h"
rc = client->ll_readv(fh, iov_in, 2, 0);
ASSERT_EQ(rc, -CEPHFS_EBADF);
}
+
+TEST_F(TestClient, LlreadvLlwritevLargeBuffersSync) {
+ /* Test that sync I/O code paths handle large buffers (total len >= 4GiB)*/
+ int mypid = getpid();
+ char filename[256];
+
+ client->unmount();
+ TearDown();
+ SetUp();
+
+ sprintf(filename, "test_llreadvllwritevlargebufferssync%u", mypid);
+
+ Inode *root, *file;
+ root = client->get_root();
+ ASSERT_NE(root, (Inode *)NULL);
+
+ Fh *fh;
+ struct ceph_statx stx;
+
+ ASSERT_EQ(0, client->ll_createx(root, filename, 0666,
+ O_RDWR | O_CREAT | O_TRUNC,
+ &file, &fh, &stx, 0, 0, myperm));
+
+ struct statvfs stbuf;
+ int64_t rc;
+ const size_t BUFSIZE = (size_t)INT_MAX + 1;
+ rc = client->ll_statfs(root, &stbuf, myperm);
+ ASSERT_EQ(rc, 0);
+ int64_t fs_available_space = stbuf.f_bfree * stbuf.f_bsize;
+ ASSERT_GT(fs_available_space, BUFSIZE * 2);
+
+ auto out_buf_0 = std::make_unique<char[]>(BUFSIZE);
+ memset(out_buf_0.get(), 0xDD, BUFSIZE);
+ auto out_buf_1 = std::make_unique<char[]>(BUFSIZE);
+ memset(out_buf_1.get(), 0xFF, BUFSIZE);
+
+ struct iovec iov_out[2] = {
+ {out_buf_0.get(), BUFSIZE},
+ {out_buf_1.get(), BUFSIZE}
+ };
+
+ bufferlist bl;
+ auto in_buf_0 = std::make_unique<char[]>(BUFSIZE);
+ auto in_buf_1 = std::make_unique<char[]>(BUFSIZE);
+
+ struct iovec iov_in[2] = {
+ {in_buf_0.get(), BUFSIZE},
+ {in_buf_1.get(), BUFSIZE}
+ };
+
+ rc = client->ll_writev(fh, iov_out, 2, 0);
+ // total write length is clamped to INT_MAX in write paths
+ ASSERT_EQ(rc, INT_MAX);
+
+ rc = client->ll_readv(fh, iov_in, 2, 0);
+ // total write length is clamped to INT_MAX in write paths
+ ASSERT_EQ(rc, INT_MAX);
+
+ client->ll_release(fh);
+ ASSERT_EQ(0, client->ll_unlink(root, filename, myperm));
+}