(1/4) dm_report support in libdevmapper
Subsystems (2)
PATCH 1/1 (1/4) dm_report support in libdevmapper
Hi,
Attached patch adds dm_report API to libdevmapper. The code is based on LVM2 lib/report with a enhancement to option format (e.g. "name=a" to report objects whose "name" field is "a") and generalizations.
I would like to use this from dmsetup to make "dmsetup info -c" more flexible like LVM2 lvs/pvs/vgs commands.
Also, LVM2 can use this API instead of its own lib/report.
(Patches for dmsetup and LVM2 will follow.)
Comments are welcome.
Thanks,
Signature · 1 line
Jun'ichi Nomura, NEC Corporation of America
New dm_report API.
The code is based on LVM2 reporter function and act much like lvs/pvs/vgs commands.
Main APIs are:
- dm_report_init
Register definition of reported object types and fields
and set options.
Returns a handle for following calls.
- dm_report_object
Generate report for one object.
The result will be sorted and bufferred until dm_report_output is called if requested.
- dm_report_output
Output bufferred report.
- dm_report_free
Abandon the report handle.
There are some other functions for types and fields definition.
Details can be found in the patch.
And each field name passed by format parameter of dm_report_init can be followed by the following comparison operator and the value or string:
= : equal to the value or string
!= : not equal to the value or string
>= : greater than or equal to the value
<= : lesser than or equal to the value
< : lesser than the value
> : greater than the value
=~ : contains the string
!~ : not contain the string =~^ : contains the string as prefix
!~^ : not contain the string as prefix
If the field name is prefixed by "-" in "-o" option string, the field is used only to check the condition and not displayed.
lib/libdevmapper.h +66 -1
@@ -1,6 +1,7 @@/* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. -* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. +* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. +* Copyright (C) 2007 NEC Corporation * * This file is part of the device-mapper userspace tools. *
@@ -623,4 +624,68 @@ int dm_snprintf(char *buf, size_t bufsiz*/ char *dm_basename (const char *path); +/********************* +* report function +*********************/ + +struct dm_report_field ; +struct dm_report ; + +/* Definition of reported object */ +struct dm_report_object_type { +uint32_t id;/* must be a power of 2 */ +const char *desc;/* description of the object type */ +const char *prefix;/* default prefix of id string (if any) */ +void * (*get) (void *object);/* callback from report_object() */ +}; + +/* Definition of field */ +#define DM_REPORT_FIELD_ALIGN_LEFT 0x00000001 +#define DM_REPORT_FIELD_ALIGN_RIGHT 0x00000002 +#define DM_REPORT_FIELD_STRING 0x00000004 +#define DM_REPORT_FIELD_NUMBER 0x00000008 +struct dm_report_field_type { +uint32_t type;/* object type id */ +const char id[32 ];/* string used to specify the field */ +unsigned int offset;/* byte offset in the object */ +const char heading[32 ];/* string printed in header */ +int width;/* default width */ +uint32_t flags;/* string or number, alignment */ +int (*report_fn) (struct dm_report * rh,struct dm_pool * mem, +struct dm_report_field * field,const void *data); +}; + +/* +* Report API +*/ +struct dm_report *dm_report_init (const char *format,const char *keys, +uint32_t *report_types,const char *separator, +int aligned,int buffered,int headings, +const struct dm_report_field_type *fds, +int num_fds, +const struct dm_report_object_type *types, +int num_types, +void *private); +void dm_report_free (struct dm_report *rh); +int dm_report_object (struct dm_report *rh,void *object); +int dm_report_output (struct dm_report *rh); +void *dm_report_get_private (struct dm_report *rh); + +/* report functions for common types */ +int dm_report_field_string (struct dm_report *rh,struct dm_pool *mem, +struct dm_report_field *field,const void *data); +int dm_report_field_int32 (struct dm_report *rh,struct dm_pool *mem, +struct dm_report_field *field,const void *data); +int dm_report_field_uint32 (struct dm_report *rh,struct dm_pool *mem, +struct dm_report_field *field,const void *data); +int dm_report_field_int (struct dm_report *rh,struct dm_pool *mem, +struct dm_report_field *field,const void *data); +int dm_report_field_uint64 (struct dm_report *rh,struct dm_pool *mem, +struct dm_report_field *field,const void *data); + +/* helper functions for custom report functions */ +int dm_report_field_raw (struct dm_report *rh,struct dm_pool *mem, +struct dm_report_field *field,const void *data); +void dm_report_field_set_string (struct dm_report_field *field,const char *string); +void dm_report_field_set_sort_value (struct dm_report_field *field,const void *value);#endif /* LIB_DEVICE_MAPPER_H */
lib/libdm-report.c new file +1111 -0
1,111 lines not on this page · raw message
lib/Makefile.in +1 -0
@@ -24,6 +24,7 @@ SOURCES =\ libdm-file.c \ libdm-deptree.c \ libdm-string.c \ + libdm-report.c \ mm/dbg_malloc.c \ mm/pool.c \ $(interface)/libdm-iface.c
lib/.exported_symbols +13 -0
@@ -115,3 +115,16 @@ dm_split_lvm_name dm_split_words dm_snprintf dm_basename +dm_report_init +dm_report_object +dm_report_output +dm_report_free +dm_report_get_private +dm_report_field_string +dm_report_field_int32 +dm_report_field_uint32 +dm_report_field_int +dm_report_field_uint64 +dm_report_field_raw +dm_report_field_set_string +dm_report_field_set_sort_value
PATCH 1/1 (2/4) dmsetup info to use dm_report
Hi,
This patch makes "dmsetup info -c" to use dm_report in libdevmapper.
For example, to see what maps are overlaying on each map,
# dmsetup info -c -o name,parents_count,parent_maps -O name Name Parents Parent Maps B8-root 0 B9-root 0 d1 2 testvg-m1_mimage_0,testvg-lvol2 d2 2 testvg-m1_mimage_1,testvg-lvol2 d3 1 testvg-lvol0-real d4 2 testvg-lvol2,testvg-lvol0-real d5 1 testvg-lvol1-cow d6 1 testvg-lvol2 d7 1 testvg-m1_mlog testvg-lvol0 0 testvg-lvol0-real 2 testvg-lvol1,testvg-lvol0 testvg-lvol1 0 testvg-lvol1-cow 1 testvg-lvol1 testvg-lvol2 0 testvg-m1 0 testvg-m1_mimage_0 1 testvg-m1 testvg-m1_mimage_1 1 testvg-m1 testvg-m1_mlog 1 testvg-m1
Then, to see the top level map names,
# dmsetup info -c -o name,-parents_count=0 --noheadings B9-root testvg-m1 testvg-lvol2 testvg-lvol1 testvg-lvol0 B8-root
Output of "dmsetup info -c" is basically same as the former version except for a few spacing difference, which should be harmless.
- Field width is correctly aligned (e.g. in case of long map name)
- Trailing space is added to fill the width
(same behaviour as LVM2 lvs/pvs/vgs)
Thanks,
--
Jun'ichi Nomura, NEC Corporation of America
Extend "dmsetup info -c -o" using dm_report API.
New options "-O" and "--seprator" are also added.
Usage:
dmsetup info -c -o <field1>[,<field2>...] \
[-O <field>[,<field>...]
[--separator <string>]Combination of the following field name is allowed:
name
device
major
minor
uuid
status
open_count
target_count
event_nr
deps
deps_count
parents
parents_count
parent_maps
Examples:
If you have the following dm tree:
# dmsetup ls --tree -o inverted
(7:0)
|-d4 (254:6)
| |-testvg-lvol2 (254:17)
| `-testvg-lvol0-real (254:15)
| |-testvg-lvol1 (254:14)
| `-testvg-lvol0 (254:13)
|-d1 (254:3)
| |-testvg-m1_mimage_0 (254:10)
| | `-testvg-m1 (254:12)
| `-testvg-lvol2 (254:17)
|-d3 (254:5)
| `-testvg-lvol0-real (254:15)
| |-testvg-lvol1 (254:14)
| `-testvg-lvol0 (254:13)
|-d2 (254:4)
| |-testvg-m1_mimage_1 (254:11)
| | `-testvg-m1 (254:12)
| `-testvg-lvol2 (254:17)
|-d7 (254:9)
| `-testvg-m1_mlog (254:0)
| `-testvg-m1 (254:12)
|-d6 (254:8)
| `-testvg-lvol2 (254:17)
`-d5 (254:7)
`-testvg-lvol1-cow (254:16)
`-testvg-lvol1 (254:14)
(8:48)
`-asr_HOSTRAID1 (254:18)
|-asr_HOSTRAID15 (254:22)
|-asr_HOSTRAID13 (254:21)
|-asr_HOSTRAID12 (254:20)
`-asr_HOSTRAID11 (254:19)
(8:32)
`-asr_HOSTRAID1 (254:18)
|-asr_HOSTRAID15 (254:22)
|-asr_HOSTRAID13 (254:21)
|-asr_HOSTRAID12 (254:20)
`-asr_HOSTRAID11 (254:19)To obtain the sorted list of the maps which have no parent maps:
# dmsetup info -c -o 'name,-parents_count=0' --noheadings -O name
asr_HOSTRAID11
asr_HOSTRAID12
asr_HOSTRAID13
asr_HOSTRAID15
testvg-lvol0
testvg-lvol1
testvg-lvol2
testvg-m1 Output of "dmsetup info -c" is basically same as the former version except for a few spacing difference, which should be harmless.
- Field width is correctly aligned (e.g. in case of long map name)
- Trailing space is added to fill the width
(same behaviour as LVM2 lvs/pvs/vgs)
dmsetup/dmsetup.c +436 -13
@@ -1,7 +1,7 @@/* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. -* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. -* Copyright (C) 2005 NEC Corperation +* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. +* Copyright (C) 2005-2007 NEC Corperation * * This file is part of the device-mapper userspace tools. *
@@ -114,7 +114,9 @@ enum {NOOPENCOUNT_ARG ,NOTABLE_ARG ,OPTIONS_ARG , +SEPARATOR_ARG ,SHOWKEYS_ARG , +SORTKEYS_ARG ,TABLE_ARG ,TARGET_ARG , TREE_ARG,
@@ -129,11 +131,12 @@ static int _switches[NUM_SWITCHES];static int _values[NUM_SWITCHES ];static int _num_devices;static char *_uuid; -static char *_fields; +static char *_fields[NUM_SWITCHES ];static char *_table;static char *_target;static char *_command;static struct dm_tree *_dtree; +static struct dm_report *_rhandle;/* * Commands
@@ -322,6 +325,8 @@ static void _display_info_long(struct dmprintf ("\n" ); } +static int _report (int argc,char **argv,void *data); +static int _display_info (struct dm_task *dmt) {struct dm_info info;
@@ -1056,6 +1061,12 @@ static int _info(int argc, char **argv,struct dm_names *names = (struct dm_names *) data;char *name =NULL ; +/* +* Using reporter function +*/ +if (_switches[COLS_ARG ]) +return _report (argc, argv, data); +if (data) name = names->name;else {
@@ -1506,6 +1517,414 @@ static int _ls(int argc, char **argv, voreturn _process_all (argc, argv,0 , _display_name); } + +/* +* Report device information +*/ + +/* dm specific display functions */ + +static int _dm_name_disp (struct dm_report *rh,struct dm_pool *mem, +struct dm_report_field *field,const void *data) +{ +const char *name =dm_task_get_name ((struct dm_task *) data); + +return dm_report_field_string (rh, mem, field, &name); +} + +static int _dm_uuid_disp (struct dm_report *rh,struct dm_pool *mem, +struct dm_report_field *field, +const void *data) +{ +const char *uuid =dm_task_get_uuid ((struct dm_task *) data); + +if (!uuid || !*uuid) + uuid ="" ; + +return dm_report_field_string (rh, mem, field, &uuid); +} + +static int _dm_info_status_disp (struct dm_report *rh,struct dm_pool *mem, +struct dm_report_field *field,const void *data) +{ +char buf[5 ], *s = buf; +struct dm_info *info = (struct dm_info *) data; + + buf[0 ] = info->live_table ?'L' :'-' ; + buf[1 ] = info->inactive_table ?'I' :'-' ; + buf[2 ] = info->suspended ?'s' :'-' ; + buf[3 ] = info->read_only ?'r' :'w' ; + buf[4 ] =0 ; + +return dm_report_field_string (rh, mem, field, &s); +} + +#define MAJ_MIN_LEN 32 + +static int _dm_info_device_disp (struct dm_report *rh,struct dm_pool *mem, +struct dm_report_field *field,const void *data) +{ +char *repstr; +struct dm_info *info = (struct dm_info *) data; + +if (!(repstr =dm_pool_zalloc (mem,MAJ_MIN_LEN ))) { +log_error ("dm_pool_alloc failed" ); +return 0 ; + } + +if (dm_snprintf (repstr,MAJ_MIN_LEN ,"%d:%d" , + info->major, info->minor) <0 ) { +dm_pool_free (mem, repstr); +log_error ("dm_pool_alloc failed" ); +return 0 ; + } + +return dm_report_field_raw (rh, mem, field, repstr); +} + +static int _dm_tree_parent_maps_disp (struct dm_report *rh, +struct dm_pool *mem, +struct dm_report_field *field, +const void *data) +{ +struct dm_tree_node *node = (struct dm_tree_node *) data, *parent; +void *t =NULL ; +const char *name; +int first_node =1 ; +char *repstr; + +if (!dm_pool_begin_object (mem,256 )) { +log_error ("dm_pool_begin_object failed" ); +return 0 ; + } + +while ((parent =dm_tree_next_child (&t, node,1 ))) { + name =dm_tree_node_get_name (parent); +if (!name || !*name) +continue ; +if (!first_node && !dm_pool_grow_object (mem,"," ,1 )) { +log_error ("dm_pool_grow_object failed" ); + goto out_abandon; + } +if (!dm_pool_grow_object (mem, name,strlen (name))) { +log_error ("dm_pool_grow_object failed" ); + goto out_abandon; + } +if (first_node) + first_node =0 ; + } + +if (!dm_pool_grow_object (mem,"\0" ,1 )) { +log_error ("dm_pool_grow_object failed" ); + goto out_abandon; + } + + repstr =dm_pool_end_object (mem); +return dm_report_field_raw (rh, mem, field, repstr); + +return 1 ; + + out_abandon: +dm_pool_abandon_object (mem); +return 0 ; +} + +static int _dm_tree_parents_disp (struct dm_report *rh,struct dm_pool *mem, +struct dm_report_field *field, +const void *data) +{ +struct dm_tree_node *node = (struct dm_tree_node *) data, *parent; +void *t =NULL ; +const struct dm_info *info; +int first_node =1 ; +char buf[MAJ_MIN_LEN ], *repstr; + +if (!dm_pool_begin_object (mem,256 )) { +log_error ("dm_pool_begin_object failed" ); +return 0 ; + } + +while ((parent =dm_tree_next_child (&t, node,1 ))) { + info =dm_tree_node_get_info (parent); +if (!info->major && !info->minor) +continue ; +if (!first_node && !dm_pool_grow_object (mem,"," ,1 )) { +log_error ("dm_pool_grow_object failed" ); + goto out_abandon; + } +if (dm_snprintf (buf,MAJ_MIN_LEN ,"%d:%d" , + info->major, info->minor) <0 ) { +log_error ("dm_snprintf failed" ); + goto out_abandon; + } +if (!dm_pool_grow_object (mem, buf,strlen (buf))) { +log_error ("dm_pool_grow_object failed" ); + goto out_abandon; + } +if (first_node) + first_node =0 ; + } + +if (!dm_pool_grow_object (mem,"\0" ,1 )) { +log_error ("dm_pool_grow_object failed" ); + goto out_abandon; + } + + repstr =dm_pool_end_object (mem); +return dm_report_field_raw (rh, mem, field, repstr); + + out_abandon: +dm_pool_abandon_object (mem); +return 0 ; +} + +static int _dm_tree_parents_count_disp (struct dm_report *rh, +struct dm_pool *mem, +struct dm_report_field *field, +const void *data) +{ +struct dm_tree_node *node = (struct dm_tree_node *) data; +int num_parent =dm_tree_node_num_children (node,1 ); + +return dm_report_field_int (rh, mem, field, &num_parent); +} + +static int _dm_deps_disp (struct dm_report *rh,struct dm_pool *mem, +struct dm_report_field *field,const void *data) +{ +struct dm_deps *deps = (struct dm_deps *) data; +int i; +char buf[MAJ_MIN_LEN ], *repstr; + +if (!dm_pool_begin_object (mem,256 )) { +log_error ("dm_pool_begin_object failed" ); +return 0 ; + } + +for (i =0 ; i < deps->count; i++) { +if (dm_snprintf (buf,sizeof (buf) -1 ,"%d:%d" , + (int )MAJOR (deps->device[i]), + (int )MINOR (deps->device[i])) <0 ) { +log_error ("dm_snprintf failed" ); + goto out_abandon; + } +if (!dm_pool_grow_object (mem, buf,strlen (buf))) { +log_error ("dm_pool_grow_object failed" ); + goto out_abandon; + } +if (i +1 < deps->count && !dm_pool_grow_object (mem,"," ,1 )) { +log_error ("dm_pool_grow_object failed" ); + goto out_abandon; + } + } + +if (!dm_pool_grow_object (mem,"\0" ,1 )) { +log_error ("dm_pool_grow_object failed" ); + goto out_abandon; + } + + repstr =dm_pool_end_object (mem); +return dm_report_field_raw (rh, mem, field, repstr); + + out_abandon: +dm_pool_abandon_object (mem); +return 0 ; +} + +/* Report object types */ + +#define DESC1 "Device Mapper Device" +#define DESC2 "Dependency" +#define PREFIX "dm_" +enum {DR_TASK =1 ,DR_INFO =2 ,DR_DEPS =4 ,DR_TREE =8 }; + +struct dmsetup_report_obj { +struct dm_task *task; +struct dm_info *info; +struct dm_tree_node *tree; +}; + +static void *_task_get_obj (void *obj) +{ +return ((struct dmsetup_report_obj *)obj)->task; +} + +static void *_info_get_obj (void *obj) +{ +return ((struct dmsetup_report_obj *)obj)->info; +} + +static void *_tree_get_obj (void *obj) +{ +return ((struct dmsetup_report_obj *)obj)->tree; +} + +static void *_deps_get_obj (void *obj) +{ +struct dm_task *dmt; + +if (!(dmt =_task_get_obj ((struct dmsetup_report_obj *)obj))) +return NULL ; + +return dm_task_get_deps (dmt); +} + +static const struct dm_report_object_type _report_types[] = { + {DR_TASK ,DESC1 ,PREFIX , _task_get_obj }, + {DR_INFO ,DESC1 ,PREFIX , _info_get_obj }, + {DR_DEPS ,DESC2 ,PREFIX , _deps_get_obj }, + {DR_TREE ,DESC2 ,PREFIX , _tree_get_obj }, +}; + +/* Column definitions */ +static union { +struct dm_info _dm_info; +struct dm_deps _dm_deps; +} _dummy; + +#define OFFSET_OF (struct, field) ((unsigned int) ((void *)&_dummy._ ## struct.field - (void *)&_dummy._ ## struct)) +#define STR (DM_REPORT_FIELD_STRING | DM_REPORT_FIELD_ALIGN_LEFT) +#define NUM (DM_REPORT_FIELD_NUMBER | DM_REPORT_FIELD_ALIGN_RIGHT) +#define FIELD_O (type, strct, sorttype, head, field, width, func, id) {DR_ ## type, id, OFFSET_OF(strct, field), head, width, sorttype, &dm_report_field_ ## func}, +#define FIELD_F (type, sorttype, head, width, func, id) {DR_ ## type, id, 0, head, width, sorttype, &_ ## func ## _disp}, + +static const struct dm_report_field_type _report_fields[] = { +/* *INDENT-OFF* */ +FIELD_F(TASK, STR, "Name", 16, dm_name, "name") +FIELD_F(TASK, STR, "UUID", 32, dm_uuid, "uuid") +FIELD_F(INFO, STR, "Stat", 4, dm_info_status, "status") +FIELD_F(INFO, STR, "Device", 6, dm_info_device, "device") +FIELD_O(INFO, dm_info, NUM, "Maj", major, 3, int32, "major") +FIELD_O(INFO, dm_info, NUM, "Min", minor, 3, int32, "minor") +FIELD_O(INFO, dm_info, NUM, "Open", open_count, 4, int32, "open_count") +FIELD_O(INFO, dm_info, NUM, "Targ", target_count, 4, int32, "target_count") +FIELD_O(INFO, dm_info, NUM, "Event", event_nr, 6, uint32, "event_nr") +FIELD_O(DEPS, dm_deps, NUM, "Deps", count, 4, int32, "deps_count") +FIELD_F(DEPS, STR, "Depend on", 10, dm_deps, "deps") +FIELD_F(TREE, STR, "Parent Devices", 16, dm_tree_parents, "parents") +FIELD_F(TREE, STR, "Parent Maps", 12, dm_tree_parent_maps, "parent_maps") +FIELD_F (TREE ,NUM ,"Parents" ,7 , dm_tree_parents_count,"parents_count" ) +/* *INDENT-ON* */ +}; + +#undef STR +#undef NUM +#undef FIELD_O +#undef FIELD_F + +static const char *default_report_options ="name,major,minor,status,open_count,target_count,event_nr,uuid" ; +static unsigned int _num_report_fields =sizeof (_report_fields) /sizeof (_report_fields[0 ]); +static unsigned int _num_report_types =sizeof (_report_types) /sizeof (_report_types[0 ]); + +static int _do_report (int argc,char **argv,void *data) +{ +const char *name =NULL ; +struct dm_task *dmt; +struct dm_info info; +int r =0 ; +struct dmsetup_report_obj obj; + +if (data) { +if (argc ==0 ) + name =dm_task_get_name ((struct dm_task *)data); +else + name = ((struct dm_names *)data)->name; + }else { +if (argc ==1 ) +return _process_all (argc, argv,0 , _report); +if (argc ==2 ) + name = argv[1 ]; + } + +if (!(dmt =dm_task_create (DM_DEVICE_DEPS ))) +return 0 ; + +if (!_set_task_device (dmt, name,0 )) + goto out; + +if (_switches[NOOPENCOUNT_ARG ] && !dm_task_no_open_count (dmt)) + goto out; + +if (!dm_task_run (dmt)) + goto out; + +if (!dm_task_get_info (dmt, &info)) + goto out; + + obj.task = dmt; + obj.info = &info; + obj.tree =dm_tree_find_node (_dtree, info.major, info.minor); +dm_report_object (_rhandle, &obj); + + r =1 ; + + out: +dm_task_destroy (dmt); +return r; +} + +static int _report (int argc,char **argv,void *data) +{ +char *options = (char *) default_report_options; +const char *keys ="" ; +const char *separator =" " ; +int aligned =1 , buffered =1 ; +int headings = !_switches[NOHEADINGS_ARG ]; +uint32_t report_type =0 ; + +if (_rhandle) +return _do_report (argc, argv, data); + +if (!(_dtree =dm_tree_create ())) +return 0 ; +if (!_process_all (argc, argv,0 , _add_dep)) +return 0 ; + +if (_switches[OPTIONS_ARG ] && _fields[OPTIONS_ARG ]) { +if (*_fields[OPTIONS_ARG ] =='+' ) { +int len =strlen (default_report_options) + +strlen (_fields[OPTIONS_ARG ]); +if (!(options =dm_malloc (len))) { +err ("Failed to malloc option string." ); +return 0 ; + } +if (dm_snprintf (options, len,"%s,%s" , + default_report_options, + &_fields[OPTIONS_ARG ][1 ]) <0 ) { +err ("snprintf failed" ); +return 0 ; + } + }else + options = _fields[OPTIONS_ARG ]; + } +if (_switches[SORTKEYS_ARG ] && _fields[SORTKEYS_ARG ]) + keys = _fields[SORTKEYS_ARG ]; +if (_switches[SEPARATOR_ARG ] && _fields[SEPARATOR_ARG ]) { + separator = _fields[SEPARATOR_ARG ]; + aligned =0 ; + } + +if (!(_rhandle =dm_report_init (options, keys, &report_type, + separator, aligned, buffered, headings, + _report_fields, _num_report_fields, + _report_types, _num_report_types, +NULL ))) +return 0 ; + +_do_report (argc, argv, data); + +dm_report_output (_rhandle); +dm_report_free (_rhandle); + _rhandle =NULL ; + +if (_dtree) { +dm_tree_free (_dtree); + _dtree =NULL ; + } + +return 1 ; +} +/* * dispatch table */
@@ -1884,7 +2303,9 @@ static int _process_switches(int *argc, {"noopencount", 0, &ind, NOOPENCOUNT_ARG}, {"notable", 0, &ind, NOTABLE_ARG}, {"options", 1, &ind, OPTIONS_ARG}, + {"separator", 1, &ind, SEPARATOR_ARG}, {"showkeys", 0, &ind, SHOWKEYS_ARG}, + {"sortkeys", 1, &ind, SORTKEYS_ARG}, {"table", 1, &ind, TABLE_ARG}, {"target", 1, &ind, TARGET_ARG}, {"tree", 0, &ind, TREE_ARG},
@@ -1914,7 +2335,7 @@ static int _process_switches(int *argc, _switches[OPTIONS_ARG ]++; _switches[MAJOR_ARG ]++; _switches[MINOR_ARG ]++; - _fields = (char *)"name" ; + _fields[OPTIONS_ARG ] = (char *)"name" ;if (*argc ==3 ) { _values[MAJOR_ARG ] =atoi ((*argv)[1 ]);
@@ -1946,7 +2367,7 @@ static int _process_switches(int *argc, optarg =0 ; optind =OPTIND_INIT ; -while ((ind =-1 , c =GETOPTLONG_FN (*argc, *argv,"cCfGj:m:Mno:ru:Uv" , +while ((ind =-1 , c =GETOPTLONG_FN (*argc, *argv,"cCfGj:m:Mno:O:ru:Uv" , long_options,NULL )) !=-1 ) {if (c ==':' || c =='?' )return 0 ;
@@ -1968,7 +2389,15 @@ static int _process_switches(int *argc, _switches[NOTABLE_ARG ]++;if (c =='o' || ind ==OPTIONS_ARG ) { _switches[OPTIONS_ARG ]++; - _fields = optarg; + _fields[OPTIONS_ARG ] = optarg; + } +if (ind ==SEPARATOR_ARG ) { + _switches[SEPARATOR_ARG ]++; + _fields[SEPARATOR_ARG ] = optarg; + } +if (c =='O' || ind ==SORTKEYS_ARG ) { + _switches[SORTKEYS_ARG ]++; + _fields[SORTKEYS_ARG ] = optarg; }if (c =='v' || ind ==VERBOSE_ARG ) _switches[VERBOSE_ARG ]++;
@@ -2027,13 +2456,7 @@ static int _process_switches(int *argc,return 0 ; } -if (_switches[COLS_ARG ] && _switches[OPTIONS_ARG ] && -strcmp (_fields,"name" )) { -fprintf (stderr,"Only -o name is supported so far.\n" ); -return 0 ; - } - -if (_switches[TREE_ARG ] && !_process_tree_options (_fields)) +if (_switches[TREE_ARG ] && !_process_tree_options (_fields[OPTIONS_ARG ]))return 0 ;if (_switches[TABLE_ARG ] && _switches[NOTABLE_ARG ]) {
PATCH 1/1 (3/4) Remove old codes for "info -c" from dmsetup
In reply to Jun'ichi NomuraHi,
This patch removes _display_info_cols*() functions used for "dmsetup info -c" implementation.
These can be replaced by the new code using dm_report.
Thanks,
--
Jun'ichi Nomura, NEC Corporation of America
Replace old _display_info_cols{_noheadings} by _report()
Slight incompatibility is introduced:
Output of verbose + column is changed.
e.g. dmsetup table -v -c
# dmsetup.old table -c -v
Name Maj Min Stat Open Targ Event UUID
d4 254 6 L--w 0 1 0
0 409600 linear 7:0 1638400 d3 254 5 L--w 0 1 0
0 409600 linear 7:0 1228800
...
# dmsetup.new table -c -v
Name Maj Min Stat Open Targ Event UUID
d4 254 6 L--w 0 1 0
0 409600 linear 7:0 1638400
Name Maj Min Stat Open Targ Event UUID
d3 254 5 L--w 0 1 0
0 409600 linear 7:0 1228800
...
Field head used to be displayed only once but now it's displayed for every tables.
dmsetup/dmsetup.c +1 -65
@@ -225,68 +225,6 @@ static int _parse_file(struct dm_task *dreturn r; } -static void _display_info_cols_noheadings (struct dm_task *dmt, -struct dm_info *info) -{ -const char *uuid; - -if (!info->exists) -return ; - - uuid =dm_task_get_uuid (dmt); - -if (_switches[OPTIONS_ARG ]) -printf ("%s\n" ,dm_task_get_name (dmt)); -else -printf ("%s:%d:%d:%s%s%s%s:%d:%d:%" PRIu32":%s\n" , -dm_task_get_name (dmt), - info->major, info->minor, - info->live_table ?"L" :"-" , - info->inactive_table ?"I" :"-" , - info->suspended ?"s" :"-" , - info->read_only ?"r" :"w" , - info->open_count, info->target_count, info->event_nr, - uuid && *uuid ? uuid :"" ); -} - -static void _display_info_cols (struct dm_task *dmt,struct dm_info *info) -{ -static int _headings =0 ; -const char *uuid; - -if (!info->exists) { -printf ("Device does not exist.\n" ); -return ; - } - -if (!_headings) { -if (_switches[OPTIONS_ARG ]) -printf ("Name\n" ); -else -printf ("Name Maj Min Stat Open Targ " -"Event UUID\n" ); - _headings =1 ; - } - -if (_switches[OPTIONS_ARG ]) -printf ("%s\n" ,dm_task_get_name (dmt)); -else { -printf ("%-16s %3d %3d %s%s%s%s %4d %4d %6" PRIu32" " , -dm_task_get_name (dmt), - info->major, info->minor, - info->live_table ?"L" :"-" , - info->inactive_table ?"I" :"-" , - info->suspended ?"s" :"-" , - info->read_only ?"r" :"w" , - info->open_count, info->target_count, info->event_nr); - -if ((uuid =dm_task_get_uuid (dmt)) && *uuid) -printf ("%s" , uuid); - -printf ("\n" ); - } -} -static void _display_info_long (struct dm_task *dmt,struct dm_info *info) {const char *uuid;
@@ -336,10 +274,8 @@ static int _display_info(struct dm_taskif (!_switches[COLS_ARG ])_display_info_long (dmt, &info); -else if (_switches[NOHEADINGS_ARG ]) -_display_info_cols_noheadings (dmt, &info);else -_display_info_cols (dmt, &info); +_report (0 ,NULL , dmt);return info.exists ?1 :0 ; }
PATCH 1/1 (4/4) LVM2 to use dm_report
In reply to Jun'ichi NomuraHi,
This patch makes LVM2 to use dm_report in libdevmapper instead of its lib/report functions.
Tested following commands where LVs of linear, striped, mirrored and snapshot exist and confirmed the output is same with the original LVM2 2.02.17.
lvs
pvs
vgs
lvs -a
pvs -a
lvs -a -o +devices
lvs -o name,name,lv_name,vg_name
lvs -a -o name,name,lv_name,vg_name
lvs -a -o name,lv_name,vg_name -O name
lvs -a -o name,lv_name,vg_name -O -name
lvs -a -o name,lv_name,vg_name -O size
lvs -a -o name,lv_name,vg_name -O lv_size
lvs -a -o name,lv_name,vg_name -O -size
pvs -o +pe_alloc_count,used,dev_size
pvs -a -o +pe_alloc_count,used,dev_size
Thanks,
--
Jun'ichi Nomura, NEC Corporation of America
Replaces lib/report by dm_report API in libdevmapper.
lib/Makefile.in +0 -1
@@ -84,7 +84,6 @@ SOURCES =\ regex/matcher.c \ regex/parse_rx.c \ regex/ttree.c \ - report/report.c \ striped/striped.c \ uuid/uuid.c \ zero/zero.c
lib/report/columns.h deleted +0 -84
84 lines not on this page · raw message
lib/report/report.c deleted +0 -1572
1,572 lines not on this page · raw message
lib/report/report.h deleted +0 -38
@@ -1,38 +0,0 @@ -/* -* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. -* Copyright (C) 2004 Red Hat, Inc. All rights reserved. -* -* This file is part of LVM2. -* -* This copyrighted material is made available to anyone wishing to use, -* modify, copy, or redistribute it subject to the terms and conditions -* of the GNU General Public License v.2. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software Foundation, -* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef _LVM_REPORT_H -#define _LVM_REPORT_H - -#include "metadata.h" - -typedef enum {LVS =1 ,PVS =2 ,VGS =4 ,SEGS =8 ,PVSEGS =16 }report_type_t ; - -struct field ; -struct report_handle ; - -typedef int (*field_report_fn ) (struct report_handle * dh,struct field * field, -const void *data); - -void *report_init (struct cmd_context *cmd,const char *format,const char *keys, -report_type_t *report_type,const char *separator, -int aligned,int buffered,int headings); -void report_free (void *handle); -int report_object (void *handle,struct volume_group *vg, -struct logical_volume *lv,struct physical_volume *pv, -struct lv_segment *seg,struct pv_segment *pvseg); -int report_output (void *handle); - -#endif
tools/columns.h new file +85 -0
85 lines not on this page · raw message
tools/reporter.c +905 -10
986 lines not on this page · raw message