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-10-09 20:05:34 +04:00
2001-11-02 19:45:44 +03:00
static void _build_lv_name ( char * buffer , size_t s , struct logical_volume * lv )
{
snprintf ( buffer , s , " %s_%s " , lv - > vg - > name , lv - > name ) ;
}
2001-11-07 18:02:07 +03:00
static struct dm_task * _setup_task ( struct logical_volume * lv , int task )
2001-11-07 14:51:42 +03:00
{
char name [ 128 ] ;
struct dm_task * dmt ;
if ( ! ( dmt = dm_task_create ( task ) ) ) {
stack ;
return NULL ;
}
_build_lv_name ( name , sizeof ( name ) , lv ) ;
dm_task_set_name ( dmt , name ) ;
return dmt ;
}
2001-11-21 22:32:35 +03:00
int lv_info ( struct logical_volume * lv , struct dm_info * info )
2001-11-07 14:51:42 +03:00
{
2001-11-19 18:38:39 +03:00
int r = 0 ;
2001-11-07 14:51:42 +03:00
struct dm_task * dmt ;
if ( ! ( dmt = _setup_task ( lv , DM_DEVICE_INFO ) ) ) {
stack ;
return 0 ;
}
if ( ! dm_task_run ( dmt ) ) {
2001-11-07 18:02:07 +03:00
stack ;
2001-11-19 18:38:39 +03:00
goto out ;
2001-11-07 18:02:07 +03:00
}
2001-11-19 18:38:39 +03:00
if ( ! dm_task_get_info ( dmt , info ) ) {
stack ;
goto out ;
}
r = 1 ;
2001-11-07 18:02:07 +03:00
2001-11-19 18:38:39 +03:00
out :
2001-11-07 18:02:07 +03:00
dm_task_destroy ( dmt ) ;
2001-11-19 18:38:39 +03:00
return r ;
2001-11-07 18:02:07 +03:00
}
2001-11-08 19:15:58 +03:00
int lv_active ( struct logical_volume * lv )
2001-11-07 18:02:07 +03:00
{
2001-11-08 19:15:58 +03:00
int r = - 1 ;
2001-11-19 18:38:39 +03:00
struct dm_info info ;
2001-11-07 18:02:07 +03:00
2001-11-21 22:32:35 +03:00
if ( ! lv_info ( lv , & info ) ) {
2001-11-07 14:51:42 +03:00
stack ;
2001-11-08 19:15:58 +03:00
return r ;
2001-11-07 14:51:42 +03:00
}
2001-11-19 18:38:39 +03:00
return info . exists ;
2001-11-07 14:51:42 +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
{
2001-11-08 19:15:58 +03:00
int r = - 1 ;
2001-11-19 18:38:39 +03:00
struct dm_info info ;
2001-11-07 18:02:07 +03:00
2001-11-21 22:32:35 +03:00
if ( ! lv_info ( lv , & info ) ) {
2001-11-07 18:02:07 +03:00
stack ;
2001-11-08 19:15:58 +03:00
return r ;
2001-11-07 18:02:07 +03:00
}
2001-11-19 18:38:39 +03:00
return info . open_count ;
2001-11-07 18:02:07 +03:00
}
2001-11-05 16:37:13 +03:00
/*
* Creates a target for the next contiguous run of
* extents .
*/
static int _emit_target ( struct dm_task * dmt , struct logical_volume * lv ,
unsigned int * ple )
{
char params [ 1024 ] ;
unsigned int le = * ple ;
uint64_t esize = lv - > vg - > extent_size ;
int i , count = 0 ;
struct pe_specifier * pes , * first = NULL ;
for ( i = le ; i < lv - > le_count ; i + + ) {
pes = lv - > map + i ;
if ( ! first )
first = pes ;
2001-11-19 18:44:06 +03:00
/*
* check that we ' re still contiguous .
*/
else if ( ( pes - > pv ! = first - > pv ) | |
( pes - > pe ! = first - > pe + count ) )
break ;
2001-11-05 16:37:13 +03:00
count + + ;
}
2001-11-15 18:18:53 +03:00
snprintf ( params , sizeof ( params ) , " %s % " PRIu64 ,
2001-11-05 16:37:13 +03:00
dev_name ( first - > pv - > dev ) ,
first - > pv - > pe_start + ( esize * first - > pe ) ) ;
if ( ! dm_task_add_target ( dmt , esize * le , esize * count ,
" linear " , params ) ) {
stack ;
return 0 ;
}
* ple = i ;
return 1 ;
}
2001-11-07 14:51:42 +03:00
int _load ( struct logical_volume * lv , int task )
2001-10-09 20:05:34 +04:00
{
2001-11-02 16:45:05 +03:00
int r = 0 ;
2001-11-05 16:37:13 +03:00
uint32_t le = 0 ;
2001-11-02 16:45:05 +03:00
struct dm_task * dmt ;
2001-10-09 21:09:46 +04:00
2001-11-07 14:51:42 +03:00
if ( ! ( dmt = _setup_task ( lv , task ) ) ) {
2001-11-02 16:45:05 +03:00
stack ;
return 0 ;
}
2001-10-09 20:05:34 +04:00
2001-11-05 16:37:13 +03:00
/*
* Merge adjacent extents .
*/
while ( le < lv - > le_count ) {
if ( ! _emit_target ( dmt , lv , & le ) ) {
2001-11-12 20:21:25 +03:00
log_error ( " Unable to activate logical volume '%s' " ,
2001-11-05 16:37:13 +03:00
lv - > name ) ;
2001-11-02 16:45:05 +03:00
goto out ;
}
}
2001-11-02 19:28:04 +03:00
if ( ! ( r = dm_task_run ( dmt ) ) )
2001-11-02 16:45:05 +03:00
stack ;
2001-11-21 22:32:35 +03:00
log_verbose ( " Logical volume %s activated " , lv - > name ) ;
2001-11-02 16:45:05 +03:00
out :
2001-11-02 19:28:04 +03:00
dm_task_destroy ( dmt ) ;
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
2001-11-07 14:51:42 +03:00
/* FIXME: Always display error msg */
int lv_activate ( struct logical_volume * lv )
2001-10-31 20:59:52 +03:00
{
2001-11-12 15:20:58 +03:00
return _load ( lv , DM_DEVICE_CREATE ) & & fs_add_lv ( lv ) ;
2001-11-07 14:51:42 +03:00
}
int _suspend ( struct logical_volume * lv , int sus )
{
int r ;
struct dm_task * dmt ;
int task = sus ? DM_DEVICE_SUSPEND : DM_DEVICE_RESUME ;
if ( ! ( dmt = _setup_task ( lv , task ) ) ) {
stack ;
return 0 ;
}
if ( ! ( r = dm_task_run ( dmt ) ) )
log_err ( " Couldn't %s device '%s' " , sus ? " suspend " : " resume " ,
lv - > name ) ;
dm_task_destroy ( dmt ) ;
return r ;
}
int lv_reactivate ( struct logical_volume * lv )
{
int r ;
if ( ! _suspend ( lv , 1 ) ) {
stack ;
return 0 ;
}
2001-10-31 20:59:52 +03:00
2001-11-07 14:51:42 +03:00
r = _load ( lv , DM_DEVICE_RELOAD ) ;
2001-11-02 16:45:05 +03:00
2001-11-07 14:51:42 +03:00
if ( ! _suspend ( lv , 0 ) ) {
stack ;
return 0 ;
}
2001-10-31 20:59:52 +03:00
2001-11-07 14:51:42 +03:00
return r ;
2001-10-31 20:59:52 +03:00
}
2001-11-02 16:45:05 +03:00
int lv_deactivate ( struct logical_volume * lv )
{
2001-11-02 19:28:04 +03:00
int r ;
2001-11-02 19:45:44 +03:00
struct dm_task * dmt ;
2001-11-07 14:51:42 +03:00
if ( ! ( dmt = _setup_task ( lv , DM_DEVICE_REMOVE ) ) ) {
2001-11-02 16:45:05 +03:00
stack ;
return 0 ;
}
2001-11-02 19:28:04 +03:00
if ( ! ( r = dm_task_run ( dmt ) ) )
2001-11-02 16:45:05 +03:00
stack ;
dm_task_destroy ( dmt ) ;
2001-11-12 15:20:58 +03:00
fs_del_lv ( lv ) ;
2001-11-02 16:45:05 +03:00
return r ;
}
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 ) {
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 )
{
return 0 ;
}
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 ) {
lv = & ( list_item ( lvh , struct lv_list ) - > lv ) ;
2001-10-31 20:59:52 +03:00
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 ) {
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 ) {
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 ;
}