summaryrefslogtreecommitdiffstats
path: root/config
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2014-01-14 09:39:13 -0800
committerBrian Behlendorf <[email protected]>2014-01-14 13:55:58 -0800
commit0f62f3f9abc4bfa0bcafee9bfa3d55e91dcb371d (patch)
tree570676b3692d31e1d7931880c5711705ff4ceab4 /config
parentcbe8e6198cb167f34adc30c6993032a4f4491397 (diff)
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 <[email protected]> Signed-off-by: Tim Chase <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes #2010 Closes #2051
Diffstat (limited to 'config')
-rw-r--r--config/Rules.am6
-rw-r--r--config/always-no-aggressive-loop-optimizations.m420
-rw-r--r--config/kernel.m41
-rw-r--r--config/zfs-build.m41
4 files changed, 26 insertions, 2 deletions
diff --git a/config/Rules.am b/config/Rules.am
index e3fa5b5a4..24f94264b 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 000000000..8f2115ae6
--- /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 cbf0ca3d6..62a9b4299 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 005185b03..477b91678 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], [