Print this page
5269 zfs: zpool import slow
PORTING: this code relies on the property of taskq_wait to wait
until no more tasks are queued and no more tasks are active. As
we always queue new tasks from within other tasks, task_wait
reliably waits for the full recursion to finish, even though we
enqueue new tasks after taskq_wait has been called.
On platforms other than illumos, taskq_wait may not have this
property.
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: George Wilson <george.wilson@delphix.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/zil.c
          +++ new/usr/src/uts/common/fs/zfs/zil.c
↓ open down ↓ 619 lines elided ↑ open up ↑
 620  620  
 621  621  void
 622  622  zil_destroy_sync(zilog_t *zilog, dmu_tx_t *tx)
 623  623  {
 624  624          ASSERT(list_is_empty(&zilog->zl_lwb_list));
 625  625          (void) zil_parse(zilog, zil_free_log_block,
 626  626              zil_free_log_record, tx, zilog->zl_header->zh_claim_txg);
 627  627  }
 628  628  
 629  629  int
 630      -zil_claim(const char *osname, void *txarg)
      630 +zil_claim(dsl_pool_t *dp, dsl_dataset_t *ds, void *txarg)
 631  631  {
 632  632          dmu_tx_t *tx = txarg;
 633  633          uint64_t first_txg = dmu_tx_get_txg(tx);
 634  634          zilog_t *zilog;
 635  635          zil_header_t *zh;
 636  636          objset_t *os;
 637  637          int error;
 638  638  
 639      -        error = dmu_objset_own(osname, DMU_OST_ANY, B_FALSE, FTAG, &os);
      639 +        error = dmu_objset_own_obj(dp, ds->ds_object,
      640 +            DMU_OST_ANY, B_FALSE, FTAG, &os);
 640  641          if (error != 0) {
 641  642                  /*
 642  643                   * EBUSY indicates that the objset is inconsistent, in which
 643  644                   * case it can not have a ZIL.
 644  645                   */
 645  646                  if (error != EBUSY) {
 646      -                        cmn_err(CE_WARN, "can't open objset for %s, error %u",
 647      -                            osname, error);
      647 +                        cmn_err(CE_WARN, "can't open objset for %llu, error %u",
      648 +                            (unsigned long long)ds->ds_object, error);
 648  649                  }
 649  650                  return (0);
 650  651          }
 651  652  
 652  653          zilog = dmu_objset_zil(os);
 653  654          zh = zil_header_in_syncing_context(zilog);
 654  655  
 655  656          if (spa_get_log_state(zilog->zl_spa) == SPA_LOG_CLEAR) {
 656  657                  if (!BP_IS_HOLE(&zh->zh_log))
 657  658                          zio_free_zil(zilog->zl_spa, first_txg, &zh->zh_log);
↓ open down ↓ 26 lines elided ↑ open up ↑
 684  685          ASSERT3U(first_txg, ==, (spa_last_synced_txg(zilog->zl_spa) + 1));
 685  686          dmu_objset_disown(os, FTAG);
 686  687          return (0);
 687  688  }
 688  689  
 689  690  /*
 690  691   * Check the log by walking the log chain.
 691  692   * Checksum errors are ok as they indicate the end of the chain.
 692  693   * Any other error (no device or read failure) returns an error.
 693  694   */
      695 +/* ARGSUSED */
 694  696  int
 695      -zil_check_log_chain(const char *osname, void *tx)
      697 +zil_check_log_chain(dsl_pool_t *dp, dsl_dataset_t *ds, void *tx)
 696  698  {
 697  699          zilog_t *zilog;
 698  700          objset_t *os;
 699  701          blkptr_t *bp;
 700  702          int error;
 701  703  
 702  704          ASSERT(tx == NULL);
 703  705  
 704      -        error = dmu_objset_hold(osname, FTAG, &os);
      706 +        error = dmu_objset_from_ds(ds, &os);
 705  707          if (error != 0) {
 706      -                cmn_err(CE_WARN, "can't open objset for %s", osname);
      708 +                cmn_err(CE_WARN, "can't open objset %llu, error %d",
      709 +                    (unsigned long long)ds->ds_object, error);
 707  710                  return (0);
 708  711          }
 709  712  
 710  713          zilog = dmu_objset_zil(os);
 711  714          bp = (blkptr_t *)&zilog->zl_header->zh_log;
 712  715  
 713  716          /*
 714  717           * Check the first block and determine if it's on a log device
 715  718           * which may have been removed or faulted prior to loading this
 716  719           * pool.  If so, there's no point in checking the rest of the log
↓ open down ↓ 2 lines elided ↑ open up ↑
 719  722          if (!BP_IS_HOLE(bp)) {
 720  723                  vdev_t *vd;
 721  724                  boolean_t valid = B_TRUE;
 722  725  
 723  726                  spa_config_enter(os->os_spa, SCL_STATE, FTAG, RW_READER);
 724  727                  vd = vdev_lookup_top(os->os_spa, DVA_GET_VDEV(&bp->blk_dva[0]));
 725  728                  if (vd->vdev_islog && vdev_is_dead(vd))
 726  729                          valid = vdev_log_state_valid(vd);
 727  730                  spa_config_exit(os->os_spa, SCL_STATE, FTAG);
 728  731  
 729      -                if (!valid) {
 730      -                        dmu_objset_rele(os, FTAG);
      732 +                if (!valid)
 731  733                          return (0);
 732      -                }
 733  734          }
 734  735  
 735  736          /*
 736  737           * Because tx == NULL, zil_claim_log_block() will not actually claim
 737  738           * any blocks, but just determine whether it is possible to do so.
 738  739           * In addition to checking the log chain, zil_claim_log_block()
 739  740           * will invoke zio_claim() with a done func of spa_claim_notify(),
 740  741           * which will update spa_max_claim_txg.  See spa_load() for details.
 741  742           */
 742  743          error = zil_parse(zilog, zil_claim_log_block, zil_claim_log_record, tx,
 743  744              zilog->zl_header->zh_claim_txg ? -1ULL : spa_first_txg(os->os_spa));
 744  745  
 745      -        dmu_objset_rele(os, FTAG);
 746      -
 747  746          return ((error == ECKSUM || error == ENOENT) ? 0 : error);
 748  747  }
 749  748  
 750  749  static int
 751  750  zil_vdev_compare(const void *x1, const void *x2)
 752  751  {
 753  752          const uint64_t v1 = ((zil_vdev_node_t *)x1)->zv_vdev;
 754  753          const uint64_t v2 = ((zil_vdev_node_t *)x2)->zv_vdev;
 755  754  
 756  755          if (v1 < v2)
↓ open down ↓ 1377 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX