2009-07-24 03:40:05 +04:00
/*
* Copyright ( C ) 2008 , 2009 Red Hat , Inc . All rights reserved .
*
* This file is part of LVM2 .
*
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v .2 .1 .
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include "lib.h"
2010-09-30 18:07:47 +04:00
# include "metadata.h"
2009-07-24 03:40:05 +04:00
# include "lvm-string.h"
2009-07-26 06:34:36 +04:00
# include "defaults.h"
# include "segtype.h"
2009-07-27 00:57:37 +04:00
# include "locking.h"
2009-07-27 00:58:11 +04:00
# include "activate.h"
2010-02-24 21:16:26 +03:00
# include "lvm_misc.h"
2010-12-15 02:20:58 +03:00
# include "lvm2app.h"
2009-07-27 00:57:37 +04:00
2010-02-24 21:16:26 +03:00
static int _lv_check_handle ( const lv_t lv , const int vg_writeable )
{
if ( ! lv | | ! lv - > vg | | vg_read_error ( lv - > vg ) )
return - 1 ;
if ( vg_writeable & & ! vg_check_write_mode ( lv - > vg ) )
return - 1 ;
return 0 ;
}
2009-07-26 17:06:59 +04:00
/* FIXME: have lib/report/report.c _disp function call lv_size()? */
2009-08-13 16:17:32 +04:00
uint64_t lvm_lv_get_size ( const lv_t lv )
2009-07-26 17:06:59 +04:00
{
2010-02-16 03:27:01 +03:00
return SECTOR_SIZE * lv_size ( lv ) ;
2009-07-26 17:06:59 +04:00
}
2010-04-19 19:22:24 +04:00
const char * lvm_lv_get_uuid ( const lv_t lv )
2009-07-24 03:40:05 +04:00
{
2010-09-30 18:07:47 +04:00
return lv_uuid_dup ( lv ) ;
2009-07-24 03:40:05 +04:00
}
2010-04-19 19:22:24 +04:00
const char * lvm_lv_get_name ( const lv_t lv )
2009-07-24 03:40:05 +04:00
{
2010-04-19 19:22:24 +04:00
return dm_pool_strndup ( lv - > vg - > vgmem , ( const char * ) lv - > name ,
NAME_LEN + 1 ) ;
2009-07-24 03:40:05 +04:00
}
2010-10-25 18:09:08 +04:00
struct lvm_property_value lvm_lv_get_property ( const lv_t lv , const char * name )
{
2010-11-17 23:12:39 +03:00
return get_property ( NULL , NULL , lv , NULL , NULL , name ) ;
2010-11-17 23:09:42 +03:00
}
struct lvm_property_value lvm_lvseg_get_property ( const lvseg_t lvseg ,
const char * name )
{
2010-11-17 23:12:39 +03:00
return get_property ( NULL , NULL , NULL , lvseg , NULL , name ) ;
2010-10-25 18:09:08 +04:00
}
2009-08-13 16:17:32 +04:00
uint64_t lvm_lv_is_active ( const lv_t lv )
2009-07-27 00:58:11 +04:00
{
struct lvinfo info ;
2011-02-03 04:24:46 +03:00
if ( lv_info ( lv - > vg - > cmd , lv , 0 , & info , 0 , 0 ) & &
2009-07-27 00:58:11 +04:00
info . exists & & info . live_table )
return 1 ;
return 0 ;
}
2009-08-13 16:17:32 +04:00
uint64_t lvm_lv_is_suspended ( const lv_t lv )
2009-07-27 00:58:11 +04:00
{
struct lvinfo info ;
2011-02-03 04:24:46 +03:00
if ( lv_info ( lv - > vg - > cmd , lv , 0 , & info , 0 , 0 ) & &
2009-07-27 00:58:11 +04:00
info . exists & & info . suspended )
return 1 ;
return 0 ;
}
2010-02-24 21:16:26 +03:00
int lvm_lv_add_tag ( lv_t lv , const char * tag )
{
if ( _lv_check_handle ( lv , 1 ) )
return - 1 ;
if ( ! lv_change_tag ( lv , tag , 1 ) )
return - 1 ;
return 0 ;
}
int lvm_lv_remove_tag ( lv_t lv , const char * tag )
{
if ( _lv_check_handle ( lv , 1 ) )
return - 1 ;
if ( ! lv_change_tag ( lv , tag , 0 ) )
return - 1 ;
return 0 ;
}
struct dm_list * lvm_lv_get_tags ( const lv_t lv )
{
return tag_list_copy ( lv - > vg - > vgmem , & lv - > tags ) ;
}
2009-07-26 06:34:36 +04:00
/* Set defaults for non-segment specific LV parameters */
static void _lv_set_default_params ( struct lvcreate_params * lp ,
2009-08-13 16:16:45 +04:00
vg_t vg , const char * lvname ,
2009-07-26 06:34:36 +04:00
uint64_t extents )
{
lp - > zero = 1 ;
lp - > major = - 1 ;
lp - > minor = - 1 ;
2011-06-01 23:21:03 +04:00
lp - > activate = CHANGE_AY ;
2009-07-26 06:34:36 +04:00
lp - > vg_name = vg - > name ;
lp - > lv_name = lvname ; /* FIXME: check this for safety */
lp - > pvh = & vg - > pvs ;
lp - > extents = extents ;
lp - > permission = LVM_READ | LVM_WRITE ;
lp - > read_ahead = DM_READ_AHEAD_NONE ;
lp - > alloc = ALLOC_INHERIT ;
2010-11-11 20:29:05 +03:00
dm_list_init ( & lp - > tags ) ;
2009-07-26 06:34:36 +04:00
}
/* Set default for linear segment specific LV parameters */
2012-02-13 15:25:56 +04:00
static int _lv_set_default_linear_params ( struct cmd_context * cmd ,
2009-07-26 06:34:36 +04:00
struct lvcreate_params * lp )
{
2012-02-13 15:25:56 +04:00
if ( ! ( lp - > segtype = get_segtype_from_string ( cmd , " striped " ) ) ) {
log_error ( INTERNAL_ERROR " Segtype striped not found. " ) ;
return 0 ;
}
2009-07-26 06:34:36 +04:00
lp - > stripes = 1 ;
lp - > stripe_size = DEFAULT_STRIPESIZE * 2 ;
2012-02-13 15:25:56 +04:00
return 1 ;
2009-07-26 06:34:36 +04:00
}
2009-07-28 17:16:40 +04:00
/*
* FIXME : This function should probably not commit to disk but require calling
* lvm_vg_write . However , this appears to be non - trivial change until
* lv_create_single is refactored by segtype .
*/
2009-08-13 16:17:32 +04:00
lv_t lvm_vg_create_lv_linear ( vg_t vg , const char * name , uint64_t size )
2009-07-26 06:34:36 +04:00
{
struct lvcreate_params lp ;
uint64_t extents ;
struct lv_list * lvl ;
if ( vg_read_error ( vg ) )
return NULL ;
2009-07-28 19:14:56 +04:00
if ( ! vg_check_write_mode ( vg ) )
return NULL ;
2009-07-26 06:34:36 +04:00
memset ( & lp , 0 , sizeof ( lp ) ) ;
2010-02-16 03:27:01 +03:00
extents = extents_from_size ( vg - > cmd , size / SECTOR_SIZE ,
vg - > extent_size ) ;
2009-07-26 06:34:36 +04:00
_lv_set_default_params ( & lp , vg , name , extents ) ;
2012-02-13 15:25:56 +04:00
if ( ! _lv_set_default_linear_params ( vg - > cmd , & lp ) )
return_NULL ;
2009-07-26 06:34:36 +04:00
if ( ! lv_create_single ( vg , & lp ) )
return NULL ;
lvl = find_lv_in_vg ( vg , name ) ;
if ( ! lvl )
return NULL ;
2009-08-13 16:17:32 +04:00
return ( lv_t ) lvl - > lv ;
2009-07-26 06:34:36 +04:00
}
2009-07-28 17:16:40 +04:00
/*
* FIXME : This function should probably not commit to disk but require calling
* lvm_vg_write .
*/
2009-08-13 16:17:32 +04:00
int lvm_vg_remove_lv ( lv_t lv )
2009-07-26 18:36:52 +04:00
{
if ( ! lv | | ! lv - > vg | | vg_read_error ( lv - > vg ) )
2009-07-27 00:28:59 +04:00
return - 1 ;
2009-07-28 19:14:56 +04:00
if ( ! vg_check_write_mode ( lv - > vg ) )
return - 1 ;
2009-07-27 00:28:59 +04:00
if ( ! lv_remove_single ( lv - > vg - > cmd , lv , DONT_PROMPT ) )
return - 1 ;
return 0 ;
2009-07-26 18:36:52 +04:00
}
2009-07-27 00:57:37 +04:00
2009-08-13 16:17:32 +04:00
int lvm_lv_activate ( lv_t lv )
2009-07-27 00:57:37 +04:00
{
if ( ! lv | | ! lv - > vg | | vg_read_error ( lv - > vg ) | | ! lv - > vg - > cmd )
return - 1 ;
/* FIXME: handle pvmove stuff later */
if ( lv - > status & LOCKED ) {
2009-07-28 01:03:15 +04:00
log_error ( " Unable to activate locked LV " ) ;
2009-07-27 00:57:37 +04:00
return - 1 ;
}
/* FIXME: handle lvconvert stuff later */
if ( lv - > status & CONVERTING ) {
2009-07-28 01:03:15 +04:00
log_error ( " Unable to activate LV with in-progress lvconvert " ) ;
2009-07-27 00:57:37 +04:00
return - 1 ;
}
if ( lv_is_origin ( lv ) ) {
log_verbose ( " Activating logical volume \" %s \" "
" exclusively " , lv - > name ) ;
if ( ! activate_lv_excl ( lv - > vg - > cmd , lv ) ) {
2009-07-28 01:03:15 +04:00
log_error ( " Activate exclusive failed. " ) ;
2009-07-27 00:57:37 +04:00
return - 1 ;
}
} else {
log_verbose ( " Activating logical volume \" %s \" " ,
lv - > name ) ;
if ( ! activate_lv ( lv - > vg - > cmd , lv ) ) {
2009-07-28 01:03:15 +04:00
log_error ( " Activate failed. " ) ;
2009-07-27 00:57:37 +04:00
return - 1 ;
}
}
return 0 ;
}
2009-08-13 16:17:32 +04:00
int lvm_lv_deactivate ( lv_t lv )
2009-07-27 00:57:37 +04:00
{
if ( ! lv | | ! lv - > vg | | vg_read_error ( lv - > vg ) | | ! lv - > vg - > cmd )
return - 1 ;
log_verbose ( " Deactivating logical volume \" %s \" " , lv - > name ) ;
if ( ! deactivate_lv ( lv - > vg - > cmd , lv ) ) {
2009-07-28 01:03:15 +04:00
log_error ( " Deactivate failed. " ) ;
2009-07-27 00:57:37 +04:00
return - 1 ;
}
return 0 ;
}
2009-07-28 01:00:50 +04:00
2010-11-17 23:07:01 +03:00
struct dm_list * lvm_lv_list_lvsegs ( lv_t lv )
{
struct dm_list * list ;
lvseg_list_t * lvseg ;
struct lv_segment * lvl ;
if ( dm_list_empty ( & lv - > segments ) )
return NULL ;
if ( ! ( list = dm_pool_zalloc ( lv - > vg - > vgmem , sizeof ( * list ) ) ) ) {
log_errno ( ENOMEM , " Memory allocation fail for dm_list. " ) ;
return NULL ;
}
dm_list_init ( list ) ;
dm_list_iterate_items ( lvl , & lv - > segments ) {
if ( ! ( lvseg = dm_pool_zalloc ( lv - > vg - > vgmem , sizeof ( * lvseg ) ) ) ) {
log_errno ( ENOMEM ,
" Memory allocation fail for lvm_lvseg_list. " ) ;
return NULL ;
}
lvseg - > lvseg = lvl ;
dm_list_add ( list , & lvseg - > list ) ;
}
return list ;
}
2010-11-25 17:33:44 +03:00
lv_t lvm_lv_from_name ( vg_t vg , const char * name )
{
struct lv_list * lvl ;
dm_list_iterate_items ( lvl , & vg - > lvs ) {
if ( ! strcmp ( name , lvl - > lv - > name ) )
return lvl - > lv ;
}
return NULL ;
}
2010-11-25 17:34:51 +03:00
lv_t lvm_lv_from_uuid ( vg_t vg , const char * uuid )
{
struct lv_list * lvl ;
struct id id ;
if ( strlen ( uuid ) < ID_LEN ) {
log_errno ( EINVAL , " Invalid UUID string length " ) ;
return NULL ;
}
2012-02-08 15:41:18 +04:00
if ( ! id_read_format ( & id , uuid ) ) {
log_errno ( EINVAL , " Invalid UUID format. " ) ;
return NULL ;
2010-11-25 17:34:51 +03:00
}
2012-02-08 15:41:18 +04:00
2010-11-25 17:34:51 +03:00
dm_list_iterate_items ( lvl , & vg - > lvs ) {
if ( id_equal ( & vg - > id , & lvl - > lv - > lvid . id [ 0 ] ) & &
id_equal ( & id , & lvl - > lv - > lvid . id [ 1 ] ) )
return lvl - > lv ;
}
return NULL ;
}
2009-08-13 16:17:32 +04:00
int lvm_lv_resize ( const lv_t lv , uint64_t new_size )
2009-07-28 01:00:50 +04:00
{
/* FIXME: add lv resize code here */
2009-07-28 01:03:15 +04:00
log_error ( " NOT IMPLEMENTED YET " ) ;
2009-07-28 01:00:50 +04:00
return - 1 ;
}