示例#1
0
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);
}
示例#2
0
文件: zil.c 项目: harshada/zfs
/*
 * 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);
}