mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
Use dm_is_dm_major instead of local copy.
Allow mapped devices to be used as PVs safely.
This commit is contained in:
parent
57d5318d32
commit
352a99b95a
@ -1,5 +1,8 @@
|
||||
Version 2.02.00 -
|
||||
===================================
|
||||
Add DEFS to make.tmpl.
|
||||
Use dm_is_dm_major instead of local copy.
|
||||
Allow mapped devices to be used as PVs.
|
||||
Move set_selinux_context into libdevmapper.
|
||||
Fix automatic text metadata buffer expansion (using macro).
|
||||
Cache formatted text metadata buffer between metadata area writes.
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "dev_manager.h"
|
||||
#include "str_list.h"
|
||||
#include "config.h"
|
||||
#include "filter.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <fcntl.h>
|
||||
@ -144,6 +145,12 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
|
||||
struct volume_group *vg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void activation_exit(void)
|
||||
{
|
||||
return;
|
||||
@ -790,6 +797,34 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Does PV use VG somewhere in its construction?
|
||||
* Returns 1 on failure.
|
||||
*/
|
||||
int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
|
||||
struct volume_group *vg)
|
||||
{
|
||||
struct dev_manager *dm;
|
||||
int r;
|
||||
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
if (!dm_is_dm_major(MAJOR(pv->dev->dev)))
|
||||
return 0;
|
||||
|
||||
if (!(dm = dev_manager_create(cmd, vg->name))) {
|
||||
stack;
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = dev_manager_device_uses_vg(dm, pv->dev, vg);
|
||||
|
||||
dev_manager_destroy(dm);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void activation_exit(void)
|
||||
{
|
||||
dev_manager_exit();
|
||||
|
@ -76,4 +76,10 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wa
|
||||
int lvs_in_vg_activated(struct volume_group *vg);
|
||||
int lvs_in_vg_opened(struct volume_group *vg);
|
||||
|
||||
/*
|
||||
* Returns 1 if PV has a dependency tree that uses anything in VG.
|
||||
*/
|
||||
int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
|
||||
struct volume_group *vg);
|
||||
|
||||
#endif
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "toolcontext.h"
|
||||
#include "targets.h"
|
||||
#include "config.h"
|
||||
#include "filter.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <dirent.h>
|
||||
@ -54,6 +55,7 @@
|
||||
*/
|
||||
|
||||
#define MAX_TARGET_PARAMSIZE 50000
|
||||
#define UUID_PREFIX "LVM-"
|
||||
|
||||
enum {
|
||||
ACTIVE = 0,
|
||||
@ -170,14 +172,14 @@ static char *_build_dlid(struct dm_pool *mem, const char *lvid, const char *laye
|
||||
if (!layer)
|
||||
layer = "";
|
||||
|
||||
len = 4 + strlen(lvid) + strlen(layer) + 2;
|
||||
len = sizeof(UUID_PREFIX) + sizeof(union lvid) + strlen(layer);
|
||||
|
||||
if (!(dlid = dm_pool_alloc(mem, len))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sprintf(dlid, "LVM-%s%s%s", lvid, (*layer) ? "-" : "", layer);
|
||||
sprintf(dlid, UUID_PREFIX "%s%s%s", lvid, (*layer) ? "-" : "", layer);
|
||||
|
||||
return dlid;
|
||||
}
|
||||
@ -2279,7 +2281,7 @@ fail:
|
||||
/*
|
||||
* Deactivate LV and all devices it references that nothing else has open.
|
||||
*/
|
||||
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv)
|
||||
static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, action_t action)
|
||||
{
|
||||
struct deptree *dtree;
|
||||
struct deptree_node *dnode;
|
||||
@ -2302,13 +2304,24 @@ int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv)
|
||||
}
|
||||
|
||||
/* Only process nodes with uuid of "LVM-" plus VG id. */
|
||||
if (!dm_deptree_deactivate_children(dnode, dlid, ID_LEN + 4)) {
|
||||
stack;
|
||||
switch(action) {
|
||||
case DEACTIVATE:
|
||||
if (!dm_deptree_deactivate_children(dnode, dlid, ID_LEN + 4)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case SUSPEND:
|
||||
if (!dm_deptree_suspend_children(dnode, dlid, ID_LEN + 4)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log_error("_tree_action: Action %u not supported.", action);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fs_del_lv(lv);
|
||||
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
@ -2317,3 +2330,56 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = _tree_action(dm, lv, DEACTIVATE);
|
||||
|
||||
fs_del_lv(lv);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Does device use VG somewhere in its construction?
|
||||
* Returns 1 if uncertain.
|
||||
*/
|
||||
int dev_manager_device_uses_vg(struct dev_manager *dm, struct device *dev,
|
||||
struct volume_group *vg)
|
||||
{
|
||||
struct deptree *dtree;
|
||||
struct deptree_node *dnode;
|
||||
char dlid[sizeof(UUID_PREFIX) + sizeof(struct id) - 1];
|
||||
int r = 1;
|
||||
|
||||
if (!(dtree = dm_deptree_create())) {
|
||||
log_error("partial deptree creation failed");
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!dm_deptree_add_dev(dtree, MAJOR(dev->dev), MINOR(dev->dev))) {
|
||||
log_error("Failed to add device %s (%" PRIu32 ":%" PRIu32") to deptree",
|
||||
dev_name(dev), (uint32_t) MAJOR(dev->dev), (uint32_t) MINOR(dev->dev));
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(dlid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1);
|
||||
memcpy(dlid + sizeof(UUID_PREFIX) - 1, &vg->id.uuid[0], sizeof(vg->id));
|
||||
|
||||
if (!(dnode = dm_deptree_find_node(dtree, 0, 0))) {
|
||||
log_error("Lost dependency tree root node");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dm_deptree_children_use_uuid(dnode, dlid, sizeof(UUID_PREFIX) + sizeof(vg->id) - 1)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = 0;
|
||||
|
||||
out:
|
||||
dm_deptree_free(dtree);
|
||||
return r;
|
||||
}
|
||||
|
@ -17,9 +17,11 @@
|
||||
#define _LVM_DEV_MANAGER_H
|
||||
|
||||
struct logical_volume;
|
||||
struct volume_group;
|
||||
struct cmd_context;
|
||||
struct dev_manager;
|
||||
struct dm_info;
|
||||
struct device;
|
||||
|
||||
/*
|
||||
* Constructor and destructor.
|
||||
@ -55,4 +57,7 @@ int dev_manager_lv_rmnodes(const struct logical_volume *lv);
|
||||
*/
|
||||
int dev_manager_execute(struct dev_manager *dm);
|
||||
|
||||
int dev_manager_device_uses_vg(struct dev_manager *dm, struct device *dev,
|
||||
struct volume_group *vg);
|
||||
|
||||
#endif
|
||||
|
8
lib/cache/lvmcache.c
vendored
8
lib/cache/lvmcache.c
vendored
@ -494,8 +494,8 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
pvid, dev_name(dev),
|
||||
dev_name(existing->dev));
|
||||
return NULL;
|
||||
} else if (is_dm_major(MAJOR(existing->dev->dev)) &&
|
||||
!is_dm_major(MAJOR(dev->dev))) {
|
||||
} else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
|
||||
!dm_is_dm_major(MAJOR(dev->dev))) {
|
||||
log_very_verbose("Ignoring duplicate PV %s on "
|
||||
"%s - using dm %s",
|
||||
pvid, dev_name(dev),
|
||||
@ -507,8 +507,8 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
"using md %s", pvid,
|
||||
dev_name(existing->dev),
|
||||
dev_name(dev));
|
||||
else if (!is_dm_major(MAJOR(existing->dev->dev)) &&
|
||||
is_dm_major(MAJOR(dev->dev)))
|
||||
else if (!dm_is_dm_major(MAJOR(existing->dev->dev)) &&
|
||||
dm_is_dm_major(MAJOR(dev->dev)))
|
||||
log_very_verbose("Duplicate PV %s on %s - "
|
||||
"using dm %s", pvid,
|
||||
dev_name(existing->dev),
|
||||
|
@ -28,7 +28,6 @@
|
||||
|
||||
#define NUMBER_OF_MAJORS 4096
|
||||
|
||||
/* FIXME Make this sparse */
|
||||
/* 0 means LVM won't use this major number. */
|
||||
static int _max_partitions_by_major[NUMBER_OF_MAJORS];
|
||||
|
||||
@ -38,18 +37,12 @@ typedef struct {
|
||||
} device_info_t;
|
||||
|
||||
static int _md_major = -1;
|
||||
static dm_bitset_t _dm_bitset;
|
||||
|
||||
int md_major(void)
|
||||
{
|
||||
return _md_major;
|
||||
}
|
||||
|
||||
int is_dm_major(int major)
|
||||
{
|
||||
return dm_bit(_dm_bitset, major) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Devices are only checked for partition tables if their minor number
|
||||
* is a multiple of the number corresponding to their type below
|
||||
@ -78,6 +71,7 @@ static const device_info_t device_info[] = {
|
||||
{"gnbd", 1}, /* Network block device */
|
||||
{"ramdisk", 1}, /* RAM disk */
|
||||
{"aoe", 16}, /* ATA over Ethernet */
|
||||
{"device-mapper", 1}, /* Other mapped devices */
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
@ -187,11 +181,6 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
|
||||
if (!strncmp("md", line + i, 2) && isspace(*(line + i + 2)))
|
||||
_md_major = line_maj;
|
||||
|
||||
/* Look for dm devices */
|
||||
if (!strncmp("device-mapper", line + i, 13) &&
|
||||
isspace(*(line + i + 13)))
|
||||
dm_bit_set(_dm_bitset, line_maj);
|
||||
|
||||
/* Go through the valid device names and if there is a
|
||||
match store max number of partitions */
|
||||
for (j = 0; device_info[j].name != NULL; j++) {
|
||||
@ -262,12 +251,6 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
|
||||
f->destroy = lvm_type_filter_destroy;
|
||||
f->private = NULL;
|
||||
|
||||
if (!(_dm_bitset = dm_bitset_create(NULL, NUMBER_OF_MAJORS))) {
|
||||
stack;
|
||||
dm_free(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_scan_proc_dev(proc, cn)) {
|
||||
stack;
|
||||
return NULL;
|
||||
@ -278,7 +261,6 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
|
||||
|
||||
void lvm_type_filter_destroy(struct dev_filter *f)
|
||||
{
|
||||
dm_bitset_destroy(_dm_bitset);
|
||||
dm_free(f);
|
||||
return;
|
||||
}
|
||||
|
@ -36,7 +36,6 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
|
||||
void lvm_type_filter_destroy(struct dev_filter *f);
|
||||
|
||||
int md_major(void);
|
||||
int is_dm_major(int major);
|
||||
int max_partitions(int major);
|
||||
|
||||
#endif
|
||||
|
@ -229,6 +229,9 @@ void set_lv_segment_area_lv(struct lv_segment *seg, uint32_t area_num,
|
||||
lv->status |= flags;
|
||||
}
|
||||
|
||||
static int _lv_segment_add_areas(struct logical_volume *lv,
|
||||
struct lv_segment *seg,
|
||||
uint32_t new_area_count) __attribute__ ((unused));
|
||||
/*
|
||||
* Prepare for adding parallel areas to an existing segment.
|
||||
*/
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "memlock.h"
|
||||
#include "str_list.h"
|
||||
#include "pv_alloc.h"
|
||||
#include "activate.h"
|
||||
|
||||
static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
|
||||
const char *pv_name)
|
||||
@ -58,6 +59,13 @@ static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ensure PV doesn't depend on another PV already in the VG */
|
||||
if (pv_uses_vg(fid->fmt->cmd, pv, vg)) {
|
||||
log_error("Physical volume %s might be constructed from same "
|
||||
"volume group %s", pv_name, vg->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(pv->vg_name = dm_pool_strdup(mem, vg->name))) {
|
||||
log_error("vg->name allocation failed for '%s'", pv_name);
|
||||
return 0;
|
||||
|
@ -20,6 +20,7 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
|
||||
{
|
||||
struct volume_group *vg_to, *vg_from;
|
||||
struct lv_list *lvl1, *lvl2;
|
||||
struct pv_list *pvl;
|
||||
int active;
|
||||
int consistent = 1;
|
||||
|
||||
@ -122,6 +123,25 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
|
||||
}
|
||||
}
|
||||
|
||||
/* Check no PVs are constructed from either VG */
|
||||
list_iterate_items(pvl, &vg_to->pvs) {
|
||||
if (pv_uses_vg(cmd, pvl->pv, vg_from)) {
|
||||
log_error("Physical volume %s might be constructed "
|
||||
"from same volume group %s.",
|
||||
dev_name(pvl->pv->dev), vg_from->name);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
list_iterate_items(pvl, &vg_from->pvs) {
|
||||
if (pv_uses_vg(cmd, pvl->pv, vg_to)) {
|
||||
log_error("Physical volume %s might be constructed "
|
||||
"from same volume group %s.",
|
||||
dev_name(pvl->pv->dev), vg_to->name);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME List arg: vg_show_with_pv_and_lv(vg_to); */
|
||||
|
||||
if (!archive(vg_from) || !archive(vg_to))
|
||||
|
Loading…
Reference in New Issue
Block a user