[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20180219095447.11757-3-viktor.prutyanov@virtuozzo.com>
Date: Mon, 19 Feb 2018 12:54:44 +0300
From: Viktor Prutyanov <viktor.prutyanov@...tuozzo.com>
To: linux-ext4@...r.kernel.org
Cc: Theodore Ts'o <tytso@....edu>,
Dmitry Monakhov <dmonakhov@...nvz.org>,
Viktor Prutyanov <viktor.prutyanov@...tuozzo.com>
Subject: [PATCH 2/5] dumpe2fs: add JSON output of block groups
This patch adds '-j' option for JSON output of block groups information
Signed-off-by: Viktor Prutyanov <viktor.prutyanov@...tuozzo.com>
---
misc/dumpe2fs.8.in | 3 +
misc/dumpe2fs.c | 273 +++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 269 insertions(+), 7 deletions(-)
diff --git a/misc/dumpe2fs.8.in b/misc/dumpe2fs.8.in
index da78d4fc..d03ee8be 100644
--- a/misc/dumpe2fs.8.in
+++ b/misc/dumpe2fs.8.in
@@ -72,6 +72,9 @@ as the pathname to the image file.
.B \-x
print the detailed group information block numbers in hexadecimal format
.TP
+.B \-j
+use JSON ouput format
+.TP
.B \-V
print the version number of
.B dumpe2fs
diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c
index 395ea9ee..ef300455 100644
--- a/misc/dumpe2fs.c
+++ b/misc/dumpe2fs.c
@@ -42,6 +42,7 @@ extern int optind;
#include "support/nls-enable.h"
#include "support/plausible.h"
+#include "support/json-out.h"
#include "../version.h"
#define in_use(m, x) (ext2fs_test_bit ((x), (m)))
@@ -53,7 +54,7 @@ static int blocks64 = 0;
static void usage(void)
{
- fprintf(stderr, _("Usage: %s [-bfghixV] [-o superblock=<num>] "
+ fprintf(stderr, _("Usage: %s [-bfghixjV] [-o superblock=<num>] "
"[-o blocksize=<num>] device\n"), program_name);
exit(1);
}
@@ -69,6 +70,17 @@ static void print_number(unsigned long long num)
printf("%llu", num);
}
+static void snprint_number(char *str, size_t size, unsigned long long num)
+{
+ if (hex_format) {
+ if (blocks64)
+ snprintf(str, size, "0x%08llx", num);
+ else
+ snprintf(str, size, "0x%04llx", num);
+ } else
+ snprintf(str, size, "%llu", num);
+}
+
static void print_range(unsigned long long a, unsigned long long b)
{
if (hex_format) {
@@ -80,6 +92,17 @@ static void print_range(unsigned long long a, unsigned long long b)
printf("%llu-%llu", a, b);
}
+static void snprint_range(char *str, size_t size, unsigned long long a, unsigned long long b)
+{
+ if (hex_format) {
+ if (blocks64)
+ snprintf(str, size, "0x%08llx-0x%08llx", a, b);
+ else
+ snprintf(str, size, "0x%04llx-0x%04llx", a, b);
+ } else
+ snprintf(str, size, "%llu-%llu", a, b);
+}
+
static void print_free(unsigned long group, char * bitmap,
unsigned long num, unsigned long offset, int ratio)
{
@@ -106,6 +129,30 @@ static void print_free(unsigned long group, char * bitmap,
}
}
+static void fill_json_free(struct json_list *list, char *buf, size_t buf_size,
+ unsigned long group, char *bitmap, unsigned long num,
+ unsigned long offset, int ratio)
+{
+ unsigned long i;
+ unsigned long j;
+
+ offset /= ratio;
+ offset += group * num;
+ for (i = 0; i < num; i++)
+ if (!in_use (bitmap, i))
+ {
+ for (j = i; j < num && !in_use (bitmap, j); j++)
+ ;
+ if (--j == i)
+ snprint_number(buf, buf_size, (i + offset) * ratio);
+ else {
+ snprint_range(buf, buf_size, (i + offset) * ratio, (j + offset) * ratio);
+ i = j;
+ }
+ json_list_add_str(list, buf);
+ }
+}
+
static void print_bg_opt(int bg_flags, int mask,
const char *str, int *first)
{
@@ -136,6 +183,25 @@ static void print_bg_opts(ext2_filsys fs, dgrp_t i)
fputc('\n', stdout);
}
+static void fill_json_bg_opts(struct json_obj *obj, ext2_filsys fs, dgrp_t i)
+{
+ int bg_flags = 0;
+ struct json_list *bg_opts_list = json_list_create_in_obj(obj, "bg-opts",
+ JSON_VAL_STRING);
+
+ if (ext2fs_has_group_desc_csum(fs))
+ bg_flags = ext2fs_bg_flags(fs, i);
+ else
+ return;
+
+ if (bg_flags & EXT2_BG_INODE_UNINIT)
+ json_list_add_str(bg_opts_list, "INODE_UNINIT");
+ if (bg_flags & EXT2_BG_BLOCK_UNINIT)
+ json_list_add_str(bg_opts_list, "BLOCK_UNINIT");
+ if (bg_flags & EXT2_BG_INODE_ZEROED)
+ json_list_add_str(bg_opts_list, "ITABLE_ZEROED");
+}
+
static void print_bg_rel_offset(ext2_filsys fs, blk64_t block, int itable,
blk64_t first_block, blk64_t last_block)
{
@@ -150,6 +216,20 @@ static void print_bg_rel_offset(ext2_filsys fs, blk64_t block, int itable,
}
}
+static void snprint_bg_rel_offset(char *str, size_t size, ext2_filsys fs,
+ blk64_t block, int itable, blk64_t first_block, blk64_t last_block)
+{
+ if ((block >= first_block) && (block <= last_block)) {
+ if (itable && block == first_block)
+ return;
+ snprintf(str, size, "+%u", (unsigned)(block - first_block));
+ } else if (ext2fs_has_feature_flex_bg(fs->super)) {
+ dgrp_t flex_grp = ext2fs_group_of_blk2(fs, block);
+ snprintf(str, size, "bg #%u + %u", flex_grp,
+ (unsigned)(block-ext2fs_group_first_block2(fs,flex_grp)));
+ }
+}
+
static void list_desc(ext2_filsys fs, int grp_only)
{
unsigned long i;
@@ -321,6 +401,165 @@ static void list_desc(ext2_filsys fs, int grp_only)
free(inode_bitmap);
}
+static void fill_json_desc(struct json_obj *obj, ext2_filsys fs)
+{
+ unsigned long i;
+ blk64_t first_block, last_block;
+ blk64_t super_blk, old_desc_blk, new_desc_blk;
+ char *block_bitmap=NULL, *inode_bitmap=NULL;
+ const char *units = "blocks";
+ int inode_blocks_per_group, old_desc_blocks, reserved_gdt;
+ int block_nbytes, inode_nbytes;
+ int has_super;
+ blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block);
+ ext2_ino_t ino_itr = 1;
+ errcode_t retval;
+ struct json_list *desc_list = json_list_create_in_obj(obj, "desc", JSON_VAL_OBJECT);
+ char buf[64];
+
+ if (ext2fs_has_feature_bigalloc(fs->super))
+ units = "clusters";
+
+ block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
+ inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
+
+ if (fs->block_map)
+ block_bitmap = malloc(block_nbytes);
+ if (fs->inode_map)
+ inode_bitmap = malloc(inode_nbytes);
+ inode_blocks_per_group = ((fs->super->s_inodes_per_group *
+ EXT2_INODE_SIZE(fs->super)) +
+ EXT2_BLOCK_SIZE(fs->super) - 1) /
+ EXT2_BLOCK_SIZE(fs->super);
+ reserved_gdt = fs->super->s_reserved_gdt_blocks;
+ first_block = fs->super->s_first_data_block;
+ if (ext2fs_has_feature_meta_bg(fs->super))
+ old_desc_blocks = fs->super->s_first_meta_bg;
+ else
+ old_desc_blocks = fs->desc_blocks;
+
+ for (i = 0; i < fs->group_desc_count; i++) {
+ struct json_obj *group_obj = json_obj_create();
+
+ json_list_add_obj(desc_list, group_obj);
+
+ first_block = ext2fs_group_first_block2(fs, i);
+ last_block = ext2fs_group_last_block2(fs, i);
+
+ ext2fs_super_and_bgd_loc2(fs, i, &super_blk,
+ &old_desc_blk, &new_desc_blk, 0);
+
+ json_obj_add_fmt_buf_str(group_obj, "num", buf, sizeof(buf), "%lu", i);
+ snprint_range(buf, sizeof(buf), first_block, last_block);
+ json_obj_add_str(group_obj, "blocks", buf);
+ if (ext2fs_has_group_desc_csum(fs)) {
+ unsigned csum = ext2fs_bg_checksum(fs, i);
+ unsigned exp_csum = ext2fs_group_desc_csum(fs, i);
+
+ json_obj_add_fmt_buf_str(group_obj, "group-desc-csum",
+ buf, sizeof(buf), "0x%04x", csum);
+ if (csum != exp_csum)
+ json_obj_add_fmt_buf_str(group_obj, "group-desc-csum-exp",
+ buf, sizeof(buf), "0x%04x", exp_csum);
+ }
+
+ fill_json_bg_opts(group_obj, fs, i);
+ has_super = ((i==0) || super_blk);
+ if (has_super) {
+ json_obj_add_str(group_obj, "superblock-type",
+ i == 0 ? "Primary" : "Backup");
+ snprint_number(buf, sizeof(buf), super_blk);
+ json_obj_add_str(group_obj, "superblock-at", buf);
+ }
+ if (old_desc_blk) {
+ snprint_range(buf, sizeof(buf), old_desc_blk,
+ old_desc_blk + old_desc_blocks - 1);
+ json_obj_add_str(group_obj, "group-descriptors-at", buf);
+ if (reserved_gdt) {
+ snprint_range(buf, sizeof(buf), old_desc_blk + old_desc_blocks,
+ old_desc_blk + old_desc_blocks +
+ reserved_gdt - 1);
+ json_obj_add_str(group_obj, "reserved-gdt-blocks-at", buf);
+ }
+ } else if (new_desc_blk) {
+ snprint_number(buf, sizeof(buf), new_desc_blk);
+ json_obj_add_str(group_obj, "group-desc-at", buf);
+ has_super++;
+ }
+
+ snprint_number(buf, sizeof(buf), ext2fs_block_bitmap_loc(fs, i));
+ json_obj_add_str(group_obj, "block-bitmap-at", buf);
+ snprint_bg_rel_offset(buf, sizeof(buf), fs,
+ ext2fs_block_bitmap_loc(fs, i), 0,
+ first_block, last_block);
+ json_obj_add_str(group_obj, "block-bitmap-rel-offset", buf);
+ if (ext2fs_has_feature_metadata_csum(fs->super))
+ json_obj_add_fmt_buf_str(group_obj, "block-bitmap-csum", buf,
+ sizeof(buf), "0x%08x", ext2fs_block_bitmap_checksum(fs, i));
+
+ snprint_number(buf, sizeof(buf), ext2fs_inode_bitmap_loc(fs, i));
+ json_obj_add_str(group_obj, "inode-bitmap-at", buf);
+ snprint_bg_rel_offset(buf, sizeof(buf), fs,
+ ext2fs_inode_bitmap_loc(fs, i), 0,
+ first_block, last_block);
+ json_obj_add_str(group_obj, "inode-bitmap-rel-offset", buf);
+ if (ext2fs_has_feature_metadata_csum(fs->super))
+ json_obj_add_fmt_buf_str(group_obj, "inode-bitmap-csum", buf,
+ sizeof(buf), "0x%08x", ext2fs_inode_bitmap_checksum(fs, i));
+
+ snprint_range(buf, sizeof(buf), ext2fs_inode_table_loc(fs, i),
+ ext2fs_inode_table_loc(fs, i) +
+ inode_blocks_per_group - 1);
+ json_obj_add_str(group_obj, "inode-table-at", buf);
+ snprint_bg_rel_offset(buf, sizeof(buf), fs,
+ ext2fs_inode_table_loc(fs, i), 1,
+ first_block, last_block);
+ json_obj_add_str(group_obj, "inode-table-rel-offset", buf);
+
+ json_obj_add_fmt_buf_str(group_obj, "free-blocks-count", buf,
+ sizeof(buf), "%u %s", ext2fs_bg_free_blocks_count(fs, i), units);
+ json_obj_add_fmt_buf_str(group_obj, "free-inodes-count", buf,
+ sizeof(buf), "%u", ext2fs_bg_free_inodes_count(fs, i));
+ json_obj_add_fmt_buf_str(group_obj, "used-dirs-count", buf,
+ sizeof(buf), "%u", ext2fs_bg_used_dirs_count(fs, i));
+ json_obj_add_fmt_buf_str(group_obj, "unused-inodes", buf,
+ sizeof(buf), "%u", ext2fs_bg_itable_unused(fs, i));
+ if (block_bitmap) {
+ struct json_list *free_blocks_list;
+
+ free_blocks_list = json_list_create_in_obj(group_obj,
+ "free-blocks", JSON_VAL_STRING);
+ retval = ext2fs_get_block_bitmap_range2(fs->block_map,
+ blk_itr, block_nbytes << 3, block_bitmap);
+ if (!retval)
+ fill_json_free(free_blocks_list, buf, sizeof(buf), i,
+ block_bitmap,
+ fs->super->s_clusters_per_group,
+ fs->super->s_first_data_block,
+ EXT2FS_CLUSTER_RATIO(fs));
+ blk_itr += fs->super->s_clusters_per_group;
+ }
+ if (inode_bitmap) {
+ struct json_list *free_inodes_list;
+
+ free_inodes_list = json_list_create_in_obj(group_obj,
+ "free-inodes", JSON_VAL_STRING);
+ retval = ext2fs_get_inode_bitmap_range2(fs->inode_map,
+ ino_itr, inode_nbytes << 3, inode_bitmap);
+ if (!retval)
+ fill_json_free(free_inodes_list, buf, sizeof(buf), i,
+ inode_bitmap,
+ fs->super->s_inodes_per_group,
+ 1, 1);
+ ino_itr += fs->super->s_inodes_per_group;
+ }
+ }
+ if (block_bitmap)
+ free(block_bitmap);
+ if (inode_bitmap)
+ free(inode_bitmap);
+}
+
static void list_bad_blocks(ext2_filsys fs, int dump)
{
badblocks_list bb_list = 0;
@@ -510,6 +749,8 @@ int main (int argc, char ** argv)
int header_only = 0;
int c;
int grp_only = 0;
+ int json = 0;
+ struct json_obj *dump_obj;
#ifdef ENABLE_NLS
setlocale(LC_MESSAGES, "");
@@ -524,7 +765,7 @@ int main (int argc, char ** argv)
if (argc && *argv)
program_name = *argv;
- while ((c = getopt(argc, argv, "bfghixVo:")) != EOF) {
+ while ((c = getopt(argc, argv, "bfghixjVo:")) != EOF) {
switch (c) {
case 'b':
print_badblocks++;
@@ -553,6 +794,9 @@ int main (int argc, char ** argv)
case 'x':
hex_format++;
break;
+ case 'j':
+ json++;
+ break;
default:
usage();
}
@@ -597,6 +841,8 @@ try_open_again:
check_plausibility(device_name, CHECK_FS_EXIST, NULL);
exit (1);
}
+ if (json)
+ dump_obj = json_obj_create();
fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE;
if (ext2fs_has_feature_64bit(fs->super))
blocks64 = 1;
@@ -605,17 +851,23 @@ try_open_again:
} else {
if (grp_only)
goto just_descriptors;
- list_super (fs->super);
- if (ext2fs_has_feature_journal_dev(fs->super)) {
+ if (!json)
+ list_super (fs->super);
+ if (!json && ext2fs_has_feature_journal_dev(fs->super)) {
print_journal_information(fs);
ext2fs_close_free(&fs);
exit(0);
}
- if (ext2fs_has_feature_journal(fs->super) &&
+ if (!json && ext2fs_has_feature_journal(fs->super) &&
(fs->super->s_journal_inum != 0))
print_inline_journal_information(fs);
- list_bad_blocks(fs, 0);
+ if (!json)
+ list_bad_blocks(fs, 0);
if (header_only) {
+ if (json) {
+ json_obj_print_json(dump_obj);
+ json_obj_delete(dump_obj);
+ }
ext2fs_close_free(&fs);
exit (0);
}
@@ -629,13 +881,20 @@ try_bitmaps_again:
if (!retval && (fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS))
printf("%s", _("\n*** Checksum errors detected in bitmaps! Run e2fsck now!\n\n"));
just_descriptors:
- list_desc(fs, grp_only);
+ if (json)
+ fill_json_desc(dump_obj, fs);
+ else
+ list_desc(fs, grp_only);
if (retval) {
printf(_("\n%s: %s: error reading bitmaps: %s\n"),
program_name, device_name,
error_message(retval));
}
}
+ if (json) {
+ json_obj_print_json(dump_obj);
+ json_obj_delete(dump_obj);
+ }
ext2fs_close_free(&fs);
remove_error_table(&et_ext2_error_table);
exit (0);
--
2.14.1
Powered by blists - more mailing lists