1
0
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:
Alasdair Kergon 2005-10-25 19:08:21 +00:00
parent 57d5318d32
commit 352a99b95a
11 changed files with 159 additions and 32 deletions

View File

@ -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.

View File

@ -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();

View File

@ -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

View File

@ -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,12 +2304,23 @@ int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv)
}
/* Only process nodes with uuid of "LVM-" plus VG id. */
switch(action) {
case DEACTIVATE:
if (!dm_deptree_deactivate_children(dnode, dlid, ID_LEN + 4)) {
stack;
goto out;
}
fs_del_lv(lv);
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;
}
r = 1;
@ -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;
}

View File

@ -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

View File

@ -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),

View File

@ -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;
}

View File

@ -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

View File

@ -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.
*/

View File

@ -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;

View File

@ -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))