]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
src/test: test sync/async i/o code paths with huge (4GiB) buffers
authorDhairya Parmar <dparmar@redhat.com>
Wed, 17 Jul 2024 13:00:29 +0000 (18:30 +0530)
committerDhairya Parmar <dparmar@redhat.com>
Tue, 22 Apr 2025 12:09:05 +0000 (14:09 +0200)
to make sure there are no crashes and max bytes written is INT_MAX
(clamped in write paths).

Fixes: https://tracker.ceph.com/issues/66245
Signed-off-by: Dhairya Parmar <dparmar@redhat.com>
src/test/client/nonblocking.cc
src/test/client/syncio.cc

index 93bcfabd3fcf15230cf869be564c8e5f1ddfeece..5be6f4fe8d5765be6096f8d74b5e76e4b4b857c6 100644 (file)
@@ -18,6 +18,7 @@
 #include <string>
 
 #include <fmt/format.h>
+#include <sys/statvfs.h>
 
 #include "test/client/TestClient.h"
 
@@ -716,3 +717,74 @@ TEST_F(TestClient, LlreadvContiguousLlwritevNonContiguous) {
   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
index f40503a3909fdee0384119cb3d91e64b90fe7d5b..fa5bbaf1ce4da7bfc9b4cdffa872ad12b8357b73 100644 (file)
@@ -18,6 +18,7 @@
 #include <string>
 
 #include <fmt/format.h>
+#include <sys/statvfs.h>
 
 #include "test/client/TestClient.h"
 
@@ -77,3 +78,64 @@ TEST_F(TestClient, LlreadvLlwritevInvalidFileHandleSync) {
     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));
+}