[PATCH][Disco] UBUNTU: SAUCE: (noup) Update spl to 0.7.12-1ubuntu1, zfs to 0.7.12-1ubuntu1

Colin King colin.king at canonical.com
Wed Nov 21 16:53:54 UTC 2018


From: Colin Ian King <colin.king at canonical.com>

This sync's SPL and ZFS to the latest versions for 19.04 Ubuntu Disco,
as built against the 4.19 unstable kernel and tested agains the
Ubuntu ZFS regression tests. This contains 4.20 compat fixes too,
so it should be good for when me move to 4.20

Signed-off-by: Colin Ian King <colin.king at canonical.com>
---
 spl/META                               |   2 +-
 spl/config/libtool.m4                  |   3 +-
 spl/config/ltmain.sh                   | 415 +++++++++++++++------------------
 spl/configure                          |  27 +--
 spl/dkms.conf                          |   2 +-
 spl/include/sys/time.h                 |  10 +-
 spl/include/sys/vnode.h                |   4 +-
 spl/rpm/generic/spl-kmod.spec.in       |   7 +
 spl/rpm/generic/spl.spec.in            |   6 +
 spl/rpm/redhat/spl.spec.in             |   6 +
 zfs/META                               |   4 +-
 zfs/Makefile.in                        |   1 +
 zfs/aclocal.m4                         |   1 +
 zfs/config/kernel-in-compat-syscall.m4 |  20 ++
 zfs/config/kernel.m4                   |   1 +
 zfs/config/libtool.m4                  |   3 +-
 zfs/config/ltmain.sh                   | 415 +++++++++++++++------------------
 zfs/configure                          | 157 +++++++++++--
 zfs/dkms.conf                          |   2 +-
 zfs/include/Makefile.in                |   1 +
 zfs/include/linux/Makefile.in          |   1 +
 zfs/include/linux/vfs_compat.h         |  18 ++
 zfs/include/sys/Makefile.in            |   1 +
 zfs/include/sys/crypto/Makefile.in     |   1 +
 zfs/include/sys/dmu_impl.h             |   1 +
 zfs/include/sys/dnode.h                |   4 +
 zfs/include/sys/fm/Makefile.in         |   1 +
 zfs/include/sys/fm/fs/Makefile.in      |   1 +
 zfs/include/sys/fs/Makefile.in         |   1 +
 zfs/include/sys/metaslab_impl.h        |   1 -
 zfs/include/sys/refcount.h             |  70 +++---
 zfs/include/sys/sysevent/Makefile.in   |   1 +
 zfs/include/sys/trace_dbuf.h           |   2 +-
 zfs/include/sys/zio.h                  |   4 +-
 zfs/module/zfs/abd.c                   |  22 +-
 zfs/module/zfs/arc.c                   | 303 ++++++++++++------------
 zfs/module/zfs/dbuf.c                  |  69 +++---
 zfs/module/zfs/dbuf_stats.c            |   4 +-
 zfs/module/zfs/dmu.c                   |   2 +-
 zfs/module/zfs/dmu_objset.c            |  15 ++
 zfs/module/zfs/dmu_tx.c                |  36 +--
 zfs/module/zfs/dnode.c                 |  69 +++---
 zfs/module/zfs/dnode_sync.c            |   6 +-
 zfs/module/zfs/dsl_dataset.c           |  12 +-
 zfs/module/zfs/dsl_destroy.c           |   6 +-
 zfs/module/zfs/metaslab.c              |  23 +-
 zfs/module/zfs/refcount.c              |  42 ++--
 zfs/module/zfs/rrwlock.c               |  35 +--
 zfs/module/zfs/sa.c                    |   8 +-
 zfs/module/zfs/spa.c                   |   8 +-
 zfs/module/zfs/spa_misc.c              |  35 +--
 zfs/module/zfs/zfs_ctldir.c            |   6 +-
 zfs/module/zfs/zfs_vfsops.c            |   8 +-
 zfs/module/zfs/zfs_znode.c             |  10 +-
 zfs/module/zfs/zio.c                   | 256 ++++++++++----------
 zfs/module/zfs/zpl_super.c             |  22 ++
 zfs/zfs_config.h.in                    |   3 +
 57 files changed, 1194 insertions(+), 1000 deletions(-)
 create mode 100644 zfs/config/kernel-in-compat-syscall.m4

diff --git a/spl/META b/spl/META
index 7bd657d..6a2b1b3 100644
--- a/spl/META
+++ b/spl/META
@@ -1,7 +1,7 @@
 Meta:         1
 Name:         spl
 Branch:       1.0
-Version:      0.7.11
+Version:      0.7.12
 Release:      1ubuntu1
 Release-Tags: relext
 License:      GPL
diff --git a/spl/config/libtool.m4 b/spl/config/libtool.m4
index e67ed69..c81e669 100644
--- a/spl/config/libtool.m4
+++ b/spl/config/libtool.m4
@@ -4063,7 +4063,8 @@ _LT_EOF
   if AC_TRY_EVAL(ac_compile); then
     # Now try to grab the symbols.
     nlist=conftest.nm
-    if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
+    $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD
+    if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then
       # Try sorting and uniquifying the output.
       if sort "$nlist" | uniq > "$nlist"T; then
 	mv -f "$nlist"T "$nlist"
diff --git a/spl/config/ltmain.sh b/spl/config/ltmain.sh
index d3230f7..68fd36c 100644
--- a/spl/config/ltmain.sh
+++ b/spl/config/ltmain.sh
@@ -31,7 +31,7 @@
 
 PROGRAM=libtool
 PACKAGE=libtool
-VERSION="2.4.6 Debian-2.4.6-4"
+VERSION="2.4.6 Debian-2.4.6-6"
 package_revision=2.4.6
 
 
@@ -64,7 +64,7 @@ package_revision=2.4.6
 # libraries, which are installed to $pkgauxdir.
 
 # Set a version string for this script.
-scriptversion=2015-10-12.13; # UTC
+scriptversion=2015-10-04.22; # UTC
 
 # General shell script boiler plate, and helper functions.
 # Written by Gary V. Vaughan, 2004
@@ -580,16 +580,16 @@ if test yes = "$_G_HAVE_PLUSEQ_OP"; then
   {
     $debug_cmd
 
-    func_quote_arg pretty "$2"
-    eval "$1+=\\ \$func_quote_arg_result"
+    func_quote_for_eval "$2"
+    eval "$1+=\\ \$func_quote_for_eval_result"
   }'
 else
   func_append_quoted ()
   {
     $debug_cmd
 
-    func_quote_arg pretty "$2"
-    eval "$1=\$$1\\ \$func_quote_arg_result"
+    func_quote_for_eval "$2"
+    eval "$1=\$$1\\ \$func_quote_for_eval_result"
   }
 fi
 
@@ -1091,184 +1091,135 @@ func_relative_path ()
 }
 
 
-# func_quote_portable EVAL ARG
-# ----------------------------
-# Internal function to portably implement func_quote_arg.  Note that we still
-# keep attention to performance here so we as much as possible try to avoid
-# calling sed binary (so far O(N) complexity as long as func_append is O(1)).
-func_quote_portable ()
+# func_quote ARG
+# --------------
+# Aesthetically quote one ARG, store the result into $func_quote_result.  Note
+# that we keep attention to performance here (so far O(N) complexity as long as
+# func_append is O(1)).
+func_quote ()
 {
     $debug_cmd
 
-    func_quote_portable_result=$2
-
-    # one-time-loop (easy break)
-    while true
-    do
-      if $1; then
-        func_quote_portable_result=`$ECHO "$2" | $SED \
-          -e "$sed_double_quote_subst" -e "$sed_double_backslash"`
-        break
-      fi
+    func_quote_result=$1
 
-      # Quote for eval.
-      case $func_quote_portable_result in
-        *[\\\`\"\$]*)
-          case $func_quote_portable_result in
-            *[\[\*\?]*)
-              func_quote_portable_result=`$ECHO "$func_quote_portable_result" | $SED "$sed_quote_subst"`
-              break
-              ;;
-          esac
+    case $func_quote_result in
+      *[\\\`\"\$]*)
+        case $func_quote_result in
+          *[\[\*\?]*)
+            func_quote_result=`$ECHO "$func_quote_result" | $SED "$sed_quote_subst"`
+            return 0
+            ;;
+        esac
 
-          func_quote_portable_old_IFS=$IFS
-          for _G_char in '\' '`' '"' '$'
+        func_quote_old_IFS=$IFS
+        for _G_char in '\' '`' '"' '$'
+        do
+          # STATE($1) PREV($2) SEPARATOR($3)
+          set start "" ""
+          func_quote_result=dummy"$_G_char$func_quote_result$_G_char"dummy
+          IFS=$_G_char
+          for _G_part in $func_quote_result
           do
-            # STATE($1) PREV($2) SEPARATOR($3)
-            set start "" ""
-            func_quote_portable_result=dummy"$_G_char$func_quote_portable_result$_G_char"dummy
-            IFS=$_G_char
-            for _G_part in $func_quote_portable_result
-            do
-              case $1 in
-              quote)
-                func_append func_quote_portable_result "$3$2"
-                set quote "$_G_part" "\\$_G_char"
-                ;;
-              start)
-                set first "" ""
-                func_quote_portable_result=
-                ;;
-              first)
-                set quote "$_G_part" ""
-                ;;
-              esac
-            done
+            case $1 in
+            quote)
+              func_append func_quote_result "$3$2"
+              set quote "$_G_part" "\\$_G_char"
+              ;;
+            start)
+              set first "" ""
+              func_quote_result=
+              ;;
+            first)
+              set quote "$_G_part" ""
+              ;;
+            esac
           done
-          IFS=$func_quote_portable_old_IFS
-          ;;
-        *) ;;
-      esac
-      break
-    done
-
-    func_quote_portable_unquoted_result=$func_quote_portable_result
-    case $func_quote_portable_result in
-      # double-quote args containing shell metacharacters to delay
-      # word splitting, command substitution and variable expansion
-      # for a subsequent eval.
-      # many bourne shells cannot handle close brackets correctly
-      # in scan sets, so we specify it separately.
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-        func_quote_portable_result=\"$func_quote_portable_result\"
+          IFS=$func_quote_old_IFS
+        done
         ;;
+      *) ;;
     esac
 }
 
 
-# func_quotefast_eval ARG
-# -----------------------
-# Quote one ARG (internal).  This is equivalent to 'func_quote_arg eval ARG',
-# but optimized for speed.  Result is stored in $func_quotefast_eval.
-if test xyes = `(x=; printf -v x %q yes; echo x"$x") 2>/dev/null`; then
-  func_quotefast_eval ()
-  {
-    printf -v func_quotefast_eval_result %q "$1"
-  }
-else
-  func_quotefast_eval ()
-  {
-    func_quote_portable false "$1"
-    func_quotefast_eval_result=$func_quote_portable_result
-  }
-fi
-
-
-# func_quote_arg MODEs ARG
-# ------------------------
-# Quote one ARG to be evaled later.  MODEs argument may contain zero ore more
-# specifiers listed below separated by ',' character.  This function returns two
-# values:
-#   i) func_quote_arg_result
-#      double-quoted (when needed), suitable for a subsequent eval
-#  ii) func_quote_arg_unquoted_result
+# func_quote_for_eval ARG...
+# --------------------------
+# Aesthetically quote ARGs to be evaled later.
+# This function returns two values:
+#   i) func_quote_for_eval_result
+#      double-quoted, suitable for a subsequent eval
+#  ii) func_quote_for_eval_unquoted_result
 #      has all characters that are still active within double
-#      quotes backslashified.  Available only if 'unquoted' is specified.
-#
-# Available modes:
-# ----------------
-# 'eval' (default)
-#       - escape shell special characters
-# 'expand'
-#       - the same as 'eval';  but do not quote variable references
-# 'pretty'
-#       - request aesthetic output, i.e. '"a b"' instead of 'a\ b'.  This might
-#         later used in func_quote to get output like: 'echo "a b"' instead of
-#         'echo a\ b'.  This is slower than default on some shells.
-# 'unquoted'
-#       - produce also $func_quote_arg_unquoted_result which does not contain
-#         wrapping double-quotes.
-#
-# Examples for 'func_quote_arg pretty,unquoted string':
-#
-#   string      | *_result              | *_unquoted_result
-#   ------------+-----------------------+-------------------
-#   "           | \"                    | \"
-#   a b         | "a b"                 | a b
-#   "a b"       | "\"a b\""             | \"a b\"
-#   *           | "*"                   | *
-#   z="${x-$y}" | "z=\"\${x-\$y}\""     | z=\"\${x-\$y}\"
-#
-# Examples for 'func_quote_arg pretty,unquoted,expand string':
-#
-#   string        |   *_result          |  *_unquoted_result
-#   --------------+---------------------+--------------------
-#   z="${x-$y}"   | "z=\"${x-$y}\""     | z=\"${x-$y}\"
-func_quote_arg ()
-{
-    _G_quote_expand=false
-    case ,$1, in
-      *,expand,*)
-        _G_quote_expand=:
-        ;;
-    esac
-
-    case ,$1, in
-      *,pretty,*|*,expand,*|*,unquoted,*)
-        func_quote_portable $_G_quote_expand "$2"
-        func_quote_arg_result=$func_quote_portable_result
-        func_quote_arg_unquoted_result=$func_quote_portable_unquoted_result
-        ;;
-      *)
-        # Faster quote-for-eval for some shells.
-        func_quotefast_eval "$2"
-        func_quote_arg_result=$func_quotefast_eval_result
-        ;;
-    esac
-}
-
-
-# func_quote MODEs ARGs...
-# ------------------------
-# Quote all ARGs to be evaled later and join them into single command.  See
-# func_quote_arg's description for more info.
-func_quote ()
+#      quotes backslashified.
+func_quote_for_eval ()
 {
     $debug_cmd
-    _G_func_quote_mode=$1 ; shift
-    func_quote_result=
+
+    func_quote_for_eval_unquoted_result=
+    func_quote_for_eval_result=
     while test 0 -lt $#; do
-      func_quote_arg "$_G_func_quote_mode" "$1"
-      if test -n "$func_quote_result"; then
-        func_append func_quote_result " $func_quote_arg_result"
+      func_quote "$1"
+      _G_unquoted_arg=$func_quote_result
+      if test -n "$func_quote_for_eval_unquoted_result"; then
+	func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg"
       else
-        func_append func_quote_result "$func_quote_arg_result"
+        func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg"
+      fi
+
+      case $_G_unquoted_arg in
+        # Double-quote args containing shell metacharacters to delay
+        # word splitting, command substitution and variable expansion
+        # for a subsequent eval.
+        # Many Bourne shells cannot handle close brackets correctly
+        # in scan sets, so we specify it separately.
+        *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+          _G_quoted_arg=\"$_G_unquoted_arg\"
+          ;;
+        *)
+          _G_quoted_arg=$_G_unquoted_arg
+	  ;;
+      esac
+
+      if test -n "$func_quote_for_eval_result"; then
+	func_append func_quote_for_eval_result " $_G_quoted_arg"
+      else
+        func_append func_quote_for_eval_result "$_G_quoted_arg"
       fi
       shift
     done
 }
 
 
+# func_quote_for_expand ARG
+# -------------------------
+# Aesthetically quote ARG to be evaled later; same as above,
+# but do not quote variable references.
+func_quote_for_expand ()
+{
+    $debug_cmd
+
+    case $1 in
+      *[\\\`\"]*)
+	_G_arg=`$ECHO "$1" | $SED \
+	    -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;;
+      *)
+        _G_arg=$1 ;;
+    esac
+
+    case $_G_arg in
+      # Double-quote args containing shell metacharacters to delay
+      # word splitting and command substitution for a subsequent eval.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+        _G_arg=\"$_G_arg\"
+        ;;
+    esac
+
+    func_quote_for_expand_result=$_G_arg
+}
+
+
 # func_stripname PREFIX SUFFIX NAME
 # ---------------------------------
 # strip PREFIX and SUFFIX from NAME, and store in func_stripname_result.
@@ -1311,8 +1262,8 @@ func_show_eval ()
     _G_cmd=$1
     _G_fail_exp=${2-':'}
 
-    func_quote_arg pretty,expand "$_G_cmd"
-    eval "func_notquiet $func_quote_arg_result"
+    func_quote_for_expand "$_G_cmd"
+    eval "func_notquiet $func_quote_for_expand_result"
 
     $opt_dry_run || {
       eval "$_G_cmd"
@@ -1337,8 +1288,8 @@ func_show_eval_locale ()
     _G_fail_exp=${2-':'}
 
     $opt_quiet || {
-      func_quote_arg expand,pretty "$_G_cmd"
-      eval "func_echo $func_quote_arg_result"
+      func_quote_for_expand "$_G_cmd"
+      eval "func_echo $func_quote_for_expand_result"
     }
 
     $opt_dry_run || {
@@ -1466,7 +1417,7 @@ func_lt_ver ()
 #! /bin/sh
 
 # Set a version string for this script.
-scriptversion=2015-10-12.13; # UTC
+scriptversion=2015-10-07.11; # UTC
 
 # A portable, pluggable option parser for Bourne shell.
 # Written by Gary V. Vaughan, 2010
@@ -1676,8 +1627,8 @@ func_run_hooks ()
 #    '
 #        # No change in '$@' (ignored completely by this hook).  There is
 #        # no need to do the equivalent (but slower) action:
-#        # func_quote eval ${1+"$@"}
-#        # my_options_prep_result=$func_quote_result
+#        # func_quote_for_eval ${1+"$@"}
+#        # my_options_prep_result=$func_quote_for_eval_result
 #        false
 #    }
 #    func_add_hook func_options_prep my_options_prep
@@ -1713,8 +1664,8 @@ func_run_hooks ()
 #        done
 #
 #        if $args_changed; then
-#          func_quote eval ${1+"$@"}
-#          my_silent_option_result=$func_quote_result
+#          func_quote_for_eval ${1+"$@"}
+#          my_silent_option_result=$func_quote_for_eval_result
 #        fi
 #
 #        $args_changed
@@ -1781,8 +1732,8 @@ func_options ()
     if $_G_rc_options; then
       func_options_result=$_G_res_var
     else
-      func_quote eval ${1+"$@"}
-      func_options_result=$func_quote_result
+      func_quote_for_eval ${1+"$@"}
+      func_options_result=$func_quote_for_eval_result
     fi
 
     $_G_rc_options
@@ -1925,8 +1876,8 @@ func_parse_options ()
 
     if $_G_rc_parse_options; then
       # save modified positional parameters for caller
-      func_quote eval ${1+"$@"}
-      func_parse_options_result=$func_quote_result
+      func_quote_for_eval ${1+"$@"}
+      func_parse_options_result=$func_quote_for_eval_result
     fi
 
     $_G_rc_parse_options
@@ -2237,7 +2188,7 @@ include the following information:
        compiler:       $LTCC
        compiler flags: $LTCFLAGS
        linker:         $LD (gnu? $with_gnu_ld)
-       version:        $progname $scriptversion Debian-2.4.6-4
+       version:        $progname $scriptversion Debian-2.4.6-6
        automake:       `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
        autoconf:       `($AUTOCONF --version) 2>/dev/null |$SED 1q`
 
@@ -2471,8 +2422,8 @@ libtool_options_prep ()
 
     if $_G_rc_lt_options_prep; then
       # Pass back the list of options.
-      func_quote eval ${1+"$@"}
-      libtool_options_prep_result=$func_quote_result
+      func_quote_for_eval ${1+"$@"}
+      libtool_options_prep_result=$func_quote_for_eval_result
     fi
 
     $_G_rc_lt_options_prep
@@ -2578,8 +2529,8 @@ libtool_parse_options ()
 
     if $_G_rc_lt_parse_options; then
       # save modified positional parameters for caller
-      func_quote eval ${1+"$@"}
-      libtool_parse_options_result=$func_quote_result
+      func_quote_for_eval ${1+"$@"}
+      libtool_parse_options_result=$func_quote_for_eval_result
     fi
 
     $_G_rc_lt_parse_options
@@ -2639,8 +2590,8 @@ libtool_validate_options ()
     }
 
     # Pass back the unparsed argument list
-    func_quote eval ${1+"$@"}
-    libtool_validate_options_result=$func_quote_result
+    func_quote_for_eval ${1+"$@"}
+    libtool_validate_options_result=$func_quote_for_eval_result
 }
 func_add_hook func_validate_options libtool_validate_options
 
@@ -3606,8 +3557,8 @@ func_mode_compile ()
       esac
     done
 
-    func_quote_arg pretty "$libobj"
-    test "X$libobj" != "X$func_quote_arg_result" \
+    func_quote_for_eval "$libobj"
+    test "X$libobj" != "X$func_quote_for_eval_result" \
       && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"'	 &()|`$[]' \
       && func_warning "libobj name '$libobj' may not contain shell special characters."
     func_dirname_and_basename "$obj" "/" ""
@@ -3680,8 +3631,8 @@ compiler."
 
     func_to_tool_file "$srcfile" func_convert_file_msys_to_w32
     srcfile=$func_to_tool_file_result
-    func_quote_arg pretty "$srcfile"
-    qsrcfile=$func_quote_arg_result
+    func_quote_for_eval "$srcfile"
+    qsrcfile=$func_quote_for_eval_result
 
     # Only build a PIC object if we are building libtool libraries.
     if test yes = "$build_libtool_libs"; then
@@ -4284,8 +4235,8 @@ func_mode_install ()
        case $nonopt in *shtool*) :;; *) false;; esac
     then
       # Aesthetically quote it.
-      func_quote_arg pretty "$nonopt"
-      install_prog="$func_quote_arg_result "
+      func_quote_for_eval "$nonopt"
+      install_prog="$func_quote_for_eval_result "
       arg=$1
       shift
     else
@@ -4295,8 +4246,8 @@ func_mode_install ()
 
     # The real first argument should be the name of the installation program.
     # Aesthetically quote it.
-    func_quote_arg pretty "$arg"
-    func_append install_prog "$func_quote_arg_result"
+    func_quote_for_eval "$arg"
+    func_append install_prog "$func_quote_for_eval_result"
     install_shared_prog=$install_prog
     case " $install_prog " in
       *[\\\ /]cp\ *) install_cp=: ;;
@@ -4353,12 +4304,12 @@ func_mode_install ()
       esac
 
       # Aesthetically quote the argument.
-      func_quote_arg pretty "$arg"
-      func_append install_prog " $func_quote_arg_result"
+      func_quote_for_eval "$arg"
+      func_append install_prog " $func_quote_for_eval_result"
       if test -n "$arg2"; then
-	func_quote_arg pretty "$arg2"
+	func_quote_for_eval "$arg2"
       fi
-      func_append install_shared_prog " $func_quote_arg_result"
+      func_append install_shared_prog " $func_quote_for_eval_result"
     done
 
     test -z "$install_prog" && \
@@ -4369,8 +4320,8 @@ func_mode_install ()
 
     if test -n "$install_override_mode" && $no_mode; then
       if $install_cp; then :; else
-	func_quote_arg pretty "$install_override_mode"
-	func_append install_shared_prog " -m $func_quote_arg_result"
+	func_quote_for_eval "$install_override_mode"
+	func_append install_shared_prog " -m $func_quote_for_eval_result"
       fi
     fi
 
@@ -4666,8 +4617,8 @@ func_mode_install ()
 	        relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'`
 
 	        $opt_quiet || {
-	          func_quote_arg expand,pretty "$relink_command"
-		  eval "func_echo $func_quote_arg_result"
+	          func_quote_for_expand "$relink_command"
+		  eval "func_echo $func_quote_for_expand_result"
 	        }
 	        if eval "$relink_command"; then :
 	          else
@@ -5446,8 +5397,8 @@ else
   if test \"\$libtool_execute_magic\" != \"$magic\"; then
     file=\"\$0\""
 
-    func_quote_arg pretty "$ECHO"
-    qECHO=$func_quote_arg_result
+    func_quote "$ECHO"
+    qECHO=$func_quote_result
     $ECHO "\
 
 # A function that is used when there is no print builtin or printf.
@@ -5457,7 +5408,7 @@ func_fallback_echo ()
 \$1
 _LTECHO_EOF'
 }
-    ECHO=$qECHO
+    ECHO=\"$qECHO\"
   fi
 
 # Very basic option parsing. These options are (a) specific to
@@ -6800,9 +6751,9 @@ func_mode_link ()
     while test "$#" -gt 0; do
       arg=$1
       shift
-      func_quote_arg pretty,unquoted "$arg"
-      qarg=$func_quote_arg_unquoted_result
-      func_append libtool_args " $func_quote_arg_result"
+      func_quote_for_eval "$arg"
+      qarg=$func_quote_for_eval_unquoted_result
+      func_append libtool_args " $func_quote_for_eval_result"
 
       # If the previous option needs an argument, assign it.
       if test -n "$prev"; then
@@ -7400,9 +7351,9 @@ func_mode_link ()
 	save_ifs=$IFS; IFS=,
 	for flag in $args; do
 	  IFS=$save_ifs
-          func_quote_arg pretty "$flag"
-	  func_append arg " $func_quote_arg_result"
-	  func_append compiler_flags " $func_quote_arg_result"
+          func_quote_for_eval "$flag"
+	  func_append arg " $func_quote_for_eval_result"
+	  func_append compiler_flags " $func_quote_for_eval_result"
 	done
 	IFS=$save_ifs
 	func_stripname ' ' '' "$arg"
@@ -7416,10 +7367,10 @@ func_mode_link ()
 	save_ifs=$IFS; IFS=,
 	for flag in $args; do
 	  IFS=$save_ifs
-          func_quote_arg pretty "$flag"
-	  func_append arg " $wl$func_quote_arg_result"
-	  func_append compiler_flags " $wl$func_quote_arg_result"
-	  func_append linker_flags " $func_quote_arg_result"
+          func_quote_for_eval "$flag"
+	  func_append arg " $wl$func_quote_for_eval_result"
+	  func_append compiler_flags " $wl$func_quote_for_eval_result"
+	  func_append linker_flags " $func_quote_for_eval_result"
 	done
 	IFS=$save_ifs
 	func_stripname ' ' '' "$arg"
@@ -7443,8 +7394,8 @@ func_mode_link ()
 
       # -msg_* for osf cc
       -msg_*)
-	func_quote_arg pretty "$arg"
-	arg=$func_quote_arg_result
+	func_quote_for_eval "$arg"
+	arg=$func_quote_for_eval_result
 	;;
 
       # Flags to be passed through unchanged, with rationale:
@@ -7468,8 +7419,8 @@ func_mode_link ()
       -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
       -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \
       -specs=*|-fsanitize=*)
-        func_quote_arg pretty "$arg"
-	arg=$func_quote_arg_result
+        func_quote_for_eval "$arg"
+	arg=$func_quote_for_eval_result
         func_append compile_command " $arg"
         func_append finalize_command " $arg"
         func_append compiler_flags " $arg"
@@ -7490,15 +7441,15 @@ func_mode_link ()
 	  continue
         else
 	  # Otherwise treat like 'Some other compiler flag' below
-	  func_quote_arg pretty "$arg"
-	  arg=$func_quote_arg_result
+	  func_quote_for_eval "$arg"
+	  arg=$func_quote_for_eval_result
         fi
 	;;
 
       # Some other compiler flag.
       -* | +*)
-        func_quote_arg pretty "$arg"
-	arg=$func_quote_arg_result
+        func_quote_for_eval "$arg"
+	arg=$func_quote_for_eval_result
 	;;
 
       *.$objext)
@@ -7618,8 +7569,8 @@ func_mode_link ()
       *)
 	# Unknown arguments in both finalize_command and compile_command need
 	# to be aesthetically quoted because they are evaled later.
-	func_quote_arg pretty "$arg"
-	arg=$func_quote_arg_result
+	func_quote_for_eval "$arg"
+	arg=$func_quote_for_eval_result
 	;;
       esac # arg
 
@@ -10131,8 +10082,8 @@ EOF
 	    for cmd in $concat_cmds; do
 	      IFS=$save_ifs
 	      $opt_quiet || {
-		  func_quote_arg expand,pretty "$cmd"
-		  eval "func_echo $func_quote_arg_result"
+		  func_quote_for_expand "$cmd"
+		  eval "func_echo $func_quote_for_expand_result"
 	      }
 	      $opt_dry_run || eval "$cmd" || {
 		lt_exit=$?
@@ -10225,8 +10176,8 @@ EOF
 	  eval cmd=\"$cmd\"
 	  IFS=$save_ifs
 	  $opt_quiet || {
-	    func_quote_arg expand,pretty "$cmd"
-	    eval "func_echo $func_quote_arg_result"
+	    func_quote_for_expand "$cmd"
+	    eval "func_echo $func_quote_for_expand_result"
 	  }
 	  $opt_dry_run || eval "$cmd" || {
 	    lt_exit=$?
@@ -10700,12 +10651,12 @@ EOF
 	  elif eval var_value=\$$var; test -z "$var_value"; then
 	    relink_command="$var=; export $var; $relink_command"
 	  else
-	    func_quote_arg pretty "$var_value"
-	    relink_command="$var=$func_quote_arg_result; export $var; $relink_command"
+	    func_quote_for_eval "$var_value"
+	    relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
 	  fi
 	done
-	func_quote_arg pretty,unquoted "(cd `pwd`; $relink_command)"
-	relink_command=$func_quote_arg_unquoted_result
+	func_quote "(cd `pwd`; $relink_command)"
+	relink_command=$func_quote_result
       fi
 
       # Only actually do things if not in dry run mode.
@@ -10945,14 +10896,14 @@ EOF
 	elif eval var_value=\$$var; test -z "$var_value"; then
 	  relink_command="$var=; export $var; $relink_command"
 	else
-	  func_quote_arg pretty,unquoted "$var_value"
-	  relink_command="$var=$func_quote_arg_unquoted_result; export $var; $relink_command"
+	  func_quote_for_eval "$var_value"
+	  relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
 	fi
       done
       # Quote the link command for shipping.
       relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
-      func_quote_arg pretty,unquoted "$relink_command"
-      relink_command=$func_quote_arg_unquoted_result
+      func_quote "$relink_command"
+      relink_command=$func_quote_result
       if test yes = "$hardcode_automatic"; then
 	relink_command=
       fi
diff --git a/spl/configure b/spl/configure
index 2e6f1ee..4c8fcc1 100755
--- a/spl/configure
+++ b/spl/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for spl 0.7.11.
+# Generated by GNU Autoconf 2.69 for spl 0.7.12.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -587,8 +587,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='spl'
 PACKAGE_TARNAME='spl'
-PACKAGE_VERSION='0.7.11'
-PACKAGE_STRING='spl 0.7.11'
+PACKAGE_VERSION='0.7.12'
+PACKAGE_STRING='spl 0.7.12'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -1389,7 +1389,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures spl 0.7.11 to adapt to many kinds of systems.
+\`configure' configures spl 0.7.12 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1461,7 +1461,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of spl 0.7.11:";;
+     short | recursive ) echo "Configuration of spl 0.7.12:";;
    esac
   cat <<\_ACEOF
 
@@ -1586,7 +1586,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-spl configure 0.7.11
+spl configure 0.7.12
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1864,7 +1864,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by spl $as_me 0.7.11, which was
+It was created by spl $as_me 0.7.12, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3005,7 +3005,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='spl'
- VERSION='0.7.11'
+ VERSION='0.7.12'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -6243,11 +6243,8 @@ _LT_EOF
   test $ac_status = 0; }; then
     # Now try to grab the symbols.
     nlist=conftest.nm
-    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5
-  (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; } && test -s "$nlist"; then
+    $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&5
+    if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&5 && test -s "$nlist"; then
       # Try sorting and uniquifying the output.
       if sort "$nlist" | uniq > "$nlist"T; then
 	mv -f "$nlist"T "$nlist"
@@ -19279,7 +19276,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by spl $as_me 0.7.11, which was
+This file was extended by spl $as_me 0.7.12, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -19345,7 +19342,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-spl config.status 0.7.11
+spl config.status 0.7.12
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/spl/dkms.conf b/spl/dkms.conf
index 62df11e..23bef46 100644
--- a/spl/dkms.conf
+++ b/spl/dkms.conf
@@ -1,6 +1,6 @@
 AUTOINSTALL="yes"
 PACKAGE_NAME="spl"
-PACKAGE_VERSION="0.7.11"
+PACKAGE_VERSION="0.7.12"
 PRE_BUILD="configure
   --prefix=/usr
   --with-config=kernel
diff --git a/spl/include/sys/time.h b/spl/include/sys/time.h
index 59557af..563c210 100644
--- a/spl/include/sys/time.h
+++ b/spl/include/sys/time.h
@@ -66,6 +66,9 @@ typedef struct timespec64	inode_timespec_t;
 typedef struct timespec		inode_timespec_t;
 #endif
 
+/* Include for Lustre compatibility */
+#define        timestruc_t     inode_timespec_t
+
 static inline void
 gethrestime(inode_timespec_t *ts)
  {
@@ -79,8 +82,11 @@ gethrestime(inode_timespec_t *ts)
 static inline time_t
 gethrestime_sec(void)
 {
-	struct timespec ts;
-	ts = current_kernel_time();
+#if defined(HAVE_INODE_TIMESPEC64_TIMES)
+	inode_timespec_t ts = current_kernel_time64();
+#else
+	inode_timespec_t ts = current_kernel_time();
+#endif
 	return (ts.tv_sec);
 }
 
diff --git a/spl/include/sys/vnode.h b/spl/include/sys/vnode.h
index 87f12d6..279bd87 100644
--- a/spl/include/sys/vnode.h
+++ b/spl/include/sys/vnode.h
@@ -87,7 +87,7 @@
 #define	AT_MTIME	ATTR_MTIME
 #define	AT_CTIME	ATTR_CTIME
 
-#define	ATTR_XVATTR	(1 << 31)
+#define	ATTR_XVATTR	(1U << 31)
 #define	AT_XVATTR	ATTR_XVATTR
 
 #define	ATTR_IATTR_MASK	(ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_SIZE | \
@@ -121,7 +121,7 @@ typedef enum vtype {
 
 typedef struct vattr {
 	enum vtype	va_type;	/* vnode type */
-	uint_t		va_mask;	/* attribute bit-mask */
+	uint32_t        va_mask;        /* attribute bit-mask */
 	ushort_t	va_mode;	/* acc mode */
 	uid_t		va_uid;		/* owner uid */
 	gid_t		va_gid;		/* owner gid */
diff --git a/spl/rpm/generic/spl-kmod.spec.in b/spl/rpm/generic/spl-kmod.spec.in
index 4cc1faf..ef32f93 100644
--- a/spl/rpm/generic/spl-kmod.spec.in
+++ b/spl/rpm/generic/spl-kmod.spec.in
@@ -26,6 +26,10 @@ URL:            http://zfsonlinux.org/
 Source0:        %{module}-%{version}.tar.gz
 Source10:       kmodtool
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id} -u -n)
+%if 0%{?rhel}%{?fedora}
+BuildRequires:  gcc, make
+BuildRequires:  elfutils-libelf-devel
+%endif
 
 # The developments headers will conflict with the dkms packages.
 Conflicts:      %{module}-dkms
@@ -167,6 +171,9 @@ chmod u+x ${RPM_BUILD_ROOT}%{kmodinstdir_prefix}/*/extra/*/*/*
 rm -rf $RPM_BUILD_ROOT
 
 %changelog
+* Thu Nov 08 2018 Tony Hutter <hutter2 at llnl.gov> - 0.7.12-1
+- Released 0.7.12-1, detailed release notes are available at:
+- https://github.com/zfsonlinux/zfs/releases/tag/zfs-0.7.12
 * Thu Sep 13 2018 Tony Hutter <hutter2 at llnl.gov> - 0.7.11-1
 - Released 0.7.11-1, detailed release notes are available at:
 - https://github.com/zfsonlinux/zfs/releases/tag/zfs-0.7.11
diff --git a/spl/rpm/generic/spl.spec.in b/spl/rpm/generic/spl.spec.in
index 4b3a3d7..30ed496 100644
--- a/spl/rpm/generic/spl.spec.in
+++ b/spl/rpm/generic/spl.spec.in
@@ -20,6 +20,9 @@ Source0:        %{name}-%{version}.tar.gz
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 Requires:       %{name}-kmod = %{version}
 Provides:       %{name}-kmod-common = %{version}
+%if 0%{?rhel}%{?fedora}%{?suse_version}
+BuildRequires:  gcc, make
+%endif
 
 %description
 This package contains the commands to verify the SPL
@@ -44,6 +47,9 @@ make install DESTDIR=%{?buildroot}
 %{_mandir}/man5/*
 
 %changelog
+* Thu Nov 08 2018 Tony Hutter <hutter2 at llnl.gov> - 0.7.12-1
+- Released 0.7.12-1, detailed release notes are available at:
+- https://github.com/zfsonlinux/zfs/releases/tag/zfs-0.7.12
 * Thu Sep 13 2018 Tony Hutter <hutter2 at llnl.gov> - 0.7.11-1
 - Released 0.7.11-1, detailed release notes are available at:
 - https://github.com/zfsonlinux/zfs/releases/tag/zfs-0.7.11
diff --git a/spl/rpm/redhat/spl.spec.in b/spl/rpm/redhat/spl.spec.in
index 4b3a3d7..30ed496 100644
--- a/spl/rpm/redhat/spl.spec.in
+++ b/spl/rpm/redhat/spl.spec.in
@@ -20,6 +20,9 @@ Source0:        %{name}-%{version}.tar.gz
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 Requires:       %{name}-kmod = %{version}
 Provides:       %{name}-kmod-common = %{version}
+%if 0%{?rhel}%{?fedora}%{?suse_version}
+BuildRequires:  gcc, make
+%endif
 
 %description
 This package contains the commands to verify the SPL
@@ -44,6 +47,9 @@ make install DESTDIR=%{?buildroot}
 %{_mandir}/man5/*
 
 %changelog
+* Thu Nov 08 2018 Tony Hutter <hutter2 at llnl.gov> - 0.7.12-1
+- Released 0.7.12-1, detailed release notes are available at:
+- https://github.com/zfsonlinux/zfs/releases/tag/zfs-0.7.12
 * Thu Sep 13 2018 Tony Hutter <hutter2 at llnl.gov> - 0.7.11-1
 - Released 0.7.11-1, detailed release notes are available at:
 - https://github.com/zfsonlinux/zfs/releases/tag/zfs-0.7.11
diff --git a/zfs/META b/zfs/META
index 04a7c41..66a4c0d 100644
--- a/zfs/META
+++ b/zfs/META
@@ -1,8 +1,8 @@
 Meta:         1
 Name:         zfs
 Branch:       1.0
-Version:      0.7.11
-Release:      3ubuntu1
+Version:      0.7.12
+Release:      1ubuntu1
 Release-Tags: relext
 License:      CDDL
 Author:       OpenZFS on Linux
diff --git a/zfs/Makefile.in b/zfs/Makefile.in
index 40a67b1..b861303 100644
--- a/zfs/Makefile.in
+++ b/zfs/Makefile.in
@@ -157,6 +157,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-arch.m4 \
 	$(top_srcdir)/config/kernel-get-gendisk.m4 \
 	$(top_srcdir)/config/kernel-get-link.m4 \
 	$(top_srcdir)/config/kernel-global_page_state.m4 \
+	$(top_srcdir)/config/kernel-in-compat-syscall.m4 \
 	$(top_srcdir)/config/kernel-inode-getattr.m4 \
 	$(top_srcdir)/config/kernel-inode-set-flags.m4 \
 	$(top_srcdir)/config/kernel-inode-set-iversion.m4 \
diff --git a/zfs/aclocal.m4 b/zfs/aclocal.m4
index 0b2b76e..ad1c4ed 100644
--- a/zfs/aclocal.m4
+++ b/zfs/aclocal.m4
@@ -1247,6 +1247,7 @@ m4_include([config/kernel-get-disk-ro.m4])
 m4_include([config/kernel-get-gendisk.m4])
 m4_include([config/kernel-get-link.m4])
 m4_include([config/kernel-global_page_state.m4])
+m4_include([config/kernel-in-compat-syscall.m4])
 m4_include([config/kernel-inode-getattr.m4])
 m4_include([config/kernel-inode-set-flags.m4])
 m4_include([config/kernel-inode-set-iversion.m4])
diff --git a/zfs/config/kernel-in-compat-syscall.m4 b/zfs/config/kernel-in-compat-syscall.m4
new file mode 100644
index 0000000..9fca9da
--- /dev/null
+++ b/zfs/config/kernel-in-compat-syscall.m4
@@ -0,0 +1,20 @@
+dnl #
+dnl # 4.5 API change
+dnl # Added in_compat_syscall() which can be overridden on a per-
+dnl # architecture basis.  Prior to this is_compat_task() was the
+dnl # provided interface.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_IN_COMPAT_SYSCALL], [
+	AC_MSG_CHECKING([whether in_compat_syscall() is available])
+	ZFS_LINUX_TRY_COMPILE([
+		#include <linux/compat.h>
+	],[
+		in_compat_syscall();
+	],[
+		AC_MSG_RESULT(yes)
+		AC_DEFINE(HAVE_IN_COMPAT_SYSCALL, 1,
+		    [in_compat_syscall() is available])
+	],[
+		AC_MSG_RESULT(no)
+	])
+])
diff --git a/zfs/config/kernel.m4 b/zfs/config/kernel.m4
index c7ca260..3777f45 100644
--- a/zfs/config/kernel.m4
+++ b/zfs/config/kernel.m4
@@ -129,6 +129,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
 	ZFS_AC_KERNEL_GLOBAL_PAGE_STATE
 	ZFS_AC_KERNEL_ACL_HAS_REFCOUNT
 	ZFS_AC_KERNEL_USERNS_CAPABILITIES
+	ZFS_AC_KERNEL_IN_COMPAT_SYSCALL
 
 	AS_IF([test "$LINUX_OBJ" != "$LINUX"], [
 		KERNELMAKE_PARAMS="$KERNELMAKE_PARAMS O=$LINUX_OBJ"
diff --git a/zfs/config/libtool.m4 b/zfs/config/libtool.m4
index e67ed69..c81e669 100644
--- a/zfs/config/libtool.m4
+++ b/zfs/config/libtool.m4
@@ -4063,7 +4063,8 @@ _LT_EOF
   if AC_TRY_EVAL(ac_compile); then
     # Now try to grab the symbols.
     nlist=conftest.nm
-    if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
+    $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD
+    if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then
       # Try sorting and uniquifying the output.
       if sort "$nlist" | uniq > "$nlist"T; then
 	mv -f "$nlist"T "$nlist"
diff --git a/zfs/config/ltmain.sh b/zfs/config/ltmain.sh
index d3230f7..68fd36c 100644
--- a/zfs/config/ltmain.sh
+++ b/zfs/config/ltmain.sh
@@ -31,7 +31,7 @@
 
 PROGRAM=libtool
 PACKAGE=libtool
-VERSION="2.4.6 Debian-2.4.6-4"
+VERSION="2.4.6 Debian-2.4.6-6"
 package_revision=2.4.6
 
 
@@ -64,7 +64,7 @@ package_revision=2.4.6
 # libraries, which are installed to $pkgauxdir.
 
 # Set a version string for this script.
-scriptversion=2015-10-12.13; # UTC
+scriptversion=2015-10-04.22; # UTC
 
 # General shell script boiler plate, and helper functions.
 # Written by Gary V. Vaughan, 2004
@@ -580,16 +580,16 @@ if test yes = "$_G_HAVE_PLUSEQ_OP"; then
   {
     $debug_cmd
 
-    func_quote_arg pretty "$2"
-    eval "$1+=\\ \$func_quote_arg_result"
+    func_quote_for_eval "$2"
+    eval "$1+=\\ \$func_quote_for_eval_result"
   }'
 else
   func_append_quoted ()
   {
     $debug_cmd
 
-    func_quote_arg pretty "$2"
-    eval "$1=\$$1\\ \$func_quote_arg_result"
+    func_quote_for_eval "$2"
+    eval "$1=\$$1\\ \$func_quote_for_eval_result"
   }
 fi
 
@@ -1091,184 +1091,135 @@ func_relative_path ()
 }
 
 
-# func_quote_portable EVAL ARG
-# ----------------------------
-# Internal function to portably implement func_quote_arg.  Note that we still
-# keep attention to performance here so we as much as possible try to avoid
-# calling sed binary (so far O(N) complexity as long as func_append is O(1)).
-func_quote_portable ()
+# func_quote ARG
+# --------------
+# Aesthetically quote one ARG, store the result into $func_quote_result.  Note
+# that we keep attention to performance here (so far O(N) complexity as long as
+# func_append is O(1)).
+func_quote ()
 {
     $debug_cmd
 
-    func_quote_portable_result=$2
-
-    # one-time-loop (easy break)
-    while true
-    do
-      if $1; then
-        func_quote_portable_result=`$ECHO "$2" | $SED \
-          -e "$sed_double_quote_subst" -e "$sed_double_backslash"`
-        break
-      fi
+    func_quote_result=$1
 
-      # Quote for eval.
-      case $func_quote_portable_result in
-        *[\\\`\"\$]*)
-          case $func_quote_portable_result in
-            *[\[\*\?]*)
-              func_quote_portable_result=`$ECHO "$func_quote_portable_result" | $SED "$sed_quote_subst"`
-              break
-              ;;
-          esac
+    case $func_quote_result in
+      *[\\\`\"\$]*)
+        case $func_quote_result in
+          *[\[\*\?]*)
+            func_quote_result=`$ECHO "$func_quote_result" | $SED "$sed_quote_subst"`
+            return 0
+            ;;
+        esac
 
-          func_quote_portable_old_IFS=$IFS
-          for _G_char in '\' '`' '"' '$'
+        func_quote_old_IFS=$IFS
+        for _G_char in '\' '`' '"' '$'
+        do
+          # STATE($1) PREV($2) SEPARATOR($3)
+          set start "" ""
+          func_quote_result=dummy"$_G_char$func_quote_result$_G_char"dummy
+          IFS=$_G_char
+          for _G_part in $func_quote_result
           do
-            # STATE($1) PREV($2) SEPARATOR($3)
-            set start "" ""
-            func_quote_portable_result=dummy"$_G_char$func_quote_portable_result$_G_char"dummy
-            IFS=$_G_char
-            for _G_part in $func_quote_portable_result
-            do
-              case $1 in
-              quote)
-                func_append func_quote_portable_result "$3$2"
-                set quote "$_G_part" "\\$_G_char"
-                ;;
-              start)
-                set first "" ""
-                func_quote_portable_result=
-                ;;
-              first)
-                set quote "$_G_part" ""
-                ;;
-              esac
-            done
+            case $1 in
+            quote)
+              func_append func_quote_result "$3$2"
+              set quote "$_G_part" "\\$_G_char"
+              ;;
+            start)
+              set first "" ""
+              func_quote_result=
+              ;;
+            first)
+              set quote "$_G_part" ""
+              ;;
+            esac
           done
-          IFS=$func_quote_portable_old_IFS
-          ;;
-        *) ;;
-      esac
-      break
-    done
-
-    func_quote_portable_unquoted_result=$func_quote_portable_result
-    case $func_quote_portable_result in
-      # double-quote args containing shell metacharacters to delay
-      # word splitting, command substitution and variable expansion
-      # for a subsequent eval.
-      # many bourne shells cannot handle close brackets correctly
-      # in scan sets, so we specify it separately.
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-        func_quote_portable_result=\"$func_quote_portable_result\"
+          IFS=$func_quote_old_IFS
+        done
         ;;
+      *) ;;
     esac
 }
 
 
-# func_quotefast_eval ARG
-# -----------------------
-# Quote one ARG (internal).  This is equivalent to 'func_quote_arg eval ARG',
-# but optimized for speed.  Result is stored in $func_quotefast_eval.
-if test xyes = `(x=; printf -v x %q yes; echo x"$x") 2>/dev/null`; then
-  func_quotefast_eval ()
-  {
-    printf -v func_quotefast_eval_result %q "$1"
-  }
-else
-  func_quotefast_eval ()
-  {
-    func_quote_portable false "$1"
-    func_quotefast_eval_result=$func_quote_portable_result
-  }
-fi
-
-
-# func_quote_arg MODEs ARG
-# ------------------------
-# Quote one ARG to be evaled later.  MODEs argument may contain zero ore more
-# specifiers listed below separated by ',' character.  This function returns two
-# values:
-#   i) func_quote_arg_result
-#      double-quoted (when needed), suitable for a subsequent eval
-#  ii) func_quote_arg_unquoted_result
+# func_quote_for_eval ARG...
+# --------------------------
+# Aesthetically quote ARGs to be evaled later.
+# This function returns two values:
+#   i) func_quote_for_eval_result
+#      double-quoted, suitable for a subsequent eval
+#  ii) func_quote_for_eval_unquoted_result
 #      has all characters that are still active within double
-#      quotes backslashified.  Available only if 'unquoted' is specified.
-#
-# Available modes:
-# ----------------
-# 'eval' (default)
-#       - escape shell special characters
-# 'expand'
-#       - the same as 'eval';  but do not quote variable references
-# 'pretty'
-#       - request aesthetic output, i.e. '"a b"' instead of 'a\ b'.  This might
-#         later used in func_quote to get output like: 'echo "a b"' instead of
-#         'echo a\ b'.  This is slower than default on some shells.
-# 'unquoted'
-#       - produce also $func_quote_arg_unquoted_result which does not contain
-#         wrapping double-quotes.
-#
-# Examples for 'func_quote_arg pretty,unquoted string':
-#
-#   string      | *_result              | *_unquoted_result
-#   ------------+-----------------------+-------------------
-#   "           | \"                    | \"
-#   a b         | "a b"                 | a b
-#   "a b"       | "\"a b\""             | \"a b\"
-#   *           | "*"                   | *
-#   z="${x-$y}" | "z=\"\${x-\$y}\""     | z=\"\${x-\$y}\"
-#
-# Examples for 'func_quote_arg pretty,unquoted,expand string':
-#
-#   string        |   *_result          |  *_unquoted_result
-#   --------------+---------------------+--------------------
-#   z="${x-$y}"   | "z=\"${x-$y}\""     | z=\"${x-$y}\"
-func_quote_arg ()
-{
-    _G_quote_expand=false
-    case ,$1, in
-      *,expand,*)
-        _G_quote_expand=:
-        ;;
-    esac
-
-    case ,$1, in
-      *,pretty,*|*,expand,*|*,unquoted,*)
-        func_quote_portable $_G_quote_expand "$2"
-        func_quote_arg_result=$func_quote_portable_result
-        func_quote_arg_unquoted_result=$func_quote_portable_unquoted_result
-        ;;
-      *)
-        # Faster quote-for-eval for some shells.
-        func_quotefast_eval "$2"
-        func_quote_arg_result=$func_quotefast_eval_result
-        ;;
-    esac
-}
-
-
-# func_quote MODEs ARGs...
-# ------------------------
-# Quote all ARGs to be evaled later and join them into single command.  See
-# func_quote_arg's description for more info.
-func_quote ()
+#      quotes backslashified.
+func_quote_for_eval ()
 {
     $debug_cmd
-    _G_func_quote_mode=$1 ; shift
-    func_quote_result=
+
+    func_quote_for_eval_unquoted_result=
+    func_quote_for_eval_result=
     while test 0 -lt $#; do
-      func_quote_arg "$_G_func_quote_mode" "$1"
-      if test -n "$func_quote_result"; then
-        func_append func_quote_result " $func_quote_arg_result"
+      func_quote "$1"
+      _G_unquoted_arg=$func_quote_result
+      if test -n "$func_quote_for_eval_unquoted_result"; then
+	func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg"
       else
-        func_append func_quote_result "$func_quote_arg_result"
+        func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg"
+      fi
+
+      case $_G_unquoted_arg in
+        # Double-quote args containing shell metacharacters to delay
+        # word splitting, command substitution and variable expansion
+        # for a subsequent eval.
+        # Many Bourne shells cannot handle close brackets correctly
+        # in scan sets, so we specify it separately.
+        *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+          _G_quoted_arg=\"$_G_unquoted_arg\"
+          ;;
+        *)
+          _G_quoted_arg=$_G_unquoted_arg
+	  ;;
+      esac
+
+      if test -n "$func_quote_for_eval_result"; then
+	func_append func_quote_for_eval_result " $_G_quoted_arg"
+      else
+        func_append func_quote_for_eval_result "$_G_quoted_arg"
       fi
       shift
     done
 }
 
 
+# func_quote_for_expand ARG
+# -------------------------
+# Aesthetically quote ARG to be evaled later; same as above,
+# but do not quote variable references.
+func_quote_for_expand ()
+{
+    $debug_cmd
+
+    case $1 in
+      *[\\\`\"]*)
+	_G_arg=`$ECHO "$1" | $SED \
+	    -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;;
+      *)
+        _G_arg=$1 ;;
+    esac
+
+    case $_G_arg in
+      # Double-quote args containing shell metacharacters to delay
+      # word splitting and command substitution for a subsequent eval.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+        _G_arg=\"$_G_arg\"
+        ;;
+    esac
+
+    func_quote_for_expand_result=$_G_arg
+}
+
+
 # func_stripname PREFIX SUFFIX NAME
 # ---------------------------------
 # strip PREFIX and SUFFIX from NAME, and store in func_stripname_result.
@@ -1311,8 +1262,8 @@ func_show_eval ()
     _G_cmd=$1
     _G_fail_exp=${2-':'}
 
-    func_quote_arg pretty,expand "$_G_cmd"
-    eval "func_notquiet $func_quote_arg_result"
+    func_quote_for_expand "$_G_cmd"
+    eval "func_notquiet $func_quote_for_expand_result"
 
     $opt_dry_run || {
       eval "$_G_cmd"
@@ -1337,8 +1288,8 @@ func_show_eval_locale ()
     _G_fail_exp=${2-':'}
 
     $opt_quiet || {
-      func_quote_arg expand,pretty "$_G_cmd"
-      eval "func_echo $func_quote_arg_result"
+      func_quote_for_expand "$_G_cmd"
+      eval "func_echo $func_quote_for_expand_result"
     }
 
     $opt_dry_run || {
@@ -1466,7 +1417,7 @@ func_lt_ver ()
 #! /bin/sh
 
 # Set a version string for this script.
-scriptversion=2015-10-12.13; # UTC
+scriptversion=2015-10-07.11; # UTC
 
 # A portable, pluggable option parser for Bourne shell.
 # Written by Gary V. Vaughan, 2010
@@ -1676,8 +1627,8 @@ func_run_hooks ()
 #    '
 #        # No change in '$@' (ignored completely by this hook).  There is
 #        # no need to do the equivalent (but slower) action:
-#        # func_quote eval ${1+"$@"}
-#        # my_options_prep_result=$func_quote_result
+#        # func_quote_for_eval ${1+"$@"}
+#        # my_options_prep_result=$func_quote_for_eval_result
 #        false
 #    }
 #    func_add_hook func_options_prep my_options_prep
@@ -1713,8 +1664,8 @@ func_run_hooks ()
 #        done
 #
 #        if $args_changed; then
-#          func_quote eval ${1+"$@"}
-#          my_silent_option_result=$func_quote_result
+#          func_quote_for_eval ${1+"$@"}
+#          my_silent_option_result=$func_quote_for_eval_result
 #        fi
 #
 #        $args_changed
@@ -1781,8 +1732,8 @@ func_options ()
     if $_G_rc_options; then
       func_options_result=$_G_res_var
     else
-      func_quote eval ${1+"$@"}
-      func_options_result=$func_quote_result
+      func_quote_for_eval ${1+"$@"}
+      func_options_result=$func_quote_for_eval_result
     fi
 
     $_G_rc_options
@@ -1925,8 +1876,8 @@ func_parse_options ()
 
     if $_G_rc_parse_options; then
       # save modified positional parameters for caller
-      func_quote eval ${1+"$@"}
-      func_parse_options_result=$func_quote_result
+      func_quote_for_eval ${1+"$@"}
+      func_parse_options_result=$func_quote_for_eval_result
     fi
 
     $_G_rc_parse_options
@@ -2237,7 +2188,7 @@ include the following information:
        compiler:       $LTCC
        compiler flags: $LTCFLAGS
        linker:         $LD (gnu? $with_gnu_ld)
-       version:        $progname $scriptversion Debian-2.4.6-4
+       version:        $progname $scriptversion Debian-2.4.6-6
        automake:       `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
        autoconf:       `($AUTOCONF --version) 2>/dev/null |$SED 1q`
 
@@ -2471,8 +2422,8 @@ libtool_options_prep ()
 
     if $_G_rc_lt_options_prep; then
       # Pass back the list of options.
-      func_quote eval ${1+"$@"}
-      libtool_options_prep_result=$func_quote_result
+      func_quote_for_eval ${1+"$@"}
+      libtool_options_prep_result=$func_quote_for_eval_result
     fi
 
     $_G_rc_lt_options_prep
@@ -2578,8 +2529,8 @@ libtool_parse_options ()
 
     if $_G_rc_lt_parse_options; then
       # save modified positional parameters for caller
-      func_quote eval ${1+"$@"}
-      libtool_parse_options_result=$func_quote_result
+      func_quote_for_eval ${1+"$@"}
+      libtool_parse_options_result=$func_quote_for_eval_result
     fi
 
     $_G_rc_lt_parse_options
@@ -2639,8 +2590,8 @@ libtool_validate_options ()
     }
 
     # Pass back the unparsed argument list
-    func_quote eval ${1+"$@"}
-    libtool_validate_options_result=$func_quote_result
+    func_quote_for_eval ${1+"$@"}
+    libtool_validate_options_result=$func_quote_for_eval_result
 }
 func_add_hook func_validate_options libtool_validate_options
 
@@ -3606,8 +3557,8 @@ func_mode_compile ()
       esac
     done
 
-    func_quote_arg pretty "$libobj"
-    test "X$libobj" != "X$func_quote_arg_result" \
+    func_quote_for_eval "$libobj"
+    test "X$libobj" != "X$func_quote_for_eval_result" \
       && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"'	 &()|`$[]' \
       && func_warning "libobj name '$libobj' may not contain shell special characters."
     func_dirname_and_basename "$obj" "/" ""
@@ -3680,8 +3631,8 @@ compiler."
 
     func_to_tool_file "$srcfile" func_convert_file_msys_to_w32
     srcfile=$func_to_tool_file_result
-    func_quote_arg pretty "$srcfile"
-    qsrcfile=$func_quote_arg_result
+    func_quote_for_eval "$srcfile"
+    qsrcfile=$func_quote_for_eval_result
 
     # Only build a PIC object if we are building libtool libraries.
     if test yes = "$build_libtool_libs"; then
@@ -4284,8 +4235,8 @@ func_mode_install ()
        case $nonopt in *shtool*) :;; *) false;; esac
     then
       # Aesthetically quote it.
-      func_quote_arg pretty "$nonopt"
-      install_prog="$func_quote_arg_result "
+      func_quote_for_eval "$nonopt"
+      install_prog="$func_quote_for_eval_result "
       arg=$1
       shift
     else
@@ -4295,8 +4246,8 @@ func_mode_install ()
 
     # The real first argument should be the name of the installation program.
     # Aesthetically quote it.
-    func_quote_arg pretty "$arg"
-    func_append install_prog "$func_quote_arg_result"
+    func_quote_for_eval "$arg"
+    func_append install_prog "$func_quote_for_eval_result"
     install_shared_prog=$install_prog
     case " $install_prog " in
       *[\\\ /]cp\ *) install_cp=: ;;
@@ -4353,12 +4304,12 @@ func_mode_install ()
       esac
 
       # Aesthetically quote the argument.
-      func_quote_arg pretty "$arg"
-      func_append install_prog " $func_quote_arg_result"
+      func_quote_for_eval "$arg"
+      func_append install_prog " $func_quote_for_eval_result"
       if test -n "$arg2"; then
-	func_quote_arg pretty "$arg2"
+	func_quote_for_eval "$arg2"
       fi
-      func_append install_shared_prog " $func_quote_arg_result"
+      func_append install_shared_prog " $func_quote_for_eval_result"
     done
 
     test -z "$install_prog" && \
@@ -4369,8 +4320,8 @@ func_mode_install ()
 
     if test -n "$install_override_mode" && $no_mode; then
       if $install_cp; then :; else
-	func_quote_arg pretty "$install_override_mode"
-	func_append install_shared_prog " -m $func_quote_arg_result"
+	func_quote_for_eval "$install_override_mode"
+	func_append install_shared_prog " -m $func_quote_for_eval_result"
       fi
     fi
 
@@ -4666,8 +4617,8 @@ func_mode_install ()
 	        relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'`
 
 	        $opt_quiet || {
-	          func_quote_arg expand,pretty "$relink_command"
-		  eval "func_echo $func_quote_arg_result"
+	          func_quote_for_expand "$relink_command"
+		  eval "func_echo $func_quote_for_expand_result"
 	        }
 	        if eval "$relink_command"; then :
 	          else
@@ -5446,8 +5397,8 @@ else
   if test \"\$libtool_execute_magic\" != \"$magic\"; then
     file=\"\$0\""
 
-    func_quote_arg pretty "$ECHO"
-    qECHO=$func_quote_arg_result
+    func_quote "$ECHO"
+    qECHO=$func_quote_result
     $ECHO "\
 
 # A function that is used when there is no print builtin or printf.
@@ -5457,7 +5408,7 @@ func_fallback_echo ()
 \$1
 _LTECHO_EOF'
 }
-    ECHO=$qECHO
+    ECHO=\"$qECHO\"
   fi
 
 # Very basic option parsing. These options are (a) specific to
@@ -6800,9 +6751,9 @@ func_mode_link ()
     while test "$#" -gt 0; do
       arg=$1
       shift
-      func_quote_arg pretty,unquoted "$arg"
-      qarg=$func_quote_arg_unquoted_result
-      func_append libtool_args " $func_quote_arg_result"
+      func_quote_for_eval "$arg"
+      qarg=$func_quote_for_eval_unquoted_result
+      func_append libtool_args " $func_quote_for_eval_result"
 
       # If the previous option needs an argument, assign it.
       if test -n "$prev"; then
@@ -7400,9 +7351,9 @@ func_mode_link ()
 	save_ifs=$IFS; IFS=,
 	for flag in $args; do
 	  IFS=$save_ifs
-          func_quote_arg pretty "$flag"
-	  func_append arg " $func_quote_arg_result"
-	  func_append compiler_flags " $func_quote_arg_result"
+          func_quote_for_eval "$flag"
+	  func_append arg " $func_quote_for_eval_result"
+	  func_append compiler_flags " $func_quote_for_eval_result"
 	done
 	IFS=$save_ifs
 	func_stripname ' ' '' "$arg"
@@ -7416,10 +7367,10 @@ func_mode_link ()
 	save_ifs=$IFS; IFS=,
 	for flag in $args; do
 	  IFS=$save_ifs
-          func_quote_arg pretty "$flag"
-	  func_append arg " $wl$func_quote_arg_result"
-	  func_append compiler_flags " $wl$func_quote_arg_result"
-	  func_append linker_flags " $func_quote_arg_result"
+          func_quote_for_eval "$flag"
+	  func_append arg " $wl$func_quote_for_eval_result"
+	  func_append compiler_flags " $wl$func_quote_for_eval_result"
+	  func_append linker_flags " $func_quote_for_eval_result"
 	done
 	IFS=$save_ifs
 	func_stripname ' ' '' "$arg"
@@ -7443,8 +7394,8 @@ func_mode_link ()
 
       # -msg_* for osf cc
       -msg_*)
-	func_quote_arg pretty "$arg"
-	arg=$func_quote_arg_result
+	func_quote_for_eval "$arg"
+	arg=$func_quote_for_eval_result
 	;;
 
       # Flags to be passed through unchanged, with rationale:
@@ -7468,8 +7419,8 @@ func_mode_link ()
       -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
       -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \
       -specs=*|-fsanitize=*)
-        func_quote_arg pretty "$arg"
-	arg=$func_quote_arg_result
+        func_quote_for_eval "$arg"
+	arg=$func_quote_for_eval_result
         func_append compile_command " $arg"
         func_append finalize_command " $arg"
         func_append compiler_flags " $arg"
@@ -7490,15 +7441,15 @@ func_mode_link ()
 	  continue
         else
 	  # Otherwise treat like 'Some other compiler flag' below
-	  func_quote_arg pretty "$arg"
-	  arg=$func_quote_arg_result
+	  func_quote_for_eval "$arg"
+	  arg=$func_quote_for_eval_result
         fi
 	;;
 
       # Some other compiler flag.
       -* | +*)
-        func_quote_arg pretty "$arg"
-	arg=$func_quote_arg_result
+        func_quote_for_eval "$arg"
+	arg=$func_quote_for_eval_result
 	;;
 
       *.$objext)
@@ -7618,8 +7569,8 @@ func_mode_link ()
       *)
 	# Unknown arguments in both finalize_command and compile_command need
 	# to be aesthetically quoted because they are evaled later.
-	func_quote_arg pretty "$arg"
-	arg=$func_quote_arg_result
+	func_quote_for_eval "$arg"
+	arg=$func_quote_for_eval_result
 	;;
       esac # arg
 
@@ -10131,8 +10082,8 @@ EOF
 	    for cmd in $concat_cmds; do
 	      IFS=$save_ifs
 	      $opt_quiet || {
-		  func_quote_arg expand,pretty "$cmd"
-		  eval "func_echo $func_quote_arg_result"
+		  func_quote_for_expand "$cmd"
+		  eval "func_echo $func_quote_for_expand_result"
 	      }
 	      $opt_dry_run || eval "$cmd" || {
 		lt_exit=$?
@@ -10225,8 +10176,8 @@ EOF
 	  eval cmd=\"$cmd\"
 	  IFS=$save_ifs
 	  $opt_quiet || {
-	    func_quote_arg expand,pretty "$cmd"
-	    eval "func_echo $func_quote_arg_result"
+	    func_quote_for_expand "$cmd"
+	    eval "func_echo $func_quote_for_expand_result"
 	  }
 	  $opt_dry_run || eval "$cmd" || {
 	    lt_exit=$?
@@ -10700,12 +10651,12 @@ EOF
 	  elif eval var_value=\$$var; test -z "$var_value"; then
 	    relink_command="$var=; export $var; $relink_command"
 	  else
-	    func_quote_arg pretty "$var_value"
-	    relink_command="$var=$func_quote_arg_result; export $var; $relink_command"
+	    func_quote_for_eval "$var_value"
+	    relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
 	  fi
 	done
-	func_quote_arg pretty,unquoted "(cd `pwd`; $relink_command)"
-	relink_command=$func_quote_arg_unquoted_result
+	func_quote "(cd `pwd`; $relink_command)"
+	relink_command=$func_quote_result
       fi
 
       # Only actually do things if not in dry run mode.
@@ -10945,14 +10896,14 @@ EOF
 	elif eval var_value=\$$var; test -z "$var_value"; then
 	  relink_command="$var=; export $var; $relink_command"
 	else
-	  func_quote_arg pretty,unquoted "$var_value"
-	  relink_command="$var=$func_quote_arg_unquoted_result; export $var; $relink_command"
+	  func_quote_for_eval "$var_value"
+	  relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
 	fi
       done
       # Quote the link command for shipping.
       relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
-      func_quote_arg pretty,unquoted "$relink_command"
-      relink_command=$func_quote_arg_unquoted_result
+      func_quote "$relink_command"
+      relink_command=$func_quote_result
       if test yes = "$hardcode_automatic"; then
 	relink_command=
       fi
diff --git a/zfs/configure b/zfs/configure
index 853e1c8..f08079c 100755
--- a/zfs/configure
+++ b/zfs/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for zfs 0.7.11.
+# Generated by GNU Autoconf 2.69 for zfs 0.7.12.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -587,8 +587,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='zfs'
 PACKAGE_TARNAME='zfs'
-PACKAGE_VERSION='0.7.11'
-PACKAGE_STRING='zfs 0.7.11'
+PACKAGE_VERSION='0.7.12'
+PACKAGE_STRING='zfs 0.7.12'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -1439,7 +1439,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures zfs 0.7.11 to adapt to many kinds of systems.
+\`configure' configures zfs 0.7.12 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1511,7 +1511,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of zfs 0.7.11:";;
+     short | recursive ) echo "Configuration of zfs 0.7.12:";;
    esac
   cat <<\_ACEOF
 
@@ -1657,7 +1657,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-zfs configure 0.7.11
+zfs configure 0.7.12
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2022,7 +2022,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by zfs $as_me 0.7.11, which was
+It was created by zfs $as_me 0.7.12, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3189,7 +3189,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='zfs'
- VERSION='0.7.11'
+ VERSION='0.7.12'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -6427,11 +6427,8 @@ _LT_EOF
   test $ac_status = 0; }; then
     # Now try to grab the symbols.
     nlist=conftest.nm
-    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5
-  (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; } && test -s "$nlist"; then
+    $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&5
+    if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&5 && test -s "$nlist"; then
       # Try sorting and uniquifying the output.
       if sort "$nlist" | uniq > "$nlist"T; then
 	mv -f "$nlist"T "$nlist"
@@ -26974,6 +26971,71 @@ fi
 
 
 
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether in_compat_syscall() is available" >&5
+$as_echo_n "checking whether in_compat_syscall() is available... " >&6; }
+
+
+cat confdefs.h - <<_ACEOF >conftest.c
+
+
+		#include <linux/compat.h>
+
+int
+main (void)
+{
+
+		in_compat_syscall();
+
+  ;
+  return 0;
+}
+
+_ACEOF
+
+
+
+cat - <<_ACEOF >conftest.h
+
+_ACEOF
+
+
+	rm -Rf build && mkdir -p build && touch build/conftest.mod.c
+	echo "obj-m := conftest.o" >build/Makefile
+	modpost_flag=''
+	test "x$enable_linux_builtin" = xyes && modpost_flag='modpost=true' # fake modpost stage
+	if { ac_try='cp conftest.c conftest.h build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror $FRAME_LARGER_THAN $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build $modpost_flag'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; } >/dev/null && { ac_try='test -s build/conftest.o'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_IN_COMPAT_SYSCALL 1" >>confdefs.h
+
+
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+
+
+fi
+	rm -Rf build
+
+
+
+
 	if test "$LINUX_OBJ" != "$LINUX"; then :
 
 		KERNELMAKE_PARAMS="$KERNELMAKE_PARAMS O=$LINUX_OBJ"
@@ -42536,6 +42598,71 @@ fi
 
 
 
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether in_compat_syscall() is available" >&5
+$as_echo_n "checking whether in_compat_syscall() is available... " >&6; }
+
+
+cat confdefs.h - <<_ACEOF >conftest.c
+
+
+		#include <linux/compat.h>
+
+int
+main (void)
+{
+
+		in_compat_syscall();
+
+  ;
+  return 0;
+}
+
+_ACEOF
+
+
+
+cat - <<_ACEOF >conftest.h
+
+_ACEOF
+
+
+	rm -Rf build && mkdir -p build && touch build/conftest.mod.c
+	echo "obj-m := conftest.o" >build/Makefile
+	modpost_flag=''
+	test "x$enable_linux_builtin" = xyes && modpost_flag='modpost=true' # fake modpost stage
+	if { ac_try='cp conftest.c conftest.h build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror $FRAME_LARGER_THAN $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build $modpost_flag'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; } >/dev/null && { ac_try='test -s build/conftest.o'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_IN_COMPAT_SYSCALL 1" >>confdefs.h
+
+
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+
+
+fi
+	rm -Rf build
+
+
+
+
 	if test "$LINUX_OBJ" != "$LINUX"; then :
 
 		KERNELMAKE_PARAMS="$KERNELMAKE_PARAMS O=$LINUX_OBJ"
@@ -43261,7 +43388,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by zfs $as_me 0.7.11, which was
+This file was extended by zfs $as_me 0.7.12, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -43327,7 +43454,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-zfs config.status 0.7.11
+zfs config.status 0.7.12
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/zfs/dkms.conf b/zfs/dkms.conf
index 8b6114c..fec9c46 100644
--- a/zfs/dkms.conf
+++ b/zfs/dkms.conf
@@ -1,5 +1,5 @@
 PACKAGE_NAME="zfs"
-PACKAGE_VERSION="0.7.11"
+PACKAGE_VERSION="0.7.12"
 PACKAGE_CONFIG="/etc/sysconfig/zfs"
 PRE_BUILD="configure
   --prefix=/usr
diff --git a/zfs/include/Makefile.in b/zfs/include/Makefile.in
index 3600626..f8205c8 100644
--- a/zfs/include/Makefile.in
+++ b/zfs/include/Makefile.in
@@ -149,6 +149,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-arch.m4 \
 	$(top_srcdir)/config/kernel-get-gendisk.m4 \
 	$(top_srcdir)/config/kernel-get-link.m4 \
 	$(top_srcdir)/config/kernel-global_page_state.m4 \
+	$(top_srcdir)/config/kernel-in-compat-syscall.m4 \
 	$(top_srcdir)/config/kernel-inode-getattr.m4 \
 	$(top_srcdir)/config/kernel-inode-set-flags.m4 \
 	$(top_srcdir)/config/kernel-inode-set-iversion.m4 \
diff --git a/zfs/include/linux/Makefile.in b/zfs/include/linux/Makefile.in
index afa7b6f..c835c68 100644
--- a/zfs/include/linux/Makefile.in
+++ b/zfs/include/linux/Makefile.in
@@ -149,6 +149,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-arch.m4 \
 	$(top_srcdir)/config/kernel-get-gendisk.m4 \
 	$(top_srcdir)/config/kernel-get-link.m4 \
 	$(top_srcdir)/config/kernel-global_page_state.m4 \
+	$(top_srcdir)/config/kernel-in-compat-syscall.m4 \
 	$(top_srcdir)/config/kernel-inode-getattr.m4 \
 	$(top_srcdir)/config/kernel-inode-set-flags.m4 \
 	$(top_srcdir)/config/kernel-inode-set-iversion.m4 \
diff --git a/zfs/include/linux/vfs_compat.h b/zfs/include/linux/vfs_compat.h
index cca16d6c..c01f585 100644
--- a/zfs/include/linux/vfs_compat.h
+++ b/zfs/include/linux/vfs_compat.h
@@ -30,6 +30,7 @@
 #include <sys/taskq.h>
 #include <sys/cred.h>
 #include <linux/backing-dev.h>
+#include <linux/compat.h>
 
 /*
  * 2.6.28 API change,
@@ -621,4 +622,21 @@ inode_set_iversion(struct inode *ip, u64 val)
 }
 #endif
 
+/*
+ * Returns true when called in the context of a 32-bit system call.
+ */
+static inline int
+zpl_is_32bit_api(void)
+{
+#ifdef CONFIG_COMPAT
+#ifdef HAVE_IN_COMPAT_SYSCALL
+	return (in_compat_syscall());
+#else
+	return (is_compat_task());
+#endif
+#else
+	return (BITS_PER_LONG == 32);
+#endif
+}
+
 #endif /* _ZFS_VFS_H */
diff --git a/zfs/include/sys/Makefile.in b/zfs/include/sys/Makefile.in
index c5f80d8..e219e6a 100644
--- a/zfs/include/sys/Makefile.in
+++ b/zfs/include/sys/Makefile.in
@@ -149,6 +149,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-arch.m4 \
 	$(top_srcdir)/config/kernel-get-gendisk.m4 \
 	$(top_srcdir)/config/kernel-get-link.m4 \
 	$(top_srcdir)/config/kernel-global_page_state.m4 \
+	$(top_srcdir)/config/kernel-in-compat-syscall.m4 \
 	$(top_srcdir)/config/kernel-inode-getattr.m4 \
 	$(top_srcdir)/config/kernel-inode-set-flags.m4 \
 	$(top_srcdir)/config/kernel-inode-set-iversion.m4 \
diff --git a/zfs/include/sys/crypto/Makefile.in b/zfs/include/sys/crypto/Makefile.in
index 2d552e3..248e884d 100644
--- a/zfs/include/sys/crypto/Makefile.in
+++ b/zfs/include/sys/crypto/Makefile.in
@@ -149,6 +149,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-arch.m4 \
 	$(top_srcdir)/config/kernel-get-gendisk.m4 \
 	$(top_srcdir)/config/kernel-get-link.m4 \
 	$(top_srcdir)/config/kernel-global_page_state.m4 \
+	$(top_srcdir)/config/kernel-in-compat-syscall.m4 \
 	$(top_srcdir)/config/kernel-inode-getattr.m4 \
 	$(top_srcdir)/config/kernel-inode-set-flags.m4 \
 	$(top_srcdir)/config/kernel-inode-set-iversion.m4 \
diff --git a/zfs/include/sys/dmu_impl.h b/zfs/include/sys/dmu_impl.h
index 65e417e..03a6307 100644
--- a/zfs/include/sys/dmu_impl.h
+++ b/zfs/include/sys/dmu_impl.h
@@ -161,6 +161,7 @@ extern "C" {
  * 	dn_allocated_txg
  * 	dn_free_txg
  * 	dn_assigned_txg
+ * 	dn_dirty_txg
  * 	dd_assigned_tx
  * 	dn_notxholds
  * 	dn_dirtyctx
diff --git a/zfs/include/sys/dnode.h b/zfs/include/sys/dnode.h
index cd7696a..1e77e0a 100644
--- a/zfs/include/sys/dnode.h
+++ b/zfs/include/sys/dnode.h
@@ -260,6 +260,7 @@ struct dnode {
 	uint64_t dn_allocated_txg;
 	uint64_t dn_free_txg;
 	uint64_t dn_assigned_txg;
+	uint64_t dn_dirty_txg;			/* txg dnode was last dirtied */
 	kcondvar_t dn_notxholds;
 	enum dnode_dirtycontext dn_dirtyctx;
 	uint8_t *dn_dirtyctx_firstset;		/* dbg: contents meaningless */
@@ -362,6 +363,9 @@ void dnode_evict_dbufs(dnode_t *dn);
 void dnode_evict_bonus(dnode_t *dn);
 void dnode_free_interior_slots(dnode_t *dn);
 
+#define	DNODE_IS_DIRTY(_dn)						\
+	((_dn)->dn_dirty_txg >= spa_syncing_txg((_dn)->dn_objset->os_spa))
+
 #define	DNODE_IS_CACHEABLE(_dn)						\
 	((_dn)->dn_objset->os_primary_cache == ZFS_CACHE_ALL ||		\
 	(DMU_OT_IS_METADATA((_dn)->dn_type) &&				\
diff --git a/zfs/include/sys/fm/Makefile.in b/zfs/include/sys/fm/Makefile.in
index 3af8772..f2c52b4 100644
--- a/zfs/include/sys/fm/Makefile.in
+++ b/zfs/include/sys/fm/Makefile.in
@@ -149,6 +149,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-arch.m4 \
 	$(top_srcdir)/config/kernel-get-gendisk.m4 \
 	$(top_srcdir)/config/kernel-get-link.m4 \
 	$(top_srcdir)/config/kernel-global_page_state.m4 \
+	$(top_srcdir)/config/kernel-in-compat-syscall.m4 \
 	$(top_srcdir)/config/kernel-inode-getattr.m4 \
 	$(top_srcdir)/config/kernel-inode-set-flags.m4 \
 	$(top_srcdir)/config/kernel-inode-set-iversion.m4 \
diff --git a/zfs/include/sys/fm/fs/Makefile.in b/zfs/include/sys/fm/fs/Makefile.in
index 1f9c802..94eda86 100644
--- a/zfs/include/sys/fm/fs/Makefile.in
+++ b/zfs/include/sys/fm/fs/Makefile.in
@@ -149,6 +149,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-arch.m4 \
 	$(top_srcdir)/config/kernel-get-gendisk.m4 \
 	$(top_srcdir)/config/kernel-get-link.m4 \
 	$(top_srcdir)/config/kernel-global_page_state.m4 \
+	$(top_srcdir)/config/kernel-in-compat-syscall.m4 \
 	$(top_srcdir)/config/kernel-inode-getattr.m4 \
 	$(top_srcdir)/config/kernel-inode-set-flags.m4 \
 	$(top_srcdir)/config/kernel-inode-set-iversion.m4 \
diff --git a/zfs/include/sys/fs/Makefile.in b/zfs/include/sys/fs/Makefile.in
index f747598..f6ccb40 100644
--- a/zfs/include/sys/fs/Makefile.in
+++ b/zfs/include/sys/fs/Makefile.in
@@ -149,6 +149,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-arch.m4 \
 	$(top_srcdir)/config/kernel-get-gendisk.m4 \
 	$(top_srcdir)/config/kernel-get-link.m4 \
 	$(top_srcdir)/config/kernel-global_page_state.m4 \
+	$(top_srcdir)/config/kernel-in-compat-syscall.m4 \
 	$(top_srcdir)/config/kernel-inode-getattr.m4 \
 	$(top_srcdir)/config/kernel-inode-set-flags.m4 \
 	$(top_srcdir)/config/kernel-inode-set-iversion.m4 \
diff --git a/zfs/include/sys/metaslab_impl.h b/zfs/include/sys/metaslab_impl.h
index d507fe0..6015193 100644
--- a/zfs/include/sys/metaslab_impl.h
+++ b/zfs/include/sys/metaslab_impl.h
@@ -180,7 +180,6 @@ struct metaslab_class {
 	 */
 	uint64_t		mc_alloc_max_slots;
 	zfs_refcount_t		mc_alloc_slots;
-
 	uint64_t		mc_alloc_groups; /* # of allocatable groups */
 
 	uint64_t		mc_alloc;	/* total allocated space */
diff --git a/zfs/include/sys/refcount.h b/zfs/include/sys/refcount.h
index 5c5198d..7eeb1366 100644
--- a/zfs/include/sys/refcount.h
+++ b/zfs/include/sys/refcount.h
@@ -63,26 +63,24 @@ typedef struct refcount {
  * refcount_create[_untracked]()
  */
 
-void refcount_create(zfs_refcount_t *rc);
-void refcount_create_untracked(zfs_refcount_t *rc);
-void refcount_create_tracked(zfs_refcount_t *rc);
-void refcount_destroy(zfs_refcount_t *rc);
-void refcount_destroy_many(zfs_refcount_t *rc, uint64_t number);
-int refcount_is_zero(zfs_refcount_t *rc);
-int64_t refcount_count(zfs_refcount_t *rc);
-int64_t zfs_refcount_add(zfs_refcount_t *rc, void *holder_tag);
-int64_t refcount_remove(zfs_refcount_t *rc, void *holder_tag);
-int64_t refcount_add_many(zfs_refcount_t *rc, uint64_t number,
-    void *holder_tag);
-int64_t refcount_remove_many(zfs_refcount_t *rc, uint64_t number,
-    void *holder_tag);
-void refcount_transfer(zfs_refcount_t *dst, zfs_refcount_t *src);
-void refcount_transfer_ownership(zfs_refcount_t *, void *, void *);
-boolean_t refcount_held(zfs_refcount_t *, void *);
-boolean_t refcount_not_held(zfs_refcount_t *, void *);
-
-void refcount_init(void);
-void refcount_fini(void);
+void zfs_refcount_create(zfs_refcount_t *);
+void zfs_refcount_create_untracked(zfs_refcount_t *);
+void zfs_refcount_create_tracked(zfs_refcount_t *);
+void zfs_refcount_destroy(zfs_refcount_t *);
+void zfs_refcount_destroy_many(zfs_refcount_t *, uint64_t);
+int zfs_refcount_is_zero(zfs_refcount_t *);
+int64_t zfs_refcount_count(zfs_refcount_t *);
+int64_t zfs_refcount_add(zfs_refcount_t *, void *);
+int64_t zfs_refcount_remove(zfs_refcount_t *, void *);
+int64_t zfs_refcount_add_many(zfs_refcount_t *, uint64_t, void *);
+int64_t zfs_refcount_remove_many(zfs_refcount_t *, uint64_t, void *);
+void zfs_refcount_transfer(zfs_refcount_t *, zfs_refcount_t *);
+void zfs_refcount_transfer_ownership(zfs_refcount_t *, void *, void *);
+boolean_t zfs_refcount_held(zfs_refcount_t *, void *);
+boolean_t zfs_refcount_not_held(zfs_refcount_t *, void *);
+
+void zfs_refcount_init(void);
+void zfs_refcount_fini(void);
 
 #else	/* ZFS_DEBUG */
 
@@ -90,30 +88,30 @@ typedef struct refcount {
 	uint64_t rc_count;
 } zfs_refcount_t;
 
-#define	refcount_create(rc) ((rc)->rc_count = 0)
-#define	refcount_create_untracked(rc) ((rc)->rc_count = 0)
-#define	refcount_create_tracked(rc) ((rc)->rc_count = 0)
-#define	refcount_destroy(rc) ((rc)->rc_count = 0)
-#define	refcount_destroy_many(rc, number) ((rc)->rc_count = 0)
-#define	refcount_is_zero(rc) ((rc)->rc_count == 0)
-#define	refcount_count(rc) ((rc)->rc_count)
+#define	zfs_refcount_create(rc) ((rc)->rc_count = 0)
+#define	zfs_refcount_create_untracked(rc) ((rc)->rc_count = 0)
+#define	zfs_refcount_create_tracked(rc) ((rc)->rc_count = 0)
+#define	zfs_refcount_destroy(rc) ((rc)->rc_count = 0)
+#define	zfs_refcount_destroy_many(rc, number) ((rc)->rc_count = 0)
+#define	zfs_refcount_is_zero(rc) ((rc)->rc_count == 0)
+#define	zfs_refcount_count(rc) ((rc)->rc_count)
 #define	zfs_refcount_add(rc, holder) atomic_inc_64_nv(&(rc)->rc_count)
-#define	refcount_remove(rc, holder) atomic_dec_64_nv(&(rc)->rc_count)
-#define	refcount_add_many(rc, number, holder) \
+#define	zfs_refcount_remove(rc, holder) atomic_dec_64_nv(&(rc)->rc_count)
+#define	zfs_refcount_add_many(rc, number, holder) \
 	atomic_add_64_nv(&(rc)->rc_count, number)
-#define	refcount_remove_many(rc, number, holder) \
+#define	zfs_refcount_remove_many(rc, number, holder) \
 	atomic_add_64_nv(&(rc)->rc_count, -number)
-#define	refcount_transfer(dst, src) { \
+#define	zfs_refcount_transfer(dst, src) { \
 	uint64_t __tmp = (src)->rc_count; \
 	atomic_add_64(&(src)->rc_count, -__tmp); \
 	atomic_add_64(&(dst)->rc_count, __tmp); \
 }
-#define	refcount_transfer_ownership(rc, current_holder, new_holder)	(void)0
-#define	refcount_held(rc, holder)		((rc)->rc_count > 0)
-#define	refcount_not_held(rc, holder)		(B_TRUE)
+#define	zfs_refcount_transfer_ownership(rc, current_holder, new_holder)	(void)0
+#define	zfs_refcount_held(rc, holder)		((rc)->rc_count > 0)
+#define	zfs_refcount_not_held(rc, holder)		(B_TRUE)
 
-#define	refcount_init()
-#define	refcount_fini()
+#define	zfs_refcount_init()
+#define	zfs_refcount_fini()
 
 #endif	/* ZFS_DEBUG */
 
diff --git a/zfs/include/sys/sysevent/Makefile.in b/zfs/include/sys/sysevent/Makefile.in
index 2d8f78a..4573eb1 100644
--- a/zfs/include/sys/sysevent/Makefile.in
+++ b/zfs/include/sys/sysevent/Makefile.in
@@ -149,6 +149,7 @@ am__aclocal_m4_deps = $(top_srcdir)/config/always-arch.m4 \
 	$(top_srcdir)/config/kernel-get-gendisk.m4 \
 	$(top_srcdir)/config/kernel-get-link.m4 \
 	$(top_srcdir)/config/kernel-global_page_state.m4 \
+	$(top_srcdir)/config/kernel-in-compat-syscall.m4 \
 	$(top_srcdir)/config/kernel-inode-getattr.m4 \
 	$(top_srcdir)/config/kernel-inode-set-flags.m4 \
 	$(top_srcdir)/config/kernel-inode-set-iversion.m4 \
diff --git a/zfs/include/sys/trace_dbuf.h b/zfs/include/sys/trace_dbuf.h
index c3e70c3..e97b611 100644
--- a/zfs/include/sys/trace_dbuf.h
+++ b/zfs/include/sys/trace_dbuf.h
@@ -71,7 +71,7 @@
 		__entry->db_offset = db->db.db_offset;			\
 		__entry->db_size   = db->db.db_size;			\
 		__entry->db_state  = db->db_state;			\
-		__entry->db_holds  = refcount_count(&db->db_holds);	\
+		__entry->db_holds  = zfs_refcount_count(&db->db_holds);	\
 		snprintf(__get_str(msg), TRACE_DBUF_MSG_MAX,		\
 		    DBUF_TP_PRINTK_FMT, DBUF_TP_PRINTK_ARGS);		\
 	} else {							\
diff --git a/zfs/include/sys/zio.h b/zfs/include/sys/zio.h
index 4b0eecc..3618912 100644
--- a/zfs/include/sys/zio.h
+++ b/zfs/include/sys/zio.h
@@ -237,7 +237,7 @@ enum zio_child {
 #define	ZIO_CHILD_DDT_BIT		ZIO_CHILD_BIT(ZIO_CHILD_DDT)
 #define	ZIO_CHILD_LOGICAL_BIT		ZIO_CHILD_BIT(ZIO_CHILD_LOGICAL)
 #define	ZIO_CHILD_ALL_BITS					\
-	(ZIO_CHILD_VDEV_BIT | ZIO_CHILD_GANG_BIT | 		\
+	(ZIO_CHILD_VDEV_BIT | ZIO_CHILD_GANG_BIT |		\
 	ZIO_CHILD_DDT_BIT | ZIO_CHILD_LOGICAL_BIT)
 
 enum zio_wait_type {
@@ -375,7 +375,7 @@ typedef struct zio_transform {
 	struct zio_transform	*zt_next;
 } zio_transform_t;
 
-typedef int zio_pipe_stage_t(zio_t *zio);
+typedef zio_t *zio_pipe_stage_t(zio_t *zio);
 
 /*
  * The io_reexecute flags are distinct from io_flags because the child must
diff --git a/zfs/module/zfs/abd.c b/zfs/module/zfs/abd.c
index 910eabf..61d3b92 100644
--- a/zfs/module/zfs/abd.c
+++ b/zfs/module/zfs/abd.c
@@ -597,7 +597,7 @@ abd_alloc(size_t size, boolean_t is_metadata)
 	}
 	abd->abd_size = size;
 	abd->abd_parent = NULL;
-	refcount_create(&abd->abd_children);
+	zfs_refcount_create(&abd->abd_children);
 
 	abd->abd_u.abd_scatter.abd_offset = 0;
 
@@ -614,7 +614,7 @@ abd_free_scatter(abd_t *abd)
 {
 	abd_free_pages(abd);
 
-	refcount_destroy(&abd->abd_children);
+	zfs_refcount_destroy(&abd->abd_children);
 	ABDSTAT_BUMPDOWN(abdstat_scatter_cnt);
 	ABDSTAT_INCR(abdstat_scatter_data_size, -(int)abd->abd_size);
 	ABDSTAT_INCR(abdstat_scatter_chunk_waste,
@@ -641,7 +641,7 @@ abd_alloc_linear(size_t size, boolean_t is_metadata)
 	}
 	abd->abd_size = size;
 	abd->abd_parent = NULL;
-	refcount_create(&abd->abd_children);
+	zfs_refcount_create(&abd->abd_children);
 
 	if (is_metadata) {
 		abd->abd_u.abd_linear.abd_buf = zio_buf_alloc(size);
@@ -664,7 +664,7 @@ abd_free_linear(abd_t *abd)
 		zio_data_buf_free(abd->abd_u.abd_linear.abd_buf, abd->abd_size);
 	}
 
-	refcount_destroy(&abd->abd_children);
+	zfs_refcount_destroy(&abd->abd_children);
 	ABDSTAT_BUMPDOWN(abdstat_linear_cnt);
 	ABDSTAT_INCR(abdstat_linear_data_size, -(int)abd->abd_size);
 
@@ -775,8 +775,8 @@ abd_get_offset_impl(abd_t *sabd, size_t off, size_t size)
 
 	abd->abd_size = size;
 	abd->abd_parent = sabd;
-	refcount_create(&abd->abd_children);
-	(void) refcount_add_many(&sabd->abd_children, abd->abd_size, abd);
+	zfs_refcount_create(&abd->abd_children);
+	(void) zfs_refcount_add_many(&sabd->abd_children, abd->abd_size, abd);
 
 	return (abd);
 }
@@ -818,7 +818,7 @@ abd_get_from_buf(void *buf, size_t size)
 	abd->abd_flags = ABD_FLAG_LINEAR;
 	abd->abd_size = size;
 	abd->abd_parent = NULL;
-	refcount_create(&abd->abd_children);
+	zfs_refcount_create(&abd->abd_children);
 
 	abd->abd_u.abd_linear.abd_buf = buf;
 
@@ -836,11 +836,11 @@ abd_put(abd_t *abd)
 	ASSERT(!(abd->abd_flags & ABD_FLAG_OWNER));
 
 	if (abd->abd_parent != NULL) {
-		(void) refcount_remove_many(&abd->abd_parent->abd_children,
+		(void) zfs_refcount_remove_many(&abd->abd_parent->abd_children,
 		    abd->abd_size, abd);
 	}
 
-	refcount_destroy(&abd->abd_children);
+	zfs_refcount_destroy(&abd->abd_children);
 	abd_free_struct(abd);
 }
 
@@ -872,7 +872,7 @@ abd_borrow_buf(abd_t *abd, size_t n)
 	} else {
 		buf = zio_buf_alloc(n);
 	}
-	(void) refcount_add_many(&abd->abd_children, n, buf);
+	(void) zfs_refcount_add_many(&abd->abd_children, n, buf);
 
 	return (buf);
 }
@@ -904,7 +904,7 @@ abd_return_buf(abd_t *abd, void *buf, size_t n)
 		ASSERT0(abd_cmp_buf(abd, buf, n));
 		zio_buf_free(buf, n);
 	}
-	(void) refcount_remove_many(&abd->abd_children, n, buf);
+	(void) zfs_refcount_remove_many(&abd->abd_children, n, buf);
 }
 
 void
diff --git a/zfs/module/zfs/arc.c b/zfs/module/zfs/arc.c
index 7518d5c..a7fb242 100644
--- a/zfs/module/zfs/arc.c
+++ b/zfs/module/zfs/arc.c
@@ -1181,7 +1181,7 @@ hdr_full_cons(void *vbuf, void *unused, int kmflag)
 
 	bzero(hdr, HDR_FULL_SIZE);
 	cv_init(&hdr->b_l1hdr.b_cv, NULL, CV_DEFAULT, NULL);
-	refcount_create(&hdr->b_l1hdr.b_refcnt);
+	zfs_refcount_create(&hdr->b_l1hdr.b_refcnt);
 	mutex_init(&hdr->b_l1hdr.b_freeze_lock, NULL, MUTEX_DEFAULT, NULL);
 	list_link_init(&hdr->b_l1hdr.b_arc_node);
 	list_link_init(&hdr->b_l2hdr.b_l2node);
@@ -1228,7 +1228,7 @@ hdr_full_dest(void *vbuf, void *unused)
 
 	ASSERT(HDR_EMPTY(hdr));
 	cv_destroy(&hdr->b_l1hdr.b_cv);
-	refcount_destroy(&hdr->b_l1hdr.b_refcnt);
+	zfs_refcount_destroy(&hdr->b_l1hdr.b_refcnt);
 	mutex_destroy(&hdr->b_l1hdr.b_freeze_lock);
 	ASSERT(!multilist_link_active(&hdr->b_l1hdr.b_arc_node));
 	arc_space_return(HDR_FULL_SIZE, ARC_SPACE_HDRS);
@@ -1893,20 +1893,20 @@ arc_evictable_space_increment(arc_buf_hdr_t *hdr, arc_state_t *state)
 		ASSERT0(hdr->b_l1hdr.b_bufcnt);
 		ASSERT3P(hdr->b_l1hdr.b_buf, ==, NULL);
 		ASSERT3P(hdr->b_l1hdr.b_pabd, ==, NULL);
-		(void) refcount_add_many(&state->arcs_esize[type],
+		(void) zfs_refcount_add_many(&state->arcs_esize[type],
 		    HDR_GET_LSIZE(hdr), hdr);
 		return;
 	}
 
 	ASSERT(!GHOST_STATE(state));
 	if (hdr->b_l1hdr.b_pabd != NULL) {
-		(void) refcount_add_many(&state->arcs_esize[type],
+		(void) zfs_refcount_add_many(&state->arcs_esize[type],
 		    arc_hdr_size(hdr), hdr);
 	}
 	for (buf = hdr->b_l1hdr.b_buf; buf != NULL; buf = buf->b_next) {
 		if (arc_buf_is_shared(buf))
 			continue;
-		(void) refcount_add_many(&state->arcs_esize[type],
+		(void) zfs_refcount_add_many(&state->arcs_esize[type],
 		    arc_buf_size(buf), buf);
 	}
 }
@@ -1928,20 +1928,20 @@ arc_evictable_space_decrement(arc_buf_hdr_t *hdr, arc_state_t *state)
 		ASSERT0(hdr->b_l1hdr.b_bufcnt);
 		ASSERT3P(hdr->b_l1hdr.b_buf, ==, NULL);
 		ASSERT3P(hdr->b_l1hdr.b_pabd, ==, NULL);
-		(void) refcount_remove_many(&state->arcs_esize[type],
+		(void) zfs_refcount_remove_many(&state->arcs_esize[type],
 		    HDR_GET_LSIZE(hdr), hdr);
 		return;
 	}
 
 	ASSERT(!GHOST_STATE(state));
 	if (hdr->b_l1hdr.b_pabd != NULL) {
-		(void) refcount_remove_many(&state->arcs_esize[type],
+		(void) zfs_refcount_remove_many(&state->arcs_esize[type],
 		    arc_hdr_size(hdr), hdr);
 	}
 	for (buf = hdr->b_l1hdr.b_buf; buf != NULL; buf = buf->b_next) {
 		if (arc_buf_is_shared(buf))
 			continue;
-		(void) refcount_remove_many(&state->arcs_esize[type],
+		(void) zfs_refcount_remove_many(&state->arcs_esize[type],
 		    arc_buf_size(buf), buf);
 	}
 }
@@ -1960,7 +1960,7 @@ add_reference(arc_buf_hdr_t *hdr, void *tag)
 	ASSERT(HDR_HAS_L1HDR(hdr));
 	if (!MUTEX_HELD(HDR_LOCK(hdr))) {
 		ASSERT(hdr->b_l1hdr.b_state == arc_anon);
-		ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
+		ASSERT(zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
 		ASSERT3P(hdr->b_l1hdr.b_buf, ==, NULL);
 	}
 
@@ -1998,7 +1998,7 @@ remove_reference(arc_buf_hdr_t *hdr, kmutex_t *hash_lock, void *tag)
 	 * arc_l2c_only counts as a ghost state so we don't need to explicitly
 	 * check to prevent usage of the arc_l2c_only list.
 	 */
-	if (((cnt = refcount_remove(&hdr->b_l1hdr.b_refcnt, tag)) == 0) &&
+	if (((cnt = zfs_refcount_remove(&hdr->b_l1hdr.b_refcnt, tag)) == 0) &&
 	    (state != arc_anon)) {
 		multilist_insert(state->arcs_list[arc_buf_type(hdr)], hdr);
 		ASSERT3U(hdr->b_l1hdr.b_bufcnt, >, 0);
@@ -2043,7 +2043,7 @@ arc_buf_info(arc_buf_t *ab, arc_buf_info_t *abi, int state_index)
 		abi->abi_mru_ghost_hits = l1hdr->b_mru_ghost_hits;
 		abi->abi_mfu_hits = l1hdr->b_mfu_hits;
 		abi->abi_mfu_ghost_hits = l1hdr->b_mfu_ghost_hits;
-		abi->abi_holds = refcount_count(&l1hdr->b_refcnt);
+		abi->abi_holds = zfs_refcount_count(&l1hdr->b_refcnt);
 	}
 
 	if (l2hdr) {
@@ -2079,7 +2079,7 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr,
 	 */
 	if (HDR_HAS_L1HDR(hdr)) {
 		old_state = hdr->b_l1hdr.b_state;
-		refcnt = refcount_count(&hdr->b_l1hdr.b_refcnt);
+		refcnt = zfs_refcount_count(&hdr->b_l1hdr.b_refcnt);
 		bufcnt = hdr->b_l1hdr.b_bufcnt;
 		update_old = (bufcnt > 0 || hdr->b_l1hdr.b_pabd != NULL);
 	} else {
@@ -2148,7 +2148,7 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr,
 			 * the reference. As a result, we use the arc
 			 * header pointer for the reference.
 			 */
-			(void) refcount_add_many(&new_state->arcs_size,
+			(void) zfs_refcount_add_many(&new_state->arcs_size,
 			    HDR_GET_LSIZE(hdr), hdr);
 			ASSERT3P(hdr->b_l1hdr.b_pabd, ==, NULL);
 		} else {
@@ -2175,13 +2175,15 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr,
 				if (arc_buf_is_shared(buf))
 					continue;
 
-				(void) refcount_add_many(&new_state->arcs_size,
+				(void) zfs_refcount_add_many(
+				    &new_state->arcs_size,
 				    arc_buf_size(buf), buf);
 			}
 			ASSERT3U(bufcnt, ==, buffers);
 
 			if (hdr->b_l1hdr.b_pabd != NULL) {
-				(void) refcount_add_many(&new_state->arcs_size,
+				(void) zfs_refcount_add_many(
+				    &new_state->arcs_size,
 				    arc_hdr_size(hdr), hdr);
 			} else {
 				ASSERT(GHOST_STATE(old_state));
@@ -2203,7 +2205,7 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr,
 			 * header on the ghost state.
 			 */
 
-			(void) refcount_remove_many(&old_state->arcs_size,
+			(void) zfs_refcount_remove_many(&old_state->arcs_size,
 			    HDR_GET_LSIZE(hdr), hdr);
 		} else {
 			arc_buf_t *buf;
@@ -2229,13 +2231,13 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr,
 				if (arc_buf_is_shared(buf))
 					continue;
 
-				(void) refcount_remove_many(
+				(void) zfs_refcount_remove_many(
 				    &old_state->arcs_size, arc_buf_size(buf),
 				    buf);
 			}
 			ASSERT3U(bufcnt, ==, buffers);
 			ASSERT3P(hdr->b_l1hdr.b_pabd, !=, NULL);
-			(void) refcount_remove_many(
+			(void) zfs_refcount_remove_many(
 			    &old_state->arcs_size, arc_hdr_size(hdr), hdr);
 		}
 	}
@@ -2506,7 +2508,7 @@ arc_return_buf(arc_buf_t *buf, void *tag)
 	ASSERT3P(buf->b_data, !=, NULL);
 	ASSERT(HDR_HAS_L1HDR(hdr));
 	(void) zfs_refcount_add(&hdr->b_l1hdr.b_refcnt, tag);
-	(void) refcount_remove(&hdr->b_l1hdr.b_refcnt, arc_onloan_tag);
+	(void) zfs_refcount_remove(&hdr->b_l1hdr.b_refcnt, arc_onloan_tag);
 
 	arc_loaned_bytes_update(-arc_buf_size(buf));
 }
@@ -2520,7 +2522,7 @@ arc_loan_inuse_buf(arc_buf_t *buf, void *tag)
 	ASSERT3P(buf->b_data, !=, NULL);
 	ASSERT(HDR_HAS_L1HDR(hdr));
 	(void) zfs_refcount_add(&hdr->b_l1hdr.b_refcnt, arc_onloan_tag);
-	(void) refcount_remove(&hdr->b_l1hdr.b_refcnt, tag);
+	(void) zfs_refcount_remove(&hdr->b_l1hdr.b_refcnt, tag);
 
 	arc_loaned_bytes_update(arc_buf_size(buf));
 }
@@ -2547,13 +2549,13 @@ arc_hdr_free_on_write(arc_buf_hdr_t *hdr)
 
 	/* protected by hash lock, if in the hash table */
 	if (multilist_link_active(&hdr->b_l1hdr.b_arc_node)) {
-		ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
+		ASSERT(zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
 		ASSERT(state != arc_anon && state != arc_l2c_only);
 
-		(void) refcount_remove_many(&state->arcs_esize[type],
+		(void) zfs_refcount_remove_many(&state->arcs_esize[type],
 		    size, hdr);
 	}
-	(void) refcount_remove_many(&state->arcs_size, size, hdr);
+	(void) zfs_refcount_remove_many(&state->arcs_size, size, hdr);
 	if (type == ARC_BUFC_METADATA) {
 		arc_space_return(size, ARC_SPACE_META);
 	} else {
@@ -2581,7 +2583,8 @@ arc_share_buf(arc_buf_hdr_t *hdr, arc_buf_t *buf)
 	 * refcount ownership to the hdr since it always owns
 	 * the refcount whenever an arc_buf_t is shared.
 	 */
-	refcount_transfer_ownership(&hdr->b_l1hdr.b_state->arcs_size, buf, hdr);
+	zfs_refcount_transfer_ownership(&hdr->b_l1hdr.b_state->arcs_size, buf,
+	    hdr);
 	hdr->b_l1hdr.b_pabd = abd_get_from_buf(buf->b_data, arc_buf_size(buf));
 	abd_take_ownership_of_buf(hdr->b_l1hdr.b_pabd,
 	    HDR_ISTYPE_METADATA(hdr));
@@ -2609,7 +2612,8 @@ arc_unshare_buf(arc_buf_hdr_t *hdr, arc_buf_t *buf)
 	 * We are no longer sharing this buffer so we need
 	 * to transfer its ownership to the rightful owner.
 	 */
-	refcount_transfer_ownership(&hdr->b_l1hdr.b_state->arcs_size, hdr, buf);
+	zfs_refcount_transfer_ownership(&hdr->b_l1hdr.b_state->arcs_size, hdr,
+	    buf);
 	arc_hdr_clear_flags(hdr, ARC_FLAG_SHARED_DATA);
 	abd_release_ownership_of_buf(hdr->b_l1hdr.b_pabd);
 	abd_put(hdr->b_l1hdr.b_pabd);
@@ -2833,7 +2837,7 @@ arc_hdr_alloc(uint64_t spa, int32_t psize, int32_t lsize,
 	 * it references and compressed arc enablement.
 	 */
 	arc_hdr_alloc_pabd(hdr);
-	ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
+	ASSERT(zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
 
 	return (hdr);
 }
@@ -2927,8 +2931,10 @@ arc_hdr_realloc(arc_buf_hdr_t *hdr, kmem_cache_t *old, kmem_cache_t *new)
 	 * the wrong pointer address when calling arc_hdr_destroy() later.
 	 */
 
-	(void) refcount_remove_many(&dev->l2ad_alloc, arc_hdr_size(hdr), hdr);
-	(void) refcount_add_many(&dev->l2ad_alloc, arc_hdr_size(nhdr), nhdr);
+	(void) zfs_refcount_remove_many(&dev->l2ad_alloc, arc_hdr_size(hdr),
+	    hdr);
+	(void) zfs_refcount_add_many(&dev->l2ad_alloc, arc_hdr_size(nhdr),
+	    nhdr);
 
 	buf_discard_identity(hdr);
 	kmem_cache_free(old, hdr);
@@ -3008,7 +3014,7 @@ arc_hdr_l2hdr_destroy(arc_buf_hdr_t *hdr)
 
 	vdev_space_update(dev->l2ad_vdev, -psize, 0, 0);
 
-	(void) refcount_remove_many(&dev->l2ad_alloc, psize, hdr);
+	(void) zfs_refcount_remove_many(&dev->l2ad_alloc, psize, hdr);
 	arc_hdr_clear_flags(hdr, ARC_FLAG_HAS_L2HDR);
 }
 
@@ -3018,7 +3024,7 @@ arc_hdr_destroy(arc_buf_hdr_t *hdr)
 	if (HDR_HAS_L1HDR(hdr)) {
 		ASSERT(hdr->b_l1hdr.b_buf == NULL ||
 		    hdr->b_l1hdr.b_bufcnt > 0);
-		ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
+		ASSERT(zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
 		ASSERT3P(hdr->b_l1hdr.b_state, ==, arc_anon);
 	}
 	ASSERT(!HDR_IO_IN_PROGRESS(hdr));
@@ -3171,7 +3177,7 @@ arc_evict_hdr(arc_buf_hdr_t *hdr, kmutex_t *hash_lock)
 		return (bytes_evicted);
 	}
 
-	ASSERT0(refcount_count(&hdr->b_l1hdr.b_refcnt));
+	ASSERT0(zfs_refcount_count(&hdr->b_l1hdr.b_refcnt));
 	while (hdr->b_l1hdr.b_buf) {
 		arc_buf_t *buf = hdr->b_l1hdr.b_buf;
 		if (!mutex_tryenter(&buf->b_evict_lock)) {
@@ -3484,7 +3490,7 @@ arc_flush_state(arc_state_t *state, uint64_t spa, arc_buf_contents_t type,
 {
 	uint64_t evicted = 0;
 
-	while (refcount_count(&state->arcs_esize[type]) != 0) {
+	while (zfs_refcount_count(&state->arcs_esize[type]) != 0) {
 		evicted += arc_evict_state(state, spa, ARC_EVICT_ALL, type);
 
 		if (!retry)
@@ -3507,7 +3513,7 @@ arc_prune_task(void *ptr)
 	if (func != NULL)
 		func(ap->p_adjust, ap->p_private);
 
-	refcount_remove(&ap->p_refcnt, func);
+	zfs_refcount_remove(&ap->p_refcnt, func);
 }
 
 /*
@@ -3530,14 +3536,14 @@ arc_prune_async(int64_t adjust)
 	for (ap = list_head(&arc_prune_list); ap != NULL;
 	    ap = list_next(&arc_prune_list, ap)) {
 
-		if (refcount_count(&ap->p_refcnt) >= 2)
+		if (zfs_refcount_count(&ap->p_refcnt) >= 2)
 			continue;
 
 		zfs_refcount_add(&ap->p_refcnt, ap->p_pfunc);
 		ap->p_adjust = adjust;
 		if (taskq_dispatch(arc_prune_taskq, arc_prune_task,
 		    ap, TQ_SLEEP) == TASKQID_INVALID) {
-			refcount_remove(&ap->p_refcnt, ap->p_pfunc);
+			zfs_refcount_remove(&ap->p_refcnt, ap->p_pfunc);
 			continue;
 		}
 		ARCSTAT_BUMP(arcstat_prune);
@@ -3559,8 +3565,9 @@ arc_adjust_impl(arc_state_t *state, uint64_t spa, int64_t bytes,
 {
 	int64_t delta;
 
-	if (bytes > 0 && refcount_count(&state->arcs_esize[type]) > 0) {
-		delta = MIN(refcount_count(&state->arcs_esize[type]), bytes);
+	if (bytes > 0 && zfs_refcount_count(&state->arcs_esize[type]) > 0) {
+		delta = MIN(zfs_refcount_count(&state->arcs_esize[type]),
+		    bytes);
 		return (arc_evict_state(state, spa, delta, type));
 	}
 
@@ -3603,8 +3610,9 @@ arc_adjust_meta_balanced(void)
 	 */
 	adjustmnt = arc_meta_used - arc_meta_limit;
 
-	if (adjustmnt > 0 && refcount_count(&arc_mru->arcs_esize[type]) > 0) {
-		delta = MIN(refcount_count(&arc_mru->arcs_esize[type]),
+	if (adjustmnt > 0 &&
+	    zfs_refcount_count(&arc_mru->arcs_esize[type]) > 0) {
+		delta = MIN(zfs_refcount_count(&arc_mru->arcs_esize[type]),
 		    adjustmnt);
 		total_evicted += arc_adjust_impl(arc_mru, 0, delta, type);
 		adjustmnt -= delta;
@@ -3620,8 +3628,9 @@ arc_adjust_meta_balanced(void)
 	 * simply decrement the amount of data evicted from the MRU.
 	 */
 
-	if (adjustmnt > 0 && refcount_count(&arc_mfu->arcs_esize[type]) > 0) {
-		delta = MIN(refcount_count(&arc_mfu->arcs_esize[type]),
+	if (adjustmnt > 0 &&
+	    zfs_refcount_count(&arc_mfu->arcs_esize[type]) > 0) {
+		delta = MIN(zfs_refcount_count(&arc_mfu->arcs_esize[type]),
 		    adjustmnt);
 		total_evicted += arc_adjust_impl(arc_mfu, 0, delta, type);
 	}
@@ -3629,17 +3638,17 @@ arc_adjust_meta_balanced(void)
 	adjustmnt = arc_meta_used - arc_meta_limit;
 
 	if (adjustmnt > 0 &&
-	    refcount_count(&arc_mru_ghost->arcs_esize[type]) > 0) {
+	    zfs_refcount_count(&arc_mru_ghost->arcs_esize[type]) > 0) {
 		delta = MIN(adjustmnt,
-		    refcount_count(&arc_mru_ghost->arcs_esize[type]));
+		    zfs_refcount_count(&arc_mru_ghost->arcs_esize[type]));
 		total_evicted += arc_adjust_impl(arc_mru_ghost, 0, delta, type);
 		adjustmnt -= delta;
 	}
 
 	if (adjustmnt > 0 &&
-	    refcount_count(&arc_mfu_ghost->arcs_esize[type]) > 0) {
+	    zfs_refcount_count(&arc_mfu_ghost->arcs_esize[type]) > 0) {
 		delta = MIN(adjustmnt,
-		    refcount_count(&arc_mfu_ghost->arcs_esize[type]));
+		    zfs_refcount_count(&arc_mfu_ghost->arcs_esize[type]));
 		total_evicted += arc_adjust_impl(arc_mfu_ghost, 0, delta, type);
 	}
 
@@ -3688,8 +3697,8 @@ arc_adjust_meta_only(void)
 	 * evict some from the MRU here, and some from the MFU below.
 	 */
 	target = MIN((int64_t)(arc_meta_used - arc_meta_limit),
-	    (int64_t)(refcount_count(&arc_anon->arcs_size) +
-	    refcount_count(&arc_mru->arcs_size) - arc_p));
+	    (int64_t)(zfs_refcount_count(&arc_anon->arcs_size) +
+	    zfs_refcount_count(&arc_mru->arcs_size) - arc_p));
 
 	total_evicted += arc_adjust_impl(arc_mru, 0, target, ARC_BUFC_METADATA);
 
@@ -3699,7 +3708,8 @@ arc_adjust_meta_only(void)
 	 * space allotted to the MFU (which is defined as arc_c - arc_p).
 	 */
 	target = MIN((int64_t)(arc_meta_used - arc_meta_limit),
-	    (int64_t)(refcount_count(&arc_mfu->arcs_size) - (arc_c - arc_p)));
+	    (int64_t)(zfs_refcount_count(&arc_mfu->arcs_size) - (arc_c -
+	    arc_p)));
 
 	total_evicted += arc_adjust_impl(arc_mfu, 0, target, ARC_BUFC_METADATA);
 
@@ -3817,8 +3827,8 @@ arc_adjust(void)
 	 * arc_p here, and then evict more from the MFU below.
 	 */
 	target = MIN((int64_t)(arc_size - arc_c),
-	    (int64_t)(refcount_count(&arc_anon->arcs_size) +
-	    refcount_count(&arc_mru->arcs_size) + arc_meta_used - arc_p));
+	    (int64_t)(zfs_refcount_count(&arc_anon->arcs_size) +
+	    zfs_refcount_count(&arc_mru->arcs_size) + arc_meta_used - arc_p));
 
 	/*
 	 * If we're below arc_meta_min, always prefer to evict data.
@@ -3902,8 +3912,8 @@ arc_adjust(void)
 	 * cache. The following logic enforces these limits on the ghost
 	 * caches, and evicts from them as needed.
 	 */
-	target = refcount_count(&arc_mru->arcs_size) +
-	    refcount_count(&arc_mru_ghost->arcs_size) - arc_c;
+	target = zfs_refcount_count(&arc_mru->arcs_size) +
+	    zfs_refcount_count(&arc_mru_ghost->arcs_size) - arc_c;
 
 	bytes = arc_adjust_impl(arc_mru_ghost, 0, target, ARC_BUFC_DATA);
 	total_evicted += bytes;
@@ -3921,8 +3931,8 @@ arc_adjust(void)
 	 *	mru + mfu + mru ghost + mfu ghost <= 2 * arc_c
 	 *		    mru ghost + mfu ghost <= arc_c
 	 */
-	target = refcount_count(&arc_mru_ghost->arcs_size) +
-	    refcount_count(&arc_mfu_ghost->arcs_size) - arc_c;
+	target = zfs_refcount_count(&arc_mru_ghost->arcs_size) +
+	    zfs_refcount_count(&arc_mfu_ghost->arcs_size) - arc_c;
 
 	bytes = arc_adjust_impl(arc_mfu_ghost, 0, target, ARC_BUFC_DATA);
 	total_evicted += bytes;
@@ -4422,10 +4432,10 @@ static uint64_t
 arc_evictable_memory(void)
 {
 	uint64_t arc_clean =
-	    refcount_count(&arc_mru->arcs_esize[ARC_BUFC_DATA]) +
-	    refcount_count(&arc_mru->arcs_esize[ARC_BUFC_METADATA]) +
-	    refcount_count(&arc_mfu->arcs_esize[ARC_BUFC_DATA]) +
-	    refcount_count(&arc_mfu->arcs_esize[ARC_BUFC_METADATA]);
+	    zfs_refcount_count(&arc_mru->arcs_esize[ARC_BUFC_DATA]) +
+	    zfs_refcount_count(&arc_mru->arcs_esize[ARC_BUFC_METADATA]) +
+	    zfs_refcount_count(&arc_mfu->arcs_esize[ARC_BUFC_DATA]) +
+	    zfs_refcount_count(&arc_mfu->arcs_esize[ARC_BUFC_METADATA]);
 	uint64_t arc_dirty = MAX((int64_t)arc_size - (int64_t)arc_clean, 0);
 
 	/*
@@ -4532,8 +4542,8 @@ arc_adapt(int bytes, arc_state_t *state)
 {
 	int mult;
 	uint64_t arc_p_min = (arc_c >> arc_p_min_shift);
-	int64_t mrug_size = refcount_count(&arc_mru_ghost->arcs_size);
-	int64_t mfug_size = refcount_count(&arc_mfu_ghost->arcs_size);
+	int64_t mrug_size = zfs_refcount_count(&arc_mru_ghost->arcs_size);
+	int64_t mfug_size = zfs_refcount_count(&arc_mfu_ghost->arcs_size);
 
 	if (state == arc_l2c_only)
 		return;
@@ -4698,7 +4708,7 @@ arc_get_data_impl(arc_buf_hdr_t *hdr, uint64_t size, void *tag)
 	 */
 	if (!GHOST_STATE(state)) {
 
-		(void) refcount_add_many(&state->arcs_size, size, tag);
+		(void) zfs_refcount_add_many(&state->arcs_size, size, tag);
 
 		/*
 		 * If this is reached via arc_read, the link is
@@ -4710,8 +4720,8 @@ arc_get_data_impl(arc_buf_hdr_t *hdr, uint64_t size, void *tag)
 		 * trying to [add|remove]_reference it.
 		 */
 		if (multilist_link_active(&hdr->b_l1hdr.b_arc_node)) {
-			ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
-			(void) refcount_add_many(&state->arcs_esize[type],
+			ASSERT(zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
+			(void) zfs_refcount_add_many(&state->arcs_esize[type],
 			    size, tag);
 		}
 
@@ -4720,8 +4730,8 @@ arc_get_data_impl(arc_buf_hdr_t *hdr, uint64_t size, void *tag)
 		 * data, and we have outgrown arc_p, update arc_p
 		 */
 		if (arc_size < arc_c && hdr->b_l1hdr.b_state == arc_anon &&
-		    (refcount_count(&arc_anon->arcs_size) +
-		    refcount_count(&arc_mru->arcs_size) > arc_p))
+		    (zfs_refcount_count(&arc_anon->arcs_size) +
+		    zfs_refcount_count(&arc_mru->arcs_size) > arc_p))
 			arc_p = MIN(arc_c, arc_p + size);
 	}
 }
@@ -4758,13 +4768,13 @@ arc_free_data_impl(arc_buf_hdr_t *hdr, uint64_t size, void *tag)
 
 	/* protected by hash lock, if in the hash table */
 	if (multilist_link_active(&hdr->b_l1hdr.b_arc_node)) {
-		ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
+		ASSERT(zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
 		ASSERT(state != arc_anon && state != arc_l2c_only);
 
-		(void) refcount_remove_many(&state->arcs_esize[type],
+		(void) zfs_refcount_remove_many(&state->arcs_esize[type],
 		    size, tag);
 	}
-	(void) refcount_remove_many(&state->arcs_size, size, tag);
+	(void) zfs_refcount_remove_many(&state->arcs_size, size, tag);
 
 	VERIFY3U(hdr->b_type, ==, type);
 	if (type == ARC_BUFC_METADATA) {
@@ -4811,7 +4821,7 @@ arc_access(arc_buf_hdr_t *hdr, kmutex_t *hash_lock)
 		 *   another prefetch (to make it less likely to be evicted).
 		 */
 		if (HDR_PREFETCH(hdr)) {
-			if (refcount_count(&hdr->b_l1hdr.b_refcnt) == 0) {
+			if (zfs_refcount_count(&hdr->b_l1hdr.b_refcnt) == 0) {
 				/* link protected by hash lock */
 				ASSERT(multilist_link_active(
 				    &hdr->b_l1hdr.b_arc_node));
@@ -4852,7 +4862,7 @@ arc_access(arc_buf_hdr_t *hdr, kmutex_t *hash_lock)
 
 		if (HDR_PREFETCH(hdr)) {
 			new_state = arc_mru;
-			if (refcount_count(&hdr->b_l1hdr.b_refcnt) > 0)
+			if (zfs_refcount_count(&hdr->b_l1hdr.b_refcnt) > 0)
 				arc_hdr_clear_flags(hdr, ARC_FLAG_PREFETCH);
 			DTRACE_PROBE1(new_state__mru, arc_buf_hdr_t *, hdr);
 		} else {
@@ -4876,7 +4886,7 @@ arc_access(arc_buf_hdr_t *hdr, kmutex_t *hash_lock)
 		 * the head of the list now.
 		 */
 		if ((HDR_PREFETCH(hdr)) != 0) {
-			ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
+			ASSERT(zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
 			/* link protected by hash_lock */
 			ASSERT(multilist_link_active(&hdr->b_l1hdr.b_arc_node));
 		}
@@ -4896,7 +4906,7 @@ arc_access(arc_buf_hdr_t *hdr, kmutex_t *hash_lock)
 			 * This is a prefetch access...
 			 * move this block back to the MRU state.
 			 */
-			ASSERT0(refcount_count(&hdr->b_l1hdr.b_refcnt));
+			ASSERT0(zfs_refcount_count(&hdr->b_l1hdr.b_refcnt));
 			new_state = arc_mru;
 		}
 
@@ -5098,7 +5108,7 @@ arc_read_done(zio_t *zio)
 		ASSERT3P(hdr->b_l1hdr.b_pabd, !=, NULL);
 	}
 
-	ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt) ||
+	ASSERT(zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt) ||
 	    callback_list != NULL);
 
 	if (no_zio_error) {
@@ -5109,7 +5119,7 @@ arc_read_done(zio_t *zio)
 			arc_change_state(arc_anon, hdr, hash_lock);
 		if (HDR_IN_HASH_TABLE(hdr))
 			buf_hash_remove(hdr);
-		freeable = refcount_is_zero(&hdr->b_l1hdr.b_refcnt);
+		freeable = zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt);
 	}
 
 	/*
@@ -5129,7 +5139,7 @@ arc_read_done(zio_t *zio)
 		 * in the cache).
 		 */
 		ASSERT3P(hdr->b_l1hdr.b_state, ==, arc_anon);
-		freeable = refcount_is_zero(&hdr->b_l1hdr.b_refcnt);
+		freeable = zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt);
 	}
 
 	/* execute each callback and free its structure */
@@ -5282,7 +5292,7 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_done_func_t *done,
 			VERIFY0(arc_buf_alloc_impl(hdr, private,
 			    compressed_read, B_TRUE, &buf));
 		} else if (*arc_flags & ARC_FLAG_PREFETCH &&
-		    refcount_count(&hdr->b_l1hdr.b_refcnt) == 0) {
+		    zfs_refcount_count(&hdr->b_l1hdr.b_refcnt) == 0) {
 			arc_hdr_set_flags(hdr, ARC_FLAG_PREFETCH);
 		}
 		DTRACE_PROBE1(arc__hit, arc_buf_hdr_t *, hdr);
@@ -5348,7 +5358,7 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_done_func_t *done,
 			ASSERT3P(hdr->b_l1hdr.b_pabd, ==, NULL);
 			ASSERT(GHOST_STATE(hdr->b_l1hdr.b_state));
 			ASSERT(!HDR_IO_IN_PROGRESS(hdr));
-			ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
+			ASSERT(zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
 			ASSERT3P(hdr->b_l1hdr.b_buf, ==, NULL);
 			ASSERT3P(hdr->b_l1hdr.b_freeze_cksum, ==, NULL);
 
@@ -5546,7 +5556,7 @@ arc_add_prune_callback(arc_prune_func_t *func, void *private)
 	p->p_pfunc = func;
 	p->p_private = private;
 	list_link_init(&p->p_node);
-	refcount_create(&p->p_refcnt);
+	zfs_refcount_create(&p->p_refcnt);
 
 	mutex_enter(&arc_prune_mtx);
 	zfs_refcount_add(&p->p_refcnt, &arc_prune_list);
@@ -5562,15 +5572,15 @@ arc_remove_prune_callback(arc_prune_t *p)
 	boolean_t wait = B_FALSE;
 	mutex_enter(&arc_prune_mtx);
 	list_remove(&arc_prune_list, p);
-	if (refcount_remove(&p->p_refcnt, &arc_prune_list) > 0)
+	if (zfs_refcount_remove(&p->p_refcnt, &arc_prune_list) > 0)
 		wait = B_TRUE;
 	mutex_exit(&arc_prune_mtx);
 
 	/* wait for arc_prune_task to finish */
 	if (wait)
 		taskq_wait_outstanding(arc_prune_taskq, 0);
-	ASSERT0(refcount_count(&p->p_refcnt));
-	refcount_destroy(&p->p_refcnt);
+	ASSERT0(zfs_refcount_count(&p->p_refcnt));
+	zfs_refcount_destroy(&p->p_refcnt);
 	kmem_free(p, sizeof (*p));
 }
 
@@ -5613,7 +5623,7 @@ arc_freed(spa_t *spa, const blkptr_t *bp)
 	 * this hdr, then we don't destroy the hdr.
 	 */
 	if (!HDR_HAS_L1HDR(hdr) || (!HDR_IO_IN_PROGRESS(hdr) &&
-	    refcount_is_zero(&hdr->b_l1hdr.b_refcnt))) {
+	    zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt))) {
 		arc_change_state(arc_anon, hdr, hash_lock);
 		arc_hdr_destroy(hdr);
 		mutex_exit(hash_lock);
@@ -5659,7 +5669,7 @@ arc_release(arc_buf_t *buf, void *tag)
 		ASSERT(HDR_EMPTY(hdr));
 
 		ASSERT3U(hdr->b_l1hdr.b_bufcnt, ==, 1);
-		ASSERT3S(refcount_count(&hdr->b_l1hdr.b_refcnt), ==, 1);
+		ASSERT3S(zfs_refcount_count(&hdr->b_l1hdr.b_refcnt), ==, 1);
 		ASSERT(!list_link_active(&hdr->b_l1hdr.b_arc_node));
 
 		hdr->b_l1hdr.b_arc_access = 0;
@@ -5687,7 +5697,7 @@ arc_release(arc_buf_t *buf, void *tag)
 	ASSERT3P(state, !=, arc_anon);
 
 	/* this buffer is not on any list */
-	ASSERT3S(refcount_count(&hdr->b_l1hdr.b_refcnt), >, 0);
+	ASSERT3S(zfs_refcount_count(&hdr->b_l1hdr.b_refcnt), >, 0);
 
 	if (HDR_HAS_L2HDR(hdr)) {
 		mutex_enter(&hdr->b_l2hdr.b_dev->l2ad_mtx);
@@ -5778,12 +5788,13 @@ arc_release(arc_buf_t *buf, void *tag)
 		ASSERT3P(hdr->b_l1hdr.b_pabd, !=, NULL);
 		ASSERT3P(state, !=, arc_l2c_only);
 
-		(void) refcount_remove_many(&state->arcs_size,
+		(void) zfs_refcount_remove_many(&state->arcs_size,
 		    arc_buf_size(buf), buf);
 
-		if (refcount_is_zero(&hdr->b_l1hdr.b_refcnt)) {
+		if (zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt)) {
 			ASSERT3P(state, !=, arc_l2c_only);
-			(void) refcount_remove_many(&state->arcs_esize[type],
+			(void) zfs_refcount_remove_many(
+			    &state->arcs_esize[type],
 			    arc_buf_size(buf), buf);
 		}
 
@@ -5804,7 +5815,7 @@ arc_release(arc_buf_t *buf, void *tag)
 		nhdr = arc_hdr_alloc(spa, psize, lsize, compress, type);
 		ASSERT3P(nhdr->b_l1hdr.b_buf, ==, NULL);
 		ASSERT0(nhdr->b_l1hdr.b_bufcnt);
-		ASSERT0(refcount_count(&nhdr->b_l1hdr.b_refcnt));
+		ASSERT0(zfs_refcount_count(&nhdr->b_l1hdr.b_refcnt));
 		VERIFY3U(nhdr->b_type, ==, type);
 		ASSERT(!HDR_SHARED_DATA(nhdr));
 
@@ -5819,11 +5830,11 @@ arc_release(arc_buf_t *buf, void *tag)
 		buf->b_hdr = nhdr;
 
 		mutex_exit(&buf->b_evict_lock);
-		(void) refcount_add_many(&arc_anon->arcs_size,
-		    HDR_GET_LSIZE(nhdr), buf);
+		(void) zfs_refcount_add_many(&arc_anon->arcs_size,
+		    arc_buf_size(buf), buf);
 	} else {
 		mutex_exit(&buf->b_evict_lock);
-		ASSERT(refcount_count(&hdr->b_l1hdr.b_refcnt) == 1);
+		ASSERT(zfs_refcount_count(&hdr->b_l1hdr.b_refcnt) == 1);
 		/* protected by hash lock, or hdr is on arc_anon */
 		ASSERT(!multilist_link_active(&hdr->b_l1hdr.b_arc_node));
 		ASSERT(!HDR_IO_IN_PROGRESS(hdr));
@@ -5860,7 +5871,7 @@ arc_referenced(arc_buf_t *buf)
 	int referenced;
 
 	mutex_enter(&buf->b_evict_lock);
-	referenced = (refcount_count(&buf->b_hdr->b_l1hdr.b_refcnt));
+	referenced = (zfs_refcount_count(&buf->b_hdr->b_l1hdr.b_refcnt));
 	mutex_exit(&buf->b_evict_lock);
 	return (referenced);
 }
@@ -5877,7 +5888,7 @@ arc_write_ready(zio_t *zio)
 	fstrans_cookie_t cookie = spl_fstrans_mark();
 
 	ASSERT(HDR_HAS_L1HDR(hdr));
-	ASSERT(!refcount_is_zero(&buf->b_hdr->b_l1hdr.b_refcnt));
+	ASSERT(!zfs_refcount_is_zero(&buf->b_hdr->b_l1hdr.b_refcnt));
 	ASSERT(hdr->b_l1hdr.b_bufcnt > 0);
 
 	/*
@@ -6029,7 +6040,7 @@ arc_write_done(zio_t *zio)
 				if (!BP_EQUAL(&zio->io_bp_orig, zio->io_bp))
 					panic("bad overwrite, hdr=%p exists=%p",
 					    (void *)hdr, (void *)exists);
-				ASSERT(refcount_is_zero(
+				ASSERT(zfs_refcount_is_zero(
 				    &exists->b_l1hdr.b_refcnt));
 				arc_change_state(arc_anon, exists, hash_lock);
 				mutex_exit(hash_lock);
@@ -6059,7 +6070,7 @@ arc_write_done(zio_t *zio)
 		arc_hdr_clear_flags(hdr, ARC_FLAG_IO_IN_PROGRESS);
 	}
 
-	ASSERT(!refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
+	ASSERT(!zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
 	callback->awcb_done(zio, buf, callback->awcb_private);
 
 	abd_put(zio->io_abd);
@@ -6222,7 +6233,7 @@ arc_tempreserve_space(uint64_t reserve, uint64_t txg)
 	/* assert that it has not wrapped around */
 	ASSERT3S(atomic_add_64_nv(&arc_loaned_bytes, 0), >=, 0);
 
-	anon_size = MAX((int64_t)(refcount_count(&arc_anon->arcs_size) -
+	anon_size = MAX((int64_t)(zfs_refcount_count(&arc_anon->arcs_size) -
 	    arc_loaned_bytes), 0);
 
 	/*
@@ -6245,9 +6256,10 @@ arc_tempreserve_space(uint64_t reserve, uint64_t txg)
 	if (reserve + arc_tempreserve + anon_size > arc_c / 2 &&
 	    anon_size > arc_c / 4) {
 		uint64_t meta_esize =
-		    refcount_count(&arc_anon->arcs_esize[ARC_BUFC_METADATA]);
+		    zfs_refcount_count(
+		    &arc_anon->arcs_esize[ARC_BUFC_METADATA]);
 		uint64_t data_esize =
-		    refcount_count(&arc_anon->arcs_esize[ARC_BUFC_DATA]);
+		    zfs_refcount_count(&arc_anon->arcs_esize[ARC_BUFC_DATA]);
 		dprintf("failing, arc_tempreserve=%lluK anon_meta=%lluK "
 		    "anon_data=%lluK tempreserve=%lluK arc_c=%lluK\n",
 		    arc_tempreserve >> 10, meta_esize >> 10,
@@ -6263,11 +6275,11 @@ static void
 arc_kstat_update_state(arc_state_t *state, kstat_named_t *size,
     kstat_named_t *evict_data, kstat_named_t *evict_metadata)
 {
-	size->value.ui64 = refcount_count(&state->arcs_size);
+	size->value.ui64 = zfs_refcount_count(&state->arcs_size);
 	evict_data->value.ui64 =
-	    refcount_count(&state->arcs_esize[ARC_BUFC_DATA]);
+	    zfs_refcount_count(&state->arcs_esize[ARC_BUFC_DATA]);
 	evict_metadata->value.ui64 =
-	    refcount_count(&state->arcs_esize[ARC_BUFC_METADATA]);
+	    zfs_refcount_count(&state->arcs_esize[ARC_BUFC_METADATA]);
 }
 
 static int
@@ -6484,25 +6496,25 @@ arc_state_init(void)
 	    offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node),
 	    arc_state_multilist_index_func);
 
-	refcount_create(&arc_anon->arcs_esize[ARC_BUFC_METADATA]);
-	refcount_create(&arc_anon->arcs_esize[ARC_BUFC_DATA]);
-	refcount_create(&arc_mru->arcs_esize[ARC_BUFC_METADATA]);
-	refcount_create(&arc_mru->arcs_esize[ARC_BUFC_DATA]);
-	refcount_create(&arc_mru_ghost->arcs_esize[ARC_BUFC_METADATA]);
-	refcount_create(&arc_mru_ghost->arcs_esize[ARC_BUFC_DATA]);
-	refcount_create(&arc_mfu->arcs_esize[ARC_BUFC_METADATA]);
-	refcount_create(&arc_mfu->arcs_esize[ARC_BUFC_DATA]);
-	refcount_create(&arc_mfu_ghost->arcs_esize[ARC_BUFC_METADATA]);
-	refcount_create(&arc_mfu_ghost->arcs_esize[ARC_BUFC_DATA]);
-	refcount_create(&arc_l2c_only->arcs_esize[ARC_BUFC_METADATA]);
-	refcount_create(&arc_l2c_only->arcs_esize[ARC_BUFC_DATA]);
-
-	refcount_create(&arc_anon->arcs_size);
-	refcount_create(&arc_mru->arcs_size);
-	refcount_create(&arc_mru_ghost->arcs_size);
-	refcount_create(&arc_mfu->arcs_size);
-	refcount_create(&arc_mfu_ghost->arcs_size);
-	refcount_create(&arc_l2c_only->arcs_size);
+	zfs_refcount_create(&arc_anon->arcs_esize[ARC_BUFC_METADATA]);
+	zfs_refcount_create(&arc_anon->arcs_esize[ARC_BUFC_DATA]);
+	zfs_refcount_create(&arc_mru->arcs_esize[ARC_BUFC_METADATA]);
+	zfs_refcount_create(&arc_mru->arcs_esize[ARC_BUFC_DATA]);
+	zfs_refcount_create(&arc_mru_ghost->arcs_esize[ARC_BUFC_METADATA]);
+	zfs_refcount_create(&arc_mru_ghost->arcs_esize[ARC_BUFC_DATA]);
+	zfs_refcount_create(&arc_mfu->arcs_esize[ARC_BUFC_METADATA]);
+	zfs_refcount_create(&arc_mfu->arcs_esize[ARC_BUFC_DATA]);
+	zfs_refcount_create(&arc_mfu_ghost->arcs_esize[ARC_BUFC_METADATA]);
+	zfs_refcount_create(&arc_mfu_ghost->arcs_esize[ARC_BUFC_DATA]);
+	zfs_refcount_create(&arc_l2c_only->arcs_esize[ARC_BUFC_METADATA]);
+	zfs_refcount_create(&arc_l2c_only->arcs_esize[ARC_BUFC_DATA]);
+
+	zfs_refcount_create(&arc_anon->arcs_size);
+	zfs_refcount_create(&arc_mru->arcs_size);
+	zfs_refcount_create(&arc_mru_ghost->arcs_size);
+	zfs_refcount_create(&arc_mfu->arcs_size);
+	zfs_refcount_create(&arc_mfu_ghost->arcs_size);
+	zfs_refcount_create(&arc_l2c_only->arcs_size);
 
 	arc_anon->arcs_state = ARC_STATE_ANON;
 	arc_mru->arcs_state = ARC_STATE_MRU;
@@ -6515,25 +6527,25 @@ arc_state_init(void)
 static void
 arc_state_fini(void)
 {
-	refcount_destroy(&arc_anon->arcs_esize[ARC_BUFC_METADATA]);
-	refcount_destroy(&arc_anon->arcs_esize[ARC_BUFC_DATA]);
-	refcount_destroy(&arc_mru->arcs_esize[ARC_BUFC_METADATA]);
-	refcount_destroy(&arc_mru->arcs_esize[ARC_BUFC_DATA]);
-	refcount_destroy(&arc_mru_ghost->arcs_esize[ARC_BUFC_METADATA]);
-	refcount_destroy(&arc_mru_ghost->arcs_esize[ARC_BUFC_DATA]);
-	refcount_destroy(&arc_mfu->arcs_esize[ARC_BUFC_METADATA]);
-	refcount_destroy(&arc_mfu->arcs_esize[ARC_BUFC_DATA]);
-	refcount_destroy(&arc_mfu_ghost->arcs_esize[ARC_BUFC_METADATA]);
-	refcount_destroy(&arc_mfu_ghost->arcs_esize[ARC_BUFC_DATA]);
-	refcount_destroy(&arc_l2c_only->arcs_esize[ARC_BUFC_METADATA]);
-	refcount_destroy(&arc_l2c_only->arcs_esize[ARC_BUFC_DATA]);
-
-	refcount_destroy(&arc_anon->arcs_size);
-	refcount_destroy(&arc_mru->arcs_size);
-	refcount_destroy(&arc_mru_ghost->arcs_size);
-	refcount_destroy(&arc_mfu->arcs_size);
-	refcount_destroy(&arc_mfu_ghost->arcs_size);
-	refcount_destroy(&arc_l2c_only->arcs_size);
+	zfs_refcount_destroy(&arc_anon->arcs_esize[ARC_BUFC_METADATA]);
+	zfs_refcount_destroy(&arc_anon->arcs_esize[ARC_BUFC_DATA]);
+	zfs_refcount_destroy(&arc_mru->arcs_esize[ARC_BUFC_METADATA]);
+	zfs_refcount_destroy(&arc_mru->arcs_esize[ARC_BUFC_DATA]);
+	zfs_refcount_destroy(&arc_mru_ghost->arcs_esize[ARC_BUFC_METADATA]);
+	zfs_refcount_destroy(&arc_mru_ghost->arcs_esize[ARC_BUFC_DATA]);
+	zfs_refcount_destroy(&arc_mfu->arcs_esize[ARC_BUFC_METADATA]);
+	zfs_refcount_destroy(&arc_mfu->arcs_esize[ARC_BUFC_DATA]);
+	zfs_refcount_destroy(&arc_mfu_ghost->arcs_esize[ARC_BUFC_METADATA]);
+	zfs_refcount_destroy(&arc_mfu_ghost->arcs_esize[ARC_BUFC_DATA]);
+	zfs_refcount_destroy(&arc_l2c_only->arcs_esize[ARC_BUFC_METADATA]);
+	zfs_refcount_destroy(&arc_l2c_only->arcs_esize[ARC_BUFC_DATA]);
+
+	zfs_refcount_destroy(&arc_anon->arcs_size);
+	zfs_refcount_destroy(&arc_mru->arcs_size);
+	zfs_refcount_destroy(&arc_mru_ghost->arcs_size);
+	zfs_refcount_destroy(&arc_mfu->arcs_size);
+	zfs_refcount_destroy(&arc_mfu_ghost->arcs_size);
+	zfs_refcount_destroy(&arc_l2c_only->arcs_size);
 
 	multilist_destroy(arc_mru->arcs_list[ARC_BUFC_METADATA]);
 	multilist_destroy(arc_mru_ghost->arcs_list[ARC_BUFC_METADATA]);
@@ -6704,8 +6716,8 @@ arc_fini(void)
 	mutex_enter(&arc_prune_mtx);
 	while ((p = list_head(&arc_prune_list)) != NULL) {
 		list_remove(&arc_prune_list, p);
-		refcount_remove(&p->p_refcnt, &arc_prune_list);
-		refcount_destroy(&p->p_refcnt);
+		zfs_refcount_remove(&p->p_refcnt, &arc_prune_list);
+		zfs_refcount_destroy(&p->p_refcnt);
 		kmem_free(p, sizeof (*p));
 	}
 	mutex_exit(&arc_prune_mtx);
@@ -7108,7 +7120,7 @@ l2arc_write_done(zio_t *zio)
 			ARCSTAT_INCR(arcstat_l2_lsize, -HDR_GET_LSIZE(hdr));
 
 			bytes_dropped += arc_hdr_size(hdr);
-			(void) refcount_remove_many(&dev->l2ad_alloc,
+			(void) zfs_refcount_remove_many(&dev->l2ad_alloc,
 			    arc_hdr_size(hdr), hdr);
 		}
 
@@ -7527,7 +7539,8 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
 			list_insert_head(&dev->l2ad_buflist, hdr);
 			mutex_exit(&dev->l2ad_mtx);
 
-			(void) refcount_add_many(&dev->l2ad_alloc, psize, hdr);
+			(void) zfs_refcount_add_many(&dev->l2ad_alloc, psize,
+			    hdr);
 
 			/*
 			 * Normally the L2ARC can use the hdr's data, but if
@@ -7762,7 +7775,7 @@ l2arc_add_vdev(spa_t *spa, vdev_t *vd)
 	    offsetof(arc_buf_hdr_t, b_l2hdr.b_l2node));
 
 	vdev_space_update(vd, 0, 0, adddev->l2ad_end - adddev->l2ad_hand);
-	refcount_create(&adddev->l2ad_alloc);
+	zfs_refcount_create(&adddev->l2ad_alloc);
 
 	/*
 	 * Add device to global list
@@ -7808,7 +7821,7 @@ l2arc_remove_vdev(vdev_t *vd)
 	l2arc_evict(remdev, 0, B_TRUE);
 	list_destroy(&remdev->l2ad_buflist);
 	mutex_destroy(&remdev->l2ad_mtx);
-	refcount_destroy(&remdev->l2ad_alloc);
+	zfs_refcount_destroy(&remdev->l2ad_alloc);
 	kmem_free(remdev, sizeof (l2arc_dev_t));
 }
 
diff --git a/zfs/module/zfs/dbuf.c b/zfs/module/zfs/dbuf.c
index c6e72d2..62b77bb 100644
--- a/zfs/module/zfs/dbuf.c
+++ b/zfs/module/zfs/dbuf.c
@@ -165,7 +165,7 @@ dbuf_cons(void *vdb, void *unused, int kmflag)
 	mutex_init(&db->db_mtx, NULL, MUTEX_DEFAULT, NULL);
 	cv_init(&db->db_changed, NULL, CV_DEFAULT, NULL);
 	multilist_link_init(&db->db_cache_link);
-	refcount_create(&db->db_holds);
+	zfs_refcount_create(&db->db_holds);
 	multilist_link_init(&db->db_cache_link);
 
 	return (0);
@@ -179,7 +179,7 @@ dbuf_dest(void *vdb, void *unused)
 	mutex_destroy(&db->db_mtx);
 	cv_destroy(&db->db_changed);
 	ASSERT(!multilist_link_active(&db->db_cache_link));
-	refcount_destroy(&db->db_holds);
+	zfs_refcount_destroy(&db->db_holds);
 }
 
 /*
@@ -317,7 +317,7 @@ dbuf_hash_remove(dmu_buf_impl_t *db)
 	 * We mustn't hold db_mtx to maintain lock ordering:
 	 * DBUF_HASH_MUTEX > db_mtx.
 	 */
-	ASSERT(refcount_is_zero(&db->db_holds));
+	ASSERT(zfs_refcount_is_zero(&db->db_holds));
 	ASSERT(db->db_state == DB_EVICTING);
 	ASSERT(!MUTEX_HELD(&db->db_mtx));
 
@@ -354,7 +354,7 @@ dbuf_verify_user(dmu_buf_impl_t *db, dbvu_verify_type_t verify_type)
 	ASSERT(db->db.db_data != NULL);
 	ASSERT3U(db->db_state, ==, DB_CACHED);
 
-	holds = refcount_count(&db->db_holds);
+	holds = zfs_refcount_count(&db->db_holds);
 	if (verify_type == DBVU_EVICTING) {
 		/*
 		 * Immediate eviction occurs when holds == dirtycnt.
@@ -478,7 +478,7 @@ dbuf_cache_above_hiwater(void)
 	uint64_t dbuf_cache_hiwater_bytes =
 	    (dbuf_cache_target * dbuf_cache_hiwater_pct) / 100;
 
-	return (refcount_count(&dbuf_cache_size) >
+	return (zfs_refcount_count(&dbuf_cache_size) >
 	    dbuf_cache_target + dbuf_cache_hiwater_bytes);
 }
 
@@ -490,7 +490,7 @@ dbuf_cache_above_lowater(void)
 	uint64_t dbuf_cache_lowater_bytes =
 	    (dbuf_cache_target * dbuf_cache_lowater_pct) / 100;
 
-	return (refcount_count(&dbuf_cache_size) >
+	return (zfs_refcount_count(&dbuf_cache_size) >
 	    dbuf_cache_target - dbuf_cache_lowater_bytes);
 }
 
@@ -524,7 +524,7 @@ dbuf_evict_one(void)
 	if (db != NULL) {
 		multilist_sublist_remove(mls, db);
 		multilist_sublist_unlock(mls);
-		(void) refcount_remove_many(&dbuf_cache_size,
+		(void) zfs_refcount_remove_many(&dbuf_cache_size,
 		    db->db.db_size, db);
 		dbuf_destroy(db);
 	} else {
@@ -611,7 +611,7 @@ dbuf_evict_notify(void)
 	 * because it's OK to occasionally make the wrong decision here,
 	 * and grabbing the lock results in massive lock contention.
 	 */
-	if (refcount_count(&dbuf_cache_size) > dbuf_cache_target_bytes()) {
+	if (zfs_refcount_count(&dbuf_cache_size) > dbuf_cache_target_bytes()) {
 		if (dbuf_cache_above_hiwater())
 			dbuf_evict_one();
 		cv_signal(&dbuf_evict_cv);
@@ -679,7 +679,7 @@ dbuf_init(void)
 	dbuf_cache = multilist_create(sizeof (dmu_buf_impl_t),
 	    offsetof(dmu_buf_impl_t, db_cache_link),
 	    dbuf_cache_multilist_index_func);
-	refcount_create(&dbuf_cache_size);
+	zfs_refcount_create(&dbuf_cache_size);
 
 	tsd_create(&zfs_dbuf_evict_key, NULL);
 	dbuf_evict_thread_exit = B_FALSE;
@@ -723,7 +723,7 @@ dbuf_fini(void)
 	mutex_destroy(&dbuf_evict_lock);
 	cv_destroy(&dbuf_evict_cv);
 
-	refcount_destroy(&dbuf_cache_size);
+	zfs_refcount_destroy(&dbuf_cache_size);
 	multilist_destroy(dbuf_cache);
 }
 
@@ -910,7 +910,7 @@ dbuf_loan_arcbuf(dmu_buf_impl_t *db)
 
 	ASSERT(db->db_blkid != DMU_BONUS_BLKID);
 	mutex_enter(&db->db_mtx);
-	if (arc_released(db->db_buf) || refcount_count(&db->db_holds) > 1) {
+	if (arc_released(db->db_buf) || zfs_refcount_count(&db->db_holds) > 1) {
 		int blksz = db->db.db_size;
 		spa_t *spa = db->db_objset->os_spa;
 
@@ -983,7 +983,7 @@ dbuf_read_done(zio_t *zio, arc_buf_t *buf, void *vdb)
 	/*
 	 * All reads are synchronous, so we must have a hold on the dbuf
 	 */
-	ASSERT(refcount_count(&db->db_holds) > 0);
+	ASSERT(zfs_refcount_count(&db->db_holds) > 0);
 	ASSERT(db->db_buf == NULL);
 	ASSERT(db->db.db_data == NULL);
 	if (db->db_level == 0 && db->db_freed_in_flight) {
@@ -1017,7 +1017,7 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags)
 
 	DB_DNODE_ENTER(db);
 	dn = DB_DNODE(db);
-	ASSERT(!refcount_is_zero(&db->db_holds));
+	ASSERT(!zfs_refcount_is_zero(&db->db_holds));
 	/* We need the struct_rwlock to prevent db_blkptr from changing. */
 	ASSERT(RW_LOCK_HELD(&dn->dn_struct_rwlock));
 	ASSERT(MUTEX_HELD(&db->db_mtx));
@@ -1150,7 +1150,7 @@ dbuf_fix_old_data(dmu_buf_impl_t *db, uint64_t txg)
 		dr->dt.dl.dr_data = kmem_alloc(bonuslen, KM_SLEEP);
 		arc_space_consume(bonuslen, ARC_SPACE_BONUS);
 		bcopy(db->db.db_data, dr->dt.dl.dr_data, bonuslen);
-	} else if (refcount_count(&db->db_holds) > db->db_dirtycnt) {
+	} else if (zfs_refcount_count(&db->db_holds) > db->db_dirtycnt) {
 		int size = arc_buf_size(db->db_buf);
 		arc_buf_contents_t type = DBUF_GET_BUFC_TYPE(db);
 		spa_t *spa = db->db_objset->os_spa;
@@ -1182,7 +1182,7 @@ dbuf_read(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags)
 	 * We don't have to hold the mutex to check db_state because it
 	 * can't be freed while we have a hold on the buffer.
 	 */
-	ASSERT(!refcount_is_zero(&db->db_holds));
+	ASSERT(!zfs_refcount_is_zero(&db->db_holds));
 
 	if (db->db_state == DB_NOFILL)
 		return (SET_ERROR(EIO));
@@ -1277,7 +1277,7 @@ dbuf_read(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags)
 static void
 dbuf_noread(dmu_buf_impl_t *db)
 {
-	ASSERT(!refcount_is_zero(&db->db_holds));
+	ASSERT(!zfs_refcount_is_zero(&db->db_holds));
 	ASSERT(db->db_blkid != DMU_BONUS_BLKID);
 	mutex_enter(&db->db_mtx);
 	while (db->db_state == DB_READ || db->db_state == DB_FILL)
@@ -1397,7 +1397,7 @@ dbuf_free_range(dnode_t *dn, uint64_t start_blkid, uint64_t end_blkid,
 			mutex_exit(&db->db_mtx);
 			continue;
 		}
-		if (refcount_count(&db->db_holds) == 0) {
+		if (zfs_refcount_count(&db->db_holds) == 0) {
 			ASSERT(db->db_buf);
 			dbuf_destroy(db);
 			continue;
@@ -1544,7 +1544,7 @@ dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
 	int txgoff = tx->tx_txg & TXG_MASK;
 
 	ASSERT(tx->tx_txg != 0);
-	ASSERT(!refcount_is_zero(&db->db_holds));
+	ASSERT(!zfs_refcount_is_zero(&db->db_holds));
 	DMU_TX_DIRTY_BUF(tx, db);
 
 	DB_DNODE_ENTER(db);
@@ -1606,6 +1606,9 @@ dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
 			    FTAG);
 		}
 	}
+
+	if (tx->tx_txg > dn->dn_dirty_txg)
+		dn->dn_dirty_txg = tx->tx_txg;
 	mutex_exit(&dn->dn_mtx);
 
 	if (db->db_blkid == DMU_SPILL_BLKID)
@@ -1909,7 +1912,7 @@ dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
 	ASSERT(db->db_dirtycnt > 0);
 	db->db_dirtycnt -= 1;
 
-	if (refcount_remove(&db->db_holds, (void *)(uintptr_t)txg) == 0) {
+	if (zfs_refcount_remove(&db->db_holds, (void *)(uintptr_t)txg) == 0) {
 		ASSERT(db->db_state == DB_NOFILL || arc_released(db->db_buf));
 		dbuf_destroy(db);
 		return (B_TRUE);
@@ -1926,7 +1929,7 @@ dmu_buf_will_dirty(dmu_buf_t *db_fake, dmu_tx_t *tx)
 	dbuf_dirty_record_t *dr;
 
 	ASSERT(tx->tx_txg != 0);
-	ASSERT(!refcount_is_zero(&db->db_holds));
+	ASSERT(!zfs_refcount_is_zero(&db->db_holds));
 
 	/*
 	 * Quick check for dirtyness.  For already dirty blocks, this
@@ -1978,7 +1981,7 @@ dmu_buf_will_fill(dmu_buf_t *db_fake, dmu_tx_t *tx)
 	ASSERT(db->db_blkid != DMU_BONUS_BLKID);
 	ASSERT(tx->tx_txg != 0);
 	ASSERT(db->db_level == 0);
-	ASSERT(!refcount_is_zero(&db->db_holds));
+	ASSERT(!zfs_refcount_is_zero(&db->db_holds));
 
 	ASSERT(db->db.db_object != DMU_META_DNODE_OBJECT ||
 	    dmu_tx_private_ok(tx));
@@ -2053,7 +2056,7 @@ dmu_buf_write_embedded(dmu_buf_t *dbuf, void *data,
 void
 dbuf_assign_arcbuf(dmu_buf_impl_t *db, arc_buf_t *buf, dmu_tx_t *tx)
 {
-	ASSERT(!refcount_is_zero(&db->db_holds));
+	ASSERT(!zfs_refcount_is_zero(&db->db_holds));
 	ASSERT(db->db_blkid != DMU_BONUS_BLKID);
 	ASSERT(db->db_level == 0);
 	ASSERT3U(dbuf_is_metadata(db), ==, arc_is_metadata(buf));
@@ -2072,7 +2075,7 @@ dbuf_assign_arcbuf(dmu_buf_impl_t *db, arc_buf_t *buf, dmu_tx_t *tx)
 	ASSERT(db->db_state == DB_CACHED || db->db_state == DB_UNCACHED);
 
 	if (db->db_state == DB_CACHED &&
-	    refcount_count(&db->db_holds) - 1 > db->db_dirtycnt) {
+	    zfs_refcount_count(&db->db_holds) - 1 > db->db_dirtycnt) {
 		mutex_exit(&db->db_mtx);
 		(void) dbuf_dirty(db, tx);
 		bcopy(buf->b_data, db->db.db_data, db->db.db_size);
@@ -2117,7 +2120,7 @@ dbuf_destroy(dmu_buf_impl_t *db)
 	dmu_buf_impl_t *dndb;
 
 	ASSERT(MUTEX_HELD(&db->db_mtx));
-	ASSERT(refcount_is_zero(&db->db_holds));
+	ASSERT(zfs_refcount_is_zero(&db->db_holds));
 
 	if (db->db_buf != NULL) {
 		arc_buf_destroy(db->db_buf, db);
@@ -2137,7 +2140,7 @@ dbuf_destroy(dmu_buf_impl_t *db)
 
 	if (multilist_link_active(&db->db_cache_link)) {
 		multilist_remove(dbuf_cache, db);
-		(void) refcount_remove_many(&dbuf_cache_size,
+		(void) zfs_refcount_remove_many(&dbuf_cache_size,
 		    db->db.db_size, db);
 	}
 
@@ -2183,7 +2186,7 @@ dbuf_destroy(dmu_buf_impl_t *db)
 		DB_DNODE_EXIT(db);
 	}
 
-	ASSERT(refcount_is_zero(&db->db_holds));
+	ASSERT(zfs_refcount_is_zero(&db->db_holds));
 
 	db->db_parent = NULL;
 
@@ -2380,7 +2383,7 @@ dbuf_create(dnode_t *dn, uint8_t level, uint64_t blkid,
 		dbuf_add_ref(parent, db);
 
 	ASSERT(dn->dn_object == DMU_META_DNODE_OBJECT ||
-	    refcount_count(&dn->dn_holds) > 0);
+	    zfs_refcount_count(&dn->dn_holds) > 0);
 	(void) zfs_refcount_add(&dn->dn_holds, db);
 	atomic_inc_32(&dn->dn_dbufs_count);
 
@@ -2741,9 +2744,9 @@ __dbuf_hold_impl(struct dbuf_hold_impl_data *dh)
 	}
 
 	if (multilist_link_active(&dh->dh_db->db_cache_link)) {
-		ASSERT(refcount_is_zero(&dh->dh_db->db_holds));
+		ASSERT(zfs_refcount_is_zero(&dh->dh_db->db_holds));
 		multilist_remove(dbuf_cache, dh->dh_db);
-		(void) refcount_remove_many(&dbuf_cache_size,
+		(void) zfs_refcount_remove_many(&dbuf_cache_size,
 		    dh->dh_db->db.db_size, dh->dh_db);
 	}
 	(void) zfs_refcount_add(&dh->dh_db->db_holds, dh->dh_tag);
@@ -2935,7 +2938,7 @@ dbuf_rele_and_unlock(dmu_buf_impl_t *db, void *tag)
 	 * dnode so we can guarantee in dnode_move() that a referenced bonus
 	 * buffer has a corresponding dnode hold.
 	 */
-	holds = refcount_remove(&db->db_holds, tag);
+	holds = zfs_refcount_remove(&db->db_holds, tag);
 	ASSERT(holds >= 0);
 
 	/*
@@ -3014,7 +3017,7 @@ dbuf_rele_and_unlock(dmu_buf_impl_t *db, void *tag)
 				dbuf_destroy(db);
 			} else if (!multilist_link_active(&db->db_cache_link)) {
 				multilist_insert(dbuf_cache, db);
-				(void) refcount_add_many(&dbuf_cache_size,
+				(void) zfs_refcount_add_many(&dbuf_cache_size,
 				    db->db.db_size, db);
 				mutex_exit(&db->db_mtx);
 
@@ -3034,7 +3037,7 @@ dbuf_rele_and_unlock(dmu_buf_impl_t *db, void *tag)
 uint64_t
 dbuf_refcount(dmu_buf_impl_t *db)
 {
-	return (refcount_count(&db->db_holds));
+	return (zfs_refcount_count(&db->db_holds));
 }
 
 void *
@@ -3337,7 +3340,7 @@ dbuf_sync_leaf(dbuf_dirty_record_t *dr, dmu_tx_t *tx)
 
 	if (db->db_state != DB_NOFILL &&
 	    dn->dn_object != DMU_META_DNODE_OBJECT &&
-	    refcount_count(&db->db_holds) > 1 &&
+	    zfs_refcount_count(&db->db_holds) > 1 &&
 	    dr->dt.dl.dr_override_state != DR_OVERRIDDEN &&
 	    *datap == db->db_buf) {
 		/*
diff --git a/zfs/module/zfs/dbuf_stats.c b/zfs/module/zfs/dbuf_stats.c
index 1712c9c..7afc9dd 100644
--- a/zfs/module/zfs/dbuf_stats.c
+++ b/zfs/module/zfs/dbuf_stats.c
@@ -89,7 +89,7 @@ __dbuf_stats_hash_table_data(char *buf, size_t size, dmu_buf_impl_t *db)
 	    (u_longlong_t)db->db.db_size,
 	    !!dbuf_is_metadata(db),
 	    db->db_state,
-	    (ulong_t)refcount_count(&db->db_holds),
+	    (ulong_t)zfs_refcount_count(&db->db_holds),
 	    /* arc_buf_info_t */
 	    abi.abi_state_type,
 	    abi.abi_state_contents,
@@ -113,7 +113,7 @@ __dbuf_stats_hash_table_data(char *buf, size_t size, dmu_buf_impl_t *db)
 	    (ulong_t)doi.doi_metadata_block_size,
 	    (u_longlong_t)doi.doi_bonus_size,
 	    (ulong_t)doi.doi_indirection,
-	    (ulong_t)refcount_count(&dn->dn_holds),
+	    (ulong_t)zfs_refcount_count(&dn->dn_holds),
 	    (u_longlong_t)doi.doi_fill_count,
 	    (u_longlong_t)doi.doi_max_offset);
 
diff --git a/zfs/module/zfs/dmu.c b/zfs/module/zfs/dmu.c
index fdb707b..13538c5 100644
--- a/zfs/module/zfs/dmu.c
+++ b/zfs/module/zfs/dmu.c
@@ -2044,7 +2044,7 @@ dmu_offset_next(objset_t *os, uint64_t object, boolean_t hole, uint64_t *off)
 	 * Check if dnode is dirty
 	 */
 	for (i = 0; i < TXG_SIZE; i++) {
-		if (list_link_active(&dn->dn_dirty_link[i])) {
+		if (multilist_link_active(&dn->dn_dirty_link[i])) {
 			clean = B_FALSE;
 			break;
 		}
diff --git a/zfs/module/zfs/dmu_objset.c b/zfs/module/zfs/dmu_objset.c
index 449ebed..0bed2d3 100644
--- a/zfs/module/zfs/dmu_objset.c
+++ b/zfs/module/zfs/dmu_objset.c
@@ -1213,10 +1213,23 @@ dmu_objset_sync_dnodes(multilist_sublist_t *list, dmu_tx_t *tx)
 		ASSERT3U(dn->dn_nlevels, <=, DN_MAX_LEVELS);
 		multilist_sublist_remove(list, dn);
 
+		/*
+		 * If we are not doing useraccounting (os_synced_dnodes == NULL)
+		 * we are done with this dnode for this txg. Unset dn_dirty_txg
+		 * if later txgs aren't dirtying it so that future holders do
+		 * not get a stale value. Otherwise, we will do this in
+		 * userquota_updates_task() when processing has completely
+		 * finished for this txg.
+		 */
 		multilist_t *newlist = dn->dn_objset->os_synced_dnodes;
 		if (newlist != NULL) {
 			(void) dnode_add_ref(dn, newlist);
 			multilist_insert(newlist, dn);
+		} else {
+			mutex_enter(&dn->dn_mtx);
+			if (dn->dn_dirty_txg == tx->tx_txg)
+				dn->dn_dirty_txg = 0;
+			mutex_exit(&dn->dn_mtx);
 		}
 
 		dnode_sync(dn, tx);
@@ -1621,6 +1634,8 @@ userquota_updates_task(void *arg)
 				dn->dn_id_flags |= DN_ID_CHKED_BONUS;
 		}
 		dn->dn_id_flags &= ~(DN_ID_NEW_EXIST);
+		if (dn->dn_dirty_txg == spa_syncing_txg(os->os_spa))
+			dn->dn_dirty_txg = 0;
 		mutex_exit(&dn->dn_mtx);
 
 		multilist_sublist_remove(list, dn);
diff --git a/zfs/module/zfs/dmu_tx.c b/zfs/module/zfs/dmu_tx.c
index b1508ff..135743e 100644
--- a/zfs/module/zfs/dmu_tx.c
+++ b/zfs/module/zfs/dmu_tx.c
@@ -132,8 +132,8 @@ dmu_tx_hold_dnode_impl(dmu_tx_t *tx, dnode_t *dn, enum dmu_tx_hold_type type,
 	txh = kmem_zalloc(sizeof (dmu_tx_hold_t), KM_SLEEP);
 	txh->txh_tx = tx;
 	txh->txh_dnode = dn;
-	refcount_create(&txh->txh_space_towrite);
-	refcount_create(&txh->txh_memory_tohold);
+	zfs_refcount_create(&txh->txh_space_towrite);
+	zfs_refcount_create(&txh->txh_memory_tohold);
 	txh->txh_type = type;
 	txh->txh_arg1 = arg1;
 	txh->txh_arg2 = arg2;
@@ -228,9 +228,9 @@ dmu_tx_count_write(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
 	if (len == 0)
 		return;
 
-	(void) refcount_add_many(&txh->txh_space_towrite, len, FTAG);
+	(void) zfs_refcount_add_many(&txh->txh_space_towrite, len, FTAG);
 
-	if (refcount_count(&txh->txh_space_towrite) > 2 * DMU_MAX_ACCESS)
+	if (zfs_refcount_count(&txh->txh_space_towrite) > 2 * DMU_MAX_ACCESS)
 		err = SET_ERROR(EFBIG);
 
 	if (dn == NULL)
@@ -295,7 +295,8 @@ dmu_tx_count_write(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
 static void
 dmu_tx_count_dnode(dmu_tx_hold_t *txh)
 {
-	(void) refcount_add_many(&txh->txh_space_towrite, DNODE_MIN_SIZE, FTAG);
+	(void) zfs_refcount_add_many(&txh->txh_space_towrite, DNODE_MIN_SIZE,
+	    FTAG);
 }
 
 void
@@ -418,7 +419,7 @@ dmu_tx_hold_free_impl(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
 				return;
 			}
 
-			(void) refcount_add_many(&txh->txh_memory_tohold,
+			(void) zfs_refcount_add_many(&txh->txh_memory_tohold,
 			    1 << dn->dn_indblkshift, FTAG);
 
 			err = dmu_tx_check_ioerr(zio, dn, 1, i);
@@ -477,7 +478,7 @@ dmu_tx_hold_zap_impl(dmu_tx_hold_t *txh, const char *name)
 	 *    - 2 blocks for possibly split leaves,
 	 *    - 2 grown ptrtbl blocks
 	 */
-	(void) refcount_add_many(&txh->txh_space_towrite,
+	(void) zfs_refcount_add_many(&txh->txh_space_towrite,
 	    MZAP_MAX_BLKSZ, FTAG);
 
 	if (dn == NULL)
@@ -568,7 +569,8 @@ dmu_tx_hold_space(dmu_tx_t *tx, uint64_t space)
 	txh = dmu_tx_hold_object_impl(tx, tx->tx_objset,
 	    DMU_NEW_OBJECT, THT_SPACE, space, 0);
 	if (txh)
-		(void) refcount_add_many(&txh->txh_space_towrite, space, FTAG);
+		(void) zfs_refcount_add_many(&txh->txh_space_towrite, space,
+		    FTAG);
 }
 
 #ifdef ZFS_DEBUG
@@ -919,8 +921,8 @@ dmu_tx_try_assign(dmu_tx_t *tx, uint64_t txg_how)
 			(void) zfs_refcount_add(&dn->dn_tx_holds, tx);
 			mutex_exit(&dn->dn_mtx);
 		}
-		towrite += refcount_count(&txh->txh_space_towrite);
-		tohold += refcount_count(&txh->txh_memory_tohold);
+		towrite += zfs_refcount_count(&txh->txh_space_towrite);
+		tohold += zfs_refcount_count(&txh->txh_memory_tohold);
 	}
 
 	/* needed allocation: worst-case estimate of write space */
@@ -962,7 +964,7 @@ dmu_tx_unassign(dmu_tx_t *tx)
 		mutex_enter(&dn->dn_mtx);
 		ASSERT3U(dn->dn_assigned_txg, ==, tx->tx_txg);
 
-		if (refcount_remove(&dn->dn_tx_holds, tx) == 0) {
+		if (zfs_refcount_remove(&dn->dn_tx_holds, tx) == 0) {
 			dn->dn_assigned_txg = 0;
 			cv_broadcast(&dn->dn_notxholds);
 		}
@@ -1100,10 +1102,10 @@ dmu_tx_destroy(dmu_tx_t *tx)
 		dnode_t *dn = txh->txh_dnode;
 
 		list_remove(&tx->tx_holds, txh);
-		refcount_destroy_many(&txh->txh_space_towrite,
-		    refcount_count(&txh->txh_space_towrite));
-		refcount_destroy_many(&txh->txh_memory_tohold,
-		    refcount_count(&txh->txh_memory_tohold));
+		zfs_refcount_destroy_many(&txh->txh_space_towrite,
+		    zfs_refcount_count(&txh->txh_space_towrite));
+		zfs_refcount_destroy_many(&txh->txh_memory_tohold,
+		    zfs_refcount_count(&txh->txh_memory_tohold));
 		kmem_free(txh, sizeof (dmu_tx_hold_t));
 		if (dn != NULL)
 			dnode_rele(dn, tx);
@@ -1135,7 +1137,7 @@ dmu_tx_commit(dmu_tx_t *tx)
 		mutex_enter(&dn->dn_mtx);
 		ASSERT3U(dn->dn_assigned_txg, ==, tx->tx_txg);
 
-		if (refcount_remove(&dn->dn_tx_holds, tx) == 0) {
+		if (zfs_refcount_remove(&dn->dn_tx_holds, tx) == 0) {
 			dn->dn_assigned_txg = 0;
 			cv_broadcast(&dn->dn_notxholds);
 		}
@@ -1250,7 +1252,7 @@ dmu_tx_hold_spill(dmu_tx_t *tx, uint64_t object)
 	txh = dmu_tx_hold_object_impl(tx, tx->tx_objset, object,
 	    THT_SPILL, 0, 0);
 	if (txh != NULL)
-		(void) refcount_add_many(&txh->txh_space_towrite,
+		(void) zfs_refcount_add_many(&txh->txh_space_towrite,
 		    SPA_OLD_MAXBLOCKSIZE, FTAG);
 }
 
diff --git a/zfs/module/zfs/dnode.c b/zfs/module/zfs/dnode.c
index 1360ea1..989a8ec 100644
--- a/zfs/module/zfs/dnode.c
+++ b/zfs/module/zfs/dnode.c
@@ -124,8 +124,8 @@ dnode_cons(void *arg, void *unused, int kmflag)
 	 * Every dbuf has a reference, and dropping a tracked reference is
 	 * O(number of references), so don't track dn_holds.
 	 */
-	refcount_create_untracked(&dn->dn_holds);
-	refcount_create(&dn->dn_tx_holds);
+	zfs_refcount_create_untracked(&dn->dn_holds);
+	zfs_refcount_create(&dn->dn_tx_holds);
 	list_link_init(&dn->dn_link);
 
 	bzero(&dn->dn_next_nblkptr[0], sizeof (dn->dn_next_nblkptr));
@@ -137,7 +137,7 @@ dnode_cons(void *arg, void *unused, int kmflag)
 	bzero(&dn->dn_next_blksz[0], sizeof (dn->dn_next_blksz));
 
 	for (i = 0; i < TXG_SIZE; i++) {
-		list_link_init(&dn->dn_dirty_link[i]);
+		multilist_link_init(&dn->dn_dirty_link[i]);
 		dn->dn_free_ranges[i] = NULL;
 		list_create(&dn->dn_dirty_records[i],
 		    sizeof (dbuf_dirty_record_t),
@@ -147,6 +147,7 @@ dnode_cons(void *arg, void *unused, int kmflag)
 	dn->dn_allocated_txg = 0;
 	dn->dn_free_txg = 0;
 	dn->dn_assigned_txg = 0;
+	dn->dn_dirty_txg = 0;
 	dn->dn_dirtyctx = 0;
 	dn->dn_dirtyctx_firstset = NULL;
 	dn->dn_bonus = NULL;
@@ -179,12 +180,12 @@ dnode_dest(void *arg, void *unused)
 	mutex_destroy(&dn->dn_mtx);
 	mutex_destroy(&dn->dn_dbufs_mtx);
 	cv_destroy(&dn->dn_notxholds);
-	refcount_destroy(&dn->dn_holds);
-	refcount_destroy(&dn->dn_tx_holds);
+	zfs_refcount_destroy(&dn->dn_holds);
+	zfs_refcount_destroy(&dn->dn_tx_holds);
 	ASSERT(!list_link_active(&dn->dn_link));
 
 	for (i = 0; i < TXG_SIZE; i++) {
-		ASSERT(!list_link_active(&dn->dn_dirty_link[i]));
+		ASSERT(!multilist_link_active(&dn->dn_dirty_link[i]));
 		ASSERT3P(dn->dn_free_ranges[i], ==, NULL);
 		list_destroy(&dn->dn_dirty_records[i]);
 		ASSERT0(dn->dn_next_nblkptr[i]);
@@ -199,6 +200,7 @@ dnode_dest(void *arg, void *unused)
 	ASSERT0(dn->dn_allocated_txg);
 	ASSERT0(dn->dn_free_txg);
 	ASSERT0(dn->dn_assigned_txg);
+	ASSERT0(dn->dn_dirty_txg);
 	ASSERT0(dn->dn_dirtyctx);
 	ASSERT3P(dn->dn_dirtyctx_firstset, ==, NULL);
 	ASSERT3P(dn->dn_bonus, ==, NULL);
@@ -375,7 +377,7 @@ dnode_buf_byteswap(void *vbuf, size_t size)
 void
 dnode_setbonuslen(dnode_t *dn, int newsize, dmu_tx_t *tx)
 {
-	ASSERT3U(refcount_count(&dn->dn_holds), >=, 1);
+	ASSERT3U(zfs_refcount_count(&dn->dn_holds), >=, 1);
 
 	dnode_setdirty(dn, tx);
 	rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
@@ -392,7 +394,7 @@ dnode_setbonuslen(dnode_t *dn, int newsize, dmu_tx_t *tx)
 void
 dnode_setbonus_type(dnode_t *dn, dmu_object_type_t newtype, dmu_tx_t *tx)
 {
-	ASSERT3U(refcount_count(&dn->dn_holds), >=, 1);
+	ASSERT3U(zfs_refcount_count(&dn->dn_holds), >=, 1);
 	dnode_setdirty(dn, tx);
 	rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
 	dn->dn_bonustype = newtype;
@@ -403,7 +405,7 @@ dnode_setbonus_type(dnode_t *dn, dmu_object_type_t newtype, dmu_tx_t *tx)
 void
 dnode_rm_spill(dnode_t *dn, dmu_tx_t *tx)
 {
-	ASSERT3U(refcount_count(&dn->dn_holds), >=, 1);
+	ASSERT3U(zfs_refcount_count(&dn->dn_holds), >=, 1);
 	ASSERT(RW_WRITE_HELD(&dn->dn_struct_rwlock));
 	dnode_setdirty(dn, tx);
 	dn->dn_rm_spillblk[tx->tx_txg&TXG_MASK] = DN_KILL_SPILLBLK;
@@ -523,6 +525,7 @@ dnode_destroy(dnode_t *dn)
 	dn->dn_allocated_txg = 0;
 	dn->dn_free_txg = 0;
 	dn->dn_assigned_txg = 0;
+	dn->dn_dirty_txg = 0;
 
 	dn->dn_dirtyctx = 0;
 	if (dn->dn_dirtyctx_firstset != NULL) {
@@ -592,8 +595,9 @@ dnode_allocate(dnode_t *dn, dmu_object_type_t ot, int blocksize, int ibs,
 	ASSERT0(dn->dn_maxblkid);
 	ASSERT0(dn->dn_allocated_txg);
 	ASSERT0(dn->dn_assigned_txg);
-	ASSERT(refcount_is_zero(&dn->dn_tx_holds));
-	ASSERT3U(refcount_count(&dn->dn_holds), <=, 1);
+	ASSERT0(dn->dn_dirty_txg);
+	ASSERT(zfs_refcount_is_zero(&dn->dn_tx_holds));
+	ASSERT3U(zfs_refcount_count(&dn->dn_holds), <=, 1);
 	ASSERT(avl_is_empty(&dn->dn_dbufs));
 
 	for (i = 0; i < TXG_SIZE; i++) {
@@ -604,7 +608,7 @@ dnode_allocate(dnode_t *dn, dmu_object_type_t ot, int blocksize, int ibs,
 		ASSERT0(dn->dn_next_bonustype[i]);
 		ASSERT0(dn->dn_rm_spillblk[i]);
 		ASSERT0(dn->dn_next_blksz[i]);
-		ASSERT(!list_link_active(&dn->dn_dirty_link[i]));
+		ASSERT(!multilist_link_active(&dn->dn_dirty_link[i]));
 		ASSERT3P(list_head(&dn->dn_dirty_records[i]), ==, NULL);
 		ASSERT3P(dn->dn_free_ranges[i], ==, NULL);
 	}
@@ -779,10 +783,11 @@ dnode_move_impl(dnode_t *odn, dnode_t *ndn)
 	ndn->dn_allocated_txg = odn->dn_allocated_txg;
 	ndn->dn_free_txg = odn->dn_free_txg;
 	ndn->dn_assigned_txg = odn->dn_assigned_txg;
+	ndn->dn_dirty_txg = odn->dn_dirty_txg;
 	ndn->dn_dirtyctx = odn->dn_dirtyctx;
 	ndn->dn_dirtyctx_firstset = odn->dn_dirtyctx_firstset;
-	ASSERT(refcount_count(&odn->dn_tx_holds) == 0);
-	refcount_transfer(&ndn->dn_holds, &odn->dn_holds);
+	ASSERT(zfs_refcount_count(&odn->dn_tx_holds) == 0);
+	zfs_refcount_transfer(&ndn->dn_holds, &odn->dn_holds);
 	ASSERT(avl_is_empty(&ndn->dn_dbufs));
 	avl_swap(&ndn->dn_dbufs, &odn->dn_dbufs);
 	ndn->dn_dbufs_count = odn->dn_dbufs_count;
@@ -845,6 +850,7 @@ dnode_move_impl(dnode_t *odn, dnode_t *ndn)
 	odn->dn_allocated_txg = 0;
 	odn->dn_free_txg = 0;
 	odn->dn_assigned_txg = 0;
+	odn->dn_dirty_txg = 0;
 	odn->dn_dirtyctx = 0;
 	odn->dn_dirtyctx_firstset = NULL;
 	odn->dn_have_spill = B_FALSE;
@@ -969,7 +975,7 @@ dnode_move(void *buf, void *newbuf, size_t size, void *arg)
 	 * hold before the dbuf is removed, the hold is discounted, and the
 	 * removal is blocked until the move completes.
 	 */
-	refcount = refcount_count(&odn->dn_holds);
+	refcount = zfs_refcount_count(&odn->dn_holds);
 	ASSERT(refcount >= 0);
 	dbufs = odn->dn_dbufs_count;
 
@@ -997,7 +1003,7 @@ dnode_move(void *buf, void *newbuf, size_t size, void *arg)
 
 	list_link_replace(&odn->dn_link, &ndn->dn_link);
 	/* If the dnode was safe to move, the refcount cannot have changed. */
-	ASSERT(refcount == refcount_count(&ndn->dn_holds));
+	ASSERT(refcount == zfs_refcount_count(&ndn->dn_holds));
 	ASSERT(dbufs == ndn->dn_dbufs_count);
 	zrl_exit(&ndn->dn_handle->dnh_zrlock); /* handle has moved */
 	mutex_exit(&os->os_lock);
@@ -1069,6 +1075,10 @@ dnode_check_slots_free(dnode_children_t *children, int idx, int slots)
 {
 	ASSERT3S(idx + slots, <=, DNODES_PER_BLOCK);
 
+	/*
+	 * If all dnode slots are either already free or
+	 * evictable return B_TRUE.
+	 */
 	for (int i = idx; i < idx + slots; i++) {
 		dnode_handle_t *dnh = &children->dnc_children[i];
 		dnode_t *dn = dnh->dnh_dnode;
@@ -1077,18 +1087,17 @@ dnode_check_slots_free(dnode_children_t *children, int idx, int slots)
 			continue;
 		} else if (DN_SLOT_IS_PTR(dn)) {
 			mutex_enter(&dn->dn_mtx);
-			dmu_object_type_t type = dn->dn_type;
+			boolean_t can_free = (dn->dn_type == DMU_OT_NONE &&
+			    !DNODE_IS_DIRTY(dn));
 			mutex_exit(&dn->dn_mtx);
 
-			if (type != DMU_OT_NONE)
+			if (!can_free)
 				return (B_FALSE);
-
-			continue;
+			else
+				continue;
 		} else {
 			return (B_FALSE);
 		}
-
-		return (B_FALSE);
 	}
 
 	return (B_TRUE);
@@ -1143,7 +1152,7 @@ dnode_special_close(dnode_handle_t *dnh)
 	 * has a hold on this dnode while we are trying to evict this
 	 * dnode.
 	 */
-	while (refcount_count(&dn->dn_holds) > 0)
+	while (zfs_refcount_count(&dn->dn_holds) > 0)
 		delay(1);
 	ASSERT(dn->dn_dbuf == NULL ||
 	    dmu_buf_get_user(&dn->dn_dbuf->db) == NULL);
@@ -1198,8 +1207,8 @@ dnode_buf_evict_async(void *dbu)
 		 * it wouldn't be eligible for eviction and this function
 		 * would not have been called.
 		 */
-		ASSERT(refcount_is_zero(&dn->dn_holds));
-		ASSERT(refcount_is_zero(&dn->dn_tx_holds));
+		ASSERT(zfs_refcount_is_zero(&dn->dn_holds));
+		ASSERT(zfs_refcount_is_zero(&dn->dn_tx_holds));
 
 		dnode_destroy(dn); /* implicit zrl_remove() for first slot */
 		zrl_destroy(&dnh->dnh_zrlock);
@@ -1451,7 +1460,7 @@ dnode_hold_impl(objset_t *os, uint64_t object, int flag, int slots,
 		}
 
 		mutex_enter(&dn->dn_mtx);
-		if (!refcount_is_zero(&dn->dn_holds)) {
+		if (!zfs_refcount_is_zero(&dn->dn_holds)) {
 			DNODE_STAT_BUMP(dnode_hold_free_refcount);
 			mutex_exit(&dn->dn_mtx);
 			dnode_slots_rele(dnc, idx, slots);
@@ -1511,7 +1520,7 @@ boolean_t
 dnode_add_ref(dnode_t *dn, void *tag)
 {
 	mutex_enter(&dn->dn_mtx);
-	if (refcount_is_zero(&dn->dn_holds)) {
+	if (zfs_refcount_is_zero(&dn->dn_holds)) {
 		mutex_exit(&dn->dn_mtx);
 		return (FALSE);
 	}
@@ -1535,7 +1544,7 @@ dnode_rele_and_unlock(dnode_t *dn, void *tag)
 	dmu_buf_impl_t *db = dn->dn_dbuf;
 	dnode_handle_t *dnh = dn->dn_handle;
 
-	refs = refcount_remove(&dn->dn_holds, tag);
+	refs = zfs_refcount_remove(&dn->dn_holds, tag);
 	mutex_exit(&dn->dn_mtx);
 
 	/*
@@ -1594,12 +1603,12 @@ dnode_setdirty(dnode_t *dn, dmu_tx_t *tx)
 	/*
 	 * If we are already marked dirty, we're done.
 	 */
-	if (list_link_active(&dn->dn_dirty_link[txg & TXG_MASK])) {
+	if (multilist_link_active(&dn->dn_dirty_link[txg & TXG_MASK])) {
 		multilist_sublist_unlock(mls);
 		return;
 	}
 
-	ASSERT(!refcount_is_zero(&dn->dn_holds) ||
+	ASSERT(!zfs_refcount_is_zero(&dn->dn_holds) ||
 	    !avl_is_empty(&dn->dn_dbufs));
 	ASSERT(dn->dn_datablksz != 0);
 	ASSERT0(dn->dn_next_bonuslen[txg&TXG_MASK]);
diff --git a/zfs/module/zfs/dnode_sync.c b/zfs/module/zfs/dnode_sync.c
index 8d65e38..2febb52 100644
--- a/zfs/module/zfs/dnode_sync.c
+++ b/zfs/module/zfs/dnode_sync.c
@@ -422,7 +422,7 @@ dnode_evict_dbufs(dnode_t *dn)
 
 		mutex_enter(&db->db_mtx);
 		if (db->db_state != DB_EVICTING &&
-		    refcount_is_zero(&db->db_holds)) {
+		    zfs_refcount_is_zero(&db->db_holds)) {
 			db_marker->db_level = db->db_level;
 			db_marker->db_blkid = db->db_blkid;
 			db_marker->db_state = DB_SEARCH;
@@ -451,7 +451,7 @@ dnode_evict_bonus(dnode_t *dn)
 {
 	rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
 	if (dn->dn_bonus != NULL) {
-		if (refcount_is_zero(&dn->dn_bonus->db_holds)) {
+		if (zfs_refcount_is_zero(&dn->dn_bonus->db_holds)) {
 			mutex_enter(&dn->dn_bonus->db_mtx);
 			dbuf_destroy(dn->dn_bonus);
 			dn->dn_bonus = NULL;
@@ -517,7 +517,7 @@ dnode_sync_free(dnode_t *dn, dmu_tx_t *tx)
 	 * zfs_obj_to_path() also depends on this being
 	 * commented out.
 	 *
-	 * ASSERT3U(refcount_count(&dn->dn_holds), ==, 1);
+	 * ASSERT3U(zfs_refcount_count(&dn->dn_holds), ==, 1);
 	 */
 
 	/* Undirty next bits */
diff --git a/zfs/module/zfs/dsl_dataset.c b/zfs/module/zfs/dsl_dataset.c
index b7562bc..2e79c48 100644
--- a/zfs/module/zfs/dsl_dataset.c
+++ b/zfs/module/zfs/dsl_dataset.c
@@ -287,7 +287,7 @@ dsl_dataset_evict_async(void *dbu)
 	mutex_destroy(&ds->ds_lock);
 	mutex_destroy(&ds->ds_opening_lock);
 	mutex_destroy(&ds->ds_sendstream_lock);
-	refcount_destroy(&ds->ds_longholds);
+	zfs_refcount_destroy(&ds->ds_longholds);
 	rrw_destroy(&ds->ds_bp_rwlock);
 
 	kmem_free(ds, sizeof (dsl_dataset_t));
@@ -422,7 +422,7 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
 		mutex_init(&ds->ds_opening_lock, NULL, MUTEX_DEFAULT, NULL);
 		mutex_init(&ds->ds_sendstream_lock, NULL, MUTEX_DEFAULT, NULL);
 		rrw_init(&ds->ds_bp_rwlock, B_FALSE);
-		refcount_create(&ds->ds_longholds);
+		zfs_refcount_create(&ds->ds_longholds);
 
 		bplist_create(&ds->ds_pending_deadlist);
 		dsl_deadlist_open(&ds->ds_deadlist,
@@ -458,7 +458,7 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
 			mutex_destroy(&ds->ds_lock);
 			mutex_destroy(&ds->ds_opening_lock);
 			mutex_destroy(&ds->ds_sendstream_lock);
-			refcount_destroy(&ds->ds_longholds);
+			zfs_refcount_destroy(&ds->ds_longholds);
 			bplist_destroy(&ds->ds_pending_deadlist);
 			dsl_deadlist_close(&ds->ds_deadlist);
 			kmem_free(ds, sizeof (dsl_dataset_t));
@@ -520,7 +520,7 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
 			mutex_destroy(&ds->ds_lock);
 			mutex_destroy(&ds->ds_opening_lock);
 			mutex_destroy(&ds->ds_sendstream_lock);
-			refcount_destroy(&ds->ds_longholds);
+			zfs_refcount_destroy(&ds->ds_longholds);
 			kmem_free(ds, sizeof (dsl_dataset_t));
 			if (err != 0) {
 				dmu_buf_rele(dbuf, tag);
@@ -651,14 +651,14 @@ dsl_dataset_long_hold(dsl_dataset_t *ds, void *tag)
 void
 dsl_dataset_long_rele(dsl_dataset_t *ds, void *tag)
 {
-	(void) refcount_remove(&ds->ds_longholds, tag);
+	(void) zfs_refcount_remove(&ds->ds_longholds, tag);
 }
 
 /* Return B_TRUE if there are any long holds on this dataset. */
 boolean_t
 dsl_dataset_long_held(dsl_dataset_t *ds)
 {
-	return (!refcount_is_zero(&ds->ds_longholds));
+	return (!zfs_refcount_is_zero(&ds->ds_longholds));
 }
 
 void
diff --git a/zfs/module/zfs/dsl_destroy.c b/zfs/module/zfs/dsl_destroy.c
index d980f7d..946eb1d 100644
--- a/zfs/module/zfs/dsl_destroy.c
+++ b/zfs/module/zfs/dsl_destroy.c
@@ -258,7 +258,7 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx)
 	rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
 	ASSERT3U(dsl_dataset_phys(ds)->ds_bp.blk_birth, <=, tx->tx_txg);
 	rrw_exit(&ds->ds_bp_rwlock, FTAG);
-	ASSERT(refcount_is_zero(&ds->ds_longholds));
+	ASSERT(zfs_refcount_is_zero(&ds->ds_longholds));
 
 	if (defer &&
 	    (ds->ds_userrefs > 0 ||
@@ -619,7 +619,7 @@ dsl_destroy_head_check_impl(dsl_dataset_t *ds, int expected_holds)
 	if (ds->ds_is_snapshot)
 		return (SET_ERROR(EINVAL));
 
-	if (refcount_count(&ds->ds_longholds) != expected_holds)
+	if (zfs_refcount_count(&ds->ds_longholds) != expected_holds)
 		return (SET_ERROR(EBUSY));
 
 	mos = ds->ds_dir->dd_pool->dp_meta_objset;
@@ -647,7 +647,7 @@ dsl_destroy_head_check_impl(dsl_dataset_t *ds, int expected_holds)
 	    dsl_dataset_phys(ds->ds_prev)->ds_num_children == 2 &&
 	    ds->ds_prev->ds_userrefs == 0) {
 		/* We need to remove the origin snapshot as well. */
-		if (!refcount_is_zero(&ds->ds_prev->ds_longholds))
+		if (!zfs_refcount_is_zero(&ds->ds_prev->ds_longholds))
 			return (SET_ERROR(EBUSY));
 	}
 	return (0);
diff --git a/zfs/module/zfs/metaslab.c b/zfs/module/zfs/metaslab.c
index 40658d5..2a5581c 100644
--- a/zfs/module/zfs/metaslab.c
+++ b/zfs/module/zfs/metaslab.c
@@ -223,7 +223,7 @@ metaslab_class_create(spa_t *spa, metaslab_ops_t *ops)
 	mc->mc_rotor = NULL;
 	mc->mc_ops = ops;
 	mutex_init(&mc->mc_lock, NULL, MUTEX_DEFAULT, NULL);
-	refcount_create_tracked(&mc->mc_alloc_slots);
+	zfs_refcount_create_tracked(&mc->mc_alloc_slots);
 
 	return (mc);
 }
@@ -237,7 +237,7 @@ metaslab_class_destroy(metaslab_class_t *mc)
 	ASSERT(mc->mc_space == 0);
 	ASSERT(mc->mc_dspace == 0);
 
-	refcount_destroy(&mc->mc_alloc_slots);
+	zfs_refcount_destroy(&mc->mc_alloc_slots);
 	mutex_destroy(&mc->mc_lock);
 	kmem_free(mc, sizeof (metaslab_class_t));
 }
@@ -585,7 +585,7 @@ metaslab_group_create(metaslab_class_t *mc, vdev_t *vd)
 	mg->mg_activation_count = 0;
 	mg->mg_initialized = B_FALSE;
 	mg->mg_no_free_space = B_TRUE;
-	refcount_create_tracked(&mg->mg_alloc_queue_depth);
+	zfs_refcount_create_tracked(&mg->mg_alloc_queue_depth);
 
 	mg->mg_taskq = taskq_create("metaslab_group_taskq", metaslab_load_pct,
 	    maxclsyspri, 10, INT_MAX, TASKQ_THREADS_CPU_PCT | TASKQ_DYNAMIC);
@@ -608,7 +608,7 @@ metaslab_group_destroy(metaslab_group_t *mg)
 	taskq_destroy(mg->mg_taskq);
 	avl_destroy(&mg->mg_metaslab_tree);
 	mutex_destroy(&mg->mg_lock);
-	refcount_destroy(&mg->mg_alloc_queue_depth);
+	zfs_refcount_destroy(&mg->mg_alloc_queue_depth);
 	kmem_free(mg, sizeof (metaslab_group_t));
 }
 
@@ -907,7 +907,7 @@ metaslab_group_allocatable(metaslab_group_t *mg, metaslab_group_t *rotor,
 		if (mg->mg_no_free_space)
 			return (B_FALSE);
 
-		qdepth = refcount_count(&mg->mg_alloc_queue_depth);
+		qdepth = zfs_refcount_count(&mg->mg_alloc_queue_depth);
 
 		/*
 		 * If this metaslab group is below its qmax or it's
@@ -928,7 +928,7 @@ metaslab_group_allocatable(metaslab_group_t *mg, metaslab_group_t *rotor,
 		for (mgp = mg->mg_next; mgp != rotor; mgp = mgp->mg_next) {
 			qmax = mgp->mg_max_alloc_queue_depth;
 
-			qdepth = refcount_count(&mgp->mg_alloc_queue_depth);
+			qdepth = zfs_refcount_count(&mgp->mg_alloc_queue_depth);
 
 			/*
 			 * If there is another metaslab group that
@@ -2679,7 +2679,7 @@ metaslab_group_alloc_decrement(spa_t *spa, uint64_t vdev, void *tag, int flags)
 	if (!mg->mg_class->mc_alloc_throttle_enabled)
 		return;
 
-	(void) refcount_remove(&mg->mg_alloc_queue_depth, tag);
+	(void) zfs_refcount_remove(&mg->mg_alloc_queue_depth, tag);
 }
 
 void
@@ -2693,7 +2693,7 @@ metaslab_group_alloc_verify(spa_t *spa, const blkptr_t *bp, void *tag)
 	for (d = 0; d < ndvas; d++) {
 		uint64_t vdev = DVA_GET_VDEV(&dva[d]);
 		metaslab_group_t *mg = vdev_lookup_top(spa, vdev)->vdev_mg;
-		VERIFY(refcount_not_held(&mg->mg_alloc_queue_depth, tag));
+		VERIFY(zfs_refcount_not_held(&mg->mg_alloc_queue_depth, tag));
 	}
 #endif
 }
@@ -3348,7 +3348,7 @@ metaslab_class_throttle_reserve(metaslab_class_t *mc, int slots, zio_t *zio,
 	ASSERT(mc->mc_alloc_throttle_enabled);
 	mutex_enter(&mc->mc_lock);
 
-	reserved_slots = refcount_count(&mc->mc_alloc_slots);
+	reserved_slots = zfs_refcount_count(&mc->mc_alloc_slots);
 	if (reserved_slots < mc->mc_alloc_max_slots)
 		available_slots = mc->mc_alloc_max_slots - reserved_slots;
 
@@ -3360,7 +3360,8 @@ metaslab_class_throttle_reserve(metaslab_class_t *mc, int slots, zio_t *zio,
 		 * them individually when an I/O completes.
 		 */
 		for (d = 0; d < slots; d++) {
-			reserved_slots = zfs_refcount_add(&mc->mc_alloc_slots, zio);
+			reserved_slots = zfs_refcount_add(&mc->mc_alloc_slots,
+			    zio);
 		}
 		zio->io_flags |= ZIO_FLAG_IO_ALLOCATING;
 		slot_reserved = B_TRUE;
@@ -3378,7 +3379,7 @@ metaslab_class_throttle_unreserve(metaslab_class_t *mc, int slots, zio_t *zio)
 	ASSERT(mc->mc_alloc_throttle_enabled);
 	mutex_enter(&mc->mc_lock);
 	for (d = 0; d < slots; d++) {
-		(void) refcount_remove(&mc->mc_alloc_slots, zio);
+		(void) zfs_refcount_remove(&mc->mc_alloc_slots, zio);
 	}
 	mutex_exit(&mc->mc_lock);
 }
diff --git a/zfs/module/zfs/refcount.c b/zfs/module/zfs/refcount.c
index 13f9bb6..0a93aaf 100644
--- a/zfs/module/zfs/refcount.c
+++ b/zfs/module/zfs/refcount.c
@@ -38,7 +38,7 @@ static kmem_cache_t *reference_cache;
 static kmem_cache_t *reference_history_cache;
 
 void
-refcount_init(void)
+zfs_refcount_init(void)
 {
 	reference_cache = kmem_cache_create("reference_cache",
 	    sizeof (reference_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
@@ -48,14 +48,14 @@ refcount_init(void)
 }
 
 void
-refcount_fini(void)
+zfs_refcount_fini(void)
 {
 	kmem_cache_destroy(reference_cache);
 	kmem_cache_destroy(reference_history_cache);
 }
 
 void
-refcount_create(zfs_refcount_t *rc)
+zfs_refcount_create(zfs_refcount_t *rc)
 {
 	mutex_init(&rc->rc_mtx, NULL, MUTEX_DEFAULT, NULL);
 	list_create(&rc->rc_list, sizeof (reference_t),
@@ -68,21 +68,21 @@ refcount_create(zfs_refcount_t *rc)
 }
 
 void
-refcount_create_tracked(zfs_refcount_t *rc)
+zfs_refcount_create_tracked(zfs_refcount_t *rc)
 {
-	refcount_create(rc);
+	zfs_refcount_create(rc);
 	rc->rc_tracked = B_TRUE;
 }
 
 void
-refcount_create_untracked(zfs_refcount_t *rc)
+zfs_refcount_create_untracked(zfs_refcount_t *rc)
 {
-	refcount_create(rc);
+	zfs_refcount_create(rc);
 	rc->rc_tracked = B_FALSE;
 }
 
 void
-refcount_destroy_many(zfs_refcount_t *rc, uint64_t number)
+zfs_refcount_destroy_many(zfs_refcount_t *rc, uint64_t number)
 {
 	reference_t *ref;
 
@@ -103,25 +103,25 @@ refcount_destroy_many(zfs_refcount_t *rc, uint64_t number)
 }
 
 void
-refcount_destroy(zfs_refcount_t *rc)
+zfs_refcount_destroy(zfs_refcount_t *rc)
 {
-	refcount_destroy_many(rc, 0);
+	zfs_refcount_destroy_many(rc, 0);
 }
 
 int
-refcount_is_zero(zfs_refcount_t *rc)
+zfs_refcount_is_zero(zfs_refcount_t *rc)
 {
 	return (rc->rc_count == 0);
 }
 
 int64_t
-refcount_count(zfs_refcount_t *rc)
+zfs_refcount_count(zfs_refcount_t *rc)
 {
 	return (rc->rc_count);
 }
 
 int64_t
-refcount_add_many(zfs_refcount_t *rc, uint64_t number, void *holder)
+zfs_refcount_add_many(zfs_refcount_t *rc, uint64_t number, void *holder)
 {
 	reference_t *ref = NULL;
 	int64_t count;
@@ -145,11 +145,11 @@ refcount_add_many(zfs_refcount_t *rc, uint64_t number, void *holder)
 int64_t
 zfs_refcount_add(zfs_refcount_t *rc, void *holder)
 {
-	return (refcount_add_many(rc, 1, holder));
+	return (zfs_refcount_add_many(rc, 1, holder));
 }
 
 int64_t
-refcount_remove_many(zfs_refcount_t *rc, uint64_t number, void *holder)
+zfs_refcount_remove_many(zfs_refcount_t *rc, uint64_t number, void *holder)
 {
 	reference_t *ref;
 	int64_t count;
@@ -197,13 +197,13 @@ refcount_remove_many(zfs_refcount_t *rc, uint64_t number, void *holder)
 }
 
 int64_t
-refcount_remove(zfs_refcount_t *rc, void *holder)
+zfs_refcount_remove(zfs_refcount_t *rc, void *holder)
 {
-	return (refcount_remove_many(rc, 1, holder));
+	return (zfs_refcount_remove_many(rc, 1, holder));
 }
 
 void
-refcount_transfer(zfs_refcount_t *dst, zfs_refcount_t *src)
+zfs_refcount_transfer(zfs_refcount_t *dst, zfs_refcount_t *src)
 {
 	int64_t count, removed_count;
 	list_t list, removed;
@@ -234,7 +234,7 @@ refcount_transfer(zfs_refcount_t *dst, zfs_refcount_t *src)
 }
 
 void
-refcount_transfer_ownership(zfs_refcount_t *rc, void *current_holder,
+zfs_refcount_transfer_ownership(zfs_refcount_t *rc, void *current_holder,
     void *new_holder)
 {
 	reference_t *ref;
@@ -264,7 +264,7 @@ refcount_transfer_ownership(zfs_refcount_t *rc, void *current_holder,
  * might be held.
  */
 boolean_t
-refcount_held(zfs_refcount_t *rc, void *holder)
+zfs_refcount_held(zfs_refcount_t *rc, void *holder)
 {
 	reference_t *ref;
 
@@ -292,7 +292,7 @@ refcount_held(zfs_refcount_t *rc, void *holder)
  * since the reference might not be held.
  */
 boolean_t
-refcount_not_held(zfs_refcount_t *rc, void *holder)
+zfs_refcount_not_held(zfs_refcount_t *rc, void *holder)
 {
 	reference_t *ref;
 
diff --git a/zfs/module/zfs/rrwlock.c b/zfs/module/zfs/rrwlock.c
index effff33..582b40a 100644
--- a/zfs/module/zfs/rrwlock.c
+++ b/zfs/module/zfs/rrwlock.c
@@ -85,7 +85,7 @@ rrn_find(rrwlock_t *rrl)
 {
 	rrw_node_t *rn;
 
-	if (refcount_count(&rrl->rr_linked_rcount) == 0)
+	if (zfs_refcount_count(&rrl->rr_linked_rcount) == 0)
 		return (NULL);
 
 	for (rn = tsd_get(rrw_tsd_key); rn != NULL; rn = rn->rn_next) {
@@ -120,7 +120,7 @@ rrn_find_and_remove(rrwlock_t *rrl, void *tag)
 	rrw_node_t *rn;
 	rrw_node_t *prev = NULL;
 
-	if (refcount_count(&rrl->rr_linked_rcount) == 0)
+	if (zfs_refcount_count(&rrl->rr_linked_rcount) == 0)
 		return (B_FALSE);
 
 	for (rn = tsd_get(rrw_tsd_key); rn != NULL; rn = rn->rn_next) {
@@ -143,8 +143,8 @@ rrw_init(rrwlock_t *rrl, boolean_t track_all)
 	mutex_init(&rrl->rr_lock, NULL, MUTEX_DEFAULT, NULL);
 	cv_init(&rrl->rr_cv, NULL, CV_DEFAULT, NULL);
 	rrl->rr_writer = NULL;
-	refcount_create(&rrl->rr_anon_rcount);
-	refcount_create(&rrl->rr_linked_rcount);
+	zfs_refcount_create(&rrl->rr_anon_rcount);
+	zfs_refcount_create(&rrl->rr_linked_rcount);
 	rrl->rr_writer_wanted = B_FALSE;
 	rrl->rr_track_all = track_all;
 }
@@ -155,8 +155,8 @@ rrw_destroy(rrwlock_t *rrl)
 	mutex_destroy(&rrl->rr_lock);
 	cv_destroy(&rrl->rr_cv);
 	ASSERT(rrl->rr_writer == NULL);
-	refcount_destroy(&rrl->rr_anon_rcount);
-	refcount_destroy(&rrl->rr_linked_rcount);
+	zfs_refcount_destroy(&rrl->rr_anon_rcount);
+	zfs_refcount_destroy(&rrl->rr_linked_rcount);
 }
 
 static void
@@ -173,10 +173,10 @@ rrw_enter_read_impl(rrwlock_t *rrl, boolean_t prio, void *tag)
 	DTRACE_PROBE(zfs__rrwfastpath__rdmiss);
 #endif
 	ASSERT(rrl->rr_writer != curthread);
-	ASSERT(refcount_count(&rrl->rr_anon_rcount) >= 0);
+	ASSERT(zfs_refcount_count(&rrl->rr_anon_rcount) >= 0);
 
 	while (rrl->rr_writer != NULL || (rrl->rr_writer_wanted &&
-	    refcount_is_zero(&rrl->rr_anon_rcount) && !prio &&
+	    zfs_refcount_is_zero(&rrl->rr_anon_rcount) && !prio &&
 	    rrn_find(rrl) == NULL))
 		cv_wait(&rrl->rr_cv, &rrl->rr_lock);
 
@@ -216,8 +216,8 @@ rrw_enter_write(rrwlock_t *rrl)
 	mutex_enter(&rrl->rr_lock);
 	ASSERT(rrl->rr_writer != curthread);
 
-	while (refcount_count(&rrl->rr_anon_rcount) > 0 ||
-	    refcount_count(&rrl->rr_linked_rcount) > 0 ||
+	while (zfs_refcount_count(&rrl->rr_anon_rcount) > 0 ||
+	    zfs_refcount_count(&rrl->rr_linked_rcount) > 0 ||
 	    rrl->rr_writer != NULL) {
 		rrl->rr_writer_wanted = B_TRUE;
 		cv_wait(&rrl->rr_cv, &rrl->rr_lock);
@@ -250,24 +250,25 @@ rrw_exit(rrwlock_t *rrl, void *tag)
 	}
 	DTRACE_PROBE(zfs__rrwfastpath__exitmiss);
 #endif
-	ASSERT(!refcount_is_zero(&rrl->rr_anon_rcount) ||
-	    !refcount_is_zero(&rrl->rr_linked_rcount) ||
+	ASSERT(!zfs_refcount_is_zero(&rrl->rr_anon_rcount) ||
+	    !zfs_refcount_is_zero(&rrl->rr_linked_rcount) ||
 	    rrl->rr_writer != NULL);
 
 	if (rrl->rr_writer == NULL) {
 		int64_t count;
 		if (rrn_find_and_remove(rrl, tag)) {
-			count = refcount_remove(&rrl->rr_linked_rcount, tag);
+			count = zfs_refcount_remove(
+			    &rrl->rr_linked_rcount, tag);
 		} else {
 			ASSERT(!rrl->rr_track_all);
-			count = refcount_remove(&rrl->rr_anon_rcount, tag);
+			count = zfs_refcount_remove(&rrl->rr_anon_rcount, tag);
 		}
 		if (count == 0)
 			cv_broadcast(&rrl->rr_cv);
 	} else {
 		ASSERT(rrl->rr_writer == curthread);
-		ASSERT(refcount_is_zero(&rrl->rr_anon_rcount) &&
-		    refcount_is_zero(&rrl->rr_linked_rcount));
+		ASSERT(zfs_refcount_is_zero(&rrl->rr_anon_rcount) &&
+		    zfs_refcount_is_zero(&rrl->rr_linked_rcount));
 		rrl->rr_writer = NULL;
 		cv_broadcast(&rrl->rr_cv);
 	}
@@ -288,7 +289,7 @@ rrw_held(rrwlock_t *rrl, krw_t rw)
 	if (rw == RW_WRITER) {
 		held = (rrl->rr_writer == curthread);
 	} else {
-		held = (!refcount_is_zero(&rrl->rr_anon_rcount) ||
+		held = (!zfs_refcount_is_zero(&rrl->rr_anon_rcount) ||
 		    rrn_find(rrl) != NULL);
 	}
 	mutex_exit(&rrl->rr_lock);
diff --git a/zfs/module/zfs/sa.c b/zfs/module/zfs/sa.c
index df4f6fd..08f6165 100644
--- a/zfs/module/zfs/sa.c
+++ b/zfs/module/zfs/sa.c
@@ -1132,7 +1132,7 @@ sa_tear_down(objset_t *os)
 	    avl_destroy_nodes(&sa->sa_layout_hash_tree, &cookie))) {
 		sa_idx_tab_t *tab;
 		while ((tab = list_head(&layout->lot_idx_tab))) {
-			ASSERT(refcount_count(&tab->sa_refcount));
+			ASSERT(zfs_refcount_count(&tab->sa_refcount));
 			sa_idx_tab_rele(os, tab);
 		}
 	}
@@ -1317,13 +1317,13 @@ sa_idx_tab_rele(objset_t *os, void *arg)
 		return;
 
 	mutex_enter(&sa->sa_lock);
-	if (refcount_remove(&idx_tab->sa_refcount, NULL) == 0) {
+	if (zfs_refcount_remove(&idx_tab->sa_refcount, NULL) == 0) {
 		list_remove(&idx_tab->sa_layout->lot_idx_tab, idx_tab);
 		if (idx_tab->sa_variable_lengths)
 			kmem_free(idx_tab->sa_variable_lengths,
 			    sizeof (uint16_t) *
 			    idx_tab->sa_layout->lot_var_sizes);
-		refcount_destroy(&idx_tab->sa_refcount);
+		zfs_refcount_destroy(&idx_tab->sa_refcount);
 		kmem_free(idx_tab->sa_idx_tab,
 		    sizeof (uint32_t) * sa->sa_num_attrs);
 		kmem_free(idx_tab, sizeof (sa_idx_tab_t));
@@ -1560,7 +1560,7 @@ sa_find_idx_tab(objset_t *os, dmu_object_type_t bonustype, sa_hdr_phys_t *hdr)
 	idx_tab->sa_idx_tab =
 	    kmem_zalloc(sizeof (uint32_t) * sa->sa_num_attrs, KM_SLEEP);
 	idx_tab->sa_layout = tb;
-	refcount_create(&idx_tab->sa_refcount);
+	zfs_refcount_create(&idx_tab->sa_refcount);
 	if (tb->lot_var_sizes)
 		idx_tab->sa_variable_lengths = kmem_alloc(sizeof (uint16_t) *
 		    tb->lot_var_sizes, KM_SLEEP);
diff --git a/zfs/module/zfs/spa.c b/zfs/module/zfs/spa.c
index 282f717..23c5c52 100644
--- a/zfs/module/zfs/spa.c
+++ b/zfs/module/zfs/spa.c
@@ -2304,7 +2304,7 @@ spa_load(spa_t *spa, spa_load_state_t state, spa_import_type_t type,
 	 * and are making their way through the eviction process.
 	 */
 	spa_evicting_os_wait(spa);
-	spa->spa_minref = refcount_count(&spa->spa_refcount);
+	spa->spa_minref = zfs_refcount_count(&spa->spa_refcount);
 	if (error) {
 		if (error != EEXIST) {
 			spa->spa_loaded_ts.tv_sec = 0;
@@ -4262,7 +4262,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
 	 * and are making their way through the eviction process.
 	 */
 	spa_evicting_os_wait(spa);
-	spa->spa_minref = refcount_count(&spa->spa_refcount);
+	spa->spa_minref = zfs_refcount_count(&spa->spa_refcount);
 	spa->spa_load_state = SPA_LOAD_NONE;
 
 	mutex_exit(&spa_namespace_lock);
@@ -6854,12 +6854,12 @@ spa_sync(spa_t *spa, uint64_t txg)
 		 * allocations look at mg_max_alloc_queue_depth, and async
 		 * allocations all happen from spa_sync().
 		 */
-		ASSERT0(refcount_count(&mg->mg_alloc_queue_depth));
+		ASSERT0(zfs_refcount_count(&mg->mg_alloc_queue_depth));
 		mg->mg_max_alloc_queue_depth = max_queue_depth;
 		queue_depth_total += mg->mg_max_alloc_queue_depth;
 	}
 	mc = spa_normal_class(spa);
-	ASSERT0(refcount_count(&mc->mc_alloc_slots));
+	ASSERT0(zfs_refcount_count(&mc->mc_alloc_slots));
 	mc->mc_alloc_max_slots = queue_depth_total;
 	mc->mc_alloc_throttle_enabled = zio_dva_throttle_enabled;
 
diff --git a/zfs/module/zfs/spa_misc.c b/zfs/module/zfs/spa_misc.c
index f6c9b40..6514813 100644
--- a/zfs/module/zfs/spa_misc.c
+++ b/zfs/module/zfs/spa_misc.c
@@ -366,7 +366,7 @@ spa_config_lock_init(spa_t *spa)
 		spa_config_lock_t *scl = &spa->spa_config_lock[i];
 		mutex_init(&scl->scl_lock, NULL, MUTEX_DEFAULT, NULL);
 		cv_init(&scl->scl_cv, NULL, CV_DEFAULT, NULL);
-		refcount_create_untracked(&scl->scl_count);
+		zfs_refcount_create_untracked(&scl->scl_count);
 		scl->scl_writer = NULL;
 		scl->scl_write_wanted = 0;
 	}
@@ -381,7 +381,7 @@ spa_config_lock_destroy(spa_t *spa)
 		spa_config_lock_t *scl = &spa->spa_config_lock[i];
 		mutex_destroy(&scl->scl_lock);
 		cv_destroy(&scl->scl_cv);
-		refcount_destroy(&scl->scl_count);
+		zfs_refcount_destroy(&scl->scl_count);
 		ASSERT(scl->scl_writer == NULL);
 		ASSERT(scl->scl_write_wanted == 0);
 	}
@@ -406,7 +406,7 @@ spa_config_tryenter(spa_t *spa, int locks, void *tag, krw_t rw)
 			}
 		} else {
 			ASSERT(scl->scl_writer != curthread);
-			if (!refcount_is_zero(&scl->scl_count)) {
+			if (!zfs_refcount_is_zero(&scl->scl_count)) {
 				mutex_exit(&scl->scl_lock);
 				spa_config_exit(spa, locks & ((1 << i) - 1),
 				    tag);
@@ -441,7 +441,7 @@ spa_config_enter(spa_t *spa, int locks, void *tag, krw_t rw)
 			}
 		} else {
 			ASSERT(scl->scl_writer != curthread);
-			while (!refcount_is_zero(&scl->scl_count)) {
+			while (!zfs_refcount_is_zero(&scl->scl_count)) {
 				scl->scl_write_wanted++;
 				cv_wait(&scl->scl_cv, &scl->scl_lock);
 				scl->scl_write_wanted--;
@@ -464,8 +464,8 @@ spa_config_exit(spa_t *spa, int locks, void *tag)
 		if (!(locks & (1 << i)))
 			continue;
 		mutex_enter(&scl->scl_lock);
-		ASSERT(!refcount_is_zero(&scl->scl_count));
-		if (refcount_remove(&scl->scl_count, tag) == 0) {
+		ASSERT(!zfs_refcount_is_zero(&scl->scl_count));
+		if (zfs_refcount_remove(&scl->scl_count, tag) == 0) {
 			ASSERT(scl->scl_writer == NULL ||
 			    scl->scl_writer == curthread);
 			scl->scl_writer = NULL;	/* OK in either case */
@@ -484,7 +484,8 @@ spa_config_held(spa_t *spa, int locks, krw_t rw)
 		spa_config_lock_t *scl = &spa->spa_config_lock[i];
 		if (!(locks & (1 << i)))
 			continue;
-		if ((rw == RW_READER && !refcount_is_zero(&scl->scl_count)) ||
+		if ((rw == RW_READER &&
+		    !zfs_refcount_is_zero(&scl->scl_count)) ||
 		    (rw == RW_WRITER && scl->scl_writer == curthread))
 			locks_held |= 1 << i;
 	}
@@ -602,7 +603,7 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
 
 	spa->spa_deadman_synctime = MSEC2NSEC(zfs_deadman_synctime_ms);
 
-	refcount_create(&spa->spa_refcount);
+	zfs_refcount_create(&spa->spa_refcount);
 	spa_config_lock_init(spa);
 	spa_stats_init(spa);
 
@@ -680,7 +681,7 @@ spa_remove(spa_t *spa)
 
 	ASSERT(MUTEX_HELD(&spa_namespace_lock));
 	ASSERT(spa->spa_state == POOL_STATE_UNINITIALIZED);
-	ASSERT3U(refcount_count(&spa->spa_refcount), ==, 0);
+	ASSERT3U(zfs_refcount_count(&spa->spa_refcount), ==, 0);
 
 	nvlist_free(spa->spa_config_splitting);
 
@@ -705,7 +706,7 @@ spa_remove(spa_t *spa)
 	nvlist_free(spa->spa_feat_stats);
 	spa_config_set(spa, NULL);
 
-	refcount_destroy(&spa->spa_refcount);
+	zfs_refcount_destroy(&spa->spa_refcount);
 
 	spa_stats_destroy(spa);
 	spa_config_lock_destroy(spa);
@@ -766,7 +767,7 @@ spa_next(spa_t *prev)
 void
 spa_open_ref(spa_t *spa, void *tag)
 {
-	ASSERT(refcount_count(&spa->spa_refcount) >= spa->spa_minref ||
+	ASSERT(zfs_refcount_count(&spa->spa_refcount) >= spa->spa_minref ||
 	    MUTEX_HELD(&spa_namespace_lock));
 	(void) zfs_refcount_add(&spa->spa_refcount, tag);
 }
@@ -778,9 +779,9 @@ spa_open_ref(spa_t *spa, void *tag)
 void
 spa_close(spa_t *spa, void *tag)
 {
-	ASSERT(refcount_count(&spa->spa_refcount) > spa->spa_minref ||
+	ASSERT(zfs_refcount_count(&spa->spa_refcount) > spa->spa_minref ||
 	    MUTEX_HELD(&spa_namespace_lock));
-	(void) refcount_remove(&spa->spa_refcount, tag);
+	(void) zfs_refcount_remove(&spa->spa_refcount, tag);
 }
 
 /*
@@ -794,7 +795,7 @@ spa_close(spa_t *spa, void *tag)
 void
 spa_async_close(spa_t *spa, void *tag)
 {
-	(void) refcount_remove(&spa->spa_refcount, tag);
+	(void) zfs_refcount_remove(&spa->spa_refcount, tag);
 }
 
 /*
@@ -807,7 +808,7 @@ spa_refcount_zero(spa_t *spa)
 {
 	ASSERT(MUTEX_HELD(&spa_namespace_lock));
 
-	return (refcount_count(&spa->spa_refcount) == spa->spa_minref);
+	return (zfs_refcount_count(&spa->spa_refcount) == spa->spa_minref);
 }
 
 /*
@@ -1878,7 +1879,7 @@ spa_init(int mode)
 #endif
 
 	fm_init();
-	refcount_init();
+	zfs_refcount_init();
 	unique_init();
 	range_tree_init();
 	metaslab_alloc_trace_init();
@@ -1914,7 +1915,7 @@ spa_fini(void)
 	metaslab_alloc_trace_fini();
 	range_tree_fini();
 	unique_fini();
-	refcount_fini();
+	zfs_refcount_fini();
 	fm_fini();
 	qat_fini();
 
diff --git a/zfs/module/zfs/zfs_ctldir.c b/zfs/module/zfs/zfs_ctldir.c
index 579f1fb..bf5a1d0 100644
--- a/zfs/module/zfs/zfs_ctldir.c
+++ b/zfs/module/zfs/zfs_ctldir.c
@@ -144,7 +144,7 @@ zfsctl_snapshot_alloc(char *full_name, char *full_path, spa_t *spa,
 	se->se_root_dentry = root_dentry;
 	se->se_taskqid = TASKQID_INVALID;
 
-	refcount_create(&se->se_refcount);
+	zfs_refcount_create(&se->se_refcount);
 
 	return (se);
 }
@@ -156,7 +156,7 @@ zfsctl_snapshot_alloc(char *full_name, char *full_path, spa_t *spa,
 static void
 zfsctl_snapshot_free(zfs_snapentry_t *se)
 {
-	refcount_destroy(&se->se_refcount);
+	zfs_refcount_destroy(&se->se_refcount);
 	strfree(se->se_name);
 	strfree(se->se_path);
 
@@ -179,7 +179,7 @@ zfsctl_snapshot_hold(zfs_snapentry_t *se)
 static void
 zfsctl_snapshot_rele(zfs_snapentry_t *se)
 {
-	if (refcount_remove(&se->se_refcount, NULL) == 0)
+	if (zfs_refcount_remove(&se->se_refcount, NULL) == 0)
 		zfsctl_snapshot_free(se);
 }
 
diff --git a/zfs/module/zfs/zfs_vfsops.c b/zfs/module/zfs/zfs_vfsops.c
index 76113393..bcdfa26 100644
--- a/zfs/module/zfs/zfs_vfsops.c
+++ b/zfs/module/zfs/zfs_vfsops.c
@@ -1245,15 +1245,13 @@ zfs_statvfs(struct dentry *dentry, struct kstatfs *statp)
 {
 	zfsvfs_t *zfsvfs = dentry->d_sb->s_fs_info;
 	uint64_t refdbytes, availbytes, usedobjs, availobjs;
-	uint64_t fsid;
-	uint32_t bshift;
 
 	ZFS_ENTER(zfsvfs);
 
 	dmu_objset_space(zfsvfs->z_os,
 	    &refdbytes, &availbytes, &usedobjs, &availobjs);
 
-	fsid = dmu_objset_fsid_guid(zfsvfs->z_os);
+	uint64_t fsid = dmu_objset_fsid_guid(zfsvfs->z_os);
 	/*
 	 * The underlying storage pool actually uses multiple block
 	 * size.  Under Solaris frsize (fragment size) is reported as
@@ -1265,7 +1263,7 @@ zfs_statvfs(struct dentry *dentry, struct kstatfs *statp)
 	 */
 	statp->f_frsize = zfsvfs->z_max_blksz;
 	statp->f_bsize = zfsvfs->z_max_blksz;
-	bshift = fls(statp->f_bsize) - 1;
+	uint32_t bshift = fls(statp->f_bsize) - 1;
 
 	/*
 	 * The following report "total" blocks of various kinds in
@@ -1282,7 +1280,7 @@ zfs_statvfs(struct dentry *dentry, struct kstatfs *statp)
 	 * static metadata.  ZFS doesn't preallocate files, so the best
 	 * we can do is report the max that could possibly fit in f_files,
 	 * and that minus the number actually used in f_ffree.
-	 * For f_ffree, report the smaller of the number of object available
+	 * For f_ffree, report the smaller of the number of objects available
 	 * and the number of blocks (each object will take at least a block).
 	 */
 	statp->f_ffree = MIN(availobjs, availbytes >> DNODE_SHIFT);
diff --git a/zfs/module/zfs/zfs_znode.c b/zfs/module/zfs/zfs_znode.c
index 0ca10f8..7b893dc 100644
--- a/zfs/module/zfs/zfs_znode.c
+++ b/zfs/module/zfs/zfs_znode.c
@@ -149,7 +149,7 @@ zfs_znode_hold_cache_constructor(void *buf, void *arg, int kmflags)
 	znode_hold_t *zh = buf;
 
 	mutex_init(&zh->zh_lock, NULL, MUTEX_DEFAULT, NULL);
-	refcount_create(&zh->zh_refcount);
+	zfs_refcount_create(&zh->zh_refcount);
 	zh->zh_obj = ZFS_NO_OBJECT;
 
 	return (0);
@@ -161,7 +161,7 @@ zfs_znode_hold_cache_destructor(void *buf, void *arg)
 	znode_hold_t *zh = buf;
 
 	mutex_destroy(&zh->zh_lock);
-	refcount_destroy(&zh->zh_refcount);
+	zfs_refcount_destroy(&zh->zh_refcount);
 }
 
 void
@@ -279,7 +279,7 @@ zfs_znode_hold_enter(zfsvfs_t *zfsvfs, uint64_t obj)
 		kmem_cache_free(znode_hold_cache, zh_new);
 
 	ASSERT(MUTEX_NOT_HELD(&zh->zh_lock));
-	ASSERT3S(refcount_count(&zh->zh_refcount), >, 0);
+	ASSERT3S(zfs_refcount_count(&zh->zh_refcount), >, 0);
 	mutex_enter(&zh->zh_lock);
 
 	return (zh);
@@ -292,11 +292,11 @@ zfs_znode_hold_exit(zfsvfs_t *zfsvfs, znode_hold_t *zh)
 	boolean_t remove = B_FALSE;
 
 	ASSERT(zfs_znode_held(zfsvfs, zh->zh_obj));
-	ASSERT3S(refcount_count(&zh->zh_refcount), >, 0);
+	ASSERT3S(zfs_refcount_count(&zh->zh_refcount), >, 0);
 	mutex_exit(&zh->zh_lock);
 
 	mutex_enter(&zfsvfs->z_hold_locks[i]);
-	if (refcount_remove(&zh->zh_refcount, NULL) == 0) {
+	if (zfs_refcount_remove(&zh->zh_refcount, NULL) == 0) {
 		avl_remove(&zfsvfs->z_hold_trees[i], zh);
 		remove = B_TRUE;
 	}
diff --git a/zfs/module/zfs/zio.c b/zfs/module/zfs/zio.c
index 9a465e1..3f8fca3 100644
--- a/zfs/module/zfs/zio.c
+++ b/zfs/module/zfs/zio.c
@@ -75,9 +75,6 @@ uint64_t zio_buf_cache_frees[SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT];
 
 int zio_delay_max = ZIO_DELAY_MAX;
 
-#define	ZIO_PIPELINE_CONTINUE		0x100
-#define	ZIO_PIPELINE_STOP		0x101
-
 #define	BP_SPANB(indblkshift, level) \
 	(((uint64_t)1) << ((level) * ((indblkshift) - SPA_BLKPTRSHIFT)))
 #define	COMPARE_META_LEVEL	0x80000000ul
@@ -516,7 +513,8 @@ zio_wait_for_children(zio_t *zio, uint8_t childbits, enum zio_wait_type wait)
 
 __attribute__((always_inline))
 static inline void
-zio_notify_parent(zio_t *pio, zio_t *zio, enum zio_wait_type wait)
+zio_notify_parent(zio_t *pio, zio_t *zio, enum zio_wait_type wait,
+    zio_t **next_to_executep)
 {
 	uint64_t *countp = &pio->io_children[zio->io_child_type][wait];
 	int *errorp = &pio->io_child_error[zio->io_child_type];
@@ -535,13 +533,33 @@ zio_notify_parent(zio_t *pio, zio_t *zio, enum zio_wait_type wait)
 		    ZIO_TASKQ_INTERRUPT;
 		pio->io_stall = NULL;
 		mutex_exit(&pio->io_lock);
+
 		/*
-		 * Dispatch the parent zio in its own taskq so that
-		 * the child can continue to make progress. This also
-		 * prevents overflowing the stack when we have deeply nested
-		 * parent-child relationships.
+		 * If we can tell the caller to execute this parent next, do
+		 * so.  Otherwise dispatch the parent zio as its own task.
+		 *
+		 * Having the caller execute the parent when possible reduces
+		 * locking on the zio taskq's, reduces context switch
+		 * overhead, and has no recursion penalty.  Note that one
+		 * read from disk typically causes at least 3 zio's: a
+		 * zio_null(), the logical zio_read(), and then a physical
+		 * zio.  When the physical ZIO completes, we are able to call
+		 * zio_done() on all 3 of these zio's from one invocation of
+		 * zio_execute() by returning the parent back to
+		 * zio_execute().  Since the parent isn't executed until this
+		 * thread returns back to zio_execute(), the caller should do
+		 * so promptly.
+		 *
+		 * In other cases, dispatching the parent prevents
+		 * overflowing the stack when we have deeply nested
+		 * parent-child relationships, as we do with the "mega zio"
+		 * of writes for spa_sync(), and the chain of ZIL blocks.
 		 */
-		zio_taskq_dispatch(pio, type, B_FALSE);
+		if (next_to_executep != NULL && *next_to_executep == NULL) {
+			*next_to_executep = pio;
+		} else {
+			zio_taskq_dispatch(pio, type, B_FALSE);
+		}
 	} else {
 		mutex_exit(&pio->io_lock);
 	}
@@ -1187,7 +1205,7 @@ zio_shrink(zio_t *zio, uint64_t size)
  * ==========================================================================
  */
 
-static int
+static zio_t *
 zio_read_bp_init(zio_t *zio)
 {
 	blkptr_t *bp = zio->io_bp;
@@ -1221,15 +1239,15 @@ zio_read_bp_init(zio_t *zio)
 	if (BP_GET_DEDUP(bp) && zio->io_child_type == ZIO_CHILD_LOGICAL)
 		zio->io_pipeline = ZIO_DDT_READ_PIPELINE;
 
-	return (ZIO_PIPELINE_CONTINUE);
+	return (zio);
 }
 
-static int
+static zio_t *
 zio_write_bp_init(zio_t *zio)
 {
 
 	if (!IO_IS_ALLOCATING(zio))
-		return (ZIO_PIPELINE_CONTINUE);
+		return (zio);
 
 	ASSERT(zio->io_child_type != ZIO_CHILD_DDT);
 
@@ -1244,7 +1262,7 @@ zio_write_bp_init(zio_t *zio)
 		zio->io_pipeline = ZIO_INTERLOCK_PIPELINE;
 
 		if (BP_IS_EMBEDDED(bp))
-			return (ZIO_PIPELINE_CONTINUE);
+			return (zio);
 
 		/*
 		 * If we've been overridden and nopwrite is set then
@@ -1255,13 +1273,13 @@ zio_write_bp_init(zio_t *zio)
 			ASSERT(!zp->zp_dedup);
 			ASSERT3U(BP_GET_CHECKSUM(bp), ==, zp->zp_checksum);
 			zio->io_flags |= ZIO_FLAG_NOPWRITE;
-			return (ZIO_PIPELINE_CONTINUE);
+			return (zio);
 		}
 
 		ASSERT(!zp->zp_nopwrite);
 
 		if (BP_IS_HOLE(bp) || !zp->zp_dedup)
-			return (ZIO_PIPELINE_CONTINUE);
+			return (zio);
 
 		ASSERT((zio_checksum_table[zp->zp_checksum].ci_flags &
 		    ZCHECKSUM_FLAG_DEDUP) || zp->zp_dedup_verify);
@@ -1269,7 +1287,7 @@ zio_write_bp_init(zio_t *zio)
 		if (BP_GET_CHECKSUM(bp) == zp->zp_checksum) {
 			BP_SET_DEDUP(bp, 1);
 			zio->io_pipeline |= ZIO_STAGE_DDT_WRITE;
-			return (ZIO_PIPELINE_CONTINUE);
+			return (zio);
 		}
 
 		/*
@@ -1281,10 +1299,10 @@ zio_write_bp_init(zio_t *zio)
 		zio->io_pipeline = zio->io_orig_pipeline;
 	}
 
-	return (ZIO_PIPELINE_CONTINUE);
+	return (zio);
 }
 
-static int
+static zio_t *
 zio_write_compress(zio_t *zio)
 {
 	spa_t *spa = zio->io_spa;
@@ -1303,11 +1321,11 @@ zio_write_compress(zio_t *zio)
 	 */
 	if (zio_wait_for_children(zio, ZIO_CHILD_LOGICAL_BIT |
 	    ZIO_CHILD_GANG_BIT, ZIO_WAIT_READY)) {
-		return (ZIO_PIPELINE_STOP);
+		return (NULL);
 	}
 
 	if (!IO_IS_ALLOCATING(zio))
-		return (ZIO_PIPELINE_CONTINUE);
+		return (zio);
 
 	if (zio->io_children_ready != NULL) {
 		/*
@@ -1366,7 +1384,7 @@ zio_write_compress(zio_t *zio)
 			zio->io_pipeline = ZIO_INTERLOCK_PIPELINE;
 			ASSERT(spa_feature_is_active(spa,
 			    SPA_FEATURE_EMBEDDED_DATA));
-			return (ZIO_PIPELINE_CONTINUE);
+			return (zio);
 		} else {
 			/*
 			 * Round up compressed size up to the ashift
@@ -1459,10 +1477,10 @@ zio_write_compress(zio_t *zio)
 			zio->io_pipeline |= ZIO_STAGE_NOP_WRITE;
 		}
 	}
-	return (ZIO_PIPELINE_CONTINUE);
+	return (zio);
 }
 
-static int
+static zio_t *
 zio_free_bp_init(zio_t *zio)
 {
 	blkptr_t *bp = zio->io_bp;
@@ -1472,7 +1490,9 @@ zio_free_bp_init(zio_t *zio)
 			zio->io_pipeline = ZIO_DDT_FREE_PIPELINE;
 	}
 
-	return (ZIO_PIPELINE_CONTINUE);
+	ASSERT3P(zio->io_bp, ==, &zio->io_bp_copy);
+
+	return (zio);
 }
 
 /*
@@ -1541,12 +1561,12 @@ zio_taskq_member(zio_t *zio, zio_taskq_type_t q)
 	return (B_FALSE);
 }
 
-static int
+static zio_t *
 zio_issue_async(zio_t *zio)
 {
 	zio_taskq_dispatch(zio, ZIO_TASKQ_ISSUE, B_FALSE);
 
-	return (ZIO_PIPELINE_STOP);
+	return (NULL);
 }
 
 void
@@ -1687,14 +1707,13 @@ __attribute__((always_inline))
 static inline void
 __zio_execute(zio_t *zio)
 {
-	zio->io_executor = curthread;
-
 	ASSERT3U(zio->io_queued_timestamp, >, 0);
 
 	while (zio->io_stage < ZIO_STAGE_DONE) {
 		enum zio_stage pipeline = zio->io_pipeline;
 		enum zio_stage stage = zio->io_stage;
-		int rv;
+
+		zio->io_executor = curthread;
 
 		ASSERT(!MUTEX_HELD(&zio->io_lock));
 		ASSERT(ISP2(stage));
@@ -1736,12 +1755,16 @@ __zio_execute(zio_t *zio)
 
 		zio->io_stage = stage;
 		zio->io_pipeline_trace |= zio->io_stage;
-		rv = zio_pipeline[highbit64(stage) - 1](zio);
 
-		if (rv == ZIO_PIPELINE_STOP)
-			return;
+		/*
+		 * The zio pipeline stage returns the next zio to execute
+		 * (typically the same as this one), or NULL if we should
+		 * stop.
+		 */
+		zio = zio_pipeline[highbit64(stage) - 1](zio);
 
-		ASSERT(rv == ZIO_PIPELINE_CONTINUE);
+		if (zio == NULL)
+			return;
 	}
 }
 
@@ -2215,7 +2238,7 @@ zio_gang_tree_issue(zio_t *pio, zio_gang_node_t *gn, blkptr_t *bp, abd_t *data,
 		zio_nowait(zio);
 }
 
-static int
+static zio_t *
 zio_gang_assemble(zio_t *zio)
 {
 	blkptr_t *bp = zio->io_bp;
@@ -2227,16 +2250,16 @@ zio_gang_assemble(zio_t *zio)
 
 	zio_gang_tree_assemble(zio, bp, &zio->io_gang_tree);
 
-	return (ZIO_PIPELINE_CONTINUE);
+	return (zio);
 }
 
-static int
+static zio_t *
 zio_gang_issue(zio_t *zio)
 {
 	blkptr_t *bp = zio->io_bp;
 
 	if (zio_wait_for_children(zio, ZIO_CHILD_GANG_BIT, ZIO_WAIT_DONE)) {
-		return (ZIO_PIPELINE_STOP);
+		return (NULL);
 	}
 
 	ASSERT(BP_IS_GANG(bp) && zio->io_gang_leader == zio);
@@ -2250,7 +2273,7 @@ zio_gang_issue(zio_t *zio)
 
 	zio->io_pipeline = ZIO_INTERLOCK_PIPELINE;
 
-	return (ZIO_PIPELINE_CONTINUE);
+	return (zio);
 }
 
 static void
@@ -2290,7 +2313,7 @@ zio_write_gang_done(zio_t *zio)
 	abd_put(zio->io_abd);
 }
 
-static int
+static zio_t *
 zio_write_gang_block(zio_t *pio)
 {
 	spa_t *spa = pio->io_spa;
@@ -2315,7 +2338,7 @@ zio_write_gang_block(zio_t *pio)
 		ASSERT(!(pio->io_flags & ZIO_FLAG_NODATA));
 
 		flags |= METASLAB_ASYNC_ALLOC;
-		VERIFY(refcount_held(&mc->mc_alloc_slots, pio));
+		VERIFY(zfs_refcount_held(&mc->mc_alloc_slots, pio));
 
 		/*
 		 * The logical zio has already placed a reservation for
@@ -2349,7 +2372,7 @@ zio_write_gang_block(zio_t *pio)
 		}
 
 		pio->io_error = error;
-		return (ZIO_PIPELINE_CONTINUE);
+		return (pio);
 	}
 
 	if (pio == gio) {
@@ -2423,7 +2446,7 @@ zio_write_gang_block(zio_t *pio)
 
 	zio_nowait(zio);
 
-	return (ZIO_PIPELINE_CONTINUE);
+	return (pio);
 }
 
 /*
@@ -2444,7 +2467,7 @@ zio_write_gang_block(zio_t *pio)
  * used for nopwrite, assuming that the salt and the checksums
  * themselves remain secret.
  */
-static int
+static zio_t *
 zio_nop_write(zio_t *zio)
 {
 	blkptr_t *bp = zio->io_bp;
@@ -2471,7 +2494,7 @@ zio_nop_write(zio_t *zio)
 	    BP_GET_COMPRESS(bp) != BP_GET_COMPRESS(bp_orig) ||
 	    BP_GET_DEDUP(bp) != BP_GET_DEDUP(bp_orig) ||
 	    zp->zp_copies != BP_GET_NDVAS(bp_orig))
-		return (ZIO_PIPELINE_CONTINUE);
+		return (zio);
 
 	/*
 	 * If the checksums match then reset the pipeline so that we
@@ -2491,7 +2514,7 @@ zio_nop_write(zio_t *zio)
 		zio->io_flags |= ZIO_FLAG_NOPWRITE;
 	}
 
-	return (ZIO_PIPELINE_CONTINUE);
+	return (zio);
 }
 
 /*
@@ -2519,7 +2542,7 @@ zio_ddt_child_read_done(zio_t *zio)
 	mutex_exit(&pio->io_lock);
 }
 
-static int
+static zio_t *
 zio_ddt_read_start(zio_t *zio)
 {
 	blkptr_t *bp = zio->io_bp;
@@ -2540,7 +2563,7 @@ zio_ddt_read_start(zio_t *zio)
 		zio->io_vsd = dde;
 
 		if (ddp_self == NULL)
-			return (ZIO_PIPELINE_CONTINUE);
+			return (zio);
 
 		for (p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
 			if (ddp->ddp_phys_birth == 0 || ddp == ddp_self)
@@ -2553,23 +2576,23 @@ zio_ddt_read_start(zio_t *zio)
 			    zio->io_priority, ZIO_DDT_CHILD_FLAGS(zio) |
 			    ZIO_FLAG_DONT_PROPAGATE, &zio->io_bookmark));
 		}
-		return (ZIO_PIPELINE_CONTINUE);
+		return (zio);
 	}
 
 	zio_nowait(zio_read(zio, zio->io_spa, bp,
 	    zio->io_abd, zio->io_size, NULL, NULL, zio->io_priority,
 	    ZIO_DDT_CHILD_FLAGS(zio), &zio->io_bookmark));
 
-	return (ZIO_PIPELINE_CONTINUE);
+	return (zio);
 }
 
-static int
+static zio_t *
 zio_ddt_read_done(zio_t *zio)
 {
 	blkptr_t *bp = zio->io_bp;
 
 	if (zio_wait_for_children(zio, ZIO_CHILD_DDT_BIT, ZIO_WAIT_DONE)) {
-		return (ZIO_PIPELINE_STOP);
+		return (NULL);
 	}
 
 	ASSERT(BP_GET_DEDUP(bp));
@@ -2581,12 +2604,12 @@ zio_ddt_read_done(zio_t *zio)
 		ddt_entry_t *dde = zio->io_vsd;
 		if (ddt == NULL) {
 			ASSERT(spa_load_state(zio->io_spa) != SPA_LOAD_NONE);
-			return (ZIO_PIPELINE_CONTINUE);
+			return (zio);
 		}
 		if (dde == NULL) {
 			zio->io_stage = ZIO_STAGE_DDT_READ_START >> 1;
 			zio_taskq_dispatch(zio, ZIO_TASKQ_ISSUE, B_FALSE);
-			return (ZIO_PIPELINE_STOP);
+			return (NULL);
 		}
 		if (dde->dde_repair_abd != NULL) {
 			abd_copy(zio->io_abd, dde->dde_repair_abd,
@@ -2599,7 +2622,7 @@ zio_ddt_read_done(zio_t *zio)
 
 	ASSERT(zio->io_vsd == NULL);
 
-	return (ZIO_PIPELINE_CONTINUE);
+	return (zio);
 }
 
 static boolean_t
@@ -2780,7 +2803,7 @@ zio_ddt_ditto_write_done(zio_t *zio)
 	ddt_exit(ddt);
 }
 
-static int
+static zio_t *
 zio_ddt_write(zio_t *zio)
 {
 	spa_t *spa = zio->io_spa;
@@ -2822,7 +2845,7 @@ zio_ddt_write(zio_t *zio)
 		}
 		zio->io_pipeline = ZIO_WRITE_PIPELINE;
 		ddt_exit(ddt);
-		return (ZIO_PIPELINE_CONTINUE);
+		return (zio);
 	}
 
 	ditto_copies = ddt_ditto_copies_needed(ddt, dde, ddp);
@@ -2848,7 +2871,7 @@ zio_ddt_write(zio_t *zio)
 			zio->io_bp_override = NULL;
 			BP_ZERO(bp);
 			ddt_exit(ddt);
-			return (ZIO_PIPELINE_CONTINUE);
+			return (zio);
 		}
 
 		dio = zio_write(zio, spa, txg, bp, zio->io_orig_abd,
@@ -2890,12 +2913,12 @@ zio_ddt_write(zio_t *zio)
 	if (dio)
 		zio_nowait(dio);
 
-	return (ZIO_PIPELINE_CONTINUE);
+	return (zio);
 }
 
 ddt_entry_t *freedde; /* for debugging */
 
-static int
+static zio_t *
 zio_ddt_free(zio_t *zio)
 {
 	spa_t *spa = zio->io_spa;
@@ -2916,7 +2939,7 @@ zio_ddt_free(zio_t *zio)
 	}
 	ddt_exit(ddt);
 
-	return (ZIO_PIPELINE_CONTINUE);
+	return (zio);
 }
 
 /*
@@ -2953,7 +2976,7 @@ zio_io_to_allocate(spa_t *spa)
 	return (zio);
 }
 
-static int
+static zio_t *
 zio_dva_throttle(zio_t *zio)
 {
 	spa_t *spa = zio->io_spa;
@@ -2963,7 +2986,7 @@ zio_dva_throttle(zio_t *zio)
 	    !spa_normal_class(zio->io_spa)->mc_alloc_throttle_enabled ||
 	    zio->io_child_type == ZIO_CHILD_GANG ||
 	    zio->io_flags & ZIO_FLAG_NODATA) {
-		return (ZIO_PIPELINE_CONTINUE);
+		return (zio);
 	}
 
 	ASSERT(zio->io_child_type > ZIO_CHILD_GANG);
@@ -2979,22 +3002,7 @@ zio_dva_throttle(zio_t *zio)
 	nio = zio_io_to_allocate(zio->io_spa);
 	mutex_exit(&spa->spa_alloc_lock);
 
-	if (nio == zio)
-		return (ZIO_PIPELINE_CONTINUE);
-
-	if (nio != NULL) {
-		ASSERT(nio->io_stage == ZIO_STAGE_DVA_THROTTLE);
-		/*
-		 * We are passing control to a new zio so make sure that
-		 * it is processed by a different thread. We do this to
-		 * avoid stack overflows that can occur when parents are
-		 * throttled and children are making progress. We allow
-		 * it to go to the head of the taskq since it's already
-		 * been waiting.
-		 */
-		zio_taskq_dispatch(nio, ZIO_TASKQ_ISSUE, B_TRUE);
-	}
-	return (ZIO_PIPELINE_STOP);
+	return (nio);
 }
 
 void
@@ -3013,7 +3021,7 @@ zio_allocate_dispatch(spa_t *spa)
 	zio_taskq_dispatch(zio, ZIO_TASKQ_ISSUE, B_TRUE);
 }
 
-static int
+static zio_t *
 zio_dva_allocate(zio_t *zio)
 {
 	spa_t *spa = zio->io_spa;
@@ -3054,18 +3062,18 @@ zio_dva_allocate(zio_t *zio)
 		zio->io_error = error;
 	}
 
-	return (ZIO_PIPELINE_CONTINUE);
+	return (zio);
 }
 
-static int
+static zio_t *
 zio_dva_free(zio_t *zio)
 {
 	metaslab_free(zio->io_spa, zio->io_bp, zio->io_txg, B_FALSE);
 
-	return (ZIO_PIPELINE_CONTINUE);
+	return (zio);
 }
 
-static int
+static zio_t *
 zio_dva_claim(zio_t *zio)
 {
 	int error;
@@ -3074,7 +3082,7 @@ zio_dva_claim(zio_t *zio)
 	if (error)
 		zio->io_error = error;
 
-	return (ZIO_PIPELINE_CONTINUE);
+	return (zio);
 }
 
 /*
@@ -3172,7 +3180,7 @@ zio_free_zil(spa_t *spa, uint64_t txg, blkptr_t *bp)
  * force the underlying vdev layers to call either zio_execute() or
  * zio_interrupt() to ensure that the pipeline continues with the correct I/O.
  */
-static int
+static zio_t *
 zio_vdev_io_start(zio_t *zio)
 {
 	vdev_t *vd = zio->io_vd;
@@ -3192,7 +3200,7 @@ zio_vdev_io_start(zio_t *zio)
 		 * The mirror_ops handle multiple DVAs in a single BP.
 		 */
 		vdev_mirror_ops.vdev_op_io_start(zio);
-		return (ZIO_PIPELINE_STOP);
+		return (NULL);
 	}
 
 	ASSERT3P(zio->io_logical, !=, zio);
@@ -3269,31 +3277,31 @@ zio_vdev_io_start(zio_t *zio)
 	    !vdev_dtl_contains(vd, DTL_PARTIAL, zio->io_txg, 1)) {
 		ASSERT(zio->io_type == ZIO_TYPE_WRITE);
 		zio_vdev_io_bypass(zio);
-		return (ZIO_PIPELINE_CONTINUE);
+		return (zio);
 	}
 
 	if (vd->vdev_ops->vdev_op_leaf &&
 	    (zio->io_type == ZIO_TYPE_READ || zio->io_type == ZIO_TYPE_WRITE)) {
 
 		if (zio->io_type == ZIO_TYPE_READ && vdev_cache_read(zio))
-			return (ZIO_PIPELINE_CONTINUE);
+			return (zio);
 
 		if ((zio = vdev_queue_io(zio)) == NULL)
-			return (ZIO_PIPELINE_STOP);
+			return (NULL);
 
 		if (!vdev_accessible(vd, zio)) {
 			zio->io_error = SET_ERROR(ENXIO);
 			zio_interrupt(zio);
-			return (ZIO_PIPELINE_STOP);
+			return (NULL);
 		}
 		zio->io_delay = gethrtime();
 	}
 
 	vd->vdev_ops->vdev_op_io_start(zio);
-	return (ZIO_PIPELINE_STOP);
+	return (NULL);
 }
 
-static int
+static zio_t *
 zio_vdev_io_done(zio_t *zio)
 {
 	vdev_t *vd = zio->io_vd;
@@ -3301,7 +3309,7 @@ zio_vdev_io_done(zio_t *zio)
 	boolean_t unexpected_error = B_FALSE;
 
 	if (zio_wait_for_children(zio, ZIO_CHILD_VDEV_BIT, ZIO_WAIT_DONE)) {
-		return (ZIO_PIPELINE_STOP);
+		return (NULL);
 	}
 
 	ASSERT(zio->io_type == ZIO_TYPE_READ || zio->io_type == ZIO_TYPE_WRITE);
@@ -3337,7 +3345,7 @@ zio_vdev_io_done(zio_t *zio)
 	if (unexpected_error)
 		VERIFY(vdev_probe(vd, zio) == NULL);
 
-	return (ZIO_PIPELINE_CONTINUE);
+	return (zio);
 }
 
 /*
@@ -3366,13 +3374,13 @@ zio_vsd_default_cksum_report(zio_t *zio, zio_cksum_report_t *zcr, void *ignored)
 	zcr->zcr_free = zio_abd_free;
 }
 
-static int
+static zio_t *
 zio_vdev_io_assess(zio_t *zio)
 {
 	vdev_t *vd = zio->io_vd;
 
 	if (zio_wait_for_children(zio, ZIO_CHILD_VDEV_BIT, ZIO_WAIT_DONE)) {
-		return (ZIO_PIPELINE_STOP);
+		return (NULL);
 	}
 
 	if (vd == NULL && !(zio->io_flags & ZIO_FLAG_CONFIG_WRITER))
@@ -3402,7 +3410,7 @@ zio_vdev_io_assess(zio_t *zio)
 		zio->io_stage = ZIO_STAGE_VDEV_IO_START >> 1;
 		zio_taskq_dispatch(zio, ZIO_TASKQ_ISSUE,
 		    zio_requeue_io_start_cut_in_line);
-		return (ZIO_PIPELINE_STOP);
+		return (NULL);
 	}
 
 	/*
@@ -3442,7 +3450,7 @@ zio_vdev_io_assess(zio_t *zio)
 		zio->io_physdone(zio->io_logical);
 	}
 
-	return (ZIO_PIPELINE_CONTINUE);
+	return (zio);
 }
 
 void
@@ -3477,7 +3485,7 @@ zio_vdev_io_bypass(zio_t *zio)
  * Generate and verify checksums
  * ==========================================================================
  */
-static int
+static zio_t *
 zio_checksum_generate(zio_t *zio)
 {
 	blkptr_t *bp = zio->io_bp;
@@ -3491,7 +3499,7 @@ zio_checksum_generate(zio_t *zio)
 		checksum = zio->io_prop.zp_checksum;
 
 		if (checksum == ZIO_CHECKSUM_OFF)
-			return (ZIO_PIPELINE_CONTINUE);
+			return (zio);
 
 		ASSERT(checksum == ZIO_CHECKSUM_LABEL);
 	} else {
@@ -3505,10 +3513,10 @@ zio_checksum_generate(zio_t *zio)
 
 	zio_checksum_compute(zio, checksum, zio->io_abd, zio->io_size);
 
-	return (ZIO_PIPELINE_CONTINUE);
+	return (zio);
 }
 
-static int
+static zio_t *
 zio_checksum_verify(zio_t *zio)
 {
 	zio_bad_cksum_t info;
@@ -3523,7 +3531,7 @@ zio_checksum_verify(zio_t *zio)
 		 * We're either verifying a label checksum, or nothing at all.
 		 */
 		if (zio->io_prop.zp_checksum == ZIO_CHECKSUM_OFF)
-			return (ZIO_PIPELINE_CONTINUE);
+			return (zio);
 
 		ASSERT(zio->io_prop.zp_checksum == ZIO_CHECKSUM_LABEL);
 	}
@@ -3538,7 +3546,7 @@ zio_checksum_verify(zio_t *zio)
 		}
 	}
 
-	return (ZIO_PIPELINE_CONTINUE);
+	return (zio);
 }
 
 /*
@@ -3581,7 +3589,7 @@ zio_worst_error(int e1, int e2)
  * I/O completion
  * ==========================================================================
  */
-static int
+static zio_t *
 zio_ready(zio_t *zio)
 {
 	blkptr_t *bp = zio->io_bp;
@@ -3590,7 +3598,7 @@ zio_ready(zio_t *zio)
 
 	if (zio_wait_for_children(zio, ZIO_CHILD_GANG_BIT | ZIO_CHILD_DDT_BIT,
 	    ZIO_WAIT_READY)) {
-		return (ZIO_PIPELINE_STOP);
+		return (NULL);
 	}
 
 	if (zio->io_ready) {
@@ -3636,7 +3644,7 @@ zio_ready(zio_t *zio)
 	 */
 	for (; pio != NULL; pio = pio_next) {
 		pio_next = zio_walk_parents(zio, &zl);
-		zio_notify_parent(pio, zio, ZIO_WAIT_READY);
+		zio_notify_parent(pio, zio, ZIO_WAIT_READY, NULL);
 	}
 
 	if (zio->io_flags & ZIO_FLAG_NODATA) {
@@ -3652,7 +3660,7 @@ zio_ready(zio_t *zio)
 	    zio->io_spa->spa_syncing_txg == zio->io_txg)
 		zio_handle_ignored_writes(zio);
 
-	return (ZIO_PIPELINE_CONTINUE);
+	return (zio);
 }
 
 /*
@@ -3716,7 +3724,7 @@ zio_dva_throttle_done(zio_t *zio)
 	zio_allocate_dispatch(zio->io_spa);
 }
 
-static int
+static zio_t *
 zio_done(zio_t *zio)
 {
 	/*
@@ -3733,7 +3741,7 @@ zio_done(zio_t *zio)
 	 * wait for them and then repeat this pipeline stage.
 	 */
 	if (zio_wait_for_children(zio, ZIO_CHILD_ALL_BITS, ZIO_WAIT_DONE)) {
-		return (ZIO_PIPELINE_STOP);
+		return (NULL);
 	}
 
 	/*
@@ -3758,7 +3766,7 @@ zio_done(zio_t *zio)
 		ASSERT(zio->io_priority == ZIO_PRIORITY_ASYNC_WRITE);
 		ASSERT(zio->io_bp != NULL);
 		metaslab_group_alloc_verify(zio->io_spa, zio->io_bp, zio);
-		VERIFY(refcount_not_held(
+		VERIFY(zfs_refcount_not_held(
 		    &(spa_normal_class(zio->io_spa)->mc_alloc_slots), zio));
 	}
 
@@ -3957,7 +3965,12 @@ zio_done(zio_t *zio)
 			if ((pio->io_flags & ZIO_FLAG_GODFATHER) &&
 			    (zio->io_reexecute & ZIO_REEXECUTE_SUSPEND)) {
 				zio_remove_child(pio, zio, remove_zl);
-				zio_notify_parent(pio, zio, ZIO_WAIT_DONE);
+				/*
+				 * This is a rare code path, so we don't
+				 * bother with "next_to_execute".
+				 */
+				zio_notify_parent(pio, zio, ZIO_WAIT_DONE,
+				    NULL);
 			}
 		}
 
@@ -3969,7 +3982,11 @@ zio_done(zio_t *zio)
 			 */
 			ASSERT(!(zio->io_flags & ZIO_FLAG_GODFATHER));
 			zio->io_flags |= ZIO_FLAG_DONT_PROPAGATE;
-			zio_notify_parent(pio, zio, ZIO_WAIT_DONE);
+			/*
+			 * This is a rare code path, so we don't bother with
+			 * "next_to_execute".
+			 */
+			zio_notify_parent(pio, zio, ZIO_WAIT_DONE, NULL);
 		} else if (zio->io_reexecute & ZIO_REEXECUTE_SUSPEND) {
 			/*
 			 * We'd fail again if we reexecuted now, so suspend
@@ -3987,7 +4004,7 @@ zio_done(zio_t *zio)
 			    (task_func_t *)zio_reexecute, zio, 0,
 			    &zio->io_tqent);
 		}
-		return (ZIO_PIPELINE_STOP);
+		return (NULL);
 	}
 
 	ASSERT(zio->io_child_count == 0);
@@ -4023,12 +4040,17 @@ zio_done(zio_t *zio)
 	zio->io_state[ZIO_WAIT_DONE] = 1;
 	mutex_exit(&zio->io_lock);
 
+	/*
+	 * We are done executing this zio.  We may want to execute a parent
+	 * next.  See the comment in zio_notify_parent().
+	 */
+	zio_t *next_to_execute = NULL;
 	zl = NULL;
 	for (pio = zio_walk_parents(zio, &zl); pio != NULL; pio = pio_next) {
 		zio_link_t *remove_zl = zl;
 		pio_next = zio_walk_parents(zio, &zl);
 		zio_remove_child(pio, zio, remove_zl);
-		zio_notify_parent(pio, zio, ZIO_WAIT_DONE);
+		zio_notify_parent(pio, zio, ZIO_WAIT_DONE, &next_to_execute);
 	}
 
 	if (zio->io_waiter != NULL) {
@@ -4040,7 +4062,7 @@ zio_done(zio_t *zio)
 		zio_destroy(zio);
 	}
 
-	return (ZIO_PIPELINE_STOP);
+	return (next_to_execute);
 }
 
 /*
diff --git a/zfs/module/zfs/zpl_super.c b/zfs/module/zfs/zpl_super.c
index 5c426b0..216c794 100644
--- a/zfs/module/zfs/zpl_super.c
+++ b/zfs/module/zfs/zpl_super.c
@@ -181,6 +181,28 @@ zpl_statfs(struct dentry *dentry, struct kstatfs *statp)
 	spl_fstrans_unmark(cookie);
 	ASSERT3S(error, <=, 0);
 
+	/*
+	 * If required by a 32-bit system call, dynamically scale the
+	 * block size up to 16MiB and decrease the block counts.  This
+	 * allows for a maximum size of 64EiB to be reported.  The file
+	 * counts must be artificially capped at 2^32-1.
+	 */
+	if (unlikely(zpl_is_32bit_api())) {
+		while (statp->f_blocks > UINT32_MAX &&
+		    statp->f_bsize < SPA_MAXBLOCKSIZE) {
+			statp->f_frsize <<= 1;
+			statp->f_bsize <<= 1;
+
+			statp->f_blocks >>= 1;
+			statp->f_bfree >>= 1;
+			statp->f_bavail >>= 1;
+		}
+
+		uint64_t usedobjs = statp->f_files - statp->f_ffree;
+		statp->f_ffree = MIN(statp->f_ffree, UINT32_MAX - usedobjs);
+		statp->f_files = statp->f_ffree + usedobjs;
+	}
+
 	return (error);
 }
 
diff --git a/zfs/zfs_config.h.in b/zfs/zfs_config.h.in
index 4fa766d..249d529 100644
--- a/zfs/zfs_config.h.in
+++ b/zfs/zfs_config.h.in
@@ -312,6 +312,9 @@
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
+/* in_compat_syscall() is available */
+#undef HAVE_IN_COMPAT_SYSCALL
+
 /* is_owner_or_cap() exists */
 #undef HAVE_IS_OWNER_OR_CAP
 
-- 
2.7.4




More information about the kernel-team mailing list