If fsck.gfs2 is run against an LVM PV it will try its best to repair it
as a gfs2 fs. This is unlikely the best course of action as it's more
likely that the user executed fsck.gfs2 against the PV after stopping
the cluster (including the LVM activation resources).

In this situation other fscks try to look up backup superblocks before
failing but gfs2 does not keep backup superblocks so the safest thing to
do is fail with an operational error code when an LVM PV is detected.

A test is included that restores a PV signature to the test volume
before attempting to run fsck.gfs2 on it.

Signed-off-by: Andrew Price <anpr...@redhat.com>
---
 gfs2/fsck/Makefile.am  |  5 ++++-
 gfs2/fsck/initialize.c | 30 ++++++++++++++++++++++++++++++
 tests/Makefile.am      |  3 ++-
 tests/atlocal.in       |  1 +
 tests/fsck.at          |  7 +++++++
 tests/pv_sig.xxd       | 12 ++++++++++++
 6 files changed, 56 insertions(+), 2 deletions(-)
 create mode 100644 tests/pv_sig.xxd

diff --git a/gfs2/fsck/Makefile.am b/gfs2/fsck/Makefile.am
index 405aabe1..543057b1 100644
--- a/gfs2/fsck/Makefile.am
+++ b/gfs2/fsck/Makefile.am
@@ -32,10 +32,13 @@ fsck_gfs2_SOURCES = \
        util.c
 
 fsck_gfs2_CPPFLAGS = $(AM_CPPFLAGS)
-fsck_gfs2_CFLAGS = $(AM_CFLAGS)
+fsck_gfs2_CFLAGS = \
+       $(AM_CFLAGS) \
+       $(blkid_CFLAGS)
 fsck_gfs2_LDADD = \
        $(top_builddir)/gfs2/libgfs2/libgfs2.la \
        $(LTLIBINTL) \
+       $(blkid_LIBS) \
        $(uuid_LIBS)
 
 if HAVE_CHECK
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index 62fb6107..8679dee9 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -12,6 +12,7 @@
 #include <libintl.h>
 #include <errno.h>
 #include <time.h>
+#include <blkid.h>
 
 #define _(String) gettext(String)
 
@@ -1555,6 +1556,33 @@ static int init_rindex(struct fsck_cx *cx)
        return 0;
 }
 
+static int is_lvm_member(struct fsck_cx *cx)
+{
+       char lvm_member[] = "LVM2_member";
+       char *filter[] = {lvm_member, NULL};
+       int fd = cx->sdp->device_fd;
+       int ret;
+
+       blkid_probe pr = blkid_new_probe();
+       if (pr == NULL || blkid_probe_set_device(pr, fd, 0, 0) != 0
+                      || blkid_probe_filter_superblocks_type(pr,
+                                      BLKID_FLTR_ONLYIN, filter)) {
+               log_err(_("Failed to create probe for %s\n"), cx->opts->device);
+               return -1;
+       }
+       ret = blkid_do_fullprobe(pr);
+       blkid_free_probe(pr);
+       if (ret == -1) {
+               log_err(_("Failed to probe device %s\n"), cx->opts->device);
+               return -1;
+       }
+       if (ret == 1)
+               return 0;
+       log_err(_("%s looks like an LVM physical volume.\n"), cx->opts->device);
+       log_err(_("fsck.gfs2 cannot check this device.\n"));
+       return 1;
+}
+
 /**
  * initialize - initialize superblock pointer
  *
@@ -1602,6 +1630,8 @@ int initialize(struct fsck_cx *cx, int *all_clean)
                   from themselves. */
                was_mounted_ro = 1;
        }
+       if (is_lvm_member(cx)) /* True or error */
+               return FSCK_ERROR;
 
        if (lgfs2_get_dev_info(sdp->device_fd, &sdp->dinfo)) {
                perror(cx->opts->device);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 27a643a2..f8538942 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -8,7 +8,8 @@ EXTRA_DIST = \
        $(TESTSCRIPTS) \
        package.m4 \
        gfs2-utils.spec.in \
-       atlocal.in
+       atlocal.in \
+       pv_sig.xxd
 
 DISTCLEANFILES = \
        atlocal \
diff --git a/tests/atlocal.in b/tests/atlocal.in
index eed58b10..769b43cb 100644
--- a/tests/atlocal.in
+++ b/tests/atlocal.in
@@ -1,3 +1,4 @@
+GFS_TESTS_DIR="${abs_top_builddir}/tests"
 GFS_TGT="@testvol@"
 GFS_TGT_SZ=20
 GFS_MKFS="mkfs.gfs2 -O -D"
diff --git a/tests/fsck.at b/tests/fsck.at
index 538d41ad..bc8a6d1c 100644
--- a/tests/fsck.at
+++ b/tests/fsck.at
@@ -89,3 +89,10 @@ AT_CHECK([fsck.gfs2 -n $GFS_TGT], 0, [ignore], [ignore])
 AT_CHECK([mkfs.gfs2 -O -p lock_nolock -o format=1802 ${GFS_TGT}], 0, [ignore], 
[ignore])
 AT_CHECK([fsck.gfs2 -n $GFS_TGT], 0, [ignore], [ignore])
 AT_CLEANUP
+
+AT_SETUP([Detect LVM PV])
+AT_KEYWORDS(fsck.gfs2 fsck)
+GFS_TGT_REGEN
+AT_CHECK([xxd -r ${GFS_TESTS_DIR}/pv_sig.xxd ${GFS_TGT}], 0, [ignore], 
[ignore])
+AT_CHECK([fsck.gfs2 -y ${GFS_TGT}], 8, [ignore], [ignore])
+AT_CLEANUP
diff --git a/tests/pv_sig.xxd b/tests/pv_sig.xxd
new file mode 100644
index 00000000..dc00faed
--- /dev/null
+++ b/tests/pv_sig.xxd
@@ -0,0 +1,12 @@
+00000200: 4c41 4245 4c4f 4e45 0100 0000 0000 0000  LABELONE........
+00000210: 22fb 8643 2000 0000 4c56 4d32 2030 3031  "..C ...LVM2 001
+00000220: 5061 6e73 586a 5632 6847 3641 7679 3854  PansXjV2hG6Avy8T
+00000230: 5739 3236 786e 516a 5956 4154 5258 734d  W926xnQjYVATRXsM
+00000240: 0000 0040 0100 0000 0000 1000 0000 0000  ...@............
+00000250: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+00000260: 0000 0000 0000 0000 0010 0000 0000 0000  ................
+00000270: 00f0 0f00 0000 0000 0000 0000 0000 0000  ................
+00000280: 0000 0000 0000 0000 0200 0000 0000 0000  ................
+00000290: 0000 0000 0000 0000 0000 0000 0000 0000  ................
+*
+000003f0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
-- 
2.40.1

Reply via email to