output objectid in btrfs_disk_key with human readable strings. Other updates are included for more readable output. Signed-off-by: Shen Feng <shen@cn.fujitsu.com> --- debug-tree.c | 11 +++--- print-tree.c | 114 +++++++++++++++++++++++++++++++++++++++++++++------------- print-tree.h | 1 + 3 files changed, 96 insertions(+), 30 deletions(-) diff --git a/debug-tree.c b/debug-tree.c index 53f8be4..9de9759 100644 --- a/debug-tree.c +++ b/debug-tree.c @@ -108,6 +108,7 @@ int main(int ac, char **av) struct btrfs_key key; struct btrfs_root_item ri; struct extent_buffer *leaf; + struct btrfs_disk_key disk_key; struct btrfs_key found_key; char uuidbuf[37]; int ret; @@ -164,7 +165,8 @@ int main(int ac, char **av) leaf = path.nodes[0]; slot = path.slots[0]; } - btrfs_item_key_to_cpu(leaf, &found_key, path.slots[0]); + btrfs_item_key(leaf, &disk_key, path.slots[0]); + btrfs_disk_key_to_cpu(&found_key, &disk_key); if (btrfs_key_type(&found_key) == BTRFS_ROOT_ITEM_KEY) { unsigned long offset; struct extent_buffer *buf; @@ -250,10 +252,9 @@ int main(int ac, char **av) } } if (!skip && !extent_only) { - printf(" tree (%llu %u %llu)\n", - (unsigned long long)found_key.objectid, - found_key.type, - (unsigned long long)found_key.offset); + printf(" tree "); + btrfs_print_key(&disk_key); + printf(" \n"); btrfs_print_tree(root, buf); } else if (extent_only && !skip) { print_extents(root, buf); diff --git a/print-tree.c b/print-tree.c index 52ef7c7..557264e 100644 --- a/print-tree.c +++ b/print-tree.c @@ -23,6 +23,7 @@ #include "radix-tree.h" #include "ctree.h" #include "disk-io.h" +#include "print-tree.h" static int print_dir_item(struct extent_buffer *eb, struct btrfs_item *item, struct btrfs_dir_item *di) @@ -38,9 +39,9 @@ static int print_dir_item(struct extent_buffer *eb, struct btrfs_item *item, total = btrfs_item_size(eb, item); while(cur < total) { btrfs_dir_item_key(eb, di, &location); - printf("\t\tdir index %llu type %u\n", - (unsigned long long)btrfs_disk_key_objectid(&location), - btrfs_dir_type(eb, di)); + printf("\t\tlocation "); + btrfs_print_key(&location); + printf(" type %u\n", btrfs_dir_type(eb, di)); name_len = btrfs_dir_name_len(eb, di); data_len = btrfs_dir_data_len(eb, di); len = (name_len <= sizeof(namebuf))? name_len: sizeof(namebuf); @@ -239,6 +240,74 @@ static void print_key_type(u8 type) }; } +static void print_objectid(unsigned long long objectid, u8 type) +{ + switch (objectid) { + case BTRFS_ROOT_TREE_OBJECTID: + if (type == BTRFS_DEV_ITEM_KEY) + printf("DEV_ITEMS"); + else + printf("ROOT_TREE"); + break; + case BTRFS_EXTENT_TREE_OBJECTID: + printf("EXTENT_TREE"); + break; + case BTRFS_CHUNK_TREE_OBJECTID: + printf("CHUNK_TREE"); + break; + case BTRFS_DEV_TREE_OBJECTID: + printf("DEV_TREE"); + break; + case BTRFS_FS_TREE_OBJECTID: + printf("FS_TREE"); + break; + case BTRFS_ROOT_TREE_DIR_OBJECTID: + printf("ROOT_TREE_DIR"); + break; + case BTRFS_CSUM_TREE_OBJECTID: + printf("CSUM_TREE"); + break; + case BTRFS_ORPHAN_OBJECTID: + printf("ORPHAN"); + break; + case BTRFS_TREE_LOG_OBJECTID: + printf("TREE_LOG"); + break; + case BTRFS_TREE_LOG_FIXUP_OBJECTID: + printf("EXTENT_TREE"); + break; + case BTRFS_TREE_RELOC_OBJECTID: + printf("TREE_RELOC"); + break; + case BTRFS_DATA_RELOC_TREE_OBJECTID: + printf("DATA_RELOC_TREE"); + break; + case BTRFS_EXTENT_CSUM_OBJECTID: + printf("EXTENT_CSUM"); + break; + case BTRFS_MULTIPLE_OBJECTIDS: + printf("MULTIPLE"); + break; + case BTRFS_FIRST_CHUNK_TREE_OBJECTID: + printf("FIRST_CHUNK_TREE"); + break; + default: + printf("%llu", objectid); + } +} + +void btrfs_print_key(struct btrfs_disk_key *disk_key) +{ + u8 type; + printf("key ("); + type = btrfs_disk_key_type(disk_key); + print_objectid((unsigned long long)btrfs_disk_key_objectid(disk_key), + type); + printf(" "); + print_key_type(type); + printf(" %llu)", (unsigned long long)btrfs_disk_key_offset(disk_key)); +} + void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) { int i; @@ -260,7 +329,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) u32 nr = btrfs_header_nritems(l); u32 type; - printf("leaf %llu ptrs %d free space %d generation %llu owner %llu\n", + printf("leaf %llu items %d free space %d generation %llu owner %llu\n", (unsigned long long)btrfs_header_bytenr(l), nr, btrfs_leaf_free_space(root, l), (unsigned long long)btrfs_header_generation(l), @@ -271,12 +340,9 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) item = btrfs_item_nr(l, i); btrfs_item_key(l, &disk_key, i); type = btrfs_disk_key_type(&disk_key); - printf("\titem %d key (%llu ", - i, - (unsigned long long)btrfs_disk_key_objectid(&disk_key)); - print_key_type(type); - printf(" %llu) itemoff %d itemsize %d\n", - (unsigned long long)btrfs_disk_key_offset(&disk_key), + printf("\titem %d ", i); + btrfs_print_key(&disk_key); + printf(" itemoff %d itemsize %d\n", btrfs_item_offset(l, item), btrfs_item_size(l, item)); switch (type) { @@ -310,15 +376,13 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) btrfs_root_level(&root_item), (unsigned long long)btrfs_root_dirid(&root_item), btrfs_root_refs(&root_item)); - if (1 || btrfs_root_refs(&root_item) == 0) { + if (btrfs_root_refs(&root_item) == 0) { struct btrfs_key drop_key; btrfs_disk_key_to_cpu(&drop_key, &root_item.drop_progress); - printf("\t\tdrop key %Lu %x %Lu level %d\n", - (unsigned long long)drop_key.objectid, - drop_key.type, - (unsigned long long)drop_key.offset, - root_item.drop_level); + printf("\t\tdrop "); + btrfs_print_key(&root_item.drop_progress); + printf(" level %d\n", root_item.drop_level); } break; case BTRFS_ROOT_REF_KEY: @@ -359,8 +423,9 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) struct btrfs_block_group_item); read_extent_buffer(l, &bg_item, (unsigned long)bi, sizeof(bg_item)); - printf("\t\tblock group used %llu flags %llu\n", + printf("\t\tblock group used %llu chunk_objectid %llu flags %llu\n", (unsigned long long)btrfs_block_group_used(&bg_item), + (unsigned long long)btrfs_block_group_chunk_objectid(&bg_item), (unsigned long long)btrfs_block_group_flags(&bg_item)); break; case BTRFS_CHUNK_ITEM_KEY: @@ -400,6 +465,7 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *eb) int i; u32 nr; u32 size; + struct btrfs_disk_key disk_key; struct btrfs_key key; if (!eb) @@ -409,7 +475,7 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *eb) btrfs_print_leaf(root, eb); return; } - printf("node %llu level %d ptrs %d free %u generation %llu owner %llu\n", + printf("node %llu level %d items %d free %u generation %llu owner %llu\n", (unsigned long long)eb->start, btrfs_header_level(eb), nr, (u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr, @@ -420,13 +486,11 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *eb) size = btrfs_level_size(root, btrfs_header_level(eb) - 1); for (i = 0; i < nr; i++) { u64 blocknr = btrfs_node_blockptr(eb, i); - btrfs_node_key_to_cpu(eb, &key, i); - printf("\tkey %d (%llu ", - i, - (unsigned long long)key.objectid); - print_key_type(key.type); - printf(" %llu) block %llu (%llu) gen %llu\n", - (unsigned long long)key.offset, + btrfs_node_key(eb, &disk_key, i); + btrfs_disk_key_to_cpu(&key, &disk_key); + printf("\t"); + btrfs_print_key(&disk_key); + printf(" block %llu (%llu) gen %llu\n", (unsigned long long)blocknr, (unsigned long long)blocknr / size, (unsigned long long)btrfs_node_ptr_generation(eb, i)); diff --git a/print-tree.h b/print-tree.h index da75efe..4d1a01a 100644 --- a/print-tree.h +++ b/print-tree.h @@ -20,4 +20,5 @@ #define __PRINT_TREE_ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l); void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *t); +void btrfs_print_key(struct btrfs_disk_key *disk_key); #endif -- 1.6.0.6 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Shen Feng wrote:> output objectid in btrfs_disk_key with human readable strings. > Other updates are included for more readable output.This gets messy fast. I''d like to see some sort of generic extensible printk mechanism in the kernel. Maybe I''ve been spoiled by the reiserfs type printing but it seems a lot nicer to do eprintk(&ops, "key: %k\n"); than to split them out into different printks. Since the core behavior ends up in vsnprintf, you get it for things like panic for free too. Ideally, the tprintk(&ops, ...) would be hidden behind a btrfs_warning() or something. I have a patch set that implements an extensible printk so that every single pointer type doesn''t need to be added to lib/vsprintf.c''s pointer(). - -Jeff> Signed-off-by: Shen Feng <shen@cn.fujitsu.com> > --- > debug-tree.c | 11 +++--- > print-tree.c | 114 +++++++++++++++++++++++++++++++++++++++++++++------------- > print-tree.h | 1 + > 3 files changed, 96 insertions(+), 30 deletions(-) > > diff --git a/debug-tree.c b/debug-tree.c > index 53f8be4..9de9759 100644 > --- a/debug-tree.c > +++ b/debug-tree.c > @@ -108,6 +108,7 @@ int main(int ac, char **av) > struct btrfs_key key; > struct btrfs_root_item ri; > struct extent_buffer *leaf; > + struct btrfs_disk_key disk_key; > struct btrfs_key found_key; > char uuidbuf[37]; > int ret; > @@ -164,7 +165,8 @@ int main(int ac, char **av) > leaf = path.nodes[0]; > slot = path.slots[0]; > } > - btrfs_item_key_to_cpu(leaf, &found_key, path.slots[0]); > + btrfs_item_key(leaf, &disk_key, path.slots[0]); > + btrfs_disk_key_to_cpu(&found_key, &disk_key); > if (btrfs_key_type(&found_key) == BTRFS_ROOT_ITEM_KEY) { > unsigned long offset; > struct extent_buffer *buf; > @@ -250,10 +252,9 @@ int main(int ac, char **av) > } > } > if (!skip && !extent_only) { > - printf(" tree (%llu %u %llu)\n", > - (unsigned long long)found_key.objectid, > - found_key.type, > - (unsigned long long)found_key.offset); > + printf(" tree "); > + btrfs_print_key(&disk_key); > + printf(" \n"); > btrfs_print_tree(root, buf); > } else if (extent_only && !skip) { > print_extents(root, buf); > diff --git a/print-tree.c b/print-tree.c > index 52ef7c7..557264e 100644 > --- a/print-tree.c > +++ b/print-tree.c > @@ -23,6 +23,7 @@ > #include "radix-tree.h" > #include "ctree.h" > #include "disk-io.h" > +#include "print-tree.h" > > static int print_dir_item(struct extent_buffer *eb, struct btrfs_item *item, > struct btrfs_dir_item *di) > @@ -38,9 +39,9 @@ static int print_dir_item(struct extent_buffer *eb, struct btrfs_item *item, > total = btrfs_item_size(eb, item); > while(cur < total) { > btrfs_dir_item_key(eb, di, &location); > - printf("\t\tdir index %llu type %u\n", > - (unsigned long long)btrfs_disk_key_objectid(&location), > - btrfs_dir_type(eb, di)); > + printf("\t\tlocation "); > + btrfs_print_key(&location); > + printf(" type %u\n", btrfs_dir_type(eb, di)); > name_len = btrfs_dir_name_len(eb, di); > data_len = btrfs_dir_data_len(eb, di); > len = (name_len <= sizeof(namebuf))? name_len: sizeof(namebuf); > @@ -239,6 +240,74 @@ static void print_key_type(u8 type) > }; > } > > +static void print_objectid(unsigned long long objectid, u8 type) > +{ > + switch (objectid) { > + case BTRFS_ROOT_TREE_OBJECTID: > + if (type == BTRFS_DEV_ITEM_KEY) > + printf("DEV_ITEMS"); > + else > + printf("ROOT_TREE"); > + break; > + case BTRFS_EXTENT_TREE_OBJECTID: > + printf("EXTENT_TREE"); > + break; > + case BTRFS_CHUNK_TREE_OBJECTID: > + printf("CHUNK_TREE"); > + break; > + case BTRFS_DEV_TREE_OBJECTID: > + printf("DEV_TREE"); > + break; > + case BTRFS_FS_TREE_OBJECTID: > + printf("FS_TREE"); > + break; > + case BTRFS_ROOT_TREE_DIR_OBJECTID: > + printf("ROOT_TREE_DIR"); > + break; > + case BTRFS_CSUM_TREE_OBJECTID: > + printf("CSUM_TREE"); > + break; > + case BTRFS_ORPHAN_OBJECTID: > + printf("ORPHAN"); > + break; > + case BTRFS_TREE_LOG_OBJECTID: > + printf("TREE_LOG"); > + break; > + case BTRFS_TREE_LOG_FIXUP_OBJECTID: > + printf("EXTENT_TREE"); > + break; > + case BTRFS_TREE_RELOC_OBJECTID: > + printf("TREE_RELOC"); > + break; > + case BTRFS_DATA_RELOC_TREE_OBJECTID: > + printf("DATA_RELOC_TREE"); > + break; > + case BTRFS_EXTENT_CSUM_OBJECTID: > + printf("EXTENT_CSUM"); > + break; > + case BTRFS_MULTIPLE_OBJECTIDS: > + printf("MULTIPLE"); > + break; > + case BTRFS_FIRST_CHUNK_TREE_OBJECTID: > + printf("FIRST_CHUNK_TREE"); > + break; > + default: > + printf("%llu", objectid); > + } > +} > + > +void btrfs_print_key(struct btrfs_disk_key *disk_key) > +{ > + u8 type; > + printf("key ("); > + type = btrfs_disk_key_type(disk_key); > + print_objectid((unsigned long long)btrfs_disk_key_objectid(disk_key), > + type); > + printf(" "); > + print_key_type(type); > + printf(" %llu)", (unsigned long long)btrfs_disk_key_offset(disk_key)); > +} > + > void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) > { > int i; > @@ -260,7 +329,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) > u32 nr = btrfs_header_nritems(l); > u32 type; > > - printf("leaf %llu ptrs %d free space %d generation %llu owner %llu\n", > + printf("leaf %llu items %d free space %d generation %llu owner %llu\n", > (unsigned long long)btrfs_header_bytenr(l), nr, > btrfs_leaf_free_space(root, l), > (unsigned long long)btrfs_header_generation(l), > @@ -271,12 +340,9 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) > item = btrfs_item_nr(l, i); > btrfs_item_key(l, &disk_key, i); > type = btrfs_disk_key_type(&disk_key); > - printf("\titem %d key (%llu ", > - i, > - (unsigned long long)btrfs_disk_key_objectid(&disk_key)); > - print_key_type(type); > - printf(" %llu) itemoff %d itemsize %d\n", > - (unsigned long long)btrfs_disk_key_offset(&disk_key), > + printf("\titem %d ", i); > + btrfs_print_key(&disk_key); > + printf(" itemoff %d itemsize %d\n", > btrfs_item_offset(l, item), > btrfs_item_size(l, item)); > switch (type) { > @@ -310,15 +376,13 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) > btrfs_root_level(&root_item), > (unsigned long long)btrfs_root_dirid(&root_item), > btrfs_root_refs(&root_item)); > - if (1 || btrfs_root_refs(&root_item) == 0) { > + if (btrfs_root_refs(&root_item) == 0) { > struct btrfs_key drop_key; > btrfs_disk_key_to_cpu(&drop_key, > &root_item.drop_progress); > - printf("\t\tdrop key %Lu %x %Lu level %d\n", > - (unsigned long long)drop_key.objectid, > - drop_key.type, > - (unsigned long long)drop_key.offset, > - root_item.drop_level); > + printf("\t\tdrop "); > + btrfs_print_key(&root_item.drop_progress); > + printf(" level %d\n", root_item.drop_level); > } > break; > case BTRFS_ROOT_REF_KEY: > @@ -359,8 +423,9 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) > struct btrfs_block_group_item); > read_extent_buffer(l, &bg_item, (unsigned long)bi, > sizeof(bg_item)); > - printf("\t\tblock group used %llu flags %llu\n", > + printf("\t\tblock group used %llu chunk_objectid %llu flags %llu\n", > (unsigned long long)btrfs_block_group_used(&bg_item), > + (unsigned long long)btrfs_block_group_chunk_objectid(&bg_item), > (unsigned long long)btrfs_block_group_flags(&bg_item)); > break; > case BTRFS_CHUNK_ITEM_KEY: > @@ -400,6 +465,7 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *eb) > int i; > u32 nr; > u32 size; > + struct btrfs_disk_key disk_key; > struct btrfs_key key; > > if (!eb) > @@ -409,7 +475,7 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *eb) > btrfs_print_leaf(root, eb); > return; > } > - printf("node %llu level %d ptrs %d free %u generation %llu owner %llu\n", > + printf("node %llu level %d items %d free %u generation %llu owner %llu\n", > (unsigned long long)eb->start, > btrfs_header_level(eb), nr, > (u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr, > @@ -420,13 +486,11 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *eb) > size = btrfs_level_size(root, btrfs_header_level(eb) - 1); > for (i = 0; i < nr; i++) { > u64 blocknr = btrfs_node_blockptr(eb, i); > - btrfs_node_key_to_cpu(eb, &key, i); > - printf("\tkey %d (%llu ", > - i, > - (unsigned long long)key.objectid); > - print_key_type(key.type); > - printf(" %llu) block %llu (%llu) gen %llu\n", > - (unsigned long long)key.offset, > + btrfs_node_key(eb, &disk_key, i); > + btrfs_disk_key_to_cpu(&key, &disk_key); > + printf("\t"); > + btrfs_print_key(&disk_key); > + printf(" block %llu (%llu) gen %llu\n", > (unsigned long long)blocknr, > (unsigned long long)blocknr / size, > (unsigned long long)btrfs_node_ptr_generation(eb, i)); > diff --git a/print-tree.h b/print-tree.h > index da75efe..4d1a01a 100644 > --- a/print-tree.h > +++ b/print-tree.h > @@ -20,4 +20,5 @@ > #define __PRINT_TREE_ > void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l); > void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *t); > +void btrfs_print_key(struct btrfs_disk_key *disk_key); > #endif- -- Jeff Mahoney SUSE Labs -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.9 (GNU/Linux) Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org iEYEARECAAYFAkmd+6sACgkQLPWxlyuTD7LpXgCfcY96xUz7bFeJiXWZaMW8pUAx F9gAnR9qwIw/rlrDkGkHKRow93dlfdn/ =/1uI -----END PGP SIGNATURE----- -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, 2009-02-19 at 19:39 -0500, Jeff Mahoney wrote:> -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Shen Feng wrote: > > output objectid in btrfs_disk_key with human readable strings. > > Other updates are included for more readable output. > > This gets messy fast. I''d like to see some sort of generic extensible > printk mechanism in the kernel.This is a btrfs-progs patch ;)> Maybe I''ve been spoiled by the reiserfs > type printing but it seems a lot nicer to do eprintk(&ops, "key: %k\n"); > than to split them out into different printks. Since the core behavior > ends up in vsnprintf, you get it for things like panic for free too. > Ideally, the tprintk(&ops, ...) would be hidden behind a btrfs_warning() > or something. > > I have a patch set that implements an extensible printk so that every > single pointer type doesn''t need to be added to lib/vsprintf.c''s pointer(). >That would be interesting, I do miss the old reiserfs %k -chris -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Chris Mason wrote:> On Thu, 2009-02-19 at 19:39 -0500, Jeff Mahoney wrote: >> -----BEGIN PGP SIGNED MESSAGE----- >> Hash: SHA1 >> >> Shen Feng wrote: >>> output objectid in btrfs_disk_key with human readable strings. >>> Other updates are included for more readable output. >> This gets messy fast. I''d like to see some sort of generic extensible >> printk mechanism in the kernel. > > This is a btrfs-progs patch ;)Heh, oops. That''s an important bit of information.>> Maybe I''ve been spoiled by the reiserfs >> type printing but it seems a lot nicer to do eprintk(&ops, "key: %k\n"); >> than to split them out into different printks. Since the core behavior >> ends up in vsnprintf, you get it for things like panic for free too. >> Ideally, the tprintk(&ops, ...) would be hidden behind a btrfs_warning() >> or something. >> >> I have a patch set that implements an extensible printk so that every >> single pointer type doesn''t need to be added to lib/vsprintf.c''s pointer(). >> > > That would be interesting, I do miss the old reiserfs %kLet me clean them up a bit and send to LKML. I can probably do that later today. I decided to rename it to eprintk from a pretty ugly printk_custom. - -Jeff - -- Jeff Mahoney SUSE Labs -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.9 (GNU/Linux) Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org iEYEARECAAYFAkme2SMACgkQLPWxlyuTD7ITSwCeO3XaNGY29kA/5oBcdDL7DqpH B5wAnRv7RYjzX5h4pX+FbjTGTBGAFy7S =a5iu -----END PGP SIGNATURE----- -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
BTW, this is what I had in mind: This patch adds the ability to add arbitrary types to vsprintf rather than adding every type to pointer(). Future users include reiserfs and btrfs, where it''s much more conventient to print messages with common data structures with a simple printk rather than a series of them. It makes the code much cleaner and easier to read. This functionality is accessed via the e-prefixed versions of the usual string formatting and printing routines by using "%pe<letter>" as a format string. Callers establish a set of operations and pass it as the first artugment. I expect this will typically be hidden behind a helper function, much like reiserfs_warning, etc does now. Example, eprintk(btrfs_printf_ops, "Invalid key %pek\n", key); or more likely: btrfs_warning(sb, "Invalid key %pek\n", key); instead of printk("Invalid key [%llu %d %llu]\n", le64_to_cpu(key->objectid), key->type, le64_to_cpu(key->offset)); It''s even more useful when larger and/or multiple objects need to be printed. Another advantage is smaller code size due to smaller strings and less calculation surrounding each print site. I haven''t converted btrfs yet and reiserfs already uses a similar mechanism, so I don''t have hard numbers for this. The only exception to the e-prefix rule is kasprintf, etc, which will retain the k prefix. It''s sort of arbitrary, since I would have assumed those functions would retain a ka-prefix, but that isn''t the case. No additional code changes are required - this is for extensions only. Signed-off-by: Jeff Mahoney <jeffm@suse.com> --- include/linux/kernel.h | 36 ++++++++++++++++ include/linux/printf.h | 11 +++++ kernel/printk.c | 25 ++++++++++- lib/kasprintf.c | 28 +++++++++++- lib/vsprintf.c | 107 +++++++++++++++++++++++++++++++++++++++++++------ 5 files changed, 191 insertions(+), 16 deletions(-) --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -114,6 +114,7 @@ extern int console_printk[]; struct completion; struct pt_regs; struct user; +struct printf_operations; #ifdef CONFIG_PREEMPT_VOLUNTARY extern int _cond_resched(void); @@ -177,19 +178,42 @@ extern int strict_strtoull(const char *, extern int strict_strtoll(const char *, unsigned int, long long *); extern int sprintf(char * buf, const char * fmt, ...) __attribute__ ((format (printf, 2, 3))); +extern int esprintf(const struct printf_operations *ops, char *buf, + const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))); extern int vsprintf(char *buf, const char *, va_list) __attribute__ ((format (printf, 2, 0))); +extern int evsprintf(const struct printf_operations *ops, char *buf, + const char *, va_list) + __attribute__ ((format (printf, 3, 0))); extern int snprintf(char * buf, size_t size, const char * fmt, ...) __attribute__ ((format (printf, 3, 4))); +extern int esnprintf(const struct printf_operations *ops, char *buf, + size_t size, const char *fmt, ...) + __attribute__ ((format (printf, 4, 5))); extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) __attribute__ ((format (printf, 3, 0))); +extern int evsnprintf(const struct printf_operations *ops, char *buf, + size_t size, const char *fmt, va_list args) + __attribute__ ((format (printf, 4, 0))); extern int scnprintf(char * buf, size_t size, const char * fmt, ...) __attribute__ ((format (printf, 3, 4))); +extern int escnprintf(const struct printf_operations *ops, char *buf, + size_t size, const char *fmt, ...) + __attribute__ ((format (printf, 4, 5))); extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) __attribute__ ((format (printf, 3, 0))); +extern int evscnprintf(const struct printf_operations *ops, char *buf, + size_t size, const char *fmt, va_list args) + __attribute__ ((format (printf, 4, 0))); extern char *kasprintf(gfp_t gfp, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); +extern char *keasprintf(const struct printf_operations *ops, gfp_t gfp, + const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))); extern char *kvasprintf(gfp_t gfp, const char *fmt, va_list args); +extern char *kevasprintf(const struct printf_operations *ops, gfp_t gfp, + const char *fmt, va_list args); extern int sscanf(const char *, const char *, ...) __attribute__ ((format (scanf, 2, 3))); @@ -233,6 +257,12 @@ extern struct pid *session_of_pgrp(struc #define FW_INFO "[Firmware Info]: " #ifdef CONFIG_PRINTK +asmlinkage int evprintk(const struct printf_operations *ops, + const char *fmt, va_list args) + __attribute__ ((format (printf, 2, 0))); +asmlinkage int eprintk(const struct printf_operations *ops, + const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))) __cold; asmlinkage int vprintk(const char *fmt, va_list args) __attribute__ ((format (printf, 1, 0))); asmlinkage int printk(const char * fmt, ...) @@ -250,6 +280,12 @@ static inline int printk(const char *s, __attribute__ ((format (printf, 1, 2))); static inline int __cold printk(const char *s, ...) { return 0; } static inline int printk_ratelimit(void) { return 0; } +static inline int evprintk(const struct printf_operations *ops, + const char *s, va_list args) + __attribute__ ((format (printf, 2, 0))); +static inline int __cold eprintk(const struct printf_operations *ops, + const char *s, ...) + __attribute__ ((format (printf, 2, 3))); static inline bool printk_timed_ratelimit(unsigned long *caller_jiffies, \ unsigned int interval_msec) \ { return false; } --- /dev/null +++ b/include/linux/printf.h @@ -0,0 +1,11 @@ +#ifndef _PRINTF_H_ +#define _PRINTF_H_ + +struct printf_operations { + char operator; + char * (*handler)(const char *fmt, char *buf, char *end, + const void *ptr, int field_width, int precision, + int flags); +}; + +#endif --- a/kernel/printk.c +++ b/kernel/printk.c @@ -567,6 +567,20 @@ asmlinkage int printk(const char *fmt, . return r; } +asmlinkage int eprintk(const struct printf_operations *ops, + const char *fmt, ...) +{ + va_list args; + int r; + + va_start(args, fmt); + r = evprintk(ops, fmt, args); + va_end(args); + + return r; +} +EXPORT_SYMBOL(eprintk); + /* cpu currently holding logbuf_lock */ static volatile unsigned int printk_cpu = UINT_MAX; @@ -622,7 +636,8 @@ static int recursion_bug; static int new_text_line = 1; static char printk_buf[1024]; -asmlinkage int vprintk(const char *fmt, va_list args) +asmlinkage int evprintk(const struct printf_operations *ops, + const char *fmt, va_list args) { int printed_len = 0; int current_log_level = default_message_loglevel; @@ -665,7 +680,7 @@ asmlinkage int vprintk(const char *fmt, printed_len = strlen(recursion_bug_msg); } /* Emit the output into the temporary buffer */ - printed_len += vscnprintf(printk_buf + printed_len, + printed_len += evscnprintf(ops, printk_buf + printed_len, sizeof(printk_buf) - printed_len, fmt, args); @@ -737,6 +752,12 @@ out_restore_irqs: preempt_enable(); return printed_len; } +EXPORT_SYMBOL(evprintk); + +asmlinkage int vprintk(const char *fmt, va_list args) +{ + return evprintk(NULL, fmt, args); +} EXPORT_SYMBOL(printk); EXPORT_SYMBOL(vprintk); --- a/lib/kasprintf.c +++ b/lib/kasprintf.c @@ -8,26 +8,34 @@ #include <linux/module.h> #include <linux/types.h> #include <linux/string.h> +#include <linux/printf.h> /* Simplified asprintf. */ -char *kvasprintf(gfp_t gfp, const char *fmt, va_list ap) +char *kevasprintf(const struct printf_operations *ops, gfp_t gfp, + const char *fmt, va_list ap) { unsigned int len; char *p; va_list aq; va_copy(aq, ap); - len = vsnprintf(NULL, 0, fmt, aq); + len = evsnprintf(ops, NULL, 0, fmt, aq); va_end(aq); p = kmalloc(len+1, gfp); if (!p) return NULL; - vsnprintf(p, len+1, fmt, ap); + evsnprintf(ops, p, len+1, fmt, ap); return p; } +EXPORT_SYMBOL(kevasprintf); + +char *kvasprintf(gfp_t gfp, const char *fmt, va_list ap) +{ + return kevasprintf(NULL, gfp, fmt, ap); +} EXPORT_SYMBOL(kvasprintf); char *kasprintf(gfp_t gfp, const char *fmt, ...) @@ -42,3 +50,17 @@ char *kasprintf(gfp_t gfp, const char *f return p; } EXPORT_SYMBOL(kasprintf); + +char *keasprintf(const struct printf_operations *ops, gfp_t gfp, + const char *fmt, ...) +{ + va_list ap; + char *p; + + va_start(ap, fmt); + p = kevasprintf(ops, gfp, fmt, ap); + va_end(ap); + + return p; +} +EXPORT_SYMBOL(keasprintf); --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -25,6 +25,7 @@ #include <linux/kallsyms.h> #include <linux/uaccess.h> #include <linux/ioport.h> +#include <linux/printf.h> #include <asm/page.h> /* for PAGE_SIZE */ #include <asm/div64.h> @@ -641,6 +642,22 @@ static char *ip4_addr_string(char *buf, return string(buf, end, ip4_addr, field_width, precision, flags & ~SPECIAL); } +static char *epointer(const char *fmt, char *buf, char *end, const void *ptr, + int field_width, int precision, int flags, + const struct printf_operations *ops) +{ + const struct printf_operations *op; + if (!*fmt) + return NULL; + + for (op = ops; op && op->handler; op++) { + if (*fmt == op->operator) + return op->handler(fmt + 1, buf, end, ptr, field_width, + precision, flags); + } + return NULL; +} + /* * Show a ''%p'' thing. A kernel extension is that the ''%p'' is followed * by an extra set of alphanumeric characters that are extended format @@ -663,8 +680,11 @@ static char *ip4_addr_string(char *buf, * function pointers are really function descriptors, which contain a * pointer to the real address. */ -static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags) +static char *pointer(const char *fmt, char *buf, char *end, void *ptr, + int field_width, int precision, int flags, + const struct printf_operations *ops) { + char *p; if (!ptr) return string(buf, end, "(null)", field_width, precision, flags); @@ -691,6 +711,10 @@ static char *pointer(const char *fmt, ch return ip4_addr_string(buf, end, ptr, field_width, precision, flags); flags &= ~SPECIAL; break; + case ''e'': + if ((p = epointer(fmt + 1, buf, end, ptr, field_width, + precision, flags, ops))) + return p; } flags |= SMALL; if (field_width == -1) { @@ -704,6 +728,7 @@ static char *pointer(const char *fmt, ch * vsnprintf - Format a string and place it in a buffer * @buf: The buffer to place the result into * @size: The size of the buffer, including the trailing null space + * @ops: An optional array of operations for special %p handling * @fmt: The format string to use * @args: Arguments for the format string * @@ -723,7 +748,8 @@ static char *pointer(const char *fmt, ch * Call this function if you are already dealing with a va_list. * You probably want snprintf() instead. */ -int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) +int evsnprintf(const struct printf_operations *ops, char *buf, + size_t size, const char *fmt, va_list args) { unsigned long long num; int base; @@ -849,7 +875,8 @@ int vsnprintf(char *buf, size_t size, co case ''p'': str = pointer(fmt+1, str, end, va_arg(args, void *), - field_width, precision, flags); + field_width, precision, flags, + ops); /* Skip all alphanumeric pointer suffixes */ while (isalnum(fmt[1])) fmt++; @@ -937,6 +964,12 @@ int vsnprintf(char *buf, size_t size, co /* the trailing null byte doesn''t count towards the total */ return str-buf; } +EXPORT_SYMBOL(evsnprintf); + +int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) +{ + return evsnprintf(NULL, buf, size, fmt, args); +} EXPORT_SYMBOL(vsnprintf); /** @@ -955,13 +988,19 @@ EXPORT_SYMBOL(vsnprintf); * * See the vsnprintf() documentation for format string extensions over C99. */ -int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) +int evscnprintf(const struct printf_operations *ops, char *buf, + size_t size, const char *fmt, va_list args) { - int i; - - i=vsnprintf(buf,size,fmt,args); + int i = evsnprintf(ops, buf, size, fmt, args); return (i >= size) ? (size - 1) : i; } +EXPORT_SYMBOL(evscnprintf); + +int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) +{ + return evscnprintf(NULL, buf, size, fmt, args); +} + EXPORT_SYMBOL(vscnprintf); /** @@ -978,18 +1017,31 @@ EXPORT_SYMBOL(vscnprintf); * * See the vsnprintf() documentation for format string extensions over C99. */ -int snprintf(char * buf, size_t size, const char *fmt, ...) +int snprintf(char *buf, size_t size, const char *fmt, ...) { va_list args; int i; va_start(args, fmt); - i=vsnprintf(buf,size,fmt,args); + i = vsnprintf(buf, size, fmt, args); va_end(args); return i; } EXPORT_SYMBOL(snprintf); +int esnprintf(const struct printf_operations *ops, char *buf, + size_t size, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = evsnprintf(ops, buf, size, fmt, args); + va_end(args); + return i; +} +EXPORT_SYMBOL(esnprintf); + /** * scnprintf - Format a string and place it in a buffer * @buf: The buffer to place the result into @@ -1001,7 +1053,7 @@ EXPORT_SYMBOL(snprintf); * the trailing ''\0''. If @size is <= 0 the function returns 0. */ -int scnprintf(char * buf, size_t size, const char *fmt, ...) +int scnprintf(char *buf, size_t size, const char *fmt, ...) { va_list args; int i; @@ -1013,6 +1065,19 @@ int scnprintf(char * buf, size_t size, c } EXPORT_SYMBOL(scnprintf); +int escnprintf(const struct printf_operations *ops, char *buf, + size_t size, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = evsnprintf(ops, buf, size, fmt, args); + va_end(args); + return (i >= size) ? (size - 1) : i; +} +EXPORT_SYMBOL(escnprintf); + /** * vsprintf - Format a string and place it in a buffer * @buf: The buffer to place the result into @@ -1034,6 +1099,13 @@ int vsprintf(char *buf, const char *fmt, } EXPORT_SYMBOL(vsprintf); +int evsprintf(const struct printf_operations *ops, char *buf, + const char *fmt, va_list args) +{ + return evsnprintf(ops, buf, INT_MAX, fmt, args); +} +EXPORT_SYMBOL(evsprintf); + /** * sprintf - Format a string and place it in a buffer * @buf: The buffer to place the result into @@ -1052,12 +1124,25 @@ int sprintf(char * buf, const char *fmt, int i; va_start(args, fmt); - i=vsnprintf(buf, INT_MAX, fmt, args); + i = vsnprintf(buf, INT_MAX, fmt, args); va_end(args); return i; } EXPORT_SYMBOL(sprintf); +int esprintf(const struct printf_operations *ops, char *buf, + const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = evsnprintf(ops, buf, INT_MAX, fmt, args); + va_end(args); + return i; +} +EXPORT_SYMBOL(esprintf); + /** * vsscanf - Unformat a buffer into a list of arguments * @buf: input buffer -- Jeff Mahoney SUSE Labs -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html