mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
device: add infrastructure to support external device info
This commit is contained in:
parent
578b236a19
commit
fbfde21e7c
@ -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 \
|
||||
|
@ -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);
|
||||
}
|
||||
|
164
lib/device/dev-ext.c
Normal file
164
lib/device/dev-ext.c
Normal file
@ -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;
|
||||
}
|
@ -28,6 +28,23 @@
|
||||
#define DEV_O_DIRECT 0x00000020 /* Use O_DIRECT */
|
||||
#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];
|
||||
@ -63,6 +81,15 @@ struct device_area {
|
||||
uint64_t size; /* Bytes */
|
||||
};
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user