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