mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-24 11:18:52 +03:00
Illumos 4370, 4371
4370 avoid transmitting holes during zfs send 4371 DMU code clean up Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: George Wilson <george.wilson@delphix.com> Reviewed by: Christopher Siden <christopher.siden@delphix.com> Reviewed by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net> Approved by: Garrett D'Amore <garrett@damore.org>a References: https://www.illumos.org/issues/4370 https://www.illumos.org/issues/4371 https://github.com/illumos/illumos-gate/commit/43466aa Ported by: Tim Chase <tim@chase2k.com> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #2529
This commit is contained in:
committed by
Brian Behlendorf
parent
fa86b5dbb6
commit
b0bc7a84d9
+109
-13
@@ -224,12 +224,32 @@ spa_features_check(spa_t *spa, boolean_t for_write,
|
||||
}
|
||||
|
||||
/*
|
||||
* Use an in-memory cache of feature refcounts for quick retrieval.
|
||||
*
|
||||
* Note: well-designed features will not need to use this; they should
|
||||
* use spa_feature_is_enabled() and spa_feature_is_active() instead.
|
||||
* However, this is non-static for zdb and zhack.
|
||||
*/
|
||||
int
|
||||
feature_get_refcount(spa_t *spa, zfeature_info_t *feature, uint64_t *res)
|
||||
{
|
||||
ASSERT(VALID_FEATURE_FID(feature->fi_feature));
|
||||
if (spa->spa_feat_refcount_cache[feature->fi_feature] ==
|
||||
SPA_FEATURE_DISABLED) {
|
||||
return (SET_ERROR(ENOTSUP));
|
||||
}
|
||||
*res = spa->spa_feat_refcount_cache[feature->fi_feature];
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: well-designed features will not need to use this; they should
|
||||
* use spa_feature_is_enabled() and spa_feature_is_active() instead.
|
||||
* However, this is non-static for zdb and zhack.
|
||||
*/
|
||||
int
|
||||
feature_get_refcount_from_disk(spa_t *spa, zfeature_info_t *feature,
|
||||
uint64_t *res)
|
||||
{
|
||||
int err;
|
||||
uint64_t refcount;
|
||||
@@ -255,6 +275,26 @@ feature_get_refcount(spa_t *spa, zfeature_info_t *feature, uint64_t *res)
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
feature_get_enabled_txg(spa_t *spa, zfeature_info_t *feature, uint64_t *res) {
|
||||
ASSERTV(uint64_t enabled_txg_obj = spa->spa_feat_enabled_txg_obj);
|
||||
|
||||
ASSERT(zfeature_depends_on(feature->fi_feature,
|
||||
SPA_FEATURE_ENABLED_TXG));
|
||||
|
||||
if (!spa_feature_is_enabled(spa, feature->fi_feature)) {
|
||||
return (SET_ERROR(ENOTSUP));
|
||||
}
|
||||
|
||||
ASSERT(enabled_txg_obj != 0);
|
||||
|
||||
VERIFY0(zap_lookup(spa->spa_meta_objset, spa->spa_feat_enabled_txg_obj,
|
||||
feature->fi_guid, sizeof (uint64_t), 1, res));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is non-static for zhack; it should otherwise not be used
|
||||
* outside this file.
|
||||
@@ -263,16 +303,32 @@ void
|
||||
feature_sync(spa_t *spa, zfeature_info_t *feature, uint64_t refcount,
|
||||
dmu_tx_t *tx)
|
||||
{
|
||||
uint64_t zapobj = feature->fi_can_readonly ?
|
||||
spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj;
|
||||
uint64_t zapobj;
|
||||
|
||||
ASSERT(VALID_FEATURE_OR_NONE(feature->fi_feature));
|
||||
zapobj = feature->fi_can_readonly ?
|
||||
spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj;
|
||||
VERIFY0(zap_update(spa->spa_meta_objset, zapobj, feature->fi_guid,
|
||||
sizeof (uint64_t), 1, &refcount, tx));
|
||||
|
||||
/*
|
||||
* feature_sync is called directly from zhack, allowing the
|
||||
* creation of arbitrary features whose fi_feature field may
|
||||
* be greater than SPA_FEATURES. When called from zhack, the
|
||||
* zfeature_info_t object's fi_feature field will be set to
|
||||
* SPA_FEATURE_NONE.
|
||||
*/
|
||||
if (feature->fi_feature != SPA_FEATURE_NONE) {
|
||||
uint64_t *refcount_cache =
|
||||
&spa->spa_feat_refcount_cache[feature->fi_feature];
|
||||
VERIFY3U(*refcount_cache, ==,
|
||||
atomic_swap_64(refcount_cache, refcount));
|
||||
}
|
||||
|
||||
if (refcount == 0)
|
||||
spa_deactivate_mos_feature(spa, feature->fi_guid);
|
||||
else if (feature->fi_mos)
|
||||
spa_activate_mos_feature(spa, feature->fi_guid);
|
||||
spa_activate_mos_feature(spa, feature->fi_guid, tx);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -282,6 +338,7 @@ feature_sync(spa_t *spa, zfeature_info_t *feature, uint64_t refcount,
|
||||
void
|
||||
feature_enable_sync(spa_t *spa, zfeature_info_t *feature, dmu_tx_t *tx)
|
||||
{
|
||||
uint64_t initial_refcount = feature->fi_activate_on_enable ? 1 : 0;
|
||||
uint64_t zapobj = feature->fi_can_readonly ?
|
||||
spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj;
|
||||
int i;
|
||||
@@ -302,27 +359,43 @@ feature_enable_sync(spa_t *spa, zfeature_info_t *feature, dmu_tx_t *tx)
|
||||
VERIFY0(zap_update(spa->spa_meta_objset, spa->spa_feat_desc_obj,
|
||||
feature->fi_guid, 1, strlen(feature->fi_desc) + 1,
|
||||
feature->fi_desc, tx));
|
||||
feature_sync(spa, feature, 0, tx);
|
||||
|
||||
feature_sync(spa, feature, initial_refcount, tx);
|
||||
|
||||
if (spa_feature_is_enabled(spa, SPA_FEATURE_ENABLED_TXG)) {
|
||||
uint64_t enabling_txg = dmu_tx_get_txg(tx);
|
||||
|
||||
if (spa->spa_feat_enabled_txg_obj == 0ULL) {
|
||||
spa->spa_feat_enabled_txg_obj =
|
||||
zap_create_link(spa->spa_meta_objset,
|
||||
DMU_OTN_ZAP_METADATA, DMU_POOL_DIRECTORY_OBJECT,
|
||||
DMU_POOL_FEATURE_ENABLED_TXG, tx);
|
||||
}
|
||||
spa_feature_incr(spa, SPA_FEATURE_ENABLED_TXG, tx);
|
||||
|
||||
VERIFY0(zap_add(spa->spa_meta_objset,
|
||||
spa->spa_feat_enabled_txg_obj, feature->fi_guid,
|
||||
sizeof (uint64_t), 1, &enabling_txg, tx));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
feature_do_action(spa_t *spa, spa_feature_t fid, feature_action_t action,
|
||||
dmu_tx_t *tx)
|
||||
{
|
||||
uint64_t refcount;
|
||||
uint64_t refcount = 0;
|
||||
zfeature_info_t *feature = &spa_feature_table[fid];
|
||||
uint64_t zapobj = feature->fi_can_readonly ?
|
||||
spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj;
|
||||
ASSERTV(uint64_t zapobj = feature->fi_can_readonly ?
|
||||
spa->spa_feat_for_write_obj : spa->spa_feat_for_read_obj);
|
||||
|
||||
ASSERT3U(fid, <, SPA_FEATURES);
|
||||
ASSERT(VALID_FEATURE_FID(fid));
|
||||
ASSERT(0 != zapobj);
|
||||
ASSERT(zfeature_is_valid_guid(feature->fi_guid));
|
||||
|
||||
ASSERT(dmu_tx_is_syncing(tx));
|
||||
ASSERT3U(spa_version(spa), >=, SPA_VERSION_FEATURES);
|
||||
|
||||
VERIFY0(zap_lookup(spa->spa_meta_objset, zapobj, feature->fi_guid,
|
||||
sizeof (uint64_t), 1, &refcount));
|
||||
VERIFY3U(feature_get_refcount(spa, feature, &refcount), !=, ENOTSUP);
|
||||
|
||||
switch (action) {
|
||||
case FEATURE_ACTION_INCR:
|
||||
@@ -369,7 +442,7 @@ void
|
||||
spa_feature_enable(spa_t *spa, spa_feature_t fid, dmu_tx_t *tx)
|
||||
{
|
||||
ASSERT3U(spa_version(spa), >=, SPA_VERSION_FEATURES);
|
||||
ASSERT3U(fid, <, SPA_FEATURES);
|
||||
ASSERT(VALID_FEATURE_FID(fid));
|
||||
feature_enable_sync(spa, &spa_feature_table[fid], tx);
|
||||
}
|
||||
|
||||
@@ -391,7 +464,7 @@ spa_feature_is_enabled(spa_t *spa, spa_feature_t fid)
|
||||
int err;
|
||||
uint64_t refcount = 0;
|
||||
|
||||
ASSERT3U(fid, <, SPA_FEATURES);
|
||||
ASSERT(VALID_FEATURE_FID(fid));
|
||||
if (spa_version(spa) < SPA_VERSION_FEATURES)
|
||||
return (B_FALSE);
|
||||
|
||||
@@ -406,7 +479,7 @@ spa_feature_is_active(spa_t *spa, spa_feature_t fid)
|
||||
int err;
|
||||
uint64_t refcount = 0;
|
||||
|
||||
ASSERT3U(fid, <, SPA_FEATURES);
|
||||
ASSERT(VALID_FEATURE_FID(fid));
|
||||
if (spa_version(spa) < SPA_VERSION_FEATURES)
|
||||
return (B_FALSE);
|
||||
|
||||
@@ -414,3 +487,26 @@ spa_feature_is_active(spa_t *spa, spa_feature_t fid)
|
||||
ASSERT(err == 0 || err == ENOTSUP);
|
||||
return (err == 0 && refcount > 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* For the feature specified by fid (which must depend on
|
||||
* SPA_FEATURE_ENABLED_TXG), return the TXG at which it was enabled in the
|
||||
* OUT txg argument.
|
||||
*
|
||||
* Returns B_TRUE if the feature is enabled, in which case txg will be filled
|
||||
* with the transaction group in which the specified feature was enabled.
|
||||
* Returns B_FALSE otherwise (i.e. if the feature is not enabled).
|
||||
*/
|
||||
boolean_t
|
||||
spa_feature_enabled_txg(spa_t *spa, spa_feature_t fid, uint64_t *txg) {
|
||||
int err;
|
||||
|
||||
ASSERT(VALID_FEATURE_FID(fid));
|
||||
if (spa_version(spa) < SPA_VERSION_FEATURES)
|
||||
return (B_FALSE);
|
||||
|
||||
err = feature_get_enabled_txg(spa, &spa_feature_table[fid], txg);
|
||||
ASSERT(err == 0 || err == ENOTSUP);
|
||||
|
||||
return (err == 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user