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:
parent
57d5318d32
commit
352a99b95a
@ -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.
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
|
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),
|
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),
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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;
|
||||||
|
@ -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))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user