dm-target.c 2.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * 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>
#include <linux/slab.h>

15 16
#define DM_MSG_PREFIX "target"

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

#define DM_MOD_NAME_SIZE 32

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

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

	return NULL;
}

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

	down_read(&_lock);

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

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

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

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

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

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

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

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

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

	return 0;
}

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

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

	up_write(&_lock);
	return rv;
}

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

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

	up_write(&_lock);
}

/*
 * io-err: always fails an io, useful for bringing
 * up LVs that have holes in them.
 */
115
static int io_err_ctr(struct dm_target *tt, unsigned int argc, char **args)
L
Linus Torvalds 已提交
116 117 118 119
{
	return 0;
}

120
static void io_err_dtr(struct dm_target *tt)
L
Linus Torvalds 已提交
121 122 123 124
{
	/* empty */
}

125
static int io_err_map(struct dm_target *tt, struct bio *bio,
L
Linus Torvalds 已提交
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
		      union map_info *map_context)
{
	return -EIO;
}

static struct target_type error_target = {
	.name = "error",
	.version = {1, 0, 1},
	.ctr  = io_err_ctr,
	.dtr  = io_err_dtr,
	.map  = io_err_map,
};

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

void dm_target_exit(void)
{
146
	dm_unregister_target(&error_target);
L
Linus Torvalds 已提交
147 148 149 150
}

EXPORT_SYMBOL(dm_register_target);
EXPORT_SYMBOL(dm_unregister_target);