2009-01-06 06:05:15 +03:00
/*
* Copyright ( C ) 2001 - 2002 Sistina Software ( UK ) Limited .
* Copyright ( C ) 2008 Red Hat , Inc . All rights reserved .
*
* Device - mapper snapshot exception store .
*
* This file is released under the GPL .
*/
# ifndef _LINUX_DM_EXCEPTION_STORE
# define _LINUX_DM_EXCEPTION_STORE
# include <linux/blkdev.h>
2009-01-06 06:05:19 +03:00
# include <linux/device-mapper.h>
2009-01-06 06:05:15 +03:00
/*
* The snapshot code deals with largish chunks of the disk at a
* time . Typically 32 k - 512 k .
*/
typedef sector_t chunk_t ;
/*
* An exception is used where an old chunk of data has been
* replaced by a new one .
* If chunk_t is 64 bits in size , the top 8 bits of new_chunk hold the number
* of chunks that follow contiguously . Remaining bits hold the number of the
* chunk within the device .
*/
2009-12-11 02:52:10 +03:00
struct dm_exception {
2009-01-06 06:05:15 +03:00
struct list_head hash_list ;
chunk_t old_chunk ;
chunk_t new_chunk ;
} ;
/*
* Abstraction to handle the meta / layout of exception stores ( the
* COW device ) .
*/
2009-04-02 22:55:30 +04:00
struct dm_exception_store ;
struct dm_exception_store_type {
2009-04-02 22:55:31 +04:00
const char * name ;
struct module * module ;
2009-04-02 22:55:30 +04:00
int ( * ctr ) ( struct dm_exception_store * store ,
unsigned argc , char * * argv ) ;
2009-01-06 06:05:15 +03:00
/*
* Destroys this object when you ' ve finished with it .
*/
2009-04-02 22:55:30 +04:00
void ( * dtr ) ( struct dm_exception_store * store ) ;
2009-01-06 06:05:15 +03:00
/*
* The target shouldn ' t read the COW device until this is
2009-01-06 06:05:19 +03:00
* called . As exceptions are read from the COW , they are
* reported back via the callback .
2009-01-06 06:05:15 +03:00
*/
2009-01-06 06:05:19 +03:00
int ( * 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:15 +03:00
/*
* Find somewhere to store the next exception .
*/
2009-01-06 06:05:16 +03:00
int ( * prepare_exception ) ( struct dm_exception_store * store ,
2009-12-11 02:52:10 +03:00
struct dm_exception * e ) ;
2009-01-06 06:05:15 +03:00
/*
* Update the metadata with this exception .
*/
2009-01-06 06:05:16 +03:00
void ( * commit_exception ) ( struct dm_exception_store * store ,
2009-12-11 02:52:10 +03:00
struct dm_exception * e ,
2009-01-06 06:05:15 +03:00
void ( * callback ) ( void * , int success ) ,
void * callback_context ) ;
2009-12-11 02:52:29 +03:00
/*
* Returns 0 if the exception store is empty .
*
* If there are exceptions still to be merged , sets
* * last_old_chunk and * last_new_chunk to the most recent
* still - to - be - merged chunk and returns the number of
* consecutive previous ones .
*/
int ( * prepare_merge ) ( struct dm_exception_store * store ,
chunk_t * last_old_chunk , chunk_t * last_new_chunk ) ;
/*
* Clear the last n exceptions .
* nr_merged must be < = the value returned by prepare_merge .
*/
int ( * commit_merge ) ( struct dm_exception_store * store , int nr_merged ) ;
2009-01-06 06:05:15 +03:00
/*
* The snapshot is invalid , note this in the metadata .
*/
2009-01-06 06:05:16 +03:00
void ( * drop_snapshot ) ( struct dm_exception_store * store ) ;
2009-01-06 06:05:15 +03:00
2009-04-02 22:55:35 +04:00
unsigned ( * status ) ( struct dm_exception_store * store ,
status_type_t status , char * result ,
unsigned maxlen ) ;
2009-01-06 06:05:19 +03:00
2009-01-06 06:05:15 +03:00
/*
* Return how full the snapshot is .
*/
2009-12-11 02:52:11 +03:00
void ( * usage ) ( struct dm_exception_store * store ,
sector_t * total_sectors , sector_t * sectors_allocated ,
sector_t * metadata_sectors ) ;
2009-04-02 22:55:31 +04:00
/* For internal device-mapper use only. */
struct list_head list ;
2009-04-02 22:55:30 +04:00
} ;
2009-12-11 02:52:12 +03:00
struct dm_snapshot ;
2009-04-02 22:55:30 +04:00
struct dm_exception_store {
2009-04-02 22:55:31 +04:00
struct dm_exception_store_type * type ;
2009-12-11 02:52:12 +03:00
struct dm_snapshot * snap ;
2009-04-02 22:55:33 +04:00
2009-04-02 22:55:32 +04:00
/* Size of data blocks saved - must be a power of 2 */
2009-10-17 02:18:17 +04:00
unsigned chunk_size ;
unsigned chunk_mask ;
unsigned chunk_shift ;
2009-04-02 22:55:32 +04:00
2009-01-06 06:05:15 +03:00
void * context ;
} ;
2009-12-11 02:52:12 +03:00
/*
2010-08-12 07:13:51 +04:00
* Obtain the origin or cow device used by a given snapshot .
2009-12-11 02:52:12 +03:00
*/
2010-08-12 07:13:51 +04:00
struct dm_dev * dm_snap_origin ( struct dm_snapshot * snap ) ;
2009-12-11 02:52:12 +03:00
struct dm_dev * dm_snap_cow ( struct dm_snapshot * snap ) ;
2009-01-06 06:05:15 +03:00
/*
* Funtions to manipulate consecutive chunks
*/
2009-06-19 10:08:50 +04:00
# if defined(CONFIG_LBDAF) || (BITS_PER_LONG == 64)
2009-01-06 06:05:15 +03:00
# define DM_CHUNK_CONSECUTIVE_BITS 8
# define DM_CHUNK_NUMBER_BITS 56
static inline chunk_t dm_chunk_number ( chunk_t chunk )
{
return chunk & ( chunk_t ) ( ( 1ULL < < DM_CHUNK_NUMBER_BITS ) - 1ULL ) ;
}
2009-12-11 02:52:10 +03:00
static inline unsigned dm_consecutive_chunk_count ( struct dm_exception * e )
2009-01-06 06:05:15 +03:00
{
return e - > new_chunk > > DM_CHUNK_NUMBER_BITS ;
}
2009-12-11 02:52:10 +03:00
static inline void dm_consecutive_chunk_count_inc ( struct dm_exception * e )
2009-01-06 06:05:15 +03:00
{
e - > new_chunk + = ( 1ULL < < DM_CHUNK_NUMBER_BITS ) ;
BUG_ON ( ! dm_consecutive_chunk_count ( e ) ) ;
}
2009-12-11 02:52:32 +03:00
static inline void dm_consecutive_chunk_count_dec ( struct dm_exception * e )
{
BUG_ON ( ! dm_consecutive_chunk_count ( e ) ) ;
e - > new_chunk - = ( 1ULL < < DM_CHUNK_NUMBER_BITS ) ;
}
2009-01-06 06:05:15 +03:00
# else
# define DM_CHUNK_CONSECUTIVE_BITS 0
static inline chunk_t dm_chunk_number ( chunk_t chunk )
{
return chunk ;
}
2009-12-11 02:52:10 +03:00
static inline unsigned dm_consecutive_chunk_count ( struct dm_exception * e )
2009-01-06 06:05:15 +03:00
{
return 0 ;
}
2009-12-11 02:52:10 +03:00
static inline void dm_consecutive_chunk_count_inc ( struct dm_exception * e )
2009-01-06 06:05:15 +03:00
{
}
2009-12-11 02:52:32 +03:00
static inline void dm_consecutive_chunk_count_dec ( struct dm_exception * e )
{
}
2009-01-06 06:05:15 +03:00
# endif
2009-04-02 22:55:33 +04:00
/*
* Return the number of sectors in the device .
*/
static inline sector_t get_dev_size ( struct block_device * bdev )
{
2009-06-22 13:12:14 +04:00
return i_size_read ( bdev - > bd_inode ) > > SECTOR_SHIFT ;
2009-04-02 22:55:33 +04:00
}
static inline chunk_t sector_to_chunk ( struct dm_exception_store * store ,
sector_t sector )
{
2009-12-11 02:52:08 +03:00
return sector > > store - > chunk_shift ;
2009-04-02 22:55:33 +04:00
}
2009-04-02 22:55:31 +04:00
int dm_exception_store_type_register ( struct dm_exception_store_type * type ) ;
int dm_exception_store_type_unregister ( struct dm_exception_store_type * type ) ;
2009-09-04 23:40:41 +04:00
int dm_exception_store_set_chunk_size ( struct dm_exception_store * store ,
2009-10-17 02:18:17 +04:00
unsigned chunk_size ,
2009-09-04 23:40:41 +04:00
char * * error ) ;
2009-04-02 22:55:34 +04:00
int dm_exception_store_create ( struct dm_target * ti , int argc , char * * argv ,
2009-12-11 02:52:12 +03:00
struct dm_snapshot * snap ,
2009-04-02 22:55:34 +04:00
unsigned * args_used ,
2009-04-02 22:55:31 +04:00
struct dm_exception_store * * store ) ;
void dm_exception_store_destroy ( struct dm_exception_store * store ) ;
2009-01-06 06:05:17 +03:00
int dm_exception_store_init ( void ) ;
void dm_exception_store_exit ( void ) ;
2009-01-06 06:05:15 +03:00
/*
* Two exception store implementations .
*/
2009-01-06 06:05:17 +03:00
int dm_persistent_snapshot_init ( void ) ;
void dm_persistent_snapshot_exit ( void ) ;
int dm_transient_snapshot_init ( void ) ;
void dm_transient_snapshot_exit ( void ) ;
2009-01-06 06:05:15 +03:00
# endif /* _LINUX_DM_EXCEPTION_STORE */