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 BUG_ON(ti->use < 0); 82 up_read(&_lock); 83 84 return; 85 } 86 87 static struct tt_internal *alloc_target(struct target_type *t) 88 { 89 struct tt_internal *ti = kmalloc(sizeof(*ti), GFP_KERNEL); 90 91 if (ti) { 92 memset(ti, 0, sizeof(*ti)); 93 ti->tt = *t; 94 } 95 96 return ti; 97 } 98 99 100 int dm_target_iterate(void (*iter_func)(struct target_type *tt, 101 void *param), void *param) 102 { 103 struct tt_internal *ti; 104 105 down_read(&_lock); 106 list_for_each_entry (ti, &_targets, list) 107 iter_func(&ti->tt, param); 108 up_read(&_lock); 109 110 return 0; 111 } 112 113 int dm_register_target(struct target_type *t) 114 { 115 int rv = 0; 116 struct tt_internal *ti = alloc_target(t); 117 118 if (!ti) 119 return -ENOMEM; 120 121 down_write(&_lock); 122 if (__find_target_type(t->name)) 123 rv = -EEXIST; 124 else 125 list_add(&ti->list, &_targets); 126 127 up_write(&_lock); 128 if (rv) 129 kfree(ti); 130 return rv; 131 } 132 133 int dm_unregister_target(struct target_type *t) 134 { 135 struct tt_internal *ti; 136 137 down_write(&_lock); 138 if (!(ti = __find_target_type(t->name))) { 139 up_write(&_lock); 140 return -EINVAL; 141 } 142 143 if (ti->use) { 144 up_write(&_lock); 145 return -ETXTBSY; 146 } 147 148 list_del(&ti->list); 149 kfree(ti); 150 151 up_write(&_lock); 152 return 0; 153 } 154 155 /* 156 * io-err: always fails an io, useful for bringing 157 * up LVs that have holes in them. 158 */ 159 static int io_err_ctr(struct dm_target *ti, unsigned int argc, char **args) 160 { 161 return 0; 162 } 163 164 static void io_err_dtr(struct dm_target *ti) 165 { 166 /* empty */ 167 } 168 169 static int io_err_map(struct dm_target *ti, struct bio *bio, 170 union map_info *map_context) 171 { 172 return -EIO; 173 } 174 175 static struct target_type error_target = { 176 .name = "error", 177 .version = {1, 0, 1}, 178 .ctr = io_err_ctr, 179 .dtr = io_err_dtr, 180 .map = io_err_map, 181 }; 182 183 int __init dm_target_init(void) 184 { 185 return dm_register_target(&error_target); 186 } 187 188 void dm_target_exit(void) 189 { 190 if (dm_unregister_target(&error_target)) 191 DMWARN("error target unregistration failed"); 192 } 193 194 EXPORT_SYMBOL(dm_register_target); 195 EXPORT_SYMBOL(dm_unregister_target); 196