Author: delphij
Date: Sat Dec  6 00:47:31 2014
New Revision: 275550
URL: https://svnweb.freebsd.org/changeset/base/275550

Log:
  5347 idle pool may run itself out of space
  Reviewed by: Alex Reece <alex.re...@delphix.com>
  Reviewed by: George Wilson <george.wil...@delphix.com>
  Reviewed by: Steven Hartland <kill...@multiplay.co.uk>
  Reviewed by: Richard Elling <richard.ell...@richardelling.com>
  Approved by: Dan McDonald <dan...@omniti.com>
  Author: Matthew Ahrens <mahr...@delphix.com>
  
  illumos/illumos-gate@231aab857f14a3e7a0ed5f2879399c3cd6ae92ea

Modified:
  vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_scan.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/spa.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/sys/uberblock.h
  vendor-sys/illumos/dist/uts/common/fs/zfs/uberblock.c

Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_scan.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_scan.c        Sat Dec  6 
00:45:27 2014        (r275549)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_scan.c        Sat Dec  6 
00:47:31 2014        (r275550)
@@ -1449,13 +1449,6 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *
                            "traverse_dataset_destroyed()", err);
                }
 
-               /*
-                * If we didn't make progress, mark the async destroy as
-                * stalled, so that we will not initiate a spa_sync() on
-                * its behalf.
-                */
-               scn->scn_async_stalled = (scn->scn_visited_this_txg == 0);
-
                if (bptree_is_empty(dp->dp_meta_objset, dp->dp_bptree_obj)) {
                        /* finished; deactivate async destroy feature */
                        spa_feature_decr(spa, SPA_FEATURE_ASYNC_DESTROY, tx);
@@ -1468,6 +1461,18 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *
                            dp->dp_bptree_obj, tx));
                        dp->dp_bptree_obj = 0;
                        scn->scn_async_destroying = B_FALSE;
+                       scn->scn_async_stalled = B_FALSE;
+               } else {
+                       /*
+                        * If we didn't make progress, mark the async
+                        * destroy as stalled, so that we will not initiate
+                        * a spa_sync() on its behalf.  Note that we only
+                        * check this if we are not finished, because if the
+                        * bptree had no blocks for us to visit, we can
+                        * finish without "making progress".
+                        */
+                       scn->scn_async_stalled =
+                           (scn->scn_visited_this_txg == 0);
                }
        }
        if (scn->scn_visited_this_txg) {

Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/spa.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/spa.c     Sat Dec  6 00:45:27 
2014        (r275549)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/spa.c     Sat Dec  6 00:47:31 
2014        (r275550)
@@ -6262,21 +6262,6 @@ spa_sync(spa_t *spa, uint64_t txg)
        }
 
        /*
-        * If anything has changed in this txg, or if someone is waiting
-        * for this txg to sync (eg, spa_vdev_remove()), push the
-        * deferred frees from the previous txg.  If not, leave them
-        * alone so that we don't generate work on an otherwise idle
-        * system.
-        */
-       if (!txg_list_empty(&dp->dp_dirty_datasets, txg) ||
-           !txg_list_empty(&dp->dp_dirty_dirs, txg) ||
-           !txg_list_empty(&dp->dp_sync_tasks, txg) ||
-           ((dsl_scan_active(dp->dp_scan) ||
-           txg_sync_waiting(dp)) && !spa_shutting_down(spa))) {
-               spa_sync_deferred_frees(spa, tx);
-       }
-
-       /*
         * Iterate to convergence.
         */
        do {
@@ -6293,6 +6278,11 @@ spa_sync(spa_t *spa, uint64_t txg)
                if (pass < zfs_sync_pass_deferred_free) {
                        spa_sync_frees(spa, free_bpl, tx);
                } else {
+                       /*
+                        * We can not defer frees in pass 1, because
+                        * we sync the deferred frees later in pass 1.
+                        */
+                       ASSERT3U(pass, >, 1);
                        bplist_iterate(free_bpl, bpobj_enqueue_cb,
                            &spa->spa_deferred_bpobj, tx);
                }
@@ -6303,8 +6293,37 @@ spa_sync(spa_t *spa, uint64_t txg)
                while (vd = txg_list_remove(&spa->spa_vdev_txg_list, txg))
                        vdev_sync(vd, txg);
 
-               if (pass == 1)
+               if (pass == 1) {
                        spa_sync_upgrades(spa, tx);
+                       ASSERT3U(txg, >=,
+                           spa->spa_uberblock.ub_rootbp.blk_birth);
+                       /*
+                        * Note: We need to check if the MOS is dirty
+                        * because we could have marked the MOS dirty
+                        * without updating the uberblock (e.g. if we
+                        * have sync tasks but no dirty user data).  We
+                        * need to check the uberblock's rootbp because
+                        * it is updated if we have synced out dirty
+                        * data (though in this case the MOS will most
+                        * likely also be dirty due to second order
+                        * effects, we don't want to rely on that here).
+                        */
+                       if (spa->spa_uberblock.ub_rootbp.blk_birth < txg &&
+                           !dmu_objset_is_dirty(mos, txg)) {
+                               /*
+                                * Nothing changed on the first pass,
+                                * therefore this TXG is a no-op.  Avoid
+                                * syncing deferred frees, so that we
+                                * can keep this TXG as a no-op.
+                                */
+                               ASSERT(txg_list_empty(&dp->dp_dirty_datasets,
+                                   txg));
+                               ASSERT(txg_list_empty(&dp->dp_dirty_dirs, txg));
+                               ASSERT(txg_list_empty(&dp->dp_sync_tasks, txg));
+                               break;
+                       }
+                       spa_sync_deferred_frees(spa, tx);
+               }
 
        } while (dmu_objset_is_dirty(mos, txg));
 

Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/sys/uberblock.h
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/sys/uberblock.h   Sat Dec  6 
00:45:27 2014        (r275549)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/sys/uberblock.h   Sat Dec  6 
00:47:31 2014        (r275550)
@@ -22,6 +22,9 @@
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright (c) 2014 by Delphix. All rights reserved.
+ */
 
 #ifndef _SYS_UBERBLOCK_H
 #define        _SYS_UBERBLOCK_H
@@ -36,8 +39,8 @@ extern "C" {
 
 typedef struct uberblock uberblock_t;
 
-extern int uberblock_verify(uberblock_t *ub);
-extern int uberblock_update(uberblock_t *ub, vdev_t *rvd, uint64_t txg);
+extern int uberblock_verify(uberblock_t *);
+extern boolean_t uberblock_update(uberblock_t *, vdev_t *, uint64_t);
 
 #ifdef __cplusplus
 }

Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/uberblock.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/uberblock.c       Sat Dec  6 
00:45:27 2014        (r275549)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/uberblock.c       Sat Dec  6 
00:47:31 2014        (r275550)
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013, 2014 by Delphix. All rights reserved.
  */
 
 #include <sys/zfs_context.h>
@@ -40,10 +40,10 @@ uberblock_verify(uberblock_t *ub)
 }
 
 /*
- * Update the uberblock and return a boolean value indicating whether
- * anything changed in this transaction group.
+ * Update the uberblock and return TRUE if anything changed in this
+ * transaction group.
  */
-int
+boolean_t
 uberblock_update(uberblock_t *ub, vdev_t *rvd, uint64_t txg)
 {
        ASSERT(ub->ub_txg < txg);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to