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