@@ -226,6 +226,63 @@ struct seastore_test_t :
226226 std::move (t)).get ();
227227 }
228228
229+ void clone_range (
230+ SeaStoreShard &sharded_seastore,
231+ const object_state_t &s_obj,
232+ extent_len_t srcoff,
233+ extent_len_t length,
234+ extent_len_t dstoff) {
235+ CTransaction t;
236+ clone_range (sharded_seastore, t, s_obj, srcoff, length, dstoff);
237+ sharded_seastore.do_transaction (coll, std::move (t)).get ();
238+ }
239+
240+ void clone_range (
241+ SeaStoreShard &sharded_seastore,
242+ CTransaction &t,
243+ const object_state_t &s_obj,
244+ extent_len_t srcoff,
245+ extent_len_t length,
246+ extent_len_t dstoff) {
247+ bufferlist to_check;
248+ if (s_obj.contents .length () >= srcoff) {
249+ to_check.substr_of (
250+ s_obj.contents ,
251+ srcoff,
252+ std::min ((uint64_t )length,
253+ (uint64_t )s_obj.contents .length () - srcoff));
254+ }
255+ auto ret = sharded_seastore.read (
256+ coll,
257+ s_obj.oid ,
258+ srcoff,
259+ length).unsafe_get ();
260+ EXPECT_EQ (ret.length (), to_check.length ());
261+ EXPECT_EQ (ret, to_check);
262+
263+ bufferlist new_contents;
264+ if (srcoff > 0 && contents.length ()) {
265+ new_contents.substr_of (
266+ contents,
267+ 0 ,
268+ std::min<size_t >(srcoff, contents.length ())
269+ );
270+ }
271+ new_contents.append_zero (srcoff - new_contents.length ());
272+ new_contents.append (ret);
273+
274+ auto tail_offset = srcoff + ret.length ();
275+ if (contents.length () > tail_offset) {
276+ bufferlist tail;
277+ tail.substr_of (
278+ contents,
279+ tail_offset,
280+ contents.length () - tail_offset);
281+ new_contents.append (tail);
282+ }
283+ contents.swap (new_contents);
284+ t.clone_range (cid, s_obj.oid , oid, srcoff, length, dstoff);
285+ }
229286 void write (
230287 SeaStoreShard &sharded_seastore,
231288 CTransaction &t,
@@ -1282,6 +1339,58 @@ TEST_P(seastore_test_t, sparse_read)
12821339 });
12831340}
12841341
1342+ TEST_P (seastore_test_t , clone_range)
1343+ {
1344+ run_async ([this ] {
1345+ auto &test_obj1 = get_object (make_oid (0 ));
1346+ test_obj1.write (*sharded_seastore, 0 , 4096 * 1024 , ' c' );
1347+ auto test_obj2 = test_obj1.get_clone (10 );
1348+ test_obj2.write (*sharded_seastore, 65536 , 65536 , ' b' );
1349+ test_obj2.write (*sharded_seastore, 1 << 18 , 1 << 16 , ' d' );
1350+
1351+ auto test_obj3 = test_obj1.get_clone (20 );
1352+ test_obj3.clone_range (*sharded_seastore, test_obj1, 98304 , 4096 , 98304 );
1353+ std::cout << " seastore_test_t.clone_range 1 clone_range" << std::endl;
1354+ test_obj3.read (*sharded_seastore, 0 , 131072 );
1355+
1356+ test_obj3.clone_range (*sharded_seastore, test_obj1, 1 << 18 , 4096 , 1 << 18 );
1357+ std::cout << " seastore_test_t.clone_range 2 clone_range" << std::endl;
1358+ test_obj3.read (*sharded_seastore, 0 , (1 << 18 ) + (1 << 16 ));
1359+
1360+ test_obj3.clone_range (
1361+ *sharded_seastore,
1362+ test_obj1,
1363+ (1 << 18 ) + (1 << 16 ) - 4096 ,
1364+ 4096 ,
1365+ (1 << 18 ) + (1 << 16 ) - 4096 );
1366+ std::cout << " seastore_test_t.clone_range 3 clone_range" << std::endl;
1367+ test_obj3.read (*sharded_seastore, 0 , (1 << 18 ) + (1 << 16 ));
1368+
1369+ auto test_obj4 = test_obj1.get_clone (30 );
1370+ test_obj4.clone_range (*sharded_seastore, test_obj2, 98304 , 4096 , 98304 );
1371+ std::cout << " seastore_test_t.clone_range 4 clone_range" << std::endl;
1372+ test_obj4.read (*sharded_seastore, 0 , 131072 );
1373+
1374+ test_obj4.clone_range (*sharded_seastore, test_obj2, 1 << 18 , 4096 , 1 << 18 );
1375+ std::cout << " seastore_test_t.clone_range 5 clone_range" << std::endl;
1376+ test_obj4.read (*sharded_seastore, 0 , (1 << 18 ) + (1 << 16 ));
1377+
1378+ test_obj4.clone_range (
1379+ *sharded_seastore,
1380+ test_obj2,
1381+ (1 << 18 ) + (1 << 16 ) - 4096 ,
1382+ 4096 ,
1383+ (1 << 18 ) + (1 << 16 ) - 4096 );
1384+ std::cout << " seastore_test_t.clone_range 6 clone_range" << std::endl;
1385+ test_obj4.read (*sharded_seastore, 0 , (1 << 18 ) + (1 << 16 ));
1386+
1387+ auto test_obj5 =test_obj1.get_clone (40 );
1388+ test_obj5.clone_range (*sharded_seastore, test_obj1, 2048 , (1 << 18 ), 2048 );
1389+ std::cout << " seastore_test_t.clone_range 7 clone_range" << std::endl;
1390+ test_obj5.read (*sharded_seastore, 0 , (1 << 18 ) + 2048 );
1391+ });
1392+ }
1393+
12851394TEST_P (seastore_test_t , zero)
12861395{
12871396 run_async ([this ] {
0 commit comments