FreeBSD/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_errlog.c
/*
 * Sync the error log out to disk.  This is a little tricky because the act of
 * writing the error log requires the spa_errlist_lock.  So, we need to lock the
 * error lists, take a copy of the lists, and then reinitialize them.  Then, we
 * drop the error list lock and take the error log lock, at which point we
 * do the errlog processing.  Then, if we encounter an I/O error during this
 * process, we can successfully add the error to the list.  Note that this will
 * result in the perpetual recycling of errors, but it is an unlikely situation
 * and not a performance critical operation.
 */
Sync the error log out to disk.  This is a little tricky because the act of
writing the error log requires the spa_errlist_lock.  So, we need to lock the
error lists, take a copy of the lists, and then reinitialize them.  Then, we
drop the error list lock and take the error log lock, at which point we
do the errlog processing.  Then, if we encounter an I/O error during this
process, we can successfully add the error to the list.  Note that this will
result in the perpetual recycling of errors, but it is an unlikely situation
and not a performance critical operation.
Sync the error log out to disk . This is a little tricky because the act of writing the error log requires the spa_errlist_lock . So we need to lock the error lists take a copy of the lists and then reinitialize them . Then we drop the error list lock and take the error log lock at which point we do the errlog processing . Then if we encounter an I / O error during this process we can successfully add the error to the list . Note that this will result in the perpetual recycling of errors but it is an unlikely situation and not a performance critical operation .
void
spa_errlog_sync(spa_t *spa, uint64_t txg)
{
	dmu_tx_t *tx;
	avl_tree_t scrub, last;
	int scrub_finished;
	mutex_enter(&spa->spa_errlist_lock);
	if (avl_numnodes(&spa->spa_errlist_scrub) == 0 &&
	    avl_numnodes(&spa->spa_errlist_last) == 0 &&
	    !spa->spa_scrub_finished) {
		mutex_exit(&spa->spa_errlist_lock);
		return;
	}
	spa_get_errlists(spa, &last, &scrub);
	scrub_finished = spa->spa_scrub_finished;
	spa->spa_scrub_finished = B_FALSE;
	mutex_exit(&spa->spa_errlist_lock);
	mutex_enter(&spa->spa_errlog_lock);
	tx = dmu_tx_create_assigned(spa->spa_dsl_pool, txg);
	sync_error_list(spa, &last, &spa->spa_errlog_last, tx);
	if (scrub_finished) {
		if (spa->spa_errlog_last != 0)
			VERIFY(dmu_object_free(spa->spa_meta_objset,
			    spa->spa_errlog_last, tx) == 0);
		spa->spa_errlog_last = spa->spa_errlog_scrub;
		spa->spa_errlog_scrub = 0;
		sync_error_list(spa, &scrub, &spa->spa_errlog_last, tx);
	}
	sync_error_list(spa, &scrub, &spa->spa_errlog_scrub, tx);
	(void) zap_update(spa->spa_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
	    DMU_POOL_ERRLOG_LAST, sizeof (uint64_t), 1,
	    &spa->spa_errlog_last, tx);
	(void) zap_update(spa->spa_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
	    DMU_POOL_ERRLOG_SCRUB, sizeof (uint64_t), 1,
	    &spa->spa_errlog_scrub, tx);
	dmu_tx_commit(tx);
	mutex_exit(&spa->spa_errlog_lock);
}
void spa_errlog_sync ( spa_t * spa , uint64_t txg ) { dmu_tx_t * tx ; avl_tree_t scrub , last ; int scrub_finished ; mutex_enter ( & spa -> spa_errlist_lock ) ; if ( avl_numnodes ( & spa -> spa_errlist_scrub ) == 0 && avl_numnodes ( & spa -> spa_errlist_last ) == 0 && ! spa -> spa_scrub_finished ) { mutex_exit ( & spa -> spa_errlist_lock ) ; return ; } spa_get_errlists ( spa , & last , & scrub ) ; scrub_finished = spa -> spa_scrub_finished ; spa -> spa_scrub_finished = B_FALSE ; mutex_exit ( & spa -> spa_errlist_lock ) ; mutex_enter ( & spa -> spa_errlog_lock ) ; tx = dmu_tx_create_assigned ( spa -> spa_dsl_pool , txg ) ; sync_error_list ( spa , & last , & spa -> spa_errlog_last , tx ) ; if ( scrub_finished ) { if ( spa -> spa_errlog_last != 0 ) VERIFY ( dmu_object_free ( spa -> spa_meta_objset , spa -> spa_errlog_last , tx ) == 0 ) ; spa -> spa_errlog_last = spa -> spa_errlog_scrub ; spa -> spa_errlog_scrub = 0 ; sync_error_list ( spa , & scrub , & spa -> spa_errlog_last , tx ) ; } sync_error_list ( spa , & scrub , & spa -> spa_errlog_scrub , tx ) ; ( void ) zap_update ( spa -> spa_meta_objset , DMU_POOL_DIRECTORY_OBJECT , DMU_POOL_ERRLOG_LAST , sizeof ( uint64_t ) , 1 , & spa -> spa_errlog_last , tx ) ; ( void ) zap_update ( spa -> spa_meta_objset , DMU_POOL_DIRECTORY_OBJECT , DMU_POOL_ERRLOG_SCRUB , sizeof ( uint64_t ) , 1 , & spa -> spa_errlog_scrub , tx ) ; dmu_tx_commit ( tx ) ; mutex_exit ( & spa -> spa_errlog_lock ) ; }
Sync the error log out to disk.
Sync the error log out to disk .
/*
	 * Bail out early under normal circumstances.
	 */ /*
	 * Sync out the current list of errors.
	 */ /*
	 * Rotate the log if necessary.
	 */ /*
	 * Sync out any pending scrub errors.
	 */ /*
	 * Update the MOS to reflect the new values.
	 */