btrfs-progs: print-tree: fix chunk/block group flags output
[BUG] Commit ("btrfs-progs: use raid table for profile names in print-tree.c") introduced one bug in block group and chunk flags output and changed the behavior: item 1 key (FIRST_CHUNK_TREE CHUNK_ITEM 13631488) itemoff 16105 itemsize 80 length 8388608 owner 2 stripe_len 65536 type SINGLE ... item 2 key (FIRST_CHUNK_TREE CHUNK_ITEM 22020096) itemoff 15993 itemsize 112 length 8388608 owner 2 stripe_len 65536 type DUP ... item 3 key (FIRST_CHUNK_TREE CHUNK_ITEM 30408704) itemoff 15881 itemsize 112 length 268435456 owner 2 stripe_len 65536 type DUP ... Note that, the flag string only contains the profile (SINGLE/DUP/etc...) no type (DATA/METADATA/SYSTEM). And we have new "SINGLE" string, even that profile has no extra bit to indicate that. [CAUSE] The "SINGLE" part is caused by the raid array which has a name for SINGLE profile, even it doesn't have the corresponding bit. The missing type string is caused by a code bug: strcpy(buf, name); while (*tmp) { *tmp = toupper(*tmp); tmp++; } strcpy(ret, buf); The last strcpy() call overrides the existing string in @ret. [FIX] - Enhance string handling using strn*()/snprintf() - Add extra "UKNOWN.0x%llx" output for unknown profiles - Call proper strncat() to merge type and profile - Add extra handling for "SINGLE" to keep the old output Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
83c0a82289
commit
eacdd1606c
|
@ -159,40 +159,51 @@ static void print_inode_ref_item(struct extent_buffer *eb, u32 size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Caller should ensure sizeof(*ret)>=21 "DATA|METADATA|RAID10" */
|
/* The minimal length for the string buffer of block group/chunk flags */
|
||||||
|
#define BG_FLAG_STRING_LEN 64
|
||||||
|
|
||||||
static void bg_flags_to_str(u64 flags, char *ret)
|
static void bg_flags_to_str(u64 flags, char *ret)
|
||||||
{
|
{
|
||||||
int empty = 1;
|
int empty = 1;
|
||||||
|
char profile[BG_FLAG_STRING_LEN] = {};
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
|
ret[0] = '\0';
|
||||||
if (flags & BTRFS_BLOCK_GROUP_DATA) {
|
if (flags & BTRFS_BLOCK_GROUP_DATA) {
|
||||||
empty = 0;
|
empty = 0;
|
||||||
strcpy(ret, "DATA");
|
strncpy(ret, "DATA", BG_FLAG_STRING_LEN);
|
||||||
}
|
}
|
||||||
if (flags & BTRFS_BLOCK_GROUP_METADATA) {
|
if (flags & BTRFS_BLOCK_GROUP_METADATA) {
|
||||||
if (!empty)
|
if (!empty)
|
||||||
strcat(ret, "|");
|
strncat(ret, "|", BG_FLAG_STRING_LEN);
|
||||||
strcat(ret, "METADATA");
|
strncat(ret, "METADATA", BG_FLAG_STRING_LEN);
|
||||||
}
|
}
|
||||||
if (flags & BTRFS_BLOCK_GROUP_SYSTEM) {
|
if (flags & BTRFS_BLOCK_GROUP_SYSTEM) {
|
||||||
if (!empty)
|
if (!empty)
|
||||||
strcat(ret, "|");
|
strncat(ret, "|", BG_FLAG_STRING_LEN);
|
||||||
strcat(ret, "SYSTEM");
|
strncat(ret, "SYSTEM", BG_FLAG_STRING_LEN);
|
||||||
}
|
}
|
||||||
strcat(ret, "|");
|
|
||||||
name = btrfs_bg_type_to_raid_name(flags);
|
name = btrfs_bg_type_to_raid_name(flags);
|
||||||
if (!name) {
|
if (!name) {
|
||||||
strcat(ret, "UNKNOWN");
|
snprintf(profile, BG_FLAG_STRING_LEN, "UNKNOWN.0x%llx",
|
||||||
|
flags & BTRFS_BLOCK_GROUP_PROFILE_MASK);
|
||||||
} else {
|
} else {
|
||||||
char buf[32];
|
int i;
|
||||||
char *tmp = buf;
|
|
||||||
|
|
||||||
strcpy(buf, name);
|
/*
|
||||||
while (*tmp) {
|
* Special handing for SINGLE profile, we don't output "SINGLE"
|
||||||
*tmp = toupper(*tmp);
|
* for SINGLE profile, since there is no such bit for it.
|
||||||
tmp++;
|
* Thus here we only fill @profile if it's not single.
|
||||||
}
|
*/
|
||||||
strcpy(ret, buf);
|
if (strncmp(name, "single", strlen("single")) != 0)
|
||||||
|
strncpy(profile, name, BG_FLAG_STRING_LEN);
|
||||||
|
|
||||||
|
for (i = 0; i < BG_FLAG_STRING_LEN && profile[i]; i++)
|
||||||
|
profile[i] = toupper(profile[i]);
|
||||||
|
}
|
||||||
|
if (profile[0]) {
|
||||||
|
strncat(ret, "|", BG_FLAG_STRING_LEN);
|
||||||
|
strncat(ret, profile, BG_FLAG_STRING_LEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +226,7 @@ void print_chunk_item(struct extent_buffer *eb, struct btrfs_chunk *chunk)
|
||||||
u16 num_stripes = btrfs_chunk_num_stripes(eb, chunk);
|
u16 num_stripes = btrfs_chunk_num_stripes(eb, chunk);
|
||||||
int i;
|
int i;
|
||||||
u32 chunk_item_size;
|
u32 chunk_item_size;
|
||||||
char chunk_flags_str[32] = {0};
|
char chunk_flags_str[BG_FLAG_STRING_LEN] = {};
|
||||||
|
|
||||||
/* The chunk must contain at least one stripe */
|
/* The chunk must contain at least one stripe */
|
||||||
if (num_stripes < 1) {
|
if (num_stripes < 1) {
|
||||||
|
@ -986,7 +997,7 @@ static void print_block_group_item(struct extent_buffer *eb,
|
||||||
struct btrfs_block_group_item *bgi)
|
struct btrfs_block_group_item *bgi)
|
||||||
{
|
{
|
||||||
struct btrfs_block_group_item bg_item;
|
struct btrfs_block_group_item bg_item;
|
||||||
char flags_str[256];
|
char flags_str[BG_FLAG_STRING_LEN] = {};
|
||||||
|
|
||||||
read_extent_buffer(eb, &bg_item, (unsigned long)bgi, sizeof(bg_item));
|
read_extent_buffer(eb, &bg_item, (unsigned long)bgi, sizeof(bg_item));
|
||||||
memset(flags_str, 0, sizeof(flags_str));
|
memset(flags_str, 0, sizeof(flags_str));
|
||||||
|
|
Loading…
Reference in New Issue