Skip to content

Commit 28b15bd

Browse files
committed
src/test: test sync/async i/o code paths with huge (4GiB) buffers
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 <[email protected]>
1 parent d6d49c9 commit 28b15bd

File tree

2 files changed

+134
-0
lines changed

2 files changed

+134
-0
lines changed

src/test/client/nonblocking.cc

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <string>
1919

2020
#include <fmt/format.h>
21+
#include <sys/statvfs.h>
2122

2223
#include "test/client/TestClient.h"
2324

@@ -716,3 +717,74 @@ TEST_F(TestClient, LlreadvContiguousLlwritevNonContiguous) {
716717
client->ll_release(fh);
717718
ASSERT_EQ(0, client->ll_unlink(root, filename, myperm));
718719
}
720+
721+
TEST_F(TestClient, LlreadvLlwritevLargeBuffers) {
722+
/* Test that async I/O code paths handle large buffers (total len >= 4GiB)*/
723+
int mypid = getpid();
724+
char filename[256];
725+
726+
client->unmount();
727+
TearDown();
728+
SetUp();
729+
730+
sprintf(filename, "test_llreadvllwritevlargebuffers%u", mypid);
731+
732+
Inode *root, *file;
733+
root = client->get_root();
734+
ASSERT_NE(root, (Inode *)NULL);
735+
736+
Fh *fh;
737+
struct ceph_statx stx;
738+
739+
ASSERT_EQ(0, client->ll_createx(root, filename, 0666,
740+
O_RDWR | O_CREAT | O_TRUNC,
741+
&file, &fh, &stx, 0, 0, myperm));
742+
743+
struct statvfs stbuf;
744+
int64_t rc;
745+
rc = client->ll_statfs(root, &stbuf, myperm);
746+
ASSERT_EQ(rc, 0);
747+
int64_t fs_available_space = stbuf.f_bfree * stbuf.f_bsize;
748+
ASSERT_GT(fs_available_space, 0);
749+
750+
const size_t BUFSIZE = (size_t)INT_MAX + 1;
751+
int64_t bytes_written = 0, bytes_read = 0;
752+
753+
C_SaferCond writefinish;
754+
C_SaferCond readfinish;
755+
756+
auto out_buf_0 = std::make_unique<char[]>(BUFSIZE);
757+
memset(out_buf_0.get(), 0xDD, BUFSIZE);
758+
auto out_buf_1 = std::make_unique<char[]>(BUFSIZE);
759+
memset(out_buf_1.get(), 0xFF, BUFSIZE);
760+
761+
struct iovec iov_out[2] = {
762+
{out_buf_0.get(), BUFSIZE},
763+
{out_buf_1.get(), BUFSIZE}
764+
};
765+
766+
bufferlist bl;
767+
auto in_buf_0 = std::make_unique<char[]>(BUFSIZE);
768+
auto in_buf_1 = std::make_unique<char[]>(BUFSIZE);
769+
770+
struct iovec iov_in[2] = {
771+
{in_buf_0.get(), BUFSIZE},
772+
{in_buf_1.get(), BUFSIZE}
773+
};
774+
775+
rc = client->ll_preadv_pwritev(fh, iov_out, 2, 0, true, &writefinish,
776+
nullptr);
777+
ASSERT_EQ(rc, 0);
778+
bytes_written = writefinish.wait();
779+
// total write length is clamped to INT_MAX in write paths
780+
ASSERT_EQ(bytes_written, INT_MAX);
781+
782+
rc = client->ll_preadv_pwritev(fh, iov_in, 2, 0, false, &readfinish, &bl);
783+
ASSERT_EQ(rc, 0);
784+
bytes_read = readfinish.wait();
785+
// total read length is clamped to INT_MAX in read paths
786+
ASSERT_EQ(bytes_read, INT_MAX);
787+
788+
client->ll_release(fh);
789+
ASSERT_EQ(0, client->ll_unlink(root, filename, myperm));
790+
}

src/test/client/syncio.cc

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <string>
1919

2020
#include <fmt/format.h>
21+
#include <sys/statvfs.h>
2122

2223
#include "test/client/TestClient.h"
2324

@@ -77,3 +78,64 @@ TEST_F(TestClient, LlreadvLlwritevInvalidFileHandleSync) {
7778
rc = client->ll_readv(fh, iov_in, 2, 0);
7879
ASSERT_EQ(rc, -CEPHFS_EBADF);
7980
}
81+
82+
TEST_F(TestClient, LlreadvLlwritevLargeBuffersSync) {
83+
/* Test that sync I/O code paths handle large buffers (total len >= 4GiB)*/
84+
int mypid = getpid();
85+
char filename[256];
86+
87+
client->unmount();
88+
TearDown();
89+
SetUp();
90+
91+
sprintf(filename, "test_llreadvllwritevlargebufferssync%u", mypid);
92+
93+
Inode *root, *file;
94+
root = client->get_root();
95+
ASSERT_NE(root, (Inode *)NULL);
96+
97+
Fh *fh;
98+
struct ceph_statx stx;
99+
100+
ASSERT_EQ(0, client->ll_createx(root, filename, 0666,
101+
O_RDWR | O_CREAT | O_TRUNC,
102+
&file, &fh, &stx, 0, 0, myperm));
103+
104+
struct statvfs stbuf;
105+
int64_t rc;
106+
const size_t BUFSIZE = (size_t)INT_MAX + 1;
107+
rc = client->ll_statfs(root, &stbuf, myperm);
108+
ASSERT_EQ(rc, 0);
109+
int64_t fs_available_space = stbuf.f_bfree * stbuf.f_bsize;
110+
ASSERT_GT(fs_available_space, BUFSIZE * 2);
111+
112+
auto out_buf_0 = std::make_unique<char[]>(BUFSIZE);
113+
memset(out_buf_0.get(), 0xDD, BUFSIZE);
114+
auto out_buf_1 = std::make_unique<char[]>(BUFSIZE);
115+
memset(out_buf_1.get(), 0xFF, BUFSIZE);
116+
117+
struct iovec iov_out[2] = {
118+
{out_buf_0.get(), BUFSIZE},
119+
{out_buf_1.get(), BUFSIZE}
120+
};
121+
122+
bufferlist bl;
123+
auto in_buf_0 = std::make_unique<char[]>(BUFSIZE);
124+
auto in_buf_1 = std::make_unique<char[]>(BUFSIZE);
125+
126+
struct iovec iov_in[2] = {
127+
{in_buf_0.get(), BUFSIZE},
128+
{in_buf_1.get(), BUFSIZE}
129+
};
130+
131+
rc = client->ll_writev(fh, iov_out, 2, 0);
132+
// total write length is clamped to INT_MAX in write paths
133+
ASSERT_EQ(rc, INT_MAX);
134+
135+
rc = client->ll_readv(fh, iov_in, 2, 0);
136+
// total write length is clamped to INT_MAX in write paths
137+
ASSERT_EQ(rc, INT_MAX);
138+
139+
client->ll_release(fh);
140+
ASSERT_EQ(0, client->ll_unlink(root, filename, myperm));
141+
}

0 commit comments

Comments
 (0)