diff --git a/grub-install-force-journal-draining-to-ensure-data-i.patch b/grub-install-force-journal-draining-to-ensure-data-i.patch new file mode 100644 index 0000000..f803cc0 --- /dev/null +++ b/grub-install-force-journal-draining-to-ensure-data-i.patch @@ -0,0 +1,199 @@ +From 3085db0922a1d803d4a9dfe54daae6fef20e4340 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Mon, 13 Apr 2020 16:08:59 +0800 +Subject: [PATCH] grub-install: force journal draining to ensure data integrity + +In XFS, the system would end up in unbootable state if an abrupt power +off after grub-install is occuring. It can be easily reproduced with. + + grub-install /dev/vda; reboot -f + +The grub error would show many different kinds of corruption in +filesystem and the problem boils down to incompleted journal transaction +which would leave pending writes behind in the on-disk journal. It is +therefore necessary to recover the system via re-mounting the filesystem +from linux system that all pending journal log can be replayed. + +On the other hand if journal draining can be enforced by grub-install +then it can bring more resilience to such abrupt power loss. The fsync +is not enough here for XFS, because that only writes in-memory log to +on-disk (ie makes sure broken state can be repaired). Unfortunately +there's no designated system call to serve solely for the journal +draining, so it can only be achieved via fsfreeze system call that the +journal draining can happen as a byproduct during the process. + +This patch adds fsfreeze/unfreeze at the end of grub-install to induce +journal draining on journaled file system. However btrfs is excluded +from the list as it is using fsync to drain journal and also is not +desired as reportedly having negative side effect. With this patch +applied, the boot falilure can no longer be reproduced with above +procedure. + +Signed-off-by: Michael Chang +--- + Makefile.util.def | 1 + + grub-core/osdep/basic/journaled_fs.c | 26 +++++++++++++++++++ + grub-core/osdep/journaled_fs.c | 5 ++++ + grub-core/osdep/linux/journaled_fs.c | 48 ++++++++++++++++++++++++++++++++++++ + include/grub/util/install.h | 2 ++ + util/grub-install.c | 20 +++++++++++++++ + 6 files changed, 102 insertions(+) + create mode 100644 grub-core/osdep/basic/journaled_fs.c + create mode 100644 grub-core/osdep/journaled_fs.c + create mode 100644 grub-core/osdep/linux/journaled_fs.c + +Index: grub-2.04/Makefile.util.def +=================================================================== +--- grub-2.04.orig/Makefile.util.def ++++ grub-2.04/Makefile.util.def +@@ -645,6 +645,7 @@ program = { + emu_condition = COND_s390x; + common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; ++ common = grub-core/osdep/journaled_fs.c; + + ldadd = '$(LIBLZMA)'; + ldadd = libgrubmods.a; +Index: grub-2.04/grub-core/osdep/basic/journaled_fs.c +=================================================================== +--- /dev/null ++++ grub-2.04/grub-core/osdep/basic/journaled_fs.c +@@ -0,0 +1,26 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2010,2011,2012,2013 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++ ++int ++grub_install_sync_fs_journal (const char *path) ++{ ++ return 1; ++} ++ +Index: grub-2.04/grub-core/osdep/journaled_fs.c +=================================================================== +--- /dev/null ++++ grub-2.04/grub-core/osdep/journaled_fs.c +@@ -0,0 +1,5 @@ ++#ifdef __linux__ ++#include "linux/journaled_fs.c" ++#else ++#include "basic/journaled_fs.c" ++#endif +Index: grub-2.04/grub-core/osdep/linux/journaled_fs.c +=================================================================== +--- /dev/null ++++ grub-2.04/grub-core/osdep/linux/journaled_fs.c +@@ -0,0 +1,48 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2010,2011,2012,2013 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++int ++grub_install_sync_fs_journal (const char *path) ++{ ++ int fd, ret; ++ ++ fd = open (path, O_RDONLY); ++ ++ if (fd == -1) ++ return 1; ++ ++ if (ioctl (fd, FIFREEZE, 0) == 0) ++ { ++ ioctl(fd, FITHAW, 0); ++ ret = 1; ++ } ++ else if (errno == EOPNOTSUPP) ++ ret = 1; ++ else ++ ret = 0; ++ ++ close (fd); ++ return ret; ++} ++ +Index: grub-2.04/include/grub/util/install.h +=================================================================== +--- grub-2.04.orig/include/grub/util/install.h ++++ grub-2.04/include/grub/util/install.h +@@ -269,4 +269,6 @@ grub_util_get_target_name (const struct + extern char *grub_install_copy_buffer; + #define GRUB_INSTALL_COPY_BUFFER_SIZE 1048576 + ++int ++grub_install_sync_fs_journal (const char *path); + #endif +Index: grub-2.04/util/grub-install.c +=================================================================== +--- grub-2.04.orig/util/grub-install.c ++++ grub-2.04/util/grub-install.c +@@ -42,6 +42,7 @@ + #include + #include + #include ++#include + + #include + +@@ -1997,6 +1998,25 @@ main (int argc, char *argv[]) + break; + } + ++ { ++ const char *journaled_fs[] = {"xfs", "ext2", NULL}; ++ int i; ++ ++ for (i = 0; journaled_fs[i]; ++i) ++ if (grub_strcmp (grub_fs->name, journaled_fs[i]) == 0) ++ { ++ int retries = 10; ++ ++ /* If the fs is already frozen at that point, we could generally ++ * expected that it will be soon unfrozen again (assuming some other ++ * process has frozen it for snapshotting or something), so we may ++ * as well retry a few (limited) times in a delay loop. */ ++ while (retries-- && !grub_install_sync_fs_journal (grubdir)) ++ grub_sleep (1); ++ break; ++ } ++ } ++ + fprintf (stderr, "%s\n", _("Installation finished. No error reported.")); + + /* Free resources. */ diff --git a/grub2.changes b/grub2.changes index 0260170..ba10e9c 100644 --- a/grub2.changes +++ b/grub2.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Tue May 5 06:48:55 UTC 2020 - Michael Chang + +- Fix boot failure as journaled data not get drained due to abrupt power + off after grub-install (bsc#1167756) + * grub-install-force-journal-draining-to-ensure-data-i.patch + ------------------------------------------------------------------- Thu Apr 16 13:35:10 UTC 2020 - Michael Chang diff --git a/grub2.spec b/grub2.spec index da8d32f..05d129d 100644 --- a/grub2.spec +++ b/grub2.spec @@ -224,6 +224,7 @@ Patch92: grub2-util-30_os-prober-multiple-initrd.patch Patch93: grub2-getroot-support-nvdimm.patch Patch94: grub2-install-fix-not-a-directory-error.patch Patch95: grub2-verifiers-fix-system-freeze-if-verify-failed.patch +Patch96: grub-install-force-journal-draining-to-ensure-data-i.patch # Btrfs snapshot booting related patches Patch101: grub2-btrfs-01-add-ability-to-boot-from-subvolumes.patch Patch102: grub2-btrfs-02-export-subvolume-envvars.patch @@ -546,6 +547,7 @@ swap partition while in resuming %patch93 -p1 %patch94 -p1 %patch95 -p1 +%patch96 -p1 %patch101 -p1 %patch102 -p1 %patch103 -p1