summaryrefslogtreecommitdiff
path: root/libdm/libdm-deptree.c
diff options
context:
space:
mode:
authorHeinz Mauelshagen <heinzm@redhat.com>2017-03-21 18:17:42 +0100
committerHeinz Mauelshagen <heinzm@redhat.com>2017-03-21 18:17:42 +0100
commit1e4462dbfbd2bbe3590936df24b3ccd83110b158 (patch)
tree99fd297e0b12b96585b66e5f105c8fed1dd55ec8 /libdm/libdm-deptree.c
parent642d682d8ddcc3152f68b3ec8518902a0ef448ac (diff)
downloadlvm2-1e4462dbfbd2bbe3590936df24b3ccd83110b158.tar.gz
raid: adjust to misordered raid table line output
The libdevmapper interface compares existing table line retrieved from the kernel to new table line created to decide if it can suppress a reload. Any difference between input and output of the table line is taken to be a change thus causing a table reload. The dm-raid target started to misorder the raid parameters (e.g. 'raid10_copies') starting with dm-raid target version 1.9.0 up to (excluding) 1.11.0. This causes runtime failures (limited to raid10 as of tests) and needs to be reversed to allow e.g. old lvm2 uspace to run properly. Check for the aforementioned version range and adjust creation of the table line to the respective (mis)ordered sequence inside and correct order outside the range (as described for the raid target in the kernels Documentation/device-mapper/dm-raid.txt).
Diffstat (limited to 'libdm/libdm-deptree.c')
-rw-r--r--libdm/libdm-deptree.c102
1 files changed, 70 insertions, 32 deletions
diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c
index 832d8de36..2dced75da 100644
--- a/libdm/libdm-deptree.c
+++ b/libdm/libdm-deptree.c
@@ -2432,46 +2432,84 @@ static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
EMIT_PARAMS(pos, " raid10_format offset");
#endif
- if (seg->data_copies > 1 && type == SEG_RAID10)
- EMIT_PARAMS(pos, " raid10_copies %u", seg->data_copies);
+ if (seg->flags & DM_RAID_TABLE_ORDERED) {
+ /* Emit order of paramters as of kernel target documentation */
+ if (seg->flags & DM_NOSYNC)
+ EMIT_PARAMS(pos, " nosync");
+ else if (seg->flags & DM_FORCESYNC)
+ EMIT_PARAMS(pos, " sync");
- if (seg->flags & DM_NOSYNC)
- EMIT_PARAMS(pos, " nosync");
- else if (seg->flags & DM_FORCESYNC)
- EMIT_PARAMS(pos, " sync");
+ for (i = 0; i < area_count; i++)
+ if (seg->rebuilds[i/64] & (1ULL << (i%64)))
+ EMIT_PARAMS(pos, " rebuild %u", i);
- if (seg->region_size)
- EMIT_PARAMS(pos, " region_size %u", seg->region_size);
+ if (seg->min_recovery_rate)
+ EMIT_PARAMS(pos, " min_recovery_rate %u",
+ seg->min_recovery_rate);
- /* If seg-data_offset == 1, kernel needs a zero offset to adjust to it */
- if (seg->data_offset)
- EMIT_PARAMS(pos, " data_offset %d", seg->data_offset == 1 ? 0 : seg->data_offset);
+ if (seg->max_recovery_rate)
+ EMIT_PARAMS(pos, " max_recovery_rate %u",
+ seg->max_recovery_rate);
- if (seg->delta_disks)
- EMIT_PARAMS(pos, " delta_disks %d", seg->delta_disks);
+ for (i = 0; i < area_count; i++)
+ if (seg->writemostly[i/64] & (1ULL << (i%64)))
+ EMIT_PARAMS(pos, " write_mostly %u", i);
- for (i = 0; i < area_count; i++)
- if (seg->rebuilds[i/64] & (1ULL << (i%64)))
- EMIT_PARAMS(pos, " rebuild %u", i);
+ if (seg->writebehind)
+ EMIT_PARAMS(pos, " max_write_behind %u", seg->writebehind);
- for (i = 0; i < area_count; i++)
- if (seg->writemostly[i/64] & (1ULL << (i%64)))
- EMIT_PARAMS(pos, " write_mostly %u", i);
+ if (seg->region_size)
+ EMIT_PARAMS(pos, " region_size %u", seg->region_size);
- if (seg->writebehind)
- EMIT_PARAMS(pos, " max_write_behind %u", seg->writebehind);
+ if (seg->data_copies > 1 && type == SEG_RAID10)
+ EMIT_PARAMS(pos, " raid10_copies %u", seg->data_copies);
- /*
- * Has to be before "min_recovery_rate" or the kernels
- * check will fail when both set and min > previous max
- */
- if (seg->max_recovery_rate)
- EMIT_PARAMS(pos, " max_recovery_rate %u",
- seg->max_recovery_rate);
+ if (seg->delta_disks)
+ EMIT_PARAMS(pos, " delta_disks %d", seg->delta_disks);
+
+ /* If seg-data_offset == 1, kernel needs a zero offset to adjust to it */
+ if (seg->data_offset)
+ EMIT_PARAMS(pos, " data_offset %d", seg->data_offset == 1 ? 0 : seg->data_offset);
+
+ } else {
+ /* Target version >= 1.9.0 && < 1.11.0 had a table line parameter ordering flaw */
+ if (seg->data_copies > 1 && type == SEG_RAID10)
+ EMIT_PARAMS(pos, " raid10_copies %u", seg->data_copies);
+
+ if (seg->flags & DM_NOSYNC)
+ EMIT_PARAMS(pos, " nosync");
+ else if (seg->flags & DM_FORCESYNC)
+ EMIT_PARAMS(pos, " sync");
- if (seg->min_recovery_rate)
- EMIT_PARAMS(pos, " min_recovery_rate %u",
- seg->min_recovery_rate);
+ if (seg->region_size)
+ EMIT_PARAMS(pos, " region_size %u", seg->region_size);
+
+ /* If seg-data_offset == 1, kernel needs a zero offset to adjust to it */
+ if (seg->data_offset)
+ EMIT_PARAMS(pos, " data_offset %d", seg->data_offset == 1 ? 0 : seg->data_offset);
+
+ if (seg->delta_disks)
+ EMIT_PARAMS(pos, " delta_disks %d", seg->delta_disks);
+
+ for (i = 0; i < area_count; i++)
+ if (seg->rebuilds[i/64] & (1ULL << (i%64)))
+ EMIT_PARAMS(pos, " rebuild %u", i);
+
+ for (i = 0; i < area_count; i++)
+ if (seg->writemostly[i/64] & (1ULL << (i%64)))
+ EMIT_PARAMS(pos, " write_mostly %u", i);
+
+ if (seg->writebehind)
+ EMIT_PARAMS(pos, " max_write_behind %u", seg->writebehind);
+
+ if (seg->max_recovery_rate)
+ EMIT_PARAMS(pos, " max_recovery_rate %u",
+ seg->max_recovery_rate);
+
+ if (seg->min_recovery_rate)
+ EMIT_PARAMS(pos, " min_recovery_rate %u",
+ seg->min_recovery_rate);
+ }
/* Print number of metadata/data device pairs */
EMIT_PARAMS(pos, " %u", area_count);
@@ -2742,7 +2780,7 @@ static int _emit_segment(struct dm_task *dmt, uint32_t major, uint32_t minor,
struct load_segment *seg, uint64_t *seg_start)
{
char *params;
- size_t paramsize = 4096;
+ size_t paramsize = 4096; /* FIXME: too small for long RAID lines when > 64 devices supported */
int ret;
do {