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