@@ -310,36 +310,75 @@ static void splice_device_list(struct list_head *seed_devices,
310
310
list_splice (seed_devices , all_devices );
311
311
}
312
312
313
- static void print_filesystem_info (char * label , char uuidbuf [BTRFS_UUID_UNPARSED_SIZE ],
314
- u64 bytes_used , u64 num_devices ,
315
- unsigned unit_mode )
313
+ static const struct rowspec filesystem_show_data_rowspec [] = {
314
+ { .key = "label" , .fmt = "%s" , .out_json = "label" },
315
+ { .key = "uuid" , .fmt = "%s" , .out_json = "uuid" },
316
+ { .key = "num_devices" , .fmt = "%llu" , .out_json = "total_devices" },
317
+ { .key = "used" , .fmt = "%llu" , .out_json = "used" },
318
+ /* device list */
319
+ { .key = "devid" , .fmt = "%llu" , .out_json = "devid" },
320
+ { .key = "size" , .fmt = "%llu" , .out_json = "size" },
321
+ { .key = "used" , .fmt = "%llu" , .out_json = "used" },
322
+ { .key = "path" , .fmt = "%s" , .out_json = "path" },
323
+ { .key = "missing" , .fmt = "bool" , .out_json = "missing" },
324
+ ROWSPEC_END
325
+ };
326
+
327
+ static void print_filesystem_info (struct format_ctx * fctx ,
328
+ char * label , char uuidbuf [BTRFS_UUID_UNPARSED_SIZE ],
329
+ u64 bytes_used , u64 num_devices ,
330
+ unsigned unit_mode )
316
331
{
317
- if (label )
318
- pr_verbose (LOG_DEFAULT , "Label: '%s' " , label );
319
- else
320
- pr_verbose (LOG_DEFAULT , "Label: none " );
321
-
322
- pr_verbose (LOG_DEFAULT , " uuid: %s\n\tTotal devices %llu FS bytes used %s\n" , uuidbuf ,
323
- num_devices ,
324
- pretty_size_mode (bytes_used ,
325
- unit_mode ));
332
+ if (bconf .output_format == CMD_FORMAT_JSON ) {
333
+ if (label )
334
+ fmt_print (fctx , "label" , label );
335
+ else
336
+ fmt_print (fctx , "label" , "none" );
337
+
338
+ fmt_print (fctx , "uuid" , uuidbuf );
339
+ fmt_print (fctx , "num_devices" , num_devices );
340
+ fmt_print (fctx , "used" , bytes_used );
341
+ } else {
342
+ if (label )
343
+ pr_verbose (LOG_DEFAULT , "Label: '%s' " , label );
344
+ else
345
+ pr_verbose (LOG_DEFAULT , "Label: none " );
346
+
347
+ pr_verbose (LOG_DEFAULT , " uuid: %s\n\tTotal devices %llu FS bytes used %s\n" , uuidbuf ,
348
+ num_devices ,
349
+ pretty_size_mode (bytes_used ,
350
+ unit_mode ));
351
+ }
326
352
}
327
353
328
- static void print_filesystem_device (u64 devid , u64 total_bytes , u64 bytes_used ,
354
+ static void print_filesystem_device (struct format_ctx * fctx ,
355
+ u64 devid , u64 total_bytes , u64 bytes_used ,
329
356
char * path ,
330
357
bool missing ,
331
358
unsigned unit_mode )
332
359
{
333
- pr_verbose (LOG_DEFAULT , "\tdevid %4llu size %s used %s path %s%s\n" ,
334
- devid ,
335
- pretty_size_mode (total_bytes , unit_mode ),
336
- pretty_size_mode (bytes_used , unit_mode ),
337
- path ,
338
- missing ? " MISSING" : "" );
360
+ if (bconf .output_format == CMD_FORMAT_JSON ) {
361
+ fmt_print_start_group (fctx , NULL , JSON_TYPE_MAP );
362
+ fmt_print (fctx , "devid" , devid );
363
+ fmt_print (fctx , "size" , 0 );
364
+ fmt_print (fctx , "used" , 0 );
365
+ fmt_print (fctx , "path" , path );
366
+ if (missing )
367
+ fmt_print (fctx , "missing" , 0 );
368
+ fmt_print_end_group (fctx , NULL );
369
+ } else {
370
+ pr_verbose (LOG_DEFAULT , "\tdevid %4llu size %s used %s path %s%s\n" ,
371
+ devid ,
372
+ pretty_size_mode (total_bytes , unit_mode ),
373
+ pretty_size_mode (bytes_used , unit_mode ),
374
+ path ,
375
+ missing ? " MISSING" : "" );
376
+ }
339
377
}
340
378
341
379
static void print_devices (struct btrfs_fs_devices * fs_devices ,
342
- u64 * devs_found , unsigned unit_mode )
380
+ u64 * devs_found , unsigned unit_mode ,
381
+ struct format_ctx * fctx )
343
382
{
344
383
struct btrfs_device * device ;
345
384
struct btrfs_fs_devices * cur_fs ;
@@ -355,16 +394,17 @@ static void print_devices(struct btrfs_fs_devices *fs_devices,
355
394
356
395
list_sort (NULL , all_devices , cmp_device_id );
357
396
list_for_each_entry (device , all_devices , dev_list ) {
358
- print_filesystem_device (device -> devid ,
359
- device -> total_bytes , device -> bytes_used ,
360
- device -> name ,
361
- false,
362
- unit_mode );
397
+ print_filesystem_device (fctx , device -> devid ,
398
+ device -> total_bytes , device -> bytes_used ,
399
+ device -> name ,
400
+ false,
401
+ unit_mode );
363
402
(* devs_found )++ ;
364
403
}
365
404
}
366
405
367
- static void print_one_uuid (struct btrfs_fs_devices * fs_devices ,
406
+ static void print_one_uuid (struct format_ctx * fctx ,
407
+ struct btrfs_fs_devices * fs_devices ,
368
408
unsigned unit_mode )
369
409
{
370
410
char uuidbuf [BTRFS_UUID_UNPARSED_SIZE ];
@@ -380,14 +420,27 @@ static void print_one_uuid(struct btrfs_fs_devices *fs_devices,
380
420
dev_list );
381
421
total = device -> total_devs ;
382
422
383
- print_filesystem_info (device -> label && device -> label [0 ] ? device -> label : NULL , uuidbuf ,
384
- device -> super_bytes_used , total ,
385
- unit_mode );
423
+ if (bconf .output_format == CMD_FORMAT_JSON )
424
+ fmt_print_start_group (fctx , NULL , JSON_TYPE_MAP );
425
+
426
+ print_filesystem_info (fctx , device -> label && device -> label [0 ] ? device -> label : NULL , uuidbuf ,
427
+ device -> super_bytes_used , total ,
428
+ unit_mode );
386
429
387
- print_devices (fs_devices , & devs_found , unit_mode );
430
+ if (bconf .output_format == CMD_FORMAT_JSON )
431
+ fmt_print_start_group (fctx , "device-list" , JSON_TYPE_ARRAY );
388
432
389
- if (devs_found < total ) {
390
- pr_verbose (LOG_DEFAULT , "\t*** Some devices missing\n" );
433
+ print_devices (fs_devices , & devs_found , unit_mode , fctx );
434
+
435
+ // TODO: global missing option?
436
+ if (bconf .output_format == CMD_FORMAT_JSON ) {
437
+ fmt_print_end_group (fctx , NULL );
438
+ fmt_print_end_group (fctx , "device-list" );
439
+ } else {
440
+ if (devs_found < total ) {
441
+ pr_verbose (LOG_DEFAULT , "\t*** Some devices missing\n" );
442
+ }
443
+ pr_verbose (LOG_DEFAULT , "\n" );
391
444
}
392
445
}
393
446
@@ -402,7 +455,8 @@ static u64 calc_used_bytes(struct btrfs_ioctl_space_args *si)
402
455
return ret ;
403
456
}
404
457
405
- static int print_one_fs (struct btrfs_ioctl_fs_info_args * fs_info ,
458
+ static int print_one_fs (struct format_ctx * fctx ,
459
+ struct btrfs_ioctl_fs_info_args * fs_info ,
406
460
struct btrfs_ioctl_dev_info_args * dev_info ,
407
461
struct btrfs_ioctl_space_args * space_info ,
408
462
char * label , unsigned unit_mode )
@@ -419,10 +473,16 @@ static int print_one_fs(struct btrfs_ioctl_fs_info_args *fs_info,
419
473
else if (ret )
420
474
return ret ;
421
475
476
+ if (bconf .output_format == CMD_FORMAT_JSON )
477
+ fmt_print_start_group (fctx , NULL , JSON_TYPE_MAP );
478
+
422
479
uuid_unparse (fs_info -> fsid , uuidbuf );
423
- print_filesystem_info (label && * label ? label : NULL , uuidbuf ,
424
- calc_used_bytes (space_info ), fs_info -> num_devices ,
425
- unit_mode );
480
+ print_filesystem_info (fctx , label && * label ? label : NULL , uuidbuf ,
481
+ calc_used_bytes (space_info ), fs_info -> num_devices ,
482
+ unit_mode );
483
+
484
+ if (bconf .output_format == CMD_FORMAT_JSON )
485
+ fmt_print_start_group (fctx , "device-list" , JSON_TYPE_ARRAY );
426
486
427
487
for (i = 0 ; i < fs_info -> num_devices ; i ++ ) {
428
488
char * canonical_path ;
@@ -432,7 +492,8 @@ static int print_one_fs(struct btrfs_ioctl_fs_info_args *fs_info,
432
492
/* Add check for missing devices even mounted */
433
493
fd = open ((char * )tmp_dev_info -> path , O_RDONLY );
434
494
if (fd < 0 ) {
435
- print_filesystem_device (tmp_dev_info -> devid ,
495
+ print_filesystem_device (fctx ,
496
+ tmp_dev_info -> devid ,
436
497
0 , 0 ,
437
498
(char * )tmp_dev_info -> path ,
438
499
true,
@@ -441,19 +502,24 @@ static int print_one_fs(struct btrfs_ioctl_fs_info_args *fs_info,
441
502
}
442
503
close (fd );
443
504
canonical_path = path_canonicalize ((char * )tmp_dev_info -> path );
444
- print_filesystem_device (tmp_dev_info -> devid ,
445
- tmp_dev_info -> total_bytes , tmp_dev_info -> bytes_used ,
446
- canonical_path ,
447
- false,
448
- unit_mode );
505
+ print_filesystem_device (fctx , tmp_dev_info -> devid ,
506
+ tmp_dev_info -> total_bytes , tmp_dev_info -> bytes_used ,
507
+ canonical_path ,
508
+ false,
509
+ unit_mode );
449
510
450
511
free (canonical_path );
451
512
}
452
513
514
+ if (bconf .output_format == CMD_FORMAT_JSON ) {
515
+ fmt_print_end_group (fctx , "device-list" );
516
+ fmt_print_end_group (fctx , NULL );
517
+ }
518
+
453
519
return 0 ;
454
520
}
455
521
456
- static int btrfs_scan_kernel (void * search , unsigned unit_mode )
522
+ static int btrfs_scan_kernel (struct format_ctx * fctx , void * search , unsigned unit_mode )
457
523
{
458
524
int ret = 0 , fd ;
459
525
int found = 0 ;
@@ -500,10 +566,10 @@ static int btrfs_scan_kernel(void *search, unsigned unit_mode)
500
566
fd = open (mnt -> mnt_dir , O_RDONLY );
501
567
if ((fd != -1 ) && !get_df (fd , & space_info_arg )) {
502
568
/* Put space between filesystem entries for readability. */
503
- if (found != 0 )
569
+ if (found != 0 && bconf . output_format != CMD_FORMAT_JSON )
504
570
pr_verbose (LOG_DEFAULT , "\n" );
505
571
506
- print_one_fs (& fs_info_arg , dev_info_arg ,
572
+ print_one_fs (fctx , & fs_info_arg , dev_info_arg ,
507
573
space_info_arg , label , unit_mode );
508
574
free (space_info_arg );
509
575
memset (label , 0 , sizeof (label ));
@@ -767,6 +833,7 @@ static int cmd_filesystem_show(const struct cmd_struct *cmd,
767
833
LIST_HEAD (all_uuids );
768
834
struct btrfs_fs_devices * fs_devices ;
769
835
struct btrfs_root * root = NULL ;
836
+ struct format_ctx fctx ;
770
837
char * search = NULL ;
771
838
char * canon_path = NULL ;
772
839
int ret ;
@@ -810,6 +877,11 @@ static int cmd_filesystem_show(const struct cmd_struct *cmd,
810
877
if (check_argc_max (argc , optind + 1 ))
811
878
return 1 ;
812
879
880
+ if (bconf .output_format == CMD_FORMAT_JSON ) {
881
+ fmt_start (& fctx , filesystem_show_data_rowspec , 1 , 0 );
882
+ fmt_print_start_group (& fctx , "filesystem-list" , JSON_TYPE_ARRAY );
883
+ }
884
+
813
885
if (argc > optind ) {
814
886
search = argv [optind ];
815
887
if (* search == 0 )
@@ -862,7 +934,7 @@ static int cmd_filesystem_show(const struct cmd_struct *cmd,
862
934
}
863
935
864
936
/* show mounted btrfs */
865
- ret = btrfs_scan_kernel (search , unit_mode );
937
+ ret = btrfs_scan_kernel (& fctx , search , unit_mode );
866
938
if (search && !ret ) {
867
939
/* since search is found we are done */
868
940
goto out ;
@@ -913,10 +985,10 @@ static int cmd_filesystem_show(const struct cmd_struct *cmd,
913
985
914
986
list_for_each_entry (fs_devices , & all_uuids , fs_list ) {
915
987
/* Put space between filesystem entries for readability. */
916
- if (needs_newline )
988
+ if (needs_newline && bconf . output_format != CMD_FORMAT_JSON )
917
989
pr_verbose (LOG_DEFAULT , "\n" );
918
990
919
- print_one_uuid (fs_devices , unit_mode );
991
+ print_one_uuid (& fctx , fs_devices , unit_mode );
920
992
needs_newline = true;
921
993
}
922
994
@@ -930,13 +1002,21 @@ static int cmd_filesystem_show(const struct cmd_struct *cmd,
930
1002
free_fs_devices (fs_devices );
931
1003
}
932
1004
out :
1005
+ if (bconf .output_format == CMD_FORMAT_JSON ) {
1006
+ fmt_print_end_group (& fctx , "filesystem-list" );
1007
+ fmt_end (& fctx );
1008
+ }
933
1009
free (canon_path );
934
1010
if (root )
935
1011
close_ctree (root );
936
1012
free_seen_fsid (seen_fsid_hash );
937
1013
return !!ret ;
938
1014
}
939
- static DEFINE_SIMPLE_COMMAND (filesystem_show , "show ") ;
1015
+ #if EXPERIMENTAL
1016
+ static DEFINE_COMMAND_WITH_FLAGS (filesystem_show , "show" , CMD_FORMAT_JSON );
1017
+ #else
1018
+ DEFINE_SIMPLE_COMMAND (filesystem_show , "show" );
1019
+ #endif
940
1020
941
1021
static const char * const cmd_filesystem_sync_usage [] = {
942
1022
"btrfs filesystem sync <path>" ,
0 commit comments