forked from mirrors/nixpkgs
d01242edb8
It turns out that some of gcc 4.8's aggressive optimizations may cause minor filesystem corruption in ZFS. To fix it, a patch was cherry-picked from the upstream's git tree. See: https://github.com/zfsonlinux/zfs/pull/2051
115 lines
4.5 KiB
Diff
115 lines
4.5 KiB
Diff
commit 0f62f3f9abc4bfa0bcafee9bfa3d55e91dcb371d
|
|
Author: Brian Behlendorf <behlendorf1@llnl.gov>
|
|
Date: Tue Jan 14 09:39:13 2014 -0800
|
|
|
|
Disable GCCs aggressive loop optimization
|
|
|
|
GCC >+ 4.8's aggressive loop optimization breaks some of the iterators
|
|
over the dn_blkptr[] pseudo-array in dnode_phys. Since dn_blkptr[] is
|
|
defined as a single-element array, GCC believes an iterator can only
|
|
access index 0 and will unroll the loop into a single iteration.
|
|
|
|
One way to resolve the issue would be to cast the array to a pointer
|
|
and fix all the iterators that might break. The only loop where it
|
|
is known to cause a problem is this loop in dmu_objset_write_ready():
|
|
|
|
for (i = 0; i < dnp->dn_nblkptr; i++)
|
|
bp->blk_fill += dnp->dn_blkptr[i].blk_fill;
|
|
|
|
In the common case where dn_nblkptr is 3, the loop is only executed a
|
|
single time and "i" is equal to 1 following the loop.
|
|
|
|
The specific breakage caused by this problem is that the blk_fill of
|
|
root block pointers wouldn't be set properly when more than one blkptr
|
|
is in use (when no indrect blocks are needed).
|
|
|
|
The simple reproducing sequence is:
|
|
|
|
zpool create tank /tank.img
|
|
zdb -ddddd tank 0
|
|
|
|
Notice that "fill=31", however, there are two L0 indirect blocks with
|
|
"F=31" and "F=5". The fill count should be 36 rather than 31. This
|
|
problem causes an assert to be hit in a simple "zdb tank" when built
|
|
with --enable-debug.
|
|
|
|
However, this approach was not taken because we need to be absolutely
|
|
sure we catch all instances of this unwanted optimization. Therefore,
|
|
the build system has been updated to detect if GCC supports the
|
|
aggressive loop optimization. If it does the optimization will be
|
|
explicitly disabled using the -fno-aggressive-loop-optimization option.
|
|
|
|
Original-fix-by: Tim Chase <tim@chase2k.com>
|
|
Signed-off-by: Tim Chase <tim@chase2k.com>
|
|
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
|
|
Closes #2010
|
|
Closes #2051
|
|
|
|
diff --git a/config/Rules.am b/config/Rules.am
|
|
index e3fa5b5..24f9426 100644
|
|
--- a/config/Rules.am
|
|
+++ b/config/Rules.am
|
|
@@ -1,8 +1,10 @@
|
|
DEFAULT_INCLUDES = -include ${top_builddir}/zfs_config.h
|
|
|
|
AM_LIBTOOLFLAGS = --silent
|
|
-AM_CFLAGS = -Wall -Wstrict-prototypes
|
|
-AM_CFLAGS += -fno-strict-aliasing ${NO_UNUSED_BUT_SET_VARIABLE} ${DEBUG_CFLAGS}
|
|
+AM_CFLAGS = ${DEBUG_CFLAGS} -Wall -Wstrict-prototypes
|
|
+AM_CFLAGS += ${NO_UNUSED_BUT_SET_VARIABLE}
|
|
+AM_CFLAGS += ${NO_AGGRESSIVE_LOOP_OPTIMIZATIONS}
|
|
+AM_CFLAGS += -fno-strict-aliasing
|
|
AM_CPPFLAGS = -D_GNU_SOURCE -D__EXTENSIONS__ -D_REENTRANT
|
|
AM_CPPFLAGS += -D_POSIX_PTHREAD_SEMANTICS -D_FILE_OFFSET_BITS=64
|
|
AM_CPPFLAGS += -D_LARGEFILE64_SOURCE -DTEXT_DOMAIN=\"zfs-linux-user\"
|
|
diff --git a/config/always-no-aggressive-loop-optimizations.m4 b/config/always-no-aggressive-loop-optimizations.m4
|
|
new file mode 100644
|
|
index 0000000..8f2115a
|
|
--- /dev/null
|
|
+++ b/config/always-no-aggressive-loop-optimizations.m4
|
|
@@ -0,0 +1,20 @@
|
|
+dnl #
|
|
+dnl # Check if gcc supports -fno-aggressive-loop-optimizations
|
|
+dnl #
|
|
+AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_NO_AGGRESSIVE_LOOP_OPTIMIZATIONS], [
|
|
+ AC_MSG_CHECKING([for -fno-aggressive-loop-optimizations support])
|
|
+
|
|
+ saved_flags="$CFLAGS"
|
|
+ CFLAGS="$CFLAGS -fno-aggressive-loop-optimizations"
|
|
+
|
|
+ AC_RUN_IFELSE([AC_LANG_PROGRAM([], [])], [
|
|
+ NO_AGGRESSIVE_LOOP_OPTIMIZATIONS=-fno-aggressive-loop-optimizations
|
|
+ AC_MSG_RESULT([yes])
|
|
+ ], [
|
|
+ NO_AGGRESSIVE_LOOP_OPTIMIZATIONS=
|
|
+ AC_MSG_RESULT([no])
|
|
+ ])
|
|
+
|
|
+ CFLAGS="$saved_flags"
|
|
+ AC_SUBST([NO_AGGRESSIVE_LOOP_OPTIMIZATIONS])
|
|
+])
|
|
diff --git a/config/kernel.m4 b/config/kernel.m4
|
|
index cbf0ca3..62a9b42 100644
|
|
--- a/config/kernel.m4
|
|
+++ b/config/kernel.m4
|
|
@@ -104,6 +104,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
|
|
dnl # -Wall -fno-strict-aliasing -Wstrict-prototypes and other
|
|
dnl # compiler options are added by the kernel build system.
|
|
KERNELCPPFLAGS="$KERNELCPPFLAGS $NO_UNUSED_BUT_SET_VARIABLE"
|
|
+ KERNELCPPFLAGS="$KERNELCPPFLAGS $NO_AGGRESSIVE_LOOP_OPTIMIZATIONS"
|
|
KERNELCPPFLAGS="$KERNELCPPFLAGS -DHAVE_SPL -D_KERNEL"
|
|
KERNELCPPFLAGS="$KERNELCPPFLAGS -DTEXT_DOMAIN=\\\"zfs-linux-kernel\\\""
|
|
|
|
diff --git a/config/zfs-build.m4 b/config/zfs-build.m4
|
|
index 005185b..477b916 100644
|
|
--- a/config/zfs-build.m4
|
|
+++ b/config/zfs-build.m4
|
|
@@ -62,6 +62,7 @@ AC_DEFUN([ZFS_AC_DEBUG_DMU_TX], [
|
|
|
|
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS], [
|
|
ZFS_AC_CONFIG_ALWAYS_NO_UNUSED_BUT_SET_VARIABLE
|
|
+ ZFS_AC_CONFIG_ALWAYS_NO_AGGRESSIVE_LOOP_OPTIMIZATIONS
|
|
])
|
|
|
|
AC_DEFUN([ZFS_AC_CONFIG], [
|