2009-07-24 03:40:05 +04:00
/*
2013-07-13 00:40:10 +04:00
* Copyright ( C ) 2008 - 2013 Red Hat , Inc . All rights reserved .
2009-07-24 03:40:05 +04:00
*
* 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 ,
2016-01-21 13:49:46 +03:00
* Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
2009-07-24 03:40:05 +04:00
*/
# include "lib.h"
2017-10-18 21:29:32 +03:00
# include "metadata-exported.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
2013-07-06 06:28:21 +04:00
/* FIXME Improve all the log messages to include context. Which VG/LV as a minimum? */
2013-07-13 00:40:10 +04:00
struct lvm_lv_create_params
{
uint32_t magic ;
vg_t vg ;
struct lvcreate_params lvp ;
} ;
# define LV_CREATE_PARAMS_MAGIC 0xFEED0001
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
{
2013-12-18 02:51:11 +04:00
uint64_t rc ;
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
rc = SECTOR_SIZE * lv_size ( lv ) ;
restore_user_env ( & e ) ;
return rc ;
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
{
2013-12-18 02:51:11 +04:00
const char * rc ;
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
2015-09-21 13:23:03 +03:00
rc = lv_uuid_dup ( lv - > vg - > vgmem , lv ) ;
2013-12-18 02:51:11 +04:00
restore_user_env ( & e ) ;
return rc ;
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
{
2013-12-18 02:51:11 +04:00
const char * rc ;
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
2017-07-20 10:57:09 +03:00
rc = dm_pool_strndup ( lv - > vg - > vgmem , lv - > name , NAME_LEN + 1 ) ;
2013-12-18 02:51:11 +04:00
restore_user_env ( & e ) ;
return rc ;
2009-07-24 03:40:05 +04:00
}
2013-04-10 22:37:56 +04:00
const char * lvm_lv_get_attr ( const lv_t lv )
{
2013-12-18 02:51:11 +04:00
const char * rc ;
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
rc = lv_attr_dup ( lv - > vg - > vgmem , lv ) ;
restore_user_env ( & e ) ;
return rc ;
2013-04-10 22:37:56 +04:00
}
2013-04-12 00:48:40 +04:00
const char * lvm_lv_get_origin ( const lv_t lv )
{
2013-12-18 02:51:11 +04:00
const char * rc ;
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
rc = lv_origin_dup ( lv - > vg - > vgmem , lv ) ;
restore_user_env ( & e ) ;
return rc ;
2013-04-12 00:48:40 +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 )
{
2013-12-18 02:51:11 +04:00
struct lvm_property_value rc ;
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
rc = get_property ( NULL , NULL , lv , NULL , NULL , NULL , NULL , name ) ;
restore_user_env ( & e ) ;
return rc ;
2010-11-17 23:09:42 +03:00
}
struct lvm_property_value lvm_lvseg_get_property ( const lvseg_t lvseg ,
const char * name )
{
2013-12-18 02:51:11 +04:00
struct lvm_property_value rc ;
struct saved_env e = store_user_env ( lvseg - > lv - > vg - > cmd ) ;
rc = get_property ( NULL , NULL , NULL , lvseg , NULL , NULL , NULL , name ) ;
restore_user_env ( & e ) ;
return rc ;
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
{
2013-12-18 02:51:11 +04:00
uint64_t rc = 0 ;
2009-07-27 00:58:11 +04:00
struct lvinfo info ;
2013-12-18 02:51:11 +04:00
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
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 )
2013-12-18 02:51:11 +04:00
rc = 1 ;
restore_user_env ( & e ) ;
return rc ;
2009-07-27 00:58:11 +04:00
}
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
{
2013-12-18 02:51:11 +04:00
uint64_t rc = 0 ;
2009-07-27 00:58:11 +04:00
struct lvinfo info ;
2013-12-18 02:51:11 +04:00
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
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 )
2013-12-18 02:51:11 +04:00
rc = 1 ;
restore_user_env ( & e ) ;
return rc ;
2009-07-27 00:58:11 +04:00
}
2013-12-18 02:51:11 +04:00
static int _lvm_lv_add_tag ( lv_t lv , const char * tag )
2010-02-24 21:16:26 +03:00
{
if ( _lv_check_handle ( lv , 1 ) )
return - 1 ;
if ( ! lv_change_tag ( lv , tag , 1 ) )
return - 1 ;
return 0 ;
}
2013-12-18 02:51:11 +04:00
int lvm_lv_add_tag ( lv_t lv , const char * tag )
{
int rc ;
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
rc = _lvm_lv_add_tag ( lv , tag ) ;
restore_user_env ( & e ) ;
return rc ;
}
2010-02-24 21:16:26 +03:00
2013-12-18 02:51:11 +04:00
static int _lvm_lv_remove_tag ( lv_t lv , const char * tag )
2010-02-24 21:16:26 +03:00
{
if ( _lv_check_handle ( lv , 1 ) )
return - 1 ;
if ( ! lv_change_tag ( lv , tag , 0 ) )
return - 1 ;
return 0 ;
}
2013-12-18 02:51:11 +04:00
int lvm_lv_remove_tag ( lv_t lv , const char * tag )
{
int rc ;
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
rc = _lvm_lv_remove_tag ( lv , tag ) ;
restore_user_env ( & e ) ;
return rc ;
}
2010-02-24 21:16:26 +03:00
struct dm_list * lvm_lv_get_tags ( const lv_t lv )
{
2013-12-18 02:51:11 +04:00
struct dm_list * rc ;
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
rc = tag_list_copy ( lv - > vg - > vgmem , & lv - > tags ) ;
restore_user_env ( & e ) ;
return rc ;
2010-02-24 21:16:26 +03:00
}
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 ;
2013-11-06 19:05:50 +04:00
lp - > wipe_signatures = 0 ;
2009-07-26 06:34:36 +04:00
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 - > 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
}
2012-12-14 05:57:38 +04:00
static struct segment_type * _get_segtype ( struct cmd_context * cmd ) {
2015-09-22 21:04:12 +03:00
struct segment_type * rc = get_segtype_from_string ( cmd , SEG_TYPE_NAME_STRIPED ) ;
2012-12-14 05:57:38 +04:00
if ( ! rc ) {
log_error ( INTERNAL_ERROR " Segtype striped not found. " ) ;
}
return rc ;
}
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-12-14 05:57:38 +04:00
if ( ! ( lp - > segtype = _get_segtype ( cmd ) ) ) {
2012-02-13 15:25:56 +04:00
return 0 ;
}
2009-07-26 06:34:36 +04:00
lp - > stripes = 1 ;
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 .
*/
2013-12-18 02:51:11 +04:00
static lv_t _lvm_vg_create_lv_linear ( vg_t vg , const char * name , uint64_t size )
2009-07-26 06:34:36 +04:00
{
2012-06-21 23:19:28 +04:00
struct lvcreate_params lp = { 0 } ;
2009-07-26 06:34:36 +04:00
uint64_t extents ;
2012-11-21 17:29:52 +04:00
struct logical_volume * lv ;
2009-07-26 06:34:36 +04:00
if ( vg_read_error ( vg ) )
return NULL ;
2009-07-28 19:14:56 +04:00
if ( ! vg_check_write_mode ( vg ) )
return NULL ;
2012-06-21 23:19:28 +04:00
2012-03-01 20:59:35 +04:00
if ( ! ( extents = extents_from_size ( vg - > cmd , size / SECTOR_SIZE ,
vg - > extent_size ) ) ) {
log_error ( " Unable to create LV without size. " ) ;
return NULL ;
}
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 ;
2012-11-13 13:49:32 +04:00
if ( ! ( lv = lv_create_single ( vg , & lp ) ) )
2012-03-01 20:59:35 +04:00
return_NULL ;
2012-11-13 13:49:32 +04:00
return ( lv_t ) lv ;
2009-07-26 06:34:36 +04:00
}
2013-12-18 02:51:11 +04:00
lv_t lvm_vg_create_lv_linear ( vg_t vg , const char * name , uint64_t size )
{
lv_t rc ;
struct saved_env e = store_user_env ( vg - > cmd ) ;
rc = _lvm_vg_create_lv_linear ( vg , name , size ) ;
restore_user_env ( & e ) ;
return rc ;
}
2009-07-28 17:16:40 +04:00
/*
* FIXME : This function should probably not commit to disk but require calling
* lvm_vg_write .
*/
2013-12-18 02:51:11 +04:00
static 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 ;
2013-11-29 20:00:55 +04:00
if ( ! lv_remove_single ( lv - > vg - > cmd , lv , DONT_PROMPT , 0 ) )
2009-07-27 00:28:59 +04:00
return - 1 ;
return 0 ;
2009-07-26 18:36:52 +04:00
}
2009-07-27 00:57:37 +04:00
2013-12-18 02:51:11 +04:00
int lvm_vg_remove_lv ( lv_t lv )
{
int rc ;
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
rc = _lvm_vg_remove_lv ( lv ) ;
restore_user_env ( & e ) ;
return rc ;
}
static 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 */
2014-09-16 00:33:53 +04:00
if ( lv_is_locked ( lv ) ) {
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 */
2014-09-16 00:33:53 +04:00
if ( lv_is_converting ( lv ) ) {
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 ) ) {
2013-07-06 06:28:21 +04:00
/* FIXME Improve msg */
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 ) ) {
2013-07-06 06:28:21 +04:00
/* FIXME Improve msg */
2009-07-28 01:03:15 +04:00
log_error ( " Activate failed. " ) ;
2009-07-27 00:57:37 +04:00
return - 1 ;
}
}
return 0 ;
}
2013-12-18 02:51:11 +04:00
int lvm_lv_activate ( lv_t lv )
{
int rc ;
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
rc = _lvm_lv_activate ( lv ) ;
restore_user_env ( & e ) ;
return rc ;
}
static 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
2013-12-18 02:51:11 +04:00
int lvm_lv_deactivate ( lv_t lv )
{
int rc ;
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
rc = _lvm_lv_deactivate ( lv ) ;
restore_user_env ( & e ) ;
return rc ;
}
static struct dm_list * _lvm_lv_list_lvsegs ( lv_t lv )
2010-11-17 23:07:01 +03:00
{
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 ;
}
2013-12-18 02:51:11 +04:00
struct dm_list * lvm_lv_list_lvsegs ( lv_t lv )
{
struct dm_list * rc ;
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
rc = _lvm_lv_list_lvsegs ( lv ) ;
restore_user_env ( & e ) ;
return rc ;
}
2010-11-25 17:33:44 +03:00
lv_t lvm_lv_from_name ( vg_t vg , const char * name )
{
2013-12-18 02:51:11 +04:00
lv_t rc = NULL ;
2010-11-25 17:33:44 +03:00
struct lv_list * lvl ;
2013-12-18 02:51:11 +04:00
struct saved_env e = store_user_env ( vg - > cmd ) ;
2010-11-25 17:33:44 +03:00
dm_list_iterate_items ( lvl , & vg - > lvs ) {
2013-12-18 02:51:11 +04:00
if ( ! strcmp ( name , lvl - > lv - > name ) ) {
rc = lvl - > lv ;
break ;
}
2010-11-25 17:33:44 +03:00
}
2013-12-18 02:51:11 +04:00
restore_user_env ( & e ) ;
return rc ;
2010-11-25 17:33:44 +03:00
}
2013-12-18 02:51:11 +04:00
static lv_t _lvm_lv_from_uuid ( vg_t vg , const char * uuid )
2010-11-25 17:34:51 +03:00
{
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 ;
}
2011-01-28 01:41:32 +03:00
2013-12-18 02:51:11 +04:00
lv_t lvm_lv_from_uuid ( vg_t vg , const char * uuid )
{
lv_t rc ;
struct saved_env e = store_user_env ( vg - > cmd ) ;
rc = _lvm_lv_from_uuid ( vg , uuid ) ;
restore_user_env ( & e ) ;
return rc ;
}
2011-01-28 01:41:32 +03:00
int lvm_lv_rename ( lv_t lv , const char * new_name )
{
2013-12-18 02:51:11 +04:00
int rc = 0 ;
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
2011-01-28 01:41:32 +03:00
if ( ! lv_rename ( lv - > vg - > cmd , lv , new_name ) ) {
2013-07-06 06:28:21 +04:00
/* FIXME Improve msg */
log_error ( " LV rename failed. " ) ;
2013-12-18 02:51:11 +04:00
rc = - 1 ;
2011-01-28 01:41:32 +03:00
}
2013-12-18 02:51:11 +04:00
restore_user_env ( & e ) ;
return rc ;
2011-01-28 01:41:32 +03:00
}
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
{
2013-12-18 02:51:11 +04:00
int rc = 0 ;
2014-06-30 14:02:05 +04:00
struct lvresize_params lp = {
. sign = SIGN_NONE ,
. percent = PERCENT_NONE ,
. resize = LV_ANY ,
. size = new_size > > SECTOR_SHIFT ,
2016-06-17 14:25:41 +03:00
. force = 1 , /* Assume the user has a good backup? */
2014-06-30 14:02:05 +04:00
} ;
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
2013-12-18 02:51:11 +04:00
2016-06-14 16:32:21 +03:00
if ( ! lv_resize ( lv , & lp , & lv - > vg - > pvs ) ) {
2013-07-06 06:28:21 +04:00
/* FIXME Improve msg */
log_error ( " LV resize failed. " ) ;
/* FIXME Define consistent symbolic return codes */
2013-12-18 02:51:11 +04:00
rc = - 1 ;
2013-03-14 02:07:16 +04:00
}
2013-12-18 02:51:11 +04:00
restore_user_env ( & e ) ;
return rc ;
2009-07-28 01:00:50 +04:00
}
2012-12-14 05:57:38 +04:00
2013-07-13 00:40:10 +04:00
lv_t lvm_lv_snapshot ( const lv_t lv , const char * snap_name ,
uint64_t max_snap_size )
{
2013-12-18 02:51:11 +04:00
lv_t rc = NULL ;
2013-07-13 00:40:10 +04:00
struct lvm_lv_create_params * lvcp = NULL ;
2013-12-18 02:51:11 +04:00
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
2013-07-13 00:40:10 +04:00
lvcp = lvm_lv_params_create_snapshot ( lv , snap_name , max_snap_size ) ;
if ( lvcp ) {
2013-12-18 02:51:11 +04:00
rc = lvm_lv_create ( lvcp ) ;
2013-07-13 00:40:10 +04:00
}
2013-12-18 02:51:11 +04:00
restore_user_env ( & e ) ;
return rc ;
2013-07-13 00:40:10 +04:00
}
/* Set defaults for thin pool specific LV parameters */
2013-07-19 17:35:04 +04:00
static int _lv_set_pool_params ( struct lvcreate_params * lp ,
2014-10-07 12:43:47 +04:00
vg_t vg , const char * pool_name ,
2013-07-13 00:40:10 +04:00
uint64_t extents , uint64_t meta_size )
{
2014-10-31 13:33:19 +03:00
uint64_t pool_metadata_size ;
2014-10-26 09:25:30 +03:00
_lv_set_default_params ( lp , vg , pool_name , extents ) ;
2013-07-13 00:40:10 +04:00
2014-01-22 20:30:55 +04:00
lp - > create_pool = 1 ;
2015-09-22 21:04:12 +03:00
lp - > segtype = get_segtype_from_string ( vg - > cmd , SEG_TYPE_NAME_THIN_POOL ) ;
2013-07-13 00:40:10 +04:00
lp - > stripes = 1 ;
if ( ! meta_size ) {
2014-10-31 13:33:19 +03:00
pool_metadata_size = extents * vg - > extent_size /
2013-07-13 00:40:10 +04:00
( lp - > chunk_size * ( SECTOR_SIZE / 64 ) ) ;
2014-10-31 13:33:19 +03:00
while ( ( pool_metadata_size >
2017-06-09 22:29:34 +03:00
( DEFAULT_THIN_POOL_OPTIMAL_METADATA_SIZE * 2 ) ) & &
2013-07-13 00:40:10 +04:00
lp - > chunk_size < DM_THIN_MAX_DATA_BLOCK_SIZE ) {
lp - > chunk_size < < = 1 ;
2014-10-31 13:33:19 +03:00
pool_metadata_size > > = 1 ;
2013-07-13 00:40:10 +04:00
}
} else
2014-10-31 13:33:19 +03:00
pool_metadata_size = meta_size ;
2013-07-13 00:40:10 +04:00
2014-10-31 13:33:19 +03:00
if ( pool_metadata_size % vg - > extent_size )
pool_metadata_size + =
vg - > extent_size - pool_metadata_size % vg - > extent_size ;
2013-07-13 00:40:10 +04:00
2014-10-07 12:43:47 +04:00
if ( ! ( lp - > pool_metadata_extents =
2014-10-31 13:33:19 +03:00
extents_from_size ( vg - > cmd , pool_metadata_size / SECTOR_SIZE ,
2013-07-19 17:35:04 +04:00
vg - > extent_size ) ) )
return_0 ;
return 1 ;
2013-07-13 00:40:10 +04:00
}
2013-12-18 02:51:11 +04:00
static lv_create_params_t _lvm_lv_params_create_thin_pool ( vg_t vg ,
2013-07-13 00:40:10 +04:00
const char * pool_name , uint64_t size , uint32_t chunk_size ,
uint64_t meta_size , lvm_thin_discards_t discard )
{
uint64_t extents = 0 ;
struct lvm_lv_create_params * lvcp = NULL ;
if ( meta_size > ( 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE ) ) {
log_error ( " Invalid metadata size " ) ;
return NULL ;
}
if ( meta_size & &
meta_size < ( 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE ) ) {
log_error ( " Invalid metadata size " ) ;
return NULL ;
}
if ( vg_read_error ( vg ) )
return NULL ;
if ( ! vg_check_write_mode ( vg ) )
return NULL ;
if ( pool_name = = NULL | | ! strlen ( pool_name ) ) {
log_error ( " pool_name invalid " ) ;
return NULL ;
}
if ( ! ( extents = extents_from_size ( vg - > cmd , size / SECTOR_SIZE ,
vg - > extent_size ) ) ) {
log_error ( " Unable to create LV thin pool without size. " ) ;
return NULL ;
}
lvcp = dm_pool_zalloc ( vg - > vgmem , sizeof ( struct lvm_lv_create_params ) ) ;
if ( lvcp ) {
lvcp - > vg = vg ;
2017-03-17 16:00:18 +03:00
switch ( discard ) {
case LVM_THIN_DISCARDS_IGNORE :
lvcp - > lvp . discards = THIN_DISCARDS_IGNORE ;
break ;
case LVM_THIN_DISCARDS_NO_PASSDOWN :
lvcp - > lvp . discards = THIN_DISCARDS_NO_PASSDOWN ;
break ;
case LVM_THIN_DISCARDS_PASSDOWN :
lvcp - > lvp . discards = THIN_DISCARDS_PASSDOWN ;
break ;
default :
log_error ( " Invalid discard argument %d for thin pool creation. " , discard ) ;
return NULL ;
}
lvcp - > lvp . zero_new_blocks = THIN_ZERO_YES ;
2013-07-13 00:40:10 +04:00
if ( chunk_size )
lvcp - > lvp . chunk_size = chunk_size ;
else
lvcp - > lvp . chunk_size = DEFAULT_THIN_POOL_CHUNK_SIZE * 2 ;
if ( lvcp - > lvp . chunk_size < DM_THIN_MIN_DATA_BLOCK_SIZE | |
lvcp - > lvp . chunk_size > DM_THIN_MAX_DATA_BLOCK_SIZE ) {
log_error ( " Invalid chunk_size " ) ;
return NULL ;
}
2013-07-19 17:35:04 +04:00
if ( ! _lv_set_pool_params ( & lvcp - > lvp , vg , pool_name , extents , meta_size ) )
return_NULL ;
2013-07-13 00:40:10 +04:00
lvcp - > magic = LV_CREATE_PARAMS_MAGIC ;
}
return lvcp ;
}
2013-12-18 02:51:11 +04:00
lv_create_params_t lvm_lv_params_create_thin_pool ( vg_t vg ,
const char * pool_name , uint64_t size , uint32_t chunk_size ,
uint64_t meta_size , lvm_thin_discards_t discard )
{
lv_create_params_t rc ;
struct saved_env e = store_user_env ( vg - > cmd ) ;
rc = _lvm_lv_params_create_thin_pool ( vg , pool_name , size , chunk_size ,
meta_size , discard ) ;
restore_user_env ( & e ) ;
return rc ;
}
2013-07-13 00:40:10 +04:00
/* Set defaults for thin LV specific parameters */
2013-07-19 17:35:04 +04:00
static int _lv_set_thin_params ( struct lvcreate_params * lp ,
2014-10-31 13:33:19 +03:00
vg_t vg , const char * pool_name ,
const char * lvname ,
uint32_t extents )
2013-07-13 00:40:10 +04:00
{
2014-10-31 13:33:19 +03:00
_lv_set_default_params ( lp , vg , lvname , 0 ) ;
2013-07-13 00:40:10 +04:00
2014-10-07 12:43:47 +04:00
lp - > pool_name = pool_name ;
2015-09-22 21:04:12 +03:00
lp - > segtype = get_segtype_from_string ( vg - > cmd , SEG_TYPE_NAME_THIN ) ;
2014-10-31 13:33:19 +03:00
lp - > virtual_extents = extents ;
2013-07-13 00:40:10 +04:00
lp - > stripes = 1 ;
2013-07-19 17:35:04 +04:00
return 1 ;
2013-07-13 00:40:10 +04:00
}
2013-12-18 02:51:11 +04:00
static lv_create_params_t _lvm_lv_params_create_snapshot ( const lv_t lv ,
2014-10-26 09:25:30 +03:00
const char * snap_name ,
uint64_t max_snap_size )
2013-07-13 00:40:10 +04:00
{
uint64_t size = 0 ;
uint64_t extents = 0 ;
struct lvm_lv_create_params * lvcp = NULL ;
if ( vg_read_error ( lv - > vg ) ) {
return NULL ;
}
if ( ! vg_check_write_mode ( lv - > vg ) )
return NULL ;
if ( snap_name = = NULL | | ! strlen ( snap_name ) ) {
log_error ( " snap_name invalid " ) ;
return NULL ;
}
if ( max_snap_size ) {
size = max_snap_size > > SECTOR_SHIFT ;
2013-07-19 17:35:04 +04:00
if ( ! ( extents = extents_from_size ( lv - > vg - > cmd , size , lv - > vg - > extent_size ) ) )
return_NULL ;
2013-07-13 00:40:10 +04:00
}
if ( ! size & & ! lv_is_thin_volume ( lv ) ) {
log_error ( " Origin is not thin, specify size of snapshot " ) ;
2014-10-26 09:25:30 +03:00
return NULL ;
2013-07-13 00:40:10 +04:00
}
lvcp = dm_pool_zalloc ( lv - > vg - > vgmem , sizeof ( struct lvm_lv_create_params ) ) ;
if ( lvcp ) {
lvcp - > vg = lv - > vg ;
_lv_set_default_params ( & lvcp - > lvp , lv - > vg , snap_name , extents ) ;
if ( size ) {
2015-09-22 21:04:12 +03:00
if ( ! ( lvcp - > lvp . segtype = get_segtype_from_string ( lv - > vg - > cmd , SEG_TYPE_NAME_SNAPSHOT ) ) ) {
2014-10-26 09:25:30 +03:00
log_error ( " Segtype snapshot not found. " ) ;
return NULL ;
}
2013-07-13 00:40:10 +04:00
lvcp - > lvp . chunk_size = 8 ;
2014-10-26 09:25:30 +03:00
lvcp - > lvp . snapshot = 1 ;
2013-07-13 00:40:10 +04:00
} else {
2015-09-22 21:04:12 +03:00
if ( ! ( lvcp - > lvp . segtype = get_segtype_from_string ( lv - > vg - > cmd , SEG_TYPE_NAME_THIN ) ) ) {
2014-10-26 09:25:30 +03:00
log_error ( " Segtype thin not found. " ) ;
2013-07-13 00:40:10 +04:00
return NULL ;
}
2014-10-07 12:43:47 +04:00
lvcp - > lvp . pool_name = first_seg ( lv ) - > pool_lv - > name ;
2013-07-13 00:40:10 +04:00
}
lvcp - > lvp . stripes = 1 ;
2014-10-07 12:43:47 +04:00
lvcp - > lvp . origin_name = lv - > name ;
2013-07-13 00:40:10 +04:00
lvcp - > magic = LV_CREATE_PARAMS_MAGIC ;
}
return lvcp ;
}
2013-12-18 02:51:11 +04:00
lv_create_params_t lvm_lv_params_create_snapshot ( const lv_t lv ,
const char * snap_name ,
uint64_t max_snap_size )
{
lv_create_params_t rc ;
struct saved_env e = store_user_env ( lv - > vg - > cmd ) ;
rc = _lvm_lv_params_create_snapshot ( lv , snap_name , max_snap_size ) ;
restore_user_env ( & e ) ;
return rc ;
}
2013-07-13 00:40:10 +04:00
2013-12-18 02:51:11 +04:00
static lv_create_params_t _lvm_lv_params_create_thin ( const vg_t vg ,
const char * pool_name ,
2013-07-13 00:40:10 +04:00
const char * lvname , uint64_t size )
{
struct lvm_lv_create_params * lvcp = NULL ;
2014-10-31 13:33:19 +03:00
uint32_t extents = 0 ;
2013-07-13 00:40:10 +04:00
/* precondition checks */
if ( vg_read_error ( vg ) )
return NULL ;
if ( ! vg_check_write_mode ( vg ) )
return NULL ;
if ( pool_name = = NULL | | ! strlen ( pool_name ) ) {
log_error ( " pool_name invalid " ) ;
return NULL ;
}
if ( lvname = = NULL | | ! strlen ( lvname ) ) {
log_error ( " lvname invalid " ) ;
return NULL ;
}
if ( ! ( extents = extents_from_size ( vg - > cmd , size / SECTOR_SIZE ,
vg - > extent_size ) ) ) {
log_error ( " Unable to create thin LV without size. " ) ;
return NULL ;
}
lvcp = dm_pool_zalloc ( vg - > vgmem , sizeof ( struct lvm_lv_create_params ) ) ;
if ( lvcp ) {
lvcp - > vg = vg ;
2013-07-19 17:35:04 +04:00
if ( ! _lv_set_thin_params ( & lvcp - > lvp , vg , pool_name , lvname , extents ) )
return_NULL ;
2013-07-13 00:40:10 +04:00
lvcp - > magic = LV_CREATE_PARAMS_MAGIC ;
}
return lvcp ;
}
2013-12-18 02:51:11 +04:00
lv_create_params_t lvm_lv_params_create_thin ( const vg_t vg , const char * pool_name ,
const char * lvname , uint64_t size )
{
lv_create_params_t rc ;
struct saved_env e = store_user_env ( vg - > cmd ) ;
rc = _lvm_lv_params_create_thin ( vg , pool_name , lvname , size ) ;
restore_user_env ( & e ) ;
return rc ;
}
2013-07-13 00:40:10 +04:00
struct lvm_property_value lvm_lv_params_get_property (
const lv_create_params_t params ,
const char * name )
{
2014-02-10 00:36:02 +04:00
struct lvm_property_value rc = { . is_valid = 0 } ;
2013-07-13 00:40:10 +04:00
if ( params & & params - > magic = = LV_CREATE_PARAMS_MAGIC ) {
2014-02-10 00:36:02 +04:00
struct saved_env e = store_user_env ( params - > vg - > cmd ) ;
2013-09-11 03:01:28 +04:00
rc = get_property ( NULL , NULL , NULL , NULL , NULL , & params - > lvp , NULL , name ) ;
2014-02-10 00:36:02 +04:00
restore_user_env ( & e ) ;
} else
2013-07-13 00:40:10 +04:00
log_error ( " Invalid lv_create_params parameter " ) ;
2014-02-10 00:36:02 +04:00
2013-07-13 00:40:10 +04:00
return rc ;
}
int lvm_lv_params_set_property ( lv_create_params_t params , const char * name ,
struct lvm_property_value * prop )
{
int rc = - 1 ;
if ( params & & params - > magic = = LV_CREATE_PARAMS_MAGIC ) {
2014-02-10 00:36:02 +04:00
struct saved_env e = store_user_env ( params - > vg - > cmd ) ;
2013-09-11 03:01:28 +04:00
rc = set_property ( NULL , NULL , NULL , & params - > lvp , NULL , name , prop ) ;
2014-02-10 00:36:02 +04:00
restore_user_env ( & e ) ;
} else
2013-07-13 00:40:10 +04:00
log_error ( " Invalid lv_create_params parameter " ) ;
2013-12-18 02:51:11 +04:00
2013-07-13 00:40:10 +04:00
return rc ;
}
2013-12-18 02:51:11 +04:00
static lv_t _lvm_lv_create ( lv_create_params_t params )
2013-07-13 00:40:10 +04:00
{
struct lv_list * lvl = NULL ;
if ( params & & params - > magic = = LV_CREATE_PARAMS_MAGIC ) {
if ( ! params - > lvp . segtype ) {
log_error ( " segtype parameter is NULL " ) ;
return_NULL ;
}
if ( ! lv_create_single ( params - > vg , & params - > lvp ) )
return_NULL ;
/*
* In some case we are making a thin pool so lv_name is not valid , but
* pool is .
*/
if ( ! ( lvl = find_lv_in_vg ( params - > vg ,
2014-10-07 12:43:47 +04:00
( params - > lvp . lv_name ) ? params - > lvp . lv_name : params - > lvp . pool_name ) ) )
2013-07-13 00:40:10 +04:00
return_NULL ;
return ( lv_t ) lvl - > lv ;
}
log_error ( " Invalid lv_create_params parameter " ) ;
return NULL ;
}
2013-12-18 02:51:11 +04:00
lv_t lvm_lv_create ( lv_create_params_t params )
{
lv_t rc ;
struct saved_env e = store_user_env ( params - > vg - > cmd ) ;
rc = _lvm_lv_create ( params ) ;
restore_user_env ( & e ) ;
return rc ;
}