@@ -1291,6 +1291,106 @@ static int parse_inode_flags(const char *option, struct list_head *inode_flags_l
1291
1291
return ret ;
1292
1292
}
1293
1293
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
+
1294
1394
int BOX_MAIN (mkfs )(int argc , char * * argv )
1295
1395
{
1296
1396
char * file ;
@@ -2312,6 +2412,15 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
2312
2412
}
2313
2413
}
2314
2414
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
+
2315
2424
/*
2316
2425
* The filesystem is now fully set up, commit the remaining changes and
2317
2426
* fix the signature as the last step before closing the devices.
0 commit comments