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
  17static LIST_HEAD(_targets);
  18static DECLARE_RWSEM(_lock);
  19
  20#define DM_MOD_NAME_SIZE 32
  21
  22static inline struct target_type *__find_target_type(const char *name)
  23{
  24        struct target_type *tt;
  25
  26        list_for_each_entry(tt, &_targets, list)
  27                if (!strcmp(name, tt->name))
  28                        return tt;
  29
  30        return NULL;
  31}
  32
  33static struct target_type *get_target_type(const char *name)
  34{
  35        struct target_type *tt;
  36
  37        down_read(&_lock);
  38
  39        tt = __find_target_type(name);
  40        if (tt && !try_module_get(tt->module))
  41                tt = NULL;
  42
  43        up_read(&_lock);
  44        return tt;
  45}
  46
  47static void load_module(const char *name)
  48{
  49        request_module("dm-%s", name);
  50}
  51
  52struct target_type *dm_get_target_type(const char *name)
  53{
  54        struct target_type *tt = get_target_type(name);
  55
  56        if (!tt) {
  57                load_module(name);
  58                tt = get_target_type(name);
  59        }
  60
  61        return tt;
  62}
  63
  64void dm_put_target_type(struct target_type *tt)
  65{
  66        down_read(&_lock);
  67        module_put(tt->module);
  68        up_read(&_lock);
  69}
  70
  71int dm_target_iterate(void (*iter_func)(struct target_type *tt,
  72                                        void *param), void *param)
  73{
  74        struct target_type *tt;
  75
  76        down_read(&_lock);
  77        list_for_each_entry(tt, &_targets, list)
  78                iter_func(tt, param);
  79        up_read(&_lock);
  80
  81        return 0;
  82}
  83
  84int dm_register_target(struct target_type *tt)
  85{
  86        int rv = 0;
  87
  88        down_write(&_lock);
  89        if (__find_target_type(tt->name))
  90                rv = -EEXIST;
  91        else
  92                list_add(&tt->list, &_targets);
  93
  94        up_write(&_lock);
  95        return rv;
  96}
  97
  98void dm_unregister_target(struct target_type *tt)
  99{
 100        down_write(&_lock);
 101        if (!__find_target_type(tt->name)) {
 102                DMCRIT("Unregistering unrecognised target: %s", tt->name);
 103                BUG();
 104        }
 105
 106        list_del(&tt->list);
 107
 108        up_write(&_lock);
 109}
 110
 111/*
 112 * io-err: always fails an io, useful for bringing
 113 * up LVs that have holes in them.
 114 */
 115static int io_err_ctr(struct dm_target *tt, unsigned int argc, char **args)
 116{
 117        return 0;
 118}
 119
 120static void io_err_dtr(struct dm_target *tt)
 121{
 122        /* empty */
 123}
 124
 125static int io_err_map(struct dm_target *tt, struct bio *bio,
 126                      union map_info *map_context)
 127{
 128        return -EIO;
 129}
 130
 131static struct target_type error_target = {
 132        .name = "error",
 133        .version = {1, 0, 1},
 134        .ctr  = io_err_ctr,
 135        .dtr  = io_err_dtr,
 136        .map  = io_err_map,
 137};
 138
 139int __init dm_target_init(void)
 140{
 141        return dm_register_target(&error_target);
 142}
 143
 144void dm_target_exit(void)
 145{
 146        dm_unregister_target(&error_target);
 147}
 148
 149EXPORT_SYMBOL(dm_register_target);
 150EXPORT_SYMBOL(dm_unregister_target);
 151