2001-10-22 18:14:00 +04:00
/*
2004-03-30 23:35:44 +04:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
* Copyright ( C ) 2004 Red Hat , Inc . All rights reserved .
2001-10-22 18:14:00 +04:00
*
2004-03-30 23:35:44 +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 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
2001-10-22 18:14:00 +04:00
*/
2002-11-18 17:01:16 +03:00
# include "lib.h"
2001-10-22 18:14:00 +04:00
# include "config.h"
# include "dev-cache.h"
# include "filter-persistent.h"
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
struct pfilter {
char * file ;
2005-10-17 03:03:59 +04:00
struct dm_hash_table * devices ;
2001-10-23 16:24:55 +04:00
struct dev_filter * real ;
2001-10-22 18:14:00 +04:00
} ;
/*
* entries in the table can be in one of these
* states .
*/
2001-10-23 16:24:55 +04:00
# define PF_BAD_DEVICE ((void *) 1)
# define PF_GOOD_DEVICE ((void *) 2)
2001-10-22 18:14:00 +04:00
2001-10-22 18:39:12 +04:00
static int _init_hash ( struct pfilter * pf )
2001-10-22 18:14:00 +04:00
{
if ( pf - > devices )
2005-10-17 03:03:59 +04:00
dm_hash_destroy ( pf - > devices ) ;
2001-10-22 18:14:00 +04:00
2005-10-17 03:03:59 +04:00
if ( ! ( pf - > devices = dm_hash_create ( 128 ) ) ) {
2003-01-08 19:41:22 +03:00
stack ;
return 0 ;
}
return 1 ;
2001-10-22 18:14:00 +04:00
}
2001-10-23 16:24:55 +04:00
int persistent_filter_wipe ( struct dev_filter * f )
2001-10-22 18:14:00 +04:00
{
2001-10-23 16:24:55 +04:00
struct pfilter * pf = ( struct pfilter * ) f - > private ;
2001-10-22 18:14:00 +04:00
2005-03-22 01:40:35 +03:00
log_verbose ( " Wiping cache of LVM-capable devices " ) ;
2005-10-17 03:03:59 +04:00
dm_hash_wipe ( pf - > devices ) ;
2005-03-22 01:40:35 +03:00
2002-11-18 17:01:16 +03:00
/* Trigger complete device scan */
dev_cache_scan ( 1 ) ;
2001-10-24 21:53:50 +04:00
return 1 ;
2001-10-23 16:24:55 +04:00
}
2001-10-22 18:14:00 +04:00
2004-03-08 21:28:45 +03:00
static int _read_array ( struct pfilter * pf , struct config_tree * cft ,
2001-10-23 16:24:55 +04:00
const char * path , void * data )
{
2004-05-04 22:28:15 +04:00
const struct config_node * cn ;
2001-10-23 16:24:55 +04:00
struct config_value * cv ;
2001-10-22 18:14:00 +04:00
2004-03-08 21:28:45 +03:00
if ( ! ( cn = find_config_node ( cft - > root , path ) ) ) {
2001-10-24 21:53:50 +04:00
log_very_verbose ( " Couldn't find %s array in '%s' " ,
2002-04-24 22:20:51 +04:00
path , pf - > file ) ;
2001-10-23 16:24:55 +04:00
return 0 ;
2001-10-22 18:14:00 +04:00
}
/*
* iterate through the array , adding
* devices as we go .
*/
for ( cv = cn - > v ; cv ; cv = cv - > next ) {
if ( cv - > type ! = CFG_STRING ) {
2001-10-24 21:53:50 +04:00
log_verbose ( " Devices array contains a value "
2002-04-24 22:20:51 +04:00
" which is not a string ... ignoring " ) ;
2001-10-22 18:14:00 +04:00
continue ;
}
2005-10-17 03:03:59 +04:00
if ( ! dm_hash_insert ( pf - > devices , cv - > v . str , data ) )
2001-10-23 22:20:27 +04:00
log_verbose ( " Couldn't add '%s' to filter ... ignoring " ,
2002-04-24 22:20:51 +04:00
cv - > v . str ) ;
2002-11-18 17:01:16 +03:00
/* Populate dev_cache ourselves */
dev_cache_get ( cv - > v . str , NULL ) ;
2001-10-22 18:14:00 +04:00
}
2001-10-23 16:24:55 +04:00
return 1 ;
}
int persistent_filter_load ( struct dev_filter * f )
{
struct pfilter * pf = ( struct pfilter * ) f - > private ;
int r = 0 ;
2004-03-08 21:28:45 +03:00
struct config_tree * cft ;
2001-10-23 16:24:55 +04:00
2004-05-04 22:28:15 +04:00
if ( ! ( cft = create_config_tree ( pf - > file ) ) ) {
2001-10-23 16:24:55 +04:00
stack ;
return 0 ;
}
2004-05-04 22:28:15 +04:00
if ( ! read_config_file ( cft ) ) {
2001-10-23 16:24:55 +04:00
stack ;
goto out ;
}
2004-03-08 21:28:45 +03:00
_read_array ( pf , cft , " persistent_filter_cache/valid_devices " ,
2001-10-25 18:41:28 +04:00
PF_GOOD_DEVICE ) ;
2002-11-18 17:01:16 +03:00
/* We don't gain anything by holding invalid devices */
2004-03-08 21:28:45 +03:00
/* _read_array(pf, cft, "persistent_filter_cache/invalid_devices",
2002-11-18 17:01:16 +03:00
PF_BAD_DEVICE ) ; */
/* Did we find anything? */
2005-10-17 03:03:59 +04:00
if ( dm_hash_get_num_entries ( pf - > devices ) ) {
2002-11-18 17:01:16 +03:00
/* We populated dev_cache ourselves */
dev_cache_scan ( 0 ) ;
2001-10-23 16:24:55 +04:00
r = 1 ;
2002-11-18 17:01:16 +03:00
}
2001-10-22 18:14:00 +04:00
2003-01-07 00:09:04 +03:00
log_very_verbose ( " Loaded persistent filter cache from %s " , pf - > file ) ;
2002-04-24 22:20:51 +04:00
out :
2004-03-08 21:28:45 +03:00
destroy_config_tree ( cft ) ;
2001-10-22 18:14:00 +04:00
return r ;
}
2002-11-18 17:01:16 +03:00
static void _write_array ( struct pfilter * pf , FILE * fp , const char * path ,
2001-10-23 16:24:55 +04:00
void * data )
2001-10-22 18:14:00 +04:00
{
2001-10-23 16:24:55 +04:00
void * d ;
2001-10-22 18:14:00 +04:00
int first = 1 ;
2005-10-17 03:03:59 +04:00
struct dm_hash_node * n ;
2001-10-22 18:14:00 +04:00
2005-10-17 03:03:59 +04:00
for ( n = dm_hash_get_first ( pf - > devices ) ; n ;
n = dm_hash_get_next ( pf - > devices , n ) ) {
d = dm_hash_get_data ( pf - > devices , n ) ;
2001-10-23 16:24:55 +04:00
if ( d ! = data )
continue ;
2001-10-22 18:14:00 +04:00
if ( ! first )
fprintf ( fp , " , \n " ) ;
2001-10-24 21:53:50 +04:00
else {
fprintf ( fp , " \t %s=[ \n " , path ) ;
2001-10-22 18:14:00 +04:00
first = 0 ;
2001-10-24 21:53:50 +04:00
}
2001-10-22 18:14:00 +04:00
2005-10-17 03:03:59 +04:00
fprintf ( fp , " \t \t \" %s \" " , dm_hash_get_key ( pf - > devices , n ) ) ;
2001-10-22 18:14:00 +04:00
}
2001-10-24 21:53:50 +04:00
if ( ! first )
fprintf ( fp , " \n \t ] \n " ) ;
return ;
2001-10-22 18:14:00 +04:00
}
2001-10-23 16:24:55 +04:00
int persistent_filter_dump ( struct dev_filter * f )
2001-10-22 18:14:00 +04:00
{
2001-10-23 16:24:55 +04:00
struct pfilter * pf = ( struct pfilter * ) f - > private ;
2001-10-22 18:14:00 +04:00
2001-10-25 19:07:26 +04:00
FILE * fp ;
2002-01-25 02:17:16 +03:00
2005-10-17 03:03:59 +04:00
if ( ! dm_hash_get_num_entries ( pf - > devices ) ) {
2002-01-25 02:17:16 +03:00
log_very_verbose ( " Internal persistent device cache empty "
" - not writing to %s " , pf - > file ) ;
return 0 ;
}
2002-11-18 17:01:16 +03:00
if ( ! dev_cache_has_scanned ( ) ) {
log_very_verbose ( " Device cache incomplete - not writing "
" to %s " , pf - > file ) ;
return 0 ;
}
2001-10-23 16:24:55 +04:00
log_very_verbose ( " Dumping persistent device cache to %s " , pf - > file ) ;
2001-10-22 18:14:00 +04:00
2001-10-25 19:07:26 +04:00
fp = fopen ( pf - > file , " w " ) ;
2001-10-23 16:24:55 +04:00
if ( ! fp ) {
2002-07-11 18:09:26 +04:00
if ( errno ! = EROFS )
log_sys_error ( " fopen " , pf - > file ) ;
2001-10-23 16:24:55 +04:00
return 0 ;
}
2001-10-22 18:14:00 +04:00
2001-10-23 16:24:55 +04:00
fprintf ( fp , " # This file is automatically maintained by lvm. \n \n " ) ;
2001-10-24 21:53:50 +04:00
fprintf ( fp , " persistent_filter_cache { \n " ) ;
2001-10-22 18:14:00 +04:00
2001-10-23 16:24:55 +04:00
_write_array ( pf , fp , " valid_devices " , PF_GOOD_DEVICE ) ;
2002-11-18 17:01:16 +03:00
/* We don't gain anything by remembering invalid devices */
/* _write_array(pf, fp, "invalid_devices", PF_BAD_DEVICE); */
2001-10-22 18:14:00 +04:00
2001-10-24 21:53:50 +04:00
fprintf ( fp , " } \n " ) ;
2001-10-23 16:24:55 +04:00
fclose ( fp ) ;
return 1 ;
2001-10-22 18:14:00 +04:00
}
2001-10-23 16:24:55 +04:00
static int _lookup_p ( struct dev_filter * f , struct device * dev )
2001-10-22 18:14:00 +04:00
{
struct pfilter * pf = ( struct pfilter * ) f - > private ;
2005-10-17 03:03:59 +04:00
void * l = dm_hash_lookup ( pf - > devices , dev_name ( dev ) ) ;
2001-10-25 18:51:51 +04:00
struct str_list * sl ;
2001-10-22 18:14:00 +04:00
2001-10-23 16:24:55 +04:00
if ( ! l ) {
l = pf - > real - > passes_filter ( pf - > real , dev ) ?
2002-04-24 22:20:51 +04:00
PF_GOOD_DEVICE : PF_BAD_DEVICE ;
2001-10-22 18:14:00 +04:00
2005-06-01 20:51:55 +04:00
list_iterate_items ( sl , & dev - > aliases )
2005-10-17 03:03:59 +04:00
dm_hash_insert ( pf - > devices , sl - > str , l ) ;
2005-06-01 20:51:55 +04:00
2004-11-24 23:36:52 +03:00
} else if ( l = = PF_BAD_DEVICE )
log_debug ( " %s: Skipping (cached) " , dev_name ( dev ) ) ;
2001-10-22 18:14:00 +04:00
2004-11-24 23:36:52 +03:00
return ( l = = PF_BAD_DEVICE ) ? 0 : 1 ;
2001-10-22 18:14:00 +04:00
}
2006-04-19 19:33:07 +04:00
static void _persistent_destroy ( struct dev_filter * f )
2001-10-22 18:14:00 +04:00
{
struct pfilter * pf = ( struct pfilter * ) f - > private ;
2005-10-17 03:03:59 +04:00
dm_hash_destroy ( pf - > devices ) ;
dm_free ( pf - > file ) ;
2001-10-23 16:24:55 +04:00
pf - > real - > destroy ( pf - > real ) ;
2005-10-17 03:03:59 +04:00
dm_free ( pf ) ;
dm_free ( f ) ;
2001-10-22 18:14:00 +04:00
}
2001-10-23 16:24:55 +04:00
struct dev_filter * persistent_filter_create ( struct dev_filter * real ,
const char * file )
2001-10-22 18:14:00 +04:00
{
struct pfilter * pf ;
struct dev_filter * f = NULL ;
2005-10-17 03:03:59 +04:00
if ( ! ( pf = dm_malloc ( sizeof ( * pf ) ) ) ) {
2001-10-22 18:14:00 +04:00
stack ;
return NULL ;
}
memset ( pf , 0 , sizeof ( * pf ) ) ;
2005-10-17 03:03:59 +04:00
if ( ! ( pf - > file = dm_malloc ( strlen ( file ) + 1 ) ) ) {
2001-10-22 18:14:00 +04:00
stack ;
goto bad ;
}
strcpy ( pf - > file , file ) ;
2001-10-23 16:24:55 +04:00
pf - > real = real ;
2001-10-22 18:14:00 +04:00
if ( ! ( _init_hash ( pf ) ) ) {
2001-10-23 22:20:27 +04:00
log_error ( " Couldn't create hash table for persistent filter. " ) ;
2001-10-22 18:14:00 +04:00
goto bad ;
}
2005-10-17 03:03:59 +04:00
if ( ! ( f = dm_malloc ( sizeof ( * f ) ) ) ) {
2001-10-22 18:14:00 +04:00
stack ;
goto bad ;
}
2001-10-23 16:24:55 +04:00
f - > passes_filter = _lookup_p ;
2006-04-19 19:33:07 +04:00
f - > destroy = _persistent_destroy ;
2001-10-22 18:14:00 +04:00
f - > private = pf ;
return f ;
2002-04-24 22:20:51 +04:00
bad :
2005-10-17 03:03:59 +04:00
dm_free ( pf - > file ) ;
2001-10-22 18:14:00 +04:00
if ( pf - > devices )
2005-10-17 03:03:59 +04:00
dm_hash_destroy ( pf - > devices ) ;
dm_free ( pf ) ;
dm_free ( f ) ;
2001-10-22 18:14:00 +04:00
return NULL ;
}