1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-18 10:04:20 +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 - 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. Move set_selinux_context into libdevmapper.
Fix automatic text metadata buffer expansion (using macro). Fix automatic text metadata buffer expansion (using macro).
Cache formatted text metadata buffer between metadata area writes. Cache formatted text metadata buffer between metadata area writes.

View File

@ -26,6 +26,7 @@
#include "dev_manager.h" #include "dev_manager.h"
#include "str_list.h" #include "str_list.h"
#include "config.h" #include "config.h"
#include "filter.h"
#include <limits.h> #include <limits.h>
#include <fcntl.h> #include <fcntl.h>
@ -144,6 +145,12 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
return 1; return 1;
} }
int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
struct volume_group *vg)
{
return 0;
}
void activation_exit(void) void activation_exit(void)
{ {
return; return;
@ -790,6 +797,34 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
return r; 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) void activation_exit(void)
{ {
dev_manager_exit(); 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_activated(struct volume_group *vg);
int lvs_in_vg_opened(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 #endif

View File

@ -24,6 +24,7 @@
#include "toolcontext.h" #include "toolcontext.h"
#include "targets.h" #include "targets.h"
#include "config.h" #include "config.h"
#include "filter.h"
#include <limits.h> #include <limits.h>
#include <dirent.h> #include <dirent.h>
@ -54,6 +55,7 @@
*/ */
#define MAX_TARGET_PARAMSIZE 50000 #define MAX_TARGET_PARAMSIZE 50000
#define UUID_PREFIX "LVM-"
enum { enum {
ACTIVE = 0, ACTIVE = 0,
@ -170,14 +172,14 @@ static char *_build_dlid(struct dm_pool *mem, const char *lvid, const char *laye
if (!layer) if (!layer)
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))) { if (!(dlid = dm_pool_alloc(mem, len))) {
stack; stack;
return NULL; return NULL;
} }
sprintf(dlid, "LVM-%s%s%s", lvid, (*layer) ? "-" : "", layer); sprintf(dlid, UUID_PREFIX "%s%s%s", lvid, (*layer) ? "-" : "", layer);
return dlid; return dlid;
} }
@ -2279,7 +2281,7 @@ fail:
/* /*
* Deactivate LV and all devices it references that nothing else has open. * 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 *dtree;
struct deptree_node *dnode; 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. */ /* Only process nodes with uuid of "LVM-" plus VG id. */
switch(action) {
case DEACTIVATE:
if (!dm_deptree_deactivate_children(dnode, dlid, ID_LEN + 4)) { if (!dm_deptree_deactivate_children(dnode, dlid, ID_LEN + 4)) {
stack; stack;
goto out; goto out;
} }
break;
fs_del_lv(lv); 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; r = 1;
@ -2317,3 +2330,56 @@ out:
return r; 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 #define _LVM_DEV_MANAGER_H
struct logical_volume; struct logical_volume;
struct volume_group;
struct cmd_context; struct cmd_context;
struct dev_manager; struct dev_manager;
struct dm_info; struct dm_info;
struct device;
/* /*
* Constructor and destructor. * 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_execute(struct dev_manager *dm);
int dev_manager_device_uses_vg(struct dev_manager *dm, struct device *dev,
struct volume_group *vg);
#endif #endif

View File

@ -494,8 +494,8 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
pvid, dev_name(dev), pvid, dev_name(dev),
dev_name(existing->dev)); dev_name(existing->dev));
return NULL; return NULL;
} else if (is_dm_major(MAJOR(existing->dev->dev)) && } else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
!is_dm_major(MAJOR(dev->dev))) { !dm_is_dm_major(MAJOR(dev->dev))) {
log_very_verbose("Ignoring duplicate PV %s on " log_very_verbose("Ignoring duplicate PV %s on "
"%s - using dm %s", "%s - using dm %s",
pvid, dev_name(dev), pvid, dev_name(dev),
@ -507,8 +507,8 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
"using md %s", pvid, "using md %s", pvid,
dev_name(existing->dev), dev_name(existing->dev),
dev_name(dev)); dev_name(dev));
else if (!is_dm_major(MAJOR(existing->dev->dev)) && else if (!dm_is_dm_major(MAJOR(existing->dev->dev)) &&
is_dm_major(MAJOR(dev->dev))) dm_is_dm_major(MAJOR(dev->dev)))
log_very_verbose("Duplicate PV %s on %s - " log_very_verbose("Duplicate PV %s on %s - "
"using dm %s", pvid, "using dm %s", pvid,
dev_name(existing->dev), dev_name(existing->dev),

View File

@ -28,7 +28,6 @@
#define NUMBER_OF_MAJORS 4096 #define NUMBER_OF_MAJORS 4096
/* FIXME Make this sparse */
/* 0 means LVM won't use this major number. */ /* 0 means LVM won't use this major number. */
static int _max_partitions_by_major[NUMBER_OF_MAJORS]; static int _max_partitions_by_major[NUMBER_OF_MAJORS];
@ -38,18 +37,12 @@ typedef struct {
} device_info_t; } device_info_t;
static int _md_major = -1; static int _md_major = -1;
static dm_bitset_t _dm_bitset;
int md_major(void) int md_major(void)
{ {
return _md_major; 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 * Devices are only checked for partition tables if their minor number
* is a multiple of the number corresponding to their type below * 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 */ {"gnbd", 1}, /* Network block device */
{"ramdisk", 1}, /* RAM disk */ {"ramdisk", 1}, /* RAM disk */
{"aoe", 16}, /* ATA over Ethernet */ {"aoe", 16}, /* ATA over Ethernet */
{"device-mapper", 1}, /* Other mapped devices */
{NULL, 0} {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))) if (!strncmp("md", line + i, 2) && isspace(*(line + i + 2)))
_md_major = line_maj; _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 /* Go through the valid device names and if there is a
match store max number of partitions */ match store max number of partitions */
for (j = 0; device_info[j].name != NULL; j++) { 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->destroy = lvm_type_filter_destroy;
f->private = NULL; 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)) { if (!_scan_proc_dev(proc, cn)) {
stack; stack;
return NULL; 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) void lvm_type_filter_destroy(struct dev_filter *f)
{ {
dm_bitset_destroy(_dm_bitset);
dm_free(f); dm_free(f);
return; 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); void lvm_type_filter_destroy(struct dev_filter *f);
int md_major(void); int md_major(void);
int is_dm_major(int major);
int max_partitions(int major); int max_partitions(int major);
#endif #endif

View File

@ -229,6 +229,9 @@ void set_lv_segment_area_lv(struct lv_segment *seg, uint32_t area_num,
lv->status |= flags; 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. * Prepare for adding parallel areas to an existing segment.
*/ */

View File

@ -22,6 +22,7 @@
#include "memlock.h" #include "memlock.h"
#include "str_list.h" #include "str_list.h"
#include "pv_alloc.h" #include "pv_alloc.h"
#include "activate.h"
static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg, static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
const char *pv_name) const char *pv_name)
@ -58,6 +59,13 @@ static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
return 0; 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))) { if (!(pv->vg_name = dm_pool_strdup(mem, vg->name))) {
log_error("vg->name allocation failed for '%s'", pv_name); log_error("vg->name allocation failed for '%s'", pv_name);
return 0; 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 volume_group *vg_to, *vg_from;
struct lv_list *lvl1, *lvl2; struct lv_list *lvl1, *lvl2;
struct pv_list *pvl;
int active; int active;
int consistent = 1; 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); */ /* FIXME List arg: vg_show_with_pv_and_lv(vg_to); */
if (!archive(vg_from) || !archive(vg_to)) if (!archive(vg_from) || !archive(vg_to))