dm-target.c 3.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * Copyright (C) 2001 Sistina Software (UK) Limited
 *
 * This file is released under the GPL.
 */

#include "dm.h"

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kmod.h>
#include <linux/bio.h>

14 15
#define DM_MSG_PREFIX "target"

L
Linus Torvalds 已提交
16 17 18 19 20
static LIST_HEAD(_targets);
static DECLARE_RWSEM(_lock);

#define DM_MOD_NAME_SIZE 32

21
static inline struct target_type *__find_target_type(const char *name)
L
Linus Torvalds 已提交
22
{
23
	struct target_type *tt;
L
Linus Torvalds 已提交
24

25 26 27
	list_for_each_entry(tt, &_targets, list)
		if (!strcmp(name, tt->name))
			return tt;
L
Linus Torvalds 已提交
28 29 30 31

	return NULL;
}

32
static struct target_type *get_target_type(const char *name)
L
Linus Torvalds 已提交
33
{
34
	struct target_type *tt;
L
Linus Torvalds 已提交
35 36 37

	down_read(&_lock);

38 39 40
	tt = __find_target_type(name);
	if (tt && !try_module_get(tt->module))
		tt = NULL;
L
Linus Torvalds 已提交
41 42

	up_read(&_lock);
43
	return tt;
L
Linus Torvalds 已提交
44 45 46 47 48 49 50 51 52
}

static void load_module(const char *name)
{
	request_module("dm-%s", name);
}

struct target_type *dm_get_target_type(const char *name)
{
53
	struct target_type *tt = get_target_type(name);
L
Linus Torvalds 已提交
54

55
	if (!tt) {
L
Linus Torvalds 已提交
56
		load_module(name);
57
		tt = get_target_type(name);
L
Linus Torvalds 已提交
58 59
	}

60
	return tt;
L
Linus Torvalds 已提交
61 62
}

63
void dm_put_target_type(struct target_type *tt)
L
Linus Torvalds 已提交
64 65
{
	down_read(&_lock);
66
	module_put(tt->module);
L
Linus Torvalds 已提交
67 68 69 70 71 72
	up_read(&_lock);
}

int dm_target_iterate(void (*iter_func)(struct target_type *tt,
					void *param), void *param)
{
73
	struct target_type *tt;
L
Linus Torvalds 已提交
74 75

	down_read(&_lock);
76 77
	list_for_each_entry(tt, &_targets, list)
		iter_func(tt, param);
L
Linus Torvalds 已提交
78 79 80 81 82
	up_read(&_lock);

	return 0;
}

83
int dm_register_target(struct target_type *tt)
L
Linus Torvalds 已提交
84 85 86 87
{
	int rv = 0;

	down_write(&_lock);
88
	if (__find_target_type(tt->name))
L
Linus Torvalds 已提交
89 90
		rv = -EEXIST;
	else
91
		list_add(&tt->list, &_targets);
L
Linus Torvalds 已提交
92 93 94 95 96

	up_write(&_lock);
	return rv;
}

97
void dm_unregister_target(struct target_type *tt)
L
Linus Torvalds 已提交
98 99
{
	down_write(&_lock);
100 101
	if (!__find_target_type(tt->name)) {
		DMCRIT("Unregistering unrecognised target: %s", tt->name);
102
		BUG();
L
Linus Torvalds 已提交
103 104
	}

105
	list_del(&tt->list);
L
Linus Torvalds 已提交
106 107 108 109 110 111 112 113

	up_write(&_lock);
}

/*
 * io-err: always fails an io, useful for bringing
 * up LVs that have holes in them.
 */
114
static int io_err_ctr(struct dm_target *tt, unsigned int argc, char **args)
L
Linus Torvalds 已提交
115
{
116 117 118
	/*
	 * Return error for discards instead of -EOPNOTSUPP
	 */
119
	tt->num_discard_bios = 1;
120

L
Linus Torvalds 已提交
121 122 123
	return 0;
}

124
static void io_err_dtr(struct dm_target *tt)
L
Linus Torvalds 已提交
125 126 127 128
{
	/* empty */
}

M
Mikulas Patocka 已提交
129
static int io_err_map(struct dm_target *tt, struct bio *bio)
L
Linus Torvalds 已提交
130 131 132 133
{
	return -EIO;
}

134 135 136 137 138 139
static int io_err_map_rq(struct dm_target *ti, struct request *clone,
			 union map_info *map_context)
{
	return -EIO;
}

140 141 142 143 144 145 146 147 148 149 150
static int io_err_clone_and_map_rq(struct dm_target *ti, struct request *rq,
				   union map_info *map_context,
				   struct request **clone)
{
	return -EIO;
}

static void io_err_release_clone_rq(struct request *clone)
{
}

L
Linus Torvalds 已提交
151 152
static struct target_type error_target = {
	.name = "error",
153 154
	.version = {1, 4, 0},
	.features = DM_TARGET_WILDCARD,
L
Linus Torvalds 已提交
155 156 157
	.ctr  = io_err_ctr,
	.dtr  = io_err_dtr,
	.map  = io_err_map,
158
	.map_rq = io_err_map_rq,
159 160
	.clone_and_map_rq = io_err_clone_and_map_rq,
	.release_clone_rq = io_err_release_clone_rq,
L
Linus Torvalds 已提交
161 162 163 164 165 166 167 168 169
};

int __init dm_target_init(void)
{
	return dm_register_target(&error_target);
}

void dm_target_exit(void)
{
170
	dm_unregister_target(&error_target);
L
Linus Torvalds 已提交
171 172 173 174
}

EXPORT_SYMBOL(dm_register_target);
EXPORT_SYMBOL(dm_unregister_target);