]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
Merge PR #58564 into main
authorVenky Shankar <vshankar@redhat.com>
Mon, 21 Jul 2025 04:09:13 +0000 (09:39 +0530)
committerVenky Shankar <vshankar@redhat.com>
Mon, 21 Jul 2025 04:09:13 +0000 (09:39 +0530)
* refs/pull/58564/head:
client: clamp sizes to INT_MAX in sync i/o code paths
client: restrict bufferlist to total write size
src/test: test sync/async i/o code paths with huge (4GiB) buffers

Reviewed-by: Venky Shankar <vshankar@redhat.com>
Reviewed-by: Kotresh Hiremath Ravishankar <khiremat@redhat.com>
Reviewed-by: Christopher Hoffman <choffman@redhat.com>
1  2 
src/client/Client.cc
src/client/Client.h
src/test/client/nonblocking.cc
src/test/client/syncio.cc

index c57e282ca6b21408ea319704e93fc9053026262d,34153bf13b2b768cd6059117ba8ebcd3ddde1cba..ffe81719f996490290d29a8bbb6d96f01b28d218
@@@ -11494,12 -11327,12 +11496,12 @@@ int64_t Client::_preadv_pwritev_locked(
  
  #if defined(__linux__) && defined(O_PATH)
      if (fh->flags & O_PATH)
 -        return -CEPHFS_EBADF;
 +        return -EBADF;
  #endif
      if(iovcnt < 0) {
 -      return -CEPHFS_EINVAL;
 +      return -EINVAL;
      }
-     loff_t totallen = 0;
+     size_t totallen = 0;
      for (int i = 0; i < iovcnt; i++) {
          totallen += iov[i].iov_len;
      }
@@@ -16165,9 -16089,9 +16172,9 @@@ int64_t Client::ll_writev(struct Fh *fh
    std::scoped_lock cl(client_lock);
    if (fh == NULL || !_ll_fh_exists(fh)) {
      ldout(cct, 3) << "(fh)" << fh << " is invalid" << dendl;
 -    return -CEPHFS_EBADF;
 +    return -EBADF;
    }
-   return _preadv_pwritev_locked(fh, iov, iovcnt, off, true, false);
+   return _preadv_pwritev_locked(fh, iov, iovcnt, off, true, true);
  }
  
  int64_t Client::ll_readv(struct Fh *fh, const struct iovec *iov, int iovcnt, int64_t off)
    std::scoped_lock cl(client_lock);
    if (fh == NULL || !_ll_fh_exists(fh)) {
      ldout(cct, 3) << "(fh)" << fh << " is invalid" << dendl;
 -    return -CEPHFS_EBADF;
 +    return -EBADF;
    }
-   return _preadv_pwritev_locked(fh, iov, iovcnt, off, false, false);
+   return _preadv_pwritev_locked(fh, iov, iovcnt, off, false, true);
  }
  
  int64_t Client::ll_preadv_pwritev(struct Fh *fh, const struct iovec *iov,
Simple merge
Simple merge
index 2373139647351a307620b38096ee603191413cf4,fa5bbaf1ce4da7bfc9b4cdffa872ad12b8357b73..7da05088c9d0e583577d31bc126152883383aefa
@@@ -72,8 -73,69 +73,69 @@@ TEST_F(TestClient, LlreadvLlwritevInval
      ASSERT_EQ(0, client->ll_unlink(root, filename, myperm));
  
      rc = client->ll_writev(fh, iov_out, 2, 0);
 -    ASSERT_EQ(rc, -CEPHFS_EBADF);
 +    ASSERT_EQ(rc, -EBADF);
  
      rc = client->ll_readv(fh, iov_in, 2, 0);
 -    ASSERT_EQ(rc, -CEPHFS_EBADF);
 +    ASSERT_EQ(rc, -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));
+ }