@@ -1290,19 +1290,84 @@ static const char * const cmd_filesystem_resize_usage[] = {
1290
1290
NULL
1291
1291
};
1292
1292
1293
+ struct resize_args {
1294
+ bool is_cancel ;
1295
+ bool specified_dev_id ;
1296
+ u64 devid ;
1297
+ bool is_max ;
1298
+ int mod ;
1299
+ u64 size ;
1300
+ };
1301
+
1302
+ static bool parse_resize_args (const char * amount , struct resize_args * ret )
1303
+ {
1304
+ char amount_dup [BTRFS_VOL_NAME_MAX ];
1305
+ char * devstr ;
1306
+ char * sizestr ;
1307
+
1308
+ ret -> is_cancel = false;
1309
+ if (strcmp ("cancel" , amount ) == 0 ) {
1310
+ ret -> is_cancel = true;
1311
+ return true;
1312
+ }
1313
+
1314
+ if (strlen (amount ) >= BTRFS_VOL_NAME_MAX ) {
1315
+ error ("newsize argument is too long %zu >= %d" , strlen (amount ),
1316
+ BTRFS_VOL_NAME_MAX );
1317
+ return false;
1318
+ }
1319
+ strncpy (amount_dup , amount , BTRFS_VOL_NAME_MAX );
1320
+
1321
+ sizestr = amount_dup ;
1322
+ devstr = strchr (sizestr , ':' );
1323
+ ret -> specified_dev_id = false;
1324
+ if (devstr ) {
1325
+ sizestr = devstr + 1 ;
1326
+ * devstr = 0 ;
1327
+ devstr = amount_dup ;
1328
+
1329
+ errno = 0 ;
1330
+ ret -> specified_dev_id = true;
1331
+ ret -> devid = strtoull (devstr , NULL , 10 );
1332
+
1333
+ if (errno ) {
1334
+ error ("failed to parse devid %s: %m" , devstr );
1335
+ return false;
1336
+ }
1337
+ }
1338
+
1339
+ if (strcmp (sizestr , "max" ) == 0 ) {
1340
+ ret -> is_max = true;
1341
+ } else {
1342
+ ret -> is_max = false;
1343
+
1344
+ ret -> mod = 0 ;
1345
+ if (sizestr [0 ] == '-' ) {
1346
+ ret -> mod = -1 ;
1347
+ sizestr ++ ;
1348
+ } else if (sizestr [0 ] == '+' ) {
1349
+ ret -> mod = 1 ;
1350
+ sizestr ++ ;
1351
+ }
1352
+ if (parse_u64_with_suffix (sizestr , & ret -> size ) < 0 ) {
1353
+ error ("failed to parse size %s" , sizestr );
1354
+ return false;
1355
+ }
1356
+ }
1357
+
1358
+ return true;
1359
+ }
1360
+
1293
1361
static int check_resize_args (const char * amount , const char * path , u64 * devid_ret )
1294
1362
{
1295
1363
struct btrfs_ioctl_fs_info_args fi_args ;
1296
1364
struct btrfs_ioctl_dev_info_args * di_args = NULL ;
1365
+ struct resize_args args ;
1297
1366
int ret , i , dev_idx = -1 ;
1298
- u64 devid = 1 ;
1299
1367
u64 mindev = (u64 )- 1 ;
1300
1368
int mindev_idx = 0 ;
1301
1369
const char * res_str = NULL ;
1302
- char * devstr = NULL , * sizestr = NULL ;
1303
- u64 new_size = 0 , old_size = 0 , diff = 0 ;
1304
- int mod = 0 ;
1305
- char amount_dup [BTRFS_VOL_NAME_MAX ];
1370
+ u64 new_size = 0 , old_size = 0 ;
1306
1371
1307
1372
* devid_ret = (u64 )- 1 ;
1308
1373
ret = get_fs_info (path , & fi_args , & di_args );
@@ -1317,64 +1382,47 @@ static int check_resize_args(const char *amount, const char *path, u64 *devid_re
1317
1382
goto out ;
1318
1383
}
1319
1384
1320
- ret = snprintf (amount_dup , BTRFS_VOL_NAME_MAX , "%s" , amount );
1321
- if (strlen (amount ) != ret ) {
1322
- error ("newsize argument is too long" );
1385
+ if (!parse_resize_args (amount , & args )) {
1323
1386
ret = 1 ;
1324
1387
goto out ;
1325
1388
}
1326
- ret = 0 ;
1327
1389
1328
1390
/* Cancel does not need to determine the device number. */
1329
- if (strcmp ( amount , "cancel" ) == 0 ) {
1391
+ if (args . is_cancel ) {
1330
1392
/* Different format, print and exit */
1331
1393
pr_verbose (LOG_DEFAULT , "Request to cancel resize\n" );
1332
1394
goto out ;
1333
1395
}
1334
1396
1335
- sizestr = amount_dup ;
1336
- devstr = strchr (sizestr , ':' );
1337
- if (devstr ) {
1338
- sizestr = devstr + 1 ;
1339
- * devstr = 0 ;
1340
- devstr = amount_dup ;
1341
-
1342
- errno = 0 ;
1343
- devid = strtoull (devstr , NULL , 10 );
1344
-
1345
- if (errno ) {
1346
- error ("failed to parse devid %s: %m" , devstr );
1347
- ret = 1 ;
1348
- goto out ;
1349
- }
1350
- }
1397
+ if (!args .specified_dev_id )
1398
+ args .devid = 1 ;
1351
1399
1352
1400
dev_idx = -1 ;
1353
1401
for (i = 0 ; i < fi_args .num_devices ; i ++ ) {
1354
1402
if (di_args [i ].devid < mindev ) {
1355
1403
mindev = di_args [i ].devid ;
1356
1404
mindev_idx = i ;
1357
1405
}
1358
- if (di_args [i ].devid == devid ) {
1406
+ if (di_args [i ].devid == args . devid ) {
1359
1407
dev_idx = i ;
1360
1408
break ;
1361
1409
}
1362
1410
}
1363
1411
1364
- if (devstr && dev_idx < 0 ) {
1412
+ if (args . specified_dev_id && dev_idx < 0 ) {
1365
1413
/* Devid specified but not found. */
1366
- error ("cannot find devid: %lld " , devid );
1414
+ error ("cannot find devid: %llu " , args . devid );
1367
1415
ret = 1 ;
1368
1416
goto out ;
1369
- } else if (!devstr && devid == 1 && dev_idx < 0 ) {
1417
+ } else if (!args . specified_dev_id && dev_idx < 0 ) {
1370
1418
/*
1371
1419
* No device specified, assuming implicit 1 but it does not
1372
1420
* exist. Use minimum device as fallback.
1373
1421
*/
1374
1422
warning ("no devid specified means devid 1 which does not exist, using\n"
1375
1423
"\t lowest devid %llu as a fallback" , mindev );
1376
1424
* devid_ret = mindev ;
1377
- devid = mindev ;
1425
+ args . devid = mindev ;
1378
1426
dev_idx = mindev_idx ;
1379
1427
} else {
1380
1428
/*
@@ -1383,44 +1431,31 @@ static int check_resize_args(const char *amount, const char *path, u64 *devid_re
1383
1431
*/
1384
1432
}
1385
1433
1386
- if (strcmp ( sizestr , "max" ) == 0 ) {
1434
+ if (args . is_max ) {
1387
1435
res_str = "max" ;
1388
1436
} else {
1389
- if (sizestr [0 ] == '-' ) {
1390
- mod = -1 ;
1391
- sizestr ++ ;
1392
- } else if (sizestr [0 ] == '+' ) {
1393
- mod = 1 ;
1394
- sizestr ++ ;
1395
- }
1396
- ret = parse_u64_with_suffix (sizestr , & diff );
1397
- if (ret < 0 ) {
1398
- error ("failed to parse size %s" , sizestr );
1399
- ret = 1 ;
1400
- goto out ;
1401
- }
1402
1437
old_size = di_args [dev_idx ].total_bytes ;
1403
1438
1404
1439
/* For target sizes without +/- sign prefix (e.g. 1:150g) */
1405
- if (mod == 0 ) {
1406
- new_size = diff ;
1407
- } else if (mod < 0 ) {
1408
- if (diff > old_size ) {
1440
+ if (args . mod == 0 ) {
1441
+ new_size = args . size ;
1442
+ } else if (args . mod < 0 ) {
1443
+ if (args . size > old_size ) {
1409
1444
error ("current size is %s which is smaller than %s" ,
1410
1445
pretty_size_mode (old_size , UNITS_DEFAULT ),
1411
- pretty_size_mode (diff , UNITS_DEFAULT ));
1446
+ pretty_size_mode (args . size , UNITS_DEFAULT ));
1412
1447
ret = 1 ;
1413
1448
goto out ;
1414
1449
}
1415
- new_size = old_size - diff ;
1416
- } else if (mod > 0 ) {
1417
- if (diff > ULLONG_MAX - old_size ) {
1450
+ new_size = old_size - args . size ;
1451
+ } else if (args . mod > 0 ) {
1452
+ if (args . size > ULLONG_MAX - old_size ) {
1418
1453
error ("increasing %s is out of range" ,
1419
- pretty_size_mode (diff , UNITS_DEFAULT ));
1454
+ pretty_size_mode (args . size , UNITS_DEFAULT ));
1420
1455
ret = 1 ;
1421
1456
goto out ;
1422
1457
}
1423
- new_size = old_size + diff ;
1458
+ new_size = old_size + args . size ;
1424
1459
}
1425
1460
new_size = round_down (new_size , fi_args .sectorsize );
1426
1461
res_str = pretty_size_mode (new_size , UNITS_DEFAULT );
@@ -1430,7 +1465,7 @@ static int check_resize_args(const char *amount, const char *path, u64 *devid_re
1430
1465
new_size , pretty_size_mode (new_size , UNITS_DEFAULT ));
1431
1466
}
1432
1467
1433
- pr_verbose (LOG_DEFAULT , "Resize device id %lld (%s) from %s to %s\n" , devid ,
1468
+ pr_verbose (LOG_DEFAULT , "Resize device id %llu (%s) from %s to %s\n" , args . devid ,
1434
1469
di_args [dev_idx ].path ,
1435
1470
pretty_size_mode (di_args [dev_idx ].total_bytes , UNITS_DEFAULT ),
1436
1471
res_str );
0 commit comments