Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 77b2555b52a894a2e39a42e43d993df875c46a6a 196 lines 3.3 kB view raw
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 15struct tt_internal { 16 struct target_type tt; 17 18 struct list_head list; 19 long use; 20}; 21 22static LIST_HEAD(_targets); 23static DECLARE_RWSEM(_lock); 24 25#define DM_MOD_NAME_SIZE 32 26 27static 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 38static 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 56static void load_module(const char *name) 57{ 58 request_module("dm-%s", name); 59} 60 61struct 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 73void 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 88static 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 101int 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 114int 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 134int 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 */ 160static int io_err_ctr(struct dm_target *ti, unsigned int argc, char **args) 161{ 162 return 0; 163} 164 165static void io_err_dtr(struct dm_target *ti) 166{ 167 /* empty */ 168} 169 170static int io_err_map(struct dm_target *ti, struct bio *bio, 171 union map_info *map_context) 172{ 173 return -EIO; 174} 175 176static 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 184int __init dm_target_init(void) 185{ 186 return dm_register_target(&error_target); 187} 188 189void dm_target_exit(void) 190{ 191 if (dm_unregister_target(&error_target)) 192 DMWARN("error target unregistration failed"); 193} 194 195EXPORT_SYMBOL(dm_register_target); 196EXPORT_SYMBOL(dm_unregister_target);