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