11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright (C) 2001 Sistina Software (UK) Limited 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * This file is released under the GPL. 51da177e4SLinus Torvalds */ 61da177e4SLinus Torvalds 74cc96131SMike Snitzer #include "dm-core.h" 81da177e4SLinus Torvalds 91da177e4SLinus Torvalds #include <linux/module.h> 101da177e4SLinus Torvalds #include <linux/init.h> 111da177e4SLinus Torvalds #include <linux/kmod.h> 121da177e4SLinus Torvalds #include <linux/bio.h> 13*e511c4a3SJane Chu #include <linux/dax.h> 141da177e4SLinus Torvalds 1572d94861SAlasdair G Kergon #define DM_MSG_PREFIX "target" 1672d94861SAlasdair G Kergon 171da177e4SLinus Torvalds static LIST_HEAD(_targets); 181da177e4SLinus Torvalds static DECLARE_RWSEM(_lock); 191da177e4SLinus Torvalds 2045194e4fSCheng Renquan static inline struct target_type *__find_target_type(const char *name) 211da177e4SLinus Torvalds { 2245194e4fSCheng Renquan struct target_type *tt; 231da177e4SLinus Torvalds 2445194e4fSCheng Renquan list_for_each_entry(tt, &_targets, list) 2545194e4fSCheng Renquan if (!strcmp(name, tt->name)) 2645194e4fSCheng Renquan return tt; 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds return NULL; 291da177e4SLinus Torvalds } 301da177e4SLinus Torvalds 3145194e4fSCheng Renquan static struct target_type *get_target_type(const char *name) 321da177e4SLinus Torvalds { 3345194e4fSCheng Renquan struct target_type *tt; 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds down_read(&_lock); 361da177e4SLinus Torvalds 3745194e4fSCheng Renquan tt = __find_target_type(name); 3845194e4fSCheng Renquan if (tt && !try_module_get(tt->module)) 3945194e4fSCheng Renquan tt = NULL; 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds up_read(&_lock); 4245194e4fSCheng Renquan return tt; 431da177e4SLinus Torvalds } 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds static void load_module(const char *name) 461da177e4SLinus Torvalds { 471da177e4SLinus Torvalds request_module("dm-%s", name); 481da177e4SLinus Torvalds } 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds struct target_type *dm_get_target_type(const char *name) 511da177e4SLinus Torvalds { 5245194e4fSCheng Renquan struct target_type *tt = get_target_type(name); 531da177e4SLinus Torvalds 5445194e4fSCheng Renquan if (!tt) { 551da177e4SLinus Torvalds load_module(name); 5645194e4fSCheng Renquan tt = get_target_type(name); 571da177e4SLinus Torvalds } 581da177e4SLinus Torvalds 5945194e4fSCheng Renquan return tt; 601da177e4SLinus Torvalds } 611da177e4SLinus Torvalds 6245194e4fSCheng Renquan void dm_put_target_type(struct target_type *tt) 631da177e4SLinus Torvalds { 641da177e4SLinus Torvalds down_read(&_lock); 6545194e4fSCheng Renquan module_put(tt->module); 661da177e4SLinus Torvalds up_read(&_lock); 671da177e4SLinus Torvalds } 681da177e4SLinus Torvalds 691da177e4SLinus Torvalds int dm_target_iterate(void (*iter_func)(struct target_type *tt, 701da177e4SLinus Torvalds void *param), void *param) 711da177e4SLinus Torvalds { 7245194e4fSCheng Renquan struct target_type *tt; 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds down_read(&_lock); 7545194e4fSCheng Renquan list_for_each_entry(tt, &_targets, list) 7645194e4fSCheng Renquan iter_func(tt, param); 771da177e4SLinus Torvalds up_read(&_lock); 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds return 0; 801da177e4SLinus Torvalds } 811da177e4SLinus Torvalds 8245194e4fSCheng Renquan int dm_register_target(struct target_type *tt) 831da177e4SLinus Torvalds { 841da177e4SLinus Torvalds int rv = 0; 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds down_write(&_lock); 8745194e4fSCheng Renquan if (__find_target_type(tt->name)) 881da177e4SLinus Torvalds rv = -EEXIST; 891da177e4SLinus Torvalds else 9045194e4fSCheng Renquan list_add(&tt->list, &_targets); 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds up_write(&_lock); 931da177e4SLinus Torvalds return rv; 941da177e4SLinus Torvalds } 951da177e4SLinus Torvalds 9645194e4fSCheng Renquan void dm_unregister_target(struct target_type *tt) 971da177e4SLinus Torvalds { 981da177e4SLinus Torvalds down_write(&_lock); 9945194e4fSCheng Renquan if (!__find_target_type(tt->name)) { 10045194e4fSCheng Renquan DMCRIT("Unregistering unrecognised target: %s", tt->name); 10110d3bd09SMikulas Patocka BUG(); 1021da177e4SLinus Torvalds } 1031da177e4SLinus Torvalds 10445194e4fSCheng Renquan list_del(&tt->list); 1051da177e4SLinus Torvalds 1061da177e4SLinus Torvalds up_write(&_lock); 1071da177e4SLinus Torvalds } 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds /* 1101da177e4SLinus Torvalds * io-err: always fails an io, useful for bringing 1111da177e4SLinus Torvalds * up LVs that have holes in them. 1121da177e4SLinus Torvalds */ 11345194e4fSCheng Renquan static int io_err_ctr(struct dm_target *tt, unsigned int argc, char **args) 1141da177e4SLinus Torvalds { 11538e1b257SMike Snitzer /* 11638e1b257SMike Snitzer * Return error for discards instead of -EOPNOTSUPP 11738e1b257SMike Snitzer */ 11855a62eefSAlasdair G Kergon tt->num_discard_bios = 1; 11938e1b257SMike Snitzer 1201da177e4SLinus Torvalds return 0; 1211da177e4SLinus Torvalds } 1221da177e4SLinus Torvalds 12345194e4fSCheng Renquan static void io_err_dtr(struct dm_target *tt) 1241da177e4SLinus Torvalds { 1251da177e4SLinus Torvalds /* empty */ 1261da177e4SLinus Torvalds } 1271da177e4SLinus Torvalds 1287de3ee57SMikulas Patocka static int io_err_map(struct dm_target *tt, struct bio *bio) 1291da177e4SLinus Torvalds { 130846785e6SChristoph Hellwig return DM_MAPIO_KILL; 1311da177e4SLinus Torvalds } 1321da177e4SLinus Torvalds 133e5863d9aSMike Snitzer static int io_err_clone_and_map_rq(struct dm_target *ti, struct request *rq, 134e5863d9aSMike Snitzer union map_info *map_context, 135e5863d9aSMike Snitzer struct request **clone) 136e5863d9aSMike Snitzer { 137412445acSChristoph Hellwig return DM_MAPIO_KILL; 138e5863d9aSMike Snitzer } 139e5863d9aSMike Snitzer 1405de719e3SYufen Yu static void io_err_release_clone_rq(struct request *clone, 1415de719e3SYufen Yu union map_info *map_context) 142e5863d9aSMike Snitzer { 143e5863d9aSMike Snitzer } 144e5863d9aSMike Snitzer 145817bf402SDan Williams static long io_err_dax_direct_access(struct dm_target *ti, pgoff_t pgoff, 146*e511c4a3SJane Chu long nr_pages, enum dax_access_mode mode, void **kaddr, 147*e511c4a3SJane Chu pfn_t *pfn) 148f8df1fdfSMike Snitzer { 149f8df1fdfSMike Snitzer return -EIO; 150f8df1fdfSMike Snitzer } 151f8df1fdfSMike Snitzer 1521da177e4SLinus Torvalds static struct target_type error_target = { 1531da177e4SLinus Torvalds .name = "error", 154f8df1fdfSMike Snitzer .version = {1, 5, 0}, 155f083b09bSMike Snitzer .features = DM_TARGET_WILDCARD, 1561da177e4SLinus Torvalds .ctr = io_err_ctr, 1571da177e4SLinus Torvalds .dtr = io_err_dtr, 1581da177e4SLinus Torvalds .map = io_err_map, 159e5863d9aSMike Snitzer .clone_and_map_rq = io_err_clone_and_map_rq, 160e5863d9aSMike Snitzer .release_clone_rq = io_err_release_clone_rq, 161817bf402SDan Williams .direct_access = io_err_dax_direct_access, 1621da177e4SLinus Torvalds }; 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds int __init dm_target_init(void) 1651da177e4SLinus Torvalds { 1661da177e4SLinus Torvalds return dm_register_target(&error_target); 1671da177e4SLinus Torvalds } 1681da177e4SLinus Torvalds 1691da177e4SLinus Torvalds void dm_target_exit(void) 1701da177e4SLinus Torvalds { 17110d3bd09SMikulas Patocka dm_unregister_target(&error_target); 1721da177e4SLinus Torvalds } 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds EXPORT_SYMBOL(dm_register_target); 1751da177e4SLinus Torvalds EXPORT_SYMBOL(dm_unregister_target); 176