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