]> sourceware.org Git - lvm2.git/commitdiff
lvdisplay: enhance LV status output for raid(0)
authorHeinz Mauelshagen <heinzm@redhat.com>
Tue, 26 Jan 2021 18:32:24 +0000 (19:32 +0100)
committerHeinz Mauelshagen <heinzm@redhat.com>
Wed, 27 Jan 2021 15:56:22 +0000 (16:56 +0100)
In case legs of a raid0 LV are removed, the lvdisplay command still
reports 'available' though raid0 is not providing any resilience
compared to the other raid levels.

Also lvdisplay does not display '(partial)' in case of missing raid0
legs as oposed to the lvs command.

Enhance lvdisplay to report "NOT available" for any RaidLV type in case
too many legs are inaccessible hence causing data loss.  I.e. any leg
for raid0, all for raid1, more than 1 for raid4/5, more than 2 for raid6
and in case of completely lost mirror groups for raid10.

Add test/shell/lvdisplay-raid.sh.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1872678

WHATS_NEW
lib/display/display.c
lib/metadata/metadata-exported.h
lib/metadata/segtype.h
lib/raid/raid.c
test/shell/lvdisplay-raid.sh [new file with mode: 0644]

index 9fda1de87d146d61a1286a30371017d5aad76982..ef1afaabd587fd0cae73d2c02f79b0542c52fbfd 100644 (file)
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
 Version 2.03.12 - 
 ===================================
+  Enhance lvdisplay to report raid availiable/partial.
   Support online rename of VDO pools.
   Imporove removal of pmspare when last pool is removed.
   Fix problem with wiping of converted LVs.
index c0224edfb27ad096faf1677c73ba29902d1bef61..a846953934fac1249b3fc12ea8dc5b962af4936e 100644 (file)
@@ -399,7 +399,7 @@ int lvdisplay_full(struct cmd_context *cmd,
                   void *handle __attribute__((unused)))
 {
        struct lvinfo info;
-       int inkernel, snap_active = 0;
+       int inkernel, snap_active = 0, partial = 0, raid_is_avail = 1;
        char uuid[64] __attribute__((aligned(8)));
        const char *access_str;
        struct lv_segment *snap_seg = NULL, *mirror_seg = NULL;
@@ -558,11 +558,18 @@ int lvdisplay_full(struct cmd_context *cmd,
                log_print("LV VDO Pool name       %s", seg_lv(seg, 0)->name);
        }
 
+       if (lv_is_partial(lv))
+               partial = 1;
+
+       if (lv_is_raid(lv))
+               raid_is_avail = raid_is_available(lv) ? 1 : 0;
+
        if (inkernel && info.suspended)
                log_print("LV Status              suspended");
        else if (activation())
-               log_print("LV Status              %savailable",
-                         inkernel ? "" : "NOT ");
+               log_print("LV Status              %savailable%s",
+                         (inkernel && raid_is_avail) ? "" : "NOT ",
+                         partial ? " (partial)" : "");
 
 /********* FIXME lv_number
     log_print("LV #                   %u", lv->lv_number + 1);
index 54dc29ffe2d64f7381826cdbfa87a27147416701..bf58b9fb217b1240c5c095542f76ddfb36d16e9c 100644 (file)
@@ -26,6 +26,7 @@
 #include "lib/metadata/vg.h"
 #include "lib/metadata/lv.h"
 #include "lib/misc/lvm-percent.h"
+#include <stdbool.h>
 
 #define MAX_STRIPES 128U
 #define SECTOR_SHIFT 9L
index 2714a6b4508857a364d129ece592913a999018f3..676f37e3ce4e3b17ea0057501cbdc2243395be93 100644 (file)
@@ -326,6 +326,7 @@ struct segment_type *init_unknown_segtype(struct cmd_context *cmd,
 
 #ifdef RAID_INTERNAL
 int init_raid_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);
+bool raid_is_available(const struct logical_volume *lv);
 #endif
 
 #define THIN_FEATURE_DISCARDS                  (1U << 0)
index a72e486e981e1f566fea477ff23a5b532bfdecad..126b22d4323e2adcda947cebed2b78b76e4278b7 100644 (file)
@@ -469,6 +469,63 @@ static int _check_feature(const struct raid_feature *feature, uint32_t maj, uint
               (maj == feature->maj && min == feature->min && patchlevel >= feature->patchlevel);
 }
 
+/* Check availability of raid10 taking data copies into consideration. */
+static bool _raid10_is_available(const struct logical_volume *lv)
+{
+       uint32_t i, rebuilds_per_group, s;
+       const uint32_t copies = 2; /* FIXME: we only support 2-way mirrors (i.e. 2 data copies) in RAID10 for now. */
+       struct lv_segment *seg = first_seg(lv); /* We only have one segment in RaidLVs for now. */
+
+       for (i = 0; i < seg->area_count * copies; ++i) {
+               s = i % seg->area_count;
+
+               if (!(i % copies))
+                       rebuilds_per_group = 0;
+
+               if (seg_type(seg, s) == AREA_LV &&
+                   (lv_is_partial(seg_lv(seg, s)) ||
+                    lv_is_virtual(seg_lv(seg, s))))
+                       rebuilds_per_group++;
+
+               if (rebuilds_per_group >= copies)
+                       return false;
+       }
+
+       return true;
+}
+
+/*
+ * Return true in case RaidLV with specific RAID level is available.
+ *
+ * - raid0: all legs have to be live
+ * - raid1 : minimum of 1 leg live
+ * - raid4/5: maximum of 1 leg unavailable
+ * - raid6:  maximum of 2 legs unavailable
+ * - raid10: minimum of 1 leg per mirror group available
+ *
+ */
+bool raid_is_available(const struct logical_volume *lv)
+{
+       uint32_t s, missing_legs = 0;
+       struct lv_segment *seg = first_seg(lv); /* We only have one segment in RaidLVs for now. */
+
+       /* Be cautious about bogus calls. */
+       if (!seg || !seg_is_raid(seg))
+               return false;
+
+       if (seg_is_any_raid10(seg))
+               return _raid10_is_available(lv);
+
+       /* Count missing RAID legs */
+       for (s = 0; s < seg->area_count; ++s)
+               if (seg_type(seg, s) == AREA_LV &&
+                   lv_is_partial(seg_lv(seg, s)))
+                       missing_legs++;
+
+       /* Degradation: segtype raid1 may miss legs-1, raid0/4/5/6 may loose parity devices. */
+       return missing_legs <= (seg_is_raid1(seg) ? seg->area_count - 1 : seg->segtype->parity_devs);
+}
+
 static int _raid_target_present(struct cmd_context *cmd,
                                const struct lv_segment *seg __attribute__((unused)),
                                unsigned *attributes)
diff --git a/test/shell/lvdisplay-raid.sh b/test/shell/lvdisplay-raid.sh
new file mode 100644 (file)
index 0000000..18ea9ae
--- /dev/null
@@ -0,0 +1,79 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#
+# tests functionality lvdisplay tool for RAID
+#
+
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+aux prepare_vg 6
+get_devs
+
+# raid0 loosing a leg
+lvcreate -aey --type raid0 -i5 -l5 -n $lv $vg
+lvdisplay $vg/$lv|grep "LV Status *available"
+aux disable_dev $dev1
+lvdisplay $vg/$lv|grep "LV Status *NOT available (partial)"
+aux enable_dev $dev1
+lvremove -y $vg/$lv
+
+# raid1 loosing a leg/all legs
+lvcreate -aey --type raid1 -m1 -l5 -n $lv $vg $dev1 $dev2
+lvdisplay $vg/$lv|grep "LV Status *available"
+aux disable_dev $dev1
+lvdisplay $vg/$lv|grep "LV Status *available (partial)"
+aux disable_dev $dev2
+lvdisplay $vg/$lv|grep "LV Status *NOT available (partial)"
+aux enable_dev $dev1 $dev2
+lvremove -y $vg/$lv
+
+# raid5 loosing a leg/2 legs
+lvcreate -aey --type raid5 -i3 -l5 -n $lv $vg
+lvdisplay $vg/$lv|grep "LV Status *available"
+aux disable_dev $dev1
+lvdisplay $vg/$lv|grep "LV Status *available (partial)"
+aux disable_dev $dev2
+lvdisplay $vg/$lv|grep "LV Status *NOT available (partial)"
+aux enable_dev $dev1 $dev2
+lvremove -y $vg/$lv
+
+# raid6 loosing a leg/2 legs/3 legs
+lvcreate -aey --type raid6 -i3 -l5 -n $lv $vg
+lvdisplay $vg/$lv|grep "LV Status *available"
+aux disable_dev $dev1
+lvdisplay $vg/$lv|grep "LV Status *available (partial)"
+aux disable_dev $dev2
+lvdisplay $vg/$lv|grep "LV Status *available (partial)"
+aux disable_dev $dev3
+lvdisplay $vg/$lv|grep "LV Status *NOT available (partial)"
+aux enable_dev $dev1 $dev2 $dev3
+lvremove -y $vg/$lv
+
+# raid10 loosing a leg per mirror group / a complete mirror group
+lvcreate -aey --type raid10 -i3 -l3 -n $lv $vg
+lvdisplay $vg/$lv|grep "LV Status *available"
+aux disable_dev $dev1
+lvdisplay $vg/$lv|grep "LV Status *available (partial)"
+aux disable_dev $dev3
+lvdisplay $vg/$lv|grep "LV Status *available (partial)"
+aux disable_dev $dev6
+lvdisplay $vg/$lv|grep "LV Status *available (partial)"
+aux enable_dev $dev1 $dev3 $dev6
+lvdisplay $vg/$lv|grep "LV Status *available"
+aux disable_dev $dev1 $dev2
+lvdisplay $vg/$lv|grep "LV Status *NOT available (partial)"
+aux enable_dev $dev1 $dev2
+
+vgremove -y -f $vg
This page took 0.061402 seconds and 5 git commands to generate.