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
/*
2001-11-27 19:37:33 +03:00
* Emit a target for a given segment .
2001-11-05 16:37:13 +03:00
*/
2001-11-27 19:37:33 +03:00
static int _emit_target ( struct dm_task * dmt , struct stripe_segment * seg )
2001-11-05 16:37:13 +03:00
{
char params [ 1024 ] ;
2001-11-27 20:39:15 +03:00
uint64_t esize = seg - > lv - > vg - > extent_size ;
2001-11-27 19:37:33 +03:00
uint32_t s , stripes = seg - > stripes ;
int w , tw ;
2001-11-28 20:52:27 +03:00
const char * no_space =
" Insufficient space to write target parameters. " ;
2001-11-27 19:37:33 +03:00
2001-11-28 20:52:27 +03:00
if ( stripes > 1 ) {
tw = snprintf ( params , sizeof ( params ) , " %u %u " ,
stripes , seg - > stripe_size ) ;
if ( tw < 0 ) {
log_err ( no_space ) ;
return 0 ;
}
w = tw ;
}
for ( s = 0 ; s < stripes ; s + + , w + = tw ) {
2001-11-27 19:37:33 +03:00
tw = snprintf ( params + w , sizeof ( params ) - w ,
" %s % " PRIu64 " %s " ,
dev_name ( seg - > area [ s ] . pv - > dev ) ,
( seg - > area [ s ] . pv - > pe_start +
( esize * seg - > area [ s ] . pe ) ) ,
s = = ( stripes - 1 ) ? " " : " " ) ;
if ( tw < 0 ) {
2001-11-28 20:52:27 +03:00
log_err ( no_space ) ;
2001-11-27 19:37:33 +03:00
return 0 ;
}
2001-11-05 16:37:13 +03:00
}
2001-11-27 20:39:15 +03:00
if ( ! dm_task_add_target ( dmt , esize * seg - > le , esize * seg - > len ,
2001-11-27 19:37:33 +03:00
stripes = = 1 ? " linear " : " striped " ,
params ) ) {
2001-11-05 16:37:13 +03:00
stack ;
return 0 ;
}
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 ;
struct dm_task * dmt ;
2001-11-27 19:37:33 +03:00
struct list * segh ;
struct stripe_segment * seg ;
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-27 19:37:33 +03:00
list_iterate ( segh , & lv - > segments ) {
seg = list_item ( segh , struct stripe_segment ) ;
if ( ! _emit_target ( dmt , seg ) ) {
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 ;
}