1/* 2 * Copyright (C) 2001 Sistina Software (UK) Limited 3 * 4 * This file is released under the GPL. 5 */ 6 7#include "dm-core.h" 8 9#include <linux/module.h> 10#include <linux/init.h> 11#include <linux/kmod.h> 12#include <linux/bio.h> 13 14#define DM_MSG_PREFIX "target" 15 16static LIST_HEAD(_targets); 17static DECLARE_RWSEM(_lock); 18 19static inline struct target_type *__find_target_type(const char *name) 20{ 21 struct target_type *tt; 22 23 list_for_each_entry(tt, &_targets, list) 24 if (!strcmp(name, tt->name)) 25 return tt; 26 27 return NULL; 28} 29 30static struct target_type *get_target_type(const char *name) 31{ 32 struct target_type *tt; 33 34 down_read(&_lock); 35 36 tt = __find_target_type(name); 37 if (tt && !try_module_get(tt->module)) 38 tt = NULL; 39 40 up_read(&_lock); 41 return tt; 42} 43 44static void load_module(const char *name) 45{ 46 request_module("dm-%s", name); 47} 48 49struct target_type *dm_get_target_type(const char *name) 50{ 51 struct target_type *tt = get_target_type(name); 52 53 if (!tt) { 54 load_module(name); 55 tt = get_target_type(name); 56 } 57 58 return tt; 59} 60 61void dm_put_target_type(struct target_type *tt) 62{ 63 down_read(&_lock); 64 module_put(tt->module); 65 up_read(&_lock); 66} 67 68int dm_target_iterate(void (*iter_func)(struct target_type *tt, 69 void *param), void *param) 70{ 71 struct target_type *tt; 72 73 down_read(&_lock); 74 list_for_each_entry(tt, &_targets, list) 75 iter_func(tt, param); 76 up_read(&_lock); 77 78 return 0; 79} 80 81int dm_register_target(struct target_type *tt) 82{ 83 int rv = 0; 84 85 down_write(&_lock); 86 if (__find_target_type(tt->name)) 87 rv = -EEXIST; 88 else 89 list_add(&tt->list, &_targets); 90 91 up_write(&_lock); 92 return rv; 93} 94 95void dm_unregister_target(struct target_type *tt) 96{ 97 down_write(&_lock); 98 if (!__find_target_type(tt->name)) { 99 DMCRIT("Unregistering unrecognised target: %s", tt->name); 100 BUG(); 101 } 102 103 list_del(&tt->list); 104 105 up_write(&_lock); 106} 107 108/* 109 * io-err: always fails an io, useful for bringing 110 * up LVs that have holes in them. 111 */ 112static int io_err_ctr(struct dm_target *tt, unsigned int argc, char **args) 113{ 114 /* 115 * Return error for discards instead of -EOPNOTSUPP 116 */ 117 tt->num_discard_bios = 1; 118 119 return 0; 120} 121 122static void io_err_dtr(struct dm_target *tt) 123{ 124 /* empty */ 125} 126 127static int io_err_map(struct dm_target *tt, struct bio *bio) 128{ 129 return DM_MAPIO_KILL; 130} 131 132static int io_err_clone_and_map_rq(struct dm_target *ti, struct request *rq, 133 union map_info *map_context, 134 struct request **clone) 135{ 136 return DM_MAPIO_KILL; 137} 138 139static void io_err_release_clone_rq(struct request *clone, 140 union map_info *map_context) 141{ 142} 143 144static long io_err_dax_direct_access(struct dm_target *ti, pgoff_t pgoff, 145 long nr_pages, void **kaddr, pfn_t *pfn) 146{ 147 return -EIO; 148} 149 150static struct target_type error_target = { 151 .name = "error", 152 .version = {1, 5, 0}, 153 .features = DM_TARGET_WILDCARD, 154 .ctr = io_err_ctr, 155 .dtr = io_err_dtr, 156 .map = io_err_map, 157 .clone_and_map_rq = io_err_clone_and_map_rq, 158 .release_clone_rq = io_err_release_clone_rq, 159 .direct_access = io_err_dax_direct_access, 160}; 161 162int __init dm_target_init(void) 163{ 164 return dm_register_target(&error_target); 165} 166 167void dm_target_exit(void) 168{ 169 dm_unregister_target(&error_target); 170} 171 172EXPORT_SYMBOL(dm_register_target); 173EXPORT_SYMBOL(dm_unregister_target); 174