18
18
#include <sys/ioctl.h>
19
19
#include <sys/stat.h>
20
20
#include <linux/version.h>
21
+ #include <linux/fs.h>
21
22
#include <stdio.h>
22
23
#include <stdlib.h>
23
24
#include <string.h>
50
51
#include "common/device-utils.h"
51
52
#include "common/open-utils.h"
52
53
#include "common/parse-utils.h"
54
+ #include "common/string-utils.h"
53
55
#include "common/filesystem-utils.h"
54
56
#include "cmds/commands.h"
55
57
#include "cmds/filesystem-usage.h"
@@ -1373,6 +1375,135 @@ static int cmd_filesystem_balance(const struct cmd_struct *unused,
1373
1375
static DEFINE_COMMAND (filesystem_balance , "balance ", cmd_filesystem_balance ,
1374
1376
cmd_filesystem_balance_usage , NULL, CMD_HIDDEN ) ;
1375
1377
1378
+ static const char * const cmd_filesystem_mkswapfile_usage [] = {
1379
+ "btrfs filesystem mkswapfile <file>" ,
1380
+ "Force a sync on a filesystem" ,
1381
+ HELPINFO_INSERT_GLOBALS ,
1382
+ HELPINFO_INSERT_VERBOSE ,
1383
+ HELPINFO_INSERT_QUIET ,
1384
+ NULL
1385
+ };
1386
+
1387
+ /*
1388
+ * Swap signature in the first 4KiB, v2:
1389
+ *
1390
+ * 00000400 .. = 01 00 00 00 ff ff 03 00 00 00 00 00 cb 70 8e 60
1391
+ * ^^^^^^^^^^^
1392
+ * uuid 4B
1393
+ * 00000420 .. = 1d fb 4e ca be d4 3f 1f 6a 6b 0c 03 00 00 00 00
1394
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1395
+ * uuid 8B
1396
+ * 00000ff0 .. = 00 00 00 00 00 00 53 57 41 50 53 50 41 43 45 32
1397
+ * S W A P S P A C E 2
1398
+ */
1399
+ static int write_swap_signature (int fd )
1400
+ {
1401
+ int ret ;
1402
+ static unsigned char swap [4096 ] = {
1403
+ [0x400 ] = 0x01 ,
1404
+ [0x404 ] = 0xff ,
1405
+ [0x405 ] = 0xff ,
1406
+ [0x406 ] = 0x03 ,
1407
+ /* 0x40c .. 0x42b UUID */
1408
+ [0xff6 ] = 'S' ,
1409
+ [0xff7 ] = 'W' ,
1410
+ [0xff8 ] = 'A' ,
1411
+ [0xff9 ] = 'P' ,
1412
+ [0xffa ] = 'S' ,
1413
+ [0xffb ] = 'P' ,
1414
+ [0xffc ] = 'A' ,
1415
+ [0xffd ] = 'C' ,
1416
+ [0xffe ] = 'E' ,
1417
+ [0xfff ] = '2' ,
1418
+ };
1419
+
1420
+ uuid_generate (& swap [0x40c ]);
1421
+ ret = pwrite (fd , swap , 4096 , 0 );
1422
+
1423
+ return ret ;
1424
+ }
1425
+
1426
+ static int cmd_filesystem_mkswapfile (const struct cmd_struct * cmd , int argc , char * * argv )
1427
+ {
1428
+ int ret ;
1429
+ int fd ;
1430
+ const char * fname ;
1431
+ unsigned long flags ;
1432
+ u64 size = SZ_2G ;
1433
+
1434
+ optind = 0 ;
1435
+ while (1 ) {
1436
+ int c ;
1437
+ static const struct option long_options [] = {
1438
+ { "size" , required_argument , NULL , 's' },
1439
+ { NULL , 0 , NULL , 0 }
1440
+ };
1441
+
1442
+ c = getopt_long (argc , argv , "s:" , long_options , NULL );
1443
+ if (c < 0 )
1444
+ break ;
1445
+
1446
+ switch (c ) {
1447
+ case 's' :
1448
+ size = parse_size_from_string (optarg );
1449
+ /* Minimum limit reported by mkswap */
1450
+ if (size < 40 * SZ_1K ) {
1451
+ error ("swapfile needs to be at least 40 KiB" );
1452
+ return 1 ;
1453
+ }
1454
+ break ;
1455
+ default :
1456
+ usage_unknown_option (cmd , argv );
1457
+ }
1458
+ }
1459
+
1460
+ if (check_argc_exact (argc - optind , 1 ))
1461
+ return 1 ;
1462
+
1463
+ fname = argv [optind ];
1464
+ pr_verbose (LOG_INFO , "create file %s with mode 0600\n" , fname );
1465
+ fd = open (fname , O_RDWR | O_CREAT | O_EXCL , 0600 );
1466
+ if (fd < 0 ) {
1467
+ error ("cannot create new swapfile: %m" );
1468
+ return 1 ;
1469
+ }
1470
+ ret = ftruncate (fd , 0 );
1471
+ if (ret < 0 ) {
1472
+ error ("cannot truncate file: %m" );
1473
+ ret = 1 ;
1474
+ goto out ;
1475
+ }
1476
+ pr_verbose (LOG_INFO , "set NOCOW attribute\n" );
1477
+ flags = FS_NOCOW_FL ;
1478
+ ret = ioctl (fd , FS_IOC_SETFLAGS , & flags );
1479
+ if (ret < 0 ) {
1480
+ error ("cannot set NOCOW flag: %m" );
1481
+ ret = 1 ;
1482
+ goto out ;
1483
+ }
1484
+ pr_verbose (LOG_INFO , "fallocate to size %llu\n" , size );
1485
+ ret = fallocate (fd , 0 , 0 , size );
1486
+ if (ret < 0 ) {
1487
+ error ("cannot fallocate file: %m" );
1488
+ ret = 1 ;
1489
+ goto out ;
1490
+ }
1491
+ pr_verbose (LOG_INFO , "write swap signature\n" );
1492
+ ret = write_swap_signature (fd );
1493
+ if (ret < 0 ) {
1494
+ error ("cannot write swap signature: %m" );
1495
+ ret = 1 ;
1496
+ goto out ;
1497
+ }
1498
+ pr_verbose (LOG_DEFAULT , "create swapfile %s size %s (%llu)\n" ,
1499
+ fname , pretty_size_mode (size , UNITS_HUMAN ), size );
1500
+ out :
1501
+ close (fd );
1502
+
1503
+ return 0 ;
1504
+ }
1505
+ static DEFINE_SIMPLE_COMMAND (filesystem_mkswapfile , "mkswapfile ") ;
1506
+
1376
1507
static const char filesystem_cmd_group_info [] =
1377
1508
"overall filesystem tasks and information" ;
1378
1509
@@ -1387,6 +1518,7 @@ static const struct cmd_group filesystem_cmd_group = {
1387
1518
& cmd_struct_filesystem_resize ,
1388
1519
& cmd_struct_filesystem_label ,
1389
1520
& cmd_struct_filesystem_usage ,
1521
+ & cmd_struct_filesystem_mkswapfile ,
1390
1522
NULL
1391
1523
}
1392
1524
};
0 commit comments