@@ -1291,6 +1291,106 @@ static int parse_inode_flags(const char *option, struct list_head *inode_flags_l
12911291 return ret ;
12921292}
12931293
1294+ static int discard_free_space (struct btrfs_fs_info * fs_info , u64 metadata_profile )
1295+ {
1296+ struct btrfs_root * free_space_root ;
1297+ struct btrfs_path path = { 0 };
1298+ struct extent_buffer * leaf ;
1299+ int ret ;
1300+ struct btrfs_key key = {
1301+ .objectid = BTRFS_FREE_SPACE_TREE_OBJECTID ,
1302+ .type = BTRFS_ROOT_ITEM_KEY ,
1303+ .offset = 0 ,
1304+ };
1305+
1306+ if (!btrfs_fs_compat_ro (fs_info , FREE_SPACE_TREE ))
1307+ return 0 ;
1308+
1309+ /*
1310+ * Follow the kernel in not doing discard for RAID5 or 6.
1311+ * We don't have to worry about data here, as --rootdir only works
1312+ * with single-device filesystems, and the data block groups are
1313+ * empty otherwise.
1314+ */
1315+
1316+ if (metadata_profile & BTRFS_BLOCK_GROUP_RAID56_MASK )
1317+ return 0 ;
1318+
1319+ free_space_root = btrfs_global_root (fs_info , & key );
1320+
1321+ key .objectid = 0 ;
1322+ key .type = 0 ;
1323+ key .offset = 0 ;
1324+
1325+ ret = btrfs_search_slot (NULL , free_space_root , & key , & path , 0 , 0 );
1326+ if (ret < 0 )
1327+ return ret ;
1328+
1329+ while (true) {
1330+ leaf = path .nodes [0 ];
1331+
1332+ if (path .slots [0 ] >= btrfs_header_nritems (leaf )) {
1333+ ret = btrfs_next_leaf (free_space_root , & path );
1334+ if (ret )
1335+ break ;
1336+
1337+ leaf = path .nodes [0 ];
1338+ }
1339+
1340+ btrfs_item_key_to_cpu (leaf , & key , path .slots [0 ]);
1341+
1342+ if (key .type == BTRFS_FREE_SPACE_EXTENT_KEY ) {
1343+ ret = discard_logical_range (fs_info , key .objectid , key .offset );
1344+ if (ret < 0 )
1345+ goto out ;
1346+ } else if (key .type == BTRFS_FREE_SPACE_BITMAP_KEY ) {
1347+ int size , nrbits ;
1348+ void * bitmap ;
1349+ unsigned long start_bit , end_bit ;
1350+
1351+ size = btrfs_item_size (leaf , path .slots [0 ]);
1352+ bitmap = malloc (size );
1353+ if (!bitmap ) {
1354+ ret = - ENOMEM ;
1355+ goto out ;
1356+ }
1357+
1358+ read_extent_buffer (leaf , bitmap ,
1359+ btrfs_item_ptr_offset (leaf , path .slots [0 ]),
1360+ size );
1361+
1362+ nrbits = div_u64 (key .offset , fs_info -> sectorsize );
1363+ start_bit = find_next_bit_le (bitmap , nrbits , 0 );
1364+
1365+ while (start_bit < nrbits ) {
1366+ u64 addr , length ;
1367+
1368+ end_bit = find_next_zero_bit_le (bitmap , nrbits , start_bit );
1369+ addr = key .objectid + (start_bit * fs_info -> sectorsize );
1370+ length = (end_bit - start_bit ) * fs_info -> sectorsize ;
1371+
1372+ ret = discard_logical_range (fs_info , addr , length );
1373+ if (ret < 0 ) {
1374+ free (bitmap );
1375+ goto out ;
1376+ }
1377+
1378+ start_bit = find_next_bit_le (bitmap , nrbits , end_bit );
1379+ }
1380+
1381+ free (bitmap );
1382+ }
1383+
1384+ path .slots [0 ]++ ;
1385+ }
1386+
1387+ ret = 0 ;
1388+
1389+ out :
1390+ btrfs_release_path (& path );
1391+ return ret ;
1392+ }
1393+
12941394int BOX_MAIN (mkfs )(int argc , char * * argv )
12951395{
12961396 char * file ;
@@ -2312,6 +2412,15 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
23122412 }
23132413 }
23142414
2415+ if (opt_discard ) {
2416+ ret = discard_free_space (fs_info , metadata_profile );
2417+ if (ret < 0 ) {
2418+ errno = - ret ;
2419+ error ("failed to discard free space: %m" );
2420+ goto out ;
2421+ }
2422+ }
2423+
23152424 /*
23162425 * The filesystem is now fully set up, commit the remaining changes and
23172426 * fix the signature as the last step before closing the devices.
0 commit comments