libdevmapper: (0/6) Filtering feature in dm_report
Subsystems (2)
PATCH 1/1 libdevmapper: (0/6) Filtering feature in dm_report
Hi,
This series of patches enables dmsetup to control which types of devices are listed.
For example, "dmsetup info -c -o name --filter 'parents_count == 0'" will display top-level dm devices and
"dmsetup info -c --filter 'uuid !~ /^LVM/'" will display dm devices which are not LVM2 volumes.
As the feature is implemented in libdevmapper, LVM2 is easily made to use it, too. The patch will be posted to lvm-devel.
Thanks,
Signature · 1 line
Jun'ichi Nomura, NEC Corporation of America
PATCH 1/1 libdevmapper: (1/6) Tidy up _field_match() and _key_match()
Hi,
This patch cleans up _field_match() and _key_match() by separating common operations out.
No effect on functionality.
Thanks,
Signature · 1 line
Jun'ichi Nomura, NEC Corporation of America
Tidy up _field_match() and _key_match()
* Add _add_field() function for flag setting, alloc, copy, and list_add of struct field_properties
* Add _is_same_field() for lengthy test to check field name abbreviation
--- lib/libdm-report.c | 101 +++++++++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 45 deletions(-)
lib/libdm-report.c +56 -45
@@ -296,35 +296,62 @@ static int _copy_field(struct dm_reportreturn 1 ; } -static int _field_match (struct dm_report *rh,const char *field,size_t flen) +static struct field_properties *_add_field (struct dm_report *rh, +uint32_t field_num,uint32_t flags) { -uint32_t f, l;struct field_properties *fp; + rh->report_types |= rh->fields[field_num].type; +if (!(fp =dm_pool_zalloc (rh->mem,sizeof (struct field_properties )))) { +log_error ("dm_report: " +"struct field_properties allocation failed" ); +return NULL ; + } +if (!_copy_field (rh, fp, field_num)) { +dm_pool_free (rh->mem, fp); +return NULL ; + } + +/* Add additional flags */ + fp->flags |= flags; + +list_add (&rh->field_props, &fp->list); +return fp; +} + +/* +* compare name1 and name2 (or prefix+name2) +* name2 is not \0 terminated. len is the length of name2. +*/ +static int _is_same_field (const char *name1,const char *name2, +size_t len,const char *prefix) +{ +size_t l; + +/* name1 == name2 */ +if (!strncasecmp (name1, name2, len) &&strlen (name1) == len) +return 1 ; + +/* name1 == name2 */ + l =strlen (prefix); +if (!strncasecmp (prefix, name1, l) && + !strncasecmp (name1 + l, name2, len) &&strlen (name1) == l + len) +return 1 ; + +return 0 ; +} + +static int _field_match (struct dm_report *rh,const char *field,size_t flen) +{ +uint32_t f; +if (!flen)return 0 ; -for (f =0 ; rh->fields[f].report_fn; f++) { -if ((!strncasecmp (rh->fields[f].id, field, flen) && -strlen (rh->fields[f].id) == flen) || - (l =strlen (rh->field_prefix), - !strncasecmp (rh->field_prefix, rh->fields[f].id, l) && - !strncasecmp (rh->fields[f].id + l, field, flen) && -strlen (rh->fields[f].id) == l + flen)) { - rh->report_types |= rh->fields[f].type; -if (!(fp =dm_pool_zalloc (rh->mem,sizeof (*fp)))) { -log_error ("dm_report: " -"struct field_properties allocation " -"failed" ); -return 0 ; - } -if (!_copy_field (rh, fp, f)) -return 0 ; - -list_add (&rh->field_props, &fp->list); -return 1 ; - } - } +for (f =0 ; rh->fields[f].report_fn; f++) +if (_is_same_field (rh->fields[f].id, + field, flen, rh->field_prefix)) +return (_add_field (rh, f,0 ) !=NULL );return 0 ; }
@@ -342,19 +369,9 @@ static int _add_sort_key(struct dm_repor }if (!found) { - rh->report_types |= rh->fields[field_num].type; -if (!(found =dm_pool_zalloc (rh->mem,sizeof (*found)))) { -log_error ("dm_report: " -"struct field_properties allocation failed" ); -return 0 ; - } -if (!_copy_field (rh, found, field_num)) -return 0 ; -/* Add as a non-display field */ - found->flags |=FLD_HIDDEN ; - -list_add (&rh->field_props, &found->list); +if (!(found =_add_field (rh, field_num,FLD_HIDDEN ))) +return 0 ; }if (found->flags &FLD_SORT_KEY ) {
@@ -372,7 +389,7 @@ static int _add_sort_key(struct dm_reporstatic int _key_match (struct dm_report *rh,const char *key,size_t len) { -uint32_t f, l; +uint32_t f;uint32_t flags;if (!len)
@@ -394,16 +411,10 @@ static int _key_match(struct dm_report *return 0 ; } -for (f =0 ; rh->fields[f].report_fn; f++) { -if ((!strncasecmp (rh->fields[f].id, key, len) && -strlen (rh->fields[f].id) == len) || - (l =strlen (rh->field_prefix), - !strncasecmp (rh->field_prefix, rh->fields[f].id, l) && - !strncasecmp (rh->fields[f].id + l, key, len) && -strlen (rh->fields[f].id) == l + len)) { +for (f =0 ; rh->fields[f].report_fn; f++) +if (_is_same_field (rh->fields[f].id, + key, len, rh->field_prefix))return _add_sort_key (rh, f, flags); - } - }return 0 ; }
PATCH 1/1 libdevmapper: (2/6) Fix trailing separator
In reply to Jun'ichi NomuraHi,
This patch fixes dm_report_output() so that it can correctly check the end of the row.
It uses list_end() but trailing fields may have HIDDEN flag and not be printed.
For example,
# dmsetup info -c -o name -O minor VG0-lv0 Name VG0-lv0 # dmsetup info -c -o name -O minor --noheadings VG0-lv0 VG0-lv0: # dmsetup info -c -o name --noheadings VG0-lv0 VG0-lv0
The patch fixes it by inserting hidden fields at the head of the list.
Thanks,
Signature · 1 line
Jun'ichi Nomura, NEC Corporation of America
Later, dm_report_output() loops through rh->field_props list and checks the end of the list by list_end() whether to display the separator or not.
The check doesn't work if hidden field is on the tail.
For example, try 'dmsetup info -c -o name -O minor' and compare the results with and without '--noheadings'.
--- lib/libdm-report.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
lib/libdm-report.c +6 -1
@@ -315,7 +315,12 @@ static struct field_properties * _add_fi/* Add additional flags */ fp->flags |= flags; -list_add (&rh->field_props, &fp->list); +/* Hidden field must come first, otherwise list_end() doesn't work +as expected */ +if (fp->flags &FLD_HIDDEN ) +list_add_h (&rh->field_props, &fp->list); +else +list_add (&rh->field_props, &fp->list);return fp; }
PATCH 1/1 libdevmapper: (3/6) Move lib/regex from LVM2
In reply to Jun'ichi NomuraHi,
This patch just moves lib/regex from LVM2 as a preparation for the filtering feature of dm_report.
Now, the following functions are exported:
- dm_regex_create()
- dm_regex_match()
Corresponding patch to LVM2 will be posted to lvm-devel.
Thanks,
Signature · 1 line
Jun'ichi Nomura, NEC Corporation of America
Moved lib/regex from LVM2
Exported functions and a structure are renamed:
- matcher_create() -> dm_regex_create()
- matcher_run() -> dm_regex_match()
- struct matcher -> struct dm_regex
--- lib/.exported_symbols | 2 lib/Makefile.in | 3 lib/libdevmapper.h | 7 lib/regex/matcher.c | 366 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/regex/parse_rx.c | 360 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/regex/parse_rx.h | 52 +++++++ lib/regex/ttree.c | 117 +++++++++++++++ lib/regex/ttree.h | 26 +++ 8 files changed, 933 insertions(+)
lib/.exported_symbols +2 -0
@@ -127,3 +127,5 @@ dm_report_field_int32 dm_report_field_uint32 dm_report_field_uint64 dm_report_field_set_value +dm_regex_create +dm_regex_match
lib/libdevmapper.h +7 -0
@@ -711,4 +711,11 @@ int dm_report_field_uint64(struct dm_repvoid dm_report_field_set_value (struct dm_report_field *field,const void *value,const void *sortvalue); +/* +* dm_regex +*/ +struct dm_regex ; +struct dm_regex *dm_regex_create (struct dm_pool *mem,const char **patterns, +unsigned num); +int dm_regex_match (struct dm_regex *regex,const char *s);#endif /* LIB_DEVICE_MAPPER_H */
lib/regex/matcher.c new file +366 -0
366 lines not on this page · raw message
lib/regex/parse_rx.c new file +360 -0
360 lines not on this page · raw message
lib/regex/parse_rx.h new file +52 -0
52 lines not on this page · raw message
lib/regex/ttree.c new file +117 -0
117 lines not on this page · raw message
lib/regex/ttree.h new file +26 -0
@@ -0,0 +1,26 @@ +/* +* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. +* Copyright (C) 2004 Red Hat, Inc. All rights reserved. +* +* This file is part of the device-mapper userspace tools. +* +* 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_TTREE_H +#define _LVM_TTREE_H + +struct ttree ; + +struct ttree *ttree_create (struct dm_pool *mem,unsigned int klen); + +void *ttree_lookup (struct ttree *tt,unsigned *key); +int ttree_insert (struct ttree *tt,unsigned *key,void *data); + +#endif
lib/Makefile.in +3 -0
@@ -25,6 +25,9 @@ SOURCES =\ libdm-deptree.c \ libdm-string.c \ libdm-report.c \ + regex/matcher.c \ + regex/parse_rx.c \ + regex/ttree.c \ mm/dbg_malloc.c \ mm/pool.c \ $(interface)/libdm-iface.c
PATCH 1/1 LVM2: (1/2) Use dm_regex
Hi,
This patch removes lib/regex from LVM2 and uses dm_regex, instead.
Corresponding patch for libdevmapper is this:
[PATCH] libdevmapper: (3/6) Move lib/regex from LVM2
https://www.redhat.com/archives/dm-devel/2007-April/msg00028.html
No change in functionality.
Thanks,
Signature · 8 lines
Jun'ichi Nomura, NEC Corporation of America -------------- next part -------------- A non-text attachment was scrubbed... Name: lvm2-remove-use-dm_regex.patch Type: text/x-patch Size: 23254 bytes Desc: not available URL: <http://listman.redhat.com/archives/lvm-devel/attachments/20070418/dd0e3a38/attachment.bin>
PATCH 1/1 libdevmapper: (4/6) Add filtering feature to dm_report
In reply to Jun'ichi NomuraHi,
This patch adds a filtering feature to dm_report.
- Add dm_report_set_filter() API.
By calling this, dm_report_object() omits rows which doesn't match the condition specified by the filter.
- Fitlers can be composed with the following components:
* Simple comparison of field value
'==', '!=', '>', '>=', '<', '<='
Strings should be quoted by either ' or ".
Only decimal, non-negative integers are currently allowed.
* Regular expression
'=~', '!~'
Regular expression can be quoted by '/', '|', '#', or any other characters.
* Logical combinations of the expressions
'and', 'or', '!', '(', ')'
Thanks,
Signature · 1 line
Jun'ichi Nomura, NEC Corporation of America
Add filtering feature to dm_report.
Filter is set by dm_report_set_filters()
--- lib/.exported_symbols | 1 lib/libdevmapper.h | 4 lib/libdm-report.c | 783 +++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 781 insertions(+), 7 deletions(-)
lib/.exported_symbols +1 -0
@@ -127,5 +127,6 @@ dm_report_field_int32 dm_report_field_uint32 dm_report_field_uint64 dm_report_field_set_value +dm_report_set_filter dm_regex_create dm_regex_match
lib/libdevmapper.h +4 -0
@@ -688,6 +688,10 @@ int dm_report_object(struct dm_report *rint dm_report_output (struct dm_report *rh);void dm_report_free (struct dm_report *rh); +/* Set filter */ +int dm_report_set_filter (struct dm_report *rh, +const char *filter,uint32_t flags); +/* * Report functions are provided for simple data types. * They take care of allocating copies of the data.
lib/libdm-report.c +776 -7
864 lines not on this page · raw message
PATCH 1/1 LVM2: (2/2) Use dm_report filter
Hi,
This patch adds '--filter' option to reporting commands: lvs, vgs and pvs.
The patch depends on the following patches:
[PATCH] libdevmapper: (4/6) Add filtering feature to dm_report
https://www.redhat.com/archives/dm-devel/2007-April/msg00029.html
[PATCH] libdevmapper: (7/6) Add dm_report_get_report_types()
https://www.redhat.com/archives/dm-devel/2007-April/msg00035.html
Examples:
Find PVs used for VG vg0
# pvs --filter 'vg_name == "vg0"'
Find PVs not used by any LVs
# pvs --filter 'used == 0'
Find PVs satisfying both of the aboves
# pvs --filter 'vg_name == "vg0" && used == 0'
Find PVs not satisfying the above
# pvs --filter '! (vg_name == "vg0" && used == 0)'
Find VGs with more than 2 PVs and with more than 400 extents
# vgs --filter 'pv_count > 2 && free_count > 400'
Find active snapshot LVs
# lvs --filter 'attr =~ /^s...a/'
Find LVs using /dev/sdc
# lvs --filter 'devices =~ |/dev/sdc|'
..
Possible future enhancements:
- Cope with units.
I.e. lvs --filter 'size > 4G' to find LVs larger than 4GB Currently, the filter can handle only the raw value of the field.
Thanks,
Signature · 8 lines
Jun'ichi Nomura, NEC Corporation of America -------------- next part -------------- A non-text attachment was scrubbed... Name: lvm2-add-filter.patch Type: text/x-patch Size: 7144 bytes Desc: not available URL: <http://listman.redhat.com/archives/lvm-devel/attachments/20070418/97908cf7/attachment.bin>
PATCH 1/1 libdevmapper: (5/6) Add '--filter' option to dmsetup
In reply to Jun'ichi NomuraHi,
This patch adds '--filter' option to dmsetup, so that it can use the filtering feature of dm_report.
Thanks,
Signature · 1 line
Jun'ichi Nomura, NEC Corporation of America
Add --filter (-F) option to dmsetup for filtering report output.
--- dmsetup/dmsetup.c | 15 ++++++++++++++- man/dmsetup.8 | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-)
dmsetup/dmsetup.c +14 -1
@@ -104,6 +104,7 @@ enum {COLS_ARG ,EXEC_ARG ,FORCE_ARG , +FILTER_ARG ,GID_ARG ,MAJOR_ARG , MINOR_ARG,
@@ -1650,6 +1651,13 @@ static int _report_init(struct command * options, separator, flags, keys, NULL))) goto out; +if (_string_args[FILTER_ARG ] && + !dm_report_set_filter (_report, _string_args[FILTER_ARG ],0 )) { +dm_report_free (_report); + _report =NULL ; + goto out; + } + r =1 ; out:
@@ -2059,6 +2067,7 @@ static int _process_switches(int *argc, {"columns", 0, &ind, COLS_ARG}, {"exec", 1, &ind, EXEC_ARG}, {"force", 0, &ind, FORCE_ARG}, + {"filter", 1, &ind, FILTER_ARG}, {"gid", 1, &ind, GID_ARG}, {"major", 1, &ind, MAJOR_ARG}, {"minor", 1, &ind, MINOR_ARG},
@@ -2133,7 +2142,7 @@ static int _process_switches(int *argc, optarg =0 ; optind =OPTIND_INIT ; -while ((ind =-1 , c =GETOPTLONG_FN (*argc, *argv,"cCfGj:m:Mno:O:ru:Uv" , +while ((ind =-1 , c =GETOPTLONG_FN (*argc, *argv,"cCfF:Gj:m:Mno:O:ru:Uv" , long_options,NULL )) !=-1 ) {if (c ==':' || c =='?' )return 0 ;
@@ -2141,6 +2150,10 @@ static int _process_switches(int *argc, _switches[COLS_ARG ]++;if (c =='f' || ind ==FORCE_ARG ) _switches[FORCE_ARG ]++; +if (c =='F' || ind ==FILTER_ARG ) { + _switches[FILTER_ARG ]++; + _string_args[FILTER_ARG ] = optarg; + }if (c =='r' || ind ==READ_ONLY ) _switches[READ_ONLY ]++;if (c =='j' || ind ==MAJOR_ARG ) {
man/dmsetup.8 +1 -1
@@ -44,7 +44,7 @@ dmsetup \- low level logical volume mana .br .B dmsetup info -c|-C|--columns .I [--noheadings] [--separator separator] [-o fields] [-O|--sort sort_fields] -.I [device_name] +.I [--filter expression] [device_name] .br .B dmsetup deps .I [device_name]
PATCH 1/1 libdevmapper: (6/6) Add deps and treenode fields for dmsetup info -c
In reply to Jun'ichi NomuraHi,
This patch adds optional fields to 'dmsetup info -c'.
You can specify the following fields with '-o', '-O' and filtering option.
- deps
- deps_count
- parents
- parents_count
For example, you can find the top-level dm devices by:
# dmsetup info -c -o name --filter 'parents_count == 0'
Thanks,
Signature · 1 line
Jun'ichi Nomura, NEC Corporation of America
Add fields of deps and treenode to dmsetup
--- dmsetup/dmsetup.c | 283 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 276 insertions(+), 7 deletions(-)
dmsetup/dmsetup.c +276 -7
@@ -241,11 +241,14 @@ static int _parse_file(struct dm_task *dstruct dmsetup_report_obj {struct dm_task *task;struct dm_info *info; +struct dm_task *deps; +struct dm_tree_node *tree; };static int _display_info_cols (struct dm_task *dmt,struct dm_info *info) {struct dmsetup_report_obj obj; +int r =0 ;if (!info->exists) {fprintf (stderr,"Device does not exist.\n" );
@@ -254,11 +257,18 @@ static int _display_info_cols(struct dm_ obj.task = dmt; obj.info = info; + obj.deps =NULL ;/* task is created later on demand */ + obj.tree =NULL ;/* deptree is created later on demand */ if (!dm_report_object (_report, &obj)) -return 0 ; + goto out; -return 1 ; + r =1 ; + + out: +if (obj.deps) +dm_task_destroy (obj.deps); +return r; }static void _display_info_long (struct dm_task *dmt,struct dm_info *info)
@@ -1457,17 +1467,26 @@ static int _add_dep(int argc __attribute/* * Create and walk dependency tree */ -static int _tree (int argc,char **argv,void *data __attribute((unused))) +static int _build_whole_deptree (void ) { +if (_dtree) +return 1 ; +if (!(_dtree =dm_tree_create ()))return 0 ; -if (!_process_all (argc, argv,0 , _add_dep)) +if (!_process_all (0 ,NULL ,0 , _add_dep))return 0 ; -_tree_walk_children (dm_tree_find_node (_dtree,0 ,0 ),0 ); +return 1 ; +} + +static int _tree (int argc,char **argv,void *data __attribute((unused))) +{ +if (!_build_whole_deptree ()) +return 0 ; -dm_tree_free (_dtree); +_tree_walk_children (dm_tree_find_node (_dtree,0 ,0 ),0 );return 1 ; }
@@ -1539,8 +1558,193 @@ static int _dm_info_status_disp(struct dreturn dm_report_field_string (rh, 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, +void *private) +{ +char buf[MAJ_MIN_LEN ], *repstr; +struct dm_info *info = (struct dm_info *) data; + +if (!dm_pool_begin_object (mem,8 )) { +log_error ("dm_pool_begin_object failed" ); +return 0 ; + } + +if (dm_snprintf (buf,sizeof (buf),"%d:%d" , + info->major, info->minor) <0 ) { +log_error ("dm_pool_alloc failed" ); + goto out_abandon; + } + +if (!dm_pool_grow_object (mem, buf,strlen (buf))) { +log_error ("dm_pool_grow_object failed" ); + goto out_abandon; + } + + repstr =dm_pool_end_object (mem); +dm_report_field_set_value (field, repstr, repstr); +return 1 ; + + out_abandon: +dm_pool_abandon_object (mem); +return 0 ; +} + +static int _dm_tree_parent_maps_disp (struct dm_report *rh, +struct dm_pool *mem, +struct dm_report_field *field, +const void *data,void *private) +{ +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,16 )) { +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); +dm_report_field_set_value (field, repstr, 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,void *private) +{ +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,16 )) { +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,sizeof (buf),"%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); +dm_report_field_set_value (field, repstr, repstr); +return 1 ; + + 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,void *private) +{ +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, field, &num_parent); +} + +static int _dm_deps_disp (struct dm_report *rh,struct dm_pool *mem, +struct dm_report_field *field,const void *data, +void *private) +{ +struct dm_deps *deps = (struct dm_deps *) data; +int i; +char buf[MAJ_MIN_LEN ], *repstr; + +if (!dm_pool_begin_object (mem,16 )) { +log_error ("dm_pool_begin_object failed" ); +return 0 ; + } + +for (i =0 ; i < deps->count; i++) { +if (dm_snprintf (buf,sizeof (buf),"%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); +dm_report_field_set_value (field, repstr, repstr); +return 1 ; + + out_abandon: +dm_pool_abandon_object (mem); +return 0 ; +} +/* Report types */ -enum {DR_TASK =1 ,DR_INFO =2 }; +enum {DR_TASK =1 ,DR_INFO =2 ,DR_DEPS =4 ,DR_TREE =8 };static void *_task_get_obj (void *obj) {
@@ -1552,9 +1756,65 @@ static void *_info_get_obj(void *obj)return ((struct dmsetup_report_obj *)obj)->info; } +static void *_tree_get_obj (void *obj) +{ +struct dmsetup_report_obj *o = (struct dmsetup_report_obj *) obj; +struct dm_info *info; + +if (o->tree) +return o->tree; + +if (!_build_whole_deptree ()) +return NULL ; + +if (!(info =_info_get_obj (o))) +return NULL ; + + o->tree =dm_tree_find_node (_dtree, info->major, info->minor); +return o->tree; +} + +static void *_deps_get_obj (void *obj) +{ +struct dmsetup_report_obj *o = (struct dmsetup_report_obj *) obj; +struct dm_task *dmt; +const char *name; + +if (o->deps) +return dm_task_get_deps (o->deps); + +/* name */ +if (!(dmt =_task_get_obj (o))) +return NULL ; +if (!(name =dm_task_get_name (dmt))) +return NULL ; + +/* deps */ +if (!(dmt =dm_task_create (DM_DEVICE_DEPS ))) +return NULL ; + +if (!dm_task_set_name (dmt, name)) + goto out; + +if (_switches[NOOPENCOUNT_ARG ] && !dm_task_no_open_count (dmt)) + goto out; + +if (!dm_task_run (dmt)) + goto out; + + o->deps = dmt; +return dm_task_get_deps (dmt); + + out: +dm_task_destroy (dmt); +return NULL ; +} +static const struct dm_report_object_type _report_types[] = { {DR_TASK ,"Mapped Device Name" ,"" , _task_get_obj }, {DR_INFO ,"Mapped Device Information" ,"" , _info_get_obj }, + {DR_DEPS ,"Mapped Device Dependency" ,"" , _deps_get_obj }, + {DR_TREE ,"Mapped Device Dependency" ,"" , _tree_get_obj }, {0 ,"" ,"" ,NULL }, };
@@ -1570,11 +1830,17 @@ static const struct dm_report_field_type FIELD_F(TASK, STR, "Name", 16, dm_name, "name", "Name of mapped device.") FIELD_F(TASK, STR, "UUID", 32, dm_uuid, "uuid", "Unique (optional) identifier for mapped device.") FIELD_F(INFO, STR, "Stat", 4, dm_info_status, "attr", "(L)ive, (I)nactive, (s)uspended, (r)ead-only, read-(w)rite.") +FIELD_F(INFO, STR, "Device", 6, dm_info_device, "device", "Device major and minor numbers") FIELD_O(INFO, dm_info, NUM, "Maj", major, 3, int32, "major", "Block device major number.") FIELD_O(INFO, dm_info, NUM, "Min", minor, 3, int32, "minor", "Block device minor number.") FIELD_O(INFO, dm_info, NUM, "Open", open_count, 4, int32, "open", "Number of references to open device, if requested.") FIELD_O(INFO, dm_info, NUM, "Targ", target_count, 4, int32, "segments", "Number of segments in live table, if present.") FIELD_O(INFO, dm_info, NUM, "Event", event_nr, 6, uint32, "events", "Number of most recent event.") +FIELD_O(DEPS, dm_deps, NUM, "Deps", count, 4, int32, "deps_count", "Number of underlying devices") +FIELD_F(DEPS, STR, "Depend on", 10, dm_deps, "deps", "List of underlying devic es") +FIELD_F(TREE, STR, "Parent Devices", 16, dm_tree_parents, "parents", "List of overlaying devices") +FIELD_F(TREE, STR, "Parent Maps", 12, dm_tree_parent_maps, "parent_maps", "List of overlaying maps") +FIELD_F(TREE, NUM, "Parents", 7, dm_tree_parents_count, "parents_count", "Number of overlaying devices") {0, 0, 0, 0, "", "", NULL, NULL}, /* *INDENT-ON* */ };
@@ -2300,5 +2566,8 @@ out:dm_report_free (_report); } +if (_dtree) +dm_tree_free (_dtree); +return r; }
PATCH 1/1 libdevmapper: (7/6) Add dm_report_get_report_types()
In reply to Jun'ichi NomuraHi,
This patch was missing from the last post...
Since rh->report_types can be updated after dm_report_init(), we need an interface to obtain it later.
Thanks,
Signature · 1 line
Jun'ichi Nomura, NEC Corporation of America
Add dm_report_get_report_types() to obtain updated report_types field after dm_report_set_filter() call.
--- dmsetup/dmsetup.c | 1 + lib/.exported_symbols | 1 + lib/libdevmapper.h | 1 + lib/libdm-report.c | 5 +++++ 4 files changed, 8 insertions(+)
lib/.exported_symbols +1 -0
@@ -128,5 +128,6 @@ dm_report_field_uint32 dm_report_field_uint64 dm_report_field_set_value dm_report_set_filter +dm_report_get_report_types dm_regex_create dm_regex_match
lib/libdm-report.c +5 -0
@@ -88,6 +88,11 @@ struct row {struct dm_report_field *(*sort_fields)[];/* Fields in sort order */ }; +uint32_t dm_report_get_report_types (struct dm_report *rh) +{ +return rh->report_types; +} +static const struct dm_report_object_type *_find_type (struct dm_report *rh,uint32_t report_type) {
lib/libdevmapper.h +1 -0
@@ -687,6 +687,7 @@ struct dm_report *dm_report_init(uint32_int dm_report_object (struct dm_report *rh,void *object);int dm_report_output (struct dm_report *rh);void dm_report_free (struct dm_report *rh); +uint32_t dm_report_get_report_types (struct dm_report *rh);/* Set filter */ int dm_report_set_filter(struct dm_report *rh,
dmsetup/dmsetup.c +1 -0
@@ -1924,6 +1924,7 @@ static int _report_init(struct command * goto out; } + report_type =dm_report_get_report_types (_report); r =1 ; out: