2005-04-17 02:20:36 +04:00
/*
* Copyright ( C ) 2001 Sistina Software ( UK ) Limited
*
* This file is released under the GPL .
*/
2016-05-12 23:28:10 +03:00
# include "dm-core.h"
2005-04-17 02:20:36 +04:00
# include <linux/module.h>
# include <linux/init.h>
# include <linux/kmod.h>
# include <linux/bio.h>
2006-06-26 11:27:35 +04:00
# define DM_MSG_PREFIX "target"
2005-04-17 02:20:36 +04:00
static LIST_HEAD ( _targets ) ;
static DECLARE_RWSEM ( _lock ) ;
2009-04-02 22:55:28 +04:00
static inline struct target_type * __find_target_type ( const char * name )
2005-04-17 02:20:36 +04:00
{
2009-04-02 22:55:28 +04:00
struct target_type * tt ;
2005-04-17 02:20:36 +04:00
2009-04-02 22:55:28 +04:00
list_for_each_entry ( tt , & _targets , list )
if ( ! strcmp ( name , tt - > name ) )
return tt ;
2005-04-17 02:20:36 +04:00
return NULL ;
}
2009-04-02 22:55:28 +04:00
static struct target_type * get_target_type ( const char * name )
2005-04-17 02:20:36 +04:00
{
2009-04-02 22:55:28 +04:00
struct target_type * tt ;
2005-04-17 02:20:36 +04:00
down_read ( & _lock ) ;
2009-04-02 22:55:28 +04:00
tt = __find_target_type ( name ) ;
if ( tt & & ! try_module_get ( tt - > module ) )
tt = NULL ;
2005-04-17 02:20:36 +04:00
up_read ( & _lock ) ;
2009-04-02 22:55:28 +04:00
return tt ;
2005-04-17 02:20:36 +04:00
}
static void load_module ( const char * name )
{
request_module ( " dm-%s " , name ) ;
}
struct target_type * dm_get_target_type ( const char * name )
{
2009-04-02 22:55:28 +04:00
struct target_type * tt = get_target_type ( name ) ;
2005-04-17 02:20:36 +04:00
2009-04-02 22:55:28 +04:00
if ( ! tt ) {
2005-04-17 02:20:36 +04:00
load_module ( name ) ;
2009-04-02 22:55:28 +04:00
tt = get_target_type ( name ) ;
2005-04-17 02:20:36 +04:00
}
2009-04-02 22:55:28 +04:00
return tt ;
2005-04-17 02:20:36 +04:00
}
2009-04-02 22:55:28 +04:00
void dm_put_target_type ( struct target_type * tt )
2005-04-17 02:20:36 +04:00
{
down_read ( & _lock ) ;
2009-04-02 22:55:28 +04:00
module_put ( tt - > module ) ;
2005-04-17 02:20:36 +04:00
up_read ( & _lock ) ;
}
int dm_target_iterate ( void ( * iter_func ) ( struct target_type * tt ,
void * param ) , void * param )
{
2009-04-02 22:55:28 +04:00
struct target_type * tt ;
2005-04-17 02:20:36 +04:00
down_read ( & _lock ) ;
2009-04-02 22:55:28 +04:00
list_for_each_entry ( tt , & _targets , list )
iter_func ( tt , param ) ;
2005-04-17 02:20:36 +04:00
up_read ( & _lock ) ;
return 0 ;
}
2009-04-02 22:55:28 +04:00
int dm_register_target ( struct target_type * tt )
2005-04-17 02:20:36 +04:00
{
int rv = 0 ;
down_write ( & _lock ) ;
2009-04-02 22:55:28 +04:00
if ( __find_target_type ( tt - > name ) )
2005-04-17 02:20:36 +04:00
rv = - EEXIST ;
else
2009-04-02 22:55:28 +04:00
list_add ( & tt - > list , & _targets ) ;
2005-04-17 02:20:36 +04:00
up_write ( & _lock ) ;
return rv ;
}
2009-04-02 22:55:28 +04:00
void dm_unregister_target ( struct target_type * tt )
2005-04-17 02:20:36 +04:00
{
down_write ( & _lock ) ;
2009-04-02 22:55:28 +04:00
if ( ! __find_target_type ( tt - > name ) ) {
DMCRIT ( " Unregistering unrecognised target: %s " , tt - > name ) ;
2009-01-06 06:04:58 +03:00
BUG ( ) ;
2005-04-17 02:20:36 +04:00
}
2009-04-02 22:55:28 +04:00
list_del ( & tt - > list ) ;
2005-04-17 02:20:36 +04:00
up_write ( & _lock ) ;
}
/*
* io - err : always fails an io , useful for bringing
* up LVs that have holes in them .
*/
2009-04-02 22:55:28 +04:00
static int io_err_ctr ( struct dm_target * tt , unsigned int argc , char * * args )
2005-04-17 02:20:36 +04:00
{
2010-08-12 07:14:14 +04:00
/*
* Return error for discards instead of - EOPNOTSUPP
*/
2013-03-02 02:45:47 +04:00
tt - > num_discard_bios = 1 ;
2010-08-12 07:14:14 +04:00
2005-04-17 02:20:36 +04:00
return 0 ;
}
2009-04-02 22:55:28 +04:00
static void io_err_dtr ( struct dm_target * tt )
2005-04-17 02:20:36 +04:00
{
/* empty */
}
2012-12-22 00:23:41 +04:00
static int io_err_map ( struct dm_target * tt , struct bio * bio )
2005-04-17 02:20:36 +04:00
{
2017-06-03 10:38:02 +03:00
return DM_MAPIO_KILL ;
2005-04-17 02:20:36 +04:00
}
2014-12-18 05:08:12 +03:00
static int io_err_clone_and_map_rq ( struct dm_target * ti , struct request * rq ,
union map_info * map_context ,
struct request * * clone )
{
2017-04-26 10:40:39 +03:00
return DM_MAPIO_KILL ;
2014-12-18 05:08:12 +03:00
}
2019-04-24 18:19:05 +03:00
static void io_err_release_clone_rq ( struct request * clone ,
union map_info * map_context )
2014-12-18 05:08:12 +03:00
{
}
2017-04-12 23:37:44 +03:00
static long io_err_dax_direct_access ( struct dm_target * ti , pgoff_t pgoff ,
long nr_pages , void * * kaddr , pfn_t * pfn )
2016-06-25 00:09:35 +03:00
{
return - EIO ;
}
2005-04-17 02:20:36 +04:00
static struct target_type error_target = {
. name = " error " ,
2016-06-25 00:09:35 +03:00
. version = { 1 , 5 , 0 } ,
2016-02-07 02:38:46 +03:00
. features = DM_TARGET_WILDCARD ,
2005-04-17 02:20:36 +04:00
. ctr = io_err_ctr ,
. dtr = io_err_dtr ,
. map = io_err_map ,
2014-12-18 05:08:12 +03:00
. clone_and_map_rq = io_err_clone_and_map_rq ,
. release_clone_rq = io_err_release_clone_rq ,
2017-04-12 23:37:44 +03:00
. direct_access = io_err_dax_direct_access ,
2005-04-17 02:20:36 +04:00
} ;
int __init dm_target_init ( void )
{
return dm_register_target ( & error_target ) ;
}
void dm_target_exit ( void )
{
2009-01-06 06:04:58 +03:00
dm_unregister_target ( & error_target ) ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL ( dm_register_target ) ;
EXPORT_SYMBOL ( dm_unregister_target ) ;