2004-04-16 20:12:04 +04:00
/*
* Copyright ( C ) 2004 Luca Berra
2007-08-21 00:55:30 +04:00
* Copyright ( C ) 2004 - 2006 Red Hat , Inc . All rights reserved .
2004-04-16 20:12:04 +04:00
*
* 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
2004-04-16 20:12:04 +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"
2018-10-15 17:50:25 +03:00
# include "lib/commands/toolcontext.h"
2004-04-16 20:12:04 +04:00
2013-11-13 17:56:29 +04:00
# ifdef __linux__
2004-04-16 20:12:04 +04:00
2015-09-03 15:19:48 +03:00
# define MSG_SKIPPING "%s: Skipping md component device"
2018-05-22 22:07:13 +03:00
/*
* The purpose of these functions is to ignore md component devices ,
* e . g . if / dev / md0 is a raid1 composed of / dev / loop0 and / dev / loop1 ,
* lvm wants to deal with md0 and ignore loop0 and loop1 . md0 should
* pass the filter , and loop0 , loop1 should not pass the filter so lvm
* will ignore them .
*
* ( This is assuming lvm . conf md_component_detection = 1. )
*
2018-06-15 19:42:10 +03:00
* If lvm does * not * ignore the components , then lvm may read lvm
* labels from the component devs and potentially the md dev ,
* which can trigger duplicate detection , and / or cause lvm to display
* md components as PVs rather than ignoring them .
*
* If scanning md componenents causes duplicates to be seen , then
* the lvm duplicate resolution will exclude the components .
*
* The lvm md filter has three modes :
*
* 1. look for md superblock at the start of the device
* 2. look for md superblock at the start and end of the device
* 3. use udev to detect components
*
* mode 1 will not detect and exclude components of md devices
2018-11-29 21:35:54 +03:00
* that use superblock version 0.9 or 1.0 which is at the end of the device .
2018-06-15 19:42:10 +03:00
*
* mode 2 will detect these , but mode 2 doubles the i / o done by label
* scan , since there ' s a read at both the start and end of every device .
*
* mode 3 is used when external_device_info_source = " udev " . It does
* not require any io from lvm , but this mode is not used by default
* because there have been problems getting reliable info from udev .
*
* lvm uses mode 2 when :
*
* - the command is pvcreate / vgcreate / vgextend , which format new
* devices , and if the user ran these commands on a component
2018-11-29 21:35:54 +03:00
* device of an md device 0.9 or 1.0 , then it would cause problems .
2018-06-15 19:42:10 +03:00
* FIXME : this would only really need to scan the end of the
* devices being formatted , not all devices .
*
2018-11-29 21:35:54 +03:00
* - it sees an md device on the system using version 0.9 or 1.0 .
2018-06-15 19:42:10 +03:00
* The point of this is just to avoid displaying md components
* from the ' pvs ' command .
* FIXME : the cost ( double i / o ) may not be worth the benefit
* ( not showing md components ) .
2018-06-15 19:03:55 +03:00
*/
2018-05-22 22:07:13 +03:00
/*
* Returns 0 if :
* the device is an md component and it should be ignored .
*
* Returns 1 if :
* the device is not md component and should not be ignored .
*
* The actual md device will pass this filter and should be used ,
* it is the md component devices that we are trying to exclude
* that will not pass .
*/
2018-12-07 23:35:22 +03:00
static int _passes_md_filter ( struct cmd_context * cmd , struct dev_filter * f __attribute__ ( ( unused ) ) , struct device * dev , const char * use_filter_name )
2004-04-16 20:12:04 +04:00
{
2004-11-19 22:25:07 +03:00
int ret ;
2018-05-22 22:07:13 +03:00
/*
* When md_component_dectection = 0 , don ' t even try to skip md
* components .
*/
2004-11-19 22:25:07 +03:00
if ( ! md_filtering ( ) )
return 1 ;
2018-05-22 22:07:13 +03:00
2019-05-21 19:44:39 +03:00
ret = dev_is_md_component ( dev , NULL , cmd - > use_full_md_check ) ;
2018-05-04 01:12:07 +03:00
if ( ret = = - EAGAIN ) {
/* let pass, call again after scan */
dev - > flags | = DEV_FILTER_AFTER_SCAN ;
log_debug_devs ( " filter md deferred %s " , dev_name ( dev ) ) ;
return 1 ;
}
2004-04-16 20:12:04 +04:00
2018-05-22 22:07:13 +03:00
if ( ret = = 0 )
return 1 ;
2004-11-18 23:02:21 +03:00
if ( ret = = 1 ) {
2018-12-03 20:22:45 +03:00
log_debug_devs ( " md filter full %d excluding md component %s " , cmd - > use_full_md_check , dev_name ( dev ) ) ;
2015-09-03 15:19:48 +03:00
if ( dev - > ext . src = = DEV_EXT_NONE )
log_debug_devs ( MSG_SKIPPING , dev_name ( dev ) ) ;
else
log_debug_devs ( MSG_SKIPPING " [%s:%p] " , dev_name ( dev ) ,
dev_ext_name ( dev ) , dev - > ext . handle ) ;
2004-04-16 20:12:04 +04:00
return 0 ;
}
2004-11-18 23:02:21 +03:00
if ( ret < 0 ) {
2013-01-08 02:30:29 +04:00
log_debug_devs ( " %s: Skipping: error in md component detection " ,
dev_name ( dev ) ) ;
2004-04-16 20:12:04 +04:00
return 0 ;
}
return 1 ;
}
static void _destroy ( struct dev_filter * f )
{
2010-09-22 05:36:13 +04:00
if ( f - > use_count )
2010-09-22 05:50:38 +04:00
log_error ( INTERNAL_ERROR " Destroying md filter while in use %u times. " , f - > use_count ) ;
2010-09-22 05:36:13 +04:00
2018-06-08 15:40:53 +03:00
free ( f ) ;
2004-04-16 20:12:04 +04:00
}
2018-05-04 01:12:07 +03:00
struct dev_filter * md_filter_create ( struct cmd_context * cmd , struct dev_types * dt )
2004-04-16 20:12:04 +04:00
{
struct dev_filter * f ;
2018-06-08 15:40:53 +03:00
if ( ! ( f = zalloc ( sizeof ( * f ) ) ) ) {
2004-04-16 20:12:04 +04:00
log_error ( " md filter allocation failed " ) ;
return NULL ;
}
2018-06-15 19:03:55 +03:00
f - > passes_filter = _passes_md_filter ;
2004-04-16 20:12:04 +04:00
f - > destroy = _destroy ;
2010-09-22 05:36:13 +04:00
f - > use_count = 0 ;
2013-06-12 14:08:56 +04:00
f - > private = dt ;
2018-12-07 23:35:22 +03:00
f - > name = " md " ;
2004-04-16 20:12:04 +04:00
2013-08-14 02:26:58 +04:00
log_debug_devs ( " MD filter initialised. " ) ;
2004-04-16 20:12:04 +04:00
return f ;
}
# else
2013-06-12 14:08:56 +04:00
struct dev_filter * md_filter_create ( struct dev_types * dt )
2004-04-16 20:12:04 +04:00
{
return NULL ;
}
# endif