2009-01-06 06:05:17 +03:00
/*
* Copyright ( C ) 2001 - 2002 Sistina Software ( UK ) Limited .
* Copyright ( C ) 2006 - 2008 Red Hat GmbH
*
* This file is released under the GPL .
*/
# include "dm-exception-store.h"
# include <linux/mm.h>
# include <linux/pagemap.h>
# include <linux/vmalloc.h>
# include <linux/slab.h>
# include <linux/dm-io.h>
# define DM_MSG_PREFIX "transient snapshot"
/*-----------------------------------------------------------------
* Implementation of the store for non - persistent snapshots .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
struct transient_c {
sector_t next_free ;
} ;
2009-04-02 22:55:31 +04:00
static void transient_dtr ( struct dm_exception_store * store )
2009-01-06 06:05:17 +03:00
{
kfree ( store - > context ) ;
}
2009-01-06 06:05:19 +03:00
static int transient_read_metadata ( struct dm_exception_store * store ,
int ( * callback ) ( void * callback_context ,
chunk_t old , chunk_t new ) ,
void * callback_context )
2009-01-06 06:05:17 +03:00
{
return 0 ;
}
2009-01-06 06:05:19 +03:00
static int transient_prepare_exception ( struct dm_exception_store * store ,
2009-12-11 02:52:10 +03:00
struct dm_exception * e )
2009-01-06 06:05:17 +03:00
{
2009-04-02 22:55:30 +04:00
struct transient_c * tc = store - > context ;
2009-12-11 02:52:12 +03:00
sector_t size = get_dev_size ( dm_snap_cow ( store - > snap ) - > bdev ) ;
2009-01-06 06:05:17 +03:00
2009-04-02 22:55:32 +04:00
if ( size < ( tc - > next_free + store - > chunk_size ) )
2009-01-06 06:05:17 +03:00
return - 1 ;
2009-04-02 22:55:33 +04:00
e - > new_chunk = sector_to_chunk ( store , tc - > next_free ) ;
2009-04-02 22:55:32 +04:00
tc - > next_free + = store - > chunk_size ;
2009-01-06 06:05:17 +03:00
return 0 ;
}
2009-01-06 06:05:19 +03:00
static void transient_commit_exception ( struct dm_exception_store * store ,
2009-12-11 02:52:10 +03:00
struct dm_exception * e ,
2009-01-06 06:05:19 +03:00
void ( * callback ) ( void * , int success ) ,
void * callback_context )
2009-01-06 06:05:17 +03:00
{
/* Just succeed */
callback ( callback_context , 1 ) ;
}
2009-12-11 02:52:11 +03:00
static void transient_usage ( struct dm_exception_store * store ,
sector_t * total_sectors ,
sector_t * sectors_allocated ,
sector_t * metadata_sectors )
2009-01-06 06:05:17 +03:00
{
2009-12-11 02:52:11 +03:00
* sectors_allocated = ( ( struct transient_c * ) store - > context ) - > next_free ;
2009-12-11 02:52:12 +03:00
* total_sectors = get_dev_size ( dm_snap_cow ( store - > snap ) - > bdev ) ;
2009-12-11 02:52:11 +03:00
* metadata_sectors = 0 ;
2009-01-06 06:05:17 +03:00
}
2009-04-02 22:55:31 +04:00
static int transient_ctr ( struct dm_exception_store * store ,
unsigned argc , char * * argv )
2009-01-06 06:05:17 +03:00
{
struct transient_c * tc ;
tc = kmalloc ( sizeof ( struct transient_c ) , GFP_KERNEL ) ;
if ( ! tc )
return - ENOMEM ;
tc - > next_free = 0 ;
store - > context = tc ;
return 0 ;
}
2009-04-02 22:55:35 +04:00
static unsigned transient_status ( struct dm_exception_store * store ,
status_type_t status , char * result ,
unsigned maxlen )
2009-04-02 22:55:31 +04:00
{
2009-04-02 22:55:35 +04:00
unsigned sz = 0 ;
switch ( status ) {
case STATUSTYPE_INFO :
break ;
case STATUSTYPE_TABLE :
2009-12-11 02:52:12 +03:00
DMEMIT ( " N %llu " , ( unsigned long long ) store - > chunk_size ) ;
2009-04-02 22:55:35 +04:00
}
2009-04-02 22:55:31 +04:00
return sz ;
}
static struct dm_exception_store_type _transient_type = {
. name = " transient " ,
. module = THIS_MODULE ,
. ctr = transient_ctr ,
. dtr = transient_dtr ,
. read_metadata = transient_read_metadata ,
. prepare_exception = transient_prepare_exception ,
. commit_exception = transient_commit_exception ,
2009-12-11 02:52:11 +03:00
. usage = transient_usage ,
2009-04-02 22:55:31 +04:00
. status = transient_status ,
} ;
static struct dm_exception_store_type _transient_compat_type = {
. name = " N " ,
. module = THIS_MODULE ,
. ctr = transient_ctr ,
. dtr = transient_dtr ,
. read_metadata = transient_read_metadata ,
. prepare_exception = transient_prepare_exception ,
. commit_exception = transient_commit_exception ,
2009-12-11 02:52:11 +03:00
. usage = transient_usage ,
2009-04-02 22:55:31 +04:00
. status = transient_status ,
} ;
2009-01-06 06:05:17 +03:00
int dm_transient_snapshot_init ( void )
{
2009-04-02 22:55:31 +04:00
int r ;
r = dm_exception_store_type_register ( & _transient_type ) ;
if ( r ) {
DMWARN ( " Unable to register transient exception store type " ) ;
return r ;
}
r = dm_exception_store_type_register ( & _transient_compat_type ) ;
if ( r ) {
DMWARN ( " Unable to register old-style transient "
" exception store type " ) ;
dm_exception_store_type_unregister ( & _transient_type ) ;
return r ;
}
return r ;
2009-01-06 06:05:17 +03:00
}
void dm_transient_snapshot_exit ( void )
{
2009-04-02 22:55:31 +04:00
dm_exception_store_type_unregister ( & _transient_type ) ;
dm_exception_store_type_unregister ( & _transient_compat_type ) ;
2009-01-06 06:05:17 +03:00
}