Skip to content

Commit

Permalink
Disable GCCs aggressive loop optimization
Browse files Browse the repository at this point in the history
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 openzfs#2010
Closes openzfs#2051
  • Loading branch information
behlendorf committed Jan 14, 2014
1 parent cbe8e61 commit 0f62f3f
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 2 deletions.
6 changes: 4 additions & 2 deletions config/Rules.am
Original file line number Diff line number Diff line change
@@ -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\"
20 changes: 20 additions & 0 deletions config/always-no-aggressive-loop-optimizations.m4
Original file line number Diff line number Diff line change
@@ -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])
])
1 change: 1 addition & 0 deletions config/kernel.m4
Original file line number Diff line number Diff line change
Expand Up @@ -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\\\""
Expand Down
1 change: 1 addition & 0 deletions config/zfs-build.m4
Original file line number Diff line number Diff line change
Expand Up @@ -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], [
Expand Down

0 comments on commit 0f62f3f

Please sign in to comment.