2023-01-25 23:00:44 +03:00
// SPDX-License-Identifier: GPL-2.0-only
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>
2011-05-27 23:50:58 +04:00
# include <linux/export.h>
2009-01-06 06:05:17 +03:00
# include <linux/slab.h>
# include <linux/dm-io.h>
# define DM_MSG_PREFIX "transient snapshot"
2023-01-26 17:48:30 +03:00
/*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2009-01-06 06:05:17 +03:00
* Implementation of the store for non - persistent snapshots .
2023-01-26 17:48:30 +03:00
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2009-01-06 06:05:17 +03:00
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 ,
2016-01-09 03:07:55 +03:00
struct dm_exception * e , int valid ,
2023-02-02 00:31:43 +03:00
void ( * callback ) ( void * , int success ) ,
2009-01-06 06:05:19 +03:00
void * callback_context )
2009-01-06 06:05:17 +03:00
{
/* Just succeed */
2016-01-09 03:07:55 +03:00
callback ( callback_context , valid ) ;
2009-01-06 06:05:17 +03:00
}
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
}
2015-10-09 01:05:41 +03:00
static int transient_ctr ( struct dm_exception_store * store , char * options )
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 ;
}
2023-01-25 23:14:58 +03:00
static unsigned int transient_status ( struct dm_exception_store * store ,
2009-04-02 22:55:35 +04:00
status_type_t status , char * result ,
2023-01-25 23:14:58 +03:00
unsigned int maxlen )
2009-04-02 22:55:31 +04:00
{
2023-01-25 23:14:58 +03:00
unsigned int sz = 0 ;
2009-04-02 22:55:35 +04:00
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 ) ;
2021-07-13 03:49:03 +03:00
break ;
case STATUSTYPE_IMA :
* result = ' \0 ' ;
break ;
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 ) {
2023-02-03 20:55:47 +03:00
DMWARN ( " Unable to register old-style transient exception store type " ) ;
2009-04-02 22:55:31 +04:00
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
}