@@ -272,36 +272,75 @@ static void splice_device_list(struct list_head *seed_devices,
272
272
list_splice (seed_devices , all_devices );
273
273
}
274
274
275
- static void print_filesystem_info (char * label , char uuidbuf [BTRFS_UUID_UNPARSED_SIZE ],
276
- u64 bytes_used , u64 num_devices ,
277
- unsigned unit_mode )
275
+ static const struct rowspec filesystem_show_data_rowspec [] = {
276
+ { .key = "label" , .fmt = "%s" , .out_json = "label" },
277
+ { .key = "uuid" , .fmt = "%s" , .out_json = "uuid" },
278
+ { .key = "num_devices" , .fmt = "%llu" , .out_json = "total_devices" },
279
+ { .key = "used" , .fmt = "%llu" , .out_json = "used" },
280
+ /* device list */
281
+ { .key = "devid" , .fmt = "%llu" , .out_json = "devid" },
282
+ { .key = "size" , .fmt = "%llu" , .out_json = "size" },
283
+ { .key = "used" , .fmt = "%llu" , .out_json = "used" },
284
+ { .key = "path" , .fmt = "%s" , .out_json = "path" },
285
+ { .key = "missing" , .fmt = "bool" , .out_json = "missing" },
286
+ ROWSPEC_END
287
+ };
288
+
289
+ static void print_filesystem_info (struct format_ctx * fctx ,
290
+ char * label , char uuidbuf [BTRFS_UUID_UNPARSED_SIZE ],
291
+ u64 bytes_used , u64 num_devices ,
292
+ unsigned unit_mode )
278
293
{
279
- if (label )
280
- pr_verbose (LOG_DEFAULT , "Label: '%s' " , label );
281
- else
282
- pr_verbose (LOG_DEFAULT , "Label: none " );
283
-
284
- pr_verbose (LOG_DEFAULT , " uuid: %s\n\tTotal devices %llu FS bytes used %s\n" , uuidbuf ,
285
- num_devices ,
286
- pretty_size_mode (bytes_used ,
287
- unit_mode ));
294
+ if (bconf .output_format == CMD_FORMAT_JSON ) {
295
+ if (label )
296
+ fmt_print (fctx , "label" , label );
297
+ else
298
+ fmt_print (fctx , "label" , "none" );
299
+
300
+ fmt_print (fctx , "uuid" , uuidbuf );
301
+ fmt_print (fctx , "num_devices" , num_devices );
302
+ fmt_print (fctx , "used" , bytes_used );
303
+ } else {
304
+ if (label )
305
+ pr_verbose (LOG_DEFAULT , "Label: '%s' " , label );
306
+ else
307
+ pr_verbose (LOG_DEFAULT , "Label: none " );
308
+
309
+ pr_verbose (LOG_DEFAULT , " uuid: %s\n\tTotal devices %llu FS bytes used %s\n" , uuidbuf ,
310
+ num_devices ,
311
+ pretty_size_mode (bytes_used ,
312
+ unit_mode ));
313
+ }
288
314
}
289
315
290
- static void print_filesystem_device (u64 devid , u64 total_bytes , u64 bytes_used ,
316
+ static void print_filesystem_device (struct format_ctx * fctx ,
317
+ u64 devid , u64 total_bytes , u64 bytes_used ,
291
318
char * path ,
292
319
bool missing ,
293
320
unsigned unit_mode )
294
321
{
295
- pr_verbose (LOG_DEFAULT , "\tdevid %4llu size %s used %s path %s%s\n" ,
296
- devid ,
297
- pretty_size_mode (total_bytes , unit_mode ),
298
- pretty_size_mode (bytes_used , unit_mode ),
299
- path ,
300
- missing ? " MISSING" : "" );
322
+ if (bconf .output_format == CMD_FORMAT_JSON ) {
323
+ fmt_print_start_group (fctx , NULL , JSON_TYPE_MAP );
324
+ fmt_print (fctx , "devid" , devid );
325
+ fmt_print (fctx , "size" , 0 );
326
+ fmt_print (fctx , "used" , 0 );
327
+ fmt_print (fctx , "path" , path );
328
+ if (missing )
329
+ fmt_print (fctx , "missing" , 0 );
330
+ fmt_print_end_group (fctx , NULL );
331
+ } else {
332
+ pr_verbose (LOG_DEFAULT , "\tdevid %4llu size %s used %s path %s%s\n" ,
333
+ devid ,
334
+ pretty_size_mode (total_bytes , unit_mode ),
335
+ pretty_size_mode (bytes_used , unit_mode ),
336
+ path ,
337
+ missing ? " MISSING" : "" );
338
+ }
301
339
}
302
340
303
341
static void print_devices (struct btrfs_fs_devices * fs_devices ,
304
- u64 * devs_found , unsigned unit_mode )
342
+ u64 * devs_found , unsigned unit_mode ,
343
+ struct format_ctx * fctx )
305
344
{
306
345
struct btrfs_device * device ;
307
346
struct btrfs_fs_devices * cur_fs ;
@@ -317,16 +356,17 @@ static void print_devices(struct btrfs_fs_devices *fs_devices,
317
356
318
357
list_sort (NULL , all_devices , cmp_device_id );
319
358
list_for_each_entry (device , all_devices , dev_list ) {
320
- print_filesystem_device (device -> devid ,
321
- device -> total_bytes , device -> bytes_used ,
322
- device -> name ,
323
- false,
324
- unit_mode );
359
+ print_filesystem_device (fctx , device -> devid ,
360
+ device -> total_bytes , device -> bytes_used ,
361
+ device -> name ,
362
+ false,
363
+ unit_mode );
325
364
(* devs_found )++ ;
326
365
}
327
366
}
328
367
329
- static void print_one_uuid (struct btrfs_fs_devices * fs_devices ,
368
+ static void print_one_uuid (struct format_ctx * fctx ,
369
+ struct btrfs_fs_devices * fs_devices ,
330
370
unsigned unit_mode )
331
371
{
332
372
char uuidbuf [BTRFS_UUID_UNPARSED_SIZE ];
@@ -342,16 +382,28 @@ static void print_one_uuid(struct btrfs_fs_devices *fs_devices,
342
382
dev_list );
343
383
total = device -> total_devs ;
344
384
345
- print_filesystem_info (device -> label && device -> label [0 ] ? device -> label : NULL , uuidbuf ,
346
- device -> super_bytes_used , total ,
347
- unit_mode );
385
+ if (bconf .output_format == CMD_FORMAT_JSON )
386
+ fmt_print_start_group (fctx , NULL , JSON_TYPE_MAP );
387
+
388
+ print_filesystem_info (fctx , device -> label && device -> label [0 ] ? device -> label : NULL , uuidbuf ,
389
+ device -> super_bytes_used , total ,
390
+ unit_mode );
348
391
349
- print_devices (fs_devices , & devs_found , unit_mode );
392
+ if (bconf .output_format == CMD_FORMAT_JSON )
393
+ fmt_print_start_group (fctx , "device-list" , JSON_TYPE_ARRAY );
350
394
351
- if (devs_found < total ) {
352
- pr_verbose (LOG_DEFAULT , "\t*** Some devices missing\n" );
395
+ print_devices (fs_devices , & devs_found , unit_mode , fctx );
396
+
397
+ // TODO: global missing option?
398
+ if (bconf .output_format == CMD_FORMAT_JSON ) {
399
+ fmt_print_end_group (fctx , NULL );
400
+ fmt_print_end_group (fctx , "device-list" );
401
+ } else {
402
+ if (devs_found < total ) {
403
+ pr_verbose (LOG_DEFAULT , "\t*** Some devices missing\n" );
404
+ }
405
+ pr_verbose (LOG_DEFAULT , "\n" );
353
406
}
354
- pr_verbose (LOG_DEFAULT , "\n" );
355
407
}
356
408
357
409
/* adds up all the used spaces as reported by the space info ioctl
@@ -365,7 +417,8 @@ static u64 calc_used_bytes(struct btrfs_ioctl_space_args *si)
365
417
return ret ;
366
418
}
367
419
368
- static int print_one_fs (struct btrfs_ioctl_fs_info_args * fs_info ,
420
+ static int print_one_fs (struct format_ctx * fctx ,
421
+ struct btrfs_ioctl_fs_info_args * fs_info ,
369
422
struct btrfs_ioctl_dev_info_args * dev_info ,
370
423
struct btrfs_ioctl_space_args * space_info ,
371
424
char * label , unsigned unit_mode )
@@ -382,10 +435,16 @@ static int print_one_fs(struct btrfs_ioctl_fs_info_args *fs_info,
382
435
else if (ret )
383
436
return ret ;
384
437
438
+ if (bconf .output_format == CMD_FORMAT_JSON )
439
+ fmt_print_start_group (fctx , NULL , JSON_TYPE_MAP );
440
+
385
441
uuid_unparse (fs_info -> fsid , uuidbuf );
386
- print_filesystem_info (label && * label ? label : NULL , uuidbuf ,
387
- calc_used_bytes (space_info ), fs_info -> num_devices ,
388
- unit_mode );
442
+ print_filesystem_info (fctx , label && * label ? label : NULL , uuidbuf ,
443
+ calc_used_bytes (space_info ), fs_info -> num_devices ,
444
+ unit_mode );
445
+
446
+ if (bconf .output_format == CMD_FORMAT_JSON )
447
+ fmt_print_start_group (fctx , "device-list" , JSON_TYPE_ARRAY );
389
448
390
449
for (i = 0 ; i < fs_info -> num_devices ; i ++ ) {
391
450
char * canonical_path ;
@@ -395,7 +454,8 @@ static int print_one_fs(struct btrfs_ioctl_fs_info_args *fs_info,
395
454
/* Add check for missing devices even mounted */
396
455
fd = open ((char * )tmp_dev_info -> path , O_RDONLY );
397
456
if (fd < 0 ) {
398
- print_filesystem_device (tmp_dev_info -> devid ,
457
+ print_filesystem_device (fctx ,
458
+ tmp_dev_info -> devid ,
399
459
0 , 0 ,
400
460
(char * )tmp_dev_info -> path ,
401
461
true,
@@ -404,20 +464,25 @@ static int print_one_fs(struct btrfs_ioctl_fs_info_args *fs_info,
404
464
}
405
465
close (fd );
406
466
canonical_path = path_canonicalize ((char * )tmp_dev_info -> path );
407
- print_filesystem_device (tmp_dev_info -> devid ,
408
- tmp_dev_info -> total_bytes , tmp_dev_info -> bytes_used ,
409
- canonical_path ,
410
- false,
411
- unit_mode );
467
+ print_filesystem_device (fctx , tmp_dev_info -> devid ,
468
+ tmp_dev_info -> total_bytes , tmp_dev_info -> bytes_used ,
469
+ canonical_path ,
470
+ false,
471
+ unit_mode );
412
472
413
473
free (canonical_path );
414
474
}
415
475
416
- pr_verbose (LOG_DEFAULT , "\n" );
476
+ if (bconf .output_format == CMD_FORMAT_JSON ) {
477
+ fmt_print_end_group (fctx , "device-list" );
478
+ fmt_print_end_group (fctx , NULL );
479
+ } else {
480
+ pr_verbose (LOG_DEFAULT , "\n" );
481
+ }
417
482
return 0 ;
418
483
}
419
484
420
- static int btrfs_scan_kernel (void * search , unsigned unit_mode )
485
+ static int btrfs_scan_kernel (struct format_ctx * fctx , void * search , unsigned unit_mode )
421
486
{
422
487
int ret = 0 , fd ;
423
488
int found = 0 ;
@@ -463,7 +528,7 @@ static int btrfs_scan_kernel(void *search, unsigned unit_mode)
463
528
464
529
fd = open (mnt -> mnt_dir , O_RDONLY );
465
530
if ((fd != -1 ) && !get_df (fd , & space_info_arg )) {
466
- print_one_fs (& fs_info_arg , dev_info_arg ,
531
+ print_one_fs (fctx , & fs_info_arg , dev_info_arg ,
467
532
space_info_arg , label , unit_mode );
468
533
free (space_info_arg );
469
534
memset (label , 0 , sizeof (label ));
@@ -727,6 +792,7 @@ static int cmd_filesystem_show(const struct cmd_struct *cmd,
727
792
LIST_HEAD (all_uuids );
728
793
struct btrfs_fs_devices * fs_devices ;
729
794
struct btrfs_root * root = NULL ;
795
+ struct format_ctx fctx ;
730
796
char * search = NULL ;
731
797
char * canon_path = NULL ;
732
798
int ret ;
@@ -769,6 +835,11 @@ static int cmd_filesystem_show(const struct cmd_struct *cmd,
769
835
if (check_argc_max (argc , optind + 1 ))
770
836
return 1 ;
771
837
838
+ if (bconf .output_format == CMD_FORMAT_JSON ) {
839
+ fmt_start (& fctx , filesystem_show_data_rowspec , 1 , 0 );
840
+ fmt_print_start_group (& fctx , "filesystem-list" , JSON_TYPE_ARRAY );
841
+ }
842
+
772
843
if (argc > optind ) {
773
844
search = argv [optind ];
774
845
if (* search == 0 )
@@ -821,7 +892,7 @@ static int cmd_filesystem_show(const struct cmd_struct *cmd,
821
892
}
822
893
823
894
/* show mounted btrfs */
824
- ret = btrfs_scan_kernel (search , unit_mode );
895
+ ret = btrfs_scan_kernel (& fctx , search , unit_mode );
825
896
if (search && !ret ) {
826
897
/* since search is found we are done */
827
898
goto out ;
@@ -865,7 +936,7 @@ static int cmd_filesystem_show(const struct cmd_struct *cmd,
865
936
}
866
937
867
938
list_for_each_entry (fs_devices , & all_uuids , fs_list )
868
- print_one_uuid (fs_devices , unit_mode );
939
+ print_one_uuid (& fctx , fs_devices , unit_mode );
869
940
870
941
if (search && !found ) {
871
942
error ("not a valid btrfs filesystem: %s" , search );
@@ -877,13 +948,21 @@ static int cmd_filesystem_show(const struct cmd_struct *cmd,
877
948
free_fs_devices (fs_devices );
878
949
}
879
950
out :
951
+ if (bconf .output_format == CMD_FORMAT_JSON ) {
952
+ fmt_print_end_group (& fctx , "filesystem-list" );
953
+ fmt_end (& fctx );
954
+ }
880
955
free (canon_path );
881
956
if (root )
882
957
close_ctree (root );
883
958
free_seen_fsid (seen_fsid_hash );
884
959
return !!ret ;
885
960
}
886
- static DEFINE_SIMPLE_COMMAND (filesystem_show , "show ") ;
961
+ #if EXPERIMENTAL
962
+ static DEFINE_COMMAND_WITH_FLAGS (filesystem_show , "show" , CMD_FORMAT_JSON );
963
+ #else
964
+ DEFINE_SIMPLE_COMMAND (filesystem_show , "show" );
965
+ #endif
887
966
888
967
static const char * const cmd_filesystem_sync_usage [] = {
889
968
"btrfs filesystem sync <path>" ,
0 commit comments