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"
2002-02-11 18:48:34 +03:00
# include "ll-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-01-21 14:06:32 +03:00
# include "names.h"
# include <limits.h>
2002-02-12 14:15:45 +03:00
# include <linux/kdev_t.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 ;
out :
dm_task_destroy ( dmt ) ;
return r ;
}
2002-02-11 18:48:34 +03:00
static int _query ( struct logical_volume * lv , int ( * fn ) ( const char * ) )
2001-11-07 14:51:42 +03:00
{
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
if ( ! build_dm_name ( buffer , sizeof ( buffer ) , " " ,
2002-01-21 14:06:32 +03:00
lv - > vg - > name , lv - > name ) ) {
stack ;
2002-02-11 18:48:34 +03:00
return - 1 ;
2002-01-21 14:06:32 +03:00
}
2002-01-11 02:21:07 +03:00
2002-02-11 18:48:34 +03:00
return fn ( buffer ) ;
2002-01-11 02:21:07 +03:00
}
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-11 18:48:34 +03:00
return _query ( lv , device_active ) ;
2001-11-07 14:51:42 +03:00
}
2002-01-08 01:28:36 +03:00
int lv_suspended ( struct logical_volume * lv )
{
2002-02-11 18:48:34 +03:00
return _query ( lv , device_suspended ) ;
2002-01-08 01:28:36 +03:00
}
2001-11-08 19:15:58 +03:00
int lv_open_count ( struct logical_volume * lv )
2001-11-07 18:02:07 +03:00
{
2002-02-11 18:48:34 +03:00
return _query ( lv , device_open_count ) ;
}
2002-02-11 20:42:02 +03:00
/*
* Returns 1 if info structure populated , else 0 on failure .
*/
2002-02-11 18:48:34 +03:00
int lv_info ( struct logical_volume * lv , struct dm_info * info )
{
char buffer [ 128 ] ;
2001-11-07 18:02:07 +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 18:02:07 +03:00
stack ;
2002-02-11 20:42:02 +03:00
return 0 ;
2001-11-07 18:02:07 +03:00
}
2002-02-11 18:48:34 +03:00
return device_info ( buffer , info ) ;
2001-11-07 18:02:07 +03:00
}
2002-02-12 14:15:45 +03:00
static inline int _read_only_lv ( struct logical_volume * lv )
{
return ( lv - > status & LVM_WRITE ) & & ( lv - > vg - > status & LVM_WRITE ) ;
}
2001-11-28 20:52:27 +03:00
2002-02-11 18:48:34 +03:00
int lv_activate ( struct logical_volume * lv )
{
2002-02-12 14:15:45 +03:00
int r = 0 ;
struct dm_task * dmt ;
2002-02-11 18:48:34 +03:00
char buffer [ 128 ] ;
2001-11-28 20:52:27 +03:00
2002-02-11 18:48:34 +03:00
if ( test_mode ( ) ) {
_skip ( " Activation of '%s'. " , lv - > name ) ;
return 0 ;
2001-11-28 20:52:27 +03:00
}
2002-02-12 14:15:45 +03:00
/*
* Decide what we ' re going to call this device .
*/
2002-02-11 18:48:34 +03:00
if ( ! build_dm_name ( buffer , sizeof ( buffer ) , " " ,
lv - > vg - > name , lv - > name ) ) {
stack ;
return 0 ;
2001-11-05 16:37:13 +03:00
}
2002-02-12 14:15:45 +03:00
/*
* Create a task .
*/
if ( ! ( dmt = setup_dm_task ( buffer , DM_DEVICE_CREATE ) ) ) {
2002-02-11 18:48:34 +03:00
stack ;
return 0 ;
}
2001-12-05 02:20:27 +03:00
2002-02-12 14:15:45 +03:00
/*
* Populate it .
*/
if ( ! device_populate_lv ( dmt , lv ) ) {
2001-11-05 16:37:13 +03:00
stack ;
return 0 ;
}
2002-02-12 14:15:45 +03:00
/*
* Do we want a specific minor number ?
*/
if ( lv - > minor > = 0 ) {
if ( ! dm_task_set_minor ( dmt , MINOR ( lv - > minor ) ) ) {
log_error ( " Failed to set minor number for %s to %d "
" during activation. " , lv - > name , lv - > minor ) ;
goto out ;
} else
log_very_verbose ( " Set minor number for %s to %d. " ,
lv - > name , lv - > minor ) ;
}
/*
* Read only ?
*/
if ( ! _read_only_lv ( lv ) ) {
if ( ! dm_task_set_ro ( dmt ) ) {
log_error ( " Failed to set %s read-only during "
" activation. " , lv - > name ) ;
goto out ;
} else
log_very_verbose ( " Activating %s read-only " , lv - > name ) ;
}
/*
* Load this into the kernel .
*/
if ( ! ( r = dm_task_run ( dmt ) ) ) {
log_err ( " Activation failed. " ) ;
goto out ;
}
/*
* Create device nodes and symbolic links .
*/
if ( ! fs_add_lv ( lv , lv - > minor ) )
stack ;
out :
dm_task_destroy ( dmt ) ;
log_verbose ( " Logical volume %s%s activated " , lv - > name ,
r = = 1 ? " " : " not " ) ;
return r ;
}
static int _reload ( const char * name , struct logical_volume * lv )
{
int r = 0 ;
struct dm_task * dmt ;
/*
* Create a task .
*/
if ( ! ( dmt = setup_dm_task ( name , DM_DEVICE_RELOAD ) ) ) {
stack ;
return 0 ;
}
/*
* Populate it .
*/
if ( ! device_populate_lv ( dmt , lv ) ) {
stack ;
return 0 ;
}
/*
* Load this into the kernel .
*/
if ( ! ( r = dm_task_run ( dmt ) ) ) {
log_err ( " Activation failed. " ) ;
goto out ;
}
/*
* Create device nodes and symbolic links .
*/
if ( ! fs_add_lv ( lv , lv - > minor ) )
stack ;
out :
dm_task_destroy ( dmt ) ;
log_verbose ( " Logical volume %s%s re-activated " , lv - > name ,
r = = 1 ? " " : " not " ) ;
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 ;
char buffer [ 128 ] ;
2001-10-09 21:09:46 +04:00
2002-02-11 18:48:34 +03:00
if ( test_mode ( ) ) {
_skip ( " Reactivation of '%s'. " , lv - > name ) ;
2001-11-02 16:45:05 +03:00
return 0 ;
}
2001-10-09 20:05:34 +04:00
2002-02-12 14:15:45 +03:00
/*
* Decide what we ' re going to call this device .
*/
2002-02-11 18:48:34 +03:00
if ( ! build_dm_name ( buffer , sizeof ( buffer ) , " " ,
lv - > vg - > name , lv - > name ) ) {
stack ;
return 0 ;
2001-11-02 16:45:05 +03:00
}
2002-02-12 14:15:45 +03:00
/*
* Suspend the device if it isn ' t already .
*/
2002-02-11 18:48:34 +03:00
if ( ! device_suspended ( buffer ) & & ! device_suspend ( buffer ) ) {
stack ;
return 0 ;
2002-01-30 20:12:14 +03:00
}
2002-01-08 01:28:36 +03:00
2002-02-12 14:15:45 +03:00
r = _reload ( buffer , lv ) ;
2002-01-08 01:28:36 +03:00
2002-02-11 18:48:34 +03:00
if ( ! device_resume ( buffer ) ) {
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
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-11 18:48:34 +03:00
char buffer [ 128 ] ;
2001-11-28 21:03:11 +03:00
2002-02-11 18:48:34 +03:00
log_very_verbose ( " Deactivating %s " , lv - > name ) ;
if ( test_mode ( ) ) {
_skip ( " Deactivating '%s'. " , lv - > name ) ;
return 0 ;
}
2001-11-07 14:51:42 +03:00
2002-02-11 18:48:34 +03:00
if ( ! build_dm_name ( buffer , sizeof ( buffer ) , " " ,
lv - > vg - > name , lv - > name ) ) {
stack ;
return 0 ;
}
2001-11-07 14:51:42 +03:00
2002-02-11 18:48:34 +03:00
if ( ! device_deactivate ( buffer ) ) {
2001-11-07 14:51:42 +03:00
stack ;
return 0 ;
}
2002-02-11 18:48:34 +03:00
fs_del_lv ( lv ) ;
2001-11-07 14:51:42 +03:00
2002-02-11 18:48:34 +03:00
return 1 ;
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-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-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-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-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-11-02 16:45:05 +03:00
int lv_update_write_access ( struct logical_volume * lv )
{
2002-01-08 01:28:36 +03:00
struct dm_info info ;
if ( ! lv_info ( lv , & info ) ) {
stack ;
return 0 ;
}
if ( ! info . exists | | info . suspended )
/* Noop */
return 1 ;
return lv_reactivate ( lv ) ;
2001-11-02 16:45:05 +03:00
}
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 ;
}