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