1 /*
2  * Copyright (C) 2001 Sistina Software (UK) Limited
3  *
4  * This file is released under the GPL.
5  */
6 
7 #include "dm-core.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/dax.h>
14 
15 #define DM_MSG_PREFIX "target"
16 
17 static LIST_HEAD(_targets);
18 static DECLARE_RWSEM(_lock);
19 
__find_target_type(const char * name)20 static inline struct target_type *__find_target_type(const char *name)
21 {
22 	struct target_type *tt;
23 
24 	list_for_each_entry(tt, &_targets, list)
25 		if (!strcmp(name, tt->name))
26 			return tt;
27 
28 	return NULL;
29 }
30 
get_target_type(const char * name)31 static struct target_type *get_target_type(const char *name)
32 {
33 	struct target_type *tt;
34 
35 	down_read(&_lock);
36 
37 	tt = __find_target_type(name);
38 	if (tt && !try_module_get(tt->module))
39 		tt = NULL;
40 
41 	up_read(&_lock);
42 	return tt;
43 }
44 
load_module(const char * name)45 static void load_module(const char *name)
46 {
47 	request_module("dm-%s", name);
48 }
49 
dm_get_target_type(const char * name)50 struct target_type *dm_get_target_type(const char *name)
51 {
52 	struct target_type *tt = get_target_type(name);
53 
54 	if (!tt) {
55 		load_module(name);
56 		tt = get_target_type(name);
57 	}
58 
59 	return tt;
60 }
61 
dm_put_target_type(struct target_type * tt)62 void dm_put_target_type(struct target_type *tt)
63 {
64 	down_read(&_lock);
65 	module_put(tt->module);
66 	up_read(&_lock);
67 }
68 
dm_target_iterate(void (* iter_func)(struct target_type * tt,void * param),void * param)69 int dm_target_iterate(void (*iter_func)(struct target_type *tt,
70 					void *param), void *param)
71 {
72 	struct target_type *tt;
73 
74 	down_read(&_lock);
75 	list_for_each_entry(tt, &_targets, list)
76 		iter_func(tt, param);
77 	up_read(&_lock);
78 
79 	return 0;
80 }
81 
dm_register_target(struct target_type * tt)82 int dm_register_target(struct target_type *tt)
83 {
84 	int rv = 0;
85 
86 	down_write(&_lock);
87 	if (__find_target_type(tt->name))
88 		rv = -EEXIST;
89 	else
90 		list_add(&tt->list, &_targets);
91 
92 	up_write(&_lock);
93 	return rv;
94 }
95 
dm_unregister_target(struct target_type * tt)96 void dm_unregister_target(struct target_type *tt)
97 {
98 	down_write(&_lock);
99 	if (!__find_target_type(tt->name)) {
100 		DMCRIT("Unregistering unrecognised target: %s", tt->name);
101 		BUG();
102 	}
103 
104 	list_del(&tt->list);
105 
106 	up_write(&_lock);
107 }
108 
109 /*
110  * io-err: always fails an io, useful for bringing
111  * up LVs that have holes in them.
112  */
io_err_ctr(struct dm_target * tt,unsigned int argc,char ** args)113 static int io_err_ctr(struct dm_target *tt, unsigned int argc, char **args)
114 {
115 	/*
116 	 * Return error for discards instead of -EOPNOTSUPP
117 	 */
118 	tt->num_discard_bios = 1;
119 
120 	return 0;
121 }
122 
io_err_dtr(struct dm_target * tt)123 static void io_err_dtr(struct dm_target *tt)
124 {
125 	/* empty */
126 }
127 
io_err_map(struct dm_target * tt,struct bio * bio)128 static int io_err_map(struct dm_target *tt, struct bio *bio)
129 {
130 	return DM_MAPIO_KILL;
131 }
132 
io_err_clone_and_map_rq(struct dm_target * ti,struct request * rq,union map_info * map_context,struct request ** clone)133 static int io_err_clone_and_map_rq(struct dm_target *ti, struct request *rq,
134 				   union map_info *map_context,
135 				   struct request **clone)
136 {
137 	return DM_MAPIO_KILL;
138 }
139 
io_err_release_clone_rq(struct request * clone,union map_info * map_context)140 static void io_err_release_clone_rq(struct request *clone,
141 				    union map_info *map_context)
142 {
143 }
144 
io_err_dax_direct_access(struct dm_target * ti,pgoff_t pgoff,long nr_pages,enum dax_access_mode mode,void ** kaddr,pfn_t * pfn)145 static long io_err_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
146 		long nr_pages, enum dax_access_mode mode, void **kaddr,
147 		pfn_t *pfn)
148 {
149 	return -EIO;
150 }
151 
152 static struct target_type error_target = {
153 	.name = "error",
154 	.version = {1, 5, 0},
155 	.features = DM_TARGET_WILDCARD,
156 	.ctr  = io_err_ctr,
157 	.dtr  = io_err_dtr,
158 	.map  = io_err_map,
159 	.clone_and_map_rq = io_err_clone_and_map_rq,
160 	.release_clone_rq = io_err_release_clone_rq,
161 	.direct_access = io_err_dax_direct_access,
162 };
163 
dm_target_init(void)164 int __init dm_target_init(void)
165 {
166 	return dm_register_target(&error_target);
167 }
168 
dm_target_exit(void)169 void dm_target_exit(void)
170 {
171 	dm_unregister_target(&error_target);
172 }
173 
174 EXPORT_SYMBOL(dm_register_target);
175 EXPORT_SYMBOL(dm_unregister_target);
176