@@ -611,3 +611,104 @@ TEST_F(TestClient, LlreadvLlwritevInvalidFileHandle) {
611611 ASSERT_EQ (bytes_read, -CEPHFS_EBADF);
612612 ASSERT_EQ (bl.length (), 0 );
613613}
614+
615+ TEST_F (TestClient, LlreadvContiguousLlwritevNonContiguous) {
616+ /* Test writing at non-contiguous memory locations, and make sure
617+ contiguous read returns bytes requested. */
618+
619+ int mypid = getpid ();
620+ char filename[256 ];
621+
622+ client->unmount ();
623+ TearDown ();
624+ SetUp ();
625+
626+ sprintf (filename, " test_llreadvcontiguousllwritevnoncontiguousfile%u" , mypid);
627+
628+ Inode *root, *file;
629+ root = client->get_root ();
630+ ASSERT_NE (root, (Inode *)NULL );
631+
632+ Fh *fh;
633+ struct ceph_statx stx;
634+
635+ ASSERT_EQ (0 , client->ll_createx (root, filename, 0666 ,
636+ O_RDWR | O_CREAT | O_TRUNC,
637+ &file, &fh, &stx, 0 , 0 , myperm));
638+
639+ const int NUM_BUF = 5 ;
640+ char out_buf_0[] = " hello " ;
641+ char out_buf_1[] = " world\n " ;
642+ char out_buf_2[] = " Ceph - " ;
643+ char out_buf_3[] = " a scalable distributed " ;
644+ char out_buf_4[] = " storage system\n " ;
645+
646+ struct iovec iov_out_non_contiguous[NUM_BUF] = {
647+ {out_buf_0, sizeof (out_buf_0)},
648+ {out_buf_1, sizeof (out_buf_1)},
649+ {out_buf_2, sizeof (out_buf_2)},
650+ {out_buf_3, sizeof (out_buf_3)},
651+ {out_buf_4, sizeof (out_buf_4)}
652+ };
653+
654+ char in_buf_0[sizeof (out_buf_0)];
655+ char in_buf_1[sizeof (out_buf_1)];
656+ char in_buf_2[sizeof (out_buf_2)];
657+ char in_buf_3[sizeof (out_buf_3)];
658+ char in_buf_4[sizeof (out_buf_4)];
659+
660+ struct iovec iov_in_contiguous[NUM_BUF] = {
661+ {in_buf_0, sizeof (in_buf_0)},
662+ {in_buf_1, sizeof (in_buf_1)},
663+ {in_buf_2, sizeof (in_buf_2)},
664+ {in_buf_3, sizeof (in_buf_3)},
665+ {in_buf_4, sizeof (in_buf_4)}
666+ };
667+
668+ ssize_t bytes_to_write = 0 , total_bytes_written = 0 , total_bytes_read = 0 ;
669+ for (int i = 0 ; i < NUM_BUF; ++i) {
670+ bytes_to_write += iov_out_non_contiguous[i].iov_len ;
671+ }
672+
673+ std::unique_ptr<C_SaferCond> writefinish = nullptr ;
674+ std::unique_ptr<C_SaferCond> readfinish = nullptr ;
675+
676+ int64_t rc;
677+ bufferlist bl;
678+
679+ struct iovec *current_iov = iov_out_non_contiguous;
680+
681+ for (int i = 0 ; i < NUM_BUF; ++i) {
682+ writefinish.reset (new C_SaferCond (" test-nonblocking-writefinish-non-contiguous" ));
683+ rc = client->ll_preadv_pwritev (fh, current_iov++, 1 , i * NUM_BUF * 100 ,
684+ true , writefinish.get (), nullptr );
685+ ASSERT_EQ (rc, 0 );
686+ total_bytes_written += writefinish->wait ();
687+ }
688+ ASSERT_EQ (total_bytes_written, bytes_to_write);
689+
690+ readfinish.reset (new C_SaferCond (" test-nonblocking-readfinish-contiguous" ));
691+ rc = client->ll_preadv_pwritev (fh, iov_in_contiguous, NUM_BUF, 0 , false ,
692+ readfinish.get (), &bl);
693+ ASSERT_EQ (rc, 0 );
694+ total_bytes_read = readfinish->wait ();
695+ ASSERT_EQ (total_bytes_read, bytes_to_write);
696+ ASSERT_EQ (bl.length (), bytes_to_write);
697+
698+ copy_bufferlist_to_iovec (iov_in_contiguous, NUM_BUF, &bl,
699+ total_bytes_read);
700+ /* since the iovec structures are written at gaps of 100, only the first
701+ iovec structure content should match when reading contiguously while rest
702+ of the read buffers should just be 0s(holes filled with zeros) */
703+ ASSERT_EQ (0 , strncmp ((const char *)iov_in_contiguous[0 ].iov_base ,
704+ (const char *)iov_out_non_contiguous[0 ].iov_base ,
705+ iov_out_non_contiguous[0 ].iov_len ));
706+ for (int i = 1 ; i < NUM_BUF; ++i) {
707+ ASSERT_NE (0 , strncmp ((const char *)iov_in_contiguous[i].iov_base ,
708+ (const char *)iov_out_non_contiguous[i].iov_base ,
709+ iov_out_non_contiguous[i].iov_len ));
710+ }
711+
712+ client->ll_release (fh);
713+ ASSERT_EQ (0 , client->ll_unlink (root, filename, myperm));
714+ }
0 commit comments