2002-12-12 23:55:49 +03:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2009-02-09 12:45:49 +03:00
* Copyright ( C ) 2004 - 2009 Red Hat , Inc . All rights reserved .
2002-12-12 23:55:49 +03:00
*
2004-03-30 23:35:44 +04:00
* This file is part of LVM2 .
2002-12-12 23:55:49 +03:00
*
2004-03-30 23:35:44 +04:00
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
2007-08-21 00:55:30 +04:00
* of the GNU Lesser General Public License v .2 .1 .
2002-12-12 23:55:49 +03:00
*
2007-08-21 00:55:30 +04:00
* You should have received a copy of the GNU Lesser General Public License
2004-03-30 23:35:44 +04:00
* along with this program ; if not , write to the Free Software Foundation ,
2016-01-21 13:49:46 +03:00
* Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
2002-12-12 23:55:49 +03:00
*/
# include "tools.h"
2015-07-06 19:30:18 +03:00
2018-05-14 12:30:20 +03:00
# include "lib/report/report.h"
2002-12-12 23:55:49 +03:00
2016-05-25 14:41:42 +03:00
typedef enum {
REPORT_IDX_NULL = - 1 ,
REPORT_IDX_SINGLE ,
REPORT_IDX_LOG ,
2016-05-03 12:18:16 +03:00
REPORT_IDX_FULL_VGS ,
REPORT_IDX_FULL_LVS ,
REPORT_IDX_FULL_PVS ,
REPORT_IDX_FULL_PVSEGS ,
REPORT_IDX_FULL_SEGS ,
2016-05-25 14:41:42 +03:00
REPORT_IDX_COUNT
} report_idx_t ;
2016-06-27 11:14:17 +03:00
# define REPORT_IDX_FULL_START REPORT_IDX_FULL_VGS
2016-05-25 14:41:42 +03:00
struct single_report_args {
report_type_t report_type ;
2016-05-02 15:37:16 +03:00
char report_prefix [ 32 ] ;
const char * report_name ;
2016-05-25 14:41:42 +03:00
int args_are_pvs ;
const char * keys ;
const char * options ;
const char * fields_to_compact ;
const char * selection ;
} ;
/* TODO: configure these common report args only once per cmd */
2016-05-10 14:57:23 +03:00
struct report_args {
int argc ;
char * * argv ;
2016-05-02 15:22:02 +03:00
dm_report_group_type_t report_group_type ;
2016-05-10 14:57:23 +03:00
report_type_t report_type ;
2023-08-22 11:54:35 +03:00
report_headings_t headings ;
2016-05-10 14:57:23 +03:00
int aligned ;
int buffered ;
int field_prefixes ;
int quoted ;
int columns_as_rows ;
const char * separator ;
2016-05-03 12:18:16 +03:00
struct volume_group * full_report_vg ;
2016-06-15 14:35:27 +03:00
int log_only ;
2016-05-25 14:41:42 +03:00
struct single_report_args single_args [ REPORT_IDX_COUNT ] ;
2016-05-10 14:57:23 +03:00
} ;
2014-11-27 17:02:13 +03:00
static int _process_each_devtype ( struct cmd_context * cmd , int argc ,
struct processing_handle * handle )
2013-09-18 04:09:15 +04:00
{
if ( argc )
log_warn ( " WARNING: devtypes currently ignores command line arguments. " ) ;
2014-11-27 17:02:13 +03:00
if ( ! report_devtypes ( handle - > custom_handle ) )
2013-09-18 04:09:15 +04:00
return_ECMD_FAILED ;
return ECMD_PROCESSED ;
}
2010-07-09 19:34:40 +04:00
static int _vgs_single ( struct cmd_context * cmd __attribute__ ( ( unused ) ) ,
2006-05-10 01:23:51 +04:00
const char * vg_name , struct volume_group * vg ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2002-12-12 23:55:49 +03:00
{
2014-12-02 15:14:12 +03:00
struct selection_handle * sh = handle - > selection_handle ;
if ( ! report_object ( sh ? : handle - > custom_handle , sh ! = NULL ,
vg , NULL , NULL , NULL , NULL , NULL , NULL ) )
2013-07-01 13:27:22 +04:00
return_ECMD_FAILED ;
2002-12-12 23:55:49 +03:00
2005-05-17 17:44:02 +04:00
check_current_backup ( vg ) ;
2003-10-22 02:06:07 +04:00
return ECMD_PROCESSED ;
2002-12-12 23:55:49 +03:00
}
2015-01-14 12:31:24 +03:00
static int _do_info_and_status ( struct cmd_context * cmd ,
const struct lv_segment * lv_seg ,
struct lv_with_info_and_seg_status * status ,
int do_info , int do_status )
2014-11-13 16:14:20 +03:00
{
2016-12-05 16:31:25 +03:00
status - > lv = lv_seg - > lv ;
2016-03-01 17:22:48 +03:00
2016-12-05 16:31:25 +03:00
if ( lv_is_historical ( lv_seg - > lv ) )
2016-03-01 17:22:48 +03:00
return 1 ;
2015-01-14 12:31:24 +03:00
if ( do_status ) {
if ( ! ( status - > seg_status . mem = dm_pool_create ( " reporter_pool " , 1024 ) ) )
return_0 ;
2016-09-09 15:24:49 +03:00
2016-12-05 12:20:42 +03:00
if ( do_info )
2015-01-14 12:31:24 +03:00
/* both info and status */
2016-12-05 16:31:25 +03:00
status - > info_ok = lv_info_with_seg_status ( cmd , lv_seg , status , 1 , 1 ) ;
2016-12-05 12:20:42 +03:00
else
2016-12-05 16:31:25 +03:00
status - > info_ok = lv_info_with_seg_status ( cmd , lv_seg , status , 0 , 0 ) ;
2015-01-20 14:38:38 +03:00
} else if ( do_info )
2015-01-14 12:31:24 +03:00
/* info only */
2016-12-05 16:31:25 +03:00
status - > info_ok = lv_info ( cmd , status - > lv , 0 , & status - > info , 1 , 1 ) ;
2015-01-14 12:31:24 +03:00
return 1 ;
2014-07-02 11:45:53 +04:00
}
2016-12-22 21:51:35 +03:00
/* Check if this is really merging origin.
* In such case , origin is gone , and user should see
* only data from merged snapshot . Important for thin . */
static int _check_merging_origin ( const struct logical_volume * lv ,
struct lv_with_info_and_seg_status * status ,
int * merged )
{
uint32_t device_id ;
* merged = 0 ;
switch ( status - > seg_status . type ) {
case SEG_STATUS_THIN :
/* Get 'device_id' from active dm-table */
if ( ! lv_thin_device_id ( lv , & device_id ) )
return_0 ;
if ( lv - > snapshot - > device_id ! = device_id )
return 1 ;
break ;
case SEG_STATUS_SNAPSHOT :
break ;
default :
2017-01-05 17:52:00 +03:00
/* When inactive, it's technically merging */
if ( status - > info_ok & & ! status - > info . exists )
break ;
2016-12-22 21:51:35 +03:00
return 1 ;
}
/* Origin is gone */
2017-01-05 17:52:00 +03:00
log_debug_activation ( " Merge is in progress, reporting merged LV %s. " ,
2016-12-22 21:51:35 +03:00
display_lvname ( lv - > snapshot - > lv ) ) ;
* merged = 1 ;
return 1 ;
}
2023-12-06 14:58:14 +03:00
static void _cond_warn_raid_volume_health ( struct cmd_context * cmd , const struct logical_volume * lv )
{
if ( lv_is_raid ( lv ) & & ! lv_raid_healthy ( lv ) & & ! lv_is_partial ( lv ) )
log_warn ( " WARNING: RaidLV %s needs to be refreshed! See character 'r' at position 9 in the RaidLV's attributes%s. " , display_lvname ( lv ) ,
arg_is_set ( cmd , all_ARG ) ? " and its SubLV(s) " : " and also its SubLV(s) with option '-a' " ) ;
}
2014-11-13 16:14:20 +03:00
static int _do_lvs_with_info_and_status_single ( struct cmd_context * cmd ,
2015-01-14 12:31:24 +03:00
const struct logical_volume * lv ,
2014-11-13 16:14:20 +03:00
int do_info , int do_status ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-07-11 12:18:59 +04:00
{
2014-12-02 15:14:12 +03:00
struct selection_handle * sh = handle - > selection_handle ;
2015-01-20 15:16:41 +03:00
struct lv_with_info_and_seg_status status = {
. seg_status . type = SEG_STATUS_NONE
} ;
2014-11-13 16:14:20 +03:00
int r = ECMD_FAILED ;
2016-12-22 21:51:35 +03:00
int merged ;
if ( lv_is_merging_origin ( lv ) )
/* Status is need to know which LV should be shown */
do_status = 1 ;
2014-11-13 16:14:20 +03:00
2016-12-05 16:31:25 +03:00
if ( ! _do_info_and_status ( cmd , first_seg ( lv ) , & status , do_info , do_status ) )
2015-02-09 13:48:21 +03:00
goto_out ;
2015-01-14 12:31:24 +03:00
2016-12-22 21:51:35 +03:00
if ( lv_is_merging_origin ( lv ) ) {
if ( ! _check_merging_origin ( lv , & status , & merged ) )
goto_out ;
2017-06-09 22:00:05 +03:00
if ( merged & & lv_is_thin_volume ( lv - > snapshot - > lv ) )
2016-12-22 21:51:35 +03:00
lv = lv - > snapshot - > lv ;
}
2023-12-06 14:58:14 +03:00
_cond_warn_raid_volume_health ( cmd , lv ) ;
2014-12-02 15:14:12 +03:00
if ( ! report_object ( sh ? : handle - > custom_handle , sh ! = NULL ,
lv - > vg , lv , NULL , NULL , NULL , & status , NULL ) )
2014-11-27 17:02:13 +03:00
goto out ;
2014-11-13 16:14:20 +03:00
r = ECMD_PROCESSED ;
out :
2015-01-14 12:31:24 +03:00
if ( status . seg_status . mem )
dm_pool_destroy ( status . seg_status . mem ) ;
2014-11-13 16:14:20 +03:00
return r ;
2014-07-11 12:18:59 +04:00
}
2014-11-13 16:14:20 +03:00
static int _lvs_single ( struct cmd_context * cmd , struct logical_volume * lv ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-10-21 14:01:57 +04:00
{
2014-11-13 16:14:20 +03:00
return _do_lvs_with_info_and_status_single ( cmd , lv , 0 , 0 , handle ) ;
2014-10-21 14:01:57 +04:00
}
2014-07-02 11:45:53 +04:00
static int _lvs_with_info_single ( struct cmd_context * cmd , struct logical_volume * lv ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-07-02 11:45:53 +04:00
{
2014-11-13 16:14:20 +03:00
return _do_lvs_with_info_and_status_single ( cmd , lv , 1 , 0 , handle ) ;
}
2002-12-12 23:55:49 +03:00
2014-11-13 16:14:20 +03:00
static int _lvs_with_status_single ( struct cmd_context * cmd , struct logical_volume * lv ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-11-13 16:14:20 +03:00
{
return _do_lvs_with_info_and_status_single ( cmd , lv , 0 , 1 , handle ) ;
2002-12-12 23:55:49 +03:00
}
2014-11-13 16:14:20 +03:00
static int _lvs_with_info_and_status_single ( struct cmd_context * cmd , struct logical_volume * lv ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-10-21 14:01:57 +04:00
{
2014-11-13 16:14:20 +03:00
return _do_lvs_with_info_and_status_single ( cmd , lv , 1 , 1 , handle ) ;
2014-10-21 14:01:57 +04:00
}
2014-11-13 16:14:20 +03:00
static int _do_segs_with_info_and_status_single ( struct cmd_context * cmd ,
2015-01-14 12:31:24 +03:00
const struct lv_segment * seg ,
2014-11-13 16:14:20 +03:00
int do_info , int do_status ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-10-21 14:01:57 +04:00
{
2014-12-02 15:14:12 +03:00
struct selection_handle * sh = handle - > selection_handle ;
2015-01-20 15:16:41 +03:00
struct lv_with_info_and_seg_status status = {
. seg_status . type = SEG_STATUS_NONE
} ;
2014-10-21 14:01:57 +04:00
int r = ECMD_FAILED ;
2016-12-22 21:51:35 +03:00
int merged ;
if ( lv_is_merging_origin ( seg - > lv ) )
/* Status is need to know which LV should be shown */
do_status = 1 ;
2014-10-21 14:01:57 +04:00
2016-12-05 16:31:25 +03:00
if ( ! _do_info_and_status ( cmd , seg , & status , do_info , do_status ) )
2015-02-09 13:48:21 +03:00
goto_out ;
2015-01-14 12:31:24 +03:00
2016-12-22 21:51:35 +03:00
if ( lv_is_merging_origin ( seg - > lv ) ) {
if ( ! _check_merging_origin ( seg - > lv , & status , & merged ) )
goto_out ;
2017-06-09 22:00:05 +03:00
if ( merged & & lv_is_thin_volume ( seg - > lv - > snapshot - > lv ) )
2016-12-22 21:51:35 +03:00
seg = seg - > lv - > snapshot ;
}
2023-12-06 14:58:14 +03:00
_cond_warn_raid_volume_health ( cmd , seg - > lv ) ;
2014-12-02 15:14:12 +03:00
if ( ! report_object ( sh ? : handle - > custom_handle , sh ! = NULL ,
seg - > lv - > vg , seg - > lv , NULL , seg , NULL , & status , NULL ) )
2017-06-09 15:52:40 +03:00
goto_out ;
2014-10-21 14:01:57 +04:00
r = ECMD_PROCESSED ;
out :
2015-01-14 12:31:24 +03:00
if ( status . seg_status . mem )
dm_pool_destroy ( status . seg_status . mem ) ;
2014-10-21 14:01:57 +04:00
return r ;
}
2014-11-13 16:14:20 +03:00
static int _segs_single ( struct cmd_context * cmd , struct lv_segment * seg ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2002-12-12 23:55:49 +03:00
{
2014-11-13 16:14:20 +03:00
return _do_segs_with_info_and_status_single ( cmd , seg , 0 , 0 , handle ) ;
}
2002-12-12 23:55:49 +03:00
2014-11-13 16:14:20 +03:00
static int _segs_with_info_single ( struct cmd_context * cmd , struct lv_segment * seg ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-11-13 16:14:20 +03:00
{
return _do_segs_with_info_and_status_single ( cmd , seg , 1 , 0 , handle ) ;
2002-12-12 23:55:49 +03:00
}
2014-07-07 17:54:13 +04:00
2014-11-13 16:14:20 +03:00
static int _segs_with_status_single ( struct cmd_context * cmd , struct lv_segment * seg ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-07-07 17:54:13 +04:00
{
2014-11-13 16:14:20 +03:00
return _do_segs_with_info_and_status_single ( cmd , seg , 0 , 1 , handle ) ;
}
2014-07-07 17:54:13 +04:00
2014-11-13 16:14:20 +03:00
static int _segs_with_info_and_status_single ( struct cmd_context * cmd , struct lv_segment * seg ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-11-13 16:14:20 +03:00
{
return _do_segs_with_info_and_status_single ( cmd , seg , 1 , 1 , handle ) ;
}
2014-07-07 17:54:13 +04:00
2014-11-13 16:14:20 +03:00
static int _lvsegs_single ( struct cmd_context * cmd , struct logical_volume * lv ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-11-13 16:14:20 +03:00
{
2016-06-22 00:24:52 +03:00
if ( ! arg_is_set ( cmd , all_ARG ) & & ! lv_is_visible ( lv ) )
2014-11-13 16:14:20 +03:00
return ECMD_PROCESSED ;
return process_each_segment_in_lv ( cmd , lv , handle , _segs_single ) ;
2014-07-07 17:54:13 +04:00
}
2014-11-13 16:14:20 +03:00
static int _lvsegs_with_info_single ( struct cmd_context * cmd , struct logical_volume * lv ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-10-21 14:01:57 +04:00
{
2016-06-22 00:24:52 +03:00
if ( ! arg_is_set ( cmd , all_ARG ) & & ! lv_is_visible ( lv ) )
2014-11-13 16:14:20 +03:00
return ECMD_PROCESSED ;
2014-10-21 14:01:57 +04:00
2014-11-13 16:14:20 +03:00
return process_each_segment_in_lv ( cmd , lv , handle , _segs_with_info_single ) ;
}
2014-10-21 14:01:57 +04:00
2014-11-13 16:14:20 +03:00
static int _lvsegs_with_status_single ( struct cmd_context * cmd , struct logical_volume * lv ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-11-13 16:14:20 +03:00
{
2016-06-22 00:24:52 +03:00
if ( ! arg_is_set ( cmd , all_ARG ) & & ! lv_is_visible ( lv ) )
2014-11-13 16:14:20 +03:00
return ECMD_PROCESSED ;
return process_each_segment_in_lv ( cmd , lv , handle , _segs_with_status_single ) ;
}
static int _lvsegs_with_info_and_status_single ( struct cmd_context * cmd , struct logical_volume * lv ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-11-13 16:14:20 +03:00
{
2016-06-22 00:24:52 +03:00
if ( ! arg_is_set ( cmd , all_ARG ) & & ! lv_is_visible ( lv ) )
2014-11-13 16:14:20 +03:00
return ECMD_PROCESSED ;
return process_each_segment_in_lv ( cmd , lv , handle , _segs_with_info_and_status_single ) ;
2014-10-21 14:01:57 +04:00
}
2014-07-07 17:54:13 +04:00
static int _do_pvsegs_sub_single ( struct cmd_context * cmd ,
struct volume_group * vg ,
struct pv_segment * pvseg ,
2014-11-13 16:14:20 +03:00
int do_info ,
int do_status ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2005-04-20 00:58:25 +04:00
{
2014-12-02 15:14:12 +03:00
struct selection_handle * sh = handle - > selection_handle ;
2005-04-20 00:58:25 +04:00
int ret = ECMD_PROCESSED ;
2007-12-15 00:53:02 +03:00
struct lv_segment * seg = pvseg - > lvseg ;
2014-10-22 16:30:33 +04:00
struct segment_type _freeseg_type = {
. flags = SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED ,
2020-08-29 22:37:39 +03:00
. name = " free " ,
2014-10-22 16:30:33 +04:00
} ;
2005-04-20 00:58:25 +04:00
2009-04-21 16:59:18 +04:00
struct volume_group _free_vg = {
. cmd = cmd ,
2011-02-18 17:47:28 +03:00
. name = " " ,
2014-10-22 16:30:33 +04:00
. pvs = DM_LIST_HEAD_INIT ( _free_vg . pvs ) ,
. lvs = DM_LIST_HEAD_INIT ( _free_vg . lvs ) ,
2016-03-01 17:18:42 +03:00
. historical_lvs = DM_LIST_HEAD_INIT ( _free_vg . historical_lvs ) ,
2014-10-22 16:30:33 +04:00
. tags = DM_LIST_HEAD_INIT ( _free_vg . tags ) ,
2009-04-21 16:59:18 +04:00
} ;
2008-06-25 20:52:27 +04:00
struct logical_volume _free_logical_volume = {
2011-02-18 17:47:28 +03:00
. name = " " ,
2020-08-29 22:37:39 +03:00
. vg = vg ? : & _free_vg ,
2008-06-25 20:52:27 +04:00
. status = VISIBLE_LV ,
. major = - 1 ,
. minor = - 1 ,
2020-08-29 22:37:39 +03:00
. snapshot_segs = DM_LIST_HEAD_INIT ( _free_logical_volume . snapshot_segs ) ,
2014-10-22 16:30:33 +04:00
. segments = DM_LIST_HEAD_INIT ( _free_logical_volume . segments ) ,
2020-08-29 22:37:39 +03:00
. tags = DM_LIST_HEAD_INIT ( _free_logical_volume . tags ) ,
2014-10-22 16:30:33 +04:00
. segs_using_this_lv = DM_LIST_HEAD_INIT ( _free_logical_volume . segs_using_this_lv ) ,
2016-03-01 17:18:42 +03:00
. indirect_glvs = DM_LIST_HEAD_INIT ( _free_logical_volume . indirect_glvs ) ,
2008-06-25 20:52:27 +04:00
} ;
struct lv_segment _free_lv_segment = {
2010-03-16 18:30:48 +03:00
. lv = & _free_logical_volume ,
2014-10-22 16:30:33 +04:00
. segtype = & _freeseg_type ,
. len = pvseg - > len ,
. origin_list = DM_LIST_HEAD_INIT ( _free_lv_segment . origin_list ) ,
2020-08-29 22:37:39 +03:00
. tags = DM_LIST_HEAD_INIT ( _free_lv_segment . tags ) ,
2008-06-25 20:52:27 +04:00
} ;
2015-01-20 15:16:41 +03:00
struct lv_with_info_and_seg_status status = {
. seg_status . type = SEG_STATUS_NONE ,
. lv = & _free_logical_volume
} ;
2016-12-05 16:31:25 +03:00
if ( seg & & ! _do_info_and_status ( cmd , seg , & status , do_info , do_status ) )
2015-02-09 13:48:21 +03:00
goto_out ;
2014-07-07 17:54:13 +04:00
2014-12-02 15:14:12 +03:00
if ( ! report_object ( sh ? : handle - > custom_handle , sh ! = NULL ,
vg , seg ? seg - > lv : & _free_logical_volume ,
pvseg - > pv , seg ? : & _free_lv_segment , pvseg ,
& status , pv_label ( pvseg - > pv ) ) ) {
2006-09-02 05:18:17 +04:00
ret = ECMD_FAILED ;
2013-07-01 13:27:11 +04:00
goto_out ;
2009-09-15 02:47:49 +04:00
}
2011-03-09 15:44:42 +03:00
2010-11-18 01:26:42 +03:00
out :
2015-01-14 12:31:24 +03:00
if ( status . seg_status . mem )
dm_pool_destroy ( status . seg_status . mem ) ;
2005-04-20 00:58:25 +04:00
return ret ;
}
2014-07-07 17:54:13 +04:00
static int _pvsegs_sub_single ( struct cmd_context * cmd ,
struct volume_group * vg ,
2014-11-13 16:14:20 +03:00
struct pv_segment * pvseg ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-07-07 17:54:13 +04:00
{
2014-10-20 15:46:50 +04:00
return _do_pvsegs_sub_single ( cmd , vg , pvseg , 0 , 0 , handle ) ;
2014-07-07 17:54:13 +04:00
}
static int _pvsegs_with_lv_info_sub_single ( struct cmd_context * cmd ,
struct volume_group * vg ,
struct pv_segment * pvseg ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-07-07 17:54:13 +04:00
{
2014-10-20 15:46:50 +04:00
return _do_pvsegs_sub_single ( cmd , vg , pvseg , 1 , 0 , handle ) ;
2014-07-07 17:54:13 +04:00
}
2014-11-13 16:14:20 +03:00
static int _pvsegs_with_lv_status_sub_single ( struct cmd_context * cmd ,
struct volume_group * vg ,
struct pv_segment * pvseg ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2002-12-12 23:55:49 +03:00
{
2014-11-13 16:14:20 +03:00
return _do_pvsegs_sub_single ( cmd , vg , pvseg , 0 , 1 , handle ) ;
2002-12-12 23:55:49 +03:00
}
2014-11-13 16:14:20 +03:00
static int _pvsegs_with_lv_info_and_status_sub_single ( struct cmd_context * cmd ,
struct volume_group * vg ,
struct pv_segment * pvseg ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-07-07 17:54:13 +04:00
{
2014-11-13 16:14:20 +03:00
return _do_pvsegs_sub_single ( cmd , vg , pvseg , 1 , 1 , handle ) ;
2014-07-07 17:54:13 +04:00
}
2014-11-13 16:14:20 +03:00
static int _pvsegs_single ( struct cmd_context * cmd ,
struct volume_group * vg ,
struct physical_volume * pv ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2005-04-20 00:58:25 +04:00
{
2014-11-13 16:14:20 +03:00
return process_each_segment_in_pv ( cmd , vg , pv , handle , _pvsegs_sub_single ) ;
2005-04-20 00:58:25 +04:00
}
2014-07-07 17:54:13 +04:00
static int _pvsegs_with_lv_info_single ( struct cmd_context * cmd ,
struct volume_group * vg ,
struct physical_volume * pv ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-07-07 17:54:13 +04:00
{
2014-11-13 16:14:20 +03:00
return process_each_segment_in_pv ( cmd , vg , pv , handle , _pvsegs_with_lv_info_sub_single ) ;
}
static int _pvsegs_with_lv_status_single ( struct cmd_context * cmd ,
struct volume_group * vg ,
struct physical_volume * pv ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-11-13 16:14:20 +03:00
{
return process_each_segment_in_pv ( cmd , vg , pv , handle , _pvsegs_with_lv_status_sub_single ) ;
}
static int _pvsegs_with_lv_info_and_status_single ( struct cmd_context * cmd ,
struct volume_group * vg ,
struct physical_volume * pv ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2014-11-13 16:14:20 +03:00
{
return process_each_segment_in_pv ( cmd , vg , pv , handle , _pvsegs_with_lv_info_and_status_sub_single ) ;
2014-07-07 17:54:13 +04:00
}
2002-12-12 23:55:49 +03:00
static int _pvs_single ( struct cmd_context * cmd , struct volume_group * vg ,
2014-11-27 17:02:13 +03:00
struct physical_volume * pv ,
struct processing_handle * handle )
2002-12-12 23:55:49 +03:00
{
2014-12-02 15:14:12 +03:00
struct selection_handle * sh = handle - > selection_handle ;
if ( ! report_object ( sh ? : handle - > custom_handle , sh ! = NULL ,
vg , NULL , pv , NULL , NULL , NULL , NULL ) )
2014-10-07 03:34:04 +04:00
return_ECMD_FAILED ;
2009-04-10 14:01:38 +04:00
2014-10-07 03:34:04 +04:00
return ECMD_PROCESSED ;
2002-12-12 23:55:49 +03:00
}
2013-07-29 21:07:11 +04:00
static int _label_single ( struct cmd_context * cmd , struct label * label ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2009-02-09 12:45:49 +03:00
{
2014-12-02 15:14:12 +03:00
struct selection_handle * sh = handle - > selection_handle ;
if ( ! report_object ( sh ? : handle - > custom_handle , sh ! = NULL ,
NULL , NULL , NULL , NULL , NULL , NULL , label ) )
2013-07-01 13:27:22 +04:00
return_ECMD_FAILED ;
2009-02-09 12:45:49 +03:00
return ECMD_PROCESSED ;
}
2007-01-27 05:09:06 +03:00
static int _pvs_in_vg ( struct cmd_context * cmd , const char * vg_name ,
2007-08-22 18:38:18 +04:00
struct volume_group * vg ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2007-01-27 05:09:06 +03:00
{
2014-10-07 03:34:04 +04:00
return process_each_pv_in_vg ( cmd , vg , handle , & _pvs_single ) ;
2007-01-27 05:09:06 +03:00
}
2007-01-27 05:32:31 +03:00
static int _pvsegs_in_vg ( struct cmd_context * cmd , const char * vg_name ,
2007-08-22 18:38:18 +04:00
struct volume_group * vg ,
2014-11-27 17:02:13 +03:00
struct processing_handle * handle )
2007-01-27 05:32:31 +03:00
{
2014-10-07 03:34:04 +04:00
return process_each_pv_in_vg ( cmd , vg , handle , & _pvsegs_single ) ;
2007-01-27 05:32:31 +03:00
}
2016-05-03 12:42:55 +03:00
static int _get_final_report_type ( struct report_args * args ,
struct single_report_args * single_args ,
2014-12-01 16:04:29 +03:00
report_type_t report_type ,
int * lv_info_needed ,
int * lv_segment_status_needed ,
report_type_t * final_report_type )
{
/* Do we need to acquire LV device info in addition? */
* lv_info_needed = ( report_type & ( LVSINFO | LVSINFOSTATUS ) ) ? 1 : 0 ;
/* Do we need to acquire LV device status in addition? */
2016-04-08 15:18:00 +03:00
* lv_segment_status_needed = ( report_type & ( LVSSTATUS | LVSINFOSTATUS ) ) ? 1 : 0 ;
2014-12-01 16:04:29 +03:00
/* Ensure options selected are compatible */
2016-04-08 15:18:00 +03:00
if ( report_type & SEGS )
2014-12-01 16:04:29 +03:00
report_type | = LVS ;
if ( report_type & PVSEGS )
report_type | = PVS ;
if ( ( report_type & ( LVS | LVSINFO | LVSSTATUS | LVSINFOSTATUS ) ) & &
2016-05-03 12:42:55 +03:00
( report_type & ( PVS | LABEL ) ) & & ! ( single_args - > args_are_pvs | | ( args - > full_report_vg & & single_args - > report_type = = PVSEGS ) ) ) {
log_error ( " Can't report LV and PV fields at the same time in %sreport type \" %s \" %s%s. " ,
args - > full_report_vg ? " sub " : " " , single_args - > report_prefix ,
args - > full_report_vg ? " in VG " : " " ,
args - > full_report_vg ? args - > full_report_vg - > name : " " ) ;
2014-12-01 16:04:29 +03:00
return 0 ;
}
/* Change report type if fields specified makes this necessary */
2016-05-03 12:18:16 +03:00
if ( report_type & FULL )
report_type = FULL ;
else if ( ( report_type & PVSEGS ) | |
( ( report_type & ( PVS | LABEL ) ) & & ( report_type & ( LVS | LVSINFO | LVSSTATUS | LVSINFOSTATUS ) ) ) )
2014-12-01 16:04:29 +03:00
report_type = PVSEGS ;
else if ( ( report_type & PVS ) | |
( ( report_type & LABEL ) & & ( report_type & VGS ) ) )
report_type = PVS ;
2016-04-08 15:18:00 +03:00
else if ( report_type & SEGS )
2014-12-01 16:04:29 +03:00
report_type = SEGS ;
else if ( report_type & ( LVS | LVSINFO | LVSSTATUS | LVSINFOSTATUS ) )
report_type = LVS ;
2016-05-03 12:42:55 +03:00
if ( args - > full_report_vg & & ( report_type ! = single_args - > report_type ) ) {
/* FIXME: Tell user about which columns exactly are incorrectly used for that report type... */
log_error ( " Subreport of type \" %s \" for VG %s contains columns which lead to change of report type. "
" Add these columns to proper subreport type. " , single_args - > report_prefix , args - > full_report_vg - > name ) ;
return 0 ;
}
2014-12-01 16:04:29 +03:00
* final_report_type = report_type ;
return 1 ;
}
2016-04-14 16:21:41 +03:00
static int _report_all_in_vg ( struct cmd_context * cmd , struct processing_handle * handle ,
struct volume_group * vg , report_type_t type ,
int do_lv_info , int do_lv_seg_status )
{
2024-04-09 18:40:45 +03:00
int r = ECMD_FAILED ;
2016-04-14 16:21:41 +03:00
switch ( type ) {
case VGS :
r = _vgs_single ( cmd , vg - > name , vg , handle ) ;
break ;
case LVS :
2016-11-29 21:00:15 +03:00
r = process_each_lv_in_vg ( cmd , vg , NULL , NULL , 0 , handle , NULL ,
2016-04-14 16:21:41 +03:00
do_lv_info & & ! do_lv_seg_status ? & _lvs_with_info_single :
! do_lv_info & & do_lv_seg_status ? & _lvs_with_status_single :
do_lv_info & & do_lv_seg_status ? & _lvs_with_info_and_status_single :
& _lvs_single ) ;
break ;
case SEGS :
2016-11-29 21:00:15 +03:00
r = process_each_lv_in_vg ( cmd , vg , NULL , NULL , 0 , handle , NULL ,
2016-04-14 16:21:41 +03:00
do_lv_info & & ! do_lv_seg_status ? & _lvsegs_with_info_single :
! do_lv_info & & do_lv_seg_status ? & _lvsegs_with_status_single :
do_lv_info & & do_lv_seg_status ? & _lvsegs_with_info_and_status_single :
& _lvsegs_single ) ;
break ;
case PVS :
r = process_each_pv_in_vg ( cmd , vg , handle , & _pvs_single ) ;
break ;
case PVSEGS :
r = process_each_pv_in_vg ( cmd , vg , handle ,
do_lv_info & & ! do_lv_seg_status ? & _pvsegs_with_lv_info_single :
! do_lv_info & & do_lv_seg_status ? & _pvsegs_with_lv_status_single :
do_lv_info & & do_lv_seg_status ? & _pvsegs_with_lv_info_and_status_single :
& _pvsegs_single ) ;
break ;
default :
log_error ( INTERNAL_ERROR " _report_all_in_vg: incorrect report type " ) ;
break ;
}
return r ;
}
static int _report_all_in_lv ( struct cmd_context * cmd , struct processing_handle * handle ,
struct logical_volume * lv , report_type_t type ,
int do_lv_info , int do_lv_seg_status )
{
2024-04-09 18:40:45 +03:00
int r = ECMD_FAILED ;
2016-04-14 16:21:41 +03:00
switch ( type ) {
case LVS :
r = _do_lvs_with_info_and_status_single ( cmd , lv , do_lv_info , do_lv_seg_status , handle ) ;
break ;
case SEGS :
r = process_each_segment_in_lv ( cmd , lv , handle ,
do_lv_info & & ! do_lv_seg_status ? & _segs_with_info_single :
! do_lv_info & & do_lv_seg_status ? & _segs_with_status_single :
do_lv_info & & do_lv_seg_status ? & _segs_with_info_and_status_single :
& _segs_single ) ;
break ;
default :
log_error ( INTERNAL_ERROR " _report_all_in_lv: incorrect report type " ) ;
break ;
}
return r ;
}
static int _report_all_in_pv ( struct cmd_context * cmd , struct processing_handle * handle ,
struct physical_volume * pv , report_type_t type ,
int do_lv_info , int do_lv_seg_status )
{
2024-04-09 18:40:45 +03:00
int r = ECMD_FAILED ;
2016-04-14 16:21:41 +03:00
2024-04-09 12:35:23 +03:00
if ( ! pv ) {
log_error ( INTERNAL_ERROR " _report_all_in_pv: missing pv. " ) ;
return r ;
}
2016-04-14 16:21:41 +03:00
switch ( type ) {
case PVS :
r = _pvs_single ( cmd , pv - > vg , pv , handle ) ;
break ;
case PVSEGS :
r = process_each_segment_in_pv ( cmd , pv - > vg , pv , handle ,
do_lv_info & & ! do_lv_seg_status ? & _pvsegs_with_lv_info_sub_single :
! do_lv_info & & do_lv_seg_status ? & _pvsegs_with_lv_status_sub_single :
do_lv_info & & do_lv_seg_status ? & _pvsegs_with_lv_info_and_status_sub_single :
& _pvsegs_sub_single ) ;
break ;
default :
log_error ( INTERNAL_ERROR " _report_all_in_pv: incorrect report type " ) ;
break ;
}
return r ;
}
2015-02-13 12:36:06 +03:00
int report_for_selection ( struct cmd_context * cmd ,
2016-05-30 17:28:47 +03:00
struct processing_handle * parent_handle ,
2014-12-01 16:19:30 +03:00
struct physical_volume * pv ,
struct volume_group * vg ,
struct logical_volume * lv )
{
2016-05-30 17:28:47 +03:00
struct selection_handle * sh = parent_handle - > selection_handle ;
2023-05-30 22:14:37 +03:00
report_type_t initial_report_type = sh - > report_type ;
2016-05-03 12:42:55 +03:00
struct report_args args = { 0 } ;
struct single_report_args * single_args = & args . single_args [ REPORT_IDX_SINGLE ] ;
2014-12-01 17:40:03 +03:00
int do_lv_info , do_lv_seg_status ;
2015-02-13 12:36:06 +03:00
struct processing_handle * handle ;
2014-12-01 17:40:03 +03:00
int r = 0 ;
2016-05-03 12:42:55 +03:00
single_args - > report_type = sh - > orig_report_type | sh - > report_type ;
single_args - > args_are_pvs = sh - > orig_report_type = = PVS ;
if ( ! _get_final_report_type ( & args , single_args ,
single_args - > report_type ,
& do_lv_info , & do_lv_seg_status ,
2014-12-01 17:40:03 +03:00
& sh - > report_type ) )
return_0 ;
2023-05-30 22:14:37 +03:00
if ( ! ( handle = init_processing_handle ( cmd , parent_handle ) ) ) {
sh - > report_type = initial_report_type ;
2015-02-13 12:36:06 +03:00
return_0 ;
2023-05-30 22:14:37 +03:00
}
2015-02-13 12:36:06 +03:00
/*
* We ' re already reporting for select so override
* internal_report_for_select to 0 as we can call
* process_each_ * functions again and we could
* end up in an infinite loop if we didn ' t stop
* internal reporting for select right here .
*
* So the overall call trace from top to bottom looks like this :
*
* process_each_ * ( top - level one , using processing_handle with internal reporting enabled and selection_handle ) - >
* select_match_ * ( processing_handle with selection_handle ) - >
* report for selection - >
* ( creating new processing_handle here with internal reporting disabled ! ! ! )
* reporting_fn OR process_each_ * ( using * new * processing_handle with original selection_handle )
*
* The selection_handle is still reused so we can track
* whether any of the items the top - level one is composed
* of are still selected or not unerneath . Do not destroy
* this selection handle - it needs to be passed to upper
* layers to check the overall selection status .
*/
handle - > internal_report_for_select = 0 ;
handle - > selection_handle = sh ;
2014-12-01 17:40:03 +03:00
/*
* Remember :
2015-02-13 12:36:06 +03:00
* sh - > orig_report_type is the original report type requested ( what are we selecting ? PV / VG / LV ? )
* sh - > report_type is the report type actually used ( it counts with all types of fields used in selection criteria )
2014-12-01 17:40:03 +03:00
*/
switch ( sh - > orig_report_type ) {
case LVS :
2016-04-14 16:21:41 +03:00
r = _report_all_in_lv ( cmd , handle , lv , sh - > report_type , do_lv_info , do_lv_seg_status ) ;
2014-12-01 17:40:03 +03:00
break ;
case VGS :
2016-04-14 16:21:41 +03:00
r = _report_all_in_vg ( cmd , handle , vg , sh - > report_type , do_lv_info , do_lv_seg_status ) ;
2014-12-01 17:40:03 +03:00
break ;
case PVS :
2016-04-14 16:21:41 +03:00
r = _report_all_in_pv ( cmd , handle , pv , sh - > report_type , do_lv_info , do_lv_seg_status ) ;
2014-12-01 17:40:03 +03:00
break ;
default :
2016-04-14 16:21:41 +03:00
log_error ( INTERNAL_ERROR " report_for_selection: incorrect report type " ) ;
2014-12-01 17:40:03 +03:00
break ;
}
2023-05-30 22:14:37 +03:00
sh - > report_type = initial_report_type ;
2015-02-13 12:36:06 +03:00
/*
* Keep the selection handle provided from the caller -
* do not destroy it - the caller will still use it to
* pass the result through it to layers above .
*/
handle - > selection_handle = NULL ;
2015-02-13 12:42:21 +03:00
destroy_processing_handle ( cmd , handle ) ;
2014-12-01 17:40:03 +03:00
return r ;
2014-12-01 16:19:30 +03:00
}
2016-05-25 14:41:42 +03:00
static void _check_pv_list ( struct cmd_context * cmd , struct report_args * args , struct single_report_args * single_args )
2015-02-27 15:32:52 +03:00
{
2017-02-12 20:18:54 +03:00
int i ;
2015-02-27 15:32:52 +03:00
2016-05-23 12:18:50 +03:00
if ( ! args - > argv )
return ;
2016-05-25 14:41:42 +03:00
single_args - > args_are_pvs = ( single_args - > report_type = = PVS | |
single_args - > report_type = = LABEL | |
single_args - > report_type = = PVSEGS ) ? 1 : 0 ;
2015-02-27 15:32:52 +03:00
2016-05-25 14:41:42 +03:00
if ( single_args - > args_are_pvs & & args - > argc ) {
2016-05-10 14:57:23 +03:00
for ( i = 0 ; i < args - > argc ; i + + ) {
if ( * args - > argv [ i ] = = ' @ ' ) {
2015-02-27 15:48:47 +03:00
/*
* Tags are metadata related , not label
* related , change report type accordingly !
*/
2016-05-25 14:41:42 +03:00
if ( single_args - > report_type = = LABEL )
single_args - > report_type = PVS ;
2019-05-04 00:12:43 +03:00
break ;
2015-02-27 15:32:52 +03:00
}
}
}
}
2015-10-22 15:30:11 +03:00
static void _del_option_from_list ( struct dm_list * sll , const char * prefix ,
size_t prefix_len , const char * str )
2015-10-21 16:36:26 +03:00
{
struct dm_list * slh ;
struct dm_str_list * sl ;
2015-10-22 15:30:11 +03:00
const char * a = str , * b ;
2015-10-21 16:36:26 +03:00
dm_list_uniterate ( slh , sll , sll ) {
sl = dm_list_item ( slh , struct dm_str_list ) ;
2015-10-22 15:30:11 +03:00
/* exact match */
2015-10-21 16:36:26 +03:00
if ( ! strcmp ( str , sl - > str ) ) {
dm_list_del ( slh ) ;
return ;
}
2015-10-22 15:30:11 +03:00
/* also try to match with known prefix */
b = sl - > str ;
if ( ! strncmp ( prefix , a , prefix_len ) ) {
a + = prefix_len ;
if ( * a = = ' _ ' )
a + + ;
}
if ( ! strncmp ( prefix , b , prefix_len ) ) {
b + = prefix_len ;
if ( * b = = ' _ ' )
b + + ;
}
if ( ! strcmp ( a , b ) ) {
dm_list_del ( slh ) ;
return ;
}
2015-10-21 16:36:26 +03:00
}
}
2016-05-26 16:50:52 +03:00
# define _get_report_idx(report_type,single_report_type) \
2017-07-19 17:17:30 +03:00
( ( ( ( report_type ) ! = FULL ) & & ( ( report_type ) = = single_report_type ) ) ? REPORT_IDX_SINGLE : REPORT_IDX_FULL_ # # single_report_type )
2016-05-26 16:50:52 +03:00
static report_idx_t _get_report_idx_from_name ( report_type_t report_type , const char * name )
{
report_idx_t idx ;
if ( ! name | | ! * name )
return REPORT_IDX_NULL ;
2016-06-20 14:15:33 +03:00
/* Change to basic report type for comparison. */
2016-06-27 11:14:17 +03:00
if ( ( report_type = = LABEL ) | | ( report_type = = PVSEGS ) )
2016-06-20 14:15:33 +03:00
report_type = PVS ;
else if ( report_type = = SEGS )
report_type = LVS ;
2016-05-26 16:50:52 +03:00
if ( ! strcasecmp ( name , " log " ) )
idx = REPORT_IDX_LOG ;
else if ( ! strcasecmp ( name , " vg " ) )
idx = _get_report_idx ( report_type , VGS ) ;
else if ( ! strcasecmp ( name , " pv " ) )
idx = _get_report_idx ( report_type , PVS ) ;
else if ( ! strcasecmp ( name , " lv " ) )
idx = _get_report_idx ( report_type , LVS ) ;
2016-06-20 14:15:33 +03:00
else if ( ! strcasecmp ( name , " pvseg " ) ) {
idx = ( report_type = = FULL ) ? _get_report_idx ( report_type , PVSEGS )
: _get_report_idx ( report_type , PVS ) ;
} else if ( ! strcasecmp ( name , " seg " ) )
idx = ( report_type = = FULL ) ? _get_report_idx ( report_type , SEGS )
: _get_report_idx ( report_type , LVS ) ;
2016-05-26 16:50:52 +03:00
else {
idx = REPORT_IDX_NULL ;
log_error ( " Unknonwn report specifier in "
" report option list: %s. " , name ) ;
}
return idx ;
}
2016-06-27 11:14:17 +03:00
static int _should_process_report_idx ( report_type_t report_type , int allow_single , report_idx_t idx )
2016-05-26 16:50:52 +03:00
{
if ( ( ( idx = = REPORT_IDX_LOG ) & & ( report_type ! = CMDLOG ) ) | |
2016-06-27 11:14:17 +03:00
( ( idx = = REPORT_IDX_SINGLE ) & & ! allow_single ) | |
( ( idx > = REPORT_IDX_FULL_START ) & & report_type ! = FULL ) )
2016-05-26 16:50:52 +03:00
return 0 ;
return 1 ;
}
2016-05-04 15:07:45 +03:00
enum opts_list_type {
OPTS_REPLACE ,
OPTS_ADD ,
OPTS_REMOVE ,
OPTS_COMPACT
} ;
2015-10-22 15:30:11 +03:00
static int _get_report_options ( struct cmd_context * cmd ,
2016-05-25 14:41:42 +03:00
struct report_args * args ,
struct single_report_args * single_args )
2015-10-20 17:36:11 +03:00
{
2016-05-04 15:07:45 +03:00
int action ;
2015-10-21 15:57:49 +03:00
struct arg_value_group_list * current_group ;
2021-09-14 20:25:31 +03:00
struct dm_list * final_opts_list [ REPORT_IDX_COUNT ] = { NULL } ;
2015-10-21 15:57:49 +03:00
struct dm_list * opts_list = NULL ;
2015-10-21 16:36:26 +03:00
struct dm_str_list * sl ;
2015-11-11 18:09:39 +03:00
struct dm_pool * mem ;
2016-05-04 15:07:45 +03:00
const char * report_name = NULL ;
const char * opts ;
report_idx_t idx = REPORT_IDX_SINGLE ;
int r = ECMD_FAILED ;
2015-10-20 17:36:11 +03:00
2016-06-22 00:24:52 +03:00
if ( ! arg_is_set ( cmd , options_ARG ) )
2016-05-25 14:41:42 +03:00
return ECMD_PROCESSED ;
2015-11-11 18:09:39 +03:00
if ( ! ( mem = dm_pool_create ( " report_options " , 128 ) ) ) {
log_error ( " Failed to create temporary mempool to process report options. " ) ;
2016-06-27 11:12:41 +03:00
return ECMD_FAILED ;
2015-11-11 18:09:39 +03:00
}
2015-10-22 16:37:27 +03:00
2016-05-04 15:07:45 +03:00
if ( single_args - > report_type = = CMDLOG ) {
if ( ! ( final_opts_list [ REPORT_IDX_LOG ] = str_to_str_list ( mem , single_args - > options , " , " , 1 ) ) )
goto_out ;
} else if ( single_args - > report_type = = FULL ) {
if ( ! ( final_opts_list [ REPORT_IDX_FULL_VGS ] = str_to_str_list ( mem , args - > single_args [ REPORT_IDX_FULL_VGS ] . options , " , " , 1 ) ) | |
! ( final_opts_list [ REPORT_IDX_FULL_PVS ] = str_to_str_list ( mem , args - > single_args [ REPORT_IDX_FULL_PVS ] . options , " , " , 1 ) ) | |
! ( final_opts_list [ REPORT_IDX_FULL_LVS ] = str_to_str_list ( mem , args - > single_args [ REPORT_IDX_FULL_LVS ] . options , " , " , 1 ) ) | |
! ( final_opts_list [ REPORT_IDX_FULL_PVSEGS ] = str_to_str_list ( mem , args - > single_args [ REPORT_IDX_FULL_PVSEGS ] . options , " , " , 1 ) ) | |
! ( final_opts_list [ REPORT_IDX_FULL_SEGS ] = str_to_str_list ( mem , args - > single_args [ REPORT_IDX_FULL_SEGS ] . options , " , " , 1 ) ) )
goto_out ;
} else {
if ( ! ( final_opts_list [ REPORT_IDX_SINGLE ] = str_to_str_list ( mem , single_args - > options , " , " , 1 ) ) )
goto_out ;
2015-10-20 17:36:11 +03:00
}
2015-10-21 15:57:49 +03:00
dm_list_iterate_items ( current_group , & cmd - > arg_value_groups ) {
if ( ! grouped_arg_is_set ( current_group - > arg_values , options_ARG ) )
continue ;
2016-05-04 15:07:45 +03:00
if ( grouped_arg_is_set ( current_group - > arg_values , configreport_ARG ) ) {
report_name = grouped_arg_str_value ( current_group - > arg_values , configreport_ARG , NULL ) ;
if ( ( idx = _get_report_idx_from_name ( single_args - > report_type , report_name ) ) = = REPORT_IDX_NULL )
goto_out ;
}
2015-10-21 15:57:49 +03:00
opts = grouped_arg_str_value ( current_group - > arg_values , options_ARG , NULL ) ;
if ( ! opts | | ! * opts ) {
log_error ( " Invalid options string: %s " , opts ) ;
r = EINVALID_CMD_LINE ;
goto out ;
2015-10-20 17:36:11 +03:00
}
2015-10-21 15:57:49 +03:00
switch ( * opts ) {
case ' + ' :
2016-05-04 15:07:45 +03:00
action = OPTS_ADD ;
opts + + ;
break ;
2015-10-21 16:36:26 +03:00
case ' - ' :
2016-05-04 15:07:45 +03:00
action = OPTS_REMOVE ;
opts + + ;
break ;
2015-10-22 16:37:27 +03:00
case ' # ' :
2016-05-04 15:07:45 +03:00
action = OPTS_COMPACT ;
opts + + ;
2015-10-21 15:57:49 +03:00
break ;
default :
2016-05-04 15:07:45 +03:00
action = OPTS_REPLACE ;
2015-10-21 15:57:49 +03:00
}
2016-06-27 11:14:17 +03:00
if ( ! _should_process_report_idx ( single_args - > report_type , ! ( single_args - > report_type & ( CMDLOG | FULL ) ) , idx ) )
2016-05-04 15:07:45 +03:00
continue ;
if ( ( action ! = OPTS_COMPACT ) & &
! ( opts_list = str_to_str_list ( mem , opts , " , " , 1 ) ) )
goto_out ;
switch ( action ) {
case OPTS_ADD :
dm_list_splice ( final_opts_list [ idx ] , opts_list ) ;
break ;
case OPTS_REMOVE :
dm_list_iterate_items ( sl , opts_list )
_del_option_from_list ( final_opts_list [ idx ] , args - > single_args [ idx ] . report_prefix ,
strlen ( args - > single_args [ idx ] . report_prefix ) , sl - > str ) ;
break ;
case OPTS_COMPACT :
args - > single_args [ idx ] . fields_to_compact = opts ;
break ;
case OPTS_REPLACE :
final_opts_list [ idx ] = opts_list ;
break ;
}
2015-10-21 15:57:49 +03:00
}
2016-05-04 15:07:45 +03:00
if ( single_args - > report_type = = CMDLOG ) {
if ( ! ( single_args - > options = str_list_to_str ( cmd - > mem , final_opts_list [ REPORT_IDX_LOG ] , " , " ) ) )
goto_out ;
} else if ( single_args - > report_type = = FULL ) {
if ( ! ( args - > single_args [ REPORT_IDX_FULL_VGS ] . options = str_list_to_str ( cmd - > mem , final_opts_list [ REPORT_IDX_FULL_VGS ] , " , " ) ) | |
! ( args - > single_args [ REPORT_IDX_FULL_PVS ] . options = str_list_to_str ( cmd - > mem , final_opts_list [ REPORT_IDX_FULL_PVS ] , " , " ) ) | |
! ( args - > single_args [ REPORT_IDX_FULL_LVS ] . options = str_list_to_str ( cmd - > mem , final_opts_list [ REPORT_IDX_FULL_LVS ] , " , " ) ) | |
! ( args - > single_args [ REPORT_IDX_FULL_PVSEGS ] . options = str_list_to_str ( cmd - > mem , final_opts_list [ REPORT_IDX_FULL_PVSEGS ] , " , " ) ) | |
! ( args - > single_args [ REPORT_IDX_FULL_SEGS ] . options = str_list_to_str ( cmd - > mem , final_opts_list [ REPORT_IDX_FULL_SEGS ] , " , " ) ) )
goto_out ;
} else {
if ( ! ( single_args - > options = str_list_to_str ( cmd - > mem , final_opts_list [ REPORT_IDX_SINGLE ] , " , " ) ) )
goto_out ;
2015-10-22 16:37:27 +03:00
}
2016-05-04 15:07:45 +03:00
r = ECMD_PROCESSED ;
2015-10-21 15:57:49 +03:00
out :
2015-11-12 00:07:39 +03:00
dm_pool_destroy ( mem ) ;
2015-10-21 15:57:49 +03:00
return r ;
2015-10-20 17:36:11 +03:00
}
2016-05-25 14:41:42 +03:00
static int _get_report_keys ( struct cmd_context * cmd ,
struct report_args * args ,
struct single_report_args * single_args )
{
2016-05-26 16:12:38 +03:00
struct arg_value_group_list * current_group ;
const char * report_name = NULL ;
report_idx_t idx = REPORT_IDX_SINGLE ;
int r = ECMD_FAILED ;
2016-05-25 14:41:42 +03:00
2016-05-26 16:12:38 +03:00
dm_list_iterate_items ( current_group , & cmd - > arg_value_groups ) {
if ( ! grouped_arg_is_set ( current_group - > arg_values , sort_ARG ) )
continue ;
2016-05-25 14:41:42 +03:00
2016-05-26 16:12:38 +03:00
if ( grouped_arg_is_set ( current_group - > arg_values , configreport_ARG ) ) {
report_name = grouped_arg_str_value ( current_group - > arg_values , configreport_ARG , NULL ) ;
if ( ( idx = _get_report_idx_from_name ( single_args - > report_type , report_name ) ) = = REPORT_IDX_NULL )
goto_out ;
}
2016-06-27 11:14:17 +03:00
if ( ! _should_process_report_idx ( single_args - > report_type , ! ( single_args - > report_type & ( CMDLOG | FULL ) ) , idx ) )
continue ;
2016-05-26 16:12:38 +03:00
args - > single_args [ idx ] . keys = grouped_arg_str_value ( current_group - > arg_values , sort_ARG , NULL ) ;
}
r = ECMD_PROCESSED ;
out :
2016-05-25 14:41:42 +03:00
return r ;
}
2016-05-26 16:20:27 +03:00
static int _do_report_get_selection ( struct cmd_context * cmd ,
2016-06-27 11:14:17 +03:00
report_type_t report_type ,
int allow_single ,
2016-05-26 16:20:27 +03:00
struct report_args * args ,
2016-06-27 11:14:17 +03:00
const char * * last_selection )
2016-05-26 16:20:27 +03:00
{
struct arg_value_group_list * current_group ;
2016-06-27 11:14:17 +03:00
const char * final_selection = NULL , * selection = NULL ;
2016-05-26 16:20:27 +03:00
const char * report_name = NULL ;
report_idx_t idx = REPORT_IDX_SINGLE ;
dm_list_iterate_items ( current_group , & cmd - > arg_value_groups ) {
if ( ! grouped_arg_is_set ( current_group - > arg_values , select_ARG ) )
continue ;
if ( grouped_arg_is_set ( current_group - > arg_values , configreport_ARG ) ) {
report_name = grouped_arg_str_value ( current_group - > arg_values , configreport_ARG , NULL ) ;
2016-06-27 11:14:17 +03:00
if ( ( idx = _get_report_idx_from_name ( report_type , report_name ) ) = = REPORT_IDX_NULL )
2016-05-26 16:20:27 +03:00
return_0 ;
}
selection = grouped_arg_str_value ( current_group - > arg_values , select_ARG , NULL ) ;
2016-06-27 11:14:17 +03:00
if ( ! _should_process_report_idx ( report_type , allow_single , idx ) )
continue ;
if ( args )
2016-05-26 16:20:27 +03:00
args - > single_args [ idx ] . selection = selection ;
2016-06-27 11:14:17 +03:00
final_selection = selection ;
2016-05-26 16:20:27 +03:00
}
2016-06-27 11:14:17 +03:00
if ( last_selection )
* last_selection = final_selection ;
2016-05-26 16:20:27 +03:00
return 1 ;
}
2016-05-25 14:41:42 +03:00
static int _get_report_selection ( struct cmd_context * cmd ,
struct report_args * args ,
struct single_report_args * single_args )
{
2016-06-27 11:14:17 +03:00
return _do_report_get_selection ( cmd , single_args - > report_type , ! ( single_args - > report_type & ( CMDLOG | FULL ) ) ,
args , NULL ) ? ECMD_PROCESSED : ECMD_FAILED ;
2016-05-26 16:20:27 +03:00
}
2016-05-25 14:41:42 +03:00
2016-06-27 11:14:17 +03:00
int report_get_single_selection ( struct cmd_context * cmd , report_type_t report_type , const char * * selection )
2016-05-26 16:20:27 +03:00
{
2016-06-27 11:14:17 +03:00
return _do_report_get_selection ( cmd , report_type , 1 , NULL , selection ) ;
2016-05-25 14:41:42 +03:00
}
2016-06-14 17:44:52 +03:00
static int _set_report_prefix_and_name ( struct report_args * args ,
struct single_report_args * single_args )
2016-05-02 15:37:16 +03:00
{
2016-06-14 17:44:52 +03:00
const char * report_prefix , * report_desc ;
2016-05-02 15:37:16 +03:00
size_t len ;
2016-05-03 12:18:16 +03:00
if ( single_args - > report_type = = FULL ) {
single_args - > report_prefix [ 0 ] = ' \0 ' ;
single_args - > report_name = single_args - > report_prefix ;
return 1 ;
}
2016-06-14 17:44:52 +03:00
( void ) report_get_prefix_and_desc ( single_args - > report_type ,
& report_prefix , & report_desc ) ;
2016-05-02 15:37:16 +03:00
len = strlen ( report_prefix ) ;
if ( report_prefix [ len - 1 ] = = ' _ ' )
len - - ;
if ( ! len ) {
log_error ( INTERNAL_ERROR " _set_report_prefix_and_name: no prefix "
" found for report type 0x%x " , single_args - > report_type ) ;
return 0 ;
}
2024-04-04 19:42:24 +03:00
if ( ! _dm_strncpy ( single_args - > report_prefix , report_prefix , sizeof ( single_args - > report_prefix ) ) ) {
2016-05-02 15:37:16 +03:00
log_error ( " _set_report_prefix_and_name: dm_strncpy failed " ) ;
return 0 ;
}
single_args - > report_prefix [ len ] = ' \0 ' ;
2016-06-14 17:44:52 +03:00
if ( args - > report_group_type ! = DM_REPORT_GROUP_BASIC )
single_args - > report_name = single_args - > report_prefix ;
else
single_args - > report_name = report_desc ;
2016-05-02 15:37:16 +03:00
return 1 ;
}
2016-05-03 12:18:16 +03:00
static int _do_report ( struct cmd_context * cmd , struct processing_handle * handle ,
struct report_args * args , struct single_report_args * single_args )
2002-12-12 23:55:49 +03:00
{
2016-05-03 12:18:16 +03:00
void * orig_custom_handle = handle - > custom_handle ;
2016-05-25 14:41:42 +03:00
report_type_t report_type = single_args - > report_type ;
2016-05-10 14:57:23 +03:00
void * report_handle = NULL ;
int lv_info_needed ;
int lv_segment_status_needed ;
2016-05-03 12:18:16 +03:00
int report_in_group = 0 ;
2016-05-10 14:57:23 +03:00
int r = ECMD_FAILED ;
2014-05-29 11:38:59 +04:00
2016-05-25 14:41:42 +03:00
if ( ! ( report_handle = report_init ( cmd , single_args - > options , single_args - > keys , & report_type ,
2016-05-10 14:57:23 +03:00
args - > separator , args - > aligned , args - > buffered ,
args - > headings , args - > field_prefixes , args - > quoted ,
2016-05-12 15:37:38 +03:00
args - > columns_as_rows , single_args - > selection , 0 ) ) )
2016-04-08 12:01:19 +03:00
goto_out ;
handle - > custom_handle = report_handle ;
2002-12-12 23:55:49 +03:00
2016-05-03 12:42:55 +03:00
if ( ! _get_final_report_type ( args , single_args , report_type , & lv_info_needed ,
& lv_segment_status_needed , & report_type ) )
2016-04-08 12:01:19 +03:00
goto_out ;
2007-01-16 21:06:12 +03:00
2016-06-15 14:35:27 +03:00
if ( ! ( args - > log_only & & ( single_args - > report_type ! = CMDLOG ) ) ) {
2016-08-03 16:37:14 +03:00
if ( ! dm_report_group_push ( cmd - > cmd_report . report_group , report_handle , ( void * ) single_args - > report_name ) )
2016-05-03 12:18:16 +03:00
goto_out ;
report_in_group = 1 ;
}
2016-05-02 15:37:16 +03:00
2002-12-12 23:55:49 +03:00
switch ( report_type ) {
2016-05-10 14:57:23 +03:00
case DEVTYPES :
r = _process_each_devtype ( cmd , args - > argc , handle ) ;
break ;
case LVSINFO :
/* fall through */
case LVSSTATUS :
/* fall through */
case LVSINFOSTATUS :
/* fall through */
case LVS :
2016-05-03 12:18:16 +03:00
if ( args - > full_report_vg )
r = _report_all_in_vg ( cmd , handle , args - > full_report_vg , LVS , lv_info_needed , lv_segment_status_needed ) ;
else
2016-11-29 21:00:15 +03:00
r = process_each_lv ( cmd , args - > argc , args - > argv , NULL , NULL , 0 , handle , NULL ,
2016-05-03 12:18:16 +03:00
lv_info_needed & & ! lv_segment_status_needed ? & _lvs_with_info_single :
! lv_info_needed & & lv_segment_status_needed ? & _lvs_with_status_single :
lv_info_needed & & lv_segment_status_needed ? & _lvs_with_info_and_status_single :
& _lvs_single ) ;
2016-05-10 14:57:23 +03:00
break ;
case VGS :
2016-05-03 12:18:16 +03:00
if ( args - > full_report_vg )
r = _report_all_in_vg ( cmd , handle , args - > full_report_vg , VGS , lv_info_needed , lv_segment_status_needed ) ;
else
2016-05-03 12:46:28 +03:00
r = process_each_vg ( cmd , args - > argc , args - > argv , NULL , NULL ,
0 , 0 , handle , & _vgs_single ) ;
2016-05-10 14:57:23 +03:00
break ;
case LABEL :
r = process_each_label ( cmd , args - > argc , args - > argv ,
handle , & _label_single ) ;
break ;
case PVS :
2016-05-03 12:18:16 +03:00
if ( args - > full_report_vg )
r = _report_all_in_vg ( cmd , handle , args - > full_report_vg , PVS , lv_info_needed , lv_segment_status_needed ) ;
else {
if ( single_args - > args_are_pvs )
r = process_each_pv ( cmd , args - > argc , args - > argv , NULL ,
arg_is_set ( cmd , all_ARG ) , 0 ,
handle , & _pvs_single ) ;
else
r = process_each_vg ( cmd , args - > argc , args - > argv , NULL , NULL ,
2016-05-03 12:46:28 +03:00
0 , 0 , handle , & _pvs_in_vg ) ;
2016-05-03 12:18:16 +03:00
}
2016-05-10 14:57:23 +03:00
break ;
case SEGS :
2016-05-03 12:18:16 +03:00
if ( args - > full_report_vg )
r = _report_all_in_vg ( cmd , handle , args - > full_report_vg , SEGS , lv_info_needed , lv_segment_status_needed ) ;
else
2016-11-29 21:00:15 +03:00
r = process_each_lv ( cmd , args - > argc , args - > argv , NULL , NULL , 0 , handle , NULL ,
2016-05-03 12:18:16 +03:00
lv_info_needed & & ! lv_segment_status_needed ? & _lvsegs_with_info_single :
! lv_info_needed & & lv_segment_status_needed ? & _lvsegs_with_status_single :
lv_info_needed & & lv_segment_status_needed ? & _lvsegs_with_info_and_status_single :
& _lvsegs_single ) ;
2016-05-10 14:57:23 +03:00
break ;
case PVSEGS :
2016-05-03 12:18:16 +03:00
if ( args - > full_report_vg )
r = _report_all_in_vg ( cmd , handle , args - > full_report_vg , PVSEGS , lv_info_needed , lv_segment_status_needed ) ;
else {
if ( single_args - > args_are_pvs )
r = process_each_pv ( cmd , args - > argc , args - > argv , NULL ,
arg_is_set ( cmd , all_ARG ) , 0 ,
handle ,
lv_info_needed & & ! lv_segment_status_needed ? & _pvsegs_with_lv_info_single :
! lv_info_needed & & lv_segment_status_needed ? & _pvsegs_with_lv_status_single :
lv_info_needed & & lv_segment_status_needed ? & _pvsegs_with_lv_info_and_status_single :
2016-05-10 14:57:23 +03:00
& _pvsegs_single ) ;
2016-05-03 12:18:16 +03:00
else
r = process_each_vg ( cmd , args - > argc , args - > argv , NULL , NULL ,
2016-05-03 12:46:28 +03:00
0 , 0 , handle , & _pvsegs_in_vg ) ;
2016-05-03 12:18:16 +03:00
}
break ;
case FULL :
/*
* Full report ' s subreports already covered by combinations above with args - > full_report_vg .
* We shouldn ' t see report_type = = FULL in this function .
*/
log_error ( INTERNAL_ERROR " _do_report: full report requested at incorrect level " ) ;
2016-05-10 14:57:23 +03:00
break ;
2016-05-10 16:15:48 +03:00
case CMDLOG :
/* Log is reported throughout the code via report_cmdlog calls. */
break ;
2016-05-10 14:57:23 +03:00
default :
log_error ( INTERNAL_ERROR " _do_report: unknown report type. " ) ;
return 0 ;
2002-12-12 23:55:49 +03:00
}
2015-10-16 17:25:51 +03:00
if ( find_config_tree_bool ( cmd , report_compact_output_CFG , NULL ) ) {
if ( ! dm_report_compact_fields ( report_handle ) )
log_error ( " Failed to compact report output. " ) ;
2016-05-25 14:41:42 +03:00
} else if ( single_args - > fields_to_compact ) {
if ( ! dm_report_compact_given_fields ( report_handle , single_args - > fields_to_compact ) )
2015-10-16 17:25:51 +03:00
log_error ( " Failed to compact given columns in report output. " ) ;
}
2014-12-05 13:46:26 +03:00
2016-06-15 14:35:27 +03:00
if ( ! ( args - > log_only & & ( single_args - > report_type ! = CMDLOG ) ) )
dm_report_output ( report_handle ) ;
2002-12-12 23:55:49 +03:00
2016-04-08 12:01:19 +03:00
out :
2016-05-03 12:18:16 +03:00
if ( report_handle ) {
2016-08-03 16:37:14 +03:00
if ( report_in_group & & ! dm_report_group_pop ( cmd - > cmd_report . report_group ) )
2016-05-03 12:18:16 +03:00
stack ;
2016-04-08 12:01:19 +03:00
dm_report_free ( report_handle ) ;
2016-05-03 12:18:16 +03:00
}
handle - > custom_handle = orig_custom_handle ;
2003-10-22 02:06:07 +04:00
return r ;
2002-12-12 23:55:49 +03:00
}
2016-05-03 12:18:16 +03:00
static int _full_report_single ( struct cmd_context * cmd ,
const char * vg_name ,
struct volume_group * vg ,
struct processing_handle * handle )
{
struct report_args * args = ( struct report_args * ) handle - > custom_handle ;
int orphan = is_orphan_vg ( vg - > name ) ;
int r = ECMD_FAILED ;
2021-10-01 15:30:49 +03:00
if ( orphan & & dm_list_empty ( & vg - > pvs ) )
2016-05-03 12:18:16 +03:00
return ECMD_PROCESSED ;
args - > full_report_vg = vg ;
2016-08-03 16:37:14 +03:00
if ( ! args - > log_only & & ! dm_report_group_push ( cmd - > cmd_report . report_group , NULL , NULL ) )
2016-05-03 12:18:16 +03:00
goto out ;
if ( orphan ) {
if ( ( ( r = _do_report ( cmd , handle , args , & args - > single_args [ REPORT_IDX_FULL_PVS ] ) ) ! = ECMD_PROCESSED ) | |
( ( r = _do_report ( cmd , handle , args , & args - > single_args [ REPORT_IDX_FULL_PVSEGS ] ) ) ! = ECMD_PROCESSED ) )
stack ;
} else {
if ( ( ( r = _do_report ( cmd , handle , args , & args - > single_args [ REPORT_IDX_FULL_VGS ] ) ) ! = ECMD_PROCESSED ) | |
( ( r = _do_report ( cmd , handle , args , & args - > single_args [ REPORT_IDX_FULL_PVS ] ) ) ! = ECMD_PROCESSED ) | |
( ( r = _do_report ( cmd , handle , args , & args - > single_args [ REPORT_IDX_FULL_LVS ] ) ) ! = ECMD_PROCESSED ) | |
( ( r = _do_report ( cmd , handle , args , & args - > single_args [ REPORT_IDX_FULL_PVSEGS ] ) ) ! = ECMD_PROCESSED ) | |
( ( r = _do_report ( cmd , handle , args , & args - > single_args [ REPORT_IDX_FULL_SEGS ] ) ) ! = ECMD_PROCESSED ) )
stack ;
}
2016-08-03 16:37:14 +03:00
if ( ! args - > log_only & & ! dm_report_group_pop ( cmd - > cmd_report . report_group ) )
2016-05-03 12:18:16 +03:00
goto_out ;
out :
args - > full_report_vg = NULL ;
return r ;
}
2016-06-14 13:38:40 +03:00
# define _set_full_report_single(cmd,args,type,name) \
2016-05-03 12:18:16 +03:00
do { \
2017-07-19 17:17:30 +03:00
( args ) - > single_args [ REPORT_IDX_FULL_ # # type ] . report_type = type ; \
( args ) - > single_args [ REPORT_IDX_FULL_ # # type ] . keys = find_config_tree_str ( cmd , report_ # # name # # _sort_full_CFG , NULL ) ; \
( args ) - > single_args [ REPORT_IDX_FULL_ # # type ] . options = find_config_tree_str ( cmd , report_ # # name # # _cols_full_CFG , NULL ) ; \
if ( ! _set_report_prefix_and_name ( ( args ) , & ( args ) - > single_args [ REPORT_IDX_FULL_ # # type ] ) ) \
2016-05-03 12:18:16 +03:00
return_0 ; \
} while ( 0 )
2016-05-25 14:41:42 +03:00
static int _config_report ( struct cmd_context * cmd , struct report_args * args , struct single_report_args * single_args )
2016-05-10 14:57:23 +03:00
{
2023-08-22 11:54:35 +03:00
const char * str ;
2016-05-23 12:18:50 +03:00
args - > aligned = find_config_tree_bool ( cmd , report_aligned_CFG , NULL ) ;
args - > buffered = find_config_tree_bool ( cmd , report_buffered_CFG , NULL ) ;
2023-08-22 11:54:35 +03:00
args - > headings = find_config_tree_int ( cmd , report_headings_CFG , NULL ) ;
2016-05-23 12:18:50 +03:00
args - > separator = find_config_tree_str ( cmd , report_separator_CFG , NULL ) ;
args - > field_prefixes = find_config_tree_bool ( cmd , report_prefixes_CFG , NULL ) ;
args - > quoted = find_config_tree_bool ( cmd , report_quoted_CFG , NULL ) ;
2016-08-25 15:53:32 +03:00
args - > columns_as_rows = find_config_tree_bool ( cmd , report_columns_as_rows_CFG , NULL ) ;
2016-05-10 14:57:23 +03:00
/* Check PV specifics and do extra changes/actions if needed. */
2016-05-25 14:41:42 +03:00
_check_pv_list ( cmd , args , single_args ) ;
2016-05-10 14:57:23 +03:00
2016-06-14 17:44:52 +03:00
if ( ! _set_report_prefix_and_name ( args , single_args ) )
2016-05-02 15:37:16 +03:00
return_0 ;
2016-05-25 14:41:42 +03:00
switch ( single_args - > report_type ) {
2016-05-10 14:57:23 +03:00
case DEVTYPES :
2016-05-25 14:41:42 +03:00
single_args - > keys = find_config_tree_str ( cmd , report_devtypes_sort_CFG , NULL ) ;
2016-06-22 00:24:52 +03:00
if ( ! arg_is_set ( cmd , verbose_ARG ) )
2016-05-25 14:41:42 +03:00
single_args - > options = find_config_tree_str ( cmd , report_devtypes_cols_CFG , NULL ) ;
2016-05-10 14:57:23 +03:00
else
2016-05-25 14:41:42 +03:00
single_args - > options = find_config_tree_str ( cmd , report_devtypes_cols_verbose_CFG , NULL ) ;
2016-05-10 14:57:23 +03:00
break ;
case LVS :
2016-05-25 14:41:42 +03:00
single_args - > keys = find_config_tree_str ( cmd , report_lvs_sort_CFG , NULL ) ;
2016-06-22 00:24:52 +03:00
if ( ! arg_is_set ( cmd , verbose_ARG ) )
2016-05-25 14:41:42 +03:00
single_args - > options = find_config_tree_str ( cmd , report_lvs_cols_CFG , NULL ) ;
2016-05-10 14:57:23 +03:00
else
2016-05-25 14:41:42 +03:00
single_args - > options = find_config_tree_str ( cmd , report_lvs_cols_verbose_CFG , NULL ) ;
2016-05-10 14:57:23 +03:00
break ;
case VGS :
2016-05-25 14:41:42 +03:00
single_args - > keys = find_config_tree_str ( cmd , report_vgs_sort_CFG , NULL ) ;
2016-06-22 00:24:52 +03:00
if ( ! arg_is_set ( cmd , verbose_ARG ) )
2016-05-25 14:41:42 +03:00
single_args - > options = find_config_tree_str ( cmd , report_vgs_cols_CFG , NULL ) ;
2016-05-10 14:57:23 +03:00
else
2016-05-25 14:41:42 +03:00
single_args - > options = find_config_tree_str ( cmd , report_vgs_cols_verbose_CFG , NULL ) ;
2016-05-10 14:57:23 +03:00
break ;
case LABEL :
case PVS :
2016-05-25 14:41:42 +03:00
single_args - > keys = find_config_tree_str ( cmd , report_pvs_sort_CFG , NULL ) ;
2016-06-22 00:24:52 +03:00
if ( ! arg_is_set ( cmd , verbose_ARG ) )
2016-05-25 14:41:42 +03:00
single_args - > options = find_config_tree_str ( cmd , report_pvs_cols_CFG , NULL ) ;
2016-05-10 14:57:23 +03:00
else
2016-05-25 14:41:42 +03:00
single_args - > options = find_config_tree_str ( cmd , report_pvs_cols_verbose_CFG , NULL ) ;
2016-05-10 14:57:23 +03:00
break ;
case SEGS :
2016-05-25 14:41:42 +03:00
single_args - > keys = find_config_tree_str ( cmd , report_segs_sort_CFG , NULL ) ;
2016-06-22 00:24:52 +03:00
if ( ! arg_is_set ( cmd , verbose_ARG ) )
2016-05-25 14:41:42 +03:00
single_args - > options = find_config_tree_str ( cmd , report_segs_cols_CFG , NULL ) ;
2016-05-10 14:57:23 +03:00
else
2016-05-25 14:41:42 +03:00
single_args - > options = find_config_tree_str ( cmd , report_segs_cols_verbose_CFG , NULL ) ;
2016-05-10 14:57:23 +03:00
break ;
case PVSEGS :
2016-05-25 14:41:42 +03:00
single_args - > keys = find_config_tree_str ( cmd , report_pvsegs_sort_CFG , NULL ) ;
2016-06-22 00:24:52 +03:00
if ( ! arg_is_set ( cmd , verbose_ARG ) )
2016-05-25 14:41:42 +03:00
single_args - > options = find_config_tree_str ( cmd , report_pvsegs_cols_CFG , NULL ) ;
2016-05-10 14:57:23 +03:00
else
2016-05-25 14:41:42 +03:00
single_args - > options = find_config_tree_str ( cmd , report_pvsegs_cols_verbose_CFG , NULL ) ;
2016-05-10 14:57:23 +03:00
break ;
2016-05-03 12:18:16 +03:00
case FULL :
2016-06-14 13:38:40 +03:00
_set_full_report_single ( cmd , args , VGS , vgs ) ;
_set_full_report_single ( cmd , args , LVS , lvs ) ;
_set_full_report_single ( cmd , args , PVS , pvs ) ;
_set_full_report_single ( cmd , args , PVSEGS , pvsegs ) ;
_set_full_report_single ( cmd , args , SEGS , segs ) ;
2016-05-03 12:18:16 +03:00
break ;
2016-05-10 16:15:48 +03:00
case CMDLOG :
2016-05-25 14:41:42 +03:00
single_args - > keys = find_config_tree_str ( cmd , log_command_log_sort_CFG , NULL ) ;
single_args - > options = find_config_tree_str ( cmd , log_command_log_cols_CFG , NULL ) ;
2016-06-14 14:25:03 +03:00
single_args - > selection = find_config_tree_str ( cmd , log_command_log_selection_CFG , NULL ) ;
2016-05-10 16:15:48 +03:00
break ;
2016-05-10 14:57:23 +03:00
default :
log_error ( INTERNAL_ERROR " _report: unknown report type. " ) ;
return 0 ;
}
2016-05-03 12:18:16 +03:00
if ( single_args - > report_type ! = FULL )
single_args - > fields_to_compact = find_config_tree_str_allow_empty ( cmd , report_compact_output_cols_CFG , NULL ) ;
2016-05-25 14:41:42 +03:00
2016-05-10 14:57:23 +03:00
/* If -o supplied use it, else use default for report_type */
2016-05-25 14:41:42 +03:00
if ( ( _get_report_options ( cmd , args , single_args ) ! = ECMD_PROCESSED ) )
2016-05-10 14:57:23 +03:00
return_0 ;
/* -O overrides default sort settings */
2016-05-25 14:41:42 +03:00
if ( ( _get_report_keys ( cmd , args , single_args ) ! = ECMD_PROCESSED ) )
return_0 ;
if ( ( _get_report_selection ( cmd , args , single_args ) ! = ECMD_PROCESSED ) )
return_0 ;
2016-05-10 14:57:23 +03:00
2016-05-23 12:18:50 +03:00
args - > separator = arg_str_value ( cmd , separator_ARG , args - > separator ) ;
2016-06-22 00:24:52 +03:00
if ( arg_is_set ( cmd , separator_ARG ) )
2016-05-23 12:18:50 +03:00
args - > aligned = 0 ;
2016-06-22 00:24:52 +03:00
if ( arg_is_set ( cmd , aligned_ARG ) )
2016-05-23 12:18:50 +03:00
args - > aligned = 1 ;
2016-06-22 00:24:52 +03:00
if ( arg_is_set ( cmd , unbuffered_ARG ) & & ! arg_is_set ( cmd , sort_ARG ) )
2016-05-23 12:18:50 +03:00
args - > buffered = 0 ;
2016-06-22 00:24:52 +03:00
if ( arg_is_set ( cmd , noheadings_ARG ) )
2023-08-22 11:54:35 +03:00
args - > headings = REPORT_HEADINGS_NONE ;
if ( ( str = arg_str_value ( cmd , headings_ARG , NULL ) ) ) {
if ( ( args - > headings = report_headings_str_to_type ( str ) ) = = REPORT_HEADINGS_UNKNOWN ) {
log_error ( " Unknown --headings value. " ) ;
return 0 ;
}
}
2016-06-22 00:24:52 +03:00
if ( arg_is_set ( cmd , nameprefixes_ARG ) ) {
2016-05-23 12:18:50 +03:00
args - > aligned = 0 ;
args - > field_prefixes = 1 ;
2016-05-10 14:57:23 +03:00
}
2016-06-22 00:24:52 +03:00
if ( arg_is_set ( cmd , unquoted_ARG ) )
2016-05-23 12:18:50 +03:00
args - > quoted = 0 ;
2016-06-22 00:24:52 +03:00
if ( arg_is_set ( cmd , rows_ARG ) )
2016-05-23 12:18:50 +03:00
args - > columns_as_rows = 1 ;
2016-05-10 14:57:23 +03:00
2016-05-23 12:18:50 +03:00
return 1 ;
}
static int _report ( struct cmd_context * cmd , int argc , char * * argv , report_type_t report_type )
{
struct report_args args = { 0 } ;
2016-05-25 14:41:42 +03:00
struct single_report_args * single_args = & args . single_args [ REPORT_IDX_SINGLE ] ;
2016-05-03 12:18:16 +03:00
static char report_name [ ] = " report " ;
struct processing_handle * handle ;
2017-06-27 12:38:56 +03:00
int r ;
2016-05-23 12:18:50 +03:00
/*
* Include foreign VGs that contain active LVs .
* That shouldn ' t happen in general , but if it does by some
* mistake , then we want to display those VGs and allow the
* LVs to be deactivated .
*/
cmd - > include_active_foreign_vgs = 1 ;
args . argc = argc ;
args . argv = argv ;
2016-05-25 14:41:42 +03:00
single_args - > report_type = report_type ;
2016-05-23 12:18:50 +03:00
2016-05-03 12:18:16 +03:00
if ( ! ( handle = init_processing_handle ( cmd , NULL ) ) )
2016-05-23 12:18:50 +03:00
return_ECMD_FAILED ;
2016-05-10 14:57:23 +03:00
2016-05-03 12:18:16 +03:00
handle - > internal_report_for_select = 0 ;
handle - > include_historical_lvs = cmd - > include_historical_lvs ;
2016-08-03 16:37:14 +03:00
args . report_group_type = cmd - > cmd_report . report_group_type ;
args . log_only = cmd - > cmd_report . log_only ;
2016-05-03 12:18:16 +03:00
if ( ! _config_report ( cmd , & args , single_args ) ) {
destroy_processing_handle ( cmd , handle ) ;
return_ECMD_FAILED ;
}
2016-08-03 16:37:14 +03:00
if ( ! args . log_only & & ! dm_report_group_push ( cmd - > cmd_report . report_group , NULL , report_name ) ) {
2016-05-03 12:18:16 +03:00
log_error ( " Failed to add main report section to report group. " ) ;
destroy_processing_handle ( cmd , handle ) ;
return ECMD_FAILED ;
}
if ( single_args - > report_type = = FULL ) {
handle - > custom_handle = & args ;
2016-05-03 12:46:28 +03:00
r = process_each_vg ( cmd , argc , argv , NULL , NULL , 0 , 1 , handle , & _full_report_single ) ;
2016-05-03 12:18:16 +03:00
} else
r = _do_report ( cmd , handle , & args , single_args ) ;
2016-08-04 14:42:57 +03:00
if ( ! args . log_only & & ! dm_report_group_pop ( cmd - > cmd_report . report_group ) ) {
log_error ( " Failed to finalize main report section in report group. " ) ;
r = ECMD_FAILED ;
}
2016-05-03 12:18:16 +03:00
destroy_processing_handle ( cmd , handle ) ;
return r ;
2016-05-10 14:57:23 +03:00
}
2002-12-12 23:55:49 +03:00
int lvs ( struct cmd_context * cmd , int argc , char * * argv )
{
report_type_t type ;
2016-06-22 00:24:52 +03:00
if ( arg_is_set ( cmd , segments_ARG ) )
2002-12-12 23:55:49 +03:00
type = SEGS ;
else
type = LVS ;
return _report ( cmd , argc , argv , type ) ;
}
int vgs ( struct cmd_context * cmd , int argc , char * * argv )
{
return _report ( cmd , argc , argv , VGS ) ;
}
int pvs ( struct cmd_context * cmd , int argc , char * * argv )
{
2005-04-20 00:58:25 +04:00
report_type_t type ;
2018-12-07 23:35:22 +03:00
/*
* Without - a , command only looks at PVs and can use hints ,
* with - a , the command looks at all ( non - hinted ) devices .
*/
if ( arg_is_set ( cmd , all_ARG ) )
cmd - > use_hints = 0 ;
2023-11-11 01:24:45 +03:00
if ( arg_is_set ( cmd , allpvs_ARG ) ) {
cmd - > filter_deviceid_skip = 1 ;
cmd - > use_hints = 0 ;
}
2016-06-22 00:24:52 +03:00
if ( arg_is_set ( cmd , segments_ARG ) )
2005-04-20 00:58:25 +04:00
type = PVSEGS ;
else
2009-02-09 12:45:49 +03:00
type = LABEL ;
2005-04-20 00:58:25 +04:00
return _report ( cmd , argc , argv , type ) ;
2002-12-12 23:55:49 +03:00
}
2013-09-18 04:09:15 +04:00
2016-05-03 12:18:16 +03:00
int fullreport ( struct cmd_context * cmd , int argc , char * * argv )
{
return _report ( cmd , argc , argv , FULL ) ;
}
2013-09-18 04:09:15 +04:00
int devtypes ( struct cmd_context * cmd , int argc , char * * argv )
{
return _report ( cmd , argc , argv , DEVTYPES ) ;
}
2016-05-02 15:22:02 +03:00
# define REPORT_FORMAT_NAME_BASIC "basic"
# define REPORT_FORMAT_NAME_JSON "json"
2022-08-04 17:42:54 +03:00
# define REPORT_FORMAT_NAME_JSON_STD "json_std"
2016-05-02 15:22:02 +03:00
2016-08-03 16:37:14 +03:00
int report_format_init ( struct cmd_context * cmd )
2016-05-02 15:22:02 +03:00
{
2016-05-24 13:05:42 +03:00
int config_set = find_config_tree_node ( cmd , report_output_format_CFG , NULL ) ! = NULL ;
const char * config_format_str = find_config_tree_str ( cmd , report_output_format_CFG , NULL ) ;
const char * format_str = arg_str_value ( cmd , reportformat_ARG , config_set ? config_format_str : NULL ) ;
2016-06-15 14:35:27 +03:00
int report_command_log ;
2016-05-02 15:22:02 +03:00
struct report_args args = { 0 } ;
2016-05-25 14:41:42 +03:00
struct single_report_args * single_args ;
2016-05-02 15:22:02 +03:00
struct dm_report_group * new_report_group ;
struct dm_report * tmp_log_rh = NULL ;
2016-08-03 16:37:14 +03:00
args . log_only = arg_is_set ( cmd , logonly_ARG ) ;
2016-06-15 14:35:27 +03:00
report_command_log = args . log_only | | find_config_tree_bool ( cmd , log_report_command_log_CFG , NULL ) ;
2016-06-14 12:58:01 +03:00
if ( ! format_str | | ! strcmp ( format_str , REPORT_FORMAT_NAME_BASIC ) ) {
2016-06-15 14:35:27 +03:00
args . report_group_type = ( report_command_log & & ! args . log_only ) ? DM_REPORT_GROUP_BASIC
: DM_REPORT_GROUP_SINGLE ;
2016-05-02 15:22:02 +03:00
} else if ( ! strcmp ( format_str , REPORT_FORMAT_NAME_JSON ) ) {
args . report_group_type = DM_REPORT_GROUP_JSON ;
2022-08-04 17:42:54 +03:00
} else if ( ! strcmp ( format_str , REPORT_FORMAT_NAME_JSON_STD ) ) {
args . report_group_type = DM_REPORT_GROUP_JSON_STD ;
2016-05-02 15:22:02 +03:00
} else {
log_error ( " %s: unknown report format. " , format_str ) ;
2022-08-04 17:42:54 +03:00
log_error ( " Supported report formats: %s, %s, %s. " ,
2016-05-02 15:22:02 +03:00
REPORT_FORMAT_NAME_BASIC ,
2022-08-04 17:42:54 +03:00
REPORT_FORMAT_NAME_JSON ,
REPORT_FORMAT_NAME_JSON_STD ) ;
2016-05-02 15:22:02 +03:00
return 0 ;
}
2016-08-03 16:37:14 +03:00
cmd - > cmd_report . report_group_type = args . report_group_type ;
cmd - > cmd_report . log_only = args . log_only ;
2016-05-02 15:22:02 +03:00
if ( ! ( new_report_group = dm_report_group_create ( args . report_group_type , NULL ) ) ) {
log_error ( " Failed to create report group. " ) ;
return 0 ;
}
2022-08-15 12:40:52 +03:00
/*
* JSON_STD requires strict type mode . That means all NUM and BIN
* fields are always reported as numeric values and not strings which
* are synonyms to these numeric values .
*/
if ( args . report_group_type = = DM_REPORT_GROUP_JSON_STD )
cmd - > report_strict_type_mode = 1 ;
else
cmd - > report_strict_type_mode = 0 ;
2016-06-14 12:58:01 +03:00
if ( report_command_log ) {
2016-05-02 15:37:16 +03:00
single_args = & args . single_args [ REPORT_IDX_LOG ] ;
single_args - > report_type = CMDLOG ;
2016-05-25 14:41:42 +03:00
2016-08-03 16:37:14 +03:00
if ( ! _config_report ( cmd , & args , single_args ) )
goto_bad ;
2016-06-14 12:58:01 +03:00
2016-08-03 16:37:14 +03:00
if ( ! ( tmp_log_rh = report_init ( NULL , single_args - > options , single_args - > keys , & single_args - > report_type ,
args . separator , args . aligned , args . buffered , args . headings ,
args . field_prefixes , args . quoted , args . columns_as_rows ,
single_args - > selection , 1 ) ) ) {
log_error ( " Failed to create log report. " ) ;
goto bad ;
2016-06-14 12:58:01 +03:00
}
2016-05-02 15:22:02 +03:00
2016-08-03 16:37:14 +03:00
if ( ! ( dm_report_group_push ( new_report_group , tmp_log_rh , ( void * ) single_args - > report_name ) ) ) {
2016-06-14 12:58:01 +03:00
log_error ( " Failed to add log report to report group. " ) ;
2016-05-02 15:22:02 +03:00
goto bad ;
}
2016-08-03 16:37:14 +03:00
cmd - > cmd_report . log_rh = tmp_log_rh ;
if ( ! ( cmd - > cmd_report . log_name = dm_pool_strdup ( cmd - > libmem , single_args - > report_name ) ) ) {
log_error ( " Failed to set log report name for command context. " ) ;
goto bad ;
}
2016-05-02 15:22:02 +03:00
}
2016-08-03 16:37:14 +03:00
cmd - > cmd_report . report_group = new_report_group ;
cmd - > cmd_report . saved_log_report_state = log_get_report_state ( ) ;
log_set_report ( cmd - > cmd_report . log_rh ) ;
2016-05-03 12:46:52 +03:00
2016-05-02 15:22:02 +03:00
return 1 ;
bad :
if ( ! dm_report_group_destroy ( new_report_group ) )
stack ;
if ( tmp_log_rh )
dm_report_free ( tmp_log_rh ) ;
return 0 ;
}
2016-05-20 16:30:58 +03:00
2016-08-04 14:42:57 +03:00
int lastlog ( struct cmd_context * cmd , int argc __attribute ( ( unused ) ) , char * * argv __attribute__ ( ( unused ) ) )
2016-05-20 16:30:58 +03:00
{
2016-06-27 11:14:17 +03:00
const char * selection ;
2016-05-20 16:30:58 +03:00
2016-08-03 16:37:14 +03:00
if ( ! cmd - > cmd_report . log_rh ) {
2016-05-20 16:30:58 +03:00
log_error ( " No log report stored. " ) ;
2016-08-04 14:42:57 +03:00
return ECMD_FAILED ;
2016-05-20 16:30:58 +03:00
}
2016-06-27 11:14:17 +03:00
if ( ! _do_report_get_selection ( cmd , CMDLOG , 1 , NULL , & selection ) )
2016-08-04 14:42:57 +03:00
return_ECMD_FAILED ;
2016-05-20 16:30:58 +03:00
2016-08-03 16:37:14 +03:00
if ( ! dm_report_set_selection ( cmd - > cmd_report . log_rh , selection ) ) {
2016-05-20 16:30:58 +03:00
log_error ( " Failed to set selection for log report. " ) ;
2016-08-04 14:42:57 +03:00
return ECMD_FAILED ;
2016-05-20 16:30:58 +03:00
}
2016-08-04 14:42:57 +03:00
return ECMD_PROCESSED ;
2016-05-20 16:30:58 +03:00
}