Home | History | Annotate | Line # | Download | only in dm
dm_target.c revision 1.6.6.1
      1  1.6.6.1   jym /*        $NetBSD: dm_target.c,v 1.6.6.1 2009/05/13 17:19:16 jym Exp $      */
      2      1.2  haad 
      3      1.2  haad /*
      4      1.2  haad  * Copyright (c) 2008 The NetBSD Foundation, Inc.
      5      1.2  haad  * All rights reserved.
      6      1.2  haad  *
      7      1.2  haad  * This code is derived from software contributed to The NetBSD Foundation
      8      1.2  haad  * by Adam Hamsik.
      9      1.2  haad  *
     10      1.2  haad  * Redistribution and use in source and binary forms, with or without
     11      1.2  haad  * modification, are permitted provided that the following conditions
     12      1.2  haad  * are met:
     13      1.2  haad  * 1. Redistributions of source code Must retain the above copyright
     14      1.2  haad  *    notice, this list of conditions and the following disclaimer.
     15      1.2  haad  * 2. Redistributions in binary form must reproduce the above copyright
     16      1.2  haad  *    notice, this list of conditions and the following disclaimer in the
     17      1.2  haad  *    documentation and/or other materials provided with the distribution.
     18      1.2  haad  *
     19      1.2  haad  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20      1.2  haad  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21      1.2  haad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22      1.2  haad  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23      1.2  haad  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24      1.2  haad  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25      1.2  haad  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26      1.2  haad  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27      1.2  haad  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28      1.2  haad  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29      1.2  haad  * POSSIBILITY OF SUCH DAMAGE.
     30      1.2  haad  */
     31      1.2  haad 
     32      1.2  haad #include <sys/types.h>
     33      1.2  haad #include <sys/param.h>
     34      1.2  haad 
     35      1.2  haad #include <sys/kmem.h>
     36  1.6.6.1   jym #include <sys/module.h>
     37  1.6.6.1   jym 
     38      1.2  haad 
     39      1.2  haad #include "netbsd-dm.h"
     40      1.2  haad #include "dm.h"
     41      1.2  haad 
     42      1.3  haad static dm_target_t* dm_target_lookup_name(const char *);
     43      1.2  haad 
     44      1.2  haad TAILQ_HEAD(dm_target_head, dm_target);
     45      1.2  haad 
     46      1.2  haad static struct dm_target_head dm_target_list =
     47      1.2  haad TAILQ_HEAD_INITIALIZER(dm_target_list);
     48      1.2  haad 
     49      1.3  haad kmutex_t dm_target_mutex;
     50      1.3  haad 
     51      1.3  haad /*
     52      1.3  haad  * Called indirectly from dm_table_load_ioct to mark target as used.
     53      1.3  haad  */
     54      1.3  haad void
     55      1.3  haad dm_target_busy(dm_target_t *target)
     56      1.3  haad {
     57  1.6.6.1   jym 	atomic_inc_32(&target->ref_cnt);
     58      1.3  haad }
     59      1.3  haad 
     60  1.6.6.1   jym /*
     61  1.6.6.1   jym  * Release reference counter on target.
     62  1.6.6.1   jym  */
     63      1.3  haad void
     64      1.3  haad dm_target_unbusy(dm_target_t *target)
     65      1.3  haad {
     66  1.6.6.1   jym 	KASSERT(target->ref_cnt > 0);
     67  1.6.6.1   jym 	atomic_dec_32(&target->ref_cnt);
     68      1.3  haad }
     69      1.3  haad 
     70  1.6.6.1   jym /*
     71  1.6.6.1   jym  * Try to autoload target module if it was not found in current
     72  1.6.6.1   jym  * target list.
     73  1.6.6.1   jym  */
     74  1.6.6.1   jym dm_target_t *
     75  1.6.6.1   jym dm_target_autoload(const char *dm_target_name)
     76  1.6.6.1   jym {
     77  1.6.6.1   jym 	char name[30];
     78  1.6.6.1   jym 	u_int gen;
     79  1.6.6.1   jym 	dm_target_t *dmt;
     80  1.6.6.1   jym 
     81  1.6.6.1   jym 	snprintf(name, sizeof(name), "dm_target_%s", dm_target_name);
     82  1.6.6.1   jym 	name[29]='\0';
     83  1.6.6.1   jym 
     84  1.6.6.1   jym 	do {
     85  1.6.6.1   jym 		gen = module_gen;
     86  1.6.6.1   jym 
     87  1.6.6.1   jym 		/* Try to autoload target module */
     88  1.6.6.1   jym 		mutex_enter(&module_lock);
     89  1.6.6.1   jym 		(void) module_autoload(name, MODULE_CLASS_MISC);
     90  1.6.6.1   jym 		mutex_exit(&module_lock);
     91  1.6.6.1   jym 	} while (gen != module_gen);
     92  1.6.6.1   jym 
     93  1.6.6.1   jym 	mutex_enter(&dm_target_mutex);
     94  1.6.6.1   jym 	dmt = dm_target_lookup_name(dm_target_name);
     95  1.6.6.1   jym 	if (dmt != NULL)
     96  1.6.6.1   jym 		dm_target_busy(dmt);
     97  1.6.6.1   jym 	mutex_exit(&dm_target_mutex);
     98  1.6.6.1   jym 
     99  1.6.6.1   jym 	return dmt;
    100  1.6.6.1   jym }
    101  1.6.6.1   jym 
    102  1.6.6.1   jym /*
    103  1.6.6.1   jym  * Lookup for target in global target list.
    104  1.6.6.1   jym  */
    105      1.3  haad dm_target_t *
    106      1.3  haad dm_target_lookup(const char *dm_target_name)
    107      1.3  haad {
    108      1.3  haad 	dm_target_t *dmt;
    109      1.3  haad 
    110      1.3  haad 	dmt = NULL;
    111      1.3  haad 
    112  1.6.6.1   jym 	if (dm_target_name == NULL)
    113  1.6.6.1   jym 		return NULL;
    114      1.3  haad 
    115  1.6.6.1   jym 	mutex_enter(&dm_target_mutex);
    116      1.3  haad 
    117  1.6.6.1   jym 	dmt = dm_target_lookup_name(dm_target_name);
    118      1.3  haad 	if (dmt != NULL)
    119      1.3  haad 		dm_target_busy(dmt);
    120      1.3  haad 
    121      1.3  haad 	mutex_exit(&dm_target_mutex);
    122      1.3  haad 
    123      1.3  haad 	return dmt;
    124      1.3  haad }
    125      1.3  haad 
    126      1.2  haad /*
    127      1.2  haad  * Search for name in TAIL and return apropriate pointer.
    128      1.2  haad  */
    129      1.3  haad static dm_target_t*
    130      1.2  haad dm_target_lookup_name(const char *dm_target_name)
    131      1.2  haad {
    132      1.2  haad 	dm_target_t *dm_target;
    133      1.2  haad         int dlen; int slen;
    134      1.2  haad 
    135      1.3  haad 	slen = strlen(dm_target_name) + 1;
    136      1.2  haad 
    137      1.3  haad 	TAILQ_FOREACH(dm_target, &dm_target_list, dm_target_next) {
    138      1.3  haad 		dlen = strlen(dm_target->name) + 1;
    139      1.2  haad 		if (dlen != slen)
    140      1.2  haad 			continue;
    141      1.2  haad 
    142  1.6.6.1   jym 		if (strncmp(dm_target_name, dm_target->name, slen) == 0)
    143      1.3  haad 			return dm_target;
    144      1.2  haad 	}
    145      1.2  haad 
    146      1.2  haad 	return NULL;
    147      1.2  haad }
    148      1.2  haad 
    149      1.2  haad /*
    150      1.2  haad  * Insert new target struct into the TAIL.
    151      1.2  haad  * dm_target
    152      1.2  haad  *   contains name, version, function pointer to specifif target functions.
    153      1.2  haad  */
    154      1.2  haad int
    155      1.2  haad dm_target_insert(dm_target_t *dm_target)
    156      1.2  haad {
    157      1.2  haad 	dm_target_t *dmt;
    158      1.3  haad 
    159      1.3  haad 	mutex_enter(&dm_target_mutex);
    160      1.2  haad 
    161      1.2  haad 	dmt = dm_target_lookup_name(dm_target->name);
    162      1.3  haad 	if (dmt != NULL) {
    163      1.3  haad 		mutex_exit(&dm_target_mutex);
    164      1.2  haad 		return EEXIST;
    165      1.3  haad 	}
    166      1.3  haad 
    167      1.2  haad 	TAILQ_INSERT_TAIL(&dm_target_list, dm_target, dm_target_next);
    168      1.3  haad 
    169      1.3  haad 	mutex_exit(&dm_target_mutex);
    170      1.2  haad 
    171      1.2  haad 	return 0;
    172      1.2  haad }
    173      1.2  haad 
    174      1.2  haad 
    175      1.2  haad /*
    176      1.2  haad  * Remove target from TAIL, target is selected with it's name.
    177      1.2  haad  */
    178      1.2  haad int
    179      1.2  haad dm_target_rem(char *dm_target_name)
    180      1.2  haad {
    181      1.3  haad 	dm_target_t *dmt;
    182      1.2  haad 
    183      1.2  haad 	KASSERT(dm_target_name != NULL);
    184      1.3  haad 
    185      1.3  haad 	mutex_enter(&dm_target_mutex);
    186      1.3  haad 
    187      1.3  haad 	dmt = dm_target_lookup_name(dm_target_name);
    188      1.3  haad 	if (dmt == NULL) {
    189      1.3  haad 		mutex_exit(&dm_target_mutex);
    190      1.2  haad 		return ENOENT;
    191      1.3  haad 	}
    192      1.3  haad 
    193      1.3  haad 	if (dmt->ref_cnt > 0) {
    194      1.3  haad 		mutex_exit(&dm_target_mutex);
    195      1.3  haad 		return EBUSY;
    196      1.3  haad 	}
    197      1.2  haad 
    198      1.2  haad 	TAILQ_REMOVE(&dm_target_list,
    199      1.3  haad 	    dmt, dm_target_next);
    200      1.3  haad 
    201      1.3  haad 	mutex_exit(&dm_target_mutex);
    202      1.2  haad 
    203      1.3  haad 	(void)kmem_free(dmt, sizeof(dm_target_t));
    204      1.2  haad 
    205      1.2  haad 	return 0;
    206      1.2  haad }
    207      1.2  haad 
    208      1.2  haad /*
    209      1.2  haad  * Destroy all targets and remove them from queue.
    210      1.2  haad  * This routine is called from dm_detach, before module
    211      1.2  haad  * is unloaded.
    212      1.2  haad  */
    213      1.2  haad int
    214      1.2  haad dm_target_destroy(void)
    215      1.2  haad {
    216      1.2  haad 	dm_target_t *dm_target;
    217      1.2  haad 
    218      1.3  haad 	mutex_enter(&dm_target_mutex);
    219      1.2  haad 	while (TAILQ_FIRST(&dm_target_list) != NULL){
    220      1.2  haad 
    221      1.2  haad 		dm_target = TAILQ_FIRST(&dm_target_list);
    222      1.2  haad 
    223      1.2  haad 		TAILQ_REMOVE(&dm_target_list, TAILQ_FIRST(&dm_target_list),
    224      1.2  haad 		dm_target_next);
    225      1.2  haad 
    226      1.2  haad 		(void)kmem_free(dm_target, sizeof(dm_target_t));
    227      1.2  haad 	}
    228      1.3  haad 	mutex_exit(&dm_target_mutex);
    229      1.2  haad 
    230      1.4  haad 	mutex_destroy(&dm_target_mutex);
    231      1.4  haad 
    232      1.2  haad 	return 0;
    233      1.2  haad }
    234      1.2  haad 
    235      1.2  haad /*
    236      1.2  haad  * Allocate new target entry.
    237      1.2  haad  */
    238      1.2  haad dm_target_t*
    239      1.2  haad dm_target_alloc(const char *name)
    240      1.2  haad {
    241      1.2  haad 	return kmem_zalloc(sizeof(dm_target_t), KM_NOSLEEP);
    242      1.2  haad }
    243      1.2  haad 
    244      1.2  haad /*
    245      1.2  haad  * Return prop_array of dm_target dictionaries.
    246      1.2  haad  */
    247      1.2  haad prop_array_t
    248      1.2  haad dm_target_prop_list(void)
    249      1.2  haad {
    250      1.2  haad 	prop_array_t target_array,ver;
    251      1.2  haad 	prop_dictionary_t target_dict;
    252      1.2  haad 	dm_target_t *dm_target;
    253      1.2  haad 
    254      1.2  haad 	size_t i;
    255      1.2  haad 
    256      1.2  haad 	target_array = prop_array_create();
    257      1.3  haad 
    258      1.3  haad 	mutex_enter(&dm_target_mutex);
    259      1.2  haad 
    260      1.2  haad 	TAILQ_FOREACH (dm_target, &dm_target_list, dm_target_next){
    261      1.2  haad 
    262      1.2  haad 		target_dict  = prop_dictionary_create();
    263      1.2  haad 		ver = prop_array_create();
    264      1.2  haad 		prop_dictionary_set_cstring(target_dict, DM_TARGETS_NAME,
    265      1.2  haad 		    dm_target->name);
    266      1.2  haad 
    267      1.2  haad 		for (i = 0; i < 3; i++)
    268      1.2  haad 			prop_array_add_uint32(ver, dm_target->version[i]);
    269      1.2  haad 
    270      1.2  haad 		prop_dictionary_set(target_dict, DM_TARGETS_VERSION, ver);
    271      1.2  haad 		prop_array_add(target_array, target_dict);
    272      1.2  haad 
    273      1.2  haad 		prop_object_release(ver);
    274      1.2  haad 		prop_object_release(target_dict);
    275      1.2  haad 	}
    276      1.2  haad 
    277      1.3  haad 	mutex_exit(&dm_target_mutex);
    278      1.3  haad 
    279      1.2  haad 	return target_array;
    280      1.2  haad }
    281      1.2  haad 
    282      1.2  haad /* Initialize dm_target subsystem. */
    283      1.2  haad int
    284      1.2  haad dm_target_init(void)
    285      1.2  haad {
    286      1.6  haad 	dm_target_t *dmt,*dmt3;
    287      1.2  haad 	int r;
    288      1.2  haad 
    289      1.2  haad 	r = 0;
    290      1.3  haad 
    291      1.3  haad 	mutex_init(&dm_target_mutex, MUTEX_DEFAULT, IPL_NONE);
    292      1.2  haad 
    293      1.2  haad 	dmt = dm_target_alloc("linear");
    294      1.2  haad 	dmt3 = dm_target_alloc("striped");
    295      1.2  haad 
    296      1.2  haad 	dmt->version[0] = 1;
    297      1.2  haad 	dmt->version[1] = 0;
    298      1.2  haad 	dmt->version[2] = 2;
    299      1.2  haad 	strlcpy(dmt->name, "linear", DM_MAX_TYPE_NAME);
    300      1.2  haad 	dmt->init = &dm_target_linear_init;
    301      1.2  haad 	dmt->status = &dm_target_linear_status;
    302      1.2  haad 	dmt->strategy = &dm_target_linear_strategy;
    303      1.2  haad 	dmt->deps = &dm_target_linear_deps;
    304      1.2  haad 	dmt->destroy = &dm_target_linear_destroy;
    305      1.2  haad 	dmt->upcall = &dm_target_linear_upcall;
    306      1.2  haad 
    307      1.2  haad 	r = dm_target_insert(dmt);
    308      1.2  haad 
    309      1.2  haad 	dmt3->version[0] = 1;
    310      1.2  haad 	dmt3->version[1] = 0;
    311      1.2  haad 	dmt3->version[2] = 3;
    312      1.2  haad 	strlcpy(dmt3->name, "striped", DM_MAX_TYPE_NAME);
    313      1.5  haad 	dmt3->init = &dm_target_stripe_init;
    314      1.5  haad 	dmt3->status = &dm_target_stripe_status;
    315      1.5  haad 	dmt3->strategy = &dm_target_stripe_strategy;
    316      1.5  haad 	dmt3->deps = &dm_target_stripe_deps;
    317      1.5  haad 	dmt3->destroy = &dm_target_stripe_destroy;
    318      1.5  haad 	dmt3->upcall = &dm_target_stripe_upcall;
    319      1.2  haad 
    320      1.2  haad 	r = dm_target_insert(dmt3);
    321      1.2  haad 
    322      1.6  haad #ifdef notyet
    323      1.6  haad 	dmt5->version[0] = 1;
    324      1.2  haad 	dmt5->version[1] = 0;
    325      1.2  haad 	dmt5->version[2] = 5;
    326      1.2  haad 	strlcpy(dmt5->name, "snapshot", DM_MAX_TYPE_NAME);
    327      1.2  haad 	dmt5->init = &dm_target_snapshot_init;
    328      1.2  haad 	dmt5->status = &dm_target_snapshot_status;
    329      1.2  haad 	dmt5->strategy = &dm_target_snapshot_strategy;
    330      1.2  haad 	dmt5->deps = &dm_target_snapshot_deps;
    331      1.2  haad 	dmt5->destroy = &dm_target_snapshot_destroy;
    332      1.2  haad 	dmt5->upcall = &dm_target_snapshot_upcall;
    333      1.2  haad 
    334      1.2  haad 	r = dm_target_insert(dmt5);
    335      1.2  haad 
    336      1.2  haad 	dmt6->version[0] = 1;
    337      1.2  haad 	dmt6->version[1] = 0;
    338      1.2  haad 	dmt6->version[2] = 5;
    339      1.2  haad 	strlcpy(dmt6->name, "snapshot-origin", DM_MAX_TYPE_NAME);
    340      1.2  haad 	dmt6->init = &dm_target_snapshot_orig_init;
    341      1.2  haad 	dmt6->status = &dm_target_snapshot_orig_status;
    342      1.2  haad 	dmt6->strategy = &dm_target_snapshot_orig_strategy;
    343      1.2  haad 	dmt6->deps = &dm_target_snapshot_orig_deps;
    344      1.2  haad 	dmt6->destroy = &dm_target_snapshot_orig_destroy;
    345      1.2  haad 	dmt6->upcall = &dm_target_snapshot_orig_upcall;
    346      1.2  haad 
    347      1.6  haad 	r = dm_target_insert(dmt6);
    348      1.6  haad #endif
    349      1.2  haad 
    350      1.2  haad 	return r;
    351      1.2  haad }
    352