2014-09-23 14:49:01 +04:00
/*
* Copyright ( C ) 2014 Red Hat , Inc . All rights reserved .
*
* This file is part of LVM2 .
*
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v .2 .1 .
*
* You should have received a copy of the GNU Lesser General Public License
* 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
2014-09-23 14:49:01 +04:00
*/
2018-06-08 15:40:53 +03:00
# include "base/memory/zalloc.h"
2018-05-14 12:30:20 +03:00
# include "lib/misc/lib.h"
# include "lib/filters/filter.h"
# include "lib/activate/activate.h"
2015-01-29 16:24:06 +03:00
2018-08-29 21:14:18 +03:00
struct filter_data {
filter_mode_t mode ;
int skip_lvs ;
} ;
2015-01-29 16:24:06 +03:00
static const char * _too_small_to_hold_pv_msg = " Too small to hold a PV " ;
2021-06-15 19:22:32 +03:00
static int _check_pv_min_size ( struct device * dev )
2015-01-29 16:24:06 +03:00
{
uint64_t size ;
int ret = 0 ;
/* Check it's not too small */
if ( ! dev_get_size ( dev , & size ) ) {
2015-09-03 15:19:48 +03:00
log_debug_devs ( " %s: Skipping: dev_get_size failed " , dev_name ( dev ) ) ;
2015-01-29 16:24:06 +03:00
goto out ;
}
if ( size < pv_min_size ( ) ) {
2015-09-03 15:19:48 +03:00
log_debug_devs ( " %s: Skipping: %s " , dev_name ( dev ) ,
_too_small_to_hold_pv_msg ) ;
2015-01-29 16:24:06 +03:00
goto out ;
}
ret = 1 ;
out :
return ret ;
}
2018-12-07 23:35:22 +03:00
static int _passes_usable_filter ( struct cmd_context * cmd , struct dev_filter * f , struct device * dev , const char * use_filter_name )
2014-09-23 14:49:01 +04:00
{
2018-08-29 21:14:18 +03:00
struct filter_data * data = f - > private ;
filter_mode_t mode = data - > mode ;
int skip_lvs = data - > skip_lvs ;
2014-10-02 15:21:24 +04:00
struct dev_usable_check_params ucp = { 0 } ;
2021-03-03 21:07:57 +03:00
int is_lv = 0 ;
2015-09-02 17:08:30 +03:00
int r = 1 ;
2015-01-29 16:24:06 +03:00
2020-07-20 20:48:36 +03:00
dev - > filtered_flags & = ~ DEV_FILTERED_MINSIZE ;
dev - > filtered_flags & = ~ DEV_FILTERED_UNUSABLE ;
2015-01-29 16:24:06 +03:00
/* further checks are done on dm devices only */
2015-09-02 17:08:30 +03:00
if ( dm_is_dm_major ( MAJOR ( dev - > dev ) ) ) {
switch ( mode ) {
2014-09-23 14:49:01 +04:00
case FILTER_MODE_NO_LVMETAD :
ucp . check_empty = 1 ;
ucp . check_blocked = 1 ;
ucp . check_suspended = ignore_suspended_devices ( ) ;
ucp . check_error_target = 1 ;
ucp . check_reserved = 1 ;
2018-08-29 21:14:18 +03:00
ucp . check_lv = skip_lvs ;
2014-09-23 14:49:01 +04:00
break ;
case FILTER_MODE_PRE_LVMETAD :
ucp . check_empty = 1 ;
2014-10-08 12:57:44 +04:00
ucp . check_blocked = 1 ;
2016-02-03 16:40:52 +03:00
ucp . check_suspended = 0 ;
2014-09-23 14:49:01 +04:00
ucp . check_error_target = 1 ;
ucp . check_reserved = 1 ;
2018-08-29 21:14:18 +03:00
ucp . check_lv = skip_lvs ;
2014-09-23 14:49:01 +04:00
break ;
case FILTER_MODE_POST_LVMETAD :
ucp . check_empty = 0 ;
ucp . check_blocked = 1 ;
ucp . check_suspended = ignore_suspended_devices ( ) ;
ucp . check_error_target = 0 ;
ucp . check_reserved = 0 ;
2018-08-29 21:14:18 +03:00
ucp . check_lv = skip_lvs ;
2014-09-23 14:49:01 +04:00
break ;
2015-09-02 17:08:30 +03:00
}
2021-12-15 13:26:21 +03:00
if ( ! ( r = device_is_usable ( cmd , dev , ucp , & is_lv ) ) ) {
2021-03-03 21:07:57 +03:00
if ( is_lv )
dev - > filtered_flags | = DEV_FILTERED_IS_LV ;
else
dev - > filtered_flags | = DEV_FILTERED_UNUSABLE ;
2015-09-02 17:08:30 +03:00
log_debug_devs ( " %s: Skipping unusable device. " , dev_name ( dev ) ) ;
2020-07-20 20:48:36 +03:00
}
2014-09-23 14:49:01 +04:00
}
2015-09-02 17:08:30 +03:00
if ( r ) {
2021-06-15 19:22:32 +03:00
r = _check_pv_min_size ( dev ) ;
if ( ! r )
dev - > filtered_flags | = DEV_FILTERED_MINSIZE ;
2015-09-02 17:08:30 +03:00
}
2014-09-23 14:49:01 +04:00
return r ;
}
static void _usable_filter_destroy ( struct dev_filter * f )
{
if ( f - > use_count )
log_error ( INTERNAL_ERROR " Destroying usable device filter while in use %u times. " , f - > use_count ) ;
2018-06-08 15:40:53 +03:00
free ( f - > private ) ;
free ( f ) ;
2014-09-23 14:49:01 +04:00
}
2018-08-29 21:14:18 +03:00
struct dev_filter * usable_filter_create ( struct cmd_context * cmd , struct dev_types * dt __attribute__ ( ( unused ) ) , filter_mode_t mode )
2014-09-23 14:49:01 +04:00
{
2018-08-29 21:14:18 +03:00
struct filter_data * data ;
2014-09-23 14:49:01 +04:00
struct dev_filter * f ;
2018-06-08 15:40:53 +03:00
if ( ! ( f = zalloc ( sizeof ( struct dev_filter ) ) ) ) {
2014-09-23 14:49:01 +04:00
log_error ( " Usable device filter allocation failed " ) ;
return NULL ;
}
f - > passes_filter = _passes_usable_filter ;
f - > destroy = _usable_filter_destroy ;
f - > use_count = 0 ;
2018-12-07 23:35:22 +03:00
f - > name = " usable " ;
2018-08-29 21:14:18 +03:00
if ( ! ( data = zalloc ( sizeof ( struct filter_data ) ) ) ) {
2014-09-23 14:49:01 +04:00
log_error ( " Usable device filter mode allocation failed " ) ;
2018-06-08 15:40:53 +03:00
free ( f ) ;
2014-09-23 14:49:01 +04:00
return NULL ;
}
2018-08-29 21:14:18 +03:00
data - > mode = mode ;
data - > skip_lvs = ! find_config_tree_bool ( cmd , devices_scan_lvs_CFG , NULL ) ;
f - > private = data ;
log_debug_devs ( " Usable device filter initialised (scan_lvs %d). " , ! data - > skip_lvs ) ;
2014-09-23 14:49:01 +04:00
return f ;
}