1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

RAID: Code changes missing from previous commit (bbc6378)

Previous commit included changes to WHATSNEW, but the code changes
were missing.  Here is the description from the previous commit:
commit bbc6378b73
Author: Jonathan Brassow <jbrassow@redhat.com>
Date:   Thu Feb 21 11:31:36 2013 -0600

    RAID:  Make 'lvchange --refresh' restore transiently failed RAID PVs

    A new function (dm_tree_node_force_identical_table_reload) was added to
    avoid the suppression of identical table reloads.  This allows RAID LVs
    to reload the on-disk superblock information that contains which devices
    have failed and the bitmaps.  If the failed device has returned, this has
    the effect of restoring the device and initiating recovery.  Without this
    patch, the user had to completely deactivate their RAID LV and re-activate
    it in order to restore the failed device.  Now they simply need to
    suspend and resume (which is done by 'lvchange --refresh').

    The identical table suppression is only avoided if the LV is not PARTAIL
    (i.e. all of it's devices can be seen and read by LVM) and the kernel
    status of the array contains failed devices.  In other words, the function
    will only be called in the case where we may have success in restoring
    a failed device in the array.
This commit is contained in:
Jonathan Brassow 2013-03-06 10:17:11 -06:00
parent ed6f3945fd
commit 31c24dd9f2
3 changed files with 36 additions and 2 deletions

View File

@ -161,6 +161,7 @@ static int _raid_add_target_line(struct dev_manager *dm __attribute__((unused)),
uint32_t s; uint32_t s;
uint64_t flags = 0; uint64_t flags = 0;
uint64_t rebuilds = 0; uint64_t rebuilds = 0;
char *raid_health = NULL;
if (!seg->area_count) { if (!seg->area_count) {
log_error(INTERNAL_ERROR "_raid_add_target_line called " log_error(INTERNAL_ERROR "_raid_add_target_line called "
@ -190,6 +191,20 @@ static int _raid_add_target_line(struct dev_manager *dm __attribute__((unused)),
if (mirror_in_sync()) if (mirror_in_sync())
flags = DM_NOSYNC; flags = DM_NOSYNC;
/*
* If the RAID LV is not 'PARTIAL' and the status indicates
* that the array has failed devices, it means that the
* failed devices have returned and can be reintegrated.
*
* We reload the (potentially identical) table to force the
* kernel to re-read the RAID superblocks - possibly restoring
* transiently failed devices.
*/
if (!(seg->lv->status & PARTIAL_LV) &&
lv_raid_dev_health(seg->lv, &raid_health) &&
strchr(raid_health, 'D'))
dm_tree_node_force_identical_table_reload(node);
if (!dm_tree_node_add_raid_target(node, len, _raid_name(seg), if (!dm_tree_node_add_raid_target(node, len, _raid_name(seg),
seg->region_size, seg->stripe_size, seg->region_size, seg->stripe_size,
rebuilds, flags)) rebuilds, flags))

View File

@ -491,13 +491,14 @@ struct dm_tree_node *dm_tree_next_child(void **handle,
uint32_t inverted); uint32_t inverted);
/* /*
* Get properties of a node. * Get and set properties of a node.
*/ */
const char *dm_tree_node_get_name(const struct dm_tree_node *node); const char *dm_tree_node_get_name(const struct dm_tree_node *node);
const char *dm_tree_node_get_uuid(const struct dm_tree_node *node); const char *dm_tree_node_get_uuid(const struct dm_tree_node *node);
const struct dm_info *dm_tree_node_get_info(const struct dm_tree_node *node); const struct dm_info *dm_tree_node_get_info(const struct dm_tree_node *node);
void *dm_tree_node_get_context(const struct dm_tree_node *node); void *dm_tree_node_get_context(const struct dm_tree_node *node);
int dm_tree_node_size_changed(const struct dm_tree_node *dnode); int dm_tree_node_size_changed(const struct dm_tree_node *dnode);
int dm_tree_node_force_identical_table_reload(struct dm_tree_node *dnode);
/* /*
* Returns the number of children of the given node (excluding the root node). * Returns the number of children of the given node (excluding the root node).

View File

@ -232,6 +232,16 @@ struct load_properties {
/* Send messages for this node in preload */ /* Send messages for this node in preload */
unsigned send_messages; unsigned send_messages;
/*
* If a mapping table is replacing an existing identical table,
* the load is suppressed by default - avoiding the construction
* of an unnecessary in-kernel table. Sometimes we want to avoid
* this optimization and load the identical table anyway. This
* field is used to indicate that we desire identical tables to be
* loaded and not suppressed.
*/
unsigned force_identical_table_reload;
}; };
/* Two of these used to join two nodes with uses and used_by. */ /* Two of these used to join two nodes with uses and used_by. */
@ -587,6 +597,13 @@ int dm_tree_node_size_changed(const struct dm_tree_node *dnode)
return dnode->props.size_changed; return dnode->props.size_changed;
} }
int dm_tree_node_force_identical_table_reload(struct dm_tree_node *dnode)
{
dnode->props.force_identical_table_reload = 1;
return 1;
}
int dm_tree_node_num_children(const struct dm_tree_node *node, uint32_t inverted) int dm_tree_node_num_children(const struct dm_tree_node *node, uint32_t inverted)
{ {
if (inverted) { if (inverted) {
@ -2409,7 +2426,8 @@ static int _load_node(struct dm_tree_node *dnode)
seg, &seg_start)) seg, &seg_start))
goto_out; goto_out;
if (!dm_task_suppress_identical_reload(dmt)) if (!dnode->props.force_identical_table_reload &&
!dm_task_suppress_identical_reload(dmt))
log_error("Failed to suppress reload of identical tables."); log_error("Failed to suppress reload of identical tables.");
if ((r = dm_task_run(dmt))) { if ((r = dm_task_run(dmt))) {