Home | History | Annotate | Line # | Download | only in dm
dm_dev.c revision 1.1.2.10
      1   1.1.2.9  haad /*        $NetBSD: dm_dev.c,v 1.1.2.10 2008/09/26 22:57:13 haad Exp $      */
      2   1.1.2.4  haad 
      3   1.1.2.1  haad /*
      4   1.1.2.1  haad  * Copyright (c) 1996, 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
      5   1.1.2.1  haad  * All rights reserved.
      6   1.1.2.1  haad  *
      7   1.1.2.1  haad  * This code is derived from software contributed to The NetBSD Foundation
      8   1.1.2.1  haad  * by Adam Hamsik.
      9   1.1.2.1  haad  *
     10   1.1.2.1  haad  * Redistribution and use in source and binary forms, with or without
     11   1.1.2.1  haad  * modification, are permitted provided that the following conditions
     12   1.1.2.1  haad  * are met:
     13   1.1.2.1  haad  * 1. Redistributions of source code must retain the above copyright
     14   1.1.2.1  haad  *    notice, this list of conditions and the following disclaimer.
     15   1.1.2.1  haad  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1.2.1  haad  *    notice, this list of conditions and the following disclaimer in the
     17   1.1.2.1  haad  *    documentation and/or other materials provided with the distribution.
     18   1.1.2.1  haad  *
     19   1.1.2.1  haad  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.1.2.1  haad  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.1.2.1  haad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.1.2.1  haad  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.1.2.1  haad  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.1.2.1  haad  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.1.2.1  haad  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.1.2.1  haad  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.1.2.1  haad  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.1.2.1  haad  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.1.2.1  haad  * POSSIBILITY OF SUCH DAMAGE.
     30   1.1.2.1  haad  */
     31   1.1.2.1  haad 
     32   1.1.2.1  haad 
     33   1.1.2.1  haad #include <sys/types.h>
     34   1.1.2.1  haad #include <sys/param.h>
     35   1.1.2.1  haad 
     36   1.1.2.3  haad #include <sys/disklabel.h>
     37   1.1.2.1  haad #include <sys/errno.h>
     38   1.1.2.1  haad #include <sys/ioctl.h>
     39   1.1.2.1  haad #include <sys/ioccom.h>
     40   1.1.2.1  haad #include <sys/kmem.h>
     41   1.1.2.1  haad #include <sys/lkm.h>
     42   1.1.2.1  haad #include <sys/queue.h>
     43   1.1.2.1  haad 
     44   1.1.2.1  haad #include "netbsd-dm.h"
     45   1.1.2.1  haad #include "dm.h"
     46   1.1.2.1  haad 
     47   1.1.2.9  haad static struct dm_dev* dm_dev_lookup_name(const char *);
     48   1.1.2.9  haad static struct dm_dev* dm_dev_lookup_uuid(const char *);
     49   1.1.2.9  haad static struct dm_dev* dm_dev_lookup_minor(int);
     50   1.1.2.9  haad 
     51   1.1.2.1  haad static struct dm_dev_head dm_dev_list =
     52   1.1.2.1  haad TAILQ_HEAD_INITIALIZER(dm_dev_list);
     53   1.1.2.1  haad 
     54   1.1.2.1  haad kmutex_t dm_dev_mutex;
     55   1.1.2.1  haad 
     56   1.1.2.1  haad /*
     57   1.1.2.1  haad  * Locking architecture, for now I use mutexes later we can convert them to
     58   1.1.2.2  haad  * rw_locks. I use IPL_NONE for specifing IPL type for mutex.
     59   1.1.2.2  haad  * I will enter into mutex everytime I'm working with dm_dev_list.
     60   1.1.2.1  haad  */
     61   1.1.2.1  haad 
     62   1.1.2.1  haad /*
     63   1.1.2.9  haad  * Generic function used to lookup struct dm_dev. Calling with dm_dev_name
     64   1.1.2.9  haad  * and dm_dev_uuid NULL is allowed.
     65   1.1.2.1  haad  */
     66   1.1.2.1  haad struct dm_dev*
     67   1.1.2.9  haad dm_dev_lookup(const char *dm_dev_name, const char *dm_dev_uuid,
     68   1.1.2.9  haad  	int dm_dev_minor)
     69   1.1.2.9  haad {
     70   1.1.2.9  haad 	struct dm_dev *dmv;
     71   1.1.2.9  haad 
     72   1.1.2.9  haad 	dmv = NULL;
     73   1.1.2.9  haad 
     74   1.1.2.9  haad 	if (dm_dev_minor > 0)
     75   1.1.2.9  haad 		if ((dmv = dm_dev_lookup_minor(dm_dev_minor)) != NULL)
     76   1.1.2.9  haad 			return dmv;
     77   1.1.2.9  haad 
     78   1.1.2.9  haad 	if (dm_dev_name != NULL)
     79   1.1.2.9  haad 		if ((dmv = dm_dev_lookup_name(dm_dev_name)) != NULL)
     80   1.1.2.9  haad 			return dmv;
     81   1.1.2.9  haad 
     82   1.1.2.9  haad 	if (dm_dev_uuid != NULL)
     83   1.1.2.9  haad 		if ((dmv = dm_dev_lookup_name(dm_dev_uuid)) != NULL)
     84   1.1.2.9  haad 			return dmv;
     85   1.1.2.9  haad 
     86   1.1.2.9  haad 	return NULL;
     87   1.1.2.9  haad }
     88   1.1.2.9  haad 
     89   1.1.2.9  haad 
     90   1.1.2.9  haad /*
     91   1.1.2.9  haad  * Lookup device with its minor number.
     92   1.1.2.9  haad  */
     93   1.1.2.9  haad static struct dm_dev*
     94   1.1.2.1  haad dm_dev_lookup_minor(int dm_dev_minor)
     95   1.1.2.1  haad {
     96   1.1.2.1  haad 	struct dm_dev *dm_dev;
     97   1.1.2.1  haad 
     98   1.1.2.1  haad 	mutex_enter(&dm_dev_mutex);
     99   1.1.2.1  haad 
    100   1.1.2.2  haad 	TAILQ_FOREACH(dm_dev, &dm_dev_list, next_devlist){
    101   1.1.2.1  haad 		if (dm_dev_minor == dm_dev->minor){
    102   1.1.2.1  haad 			mutex_exit(&dm_dev_mutex);
    103   1.1.2.1  haad 			return dm_dev;
    104   1.1.2.1  haad 		}
    105   1.1.2.1  haad 	}
    106   1.1.2.1  haad 
    107   1.1.2.1  haad 	mutex_exit(&dm_dev_mutex);
    108   1.1.2.1  haad 
    109   1.1.2.1  haad 	return NULL;
    110   1.1.2.1  haad }
    111   1.1.2.1  haad 
    112   1.1.2.1  haad /*
    113   1.1.2.1  haad  * Lookup device with it's device name.
    114   1.1.2.1  haad  */
    115   1.1.2.9  haad static struct dm_dev*
    116   1.1.2.1  haad dm_dev_lookup_name(const char *dm_dev_name)
    117   1.1.2.1  haad {
    118   1.1.2.1  haad 	struct dm_dev *dm_dev;
    119   1.1.2.1  haad 	int dlen; int slen;
    120   1.1.2.1  haad 
    121   1.1.2.9  haad 	slen = strlen(dm_dev_name);
    122   1.1.2.9  haad 
    123   1.1.2.9  haad 	if (slen == 0)
    124   1.1.2.1  haad 		return NULL;
    125   1.1.2.1  haad 
    126   1.1.2.1  haad 	mutex_enter(&dm_dev_mutex);
    127   1.1.2.1  haad 
    128   1.1.2.2  haad 	TAILQ_FOREACH(dm_dev, &dm_dev_list, next_devlist){
    129   1.1.2.9  haad 
    130   1.1.2.1  haad 		dlen = strlen(dm_dev->name);
    131   1.1.2.9  haad 
    132   1.1.2.1  haad 		if(slen != dlen)
    133   1.1.2.1  haad 			continue;
    134   1.1.2.9  haad 
    135   1.1.2.2  haad 		if (strncmp(dm_dev_name, dm_dev->name, slen) == 0) {
    136   1.1.2.1  haad 			mutex_exit(&dm_dev_mutex);
    137   1.1.2.1  haad 			return dm_dev;
    138   1.1.2.1  haad 		}
    139   1.1.2.1  haad 	}
    140   1.1.2.1  haad 
    141   1.1.2.1  haad 	mutex_exit(&dm_dev_mutex);
    142   1.1.2.1  haad 
    143   1.1.2.1  haad 	return NULL;
    144   1.1.2.1  haad }
    145   1.1.2.1  haad 
    146   1.1.2.1  haad /*
    147   1.1.2.1  haad  * Lookup device with it's device uuid. Used mostly by LVM2tools.
    148   1.1.2.1  haad  */
    149   1.1.2.9  haad static struct dm_dev*
    150   1.1.2.1  haad dm_dev_lookup_uuid(const char *dm_dev_uuid)
    151   1.1.2.1  haad {
    152   1.1.2.1  haad 	struct dm_dev *dm_dev;
    153   1.1.2.6  haad 	size_t len;
    154   1.1.2.6  haad 
    155   1.1.2.6  haad 	len = 0;
    156   1.1.2.9  haad 
    157   1.1.2.9  haad 	len = strlen(dm_dev_uuid);
    158   1.1.2.6  haad 
    159   1.1.2.9  haad 	if (len == 0)
    160   1.1.2.1  haad 		return NULL;
    161   1.1.2.1  haad 
    162   1.1.2.1  haad 	mutex_enter(&dm_dev_mutex);
    163   1.1.2.1  haad 
    164   1.1.2.6  haad 	TAILQ_FOREACH(dm_dev, &dm_dev_list, next_devlist){
    165   1.1.2.6  haad 
    166   1.1.2.6  haad 		if (strlen(dm_dev->uuid) != len)
    167   1.1.2.9  haad 			continue;
    168   1.1.2.6  haad 
    169   1.1.2.9  haad 		if (strncmp(dm_dev_uuid, dm_dev->uuid, strlen(dm_dev->uuid)) == 0){
    170   1.1.2.9  haad 			mutex_exit(&dm_dev_mutex);
    171   1.1.2.9  haad 			return dm_dev;
    172   1.1.2.9  haad 		}
    173   1.1.2.6  haad 	}
    174   1.1.2.6  haad 		mutex_exit(&dm_dev_mutex);
    175   1.1.2.1  haad 
    176   1.1.2.1  haad 	return NULL;
    177   1.1.2.1  haad }
    178   1.1.2.1  haad 
    179   1.1.2.1  haad /*
    180   1.1.2.1  haad  * Insert new device to the global list of devices.
    181   1.1.2.1  haad  */
    182   1.1.2.1  haad int
    183   1.1.2.1  haad dm_dev_insert(struct dm_dev *dev)
    184   1.1.2.1  haad {
    185   1.1.2.1  haad 	struct dm_dev *dmt;
    186   1.1.2.1  haad 	int r;
    187   1.1.2.1  haad 
    188   1.1.2.1  haad 	dmt = NULL;
    189   1.1.2.1  haad 	r = 0;
    190   1.1.2.1  haad 
    191   1.1.2.6  haad 	if (((dmt = dm_dev_lookup_uuid(dev->uuid)) == NULL) &&
    192   1.1.2.6  haad 	    ((dmt = dm_dev_lookup_name(dev->name)) == NULL) &&
    193   1.1.2.6  haad 	    ((dmt = dm_dev_lookup_minor(dev->minor)) == NULL)){
    194   1.1.2.1  haad 
    195   1.1.2.1  haad 		mutex_enter(&dm_dev_mutex);
    196   1.1.2.1  haad 		TAILQ_INSERT_TAIL(&dm_dev_list, dev, next_devlist);
    197   1.1.2.1  haad 		mutex_exit(&dm_dev_mutex);
    198   1.1.2.1  haad 	} else
    199   1.1.2.1  haad 		r = EEXIST;
    200   1.1.2.1  haad 
    201   1.1.2.1  haad 	return r;
    202   1.1.2.1  haad }
    203   1.1.2.1  haad 
    204   1.1.2.1  haad 
    205   1.1.2.1  haad /*
    206   1.1.2.6  haad  * Remove device selected with dm_dev from global list of devices.
    207   1.1.2.1  haad  */
    208   1.1.2.1  haad int
    209   1.1.2.6  haad dm_dev_rem(struct dm_dev *dm_dev)
    210   1.1.2.6  haad {
    211   1.1.2.1  haad 	mutex_enter(&dm_dev_mutex);
    212   1.1.2.1  haad 
    213   1.1.2.2  haad 	TAILQ_REMOVE(&dm_dev_list, dm_dev, next_devlist);
    214   1.1.2.1  haad 
    215   1.1.2.1  haad 	mutex_exit(&dm_dev_mutex);
    216   1.1.2.1  haad 
    217   1.1.2.6  haad 	return 0;
    218   1.1.2.1  haad }
    219   1.1.2.1  haad 
    220   1.1.2.1  haad /*
    221   1.1.2.5  haad  * Destroy all devices created in device-mapper. Remove all tables
    222   1.1.2.5  haad  * free all allocated memmory.
    223   1.1.2.5  haad  */
    224   1.1.2.5  haad 
    225   1.1.2.5  haad int
    226   1.1.2.5  haad dm_dev_destroy(void)
    227   1.1.2.5  haad {
    228   1.1.2.5  haad 	struct dm_dev *dm_dev;
    229   1.1.2.5  haad 
    230   1.1.2.8  haad 	/* XXX should I get rw_lock here ? */
    231   1.1.2.5  haad 	mutex_enter(&dm_dev_mutex);
    232   1.1.2.5  haad 
    233   1.1.2.5  haad 	while (TAILQ_FIRST(&dm_dev_list) != NULL){
    234   1.1.2.5  haad 
    235   1.1.2.5  haad 		dm_dev = TAILQ_FIRST(&dm_dev_list);
    236   1.1.2.5  haad 
    237   1.1.2.5  haad 		TAILQ_REMOVE(&dm_dev_list, TAILQ_FIRST(&dm_dev_list),
    238  1.1.2.10  haad 		    next_devlist);
    239   1.1.2.5  haad 
    240  1.1.2.10  haad 		rw_enter(&dm_dev->dev_rwlock, RW_WRITER);
    241  1.1.2.10  haad 
    242   1.1.2.5  haad 		/* Destroy active table first.  */
    243   1.1.2.8  haad 		if (!SLIST_EMPTY(&dm_dev->tables[dm_dev->cur_active_table]))
    244   1.1.2.8  haad 			dm_table_destroy(&dm_dev->tables[dm_dev->cur_active_table]);
    245   1.1.2.5  haad 
    246   1.1.2.5  haad 		/* Destroy unactive table if exits, too. */
    247   1.1.2.5  haad 		if (!SLIST_EMPTY(&dm_dev->tables[1 - dm_dev->cur_active_table]))
    248   1.1.2.5  haad 			dm_table_destroy(&dm_dev->tables[1 - dm_dev->cur_active_table]);
    249  1.1.2.10  haad 
    250  1.1.2.10  haad 		rw_exit(&dm_dev->dev_rwlock);
    251  1.1.2.10  haad 
    252  1.1.2.10  haad 		rw_destroy(&dm_dev->dev_rwlock);
    253   1.1.2.5  haad 
    254   1.1.2.5  haad 		(void)kmem_free(dm_dev, sizeof(struct dm_dev));
    255   1.1.2.5  haad 	}
    256   1.1.2.5  haad 
    257   1.1.2.5  haad 	mutex_exit(&dm_dev_mutex);
    258   1.1.2.5  haad 
    259  1.1.2.10  haad 	mutex_destroy(&dm_dev_mutex);
    260  1.1.2.10  haad 
    261   1.1.2.5  haad 	return 0;
    262   1.1.2.5  haad }
    263   1.1.2.5  haad 
    264   1.1.2.5  haad /*
    265   1.1.2.1  haad  * Allocate new device entry.
    266   1.1.2.1  haad  */
    267   1.1.2.1  haad struct dm_dev*
    268   1.1.2.1  haad dm_dev_alloc()
    269  1.1.2.10  haad {
    270  1.1.2.10  haad 	struct dm_dev *dmv;
    271  1.1.2.10  haad 
    272  1.1.2.10  haad 	dmv = kmem_zalloc(sizeof(struct dm_dev), KM_NOSLEEP);
    273  1.1.2.10  haad 	dmv->dk_label = kmem_zalloc(sizeof(struct disklabel), KM_NOSLEEP);
    274  1.1.2.10  haad 
    275  1.1.2.10  haad 	return dmv;
    276   1.1.2.1  haad }
    277   1.1.2.1  haad 
    278   1.1.2.1  haad /*
    279   1.1.2.1  haad  * Freed device entry.
    280   1.1.2.1  haad  */
    281   1.1.2.1  haad int
    282   1.1.2.1  haad dm_dev_free(struct dm_dev *dmv)
    283   1.1.2.1  haad {
    284  1.1.2.10  haad 	if (dmv->dk_label != NULL)
    285  1.1.2.10  haad 		(void)kmem_free(dmv, sizeof(struct disklabel));
    286  1.1.2.10  haad 
    287   1.1.2.7  haad 	if (dmv != NULL)
    288   1.1.2.6  haad 		(void)kmem_free(dmv, sizeof(struct dm_dev));
    289   1.1.2.1  haad 
    290   1.1.2.1  haad 	return 0;
    291   1.1.2.1  haad }
    292   1.1.2.1  haad 
    293   1.1.2.1  haad 
    294   1.1.2.1  haad /*
    295   1.1.2.1  haad  * Return prop_array of dm_targer_list dictionaries.
    296   1.1.2.1  haad  */
    297   1.1.2.1  haad prop_array_t
    298   1.1.2.1  haad dm_dev_prop_list(void)
    299   1.1.2.1  haad {
    300   1.1.2.1  haad 	struct dm_dev *dmd;
    301   1.1.2.1  haad 
    302   1.1.2.1  haad 	int j;
    303   1.1.2.1  haad 
    304   1.1.2.1  haad 	prop_array_t dev_array;
    305   1.1.2.1  haad 	prop_dictionary_t dev_dict;
    306   1.1.2.1  haad 
    307   1.1.2.1  haad 	j =0;
    308   1.1.2.1  haad 
    309   1.1.2.1  haad 	dev_array = prop_array_create();
    310   1.1.2.1  haad 
    311   1.1.2.1  haad 	mutex_enter(&dm_dev_mutex);
    312   1.1.2.1  haad 
    313   1.1.2.2  haad 	TAILQ_FOREACH(dmd, &dm_dev_list,next_devlist) {
    314   1.1.2.1  haad 		dev_dict  = prop_dictionary_create();
    315   1.1.2.1  haad 
    316   1.1.2.2  haad 		prop_dictionary_set_cstring(dev_dict, DM_DEV_NAME, dmd->name);
    317   1.1.2.1  haad 
    318   1.1.2.2  haad 		prop_dictionary_set_uint32(dev_dict, DM_DEV_DEV, dmd->minor);
    319   1.1.2.1  haad 
    320   1.1.2.2  haad 		prop_array_set(dev_array, j, dev_dict);
    321   1.1.2.1  haad 
    322   1.1.2.1  haad 		prop_object_release(dev_dict);
    323   1.1.2.1  haad 
    324   1.1.2.1  haad 		j++;
    325   1.1.2.1  haad 	}
    326   1.1.2.1  haad 
    327   1.1.2.1  haad 	mutex_exit(&dm_dev_mutex);
    328   1.1.2.1  haad 
    329   1.1.2.1  haad 	return dev_array;
    330   1.1.2.1  haad }
    331   1.1.2.1  haad 
    332   1.1.2.1  haad /*
    333   1.1.2.7  haad  * Initialize global device mutex.
    334   1.1.2.1  haad  */
    335   1.1.2.1  haad int
    336   1.1.2.1  haad dm_dev_init()
    337   1.1.2.1  haad {
    338   1.1.2.7  haad 	TAILQ_INIT(&dm_dev_list); /* initialize global dev list */
    339   1.1.2.7  haad 
    340   1.1.2.2  haad 	mutex_init(&dm_dev_mutex, MUTEX_DEFAULT, IPL_NONE);
    341   1.1.2.1  haad 
    342   1.1.2.1  haad 	return 0;
    343   1.1.2.1  haad }
    344