Print this page
5269 zfs: zpool import slow
While importing a pool all objsets are enumerated twice, once to check
the zil log chains and once to claim them. On pools with many datasets
this process might take a substantial amount of time.
Speed up the process by parallelizing it utilizing a taskq. The number
of parallel tasks is limited to 4 times the number of leaf vdevs.

@@ -622,22 +622,24 @@
         (void) zil_parse(zilog, zil_free_log_block,
             zil_free_log_record, tx, zilog->zl_header->zh_claim_txg);
 }
 
 int
-zil_claim(const char *osname, void *txarg)
+zil_claim(dsl_pool_t *dp, dsl_dataset_t *ds, void *txarg)
 {
         dmu_tx_t *tx = txarg;
         uint64_t first_txg = dmu_tx_get_txg(tx);
         zilog_t *zilog;
         zil_header_t *zh;
         objset_t *os;
         int error;
 
-        error = dmu_objset_own(osname, DMU_OST_ANY, B_FALSE, FTAG, &os);
+        error = dmu_objset_own_obj(dp, ds->ds_object,
+            DMU_OST_ANY, B_FALSE, FTAG, &os);
         if (error != 0) {
-                cmn_err(CE_WARN, "can't open objset for %s", osname);
+                cmn_err(CE_WARN, "can't open objset %llu, error %d",
+                    (unsigned long long)ds->ds_object, error);
                 return (0);
         }
 
         zilog = dmu_objset_zil(os);
         zh = zil_header_in_syncing_context(zilog);

@@ -680,22 +682,23 @@
  * Check the log by walking the log chain.
  * Checksum errors are ok as they indicate the end of the chain.
  * Any other error (no device or read failure) returns an error.
  */
 int
-zil_check_log_chain(const char *osname, void *tx)
+zil_check_log_chain(dsl_pool_t *dp, dsl_dataset_t *ds, void *tx)
 {
         zilog_t *zilog;
         objset_t *os;
         blkptr_t *bp;
         int error;
 
         ASSERT(tx == NULL);
 
-        error = dmu_objset_hold(osname, FTAG, &os);
+        error = dmu_objset_from_ds(ds, &os);
         if (error != 0) {
-                cmn_err(CE_WARN, "can't open objset for %s", osname);
+                cmn_err(CE_WARN, "can't open objset %llu, error %d",
+                    (unsigned long long)ds->ds_object, error);
                 return (0);
         }
 
         zilog = dmu_objset_zil(os);
         bp = (blkptr_t *)&zilog->zl_header->zh_log;

@@ -714,15 +717,13 @@
                 vd = vdev_lookup_top(os->os_spa, DVA_GET_VDEV(&bp->blk_dva[0]));
                 if (vd->vdev_islog && vdev_is_dead(vd))
                         valid = vdev_log_state_valid(vd);
                 spa_config_exit(os->os_spa, SCL_STATE, FTAG);
 
-                if (!valid) {
-                        dmu_objset_rele(os, FTAG);
+                if (!valid)
                         return (0);
                 }
-        }
 
         /*
          * Because tx == NULL, zil_claim_log_block() will not actually claim
          * any blocks, but just determine whether it is possible to do so.
          * In addition to checking the log chain, zil_claim_log_block()

@@ -730,12 +731,10 @@
          * which will update spa_max_claim_txg.  See spa_load() for details.
          */
         error = zil_parse(zilog, zil_claim_log_block, zil_claim_log_record, tx,
             zilog->zl_header->zh_claim_txg ? -1ULL : spa_first_txg(os->os_spa));
 
-        dmu_objset_rele(os, FTAG);
-
         return ((error == ECKSUM || error == ENOENT) ? 0 : error);
 }
 
 static int
 zil_vdev_compare(const void *x1, const void *x2)