2001-10-09 20:05:34 +04:00
/*
* Copyright ( C ) 2001 Sistina Software ( UK ) Limited .
*
2001-10-31 15:47:01 +03:00
* This file is released under the LGPL .
2001-10-09 20:05:34 +04:00
*/
2001-10-16 20:25:28 +04:00
# include "metadata.h"
2001-10-09 20:05:34 +04:00
# include "activate.h"
2001-11-15 17:27:51 +03:00
# include "display.h"
2001-11-02 19:28:04 +03:00
# include "log.h"
2001-11-12 15:20:58 +03:00
# include "fs.h"
2001-12-31 22:09:51 +03:00
# include "lvm-string.h"
2002-02-25 15:56:16 +03:00
# include "pool.h"
# include "toolcontext.h"
2002-02-26 14:49:17 +03:00
# include "dev_manager.h"
2002-01-21 14:06:32 +03:00
# include <limits.h>
2002-02-12 14:15:45 +03:00
# include <linux/kdev_t.h>
2002-02-18 18:52:48 +03:00
# include <fcntl.h>
2002-01-21 14:06:32 +03:00
2002-02-11 18:48:34 +03:00
# define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args)
2001-10-09 20:05:34 +04:00
2002-01-17 19:39:24 +03:00
int library_version ( char * version , size_t size )
{
if ( ! dm_get_library_version ( version , size ) )
return 0 ;
return 1 ;
}
int driver_version ( char * version , size_t size )
{
int r = 0 ;
struct dm_task * dmt ;
log_very_verbose ( " Getting driver version " ) ;
if ( ! ( dmt = dm_task_create ( DM_DEVICE_VERSION ) ) ) {
stack ;
return 0 ;
}
if ( ! dm_task_run ( dmt ) )
log_error ( " Failed to get driver version " ) ;
if ( ! dm_task_get_driver_version ( dmt , version , size ) )
goto out ;
r = 1 ;
2002-02-26 14:49:17 +03:00
out :
2002-01-17 19:39:24 +03:00
dm_task_destroy ( dmt ) ;
return r ;
}
2002-02-26 14:49:17 +03:00
/*
* Returns 1 if info structure populated , else 0 on failure .
*/
int lv_info ( struct logical_volume * lv , struct dm_info * info )
2001-11-07 14:51:42 +03:00
{
2002-02-26 14:49:17 +03:00
int r ;
struct dev_manager * dm ;
2002-01-11 02:21:07 +03:00
2002-02-26 14:49:17 +03:00
if ( ! ( dm = dev_manager_create ( lv - > vg - > name ) ) ) {
2002-01-21 14:06:32 +03:00
stack ;
2002-02-26 14:49:17 +03:00
return 0 ;
2002-01-21 14:06:32 +03:00
}
2002-01-11 02:21:07 +03:00
2002-02-26 14:49:17 +03:00
if ( ! ( r = dev_manager_info ( dm , lv , info ) ) )
stack ;
2002-01-11 02:21:07 +03:00
2002-02-26 14:49:17 +03:00
dev_manager_destroy ( dm ) ;
return r ;
}
2002-02-11 20:42:02 +03:00
/*
2002-02-12 14:15:45 +03:00
* These three functions return the number of LVs in the state ,
2002-02-11 20:42:02 +03:00
* or - 1 on error .
*/
2001-11-08 19:15:58 +03:00
int lv_active ( struct logical_volume * lv )
2001-11-07 18:02:07 +03:00
{
2002-02-26 14:49:17 +03:00
struct dm_info info ;
2001-11-07 18:02:07 +03:00
2002-02-26 14:49:17 +03:00
if ( ! lv_info ( lv , & info ) ) {
2001-11-07 18:02:07 +03:00
stack ;
2002-02-26 14:49:17 +03:00
return - 1 ;
2001-11-07 18:02:07 +03:00
}
2002-02-26 14:49:17 +03:00
return info . exists ;
2001-11-07 18:02:07 +03:00
}
2002-02-26 14:49:17 +03:00
int lv_suspended ( struct logical_volume * lv )
2002-02-11 18:48:34 +03:00
{
2002-02-26 14:49:17 +03:00
struct dm_info info ;
2001-11-28 20:52:27 +03:00
2002-02-26 14:49:17 +03:00
if ( ! lv_info ( lv , & info ) ) {
2001-11-05 16:37:13 +03:00
stack ;
2002-02-26 14:49:17 +03:00
return - 1 ;
2002-02-12 14:15:45 +03:00
}
2002-02-26 14:49:17 +03:00
return info . suspended ;
2002-02-12 14:15:45 +03:00
}
2002-02-26 14:49:17 +03:00
int lv_open_count ( struct logical_volume * lv )
2002-02-18 18:52:48 +03:00
{
2002-02-26 14:49:17 +03:00
struct dm_info info ;
2002-02-18 18:52:48 +03:00
2002-02-26 14:49:17 +03:00
if ( ! lv_info ( lv , & info ) ) {
2002-02-18 18:52:48 +03:00
stack ;
2002-02-26 14:49:17 +03:00
return - 1 ;
2002-02-18 18:52:48 +03:00
}
2002-02-26 14:49:17 +03:00
return info . open_count ;
2002-02-18 18:52:48 +03:00
}
2002-02-26 14:49:17 +03:00
int lv_activate ( struct logical_volume * lv )
2002-02-12 14:15:45 +03:00
{
2002-02-26 14:49:17 +03:00
int r ;
struct dev_manager * dm ;
2002-02-12 14:15:45 +03:00
2002-02-26 14:49:17 +03:00
if ( ! ( dm = dev_manager_create ( lv - > vg - > name ) ) ) {
2002-02-12 14:15:45 +03:00
stack ;
return 0 ;
}
2002-02-26 14:49:17 +03:00
if ( ! ( r = dev_manager_activate ( dm , lv ) ) )
2002-02-12 14:15:45 +03:00
stack ;
2002-02-26 14:49:17 +03:00
dev_manager_destroy ( dm ) ;
2002-02-12 14:15:45 +03:00
return r ;
2001-11-05 16:37:13 +03:00
}
2002-02-11 18:48:34 +03:00
int lv_reactivate ( struct logical_volume * lv )
2001-10-09 20:05:34 +04:00
{
2002-02-11 18:48:34 +03:00
int r ;
2002-02-26 14:49:17 +03:00
struct dev_manager * dm ;
2001-10-09 20:05:34 +04:00
2002-02-26 14:49:17 +03:00
if ( ! ( dm = dev_manager_create ( lv - > vg - > name ) ) ) {
2002-02-11 18:48:34 +03:00
stack ;
return 0 ;
2001-11-02 16:45:05 +03:00
}
2002-02-26 14:49:17 +03:00
if ( ! ( r = dev_manager_reactivate ( dm , lv ) ) )
2002-02-11 18:48:34 +03:00
stack ;
2001-11-02 16:45:05 +03:00
2002-02-26 14:49:17 +03:00
dev_manager_destroy ( dm ) ;
2001-11-02 16:45:05 +03:00
return r ;
2001-10-09 20:05:34 +04:00
}
2001-10-16 20:25:28 +04:00
2002-02-11 18:48:34 +03:00
int lv_deactivate ( struct logical_volume * lv )
2001-10-31 20:59:52 +03:00
{
2002-02-26 14:49:17 +03:00
int r ;
struct dev_manager * dm ;
2001-11-07 14:51:42 +03:00
2002-02-26 14:49:17 +03:00
if ( ! ( dm = dev_manager_create ( lv - > vg - > name ) ) ) {
2002-02-11 18:48:34 +03:00
stack ;
return 0 ;
}
2001-11-07 14:51:42 +03:00
2002-02-26 14:49:17 +03:00
if ( ! ( r = dev_manager_deactivate ( dm , lv ) ) )
2001-11-07 14:51:42 +03:00
stack ;
2002-02-26 14:49:17 +03:00
dev_manager_destroy ( dm ) ;
return r ;
2001-11-07 14:51:42 +03:00
}
2002-01-11 02:21:07 +03:00
int lv_suspend ( struct logical_volume * lv )
{
2002-02-26 14:49:17 +03:00
#if 0
2002-02-11 18:48:34 +03:00
char buffer [ 128 ] ;
2002-01-11 02:21:07 +03:00
2002-02-11 18:48:34 +03:00
log_very_verbose ( " Suspending %s " , lv - > name ) ;
if ( test_mode ( ) ) {
_skip ( " Suspending '%s'. " , lv - > name ) ;
2001-11-28 21:03:11 +03:00
return 0 ;
2002-02-11 18:48:34 +03:00
}
2001-11-28 21:03:11 +03:00
2002-02-11 18:48:34 +03:00
if ( ! build_dm_name ( buffer , sizeof ( buffer ) , " " ,
lv - > vg - > name , lv - > name ) ) {
2001-11-07 14:51:42 +03:00
stack ;
return 0 ;
}
2001-10-31 20:59:52 +03:00
2002-02-11 18:48:34 +03:00
if ( ! device_suspend ( buffer ) ) {
2001-11-07 14:51:42 +03:00
stack ;
return 0 ;
}
2001-10-31 20:59:52 +03:00
2002-02-11 18:48:34 +03:00
fs_del_lv ( lv ) ;
2001-10-31 20:59:52 +03:00
2002-02-11 18:48:34 +03:00
return 1 ;
2002-02-26 14:49:17 +03:00
# else
log_err ( " lv_suspend not implemented. " ) ;
return 1 ;
# endif
2002-02-11 18:48:34 +03:00
}
2002-01-11 02:21:07 +03:00
2002-02-11 18:48:34 +03:00
int lv_rename ( const char * old_name , struct logical_volume * lv )
2001-11-02 16:45:05 +03:00
{
2002-02-26 14:49:17 +03:00
#if 0
2002-02-11 18:48:34 +03:00
int r = 0 ;
char new_name [ PATH_MAX ] ;
2001-11-02 19:45:44 +03:00
struct dm_task * dmt ;
2002-02-11 18:48:34 +03:00
if ( test_mode ( ) ) {
_skip ( " Rename '%s' to '%s'. " , old_name , lv - > name ) ;
2001-11-28 21:03:11 +03:00
return 0 ;
2002-02-11 18:48:34 +03:00
}
2001-11-28 21:03:11 +03:00
2002-02-11 18:48:34 +03:00
if ( ! ( dmt = setup_dm_task ( old_name , DM_DEVICE_RENAME ) ) ) {
2001-11-02 16:45:05 +03:00
stack ;
return 0 ;
}
2002-02-11 18:48:34 +03:00
if ( ! build_dm_name ( new_name , sizeof ( new_name ) , " " ,
lv - > vg - > name , lv - > name ) ) {
2001-11-02 16:45:05 +03:00
stack ;
2002-02-11 18:48:34 +03:00
return 0 ;
}
2001-11-02 16:45:05 +03:00
2002-02-11 18:48:34 +03:00
if ( ! dm_task_set_newname ( dmt , new_name ) ) {
stack ;
r = 0 ;
goto end ;
}
2001-11-12 15:20:58 +03:00
2002-02-11 18:48:34 +03:00
if ( ! dm_task_run ( dmt ) ) {
stack ;
r = 0 ;
goto end ;
}
fs_rename_lv ( old_name , lv ) ;
2001-11-12 15:20:58 +03:00
2002-02-11 18:48:34 +03:00
end :
dm_task_destroy ( dmt ) ;
2001-11-02 16:45:05 +03:00
return r ;
2002-02-26 14:49:17 +03:00
# else
log_err ( " lv_rename not implemented yet. " ) ;
return 1 ;
# endif
2001-11-02 16:45:05 +03:00
}
2002-02-18 18:52:48 +03:00
/*
* Zero the start of a cow store so the driver spots that it is a
* new store .
*/
int lv_setup_cow_store ( struct logical_volume * lv )
{
2002-02-26 14:49:17 +03:00
#if 0
2002-02-18 18:52:48 +03:00
char buffer [ 128 ] ;
char path [ PATH_MAX ] ;
struct device * dev ;
/*
* Decide what we ' re going to call this device .
*/
if ( ! build_dm_name ( buffer , sizeof ( buffer ) , " cow_init " ,
lv - > vg - > name , lv - > name ) ) {
stack ;
return 0 ;
}
if ( ! _lv_activate_named ( lv , buffer ) ) {
log_err ( " Unable to activate cow store logical volume. " ) ;
return 0 ;
}
/* FIXME: hard coded dir */
if ( lvm_snprintf ( path , sizeof ( path ) , " /dev/device-mapper/%s " ,
buffer ) < 0 ) {
log_error ( " Name too long - device not zeroed (%s) " ,
lv - > name ) ;
return 0 ;
}
if ( ! ( dev = dev_cache_get ( path , NULL ) ) ) {
log_error ( " \" %s \" not found: device not zeroed " , path ) ;
return 0 ;
}
if ( ! ( dev_open ( dev , O_WRONLY ) ) )
return 0 ;
dev_zero ( dev , 0 , 4096 ) ;
dev_close ( dev ) ;
return 1 ;
2002-02-26 14:49:17 +03:00
# else
return 0 ;
# endif
2002-02-18 18:52:48 +03:00
}
2002-02-11 18:48:34 +03:00
2001-11-07 14:51:42 +03:00
int activate_lvs_in_vg ( struct volume_group * vg )
{
struct list * lvh ;
struct logical_volume * lv ;
2001-11-08 19:15:58 +03:00
int count = 0 ;
2001-11-07 14:51:42 +03:00
list_iterate ( lvh , & vg - > lvs ) {
2002-01-21 19:49:32 +03:00
lv = list_item ( lvh , struct lv_list ) - > lv ;
2001-11-08 19:15:58 +03:00
count + = ( ! lv_active ( lv ) & & lv_activate ( lv ) ) ;
2001-11-07 14:51:42 +03:00
}
return count ;
}
2001-10-16 20:25:28 +04:00
int deactivate_lvs_in_vg ( struct volume_group * vg )
{
2001-10-31 20:59:52 +03:00
struct list * lvh ;
2001-11-07 14:51:42 +03:00
struct logical_volume * lv ;
2001-11-08 19:15:58 +03:00
int count = 0 ;
2001-11-07 14:51:42 +03:00
list_iterate ( lvh , & vg - > lvs ) {
2002-01-21 19:49:32 +03:00
lv = list_item ( lvh , struct lv_list ) - > lv ;
2001-11-08 19:15:58 +03:00
count + = ( ( lv_active ( lv ) = = 1 ) & & lv_deactivate ( lv ) ) ;
2001-11-07 14:51:42 +03:00
}
2001-10-31 20:59:52 +03:00
2001-11-07 14:51:42 +03:00
return count ;
2001-10-16 20:25:28 +04:00
}
2001-11-02 19:28:04 +03:00
int lvs_in_vg_activated ( struct volume_group * vg )
{
2001-11-07 14:51:42 +03:00
struct list * lvh ;
struct logical_volume * lv ;
2001-11-08 19:15:58 +03:00
int count = 0 ;
2001-11-07 14:51:42 +03:00
list_iterate ( lvh , & vg - > lvs ) {
2002-01-21 19:49:32 +03:00
lv = list_item ( lvh , struct lv_list ) - > lv ;
2001-11-08 19:15:58 +03:00
count + = ( lv_active ( lv ) = = 1 ) ;
2001-11-07 14:51:42 +03:00
}
return count ;
2001-11-02 19:28:04 +03:00
}
2001-11-07 18:02:07 +03:00
int lvs_in_vg_opened ( struct volume_group * vg )
{
struct list * lvh ;
struct logical_volume * lv ;
2001-11-08 19:15:58 +03:00
int count = 0 ;
2001-11-07 18:02:07 +03:00
list_iterate ( lvh , & vg - > lvs ) {
2002-01-21 19:49:32 +03:00
lv = list_item ( lvh , struct lv_list ) - > lv ;
2001-11-08 19:15:58 +03:00
count + = ( lv_open_count ( lv ) = = 1 ) ;
2001-11-07 18:02:07 +03:00
}
return count ;
}
2002-02-25 15:56:16 +03:00
/* FIXME Currently lvid is "vgname/lv_uuid". Needs to be vg_uuid/lv_uuid. */
2002-02-26 14:49:17 +03:00
static struct logical_volume * _lv_from_lvid ( struct cmd_context * cmd ,
2002-02-25 15:56:16 +03:00
const char * lvid )
{
struct lv_list * lvl ;
struct volume_group * vg ;
char * vgname ;
char * slash ;
if ( ! ( slash = strchr ( lvid , ' / ' ) ) ) {
log_error ( " Invalid VG/LV identifier: %s " , lvid ) ;
return NULL ;
}
vgname = pool_strdup ( cmd - > mem , lvid ) ;
* strchr ( vgname , ' / ' ) = ' \0 ' ;
log_verbose ( " Finding volume group \" %s \" " , vgname ) ;
if ( ! ( vg = cmd - > fid - > ops - > vg_read ( cmd - > fid , vgname ) ) ) {
log_error ( " Volume group \" %s \" doesn't exist " , vgname ) ;
return NULL ;
}
if ( vg - > status & EXPORTED_VG ) {
log_error ( " Volume group \" %s \" is exported " , vgname ) ;
return NULL ;
}
if ( ! ( lvl = find_lv_in_vg_by_uuid ( vg , slash + 1 ) ) ) {
2002-02-27 15:26:41 +03:00
log_verbose ( " Can't find logical volume id %s " , lvid ) ;
2002-02-25 15:56:16 +03:00
return NULL ;
}
return lvl - > lv ;
}
int lv_suspend_if_active ( struct cmd_context * cmd , const char * lvid )
{
struct logical_volume * lv ;
if ( ! ( lv = _lv_from_lvid ( cmd , lvid ) ) )
return 0 ;
2002-02-27 15:26:41 +03:00
if ( lv_active ( lv ) > 0 )
2002-02-25 15:56:16 +03:00
lv_suspend ( lv ) ;
return 1 ;
}
int lv_resume_if_active ( struct cmd_context * cmd , const char * lvid )
{
struct logical_volume * lv ;
if ( ! ( lv = _lv_from_lvid ( cmd , lvid ) ) )
return 0 ;
2002-02-27 15:26:41 +03:00
if ( ( lv_active ( lv ) > 0 ) & & lv_suspended ( lv ) )
2002-02-25 15:56:16 +03:00
lv_reactivate ( lv ) ;
return 1 ;
}
2002-02-27 15:26:41 +03:00
int lv_deactivate_if_active ( struct cmd_context * cmd , const char * lvid )
{
struct logical_volume * lv ;
if ( ! ( lv = _lv_from_lvid ( cmd , lvid ) ) )
return 0 ;
if ( lv_active ( lv ) > 0 )
lv_deactivate ( lv ) ;
return 1 ;
}
int lv_activate_if_inactive ( struct cmd_context * cmd , const char * lvid )
{
struct logical_volume * lv ;
if ( ! ( lv = _lv_from_lvid ( cmd , lvid ) ) )
return 0 ;
if ( ! lv_active ( lv ) )
lv_activate ( lv ) ;
return 1 ;
}