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