diff options
author | Peter Rajnoha <prajnoha@redhat.com> | 2014-12-12 12:55:41 +0100 |
---|---|---|
committer | Peter Rajnoha <prajnoha@redhat.com> | 2015-01-30 13:01:12 +0100 |
commit | fbfde21e7cdc770f0a1189d40f983aa046d605bb (patch) | |
tree | 23e56415a1ab352d7f8e3cab91a07ce3671892ac | |
parent | 578b236a19fab565a4416b17cbc26d53a72b66db (diff) | |
download | lvm2-fbfde21e7cdc770f0a1189d40f983aa046d605bb.tar.gz |
device: add infrastructure to support external device info
-rw-r--r-- | lib/Makefile.in | 1 | ||||
-rw-r--r-- | lib/device/dev-cache.c | 3 | ||||
-rw-r--r-- | lib/device/dev-ext.c | 164 | ||||
-rw-r--r-- | lib/device/device.h | 27 |
4 files changed, 195 insertions, 0 deletions
diff --git a/lib/Makefile.in b/lib/Makefile.in index bad5d8cd3..99cc0fe39 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -56,6 +56,7 @@ SOURCES =\ datastruct/btree.c \ datastruct/str_list.c \ device/dev-cache.c \ + device/dev-ext.c \ device/dev-io.c \ device/dev-md.c \ device/dev-swap.c \ diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c index ba4ee5462..7ad9fb804 100644 --- a/lib/device/dev-cache.c +++ b/lib/device/dev-cache.c @@ -64,6 +64,9 @@ static void _dev_init(struct device *dev, int max_error_count) dev->read_ahead = -1; dev->max_error_count = max_error_count; + dev->ext.enabled = 0; + dev->ext.src = DEV_EXT_NONE; + dm_list_init(&dev->aliases); dm_list_init(&dev->open_list); } diff --git a/lib/device/dev-ext.c b/lib/device/dev-ext.c new file mode 100644 index 000000000..8f2024e92 --- /dev/null +++ b/lib/device/dev-ext.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. All rights reserved. + * + * This file is part of LVM2. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU Lesser General Public License v.2.1. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "lib.h" +#include "device.h" + +#ifdef UDEV_SYNC_SUPPORT +#include <libudev.h> +#endif + +struct ext_registry_item { + const char *name; + struct dev_ext *(* dev_ext_get) (struct device *dev); + int (*dev_ext_release) (struct device *dev); +}; + +#define EXT_REGISTER(id,name) [id] = { #name, &_dev_ext_get_ ## name, &_dev_ext_release_ ## name } + +/* + * DEV_EXT_NONE + */ +static struct dev_ext *_dev_ext_get_none(struct device *dev) +{ + dev->ext.handle = NULL; + return &dev->ext; +} + +static int _dev_ext_release_none(struct device *dev) +{ + dev->ext.handle = NULL; + return 1; +} + +/* + * DEV_EXT_UDEV + */ +static struct dev_ext *_dev_ext_get_udev(struct device *dev) +{ +#ifdef UDEV_SYNC_SUPPORT + struct udev *udev; + struct udev_device *udev_device; + + if (dev->ext.handle) + return &dev->ext; + + if (!(udev = udev_get_library_context())) + return_NULL; + + if (!(udev_device = udev_device_new_from_devnum(udev, 'b', dev->dev))) + return_NULL; + + dev->ext.handle = (void *) udev_device; + return &dev->ext; +#else + return NULL; +#endif +} + +static int _dev_ext_release_udev(struct device *dev) +{ +#ifdef UDEV_SYNC_SUPPORT + if (!dev->ext.handle) + return 1; + + /* udev_device_unref can't fail - it has no return value */ + udev_device_unref((struct udev_device *) dev->ext.handle); + dev->ext.handle = NULL; + return 1; +#else + return 0; +#endif +} + +static struct ext_registry_item _ext_registry[DEV_EXT_NUM] = { + EXT_REGISTER(DEV_EXT_NONE, none), + EXT_REGISTER(DEV_EXT_UDEV, udev) +}; + +const char *dev_ext_name(struct device *dev) +{ + return _ext_registry[dev->ext.src].name; +} + +static const char *_ext_attached_msg = "External handle attached to device"; + +struct dev_ext *dev_ext_get(struct device *dev) +{ + struct dev_ext *ext; + void *handle_ptr; + + handle_ptr = dev->ext.handle; + + if (!(ext = _ext_registry[dev->ext.src].dev_ext_get(dev))) + log_error("Failed to get external handle for device %s [%s].", + dev_name(dev), dev_ext_name(dev)); + else if (handle_ptr != dev->ext.handle) + log_debug_devs("%s %s [%s:%p]", _ext_attached_msg, dev_name(dev), + dev_ext_name(dev), dev->ext.handle); + + return ext; +} + +int dev_ext_release(struct device *dev) +{ + int r; + void *handle_ptr; + + if (!dev->ext.enabled || + !dev->ext.handle) + return 1; + + handle_ptr = dev->ext.handle; + + if (!(r = _ext_registry[dev->ext.src].dev_ext_release(dev))) + log_error("Failed to release external handle for device %s [%s:%p].", + dev_name(dev), dev_ext_name(dev), dev->ext.handle); + else + log_debug_devs("External handle detached from device %s [%s:%p]", + dev_name(dev), dev_ext_name(dev), handle_ptr); + + return r; +} + +int dev_ext_enable(struct device *dev, dev_ext_t src) +{ + if (dev->ext.enabled && (dev->ext.src != src) && !dev_ext_release(dev)) { + log_error("Failed to enable external handle for device %s [%s].", + dev_name(dev), _ext_registry[src].name); + return 0; + } + + dev->ext.src = src; + dev->ext.enabled = 1; + + return 1; +} + +int dev_ext_disable(struct device *dev) +{ + if (!dev->ext.enabled) + return 1; + + if (!dev_ext_release(dev)) { + log_error("Failed to disable external handle for device %s [%s].", + dev_name(dev), dev_ext_name(dev)); + return 0; + } + + dev->ext.enabled = 0; + dev->ext.src = DEV_EXT_NONE; + + return 1; +} diff --git a/lib/device/device.h b/lib/device/device.h index c916a4bdb..0d38f96b7 100644 --- a/lib/device/device.h +++ b/lib/device/device.h @@ -29,6 +29,23 @@ #define DEV_O_DIRECT_TESTED 0x00000040 /* DEV_O_DIRECT is reliable */ /* + * Support for external device info. + * Any new external device info source needs to be + * registered using EXT_REGISTER macro in dev-ext.c. + */ +typedef enum { + DEV_EXT_NONE, + DEV_EXT_UDEV, + DEV_EXT_NUM +} dev_ext_t; + +struct dev_ext { + int enabled; + dev_ext_t src; + void *handle; +}; + +/* * All devices in LVM will be represented by one of these. * pointer comparisons are valid. */ @@ -47,6 +64,7 @@ struct device { uint32_t flags; uint64_t end; struct dm_list open_list; + struct dev_ext ext; char pvid[ID_LEN + 1]; char _padding[7]; @@ -64,6 +82,15 @@ struct device_area { }; /* + * Support for external device info. + */ +const char *dev_ext_name(struct device *dev); +int dev_ext_enable(struct device *dev, dev_ext_t src); +int dev_ext_disable(struct device *dev); +struct dev_ext *dev_ext_get(struct device *dev); +int dev_ext_release(struct device *dev); + +/* * All io should use these routines. */ int dev_get_block_size(struct device *dev, unsigned int *phys_block_size, unsigned int *block_size); |