mirror of
git://sourceware.org/git/lvm2.git
synced 2026-02-03 08:32:44 +03:00
Compare commits
19 Commits
dm_v1_02_0
...
v2_02_06
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59db4b50cd | ||
|
|
bdae38765d | ||
|
|
66d3ceeb61 | ||
|
|
445dd17db3 | ||
|
|
cff78a2577 | ||
|
|
6a09e64195 | ||
|
|
22eabe5eab | ||
|
|
b69ba36c2d | ||
|
|
5240aad22b | ||
|
|
2897eb3cb3 | ||
|
|
d3f2f00c25 | ||
|
|
bacfb913a0 | ||
|
|
c99d0236a0 | ||
|
|
aac2b655f7 | ||
|
|
126c41e73a | ||
|
|
359ee54f0d | ||
|
|
28ab560907 | ||
|
|
ead252fee4 | ||
|
|
abf67914c4 |
18
WHATS_NEW
18
WHATS_NEW
@@ -1,5 +1,19 @@
|
||||
Version 2.02.06 -
|
||||
=================================
|
||||
Version 2.02.06 - 12th May 2006
|
||||
===============================
|
||||
Propagate --monitor around cluster.
|
||||
Add --monitor to vgcreate and lvcreate to control dmeventd registration.
|
||||
Filter LCK_NONBLOCK in clvmd lock_vg.
|
||||
Add --nosync to lvcreate with LV flag NOTSYNCED.
|
||||
Use mirror's uuid for a core log.
|
||||
Add mirror log fault-handling policy.
|
||||
Improve mirror warning messages and tidy dmeventd syslog output.
|
||||
Propagate nosync flag around cluster.
|
||||
Allow vgreduce to handle mirror log failures.
|
||||
Add --corelog to lvcreate and lvconvert.
|
||||
Create a log header for replacement in-sync mirror log.
|
||||
Use set_lv() and dev_set() to wipe sections of devices.
|
||||
Add mirror_in_sync() flag to avoid unnecessary resync on activation.
|
||||
Add mirror_library description to example.conf.
|
||||
Fix uuid_from_num() buffer overrun.
|
||||
Make SIZE_SHORT the default for display_size().
|
||||
Fix some memory leaks in error paths found by coverity.
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
Version 1.02.07 - 11 May 2006
|
||||
=============================
|
||||
Add DM_CORELOG flag to dm_tree_node_add_mirror_target().
|
||||
Avoid a dmeventd compiler warning.
|
||||
|
||||
Version 1.02.06 - 10 May 2006
|
||||
=============================
|
||||
Move DEFS into configure.h.
|
||||
|
||||
@@ -180,7 +180,7 @@ static int lock_vg(struct local_client *client)
|
||||
}
|
||||
else {
|
||||
|
||||
status = sync_lock(lockname, (int)lock_cmd, (int)lock_flags, &lkid);
|
||||
status = sync_lock(lockname, (int)lock_cmd, (lock_flags & LCK_NONBLOCK) ? LKF_NOQUEUE : 0, &lkid);
|
||||
if (status)
|
||||
status = errno;
|
||||
else
|
||||
|
||||
@@ -306,6 +306,12 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
if (lock_flags & LCK_PARTIAL_MODE)
|
||||
init_partial(1);
|
||||
|
||||
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
|
||||
init_mirror_in_sync(1);
|
||||
|
||||
if (!(lock_flags & LCK_DMEVENTD_MONITOR))
|
||||
init_dmeventd_register(0);
|
||||
|
||||
switch (command) {
|
||||
case LCK_LV_EXCLUSIVE:
|
||||
status = do_activate_lv(resource, lock_flags, LKM_EXMODE);
|
||||
@@ -337,6 +343,12 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
if (lock_flags & LCK_PARTIAL_MODE)
|
||||
init_partial(0);
|
||||
|
||||
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
|
||||
init_mirror_in_sync(0);
|
||||
|
||||
if (!(lock_flags & LCK_DMEVENTD_REGISTER_MODE))
|
||||
init_dmeventd_register(DEFAULT_DMEVENTD_MONITOR);
|
||||
|
||||
/* clean the pool for another command */
|
||||
dm_pool_empty(cmd->mem);
|
||||
|
||||
|
||||
@@ -1213,14 +1213,14 @@ static void sig_alarm(int signum)
|
||||
/* Init thread signal handling. */
|
||||
static void init_thread_signals(void)
|
||||
{
|
||||
sigset_t sigset;
|
||||
sigset_t my_sigset;
|
||||
struct sigaction act;
|
||||
|
||||
memset(&act, 0, sizeof(act));
|
||||
act.sa_handler = sig_alarm;
|
||||
sigaction(SIGALRM, &act, NULL);
|
||||
sigfillset(&sigset);
|
||||
pthread_sigmask(SIG_BLOCK, &sigset, NULL);
|
||||
sigfillset(&my_sigset);
|
||||
pthread_sigmask(SIG_BLOCK, &my_sigset, NULL);
|
||||
}
|
||||
|
||||
static int daemonize(void)
|
||||
|
||||
@@ -99,10 +99,13 @@ static int _get_mirror_event(char *params)
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static void _temporary_log_fn(int level, const char *file, int line, const char *format)
|
||||
static void _temporary_log_fn(int level, const char *file,
|
||||
int line, const char *format)
|
||||
{
|
||||
return;
|
||||
syslog(LOG_DEBUG, "%s", format);
|
||||
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
|
||||
syslog(LOG_CRIT, "%s", format);
|
||||
else
|
||||
syslog(LOG_DEBUG, "%s", format);
|
||||
}
|
||||
|
||||
static int _remove_failed_devices(const char *device)
|
||||
@@ -205,7 +208,7 @@ void process_event(const char *device, enum dm_event_type event)
|
||||
|
||||
int register_device(const char *device)
|
||||
{
|
||||
syslog(LOG_INFO, "Monitoring %s for events\n", device);
|
||||
syslog(LOG_INFO, "Monitoring mirror device, %s for events\n", device);
|
||||
|
||||
/*
|
||||
* Need some space for allocations. 1024 should be more
|
||||
@@ -224,8 +227,6 @@ int register_device(const char *device)
|
||||
|
||||
int unregister_device(const char *device)
|
||||
{
|
||||
syslog(LOG_INFO, "Stopped monitoring %s for events\n", device);
|
||||
|
||||
if (!(--register_count)) {
|
||||
dm_pool_destroy(mem_pool);
|
||||
mem_pool = NULL;
|
||||
|
||||
@@ -99,10 +99,13 @@ static int _get_mirror_event(char *params)
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static void _temporary_log_fn(int level, const char *file, int line, const char *format)
|
||||
static void _temporary_log_fn(int level, const char *file,
|
||||
int line, const char *format)
|
||||
{
|
||||
return;
|
||||
syslog(LOG_DEBUG, "%s", format);
|
||||
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
|
||||
syslog(LOG_CRIT, "%s", format);
|
||||
else
|
||||
syslog(LOG_DEBUG, "%s", format);
|
||||
}
|
||||
|
||||
static int _remove_failed_devices(const char *device)
|
||||
@@ -205,7 +208,7 @@ void process_event(const char *device, enum dm_event_type event)
|
||||
|
||||
int register_device(const char *device)
|
||||
{
|
||||
syslog(LOG_INFO, "Monitoring %s for events\n", device);
|
||||
syslog(LOG_INFO, "Monitoring mirror device, %s for events\n", device);
|
||||
|
||||
/*
|
||||
* Need some space for allocations. 1024 should be more
|
||||
@@ -224,8 +227,6 @@ int register_device(const char *device)
|
||||
|
||||
int unregister_device(const char *device)
|
||||
{
|
||||
syslog(LOG_INFO, "Stopped monitoring %s for events\n", device);
|
||||
|
||||
if (!(--register_count)) {
|
||||
dm_pool_destroy(mem_pool);
|
||||
mem_pool = NULL;
|
||||
|
||||
@@ -232,9 +232,6 @@ activation {
|
||||
# target or make it return zeros.
|
||||
missing_stripe_filler = "/dev/ioerror"
|
||||
|
||||
# Size (in KB) of each copy operation when mirroring
|
||||
mirror_region_size = 512
|
||||
|
||||
# How much stack (in KB) to reserve for use while devices suspended
|
||||
reserved_stack = 256
|
||||
|
||||
@@ -251,6 +248,54 @@ activation {
|
||||
# "@*" matches if any tag defined on the host is also set in the LV or VG
|
||||
#
|
||||
# volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
|
||||
|
||||
# Size (in KB) of each copy operation when mirroring
|
||||
mirror_region_size = 512
|
||||
|
||||
# 'mirror_image_fault_policy' and 'mirror_log_fault_policy' define
|
||||
# how a device failure affecting a mirror is handled.
|
||||
# A mirror is composed of mirror images (copies) and a log.
|
||||
# A disk log ensures that a mirror does not need to be re-synced
|
||||
# (all copies made the same) every time a machine reboots or crashes.
|
||||
#
|
||||
# In the event of a failure, the specified policy will be used to
|
||||
# determine what happens:
|
||||
#
|
||||
# "remove" - Simply remove the faulty device and run without it. If
|
||||
# the log device fails, the mirror would convert to using
|
||||
# an in-memory log. This means the mirror will not
|
||||
# remember its sync status across crashes/reboots and
|
||||
# the entire mirror will be re-synced. If a
|
||||
# mirror image fails, the mirror will convert to a
|
||||
# non-mirrored device if there is only one remaining good
|
||||
# copy.
|
||||
#
|
||||
# "allocate" - Remove the faulty device and try to allocate space on
|
||||
# a new device to be a replacement for the failed device.
|
||||
# Using this policy for the log is fast and maintains the
|
||||
# ability to remember sync state through crashes/reboots.
|
||||
# Using this policy for a mirror device is slow, as it
|
||||
# requires the mirror to resynchronize the devices, but it
|
||||
# will preserve the mirror characteristic of the device.
|
||||
# This policy acts like "remove" if no suitable device and
|
||||
# space can be allocated for the replacement.
|
||||
# Currently this is not implemented properly and behaves
|
||||
# similarly to:
|
||||
#
|
||||
# "allocate_anywhere" - Operates like "allocate", but it does not
|
||||
# require that the new space being allocated be on a
|
||||
# device is not part of the mirror. For a log device
|
||||
# failure, this could mean that the log is allocated on
|
||||
# the same device as a mirror device. For a mirror
|
||||
# device, this could mean that the mirror device is
|
||||
# allocated on the same device as another mirror device.
|
||||
# This policy would not be wise for mirror devices
|
||||
# because it would break the redundant nature of the
|
||||
# mirror. This policy acts like "remove" if no suitable
|
||||
# device and space can be allocated for the replacement.
|
||||
|
||||
mirror_log_fault_policy = "allocate"
|
||||
mirror_device_fault_policy = "remove"
|
||||
}
|
||||
|
||||
|
||||
@@ -291,7 +336,13 @@ activation {
|
||||
|
||||
# Event daemon
|
||||
#
|
||||
#dmeventd {
|
||||
# dmeventd {
|
||||
# mirror_library is the library used when monitoring a mirror device.
|
||||
#
|
||||
# "libdevmapper-event-lvm2mirror.so" attempts to recover from failures.
|
||||
# It removes failed devices from a volume group and reconfigures a
|
||||
# mirror as necessary.
|
||||
#
|
||||
# mirror_library = "libdevmapper-event-lvm2mirror.so"
|
||||
#}
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
|
||||
}
|
||||
|
||||
int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
|
||||
struct volume_group *vg)
|
||||
struct volume_group *vg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -574,15 +574,31 @@ int lvs_in_vg_opened(struct volume_group *vg)
|
||||
return count;
|
||||
}
|
||||
|
||||
static int _register_dev_for_events(struct cmd_context *cmd,
|
||||
struct logical_volume *lv, int do_reg)
|
||||
/*
|
||||
* register_dev_for_events
|
||||
*
|
||||
* This function uses proper error codes (but breaks convention)
|
||||
* to return:
|
||||
* -1 on error
|
||||
* 0 if the lv's targets don't do event [un]registration
|
||||
* 0 if the lv is already [un]registered -- FIXME: not implemented
|
||||
* 1 if the lv had a segment which was [un]registered
|
||||
*
|
||||
* Returns: -1 on error
|
||||
*/
|
||||
int register_dev_for_events(struct cmd_context *cmd,
|
||||
struct logical_volume *lv, int do_reg)
|
||||
{
|
||||
#ifdef DMEVENTD
|
||||
int r = 0;
|
||||
struct list *tmp;
|
||||
struct lv_segment *seg;
|
||||
int (*reg) (struct dm_pool *mem, struct lv_segment *,
|
||||
struct config_tree *cft, int events);
|
||||
|
||||
if (do_reg && !dmeventd_register_mode())
|
||||
return 1;
|
||||
|
||||
list_iterate(tmp, &lv->segments) {
|
||||
seg = list_item(tmp, struct lv_segment);
|
||||
|
||||
@@ -595,17 +611,21 @@ static int _register_dev_for_events(struct cmd_context *cmd,
|
||||
reg = seg->segtype->ops->target_unregister_events;
|
||||
|
||||
if (!reg)
|
||||
return_0;
|
||||
continue;
|
||||
|
||||
/* FIXME specify events */
|
||||
/* FIXME specify events */
|
||||
if (!reg(cmd->mem, seg, cmd->cft, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
return r;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
@@ -643,7 +663,7 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
}
|
||||
}
|
||||
|
||||
if (!_register_dev_for_events(cmd, lv, 0))
|
||||
if (register_dev_for_events(cmd, lv, 0) != 1)
|
||||
/* FIXME Consider aborting here */
|
||||
stack;
|
||||
|
||||
@@ -697,7 +717,7 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
|
||||
memlock_dec();
|
||||
fs_unlock();
|
||||
|
||||
if (!_register_dev_for_events(cmd, lv, 1))
|
||||
if (register_dev_for_events(cmd, lv, 1) != 1)
|
||||
stack;
|
||||
|
||||
return 1;
|
||||
@@ -743,7 +763,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_register_dev_for_events(cmd, lv, 0))
|
||||
if (register_dev_for_events(cmd, lv, 0) != 1)
|
||||
stack;
|
||||
|
||||
memlock_inc();
|
||||
@@ -816,7 +836,7 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
|
||||
memlock_dec();
|
||||
fs_unlock();
|
||||
|
||||
if (!_register_dev_for_events(cmd, lv, 1))
|
||||
if (!register_dev_for_events(cmd, lv, 1) != 1)
|
||||
stack;
|
||||
|
||||
return r;
|
||||
@@ -862,28 +882,16 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
|
||||
* 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)
|
||||
int pv_uses_vg(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;
|
||||
return dev_manager_device_uses_vg(pv->dev, vg);
|
||||
}
|
||||
|
||||
void activation_exit(void)
|
||||
|
||||
@@ -80,10 +80,14 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
int lvs_in_vg_activated(struct volume_group *vg);
|
||||
int lvs_in_vg_opened(struct volume_group *vg);
|
||||
|
||||
|
||||
int register_dev_for_events(struct cmd_context *cmd,
|
||||
struct logical_volume *lv, int do_reg);
|
||||
|
||||
/*
|
||||
* 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,
|
||||
int pv_uses_vg(struct physical_volume *pv,
|
||||
struct volume_group *vg);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -679,7 +679,7 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
(seg_type(seg, s) == AREA_LV && !seg_lv(seg, s)))
|
||||
dm_tree_node_add_target_area(node,
|
||||
dm->stripe_filler,
|
||||
NULL, 0);
|
||||
NULL, UINT64_C(0));
|
||||
else if (seg_type(seg, s) == AREA_PV)
|
||||
dm_tree_node_add_target_area(node,
|
||||
dev_name(seg_dev(seg, s)),
|
||||
@@ -704,7 +704,6 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
}
|
||||
|
||||
static int _add_origin_target_to_dtree(struct dev_manager *dm,
|
||||
struct dm_tree *dtree,
|
||||
struct dm_tree_node *dnode,
|
||||
struct logical_volume *lv)
|
||||
{
|
||||
@@ -720,7 +719,6 @@ static int _add_origin_target_to_dtree(struct dev_manager *dm,
|
||||
}
|
||||
|
||||
static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
|
||||
struct dm_tree *dtree,
|
||||
struct dm_tree_node *dnode,
|
||||
struct logical_volume *lv)
|
||||
{
|
||||
@@ -749,7 +747,6 @@ static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
|
||||
}
|
||||
|
||||
static int _add_target_to_dtree(struct dev_manager *dm,
|
||||
struct dm_tree *dtree,
|
||||
struct dm_tree_node *dnode,
|
||||
struct lv_segment *seg)
|
||||
{
|
||||
@@ -814,12 +811,12 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
|
||||
|
||||
/* Now we've added its dependencies, we can add the target itself */
|
||||
if (lv_is_origin(seg->lv) && !layer) {
|
||||
if (!_add_origin_target_to_dtree(dm, dtree, dnode, seg->lv))
|
||||
if (!_add_origin_target_to_dtree(dm, dnode, seg->lv))
|
||||
return_0;
|
||||
} else if (lv_is_cow(seg->lv) && !layer) {
|
||||
if (!_add_snapshot_target_to_dtree(dm, dtree, dnode, seg->lv))
|
||||
if (!_add_snapshot_target_to_dtree(dm, dnode, seg->lv))
|
||||
return_0;
|
||||
} else if (!_add_target_to_dtree(dm, dtree, dnode, seg))
|
||||
} else if (!_add_target_to_dtree(dm, dnode, seg))
|
||||
return_0;
|
||||
|
||||
if (lv_is_origin(seg->lv) && !layer)
|
||||
@@ -864,10 +861,10 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
* Major/minor settings only apply to the visible layer.
|
||||
*/
|
||||
if (!(dnode = dm_tree_add_new_dev(dtree, name, dlid,
|
||||
layer ? lv->major : 0,
|
||||
layer ? lv->minor : 0,
|
||||
layer ? (uint32_t) lv->major : UINT32_C(0),
|
||||
layer ? (uint32_t) lv->minor : UINT32_C(0),
|
||||
_read_only_lv(lv),
|
||||
lv->vg->status & PRECOMMITTED,
|
||||
(lv->vg->status & PRECOMMITTED) ? 1 : 0,
|
||||
lvlayer)))
|
||||
return_0;
|
||||
|
||||
@@ -921,7 +918,7 @@ static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _clean_tree(struct dev_manager *dm, struct logical_volume *lv, struct dm_tree_node *root)
|
||||
static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root)
|
||||
{
|
||||
void *handle = NULL;
|
||||
struct dm_tree_node *child;
|
||||
@@ -973,7 +970,7 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, actio
|
||||
switch(action) {
|
||||
case CLEAN:
|
||||
/* Deactivate any unused non-toplevel nodes */
|
||||
if (!_clean_tree(dm, lv, root))
|
||||
if (!_clean_tree(dm, root))
|
||||
goto_out;
|
||||
break;
|
||||
case DEACTIVATE:
|
||||
@@ -1056,7 +1053,7 @@ int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv)
|
||||
* 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,
|
||||
int dev_manager_device_uses_vg(struct device *dev,
|
||||
struct volume_group *vg)
|
||||
{
|
||||
struct dm_tree *dtree;
|
||||
@@ -1069,7 +1066,7 @@ int dev_manager_device_uses_vg(struct dev_manager *dm, struct device *dev,
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!dm_tree_add_dev(dtree, MAJOR(dev->dev), MINOR(dev->dev))) {
|
||||
if (!dm_tree_add_dev(dtree, (uint32_t) MAJOR(dev->dev), (uint32_t) MINOR(dev->dev))) {
|
||||
log_error("Failed to add device %s (%" PRIu32 ":%" PRIu32") to dtree",
|
||||
dev_name(dev), (uint32_t) MAJOR(dev->dev), (uint32_t) MINOR(dev->dev));
|
||||
goto out;
|
||||
|
||||
@@ -59,7 +59,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,
|
||||
int dev_manager_device_uses_vg(struct device *dev,
|
||||
struct volume_group *vg);
|
||||
|
||||
#endif
|
||||
|
||||
4
lib/cache/lvmcache.c
vendored
4
lib/cache/lvmcache.c
vendored
@@ -50,7 +50,7 @@ int lvmcache_init(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void lvmcache_lock_vgname(const char *vgname, int read_only)
|
||||
void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)))
|
||||
{
|
||||
if (!_lock_hash && !lvmcache_init()) {
|
||||
log_error("Internal cache initialisation failed");
|
||||
@@ -857,7 +857,7 @@ static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
|
||||
} while ((vginfo = next));
|
||||
}
|
||||
|
||||
static void _lvmcache_destroy_lockname(int present)
|
||||
static void _lvmcache_destroy_lockname(int present __attribute((unused)))
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
@@ -34,7 +34,10 @@
|
||||
#define DEFAULT_LOCK_DIR "/var/lock/lvm"
|
||||
#define DEFAULT_LOCKING_LIB "lvm2_locking.so"
|
||||
|
||||
#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
|
||||
#define DEFAULT_MIRROR_DEV_FAULT_POLICY "remove"
|
||||
#define DEFAULT_DMEVENTD_MIRROR_LIB "libdevmapper-event-lvm2mirror.so"
|
||||
#define DEFAULT_DMEVENTD_MONITOR 1
|
||||
|
||||
#define DEFAULT_UMASK 0077
|
||||
|
||||
|
||||
@@ -602,7 +602,7 @@ int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
|
||||
return _aligned_io(&where, buffer, 1);
|
||||
}
|
||||
|
||||
int dev_zero(struct device *dev, uint64_t offset, size_t len)
|
||||
int dev_set(struct device *dev, uint64_t offset, size_t len, int value)
|
||||
{
|
||||
size_t s;
|
||||
char buffer[4096];
|
||||
@@ -620,7 +620,7 @@ int dev_zero(struct device *dev, uint64_t offset, size_t len)
|
||||
" sectors", dev_name(dev), offset >> SECTOR_SHIFT,
|
||||
len >> SECTOR_SHIFT);
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
memset(buffer, value, sizeof(buffer));
|
||||
while (1) {
|
||||
s = len > sizeof(buffer) ? sizeof(buffer) : len;
|
||||
if (!dev_write(dev, offset, s, buffer))
|
||||
|
||||
@@ -62,7 +62,7 @@ static int _has_partition_table(struct device *dev)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!dev_read(dev, 0, sizeof(buf), &buf)) {
|
||||
if (!dev_read(dev, UINT64_C(0), sizeof(buf), &buf)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ const char *dev_name(const struct device *dev);
|
||||
int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer);
|
||||
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer);
|
||||
int dev_append(struct device *dev, size_t len, void *buffer);
|
||||
int dev_zero(struct device *dev, uint64_t offset, size_t len);
|
||||
int dev_set(struct device *dev, uint64_t offset, size_t len, int value);
|
||||
void dev_flush(struct device *dev);
|
||||
|
||||
struct device *dev_create_file(const char *filename, struct device *dev,
|
||||
|
||||
@@ -38,11 +38,13 @@ static int _errseg_merge_segments(struct lv_segment *seg1, struct lv_segment *se
|
||||
}
|
||||
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
static int _errseg_add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
struct config_tree *cft, void **target_state,
|
||||
struct lv_segment *seg,
|
||||
static int _errseg_add_target_line(struct dev_manager *dm __attribute((unused)),
|
||||
struct dm_pool *mem __attribute((unused)),
|
||||
struct config_tree *cft __attribute((unused)),
|
||||
void **target_state __attribute((unused)),
|
||||
struct lv_segment *seg __attribute((unused)),
|
||||
struct dm_tree_node *node, uint64_t len,
|
||||
uint32_t *pvmove_mirror_count)
|
||||
uint32_t *pvmove_mirror_count __attribute((unused)))
|
||||
{
|
||||
return dm_tree_node_add_error_target(node, len);
|
||||
}
|
||||
@@ -64,7 +66,7 @@ static int _errseg_target_present(void)
|
||||
|
||||
static void _errseg_destroy(const struct segment_type *segtype)
|
||||
{
|
||||
dm_free((void *) segtype);
|
||||
dm_free((void *)segtype);
|
||||
}
|
||||
|
||||
static struct segtype_handler _error_ops = {
|
||||
|
||||
@@ -576,7 +576,7 @@ static int _write_lvs(struct disk_list *data)
|
||||
|
||||
pos = data->pvd.lv_on_disk.base;
|
||||
|
||||
if (!dev_zero(data->dev, pos, data->pvd.lv_on_disk.size)) {
|
||||
if (!dev_set(data->dev, pos, data->pvd.lv_on_disk.size, 0)) {
|
||||
log_error("Couldn't zero lv area on device '%s'",
|
||||
dev_name(data->dev));
|
||||
return 0;
|
||||
|
||||
@@ -183,7 +183,8 @@ static int _out_with_comment_file(struct formatter *f, const char *comment,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _out_with_comment_raw(struct formatter *f, const char *comment,
|
||||
static int _out_with_comment_raw(struct formatter *f,
|
||||
const char *comment __attribute((unused)),
|
||||
const char *fmt, va_list ap)
|
||||
{
|
||||
int n;
|
||||
@@ -281,7 +282,7 @@ int out_text(struct formatter *f, const char *fmt, ...)
|
||||
}
|
||||
|
||||
static int _print_header(struct formatter *f,
|
||||
struct volume_group *vg, const char *desc)
|
||||
const char *desc)
|
||||
{
|
||||
time_t t;
|
||||
|
||||
@@ -665,7 +666,7 @@ static int _text_vg_export(struct formatter *f,
|
||||
}
|
||||
#define fail do {stack; goto out;} while(0)
|
||||
|
||||
if (f->header && !_print_header(f, vg, desc))
|
||||
if (f->header && !_print_header(f, desc))
|
||||
fail;
|
||||
|
||||
if (!out_text(f, "%s {", vg->name))
|
||||
@@ -688,7 +689,7 @@ static int _text_vg_export(struct formatter *f,
|
||||
if (!out_text(f, "}"))
|
||||
fail;
|
||||
|
||||
if (!f->header && !_print_header(f, vg, desc))
|
||||
if (!f->header && !_print_header(f, desc))
|
||||
fail;
|
||||
|
||||
#undef fail
|
||||
|
||||
@@ -53,6 +53,7 @@ static struct flag _lv_flags[] = {
|
||||
{VISIBLE_LV, "VISIBLE"},
|
||||
{PVMOVE, "PVMOVE"},
|
||||
{LOCKED, "LOCKED"},
|
||||
{MIRROR_NOTSYNCED, "NOTSYNCED"},
|
||||
{MIRROR_IMAGE, NULL},
|
||||
{MIRROR_LOG, NULL},
|
||||
{MIRRORED, NULL},
|
||||
|
||||
@@ -69,7 +69,8 @@ struct text_context {
|
||||
* NOTE: Currently there can be only one vg per text file.
|
||||
*/
|
||||
|
||||
static int _text_vg_setup(struct format_instance *fid, struct volume_group *vg)
|
||||
static int _text_vg_setup(struct format_instance *fid __attribute((unused)),
|
||||
struct volume_group *vg)
|
||||
{
|
||||
if (vg->extent_size & (vg->extent_size - 1)) {
|
||||
log_error("Extent size must be power of 2");
|
||||
@@ -79,7 +80,8 @@ static int _text_vg_setup(struct format_instance *fid, struct volume_group *vg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _text_lv_setup(struct format_instance *fid, struct logical_volume *lv)
|
||||
static int _text_lv_setup(struct format_instance *fid __attribute((unused)),
|
||||
struct logical_volume *lv)
|
||||
{
|
||||
/******** FIXME Any LV size restriction?
|
||||
uint64_t max_size = UINT_MAX;
|
||||
@@ -1071,9 +1073,9 @@ static int _mda_setup(const struct format_type *fmt,
|
||||
if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start1,
|
||||
mda_size1)) return 0;
|
||||
|
||||
if (!dev_zero((struct device *) pv->dev, start1,
|
||||
(size_t) (mda_size1 >
|
||||
wipe_size ? : mda_size1))) {
|
||||
if (!dev_set((struct device *) pv->dev, start1,
|
||||
(size_t) (mda_size1 >
|
||||
wipe_size ? : mda_size1), 0)) {
|
||||
log_error("Failed to wipe new metadata area");
|
||||
return 0;
|
||||
}
|
||||
@@ -1117,9 +1119,9 @@ static int _mda_setup(const struct format_type *fmt,
|
||||
if (mda_size2) {
|
||||
if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start2,
|
||||
mda_size2)) return 0;
|
||||
if (!dev_zero(pv->dev, start2,
|
||||
(size_t) (mda_size1 >
|
||||
wipe_size ? : mda_size1))) {
|
||||
if (!dev_set(pv->dev, start2,
|
||||
(size_t) (mda_size1 >
|
||||
wipe_size ? : mda_size1), 0)) {
|
||||
log_error("Failed to wipe new metadata area");
|
||||
return 0;
|
||||
}
|
||||
@@ -1202,7 +1204,7 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
|
||||
}
|
||||
}
|
||||
if (!add_da
|
||||
(fmt, NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0))) {
|
||||
(NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -1339,7 +1341,7 @@ static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _text_destroy_instance(struct format_instance *fid)
|
||||
static void _text_destroy_instance(struct format_instance *fid __attribute((unused)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1372,7 +1374,7 @@ static void _text_destroy(const struct format_type *fmt)
|
||||
dm_free(fmt->private);
|
||||
}
|
||||
|
||||
dm_free((void *) fmt);
|
||||
dm_free((void *)fmt);
|
||||
}
|
||||
|
||||
static struct metadata_area_ops _metadata_text_file_ops = {
|
||||
|
||||
@@ -46,7 +46,7 @@ struct labeller *text_labeller_create(const struct format_type *fmt);
|
||||
|
||||
int pvhdr_read(struct device *dev, char *buf);
|
||||
|
||||
int add_da(const struct format_type *fmt, struct dm_pool *mem, struct list *das,
|
||||
int add_da(struct dm_pool *mem, struct list *das,
|
||||
uint64_t start, uint64_t size);
|
||||
void del_das(struct list *das);
|
||||
|
||||
|
||||
@@ -129,6 +129,6 @@ struct volume_group *text_vg_import_file(struct format_instance *fid,
|
||||
const char *file,
|
||||
time_t *when, char **desc)
|
||||
{
|
||||
return text_vg_import_fd(fid, file, NULL, 0, 0, 0, 0, NULL, 0,
|
||||
return text_vg_import_fd(fid, file, NULL, (off_t)0, 0, (off_t)0, 0, NULL, 0,
|
||||
when, desc);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,9 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static int _text_can_handle(struct labeller *l, char *buf, uint64_t sector)
|
||||
static int _text_can_handle(struct labeller *l __attribute((unused)),
|
||||
char *buf,
|
||||
uint64_t sector __attribute((unused)))
|
||||
{
|
||||
struct label_header *lh = (struct label_header *) buf;
|
||||
|
||||
@@ -86,7 +88,7 @@ static int _text_write(struct label *label, char *buf)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int add_da(const struct format_type *fmt, struct dm_pool *mem, struct list *das,
|
||||
int add_da(struct dm_pool *mem, struct list *das,
|
||||
uint64_t start, uint64_t size)
|
||||
{
|
||||
struct data_area_list *dal;
|
||||
@@ -179,7 +181,8 @@ void del_mdas(struct list *mdas)
|
||||
}
|
||||
}
|
||||
|
||||
static int _text_initialise_label(struct labeller *l, struct label *label)
|
||||
static int _text_initialise_label(struct labeller *l __attribute((unused)),
|
||||
struct label *label)
|
||||
{
|
||||
strncpy(label->type, LVM2_LABEL, sizeof(label->type));
|
||||
|
||||
@@ -220,7 +223,7 @@ static int _text_read(struct labeller *l, struct device *dev, char *buf,
|
||||
/* Data areas holding the PEs */
|
||||
dlocn_xl = pvhdr->disk_areas_xl;
|
||||
while ((offset = xlate64(dlocn_xl->offset))) {
|
||||
add_da(info->fmt, NULL, &info->das, offset,
|
||||
add_da(NULL, &info->das, offset,
|
||||
xlate64(dlocn_xl->size));
|
||||
dlocn_xl++;
|
||||
}
|
||||
@@ -248,7 +251,8 @@ static int _text_read(struct labeller *l, struct device *dev, char *buf,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _text_destroy_label(struct labeller *l, struct label *label)
|
||||
static void _text_destroy_label(struct labeller *l __attribute((unused)),
|
||||
struct label *label)
|
||||
{
|
||||
struct lvmcache_info *info = (struct lvmcache_info *) label->info;
|
||||
|
||||
|
||||
@@ -333,6 +333,12 @@ static int _lock_for_cluster(unsigned char cmd, unsigned int flags, char *name)
|
||||
if (partial_mode())
|
||||
args[1] |= LCK_PARTIAL_MODE;
|
||||
|
||||
if (mirror_in_sync())
|
||||
args[1] |= LCK_MIRROR_NOSYNC_MODE;
|
||||
|
||||
if (dmeventd_register_mode())
|
||||
args[1] |= LCK_DMEVENTD_REGISTER_MODE;
|
||||
|
||||
/*
|
||||
* VG locks are just that: locks, and have no side effects
|
||||
* so we only need to do them on the local node because all
|
||||
|
||||
@@ -105,7 +105,7 @@ static void _remove_ctrl_c_handler()
|
||||
log_sys_error("signal", "_remove_ctrl_c_handler");
|
||||
}
|
||||
|
||||
static void _trap_ctrl_c(int sig)
|
||||
static void _trap_ctrl_c(int sig __attribute((unused)))
|
||||
{
|
||||
_remove_ctrl_c_handler();
|
||||
log_error("CTRL-c detected: giving up waiting for lock");
|
||||
|
||||
@@ -33,7 +33,7 @@ static int _vg_lock_count = 0; /* Number of locks held */
|
||||
static int _vg_write_lock_held = 0; /* VG write lock held? */
|
||||
static int _signals_blocked = 0;
|
||||
|
||||
static void _block_signals(int flags)
|
||||
static void _block_signals(int flags __attribute((unused)))
|
||||
{
|
||||
sigset_t set;
|
||||
|
||||
|
||||
@@ -74,6 +74,9 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
|
||||
* Additional lock bits for cluster communication
|
||||
*/
|
||||
#define LCK_PARTIAL_MODE 0x00000001 /* Running in partial mode */
|
||||
#define LCK_MIRROR_NOSYNC_MODE 0x00000002 /* Mirrors don't require sync */
|
||||
#define LCK_DMEVENTD_REGISTER_MODE 0x00000004 /* Register with dmeventd */
|
||||
|
||||
|
||||
/*
|
||||
* Common combinations
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "device.h"
|
||||
#include "memlock.h"
|
||||
#include "lvm-string.h"
|
||||
#include "defaults.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <syslog.h>
|
||||
@@ -45,6 +46,8 @@ static int _security_level = SECURITY_LEVEL;
|
||||
static char _cmd_name[30] = "";
|
||||
static char _msg_prefix[30] = " ";
|
||||
static int _already_logging = 0;
|
||||
static int _mirror_in_sync = 0;
|
||||
static int _dmeventd_register = DEFAULT_DMEVENTD_MONITOR;
|
||||
|
||||
static lvm2_log_fn_t _lvm2_log_fn = NULL;
|
||||
|
||||
@@ -175,6 +178,16 @@ void init_security_level(int level)
|
||||
_security_level = level;
|
||||
}
|
||||
|
||||
void init_mirror_in_sync(int in_sync)
|
||||
{
|
||||
_mirror_in_sync = in_sync;
|
||||
}
|
||||
|
||||
void init_dmeventd_register(int reg)
|
||||
{
|
||||
_dmeventd_register = reg;
|
||||
}
|
||||
|
||||
void init_cmd_name(int status)
|
||||
{
|
||||
_log_cmd_name = status;
|
||||
@@ -239,6 +252,16 @@ int security_level()
|
||||
return _security_level;
|
||||
}
|
||||
|
||||
int mirror_in_sync(void)
|
||||
{
|
||||
return _mirror_in_sync;
|
||||
}
|
||||
|
||||
int dmeventd_register_mode(void)
|
||||
{
|
||||
return _dmeventd_register;
|
||||
}
|
||||
|
||||
void init_debug(int level)
|
||||
{
|
||||
_debug_level = level;
|
||||
|
||||
@@ -73,6 +73,8 @@ void init_indent(int indent);
|
||||
void init_ignorelockingfailure(int level);
|
||||
void init_lockingfailed(int level);
|
||||
void init_security_level(int level);
|
||||
void init_mirror_in_sync(int in_sync);
|
||||
void init_dmeventd_register(int reg);
|
||||
|
||||
void set_cmd_name(const char *cmd_name);
|
||||
|
||||
@@ -85,6 +87,8 @@ int debug_level(void);
|
||||
int ignorelockingfailure(void);
|
||||
int lockingfailed(void);
|
||||
int security_level(void);
|
||||
int mirror_in_sync(void);
|
||||
int dmeventd_register_mode(void);
|
||||
|
||||
/* Suppress messages to stdout/stderr (1) or everywhere (2) */
|
||||
/* Returns previous setting */
|
||||
|
||||
@@ -498,7 +498,7 @@ static int _setup_alloced_segment(struct logical_volume *lv, uint32_t status,
|
||||
struct physical_volume *mirrored_pv,
|
||||
uint32_t mirrored_pe,
|
||||
uint32_t region_size,
|
||||
struct logical_volume *log_lv)
|
||||
struct logical_volume *log_lv __attribute((unused)))
|
||||
{
|
||||
uint32_t s, extents, area_multiple, extra_areas = 0;
|
||||
struct lv_segment *seg;
|
||||
@@ -1102,7 +1102,7 @@ int lv_add_mirror_segment(struct alloc_handle *ah,
|
||||
struct lv_segment *seg;
|
||||
uint32_t m;
|
||||
|
||||
if (list_empty(&log_lv->segments)) {
|
||||
if (log_lv && list_empty(&log_lv->segments)) {
|
||||
log_error("Log LV %s is empty.", log_lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
|
||||
}
|
||||
|
||||
/* Ensure PV doesn't depend on another PV already in the VG */
|
||||
if (pv_uses_vg(fid->fmt->cmd, pv, vg)) {
|
||||
if (pv_uses_vg(pv, vg)) {
|
||||
log_error("Physical volume %s might be constructed from same "
|
||||
"volume group %s", pv_name, vg->name);
|
||||
return 0;
|
||||
@@ -1342,7 +1342,7 @@ struct list *get_pvs(struct cmd_context *cmd)
|
||||
return results;
|
||||
}
|
||||
|
||||
int pv_write(struct cmd_context *cmd, struct physical_volume *pv,
|
||||
int pv_write(struct cmd_context *cmd __attribute((unused)), struct physical_volume *pv,
|
||||
struct list *mdas, int64_t label_sector)
|
||||
{
|
||||
if (!pv->fmt->ops->pv_write) {
|
||||
|
||||
@@ -58,8 +58,9 @@
|
||||
#define VIRTUAL 0x00010000U /* LV - internal use only */
|
||||
#define MIRROR_LOG 0x00020000U /* LV */
|
||||
#define MIRROR_IMAGE 0x00040000U /* LV */
|
||||
#define ACTIVATE_EXCL 0x00080000U /* LV - internal use only */
|
||||
#define PRECOMMITTED 0x00100000U /* VG - internal use only */
|
||||
#define MIRROR_NOTSYNCED 0x00080000U /* LV */
|
||||
#define ACTIVATE_EXCL 0x00100000U /* LV - internal use only */
|
||||
#define PRECOMMITTED 0x00200000U /* VG - internal use only */
|
||||
|
||||
#define LVM_READ 0x00000100U /* LV VG */
|
||||
#define LVM_WRITE 0x00000200U /* LV VG */
|
||||
@@ -580,6 +581,8 @@ int add_mirror_layers(struct alloc_handle *ah,
|
||||
|
||||
int remove_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
|
||||
struct list *removable_pvs, int remove_log);
|
||||
int reconfigure_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
|
||||
struct list *removable_pvs, int remove_log);
|
||||
/*
|
||||
* Given mirror image or mirror log segment, find corresponding mirror segment
|
||||
*/
|
||||
|
||||
@@ -23,6 +23,13 @@
|
||||
#include "lvm-string.h"
|
||||
#include "locking.h" /* FIXME Should not be used in this file */
|
||||
|
||||
#include "defaults.h" /* FIXME: should this be defaults.h? */
|
||||
|
||||
/* These are the flags that represent the mirror failure restoration policies */
|
||||
#define MIRROR_REMOVE 0
|
||||
#define MIRROR_ALLOCATE 1
|
||||
#define MIRROR_ALLOCATE_ANYWHERE 2
|
||||
|
||||
struct lv_segment *find_mirror_seg(struct lv_segment *seg)
|
||||
{
|
||||
return seg->mirror_seg;
|
||||
@@ -230,6 +237,163 @@ int remove_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_mirror_fault_policy(struct cmd_context *cmd, int log_policy)
|
||||
{
|
||||
const char *policy;
|
||||
|
||||
if (log_policy)
|
||||
policy = find_config_str(NULL, "activation/mirror_log_fault_policy",
|
||||
DEFAULT_MIRROR_LOG_FAULT_POLICY);
|
||||
else
|
||||
policy = find_config_str(NULL, "activation/mirror_device_fault_policy",
|
||||
DEFAULT_MIRROR_DEV_FAULT_POLICY);
|
||||
|
||||
if (!strcmp(policy, "remove"))
|
||||
return MIRROR_REMOVE;
|
||||
else if (!strcmp(policy, "allocate"))
|
||||
return MIRROR_ALLOCATE;
|
||||
else if (!strcmp(policy, "allocate_anywhere"))
|
||||
return MIRROR_ALLOCATE_ANYWHERE;
|
||||
|
||||
if (log_policy)
|
||||
log_error("Bad activation/mirror_log_fault_policy");
|
||||
else
|
||||
log_error("Bad activation/mirror_device_fault_policy");
|
||||
|
||||
return MIRROR_REMOVE;
|
||||
}
|
||||
|
||||
static int get_mirror_log_fault_policy(struct cmd_context *cmd)
|
||||
{
|
||||
return get_mirror_fault_policy(cmd, 1);
|
||||
}
|
||||
|
||||
static int get_mirror_device_fault_policy(struct cmd_context *cmd)
|
||||
{
|
||||
return get_mirror_fault_policy(cmd, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* replace_mirror_images
|
||||
* @mirrored_seg: segment (which may be linear now) to restore
|
||||
* @num_mirrors: number of copies we should end up with
|
||||
* @replace_log: replace log if not present
|
||||
* @in_sync: was the original mirror in-sync?
|
||||
*
|
||||
* in_sync will be set to 0 if new mirror devices are being added
|
||||
* In other words, it is only useful if the log (and only the log)
|
||||
* is being restored.
|
||||
*
|
||||
* Returns: 0 on failure, 1 on reconfig, -1 if no reconfig done
|
||||
*/
|
||||
static int replace_mirror_images(struct lv_segment *mirrored_seg,
|
||||
uint32_t num_mirrors,
|
||||
int log_policy, int in_sync)
|
||||
{
|
||||
int r = -1;
|
||||
struct logical_volume *lv = mirrored_seg->lv;
|
||||
|
||||
/* FIXME: Use lvconvert rather than duplicating its code */
|
||||
|
||||
if (mirrored_seg->area_count < num_mirrors) {
|
||||
log_error("WARNING: Failed to replace mirror device in %s/%s",
|
||||
mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
|
||||
|
||||
if ((mirrored_seg->area_count > 1) && !mirrored_seg->log_lv)
|
||||
log_error("WARNING: Use 'lvconvert -m %d %s/%s --corelog' to replace failed devices",
|
||||
num_mirrors - 1, lv->vg->name, lv->name);
|
||||
else
|
||||
log_error("WARNING: Use 'lvconvert -m %d %s/%s' to replace failed devices",
|
||||
num_mirrors - 1, lv->vg->name, lv->name);
|
||||
r = 0;
|
||||
|
||||
/* REMEMBER/FIXME: set in_sync to 0 if a new mirror device was added */
|
||||
in_sync = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: right now, we ignore the allocation policy specified to
|
||||
* allocate the new log.
|
||||
*/
|
||||
if ((mirrored_seg->area_count > 1) && !mirrored_seg->log_lv &&
|
||||
(log_policy != MIRROR_REMOVE)) {
|
||||
log_error("WARNING: Failed to replace mirror log device in %s/%s",
|
||||
lv->vg->name, lv->name);
|
||||
|
||||
log_error("WARNING: Use 'lvconvert -m %d %s/%s' to replace failed devices",
|
||||
mirrored_seg->area_count - 1 , lv->vg->name, lv->name);
|
||||
r = 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int reconfigure_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
|
||||
struct list *removable_pvs, int remove_log)
|
||||
{
|
||||
int r;
|
||||
int insync = 0;
|
||||
int log_policy, dev_policy;
|
||||
uint32_t old_num_mirrors = mirrored_seg->area_count;
|
||||
int had_log = (mirrored_seg->log_lv) ? 1 : 0;
|
||||
float sync_percent = 0;
|
||||
|
||||
/* was the mirror in-sync before problems? */
|
||||
if (!lv_mirror_percent(mirrored_seg->lv->vg->cmd,
|
||||
mirrored_seg->lv, 0, &sync_percent, NULL))
|
||||
log_error("WARNING: Unable to determine mirror sync status of %s/%s.",
|
||||
mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
|
||||
else if (sync_percent >= 100.0)
|
||||
insync = 1;
|
||||
|
||||
/*
|
||||
* While we are only removing devices, we can have sync set.
|
||||
* Setting this is only useful if we are moving to core log
|
||||
* otherwise the disk log will contain the sync information
|
||||
*/
|
||||
init_mirror_in_sync(insync);
|
||||
|
||||
r = remove_mirror_images(mirrored_seg, num_mirrors,
|
||||
removable_pvs, remove_log);
|
||||
if (!r)
|
||||
/* Unable to remove bad devices */
|
||||
return 0;
|
||||
|
||||
log_print("WARNING: Bad device removed from mirror volume, %s/%s",
|
||||
mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
|
||||
|
||||
log_policy = get_mirror_log_fault_policy(mirrored_seg->lv->vg->cmd);
|
||||
dev_policy = get_mirror_device_fault_policy(mirrored_seg->lv->vg->cmd);
|
||||
|
||||
r = replace_mirror_images(mirrored_seg,
|
||||
(dev_policy != MIRROR_REMOVE) ?
|
||||
old_num_mirrors : num_mirrors,
|
||||
log_policy, insync);
|
||||
|
||||
if (!r)
|
||||
/* Failed to replace device(s) */
|
||||
log_error("WARNING: Unable to find substitute device for mirror volume, %s/%s",
|
||||
mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
|
||||
else if (r > 0)
|
||||
/* Success in replacing device(s) */
|
||||
log_print("WARNING: Mirror volume, %s/%s restored - substitute for failed device found.",
|
||||
mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
|
||||
else
|
||||
/* Bad device removed, but not replaced because of policy */
|
||||
if (mirrored_seg->area_count == 1) {
|
||||
log_print("WARNING: Mirror volume, %s/%s converted to linear due to device failure.",
|
||||
mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
|
||||
} else if (had_log && !mirrored_seg->log_lv) {
|
||||
log_print("WARNING: Mirror volume, %s/%s disk log removed due to device failure.",
|
||||
mirrored_seg->lv->vg->name, mirrored_seg->lv->name);
|
||||
}
|
||||
/*
|
||||
* If we made it here, we at least removed the bad device.
|
||||
* Consider this success.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _create_layers_for_mirror(struct alloc_handle *ah,
|
||||
uint32_t first_area,
|
||||
uint32_t num_mirrors,
|
||||
|
||||
@@ -174,7 +174,8 @@ static struct mirror_state *_mirrored_init_target(struct dm_pool *mem,
|
||||
static int _mirrored_target_percent(void **target_state, struct dm_pool *mem,
|
||||
struct config_tree *cft, struct lv_segment *seg,
|
||||
char *params, uint64_t *total_numerator,
|
||||
uint64_t *total_denominator, float *percent)
|
||||
uint64_t *total_denominator,
|
||||
float *percent __attribute((unused)))
|
||||
{
|
||||
struct mirror_state *mirr_state;
|
||||
uint64_t numerator, denominator;
|
||||
@@ -237,13 +238,26 @@ static int _add_log(struct dev_manager *dm, struct lv_segment *seg,
|
||||
(seg->lv->vg->status & CLUSTERED)))
|
||||
clustered = 1;
|
||||
|
||||
if (seg->log_lv &&
|
||||
!(log_dlid = build_dlid(dm, seg->log_lv->lvid.s, NULL))) {
|
||||
log_error("Failed to build uuid for log LV %s.",
|
||||
seg->log_lv->name);
|
||||
return 0;
|
||||
if (seg->log_lv) {
|
||||
/* If disk log, use its UUID */
|
||||
if (!(log_dlid = build_dlid(dm, seg->log_lv->lvid.s, NULL))) {
|
||||
log_error("Failed to build uuid for log LV %s.",
|
||||
seg->log_lv->name);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* If core log, use mirror's UUID and set DM_CORELOG flag */
|
||||
if (!(log_dlid = build_dlid(dm, seg->lv->lvid.s, NULL))) {
|
||||
log_error("Failed to build uuid for mirror LV %s.",
|
||||
seg->lv->name);
|
||||
return 0;
|
||||
}
|
||||
log_flags |= DM_CORELOG;
|
||||
}
|
||||
|
||||
if (mirror_in_sync() && !(seg->status & PVMOVE))
|
||||
log_flags |= DM_NOSYNC;
|
||||
|
||||
if (_block_on_error_available && !(seg->status & PVMOVE))
|
||||
log_flags |= DM_BLOCK_ON_ERROR;
|
||||
|
||||
|
||||
@@ -1,430 +0,0 @@
|
||||
/* lib/misc/configure.h. Generated by configure. */
|
||||
/* lib/misc/configure.h.in. Generated from configure.in by autoheader. */
|
||||
|
||||
/* Define to 1 if the `closedir' function returns void instead of `int'. */
|
||||
/* #undef CLOSEDIR_VOID */
|
||||
|
||||
/* Define to 1 to include built-in support for clustered LVM locking. */
|
||||
/* #undef CLUSTER_LOCKING_INTERNAL */
|
||||
|
||||
/* Define to 1 to build the shared command library. */
|
||||
/* #undef CMDLIB */
|
||||
|
||||
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
|
||||
systems. This function is required for `alloca.c' support on those systems.
|
||||
*/
|
||||
/* #undef CRAY_STACKSEG_END */
|
||||
|
||||
/* Define to 1 if using `alloca.c'. */
|
||||
/* #undef C_ALLOCA */
|
||||
|
||||
/* Define to 1 to enable device-mapper interaction. */
|
||||
#define DEVMAPPER_SUPPORT 1
|
||||
|
||||
/* Define to 1 to enable the device-mapper event daemon. */
|
||||
/* #undef DMEVENTD */
|
||||
|
||||
/* Define to 1 if you have `alloca', as a function or macro. */
|
||||
#define HAVE_ALLOCA 1
|
||||
|
||||
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
|
||||
*/
|
||||
#define HAVE_ALLOCA_H 1
|
||||
|
||||
/* Define to 1 if you have the <asm/byteorder.h> header file. */
|
||||
/* #undef HAVE_ASM_BYTEORDER_H */
|
||||
|
||||
/* Define to 1 if you have the <assert.h> header file. */
|
||||
#define HAVE_ASSERT_H 1
|
||||
|
||||
/* Define to 1 if you have the <ctype.h> header file. */
|
||||
#define HAVE_CTYPE_H 1
|
||||
|
||||
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
|
||||
*/
|
||||
#define HAVE_DIRENT_H 1
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
|
||||
/* #undef HAVE_DOPRNT */
|
||||
|
||||
/* Define to 1 if you have the `dup2' function. */
|
||||
/* #undef HAVE_DUP2 */
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#define HAVE_FCNTL_H 1
|
||||
|
||||
/* Define to 1 if you have the `fork' function. */
|
||||
#define HAVE_FORK 1
|
||||
|
||||
/* Define to 1 if you have the <fstab.h> header file. */
|
||||
/* #undef HAVE_FSTAB_H */
|
||||
|
||||
/* Define to 1 if you have the `gethostname' function. */
|
||||
#define HAVE_GETHOSTNAME 1
|
||||
|
||||
/* Define to 1 if you have the `getmntent' function. */
|
||||
/* #undef HAVE_GETMNTENT */
|
||||
|
||||
/* Define to 1 to if getopt_long is available. */
|
||||
#define HAVE_GETOPTLONG 1
|
||||
|
||||
/* Define to 1 if you have the <getopt.h> header file. */
|
||||
#define HAVE_GETOPT_H 1
|
||||
|
||||
/* Define to 1 if you have the `getpagesize' function. */
|
||||
#define HAVE_GETPAGESIZE 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <libdevmapper.h> header file. */
|
||||
#define HAVE_LIBDEVMAPPER_H 1
|
||||
|
||||
/* Define to 1 if dynamic libraries are available. */
|
||||
#define HAVE_LIBDL 1
|
||||
|
||||
/* Define to 1 if you have the <libgen.h> header file. */
|
||||
#define HAVE_LIBGEN_H 1
|
||||
|
||||
/* Define to 1 if you have the <libintl.h> header file. */
|
||||
/* #undef HAVE_LIBINTL_H */
|
||||
|
||||
/* Define to 1 if you have the `readline' library (-lreadline). */
|
||||
/* #undef HAVE_LIBREADLINE */
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#define HAVE_LIMITS_H 1
|
||||
|
||||
/* Define to 1 if you have the <linux/fs.h> header file. */
|
||||
/* #undef HAVE_LINUX_FS_H */
|
||||
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
#define HAVE_LOCALE_H 1
|
||||
|
||||
/* Define to 1 if `lstat' has the bug that it succeeds when given the
|
||||
zero-length file name argument. */
|
||||
/* #undef HAVE_LSTAT_EMPTY_STRING_BUG */
|
||||
|
||||
/* Define to 1 if you have the <machine/endian.h> header file. */
|
||||
#define HAVE_MACHINE_ENDIAN_H 1
|
||||
|
||||
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
|
||||
to 0 otherwise. */
|
||||
#define HAVE_MALLOC 1
|
||||
|
||||
/* Define to 1 if you have the <malloc.h> header file. */
|
||||
/* #undef HAVE_MALLOC_H */
|
||||
|
||||
/* Define to 1 if you have the `memmove' function. */
|
||||
/* #undef HAVE_MEMMOVE */
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#define HAVE_MEMSET 1
|
||||
|
||||
/* Define to 1 if you have the `mkdir' function. */
|
||||
#define HAVE_MKDIR 1
|
||||
|
||||
/* Define to 1 if you have a working `mmap' system call. */
|
||||
#define HAVE_MMAP 1
|
||||
|
||||
/* Define to 1 if you have the <mntent.h> header file. */
|
||||
/* #undef HAVE_MNTENT_H */
|
||||
|
||||
/* Define to 1 if you have the `munmap' function. */
|
||||
#define HAVE_MUNMAP 1
|
||||
|
||||
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
|
||||
/* #undef HAVE_NDIR_H */
|
||||
|
||||
/* Define to 1 if you have the <netdb.h> header file. */
|
||||
/* #undef HAVE_NETDB_H */
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
/* #undef HAVE_NETINET_IN_H */
|
||||
|
||||
/* Define to 1 if you have the <pthread.h> header file. */
|
||||
/* #undef HAVE_PTHREAD_H */
|
||||
|
||||
/* Define to 1 if you have the <readline/history.h> header file. */
|
||||
/* #undef HAVE_READLINE_HISTORY_H */
|
||||
|
||||
/* Define to 1 if you have the <readline/readline.h> header file. */
|
||||
/* #undef HAVE_READLINE_READLINE_H */
|
||||
|
||||
/* Define to 1 if rl_completion_matches() is available. */
|
||||
/* #undef HAVE_RL_COMPLETION_MATCHES */
|
||||
|
||||
/* Define to 1 if you have the `rmdir' function. */
|
||||
#define HAVE_RMDIR 1
|
||||
|
||||
/* Define to 1 if you have the <search.h> header file. */
|
||||
/* #undef HAVE_SEARCH_H */
|
||||
|
||||
/* Define to 1 if you have the `select' function. */
|
||||
/* #undef HAVE_SELECT */
|
||||
|
||||
/* Define to 1 to include support for selinux. */
|
||||
/* #undef HAVE_SELINUX */
|
||||
|
||||
/* Define to 1 if you have the <selinux/selinux.h> header file. */
|
||||
/* #undef HAVE_SELINUX_SELINUX_H */
|
||||
|
||||
/* Define to 1 if you have the `setlocale' function. */
|
||||
#define HAVE_SETLOCALE 1
|
||||
|
||||
/* Define to 1 if you have the <signal.h> header file. */
|
||||
#define HAVE_SIGNAL_H 1
|
||||
|
||||
/* Define to 1 if you have the `socket' function. */
|
||||
/* #undef HAVE_SOCKET */
|
||||
|
||||
/* Define to 1 if `stat' has the bug that it succeeds when given the
|
||||
zero-length file name argument. */
|
||||
/* #undef HAVE_STAT_EMPTY_STRING_BUG */
|
||||
|
||||
/* Define to 1 if you have the <stddef.h> header file. */
|
||||
#define HAVE_STDDEF_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#define HAVE_STDIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the `strcasecmp' function. */
|
||||
#define HAVE_STRCASECMP 1
|
||||
|
||||
/* Define to 1 if you have the `strchr' function. */
|
||||
#define HAVE_STRCHR 1
|
||||
|
||||
/* Define to 1 if you have the `strdup' function. */
|
||||
#define HAVE_STRDUP 1
|
||||
|
||||
/* Define to 1 if you have the `strerror' function. */
|
||||
#define HAVE_STRERROR 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the `strncasecmp' function. */
|
||||
#define HAVE_STRNCASECMP 1
|
||||
|
||||
/* Define to 1 if you have the `strrchr' function. */
|
||||
#define HAVE_STRRCHR 1
|
||||
|
||||
/* Define to 1 if you have the `strstr' function. */
|
||||
#define HAVE_STRSTR 1
|
||||
|
||||
/* Define to 1 if you have the `strtol' function. */
|
||||
#define HAVE_STRTOL 1
|
||||
|
||||
/* Define to 1 if you have the `strtoul' function. */
|
||||
#define HAVE_STRTOUL 1
|
||||
|
||||
/* Define to 1 if `st_rdev' is member of `struct stat'. */
|
||||
#define HAVE_STRUCT_STAT_ST_RDEV 1
|
||||
|
||||
/* Define to 1 if your `struct stat' has `st_rdev'. Deprecated, use
|
||||
`HAVE_STRUCT_STAT_ST_RDEV' instead. */
|
||||
#define HAVE_ST_RDEV 1
|
||||
|
||||
/* Define to 1 if you have the <syslog.h> header file. */
|
||||
#define HAVE_SYSLOG_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
|
||||
*/
|
||||
/* #undef HAVE_SYS_DIR_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/disk.h> header file. */
|
||||
#define HAVE_SYS_DISK_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/file.h> header file. */
|
||||
#define HAVE_SYS_FILE_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
#define HAVE_SYS_IOCTL_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/mman.h> header file. */
|
||||
#define HAVE_SYS_MMAN_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/mount.h> header file. */
|
||||
/* #undef HAVE_SYS_MOUNT_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
|
||||
*/
|
||||
/* #undef HAVE_SYS_NDIR_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#define HAVE_SYS_PARAM_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/resource.h> header file. */
|
||||
#define HAVE_SYS_RESOURCE_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||
/* #undef HAVE_SYS_SELECT_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
/* #undef HAVE_SYS_SOCKET_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#define HAVE_SYS_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/uio.h> header file. */
|
||||
/* #undef HAVE_SYS_UIO_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/un.h> header file. */
|
||||
/* #undef HAVE_SYS_UN_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/utsname.h> header file. */
|
||||
#define HAVE_SYS_UTSNAME_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/vfs.h> header file. */
|
||||
/* #undef HAVE_SYS_VFS_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/wait.h> header file. */
|
||||
#define HAVE_SYS_WAIT_H 1
|
||||
|
||||
/* Define to 1 if you have the <time.h> header file. */
|
||||
#define HAVE_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the `uname' function. */
|
||||
#define HAVE_UNAME 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have the <utmpx.h> header file. */
|
||||
/* #undef HAVE_UTMPX_H */
|
||||
|
||||
/* Define to 1 if you have the `vfork' function. */
|
||||
#define HAVE_VFORK 1
|
||||
|
||||
/* Define to 1 if you have the <vfork.h> header file. */
|
||||
/* #undef HAVE_VFORK_H */
|
||||
|
||||
/* Define to 1 if you have the `vprintf' function. */
|
||||
#define HAVE_VPRINTF 1
|
||||
|
||||
/* Define to 1 if `fork' works. */
|
||||
#define HAVE_WORKING_FORK 1
|
||||
|
||||
/* Define to 1 if `vfork' works. */
|
||||
#define HAVE_WORKING_VFORK 1
|
||||
|
||||
/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
|
||||
slash. */
|
||||
/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */
|
||||
|
||||
/* Define to 1 if 'lvm' should fall back to using LVM1 binaries if
|
||||
device-mapper is missing from the kernel */
|
||||
/* #undef LVM1_FALLBACK */
|
||||
|
||||
/* Define to 1 to include built-in support for LVM1 metadata. */
|
||||
#define LVM1_INTERNAL 1
|
||||
|
||||
/* Define to 1 to include built-in support for mirrors. */
|
||||
#define MIRRORED_INTERNAL 1
|
||||
|
||||
/* The path to 'modprobe', if available. */
|
||||
#define MODPROBE_CMD "/sbin/ifconfig"
|
||||
|
||||
/* Define to 1 to enable O_DIRECT support. */
|
||||
/* #undef O_DIRECT_SUPPORT */
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME ""
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING ""
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION ""
|
||||
|
||||
/* Define to 1 to include built-in support for GFS pool metadata. */
|
||||
#define POOL_INTERNAL 1
|
||||
|
||||
/* Define to 1 to include the LVM readline shell. */
|
||||
/* #undef READLINE_SUPPORT */
|
||||
|
||||
/* Define as the return type of signal handlers (`int' or `void'). */
|
||||
#define RETSIGTYPE void
|
||||
|
||||
/* Define to the type of arg 1 for `select'. */
|
||||
/* #undef SELECT_TYPE_ARG1 */
|
||||
|
||||
/* Define to the type of args 2, 3 and 4 for `select'. */
|
||||
/* #undef SELECT_TYPE_ARG234 */
|
||||
|
||||
/* Define to the type of arg 5 for `select'. */
|
||||
/* #undef SELECT_TYPE_ARG5 */
|
||||
|
||||
/* Define to 1 to include built-in support for snapshots. */
|
||||
#define SNAPSHOT_INTERNAL 1
|
||||
|
||||
/* If using the C implementation of alloca, define if you know the
|
||||
direction of stack growth for your system; otherwise it will be
|
||||
automatically deduced at run-time.
|
||||
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||
STACK_DIRECTION = 0 => direction of growth unknown */
|
||||
/* #undef STACK_DIRECTION */
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#define TIME_WITH_SYS_TIME 1
|
||||
|
||||
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
|
||||
/* #undef TM_IN_SYS_TIME */
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
/* #undef inline */
|
||||
#endif
|
||||
|
||||
/* Define to rpl_malloc if the replacement function should be used. */
|
||||
/* #undef malloc */
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
/* #undef mode_t */
|
||||
|
||||
/* Define to `long' if <sys/types.h> does not define. */
|
||||
/* #undef off_t */
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
/* #undef pid_t */
|
||||
|
||||
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||
/* #undef size_t */
|
||||
|
||||
/* Define as `fork' if `vfork' does not work. */
|
||||
/* #undef vfork */
|
||||
@@ -333,9 +333,12 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
|
||||
|
||||
if (lv->status & PVMOVE)
|
||||
repstr[0] = 'p';
|
||||
else if (lv->status & MIRRORED)
|
||||
repstr[0] = 'm';
|
||||
else if (lv->status & MIRROR_IMAGE)
|
||||
else if (lv->status & MIRRORED) {
|
||||
if (lv->status & MIRROR_NOTSYNCED)
|
||||
repstr[0] = 'M';
|
||||
else
|
||||
repstr[0] = 'm';
|
||||
}else if (lv->status & MIRROR_IMAGE)
|
||||
repstr[0] = 'i';
|
||||
else if (lv->status & MIRROR_LOG)
|
||||
repstr[0] = 'l';
|
||||
@@ -472,7 +475,8 @@ static int _vgstatus_disp(struct report_handle *rh, struct field *field,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _segtype_disp(struct report_handle *rh, struct field *field,
|
||||
static int _segtype_disp(struct report_handle *rh __attribute((unused)),
|
||||
struct field *field,
|
||||
const void *data)
|
||||
{
|
||||
const struct lv_segment *seg = (const struct lv_segment *) data;
|
||||
|
||||
@@ -27,7 +27,7 @@ static const char *_snap_name(const struct lv_segment *seg)
|
||||
}
|
||||
|
||||
static int _snap_text_import(struct lv_segment *seg, const struct config_node *sn,
|
||||
struct dm_hash_table *pv_hash)
|
||||
struct dm_hash_table *pv_hash __attribute((unused)))
|
||||
{
|
||||
uint32_t chunk_size;
|
||||
const char *org_name, *cow_name;
|
||||
@@ -87,8 +87,10 @@ static int _snap_text_export(const struct lv_segment *seg, struct formatter *f)
|
||||
}
|
||||
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
static int _snap_target_percent(void **target_state, struct dm_pool *mem,
|
||||
struct config_tree *cft, struct lv_segment *seg,
|
||||
static int _snap_target_percent(void **target_state __attribute((unused)),
|
||||
struct dm_pool *mem __attribute((unused)),
|
||||
struct config_tree *cft __attribute((unused)),
|
||||
struct lv_segment *seg __attribute((unused)),
|
||||
char *params, uint64_t *total_numerator,
|
||||
uint64_t *total_denominator, float *percent)
|
||||
{
|
||||
@@ -126,7 +128,7 @@ static int _snap_target_present(void)
|
||||
|
||||
static void _snap_destroy(const struct segment_type *segtype)
|
||||
{
|
||||
dm_free((void *) segtype);
|
||||
dm_free((void *)segtype);
|
||||
}
|
||||
|
||||
static struct segtype_handler _snapshot_ops = {
|
||||
|
||||
@@ -151,11 +151,13 @@ static int _striped_merge_segments(struct lv_segment *seg1, struct lv_segment *s
|
||||
}
|
||||
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
static int _striped_add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
struct config_tree *cft, void **target_state,
|
||||
static int _striped_add_target_line(struct dev_manager *dm,
|
||||
struct dm_pool *mem __attribute((unused)),
|
||||
struct config_tree *cft __attribute((unused)),
|
||||
void **target_state __attribute((unused)),
|
||||
struct lv_segment *seg,
|
||||
struct dm_tree_node *node, uint64_t len,
|
||||
uint32_t *pvmove_mirror_count)
|
||||
uint32_t *pvmove_mirror_count __attribute((unused)))
|
||||
{
|
||||
if (!seg->area_count) {
|
||||
log_error("Internal error: striped add_target_line called "
|
||||
@@ -189,7 +191,7 @@ static int _striped_target_present(void)
|
||||
|
||||
static void _striped_destroy(const struct segment_type *segtype)
|
||||
{
|
||||
dm_free((void *) segtype);
|
||||
dm_free((void *)segtype);
|
||||
}
|
||||
|
||||
static struct segtype_handler _striped_ops = {
|
||||
|
||||
@@ -350,6 +350,7 @@ int dm_tree_node_add_mirror_target(struct dm_tree_node *node,
|
||||
#define DM_NOSYNC 0x00000001 /* Known already in sync */
|
||||
#define DM_FORCESYNC 0x00000002 /* Force resync */
|
||||
#define DM_BLOCK_ON_ERROR 0x00000004 /* On error, suspend I/O */
|
||||
#define DM_CORELOG 0x00000008 /* In-memory log */
|
||||
|
||||
int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
|
||||
uint32_t region_size,
|
||||
|
||||
@@ -1243,8 +1243,8 @@ static int _emit_segment_line(struct dm_task *dmt, struct load_segment *seg, uin
|
||||
log_parm_count += hweight32(seg->flags); /* [no]sync, block_on_error etc. */
|
||||
|
||||
if (seg->clustered) {
|
||||
if (seg->uuid)
|
||||
log_parm_count++; /* uuid */
|
||||
if (seg->uuid && !(seg->flags & DM_CORELOG))
|
||||
log_parm_count++; /* uuid (already counted for core log) */
|
||||
if ((tw = _dm_snprintf(params + pos, paramsize - pos, "clustered_")) < 0) {
|
||||
stack; /* Out of space */
|
||||
return -1;
|
||||
@@ -1701,18 +1701,19 @@ int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
|
||||
seg = list_item(list_last(&node->props.segs), struct load_segment);
|
||||
|
||||
if (log_uuid) {
|
||||
if (!(log_node = dm_tree_find_node_by_uuid(node->dtree, log_uuid))) {
|
||||
log_error("Couldn't find mirror log uuid %s.", log_uuid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_link_tree_nodes(node, log_node))
|
||||
return_0;
|
||||
|
||||
if (!(seg->uuid = dm_pool_strdup(node->dtree->mem, log_uuid))) {
|
||||
log_error("log uuid pool_strdup failed");
|
||||
return 0;
|
||||
}
|
||||
if (!(flags & DM_CORELOG)) {
|
||||
if (!(log_node = dm_tree_find_node_by_uuid(node->dtree, log_uuid))) {
|
||||
log_error("Couldn't find mirror log uuid %s.", log_uuid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_link_tree_nodes(node, log_node))
|
||||
return_0;
|
||||
}
|
||||
}
|
||||
|
||||
seg->log = log_node;
|
||||
|
||||
@@ -44,7 +44,7 @@ can also be chosen.
|
||||
The lv_attr bits are:
|
||||
.RS
|
||||
.IP 1 3
|
||||
Volume type: (m)irrored, (o)rigin, (p)vmove, (s)napshot,
|
||||
Volume type: (m)irrored, (M)irrored without initial sync, (o)rigin, (p)vmove, (s)napshot,
|
||||
invalid (S)napshot, (v)irtual
|
||||
.IP 2 3
|
||||
Permissions: (w)riteable, (r)ead-only
|
||||
|
||||
@@ -45,6 +45,9 @@ arg(type_ARG, '\0', "type", segtype_arg)
|
||||
arg(alloc_ARG, '\0', "alloc", alloc_arg)
|
||||
arg(separator_ARG, '\0', "separator", string_arg)
|
||||
arg(mirrorsonly_ARG, '\0', "mirrorsonly", NULL)
|
||||
arg(nosync_ARG, '\0', "nosync", NULL)
|
||||
arg(corelog_ARG, '\0', "corelog", NULL)
|
||||
arg(monitor_ARG, '\0', "monitor", yes_no_arg)
|
||||
|
||||
/* Allow some variations */
|
||||
arg(resizable_ARG, '\0', "resizable", yes_no_arg)
|
||||
|
||||
@@ -63,6 +63,7 @@ xx(lvchange,
|
||||
"\t[-f|--force]\n"
|
||||
"\t[-h|--help]\n"
|
||||
"\t[--ignorelockingfailure]\n"
|
||||
"\t[--monitor {y|n}]\n"
|
||||
"\t[-M|--persistent y|n] [--major major] [--minor minor]\n"
|
||||
"\t[-P|--partial] " "\n"
|
||||
"\t[-p|--permission r|rw]\n"
|
||||
@@ -74,14 +75,14 @@ xx(lvchange,
|
||||
"\tLogicalVolume[Path] [LogicalVolume[Path]...]\n",
|
||||
|
||||
alloc_ARG, autobackup_ARG, available_ARG, contiguous_ARG, force_ARG,
|
||||
ignorelockingfailure_ARG, major_ARG, minor_ARG, partial_ARG, permission_ARG,
|
||||
persistent_ARG, readahead_ARG, refresh_ARG, addtag_ARG, deltag_ARG,
|
||||
test_ARG)
|
||||
ignorelockingfailure_ARG, major_ARG, minor_ARG, monitor_ARG,
|
||||
partial_ARG, permission_ARG, persistent_ARG, readahead_ARG,
|
||||
refresh_ARG, addtag_ARG, deltag_ARG, test_ARG)
|
||||
|
||||
xx(lvconvert,
|
||||
"Change logical volume layout",
|
||||
"lvconvert "
|
||||
"[-m|--mirrors Mirrors]\n"
|
||||
"[-m|--mirrors Mirrors [--corelog]]\n"
|
||||
"\t[--alloc AllocationPolicy]\n"
|
||||
"\t[-d|--debug]\n"
|
||||
"\t[-h|-?|--help]\n"
|
||||
@@ -99,7 +100,8 @@ xx(lvconvert,
|
||||
"\t[--version]" "\n"
|
||||
"\tOriginalLogicalVolume[Path] SnapshotLogicalVolume[Path]\n",
|
||||
|
||||
alloc_ARG, chunksize_ARG, mirrors_ARG, snapshot_ARG, test_ARG, zero_ARG)
|
||||
alloc_ARG, chunksize_ARG, mirrors_ARG, corelog_ARG,
|
||||
snapshot_ARG, test_ARG, zero_ARG)
|
||||
|
||||
xx(lvcreate,
|
||||
"Create a logical volume",
|
||||
@@ -114,7 +116,7 @@ xx(lvcreate,
|
||||
"\t{-l|--extents LogicalExtentsNumber |\n"
|
||||
"\t -L|--size LogicalVolumeSize[kKmMgGtT]}\n"
|
||||
"\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n"
|
||||
"\t[-m|--mirrors Mirrors]\n"
|
||||
"\t[-m|--mirrors Mirrors [--nosync] [--corelog]]\n"
|
||||
"\t[-n|--name LogicalVolumeName]\n"
|
||||
"\t[-p|--permission {r|rw}]\n"
|
||||
"\t[-r|--readahead ReadAheadSectors]\n"
|
||||
@@ -147,9 +149,10 @@ xx(lvcreate,
|
||||
"\tOriginalLogicalVolume[Path] [PhysicalVolumePath...]\n\n",
|
||||
|
||||
addtag_ARG, alloc_ARG, autobackup_ARG, chunksize_ARG, contiguous_ARG,
|
||||
extents_ARG, major_ARG, minor_ARG, mirrors_ARG, name_ARG, permission_ARG,
|
||||
persistent_ARG, readahead_ARG, regionsize_ARG, size_ARG, snapshot_ARG,
|
||||
stripes_ARG, stripesize_ARG, test_ARG, type_ARG, zero_ARG)
|
||||
corelog_ARG, extents_ARG, major_ARG, minor_ARG, mirrors_ARG, name_ARG,
|
||||
nosync_ARG, permission_ARG, persistent_ARG, readahead_ARG, regionsize_ARG,
|
||||
size_ARG, snapshot_ARG, stripes_ARG, stripesize_ARG, test_ARG, type_ARG,
|
||||
zero_ARG)
|
||||
|
||||
xx(lvdisplay,
|
||||
"Display information about a logical volume",
|
||||
@@ -345,7 +348,7 @@ xx(lvs,
|
||||
"\t[-v|--verbose]\n"
|
||||
"\t[--version]" "\n"
|
||||
"\t[LogicalVolume[Path] [LogicalVolume[Path]...]]\n",
|
||||
|
||||
|
||||
aligned_ARG, all_ARG, ignorelockingfailure_ARG, noheadings_ARG,
|
||||
nolocking_ARG, nosuffix_ARG, options_ARG, partial_ARG, segments_ARG,
|
||||
separator_ARG, sort_ARG, unbuffered_ARG, units_ARG)
|
||||
@@ -492,7 +495,7 @@ xx(pvmove,
|
||||
"\tSourcePhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]}\n"
|
||||
"\t[DestinationPhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]...]\n",
|
||||
|
||||
abort_ARG, alloc_ARG, autobackup_ARG, background_ARG,
|
||||
abort_ARG, alloc_ARG, autobackup_ARG, background_ARG,
|
||||
interval_ARG, name_ARG, test_ARG)
|
||||
|
||||
xx(pvremove,
|
||||
@@ -529,7 +532,7 @@ xx(pvs,
|
||||
"\t[-v|--verbose]\n"
|
||||
"\t[--version]\n"
|
||||
"\t[PhysicalVolume [PhysicalVolume...]]\n",
|
||||
|
||||
|
||||
aligned_ARG, all_ARG, ignorelockingfailure_ARG, noheadings_ARG,
|
||||
nolocking_ARG, nosuffix_ARG, options_ARG, partial_ARG, segments_ARG,
|
||||
separator_ARG, sort_ARG, unbuffered_ARG, units_ARG)
|
||||
@@ -593,6 +596,7 @@ xx(vgchange,
|
||||
"\t[-d|--debug] " "\n"
|
||||
"\t[-h|--help] " "\n"
|
||||
"\t[--ignorelockingfailure]\n"
|
||||
"\t[--monitor {y|n}]\n"
|
||||
"\t[-t|--test]" "\n"
|
||||
"\t[-u|--uuid] " "\n"
|
||||
"\t[-v|--verbose] " "\n"
|
||||
@@ -608,8 +612,8 @@ xx(vgchange,
|
||||
|
||||
addtag_ARG, alloc_ARG, allocation_ARG, autobackup_ARG, available_ARG,
|
||||
clustered_ARG, deltag_ARG, ignorelockingfailure_ARG, logicalvolume_ARG,
|
||||
partial_ARG, physicalextentsize_ARG, resizeable_ARG, resizable_ARG,
|
||||
test_ARG, uuid_ARG)
|
||||
monitor_ARG, partial_ARG, physicalextentsize_ARG, resizeable_ARG,
|
||||
resizable_ARG, test_ARG, uuid_ARG)
|
||||
|
||||
xx(vgck,
|
||||
"Check the consistency of volume group(s)",
|
||||
@@ -820,7 +824,7 @@ xx(vgs,
|
||||
"\t[-v|--verbose]\n"
|
||||
"\t[--version]\n"
|
||||
"\t[VolumeGroupName [VolumeGroupName...]]\n",
|
||||
|
||||
|
||||
aligned_ARG, all_ARG, ignorelockingfailure_ARG, noheadings_ARG,
|
||||
nolocking_ARG, nosuffix_ARG, options_ARG, partial_ARG, separator_ARG,
|
||||
sort_ARG, unbuffered_ARG, units_ARG)
|
||||
@@ -833,7 +837,7 @@ xx(vgscan,
|
||||
"\t[--ignorelockingfailure]\n"
|
||||
"\t[--mknodes]\n"
|
||||
"\t[-P|--partial] " "\n"
|
||||
"\t[-v|--verbose]\n"
|
||||
"\t[-v|--verbose]\n"
|
||||
"\t[--version]" "\n",
|
||||
|
||||
ignorelockingfailure_ARG, mknodes_ARG, partial_ARG)
|
||||
|
||||
@@ -72,6 +72,38 @@ static int lvchange_permission(struct cmd_context *cmd,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lvchange_registration(struct cmd_context *cmd,
|
||||
struct logical_volume *lv)
|
||||
{
|
||||
int r;
|
||||
struct lvinfo info;
|
||||
|
||||
if (!lv_info(cmd, lv, &info, 0) || !info.exists) {
|
||||
log_error("Logical volume, %s, is not active", lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* do not register pvmove lv's */
|
||||
if (lv->status & PVMOVE)
|
||||
return 1;
|
||||
|
||||
log_verbose("%smonitoring logical volume \"%s\"",
|
||||
(dmeventd_register_mode()) ? "" : "Not ", lv->name);
|
||||
r = register_dev_for_events(cmd, lv, dmeventd_register_mode());
|
||||
|
||||
if (r < 0) {
|
||||
log_error("Unable to %smonitor logical volume, %s",
|
||||
(dmeventd_register_mode()) ? "" : "un", lv->name);
|
||||
r = 0;
|
||||
} else if (!r) {
|
||||
log_verbose("Logical volume %s needs no monitoring.",
|
||||
lv->name);
|
||||
r = 1;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int lvchange_availability(struct cmd_context *cmd,
|
||||
struct logical_volume *lv)
|
||||
{
|
||||
@@ -422,6 +454,8 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
init_dmeventd_register(arg_int_value(cmd, monitor_ARG, DEFAULT_DMEVENTD_MONITOR));
|
||||
|
||||
/* access permission change */
|
||||
if (arg_count(cmd, permission_ARG)) {
|
||||
if (!archive(lv->vg))
|
||||
@@ -474,14 +508,22 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
log_print("Logical volume \"%s\" changed", lv->name);
|
||||
|
||||
/* availability change */
|
||||
if (arg_count(cmd, available_ARG))
|
||||
if (arg_count(cmd, available_ARG)) {
|
||||
if (!lvchange_availability(cmd, lv))
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (arg_count(cmd, refresh_ARG))
|
||||
if (!lvchange_refresh(cmd, lv))
|
||||
return ECMD_FAILED;
|
||||
|
||||
if (!arg_count(cmd, available_ARG) &&
|
||||
!arg_count(cmd, refresh_ARG) &&
|
||||
arg_count(cmd, monitor_ARG)) {
|
||||
if (!lvchange_registration(cmd, lv))
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
return ECMD_PROCESSED;
|
||||
}
|
||||
|
||||
@@ -492,9 +534,10 @@ int lvchange(struct cmd_context *cmd, int argc, char **argv)
|
||||
&& !arg_count(cmd, minor_ARG) && !arg_count(cmd, major_ARG)
|
||||
&& !arg_count(cmd, persistent_ARG) && !arg_count(cmd, addtag_ARG)
|
||||
&& !arg_count(cmd, deltag_ARG) && !arg_count(cmd, refresh_ARG)
|
||||
&& !arg_count(cmd, alloc_ARG)) {
|
||||
log_error("One or more of -a, -C, -j, -m, -M, -p, -r, "
|
||||
"--refresh, --alloc, --addtag or --deltag required");
|
||||
&& !arg_count(cmd, alloc_ARG) && !arg_count(cmd, monitor_ARG)) {
|
||||
log_error("Need 1 or more of -a, -C, -j, -m, -M, -p, -r, "
|
||||
"--refresh, --alloc, --addtag, --deltag "
|
||||
"or --monitor");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
|
||||
@@ -235,6 +235,8 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
||||
struct alloc_handle *ah = NULL;
|
||||
struct logical_volume *log_lv;
|
||||
struct list *parallel_areas;
|
||||
struct segment_type *segtype; /* FIXME: could I just use lp->segtype */
|
||||
float sync_percent;
|
||||
|
||||
seg = first_seg(lv);
|
||||
existing_mirrors = seg->area_count;
|
||||
@@ -277,10 +279,71 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
||||
return 0;
|
||||
}
|
||||
if (lp->mirrors == existing_mirrors) {
|
||||
log_error("Logical volume %s already has %"
|
||||
PRIu32 " mirror(s).", lv->name,
|
||||
lp->mirrors - 1);
|
||||
return 1;
|
||||
if (!seg->log_lv && !arg_count(cmd, corelog_ARG)) {
|
||||
/* No disk log present, add one. */
|
||||
/* FIXME: Why doesn't this work? Without
|
||||
it, we will probably put the log on the
|
||||
same device as a mirror leg.
|
||||
if (!(parallel_areas = build_parallel_areas_from_lv(cmd, lv))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
parallel_areas = NULL;
|
||||
if (!lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL)) {
|
||||
log_error("Unable to determine mirror sync status.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
segtype = get_segtype_from_string(cmd, "striped");
|
||||
|
||||
if (!(ah = allocate_extents(lv->vg, NULL, segtype, 1,
|
||||
0, 1, 0,
|
||||
NULL, 0, 0, lp->pvh,
|
||||
lp->alloc,
|
||||
parallel_areas))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sync_percent >= 100.0)
|
||||
init_mirror_in_sync(1);
|
||||
else
|
||||
init_mirror_in_sync(0);
|
||||
|
||||
if (!(log_lv = create_mirror_log(cmd, lv->vg, ah,
|
||||
lp->alloc, lv->name,
|
||||
(sync_percent >= 100.0) ?
|
||||
1 : 0))) {
|
||||
log_error("Failed to create mirror log.");
|
||||
return 0;
|
||||
}
|
||||
seg->log_lv = log_lv;
|
||||
log_lv->status |= MIRROR_LOG;
|
||||
first_seg(log_lv)->mirror_seg = seg;
|
||||
} else if (seg->log_lv && arg_count(cmd, corelog_ARG)) {
|
||||
/* Had disk log, switch to core. */
|
||||
if (!lv_mirror_percent(cmd, lv, 0, &sync_percent, NULL)) {
|
||||
log_error("Unable to determine mirror sync status.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sync_percent >= 100.0)
|
||||
init_mirror_in_sync(1);
|
||||
else
|
||||
init_mirror_in_sync(0);
|
||||
|
||||
if (!remove_mirror_images(seg, lp->mirrors,
|
||||
lp->pv_count ?
|
||||
lp->pvh : NULL, 1))
|
||||
return_0;
|
||||
} else {
|
||||
/* No change */
|
||||
log_error("Logical volume %s already has %"
|
||||
PRIu32 " mirror(s).", lv->name,
|
||||
lp->mirrors - 1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (lp->mirrors > existing_mirrors) {
|
||||
/* FIXME Unless anywhere, remove PV of log_lv
|
||||
@@ -314,7 +377,8 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
||||
return_0;
|
||||
|
||||
if (!(ah = allocate_extents(lv->vg, NULL, lp->segtype,
|
||||
1, lp->mirrors - 1, 1,
|
||||
1, lp->mirrors - 1,
|
||||
arg_count(cmd, corelog_ARG) ? 0 : 1,
|
||||
lv->le_count * (lp->mirrors - 1),
|
||||
NULL, 0, 0, lp->pvh,
|
||||
lp->alloc,
|
||||
@@ -325,9 +389,11 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
||||
lv->le_count,
|
||||
lp->region_size);
|
||||
|
||||
if (!(log_lv = create_mirror_log(cmd, lv->vg, ah,
|
||||
log_lv = NULL;
|
||||
if (!arg_count(cmd, corelog_ARG) &&
|
||||
!(log_lv = create_mirror_log(cmd, lv->vg, ah,
|
||||
lp->alloc,
|
||||
lv->name))) {
|
||||
lv->name, 0))) {
|
||||
log_error("Failed to create mirror log.");
|
||||
return 0;
|
||||
}
|
||||
@@ -390,7 +456,7 @@ static int lvconvert_snapshot(struct cmd_context *cmd,
|
||||
|
||||
if (!lp->zero)
|
||||
log_error("WARNING: \"%s\" not zeroed", lv->name);
|
||||
else if (!zero_lv(cmd, lv)) {
|
||||
else if (!set_lv(cmd, lv, 0)) {
|
||||
log_error("Aborting. Failed to wipe snapshot "
|
||||
"exception store.");
|
||||
return 0;
|
||||
|
||||
@@ -24,6 +24,8 @@ struct lvcreate_params {
|
||||
int zero;
|
||||
int major;
|
||||
int minor;
|
||||
int corelog;
|
||||
int nosync;
|
||||
|
||||
char *origin;
|
||||
const char *vg_name;
|
||||
@@ -291,6 +293,9 @@ static int _read_mirror_params(struct lvcreate_params *lp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
lp->corelog = arg_count(cmd, corelog_ARG) ? 1 : 0;
|
||||
lp->nosync = arg_count(cmd, nosync_ARG) ? 1 : 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -377,6 +382,16 @@ static int _lvcreate_params(struct lvcreate_params *lp, struct cmd_context *cmd,
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (arg_count(cmd, corelog_ARG)) {
|
||||
log_error("--corelog is only available with mirrors");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (arg_count(cmd, nosync_ARG)) {
|
||||
log_error("--nosync is only available with mirrors");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (activation() && lp->segtype->ops->target_present &&
|
||||
@@ -634,9 +649,9 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
/* FIXME Calculate how many extents needed for the log */
|
||||
|
||||
if (!(ah = allocate_extents(vg, NULL, lp->segtype, lp->stripes,
|
||||
lp->mirrors, 1, lp->extents,
|
||||
NULL, 0, 0, pvh, lp->alloc,
|
||||
NULL))) {
|
||||
lp->mirrors, lp->corelog ? 0 : 1,
|
||||
lp->extents, NULL, 0, 0,
|
||||
pvh, lp->alloc, NULL))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -645,8 +660,16 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
lp->extents,
|
||||
lp->region_size);
|
||||
|
||||
init_mirror_in_sync(lp->nosync);
|
||||
|
||||
if (lp->nosync) {
|
||||
log_print("WARNING: New mirror won't be synchronised. "
|
||||
"Don't read what you didn't write!");
|
||||
status |= MIRROR_NOTSYNCED;
|
||||
}
|
||||
|
||||
if (!(log_lv = create_mirror_log(cmd, vg, ah, lp->alloc,
|
||||
lv_name))) {
|
||||
lv_name, lp->nosync))) {
|
||||
log_error("Failed to create mirror log.");
|
||||
return 0;
|
||||
}
|
||||
@@ -730,7 +753,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
}
|
||||
|
||||
if ((lp->zero || lp->snapshot) && activation()) {
|
||||
if (!zero_lv(cmd, lv) && lp->snapshot) {
|
||||
if (!set_lv(cmd, lv, 0) && lp->snapshot) {
|
||||
/* FIXME Remove the failed lv we just added */
|
||||
log_error("Aborting. Failed to wipe snapshot "
|
||||
"exception store. Remove new LV and retry.");
|
||||
|
||||
@@ -713,6 +713,8 @@ static int _get_settings(struct cmd_context *cmd)
|
||||
!_merge_synonym(cmd, allocation_ARG, resizeable_ARG))
|
||||
return EINVALID_CMD_LINE;
|
||||
|
||||
init_mirror_in_sync(0);
|
||||
|
||||
/* Zero indicates success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name)
|
||||
(yes_no_prompt("Software RAID md superblock "
|
||||
"detected on %s. Wipe it? [y/n] ", name) == 'y'))) {
|
||||
log_print("Wiping software RAID md superblock on %s", name);
|
||||
if (!dev_zero(dev, md_superblock, 4)) {
|
||||
if (!dev_set(dev, md_superblock, 4, 0)) {
|
||||
log_error("Failed to wipe RAID md superblock on %s",
|
||||
name);
|
||||
return 0;
|
||||
@@ -225,7 +225,7 @@ static int pvcreate_single(struct cmd_context *cmd, const char *pv_name,
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!dev_zero(dev, UINT64_C(0), (size_t) 2048)) {
|
||||
if (!dev_set(dev, UINT64_C(0), (size_t) 2048, 0)) {
|
||||
log_error("%s not wiped: aborting", pv_name);
|
||||
dev_close(dev);
|
||||
goto error;
|
||||
|
||||
@@ -15,10 +15,15 @@
|
||||
|
||||
#include "tools.h"
|
||||
#include "lv_alloc.h"
|
||||
#include "xlate.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
/* From linux/drivers/md/dm-log.c */
|
||||
#define MIRROR_MAGIC 0x4D695272
|
||||
#define MIRROR_DISK_VERSION 2
|
||||
|
||||
/* Command line args */
|
||||
unsigned arg_count(struct cmd_context *cmd, int a)
|
||||
{
|
||||
@@ -1111,9 +1116,9 @@ int generate_log_name_format(struct volume_group *vg __attribute((unused)),
|
||||
}
|
||||
|
||||
/*
|
||||
* Volumes may be zeroed to remove old application data.
|
||||
* Initialize the LV with 'value'.
|
||||
*/
|
||||
int zero_lv(struct cmd_context *cmd, struct logical_volume *lv)
|
||||
int set_lv(struct cmd_context *cmd, struct logical_volume *lv, int value)
|
||||
{
|
||||
struct device *dev;
|
||||
char *name;
|
||||
@@ -1126,27 +1131,80 @@ int zero_lv(struct cmd_context *cmd, struct logical_volume *lv)
|
||||
* (I know the device is at least 4k, but not 32k)
|
||||
*/
|
||||
if (!(name = dm_pool_alloc(cmd->mem, PATH_MAX))) {
|
||||
log_error("Name allocation failed - device not zeroed");
|
||||
log_error("Name allocation failed - device not cleared");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(name, PATH_MAX, "%s%s/%s", cmd->dev_dir,
|
||||
lv->vg->name, lv->name) < 0) {
|
||||
log_error("Name too long - device not zeroed (%s)", lv->name);
|
||||
log_error("Name too long - device not cleared (%s)", lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_verbose("Zeroing start of logical volume \"%s\"", lv->name);
|
||||
log_verbose("Clearing start of logical volume \"%s\"", lv->name);
|
||||
|
||||
if (!(dev = dev_cache_get(name, NULL))) {
|
||||
log_error("%s: not found: device not zeroed", name);
|
||||
log_error("%s: not found: device not cleared", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dev_open_quiet(dev))
|
||||
return 0;
|
||||
|
||||
dev_zero(dev, UINT64_C(0), (size_t) 4096);
|
||||
dev_set(dev, UINT64_C(0), (size_t) 4096, value);
|
||||
dev_close_immediate(dev);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function writes a new header to the mirror log header to the lv
|
||||
*
|
||||
* Returns: 1 on success, 0 on failure
|
||||
*/
|
||||
static int _write_log_header(struct cmd_context *cmd, struct logical_volume *lv)
|
||||
{
|
||||
struct device *dev;
|
||||
char *name;
|
||||
struct { /* The mirror log header */
|
||||
uint32_t magic;
|
||||
uint32_t version;
|
||||
uint64_t nr_regions;
|
||||
} log_header;
|
||||
|
||||
log_header.magic = xlate32(MIRROR_MAGIC);
|
||||
log_header.version = xlate32(MIRROR_DISK_VERSION);
|
||||
log_header.nr_regions = xlate64((uint64_t)-1);
|
||||
|
||||
if (!(name = dm_pool_alloc(cmd->mem, PATH_MAX))) {
|
||||
log_error("Name allocation failed - log header not written (%s)",
|
||||
lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(name, PATH_MAX, "%s%s/%s", cmd->dev_dir,
|
||||
lv->vg->name, lv->name) < 0) {
|
||||
log_error("Name too long - log header not written (%s)", lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_verbose("Writing log header to device, %s", lv->name);
|
||||
|
||||
if (!(dev = dev_cache_get(name, NULL))) {
|
||||
log_error("%s: not found: log header not written", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dev_open_quiet(dev))
|
||||
return 0;
|
||||
|
||||
if (!dev_write(dev, UINT64_C(0), sizeof(log_header), &log_header)) {
|
||||
log_error("Failed to write log header to %s", name);
|
||||
dev_close_immediate(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_close_immediate(dev);
|
||||
|
||||
return 1;
|
||||
@@ -1156,7 +1214,8 @@ struct logical_volume *create_mirror_log(struct cmd_context *cmd,
|
||||
struct volume_group *vg,
|
||||
struct alloc_handle *ah,
|
||||
alloc_policy_t alloc,
|
||||
const char *lv_name)
|
||||
const char *lv_name,
|
||||
int in_sync)
|
||||
{
|
||||
struct logical_volume *log_lv;
|
||||
char *log_name;
|
||||
@@ -1201,12 +1260,18 @@ struct logical_volume *create_mirror_log(struct cmd_context *cmd,
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (activation() && !zero_lv(cmd, log_lv)) {
|
||||
if (activation() && !set_lv(cmd, log_lv, in_sync)) {
|
||||
log_error("Aborting. Failed to wipe mirror log. "
|
||||
"Remove new LV and retry.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!_write_log_header(cmd, log_lv)) {
|
||||
log_error("Aborting. Failed to write mirror log header. "
|
||||
"Remove new LV and retry.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!deactivate_lv(cmd, log_lv)) {
|
||||
log_error("Aborting. Failed to deactivate mirror log. "
|
||||
"Remove new LV and retry.");
|
||||
|
||||
@@ -97,8 +97,9 @@ struct logical_volume *create_mirror_log(struct cmd_context *cmd,
|
||||
struct volume_group *vg,
|
||||
struct alloc_handle *ah,
|
||||
alloc_policy_t alloc,
|
||||
const char *lv_name);
|
||||
const char *lv_name,
|
||||
int in_sync);
|
||||
|
||||
int zero_lv(struct cmd_context *cmd, struct logical_volume *lv);
|
||||
int set_lv(struct cmd_context *cmd, struct logical_volume *lv, int value);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,6 +15,51 @@
|
||||
|
||||
#include "tools.h"
|
||||
|
||||
static int _register_lvs_in_vg(struct cmd_context *cmd,
|
||||
struct volume_group *vg, int reg)
|
||||
{
|
||||
struct lv_list *lvl;
|
||||
struct logical_volume *lv;
|
||||
struct lvinfo info;
|
||||
int lv_active;
|
||||
int count = 0;
|
||||
int r;
|
||||
|
||||
list_iterate_items(lvl, &vg->lvs) {
|
||||
lv = lvl->lv;
|
||||
|
||||
if (!lv_info(cmd, lv, &info, 0))
|
||||
lv_active = 0;
|
||||
else
|
||||
lv_active = info.exists;
|
||||
|
||||
/*
|
||||
* FIXME: Need to consider all cases... PVMOVE, etc
|
||||
*/
|
||||
if ((lv->status & PVMOVE) || !lv_active)
|
||||
continue;
|
||||
|
||||
r = register_dev_for_events(cmd, lv, reg);
|
||||
|
||||
if (r < 0) {
|
||||
log_error("Failed to %s logical volume, %s",
|
||||
(reg) ? "register" : "unregister",
|
||||
lv->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (r)
|
||||
count++;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the number of monitored devices, not the number
|
||||
* of _new_ monitored devices
|
||||
*/
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int _activate_lvs_in_vg(struct cmd_context *cmd,
|
||||
struct volume_group *vg, int activate)
|
||||
{
|
||||
@@ -65,9 +110,23 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd,
|
||||
return count;
|
||||
}
|
||||
|
||||
static int _vgchange_monitoring(struct cmd_context *cmd, struct volume_group *vg)
|
||||
{
|
||||
int active, monitored;
|
||||
|
||||
if ((active = lvs_in_vg_activated(vg))) {
|
||||
monitored = _register_lvs_in_vg(cmd, vg, dmeventd_register_mode());
|
||||
log_print("%d logical volume(s) in volume group "
|
||||
"\"%s\" now %smonitored",
|
||||
monitored, vg->name, (dmeventd_register_mode()) ? "" : "un");
|
||||
}
|
||||
|
||||
return ECMD_PROCESSED;
|
||||
}
|
||||
|
||||
static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg)
|
||||
{
|
||||
int lv_open, active;
|
||||
int lv_open, active, monitored;
|
||||
int available;
|
||||
int activate = 1;
|
||||
|
||||
@@ -93,9 +152,15 @@ static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg)
|
||||
if (activate && !lockingfailed())
|
||||
check_current_backup(vg);
|
||||
|
||||
if (activate && (active = lvs_in_vg_activated(vg)))
|
||||
if (activate && (active = lvs_in_vg_activated(vg))) {
|
||||
log_verbose("%d logical volume(s) in volume group \"%s\" "
|
||||
"already active", active, vg->name);
|
||||
monitored = _register_lvs_in_vg(cmd, vg, dmeventd_register_mode());
|
||||
log_verbose("%d existing logical volume(s) in volume "
|
||||
"group \"%s\" now %smonitored",
|
||||
monitored, vg->name,
|
||||
dmeventd_register_mode() ? "" : "un");
|
||||
}
|
||||
|
||||
if (activate && _activate_lvs_in_vg(cmd, vg, available))
|
||||
log_verbose("Activated logical volumes in "
|
||||
@@ -429,9 +494,14 @@ static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
init_dmeventd_register(arg_int_value(cmd, monitor_ARG, DEFAULT_DMEVENTD_MONITOR));
|
||||
|
||||
if (arg_count(cmd, available_ARG))
|
||||
r = _vgchange_available(cmd, vg);
|
||||
|
||||
else if (arg_count(cmd, monitor_ARG))
|
||||
r = _vgchange_monitoring(cmd, vg);
|
||||
|
||||
else if (arg_count(cmd, resizeable_ARG))
|
||||
r = _vgchange_resizeable(cmd, vg);
|
||||
|
||||
@@ -466,7 +536,8 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
|
||||
arg_count(cmd, resizeable_ARG) + arg_count(cmd, deltag_ARG) +
|
||||
arg_count(cmd, addtag_ARG) + arg_count(cmd, uuid_ARG) +
|
||||
arg_count(cmd, physicalextentsize_ARG) +
|
||||
arg_count(cmd, clustered_ARG) + arg_count(cmd, alloc_ARG))) {
|
||||
arg_count(cmd, clustered_ARG) + arg_count(cmd, alloc_ARG) +
|
||||
arg_count(cmd, monitor_ARG))) {
|
||||
log_error("One of -a, -c, -l, -s, -x, --uuid, --alloc, --addtag or "
|
||||
"--deltag required");
|
||||
return EINVALID_CMD_LINE;
|
||||
|
||||
@@ -125,7 +125,7 @@ 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)) {
|
||||
if (pv_uses_vg(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);
|
||||
@@ -134,7 +134,7 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
|
||||
}
|
||||
|
||||
list_iterate_items(pvl, &vg_from->pvs) {
|
||||
if (pv_uses_vg(cmd, pvl->pv, vg_to)) {
|
||||
if (pv_uses_vg(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);
|
||||
|
||||
@@ -111,7 +111,13 @@ static int _remove_lv(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
* and add to list of LVs to be removed later.
|
||||
* Doesn't apply to snapshots/origins yet - they're already deactivated.
|
||||
*/
|
||||
if (lv_info(cmd, lv, &info, 0) && info.exists) {
|
||||
/*
|
||||
* If the LV is a part of mirror segment,
|
||||
* the mirrored LV also should be cleaned up.
|
||||
* Clean-up is currently done by caller (_make_vg_consistent()).
|
||||
*/
|
||||
if ((lv_info(cmd, lv, &info, 0) && info.exists)
|
||||
|| first_seg(lv)->mirror_seg) {
|
||||
extents = lv->le_count;
|
||||
mirror_seg = first_seg(lv)->mirror_seg;
|
||||
if (!lv_empty(lv)) {
|
||||
@@ -158,7 +164,7 @@ static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg)
|
||||
struct lv_segment *seg, *mirrored_seg;
|
||||
struct lv_segment_area area;
|
||||
unsigned s;
|
||||
uint32_t mimages;
|
||||
uint32_t mimages, remove_log;
|
||||
int list_unsafe, only_mirror_images_found;
|
||||
LIST_INIT(lvs_changed);
|
||||
only_mirror_images_found = 1;
|
||||
@@ -259,7 +265,10 @@ static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg)
|
||||
mirrored_seg = first_seg(lvl->lv);
|
||||
if (!seg_is_mirrored(mirrored_seg))
|
||||
continue;
|
||||
|
||||
mimages = mirrored_seg->area_count;
|
||||
remove_log = 0;
|
||||
|
||||
for (s = 0; s < mirrored_seg->area_count; s++) {
|
||||
list_iterate_items_safe(lvl2, lvlt, &lvs_changed) {
|
||||
if (seg_type(mirrored_seg, s) != AREA_LV ||
|
||||
@@ -272,8 +281,24 @@ static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg)
|
||||
mimages--; /* FIXME Assumes uniqueness */
|
||||
}
|
||||
}
|
||||
if (mimages != mirrored_seg->area_count) {
|
||||
if (!remove_mirror_images(mirrored_seg, mimages, NULL, 0)) {
|
||||
|
||||
if (mirrored_seg->log_lv) {
|
||||
list_iterate_items(seg, &mirrored_seg->log_lv->segments) {
|
||||
/* FIXME: The second test shouldn't be required */
|
||||
if ((seg->segtype ==
|
||||
get_segtype_from_string(vg->cmd, "error")) ||
|
||||
(!strcmp(seg->segtype->name, "error"))) {
|
||||
log_print("The log device for %s/%s has failed.",
|
||||
vg->name, mirrored_seg->lv->name);
|
||||
remove_log = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((mimages != mirrored_seg->area_count) || (remove_log)){
|
||||
if (!reconfigure_mirror_images(mirrored_seg, mimages,
|
||||
NULL, remove_log)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -295,14 +320,20 @@ static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg)
|
||||
|
||||
/* Deactivate error LVs */
|
||||
if (!test_mode()) {
|
||||
list_iterate_items(lvl, &lvs_changed) {
|
||||
list_iterate_items_safe(lvl, lvlt, &lvs_changed) {
|
||||
log_verbose("Deactivating (if active) logical volume %s",
|
||||
lvl->lv->name);
|
||||
|
||||
if (!deactivate_lv(cmd, lvl->lv)) {
|
||||
log_error("Failed to deactivate LV %s",
|
||||
lvl->lv->name);
|
||||
return 0;
|
||||
/*
|
||||
* We failed to deactivate.
|
||||
* Probably because this was a mirror log.
|
||||
* Don't try to lv_remove it.
|
||||
* Continue work on others.
|
||||
*/
|
||||
list_del(&lvl->list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user