2001-12-13 03:07:29 +03:00
/*
2002-01-15 13:24:48 +03:00
* Copyright ( C ) 2001 Sistina Software ( UK ) Limited .
2001-12-13 03:07:29 +03:00
*
* This file is released under the LGPL .
2002-01-15 13:24:48 +03:00
*
2001-12-13 03:07:29 +03:00
*/
# include <stdlib.h>
# include "vgcache.h"
2002-01-15 13:24:48 +03:00
# include "hash.h"
2001-12-13 03:07:29 +03:00
# include "dbg_malloc.h"
# include "log.h"
2002-03-05 23:03:09 +03:00
# include "uuid.h"
# include "toolcontext.h"
2001-12-13 03:07:29 +03:00
2002-01-15 13:24:48 +03:00
static struct hash_table * _vghash ;
2002-03-05 23:03:09 +03:00
static struct hash_table * _vgidhash ;
2002-01-15 13:24:48 +03:00
static struct hash_table * _pvhash ;
2001-12-13 03:07:29 +03:00
2002-01-15 13:24:48 +03:00
const char * all_devices = " \0 " ;
2001-12-13 03:07:29 +03:00
2002-01-15 13:24:48 +03:00
int vgcache_init ( )
2001-12-13 03:07:29 +03:00
{
2002-01-15 13:24:48 +03:00
if ( ! ( _vghash = hash_create ( 128 ) ) )
return 0 ;
2002-03-05 23:03:09 +03:00
if ( ! ( _vgidhash = hash_create ( 128 ) ) )
return 0 ;
2002-01-15 13:24:48 +03:00
if ( ! ( _pvhash = hash_create ( 128 ) ) )
return 0 ;
2001-12-13 03:07:29 +03:00
2002-01-15 13:24:48 +03:00
return 1 ;
}
/* A vg_name of NULL returns all_devices */
struct list * vgcache_find ( const char * vg_name )
{
struct vgname_entry * vgn ;
if ( ! _vghash )
2001-12-13 03:07:29 +03:00
return NULL ;
2002-01-15 13:24:48 +03:00
if ( ! vg_name )
vg_name = all_devices ;
2001-12-13 03:07:29 +03:00
2002-01-15 13:24:48 +03:00
if ( ! ( vgn = hash_lookup ( _vghash , vg_name ) ) )
return NULL ;
return & vgn - > pvdevs ;
2001-12-13 03:07:29 +03:00
}
2002-04-24 22:20:51 +04:00
struct format_type * vgcache_find_format ( const char * vg_name )
{
struct vgname_entry * vgn ;
if ( ! _vghash )
return NULL ;
if ( ! vg_name )
vg_name = all_devices ;
if ( ! ( vgn = hash_lookup ( _vghash , vg_name ) ) )
return NULL ;
return vgn - > fmt ;
}
2002-03-05 23:03:09 +03:00
struct list * vgcache_find_by_vgid ( const char * vgid )
{
struct vgname_entry * vgn ;
char vgid_s [ ID_LEN + 1 ] ;
if ( ! _vgidhash | | ! vgid )
return NULL ;
memcpy ( vgid_s , vgid , ID_LEN ) ;
vgid_s [ ID_LEN ] = ' \0 ' ;
if ( ! ( vgn = hash_lookup ( _vgidhash , vgid_s ) ) )
return NULL ;
return & vgn - > pvdevs ;
}
2002-01-15 13:24:48 +03:00
void vgcache_del_orphan ( struct device * dev )
2001-12-13 03:07:29 +03:00
{
2002-01-15 13:24:48 +03:00
struct pvdev_list * pvdev ;
if ( _pvhash & & ( ( pvdev = hash_lookup ( _pvhash , dev_name ( dev ) ) ) ) ) {
list_del ( & pvdev - > list ) ;
hash_remove ( _pvhash , dev_name ( pvdev - > dev ) ) ;
dbg_free ( pvdev ) ;
}
2001-12-13 18:08:58 +03:00
}
2002-04-24 22:20:51 +04:00
int vgcache_add_entry ( const char * vg_name , const char * vgid , struct device * dev ,
struct format_type * fmt )
2001-12-13 18:08:58 +03:00
{
2002-01-15 13:24:48 +03:00
const char * pv_name ;
struct vgname_entry * vgn ;
struct pvdev_list * pvdev ;
struct list * pvdh , * pvdevs ;
if ( ! ( pvdevs = vgcache_find ( vg_name ) ) ) {
if ( ! ( vgn = dbg_malloc ( sizeof ( struct vgname_entry ) ) ) ) {
log_error ( " struct vgname_entry allocation failed " ) ;
return 0 ;
}
2002-03-05 23:03:09 +03:00
memset ( vgn , 0 , sizeof ( struct vgname_entry ) ) ;
2001-12-13 03:07:29 +03:00
2002-04-24 22:20:51 +04:00
vgn - > fmt = fmt ;
2002-01-15 13:24:48 +03:00
pvdevs = & vgn - > pvdevs ;
list_init ( pvdevs ) ;
2001-12-13 03:07:29 +03:00
2002-01-15 13:24:48 +03:00
if ( ! ( vgn - > vgname = dbg_strdup ( vg_name ) ) ) {
log_error ( " vgcache_add: strdup vg_name failed " ) ;
return 0 ;
}
2001-12-13 18:08:58 +03:00
2002-01-15 13:24:48 +03:00
if ( ! hash_insert ( _vghash , vg_name , vgn ) ) {
log_error ( " vgcache_add: VG hash insertion failed " ) ;
return 0 ;
}
2002-04-24 22:20:51 +04:00
} else if ( ! ( vgn = hash_lookup ( _vghash , vg_name ) ) ) {
log_error ( " vgcache_add: VG name entry %s not found " , vg_name ) ;
return 0 ;
}
2002-03-05 23:03:09 +03:00
2002-04-24 22:20:51 +04:00
if ( vgid & & strncmp ( vgid , vgn - > vgid , ID_LEN ) ) {
hash_remove ( _vgidhash , vgn - > vgid ) ;
memcpy ( vgn - > vgid , vgid , ID_LEN ) ;
vgn - > vgid [ ID_LEN ] = ' \0 ' ;
2002-03-05 23:03:09 +03:00
2002-04-24 22:20:51 +04:00
if ( ! hash_insert ( _vgidhash , vgn - > vgid , vgn ) ) {
log_error ( " vgcache_add: vgid hash insertion " " failed " ) ;
return 0 ;
2002-03-05 23:03:09 +03:00
}
2002-01-15 13:24:48 +03:00
}
2001-12-13 03:07:29 +03:00
2002-04-24 22:20:51 +04:00
if ( ! dev )
return 1 ;
2002-01-15 13:24:48 +03:00
list_iterate ( pvdh , pvdevs ) {
pvdev = list_item ( pvdh , struct pvdev_list ) ;
if ( dev = = pvdev - > dev )
return 1 ;
}
2001-12-13 03:07:29 +03:00
2002-01-15 13:24:48 +03:00
/* Remove PV from any existing VG unless an all_devices request */
pvdev = NULL ;
pv_name = dev_name ( dev ) ;
if ( * vg_name & & _pvhash & & ( ( pvdev = hash_lookup ( _pvhash , pv_name ) ) ) ) {
list_del ( & pvdev - > list ) ;
hash_remove ( _pvhash , dev_name ( pvdev - > dev ) ) ;
2001-12-13 18:08:58 +03:00
}
2002-01-15 13:24:48 +03:00
/* Allocate new pvdev_list if there isn't an existing one to reuse */
if ( ! pvdev & & ! ( pvdev = dbg_malloc ( sizeof ( struct pvdev_list ) ) ) ) {
log_error ( " struct pvdev_list allocation failed " ) ;
return 0 ;
}
2001-12-13 03:07:29 +03:00
2002-01-15 13:24:48 +03:00
pvdev - > dev = dev ;
list_add ( pvdevs , & pvdev - > list ) ;
2001-12-13 03:07:29 +03:00
2002-01-15 13:24:48 +03:00
if ( * vg_name & & _pvhash & & ! hash_insert ( _pvhash , pv_name , pvdev ) ) {
log_error ( " vgcache_add: PV hash insertion for %s "
" failed " , pv_name ) ;
return 0 ;
}
2001-12-13 18:08:58 +03:00
2002-01-15 13:24:48 +03:00
return 1 ;
}
2001-12-13 03:07:29 +03:00
2002-01-15 13:24:48 +03:00
/* vg_name of "\0" is an orphan PV; NULL means only add to all_devices */
2002-04-24 22:20:51 +04:00
int vgcache_add ( const char * vg_name , const char * vgid , struct device * dev ,
struct format_type * fmt )
2002-01-15 13:24:48 +03:00
{
if ( ! _vghash & & ! vgcache_init ( ) )
return 0 ;
2001-12-13 03:07:29 +03:00
2002-01-15 13:24:48 +03:00
/* If orphan PV remove it */
2002-04-24 22:20:51 +04:00
if ( dev & & vg_name & & ! * vg_name )
2002-01-15 13:24:48 +03:00
vgcache_del_orphan ( dev ) ;
2002-01-14 14:43:52 +03:00
2002-01-15 13:24:48 +03:00
/* Add PV if vg_name supplied */
2002-04-24 22:20:51 +04:00
if ( vg_name & & * vg_name & & ! vgcache_add_entry ( vg_name , vgid , dev , fmt ) )
2002-01-15 13:24:48 +03:00
return 0 ;
2002-01-14 14:43:52 +03:00
2002-04-24 22:20:51 +04:00
/* Add to all_devices */
if ( dev )
return vgcache_add_entry ( all_devices , NULL , dev , fmt ) ;
return 1 ;
2002-01-15 13:24:48 +03:00
}
2002-01-14 14:43:52 +03:00
2002-01-15 13:24:48 +03:00
void vgcache_destroy_entry ( struct vgname_entry * vgn )
{
struct list * pvdh ;
struct pvdev_list * pvdev ;
if ( vgn ) {
pvdh = vgn - > pvdevs . n ;
while ( pvdh ! = & vgn - > pvdevs ) {
pvdev = list_item ( pvdh , struct pvdev_list ) ;
pvdh = pvdh - > n ;
2002-01-21 22:04:13 +03:00
if ( _pvhash )
hash_remove ( _pvhash , dev_name ( pvdev - > dev ) ) ;
2002-01-15 13:24:48 +03:00
dbg_free ( pvdev ) ;
2001-12-13 03:07:29 +03:00
}
2002-01-15 13:24:48 +03:00
dbg_free ( vgn - > vgname ) ;
2002-03-05 23:03:09 +03:00
if ( _vgidhash & & vgn - > vgid [ 0 ] )
hash_remove ( _vgidhash , vgn - > vgid ) ;
2001-12-13 03:07:29 +03:00
}
2002-01-15 13:24:48 +03:00
dbg_free ( vgn ) ;
2001-12-13 03:07:29 +03:00
}
2002-01-15 13:24:48 +03:00
void vgcache_del ( const char * vg_name )
2001-12-13 03:07:29 +03:00
{
2002-01-15 13:24:48 +03:00
struct vgname_entry * vgn ;
2001-12-13 03:07:29 +03:00
2002-01-15 13:24:48 +03:00
if ( ! _vghash )
return ;
2001-12-13 03:07:29 +03:00
2002-01-15 13:24:48 +03:00
if ( ! vg_name )
vg_name = all_devices ;
2001-12-13 03:07:29 +03:00
2002-01-15 13:24:48 +03:00
if ( ! ( vgn = hash_lookup ( _vghash , vg_name ) ) )
return ;
2001-12-13 03:07:29 +03:00
2002-01-15 13:24:48 +03:00
hash_remove ( _vghash , vg_name ) ;
2002-03-05 23:03:09 +03:00
if ( vgn - > vgid [ 0 ] )
hash_remove ( _vgidhash , vgn - > vgid ) ;
vgcache_destroy_entry ( vgn ) ;
}
void vgcache_del_by_vgid ( const char * vgid )
{
struct vgname_entry * vgn ;
char vgid_s [ ID_LEN + 1 ] ;
if ( ! _vgidhash | | ! vgid )
return ;
memcpy ( vgid_s , vgid , ID_LEN ) ;
vgid_s [ ID_LEN ] = ' \0 ' ;
if ( ! ( vgn = hash_lookup ( _vghash , vgid_s ) ) )
return ;
hash_remove ( _vgidhash , vgn - > vgid ) ;
if ( vgn - > vgname [ 0 ] )
hash_remove ( _vghash , vgn - > vgname ) ;
2002-01-15 13:24:48 +03:00
vgcache_destroy_entry ( vgn ) ;
2001-12-13 03:07:29 +03:00
}
2002-01-15 13:24:48 +03:00
void vgcache_destroy ( )
2001-12-13 03:07:29 +03:00
{
2002-01-15 13:24:48 +03:00
if ( _vghash ) {
2002-04-24 22:20:51 +04:00
hash_iter ( _vghash , ( iterate_fn ) vgcache_destroy_entry ) ;
2002-01-15 13:24:48 +03:00
hash_destroy ( _vghash ) ;
_vghash = NULL ;
}
2001-12-13 18:08:58 +03:00
2002-03-05 23:03:09 +03:00
if ( _vgidhash ) {
hash_destroy ( _vgidhash ) ;
_vgidhash = NULL ;
}
2002-01-15 13:24:48 +03:00
if ( _pvhash ) {
hash_destroy ( _pvhash ) ;
_pvhash = NULL ;
}
2001-12-13 03:07:29 +03:00
}
2002-03-05 23:03:09 +03:00
char * vgname_from_vgid ( struct cmd_context * cmd , struct id * vgid )
{
struct vgname_entry * vgn ;
char vgid_s [ ID_LEN + 1 ] ;
if ( ! _vgidhash | | ! vgid )
return NULL ;
memcpy ( vgid_s , vgid - > uuid , ID_LEN ) ;
vgid_s [ ID_LEN ] = ' \0 ' ;
if ( ! ( vgn = hash_lookup ( _vgidhash , vgid_s ) ) )
return NULL ;
return pool_strdup ( cmd - > mem , vgn - > vgname ) ;
}