@@ -1419,6 +1419,87 @@ TEST(BlueFS, test_concurrent_dir_link_and_compact_log_56210) {
14191419 }
14201420}
14211421
1422+ TEST (BlueFS, truncate_drops_allocations) {
1423+ constexpr uint64_t K = 1024 ;
1424+ constexpr uint64_t M = 1024 * K;
1425+ uuid_d fsid;
1426+ const char * DIR_NAME=" dir" ;
1427+ const char * FILE_NAME=" file1" ;
1428+ struct {
1429+ uint64_t preallocated_size;
1430+ uint64_t write_size;
1431+ uint64_t truncate_to;
1432+ uint64_t allocated_after_truncate;
1433+ uint64_t slow_size = 0 ;
1434+ uint64_t slow_alloc_size = 64 *K;
1435+ uint64_t db_size = 128 *M;
1436+ uint64_t db_alloc_size = 1 *M;
1437+ } scenarios [] = {
1438+ // on DB(which is SLOW) : 1 => 1, 64K remains
1439+ { 1 *M, 1 , 1 , 64 *K },
1440+ // on DB(which is SLOW), alloc 4K : 1 => 1, 4K remains
1441+ { 1 *M, 1 , 1 , 4 *K, 0 , 4 *K },
1442+ // on DB(which is SLOW), truncation on AU boundary : 128K => 128K, 128K remains
1443+ { 1 *M, 128 *K, 128 *K, 128 *K },
1444+ // on DB(which is SLOW), no prealloc, truncation to 0 : 1666K => 0, 0 remains
1445+ { 0 , 1666 *K, 0 , 0 },
1446+ // on DB, truncate to 123K, expect 1M occupied
1447+ { 1234 *K, 123 *K, 123 *K, 1 *M, 128 *M, 64 *K, 10 *M, 1 *M },
1448+ // on DB, truncate to 0, expect 0 occupied
1449+ { 1234 *K, 345 *K, 0 , 0 , 128 *M, 64 *K, 10 *M, 1 *M },
1450+ // on DB, truncate to AU boundary, expect exactly 1M occupied
1451+ { 1234 *K, 1123 *K, 1 *M, 1 *M, 128 *M, 64 *K, 10 *M, 1 *M },
1452+ // on DB and SLOW, truncate only data on SLOW
1453+ { 0 , 10 *M+1 , 10 *M+1 , 10 *M+64 *K, 128 *M, 64 *K, 10 *M, 1 *M },
1454+ // on DB and SLOW, preallocate and truncate only data on SLOW
1455+ { 6 *M, 12 *M, 10 *M+1 , 10 *M+64 *K, 128 *M, 64 *K, 10 *M, 1 *M },
1456+ // on DB and SLOW, preallocate and truncate all in SLOW and some on DB
1457+ // note! prealloc 6M is important, one allocation for 12M will fallback to SLOW
1458+ // in 6M + 6M we can be sure that 6M is on DB and 6M is on SLOW
1459+ { 6 *M, 12 *M, 3 *M+1 , 4 *M, 128 *M, 64 *K, 11 *M, 1 *M },
1460+ };
1461+ for (auto & s : scenarios) {
1462+ ConfSaver conf (g_ceph_context->_conf );
1463+ conf.SetVal (" bluefs_shared_alloc_size" , stringify (s.slow_alloc_size ).c_str ());
1464+ conf.SetVal (" bluefs_alloc_size" , stringify (s.db_alloc_size ).c_str ());
1465+
1466+ g_ceph_context->_conf .set_val (" bluefs_shared_alloc_size" , stringify (s.slow_alloc_size ));
1467+ g_ceph_context->_conf .set_val (" bluefs_alloc_size" , stringify (s.db_alloc_size ));
1468+ TempBdev bdev_db{s.db_size };
1469+ TempBdev bdev_slow{s.slow_size };
1470+
1471+ BlueFS fs (g_ceph_context);
1472+ if (s.db_size != 0 ) {
1473+ ASSERT_EQ (0 , fs.add_block_device (BlueFS::BDEV_DB, bdev_db.path , false , 0 ));
1474+ }
1475+ if (s.slow_size != 0 ) {
1476+ ASSERT_EQ (0 , fs.add_block_device (BlueFS::BDEV_SLOW, bdev_slow.path , false , 0 ));
1477+ }
1478+
1479+ ASSERT_EQ (0 , fs.mkfs (fsid, {BlueFS::BDEV_DB, false , false }));
1480+ ASSERT_EQ (0 , fs.mount ());
1481+ ASSERT_EQ (0 , fs.maybe_verify_layout ({BlueFS::BDEV_DB, false , false }));
1482+ BlueFS::FileWriter *h;
1483+ ASSERT_EQ (0 , fs.mkdir (" dir" ));
1484+ ASSERT_EQ (0 , fs.open_for_write (DIR_NAME, FILE_NAME, &h, false ));
1485+ uint64_t pre = fs.get_used ();
1486+ ASSERT_EQ (0 , fs.preallocate (h->file , 0 , s.preallocated_size ));
1487+ const std::string content (s.write_size , ' x' );
1488+ h->append (content.c_str (), content.length ());
1489+ fs.fsync (h);
1490+ ASSERT_EQ (0 , fs.truncate (h, s.truncate_to ));
1491+ fs.fsync (h);
1492+ uint64_t post = fs.get_used ();
1493+ fs.close_writer (h);
1494+ EXPECT_EQ (pre , post - s.allocated_after_truncate );
1495+
1496+ fs.umount ();
1497+ }
1498+ }
1499+
1500+
1501+
1502+
14221503TEST (BlueFS, test_log_runway) {
14231504 uint64_t max_log_runway = 65536 ;
14241505 ConfSaver conf (g_ceph_context->_conf );
0 commit comments