int zil_claim(char *osname, 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_open(osname, DMU_OST_ANY, DS_MODE_USER, &os); if (error) { cmn_err(CE_WARN, "can't open objset for %s", osname); return (0); } zilog = dmu_objset_zil(os); zh = zil_header_in_syncing_context(zilog); /* * Record here whether the zil has any records to replay. * If the header block pointer is null or the block points * to the stubby then we know there are no valid log records. * We use the header to store this state as the the zilog gets * freed later in dmu_objset_close(). * The flags (and the rest of the header fields) are cleared in * zil_sync() as a result of a zil_destroy(), after replaying the log. * * Note, the intent log can be empty but still need the * stubby to be claimed. */ if (!zil_empty(zilog)) zh->zh_flags |= ZIL_REPLAY_NEEDED; /* * Claim all log blocks if we haven't already done so, and remember * the highest claimed sequence number. This ensures that if we can * read only part of the log now (e.g. due to a missing device), * but we can read the entire log later, we will not try to replay * or destroy beyond the last block we successfully claimed. */ ASSERT3U(zh->zh_claim_txg, <=, first_txg); if (zh->zh_claim_txg == 0 && !BP_IS_HOLE(&zh->zh_log)) { zh->zh_claim_txg = first_txg; zh->zh_claim_seq = zil_parse(zilog, zil_claim_log_block, zil_claim_log_record, tx, first_txg); dsl_dataset_dirty(dmu_objset_ds(os), tx); } ASSERT3U(first_txg, ==, (spa_last_synced_txg(zilog->zl_spa) + 1)); dmu_objset_close(os); return (0); }
/* * Report whether all transactions are committed */ int zil_is_committed(zilog_t *zilog) { lwb_t *lwb; int ret; mutex_enter(&zilog->zl_lock); while (zilog->zl_writer) cv_wait(&zilog->zl_cv_writer, &zilog->zl_lock); /* recent unpushed intent log transactions? */ if (!list_is_empty(&zilog->zl_itx_list)) { ret = B_FALSE; goto out; } /* intent log never used? */ lwb = list_head(&zilog->zl_lwb_list); if (lwb == NULL) { ret = B_TRUE; goto out; } /* * more than 1 log buffer means zil_sync() hasn't yet freed * entries after a txg has committed */ if (list_next(&zilog->zl_lwb_list, lwb)) { ret = B_FALSE; goto out; } ASSERT(zil_empty(zilog)); ret = B_TRUE; out: cv_broadcast(&zilog->zl_cv_writer); mutex_exit(&zilog->zl_lock); return (ret); }