2009-07-14 07:02:14 +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"
2009-07-29 17:26:01 +04:00
# include "lvm2app.h"
2009-07-14 07:02:14 +04:00
# include "toolcontext.h"
# include "metadata-exported.h"
# include "archiver.h"
# include "locking.h"
2009-07-24 03:40:05 +04:00
# include "lvm-string.h"
2009-07-24 16:48:21 +04:00
# include "lvmcache.h"
2009-07-26 05:54:40 +04:00
# include "metadata.h"
# include <errno.h>
# include <string.h>
2009-07-14 07:02:14 +04:00
vg_t * lvm_vg_create ( lvm_t libh , const char * vg_name )
{
2009-07-23 05:20:22 +04:00
vg_t * vg ;
vg = vg_create ( ( struct cmd_context * ) libh , vg_name ) ;
/* FIXME: error handling is still TBD */
if ( vg_read_error ( vg ) ) {
vg_release ( vg ) ;
return NULL ;
}
2009-07-28 19:14:56 +04:00
vg - > open_mode = ' w ' ;
2009-07-29 17:26:01 +04:00
return ( vg_t * ) vg ;
2009-07-14 07:02:14 +04:00
}
int lvm_vg_extend ( vg_t * vg , const char * device )
{
if ( vg_read_error ( vg ) )
2009-07-27 00:28:59 +04:00
return - 1 ;
2009-07-14 07:02:14 +04:00
2009-07-28 19:14:56 +04:00
if ( ! vg_check_write_mode ( vg ) )
return - 1 ;
2009-07-24 19:12:50 +04:00
if ( ! lock_vol ( vg - > cmd , VG_ORPHANS , LCK_VG_WRITE ) ) {
log_error ( " Can't get lock for orphan PVs " ) ;
2009-07-27 00:28:59 +04:00
return - 1 ;
2009-07-24 19:12:50 +04:00
}
2009-07-26 05:54:40 +04:00
/* If device not initialized, pvcreate it */
if ( ! pv_by_path ( vg - > cmd , device ) & &
( ! pvcreate_single ( vg - > cmd , device , NULL ) ) ) {
2009-07-28 01:03:15 +04:00
log_error ( " Unable to initialize device for LVM use " ) ;
2009-07-26 05:54:40 +04:00
unlock_vg ( vg - > cmd , VG_ORPHANS ) ;
2009-07-27 00:28:59 +04:00
return - 1 ;
2009-07-26 05:54:40 +04:00
}
2009-07-24 19:12:50 +04:00
if ( ! vg_extend ( vg , 1 , ( char * * ) & device ) ) {
unlock_vg ( vg - > cmd , VG_ORPHANS ) ;
2009-07-27 00:28:59 +04:00
return - 1 ;
2009-07-24 19:12:50 +04:00
}
/*
* FIXME : Either commit to disk , or keep holding VG_ORPHANS and
* release in lvm_vg_close ( ) .
*/
unlock_vg ( vg - > cmd , VG_ORPHANS ) ;
2009-07-27 00:28:59 +04:00
return 0 ;
2009-07-14 07:02:14 +04:00
}
2009-07-27 21:44:29 +04:00
int lvm_vg_reduce ( vg_t * vg , const char * device )
{
if ( vg_read_error ( vg ) )
return - 1 ;
2009-07-28 19:14:56 +04:00
if ( ! vg_check_write_mode ( vg ) )
return - 1 ;
2009-07-27 21:44:29 +04:00
if ( ! vg_reduce ( vg , ( char * ) device ) )
return - 1 ;
return 0 ;
}
2009-07-14 07:02:14 +04:00
int lvm_vg_set_extent_size ( vg_t * vg , uint32_t new_size )
{
if ( vg_read_error ( vg ) )
2009-07-27 00:28:59 +04:00
return - 1 ;
2009-07-28 19:14:56 +04:00
if ( ! vg_check_write_mode ( vg ) )
return - 1 ;
2009-07-14 07:02:14 +04:00
2009-07-27 00:28:59 +04:00
if ( ! vg_set_extent_size ( vg , new_size ) )
return - 1 ;
2009-07-14 07:02:14 +04:00
return 0 ;
}
int lvm_vg_write ( vg_t * vg )
{
2009-07-27 21:44:29 +04:00
struct pv_list * pvl ;
2009-07-14 07:02:14 +04:00
if ( vg_read_error ( vg ) )
2009-07-27 00:28:59 +04:00
return - 1 ;
2009-07-28 19:14:56 +04:00
if ( ! vg_check_write_mode ( vg ) )
return - 1 ;
2009-07-14 07:02:14 +04:00
2009-07-27 21:44:29 +04:00
if ( dm_list_empty ( & vg - > pvs ) ) {
log_error ( " Volume group %s does not contain any "
2009-07-28 01:03:15 +04:00
" physical volumes. " , vg - > name ) ;
2009-07-27 21:44:29 +04:00
return - 1 ;
}
if ( ! dm_list_empty ( & vg - > removed_pvs ) ) {
if ( ! lock_vol ( vg - > cmd , VG_ORPHANS , LCK_VG_WRITE ) ) {
log_error ( " Can't get lock for orphan PVs " ) ;
return 0 ;
}
}
2009-07-27 00:28:59 +04:00
if ( ! archive ( vg ) )
return - 1 ;
2009-07-14 07:02:14 +04:00
/* Store VG on disk(s) */
2009-07-27 00:28:59 +04:00
if ( ! vg_write ( vg ) | | ! vg_commit ( vg ) )
return - 1 ;
2009-07-27 21:44:29 +04:00
if ( ! dm_list_empty ( & vg - > removed_pvs ) ) {
dm_list_iterate_items ( pvl , & vg - > removed_pvs ) {
pv_write_orphan ( vg - > cmd , pvl - > pv ) ;
/* FIXME: do pvremove / label_remove()? */
}
dm_list_init ( & vg - > removed_pvs ) ;
unlock_vg ( vg - > cmd , VG_ORPHANS ) ;
}
2009-07-14 07:02:14 +04:00
return 0 ;
}
int lvm_vg_close ( vg_t * vg )
{
2009-07-22 07:13:35 +04:00
if ( vg_read_error ( vg ) = = FAILED_LOCKING )
vg_release ( vg ) ;
else
unlock_and_release_vg ( vg - > cmd , vg , vg - > name ) ;
2009-07-27 00:28:59 +04:00
return 0 ;
2009-07-14 07:02:14 +04:00
}
int lvm_vg_remove ( vg_t * vg )
{
if ( vg_read_error ( vg ) )
2009-07-27 00:28:59 +04:00
return - 1 ;
2009-07-28 19:14:56 +04:00
if ( ! vg_check_write_mode ( vg ) )
return - 1 ;
2009-07-14 07:02:14 +04:00
2009-07-27 00:28:59 +04:00
if ( ! vg_remove_single ( vg ) )
return - 1 ;
2009-07-14 07:02:14 +04:00
return 0 ;
}
2009-07-23 02:24:16 +04:00
vg_t * lvm_vg_open ( lvm_t libh , const char * vgname , const char * mode ,
uint32_t flags )
{
uint32_t internal_flags = 0 ;
vg_t * vg ;
if ( ! strncmp ( mode , " w " , 1 ) )
internal_flags | = READ_FOR_UPDATE ;
else if ( strncmp ( mode , " r " , 1 ) ) {
log_errno ( EINVAL , " Invalid VG open mode " ) ;
return NULL ;
}
vg = vg_read ( ( struct cmd_context * ) libh , vgname , NULL , internal_flags ) ;
if ( vg_read_error ( vg ) ) {
/* FIXME: use log_errno either here in inside vg_read */
vg_release ( vg ) ;
return NULL ;
}
2009-07-28 19:14:56 +04:00
/* FIXME: combine this with locking ? */
vg - > open_mode = mode [ 0 ] ;
2009-07-23 02:24:16 +04:00
2009-07-29 17:26:01 +04:00
return ( vg_t * ) vg ;
2009-07-23 02:24:16 +04:00
}
2009-07-24 03:39:02 +04:00
struct dm_list * lvm_vg_list_pvs ( vg_t * vg )
{
struct dm_list * list ;
pv_list_t * pvs ;
struct pv_list * pvl ;
if ( dm_list_empty ( & vg - > pvs ) )
return NULL ;
if ( ! ( list = dm_pool_zalloc ( vg - > vgmem , sizeof ( * list ) ) ) ) {
2009-07-28 01:03:15 +04:00
log_errno ( ENOMEM , " Memory allocation fail for dm_list. " ) ;
2009-07-24 03:39:02 +04:00
return NULL ;
}
dm_list_init ( list ) ;
dm_list_iterate_items ( pvl , & vg - > pvs ) {
if ( ! ( pvs = dm_pool_zalloc ( vg - > vgmem , sizeof ( * pvs ) ) ) ) {
2009-07-27 00:29:28 +04:00
log_errno ( ENOMEM ,
2009-07-28 01:03:15 +04:00
" Memory allocation fail for lvm_pv_list. " ) ;
2009-07-24 03:39:02 +04:00
return NULL ;
}
pvs - > pv = pvl - > pv ;
dm_list_add ( list , & pvs - > list ) ;
}
return list ;
}
struct dm_list * lvm_vg_list_lvs ( vg_t * vg )
{
struct dm_list * list ;
lv_list_t * lvs ;
struct lv_list * lvl ;
if ( dm_list_empty ( & vg - > lvs ) )
return NULL ;
if ( ! ( list = dm_pool_zalloc ( vg - > vgmem , sizeof ( * list ) ) ) ) {
2009-07-28 01:03:15 +04:00
log_errno ( ENOMEM , " Memory allocation fail for dm_list. " ) ;
2009-07-24 03:39:02 +04:00
return NULL ;
}
dm_list_init ( list ) ;
dm_list_iterate_items ( lvl , & vg - > lvs ) {
if ( ! ( lvs = dm_pool_zalloc ( vg - > vgmem , sizeof ( * lvs ) ) ) ) {
2009-07-27 00:29:28 +04:00
log_errno ( ENOMEM ,
2009-07-28 01:03:15 +04:00
" Memory allocation fail for lvm_lv_list. " ) ;
2009-07-24 03:39:02 +04:00
return NULL ;
}
lvs - > lv = lvl - > lv ;
dm_list_add ( list , & lvs - > list ) ;
}
return list ;
}
2009-07-24 03:40:05 +04:00
2009-07-28 17:17:04 +04:00
uint64_t lvm_vg_get_seqno ( const vg_t * vg )
{
return vg_seqno ( vg ) ;
}
2009-07-26 17:06:59 +04:00
/* FIXME: invalid handle? return INTMAX? */
uint64_t lvm_vg_get_size ( const vg_t * vg )
{
return vg_size ( vg ) ;
}
2009-07-26 20:06:46 +04:00
uint64_t lvm_vg_get_free_size ( const vg_t * vg )
2009-07-26 17:06:59 +04:00
{
return vg_free ( vg ) ;
}
uint64_t lvm_vg_get_extent_size ( const vg_t * vg )
{
return vg_extent_size ( vg ) ;
}
uint64_t lvm_vg_get_extent_count ( const vg_t * vg )
{
return vg_extent_count ( vg ) ;
}
2009-07-26 20:05:49 +04:00
uint64_t lvm_vg_get_free_extent_count ( const vg_t * vg )
2009-07-26 17:06:59 +04:00
{
return vg_free_count ( vg ) ;
}
uint64_t lvm_vg_get_pv_count ( const vg_t * vg )
{
return vg_pv_count ( vg ) ;
}
2009-07-24 03:40:05 +04:00
char * lvm_vg_get_uuid ( const vg_t * vg )
{
char uuid [ 64 ] __attribute ( ( aligned ( 8 ) ) ) ;
if ( ! id_write_format ( & vg - > id , uuid , sizeof ( uuid ) ) ) {
log_error ( " Internal error converting uuid " ) ;
return NULL ;
}
return strndup ( ( const char * ) uuid , 64 ) ;
}
char * lvm_vg_get_name ( const vg_t * vg )
{
char * name ;
2009-07-28 13:56:48 +04:00
name = dm_malloc ( NAME_LEN + 1 ) ;
2009-07-24 03:40:05 +04:00
strncpy ( name , ( const char * ) vg - > name , NAME_LEN ) ;
name [ NAME_LEN ] = ' \0 ' ;
return name ;
}
2009-07-24 16:47:15 +04:00
2009-07-27 15:00:17 +04:00
/*
* FIXME : These functions currently return hidden VGs . We should either filter
* these out and not return them in the list , or export something like
* is_orphan_vg and tell the caller to filter .
*/
2009-07-24 16:47:15 +04:00
struct dm_list * lvm_list_vg_names ( lvm_t libh )
{
return get_vgnames ( ( struct cmd_context * ) libh , 0 ) ;
}
2009-07-26 20:06:21 +04:00
struct dm_list * lvm_list_vg_uuids ( lvm_t libh )
2009-07-24 16:47:15 +04:00
{
return get_vgids ( ( struct cmd_context * ) libh , 0 ) ;
}
2009-07-24 16:48:21 +04:00
2009-08-03 16:11:45 +04:00
/*
* FIXME : Elaborate on when to use , side - effects , . cache file , etc
*/
2009-07-26 20:44:05 +04:00
int lvm_scan ( lvm_t libh )
2009-07-24 16:48:21 +04:00
{
2009-07-27 00:28:59 +04:00
if ( ! lvmcache_label_scan ( ( struct cmd_context * ) libh , 2 ) )
return - 1 ;
return 0 ;
2009-07-24 16:48:21 +04:00
}