2001-12-11 11:42:30 +00:00
/*
2004-03-30 19:35:44 +00:00
* Copyright ( C ) 2002 - 2004 Sistina Software , Inc . All rights reserved .
2018-01-05 02:31:28 +00:00
* Copyright ( C ) 2004 - 2018 Red Hat , Inc . All rights reserved .
2001-12-11 11:42:30 +00:00
*
2004-03-30 19:35:44 +00: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
2007-08-20 20:55:30 +00:00
* of the GNU Lesser General Public License v .2 .1 .
2004-03-30 19:35:44 +00:00
*
2007-08-20 20:55:30 +00:00
* You should have received a copy of the GNU Lesser General Public License
2004-03-30 19:35:44 +00:00
* along with this program ; if not , write to the Free Software Foundation ,
2016-01-21 11:49:46 +01:00
* Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
2001-12-11 11:42:30 +00:00
*/
2002-11-18 14:04:08 +00:00
# include "lib.h"
2001-12-11 11:42:30 +00:00
# include "label.h"
2002-11-18 14:04:08 +00:00
# include "crc.h"
# include "xlate.h"
2003-07-04 22:34:56 +00:00
# include "lvmcache.h"
2002-11-18 14:04:08 +00:00
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
/* FIXME Allow for larger labels? Restricted to single sector currently */
2001-12-11 11:42:30 +00:00
2018-01-02 13:37:12 +00:00
static struct dm_pool * _labeller_mem ;
2002-01-10 15:01:58 +00:00
/*
* Internal labeller struct .
*/
struct labeller_i {
2008-11-03 22:14:30 +00:00
struct dm_list list ;
2001-12-11 11:42:30 +00:00
2002-01-10 15:01:58 +00:00
struct labeller * l ;
char name [ 0 ] ;
} ;
2001-12-13 08:40:47 +00:00
2008-11-03 22:14:30 +00:00
static struct dm_list _labellers ;
2001-12-11 11:42:30 +00:00
2002-01-10 15:01:58 +00:00
static struct labeller_i * _alloc_li ( const char * name , struct labeller * l )
2001-12-11 11:42:30 +00:00
{
2002-01-10 15:01:58 +00:00
struct labeller_i * li ;
size_t len ;
2001-12-11 11:42:30 +00:00
2002-01-10 15:01:58 +00:00
len = sizeof ( * li ) + strlen ( name ) + 1 ;
2001-12-11 11:42:30 +00:00
2005-10-16 23:03:59 +00:00
if ( ! ( li = dm_malloc ( len ) ) ) {
2002-01-16 00:01:36 +00:00
log_error ( " Couldn't allocate memory for labeller list object. " ) ;
2002-01-10 15:01:58 +00:00
return NULL ;
}
li - > l = l ;
strcpy ( li - > name , name ) ;
return li ;
2001-12-12 09:05:44 +00:00
}
2001-12-11 11:42:30 +00:00
2002-01-10 15:01:58 +00:00
int label_init ( void )
{
2018-01-02 13:37:12 +00:00
if ( ! ( _labeller_mem = dm_pool_create ( " label scan " , 128 ) ) ) {
log_error ( " Labeller pool creation failed. " ) ;
return 0 ;
}
2008-11-03 22:14:30 +00:00
dm_list_init ( & _labellers ) ;
2018-01-02 13:37:12 +00:00
2002-01-10 16:48:28 +00:00
return 1 ;
2001-12-11 11:42:30 +00:00
}
2002-01-10 15:01:58 +00:00
void label_exit ( void )
2001-12-14 13:15:15 +00:00
{
2012-02-08 11:12:18 +00:00
struct labeller_i * li , * tli ;
2002-01-10 15:01:58 +00:00
2012-02-08 11:12:18 +00:00
dm_list_iterate_items_safe ( li , tli , & _labellers ) {
dm_list_del ( & li - > list ) ;
2002-11-18 14:04:08 +00:00
li - > l - > ops - > destroy ( li - > l ) ;
2012-02-08 11:12:18 +00:00
dm_free ( li ) ;
2002-01-10 15:01:58 +00:00
}
2004-05-04 21:25:57 +00:00
2008-11-03 22:14:30 +00:00
dm_list_init ( & _labellers ) ;
2018-01-02 13:37:12 +00:00
dm_pool_destroy ( _labeller_mem ) ;
2001-12-14 13:15:15 +00:00
}
2013-07-29 15:58:18 +02:00
int label_register_handler ( struct labeller * handler )
2001-12-11 11:42:30 +00:00
{
2002-01-10 15:01:58 +00:00
struct labeller_i * li ;
2013-07-29 15:58:18 +02:00
if ( ! ( li = _alloc_li ( handler - > fmt - > name , handler ) ) )
2008-01-30 13:19:47 +00:00
return_0 ;
2001-12-11 11:42:30 +00:00
2008-11-03 22:14:30 +00:00
dm_list_add ( & _labellers , & li - > list ) ;
2002-01-10 15:01:58 +00:00
return 1 ;
2001-12-11 11:42:30 +00:00
}
2002-01-10 15:01:58 +00:00
struct labeller * label_get_handler ( const char * name )
2001-12-11 11:42:30 +00:00
{
2002-01-10 15:01:58 +00:00
struct labeller_i * li ;
2001-12-11 11:42:30 +00:00
2008-11-03 22:14:30 +00:00
dm_list_iterate_items ( li , & _labellers )
2002-01-10 15:01:58 +00:00
if ( ! strcmp ( li - > name , name ) )
return li - > l ;
2001-12-11 11:42:30 +00:00
2002-01-10 15:01:58 +00:00
return NULL ;
}
2001-12-11 11:42:30 +00:00
2015-03-18 23:43:02 +00:00
static void _update_lvmcache_orphan ( struct lvmcache_info * info )
{
struct lvmcache_vgsummary vgsummary_orphan = {
. vgname = lvmcache_fmt ( info ) - > orphan_vg_name ,
} ;
memcpy ( & vgsummary_orphan . vgid , lvmcache_fmt ( info ) - > orphan_vg_name , strlen ( lvmcache_fmt ( info ) - > orphan_vg_name ) ) ;
2015-08-18 13:48:53 +02:00
if ( ! lvmcache_update_vgname_and_id ( info , & vgsummary_orphan ) )
stack ;
2015-03-18 23:43:02 +00:00
}
2018-01-02 16:01:10 +00:00
struct find_labeller_params {
struct device * dev ;
uint64_t scan_sector ; /* Sector to be scanned */
uint64_t label_sector ; /* Sector where label found */
2018-01-08 23:08:22 +00:00
lvm_callback_fn_t process_label_data_fn ;
void * process_label_data_context ;
2018-01-02 16:01:10 +00:00
struct label * * result ;
2018-01-05 02:31:28 +00:00
int ret ;
2018-01-02 16:01:10 +00:00
} ;
2018-01-21 15:41:49 +00:00
static void _set_label_read_result ( int failed , unsigned ioflags , void * context , const void * data )
2018-01-02 14:19:20 +00:00
{
2018-01-07 03:43:25 +00:00
struct find_labeller_params * flp = context ;
2018-01-02 16:01:10 +00:00
struct label * * result = flp - > result ;
2018-01-11 02:39:30 +00:00
struct label * label = ( struct label * ) data ;
2018-01-02 16:01:10 +00:00
2018-01-08 23:08:22 +00:00
if ( failed ) {
flp - > ret = 0 ;
2018-01-02 14:58:21 +00:00
goto_out ;
2018-01-08 23:08:22 +00:00
}
2018-01-02 14:58:21 +00:00
2018-01-11 02:39:30 +00:00
/* Fix up device and label sector which the low-level code doesn't set */
if ( label ) {
label - > dev = flp - > dev ;
label - > sector = flp - > label_sector ;
2018-01-02 14:19:20 +00:00
}
2018-01-02 14:58:21 +00:00
2018-01-11 02:39:30 +00:00
if ( result )
* result = ( struct label * ) label ;
2018-01-02 14:58:21 +00:00
out :
2018-01-02 16:01:10 +00:00
if ( ! dev_close ( flp - > dev ) )
2018-01-02 14:58:21 +00:00
stack ;
2018-01-08 23:08:22 +00:00
2018-02-06 21:43:06 +00:00
if ( flp - > process_label_data_fn ) {
log_debug_io ( " Completed label reading for %s " , dev_name ( flp - > dev ) ) ;
2018-01-22 15:41:11 +00:00
flp - > process_label_data_fn ( ! flp - > ret , ioflags , flp - > process_label_data_context , NULL ) ;
2018-02-06 21:43:06 +00:00
}
2018-01-02 14:19:20 +00:00
}
2018-01-21 15:41:49 +00:00
static void _find_labeller ( int failed , unsigned ioflags , void * context , const void * data )
2001-12-11 11:42:30 +00:00
{
2018-01-05 14:24:10 +00:00
struct find_labeller_params * flp = context ;
2018-01-10 19:50:53 +00:00
const char * readbuf = data ;
2018-01-02 16:01:10 +00:00
struct device * dev = flp - > dev ;
uint64_t scan_sector = flp - > scan_sector ;
2018-01-02 14:58:21 +00:00
char labelbuf [ LABEL_SIZE ] __attribute__ ( ( aligned ( 8 ) ) ) ;
2002-01-10 15:01:58 +00:00
struct labeller_i * li ;
2018-01-02 14:58:21 +00:00
struct labeller * l = NULL ; /* Set when a labeller claims the label */
2018-01-10 19:50:53 +00:00
const struct label_header * lh ;
2005-03-21 22:40:35 +00:00
struct lvmcache_info * info ;
2002-11-18 14:04:08 +00:00
uint64_t sector ;
2018-01-05 02:31:28 +00:00
2018-01-08 23:08:22 +00:00
if ( failed ) {
log_debug_devs ( " %s: Failed to read label area " , dev_name ( dev ) ) ;
2018-01-21 15:41:49 +00:00
_set_label_read_result ( 1 , ioflags , flp , NULL ) ;
2018-01-08 23:08:22 +00:00
return ;
}
2007-04-23 18:21:01 +00:00
/* Scan a few sectors for a valid label */
2002-11-18 14:04:08 +00:00
for ( sector = 0 ; sector < LABEL_SCAN_SECTORS ;
sector + = LABEL_SIZE > > SECTOR_SHIFT ) {
2018-01-02 16:01:10 +00:00
lh = ( struct label_header * ) ( readbuf + ( sector < < SECTOR_SHIFT ) ) ;
2002-11-18 14:04:08 +00:00
2006-05-09 21:23:51 +00:00
if ( ! strncmp ( ( char * ) lh - > id , LABEL_ID , sizeof ( lh - > id ) ) ) {
2018-01-02 14:58:21 +00:00
if ( l ) {
2002-11-18 14:04:08 +00:00
log_error ( " Ignoring additional label on %s at "
" sector % " PRIu64 , dev_name ( dev ) ,
2007-04-23 18:21:01 +00:00
sector + scan_sector ) ;
2002-11-18 14:04:08 +00:00
}
2007-04-23 18:21:01 +00:00
if ( xlate64 ( lh - > sector_xl ) ! = sector + scan_sector ) {
2016-11-01 11:02:01 +01:00
log_very_verbose ( " %s: Label for sector % " PRIu64
" found at sector % " PRIu64
" - ignoring " , dev_name ( dev ) ,
( uint64_t ) xlate64 ( lh - > sector_xl ) ,
sector + scan_sector ) ;
2002-11-18 14:04:08 +00:00
continue ;
}
2010-09-27 19:09:34 +00:00
if ( calc_crc ( INITIAL_CRC , ( uint8_t * ) & lh - > offset_xl , LABEL_SIZE -
( ( uint8_t * ) & lh - > offset_xl - ( uint8_t * ) lh ) ) ! =
2002-11-18 14:04:08 +00:00
xlate32 ( lh - > crc_xl ) ) {
2016-11-01 11:02:01 +01:00
log_very_verbose ( " Label checksum incorrect on %s - "
" ignoring " , dev_name ( dev ) ) ;
2002-11-18 14:04:08 +00:00
continue ;
}
2018-01-02 14:58:21 +00:00
if ( l )
2002-11-18 14:04:08 +00:00
continue ;
}
2008-11-03 22:14:30 +00:00
dm_list_iterate_items ( li , & _labellers ) {
2007-04-23 18:21:01 +00:00
if ( li - > l - > ops - > can_handle ( li - > l , ( char * ) lh ,
sector + scan_sector ) ) {
2011-06-01 15:30:36 +00:00
log_very_verbose ( " %s: %s label detected at "
" sector % " PRIu64 ,
dev_name ( dev ) , li - > name ,
sector + scan_sector ) ;
2018-01-02 14:58:21 +00:00
if ( l ) {
2002-11-18 14:04:08 +00:00
log_error ( " Ignoring additional label "
" on %s at sector % " PRIu64 ,
2007-04-23 18:21:01 +00:00
dev_name ( dev ) ,
sector + scan_sector ) ;
2002-11-18 14:04:08 +00:00
continue ;
}
2017-12-19 01:12:18 +00:00
memcpy ( labelbuf , lh , LABEL_SIZE ) ;
2018-01-02 16:01:10 +00:00
flp - > label_sector = sector + scan_sector ;
2018-01-02 14:58:21 +00:00
l = li - > l ;
2002-11-18 14:04:08 +00:00
break ;
}
}
}
2018-01-02 14:58:21 +00:00
if ( ! l ) {
2016-06-06 14:04:17 -05:00
if ( ( info = lvmcache_info_from_pvid ( dev - > pvid , dev , 0 ) ) )
2015-03-18 23:43:02 +00:00
_update_lvmcache_orphan ( info ) ;
2002-11-18 14:04:08 +00:00
log_very_verbose ( " %s: No label detected " , dev_name ( dev ) ) ;
2018-01-05 02:31:28 +00:00
flp - > ret = 0 ;
2018-01-21 15:41:49 +00:00
_set_label_read_result ( 1 , ioflags , flp , NULL ) ;
2018-01-02 14:58:21 +00:00
} else
2018-01-21 15:41:49 +00:00
( void ) ( l - > ops - > read ) ( l , dev , labelbuf , ioflags , & _set_label_read_result , flp ) ;
2001-12-11 11:42:30 +00:00
}
2002-11-18 14:04:08 +00:00
/* FIXME Also wipe associated metadata area headers? */
2002-01-11 10:43:32 +00:00
int label_remove ( struct device * dev )
2001-12-11 11:42:30 +00:00
{
2017-12-19 01:12:18 +00:00
char labelbuf [ LABEL_SIZE ] __attribute__ ( ( aligned ( 8 ) ) ) ;
2002-11-18 14:04:08 +00:00
int r = 1 ;
uint64_t sector ;
int wipe ;
struct labeller_i * li ;
struct label_header * lh ;
2017-08-11 20:32:04 +01:00
struct lvmcache_info * info ;
2018-01-10 19:50:53 +00:00
const char * readbuf = NULL ;
2002-11-18 14:04:08 +00:00
2017-12-19 01:12:18 +00:00
memset ( labelbuf , 0 , LABEL_SIZE ) ;
2002-01-10 15:01:58 +00:00
2002-11-18 14:04:08 +00:00
log_very_verbose ( " Scanning for labels to wipe from %s " , dev_name ( dev ) ) ;
2008-01-30 13:19:47 +00:00
if ( ! dev_open ( dev ) )
return_0 ;
2001-12-11 11:42:30 +00:00
2003-07-04 22:34:56 +00:00
/*
* We flush the device just in case someone is stupid
* enough to be trying to import an open pv into lvm .
*/
dev_flush ( dev ) ;
2018-01-09 21:13:46 +00:00
if ( ! ( readbuf = dev_read ( dev , UINT64_C ( 0 ) , LABEL_SCAN_SIZE , DEV_IO_LABEL ) ) ) {
2013-01-07 22:30:29 +00:00
log_debug_devs ( " %s: Failed to read label area " , dev_name ( dev ) ) ;
2002-11-18 14:04:08 +00:00
goto out ;
}
/* Scan first few sectors for anything looking like a label */
for ( sector = 0 ; sector < LABEL_SCAN_SECTORS ;
sector + = LABEL_SIZE > > SECTOR_SHIFT ) {
2018-01-09 21:13:46 +00:00
lh = ( struct label_header * ) ( readbuf + ( sector < < SECTOR_SHIFT ) ) ;
2002-11-18 14:04:08 +00:00
wipe = 0 ;
2006-05-09 21:23:51 +00:00
if ( ! strncmp ( ( char * ) lh - > id , LABEL_ID , sizeof ( lh - > id ) ) ) {
2002-11-18 14:04:08 +00:00
if ( xlate64 ( lh - > sector_xl ) = = sector )
wipe = 1 ;
} else {
2008-11-03 22:14:30 +00:00
dm_list_iterate_items ( li , & _labellers ) {
2002-11-18 14:04:08 +00:00
if ( li - > l - > ops - > can_handle ( li - > l , ( char * ) lh ,
sector ) ) {
wipe = 1 ;
break ;
}
}
}
if ( wipe ) {
2016-11-01 11:02:01 +01:00
log_very_verbose ( " %s: Wiping label at sector % " PRIu64 ,
dev_name ( dev ) , sector ) ;
2017-12-19 01:12:18 +00:00
if ( dev_write ( dev , sector < < SECTOR_SHIFT , LABEL_SIZE , DEV_IO_LABEL , labelbuf ) ) {
2017-08-11 20:32:04 +01:00
/* Also remove the PV record from cache. */
info = lvmcache_info_from_pvid ( dev - > pvid , dev , 0 ) ;
if ( info )
lvmcache_del ( info ) ;
} else {
2002-11-18 14:04:08 +00:00
log_error ( " Failed to remove label from %s at "
" sector % " PRIu64 , dev_name ( dev ) ,
sector ) ;
r = 0 ;
}
}
}
out :
if ( ! dev_close ( dev ) )
stack ;
return r ;
2001-12-11 11:42:30 +00:00
}
2018-01-08 23:08:22 +00:00
static int _label_read ( struct device * dev , uint64_t scan_sector , struct label * * result ,
2018-01-21 15:41:49 +00:00
unsigned ioflags , lvm_callback_fn_t process_label_data_fn , void * process_label_data_context )
2001-12-11 11:42:30 +00:00
{
2006-04-11 13:55:59 +00:00
struct lvmcache_info * info ;
2018-01-02 16:01:10 +00:00
struct find_labeller_params * flp ;
2001-12-11 11:42:30 +00:00
2016-06-06 14:04:17 -05:00
if ( ( info = lvmcache_info_from_pvid ( dev - > pvid , dev , 1 ) ) ) {
log_debug_devs ( " Reading label from lvmcache for %s " , dev_name ( dev ) ) ;
2018-01-11 02:39:30 +00:00
if ( result )
* result = lvmcache_get_label ( info ) ;
2018-02-06 21:43:06 +00:00
if ( process_label_data_fn ) {
log_debug_io ( " Completed label reading for %s " , dev_name ( dev ) ) ;
2018-01-21 15:41:49 +00:00
process_label_data_fn ( 0 , ioflags , process_label_data_context , NULL ) ;
2018-02-06 21:43:06 +00:00
}
2008-01-29 23:45:48 +00:00
return 1 ;
}
2018-01-02 16:01:10 +00:00
if ( ! ( flp = dm_pool_zalloc ( _labeller_mem , sizeof * flp ) ) ) {
log_error ( " find_labeller_params allocation failed. " ) ;
return 0 ;
}
flp - > dev = dev ;
flp - > scan_sector = scan_sector ;
flp - > result = result ;
2018-01-08 23:08:22 +00:00
flp - > process_label_data_fn = process_label_data_fn ;
flp - > process_label_data_context = process_label_data_context ;
2018-01-05 02:31:28 +00:00
flp - > ret = 1 ;
2018-01-02 16:01:10 +00:00
/* Ensure result is always wiped as a precaution */
if ( result )
* result = NULL ;
2016-06-06 14:04:17 -05:00
log_debug_devs ( " Reading label from device %s " , dev_name ( dev ) ) ;
2011-05-28 09:48:14 +00:00
if ( ! dev_open_readonly ( dev ) ) {
2002-11-18 14:04:08 +00:00
stack ;
2006-04-11 13:55:59 +00:00
2016-06-06 14:04:17 -05:00
if ( ( info = lvmcache_info_from_pvid ( dev - > pvid , dev , 0 ) ) )
2015-03-18 23:43:02 +00:00
_update_lvmcache_orphan ( info ) ;
2006-04-11 13:55:59 +00:00
2018-01-02 14:58:21 +00:00
return 0 ;
2001-12-11 11:42:30 +00:00
}
2018-02-06 21:43:06 +00:00
dev_read_callback ( dev , scan_sector < < SECTOR_SHIFT , LABEL_SCAN_SIZE , DEV_IO_LABEL , ioflags , _find_labeller , flp ) ;
2018-01-22 15:41:11 +00:00
if ( process_label_data_fn )
return 1 ;
else
return flp - > ret ;
2002-11-18 14:04:08 +00:00
}
2018-01-11 02:39:30 +00:00
/* result may be NULL if caller doesn't need it */
2018-01-02 14:19:20 +00:00
int label_read ( struct device * dev , struct label * * result , uint64_t scan_sector )
{
2018-01-21 15:41:49 +00:00
return _label_read ( dev , scan_sector , result , 0 , NULL , NULL ) ;
2018-01-08 23:08:22 +00:00
}
2018-01-21 15:41:49 +00:00
int label_read_callback ( struct device * dev , uint64_t scan_sector , unsigned ioflags ,
2018-01-08 23:08:22 +00:00
lvm_callback_fn_t process_label_data_fn , void * process_label_data_context )
{
2018-01-21 15:41:49 +00:00
return _label_read ( dev , scan_sector , NULL , ioflags , process_label_data_fn , process_label_data_context ) ;
2018-01-02 14:19:20 +00:00
}
2002-11-18 14:04:08 +00:00
/* Caller may need to use label_get_handler to create label struct! */
int label_write ( struct device * dev , struct label * label )
{
2010-07-09 15:34:40 +00:00
char buf [ LABEL_SIZE ] __attribute__ ( ( aligned ( 8 ) ) ) ;
2002-11-18 14:04:08 +00:00
struct label_header * lh = ( struct label_header * ) buf ;
int r = 1 ;
2003-08-26 21:12:06 +00:00
if ( ! label - > labeller - > ops - > write ) {
2009-07-15 20:02:46 +00:00
log_error ( " Label handler does not support label writes " ) ;
2003-08-26 21:12:06 +00:00
return 0 ;
}
2002-11-18 14:04:08 +00:00
if ( ( LABEL_SIZE + ( label - > sector < < SECTOR_SHIFT ) ) > LABEL_SCAN_SIZE ) {
log_error ( " Label sector % " PRIu64 " beyond range (%ld) " ,
label - > sector , LABEL_SCAN_SECTORS ) ;
return 0 ;
}
memset ( buf , 0 , LABEL_SIZE ) ;
2006-05-09 21:23:51 +00:00
strncpy ( ( char * ) lh - > id , LABEL_ID , sizeof ( lh - > id ) ) ;
2002-11-18 14:04:08 +00:00
lh - > sector_xl = xlate64 ( label - > sector ) ;
lh - > offset_xl = xlate32 ( sizeof ( * lh ) ) ;
2008-01-30 13:19:47 +00:00
if ( ! ( label - > labeller - > ops - > write ) ( label , buf ) )
return_0 ;
2002-11-18 14:04:08 +00:00
2010-09-27 19:09:34 +00:00
lh - > crc_xl = xlate32 ( calc_crc ( INITIAL_CRC , ( uint8_t * ) & lh - > offset_xl , LABEL_SIZE -
( ( uint8_t * ) & lh - > offset_xl - ( uint8_t * ) lh ) ) ) ;
2002-11-18 14:04:08 +00:00
2008-01-30 13:19:47 +00:00
if ( ! dev_open ( dev ) )
return_0 ;
2002-11-18 14:04:08 +00:00
2016-11-01 11:02:01 +01:00
log_very_verbose ( " %s: Writing label to sector % " PRIu64 " with stored offset % "
PRIu32 " . " , dev_name ( dev ) , label - > sector ,
xlate32 ( lh - > offset_xl ) ) ;
2017-12-04 23:18:56 +00:00
if ( ! dev_write ( dev , label - > sector < < SECTOR_SHIFT , LABEL_SIZE , DEV_IO_LABEL , buf ) ) {
2013-01-07 22:30:29 +00:00
log_debug_devs ( " Failed to write label to %s " , dev_name ( dev ) ) ;
2002-11-18 14:04:08 +00:00
r = 0 ;
}
2003-07-04 22:34:56 +00:00
if ( ! dev_close ( dev ) )
2002-11-18 14:04:08 +00:00
stack ;
return r ;
2001-12-11 11:42:30 +00:00
}
2002-11-18 14:04:08 +00:00
void label_destroy ( struct label * label )
2001-12-11 16:49:40 +00:00
{
2002-11-18 14:04:08 +00:00
label - > labeller - > ops - > destroy_label ( label - > labeller , label ) ;
2005-10-16 23:03:59 +00:00
dm_free ( label ) ;
2002-11-18 14:04:08 +00:00
}
struct label * label_create ( struct labeller * labeller )
{
struct label * label ;
2010-09-30 21:06:50 +00:00
if ( ! ( label = dm_zalloc ( sizeof ( * label ) ) ) ) {
2002-11-18 14:04:08 +00:00
log_error ( " label allocaction failed " ) ;
return NULL ;
}
label - > labeller = labeller ;
labeller - > ops - > initialise_label ( labeller , label ) ;
return label ;
2001-12-11 16:49:40 +00:00
}