*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/arc.h>
#include <sys/ddt.h>
#include "zfs_prop.h"
+#include "zfeature_common.h"
/*
* SPA locking
* Like spa_vdev_enter/exit, these are convenience wrappers -- the actual
* locking is, always, based on spa_namespace_lock and spa_config_lock[].
*
- * spa_rename() is also implemented within this file since is requires
+ * spa_rename() is also implemented within this file since it requires
* manipulation of the namespace.
*/
ASSERT(MUTEX_HELD(&spa_namespace_lock));
- spa = kmem_zalloc(sizeof (spa_t), KM_SLEEP | KM_NODEBUG);
+ spa = kmem_zalloc(sizeof (spa_t), KM_PUSHPAGE | KM_NODEBUG);
mutex_init(&spa->spa_async_lock, NULL, MUTEX_DEFAULT, NULL);
mutex_init(&spa->spa_errlist_lock, NULL, MUTEX_DEFAULT, NULL);
list_create(&spa->spa_config_list, sizeof (spa_config_dirent_t),
offsetof(spa_config_dirent_t, scd_link));
- dp = kmem_zalloc(sizeof (spa_config_dirent_t), KM_SLEEP);
+ dp = kmem_zalloc(sizeof (spa_config_dirent_t), KM_PUSHPAGE);
dp->scd_path = altroot ? NULL : spa_strdup(spa_config_path);
list_insert_head(&spa->spa_config_list, dp);
VERIFY(nvlist_alloc(&spa->spa_load_info, NV_UNIQUE_NAME,
- KM_SLEEP) == 0);
+ KM_PUSHPAGE) == 0);
+
+ if (config != NULL) {
+ nvlist_t *features;
+
+ if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_FEATURES_FOR_READ,
+ &features) == 0) {
+ VERIFY(nvlist_dup(features, &spa->spa_label_features,
+ 0) == 0);
+ }
- if (config != NULL)
VERIFY(nvlist_dup(config, &spa->spa_config, 0) == 0);
+ }
+
+ if (spa->spa_label_features == NULL) {
+ VERIFY(nvlist_alloc(&spa->spa_label_features, NV_UNIQUE_NAME,
+ KM_SLEEP) == 0);
+ }
return (spa);
}
list_destroy(&spa->spa_config_list);
+ nvlist_free(spa->spa_label_features);
nvlist_free(spa->spa_load_info);
spa_config_set(spa, NULL);
if ((aux = avl_find(avl, &search, &where)) != NULL) {
aux->aux_count++;
} else {
- aux = kmem_zalloc(sizeof (spa_aux_t), KM_SLEEP);
+ aux = kmem_zalloc(sizeof (spa_aux_t), KM_PUSHPAGE);
aux->aux_guid = vd->vdev_guid;
aux->aux_count = 1;
avl_insert(avl, aux, where);
* ==========================================================================
*/
+void
+spa_activate_mos_feature(spa_t *spa, const char *feature)
+{
+ (void) nvlist_add_boolean(spa->spa_label_features, feature);
+ vdev_config_dirty(spa->spa_root_vdev);
+}
+
+void
+spa_deactivate_mos_feature(spa_t *spa, const char *feature)
+{
+ (void) nvlist_remove_all(spa->spa_label_features, feature);
+ vdev_config_dirty(spa->spa_root_vdev);
+}
+
/*
* Rename a spa_t.
*/
char *new;
len = strlen(s);
- new = kmem_alloc(len + 1, KM_SLEEP);
+ new = kmem_alloc(len + 1, KM_PUSHPAGE);
bcopy(s, new, len);
new[len] = '\0';
void
sprintf_blkptr(char *buf, const blkptr_t *bp)
{
- char *type = NULL;
+ char type[256];
char *checksum = NULL;
char *compress = NULL;
if (bp != NULL) {
- type = dmu_ot[BP_GET_TYPE(bp)].ot_name;
+ if (BP_GET_TYPE(bp) & DMU_OT_NEWTYPE) {
+ dmu_object_byteswap_t bswap =
+ DMU_OT_BYTESWAP(BP_GET_TYPE(bp));
+ (void) snprintf(type, sizeof (type), "bswap %s %s",
+ DMU_OT_IS_METADATA(BP_GET_TYPE(bp)) ?
+ "metadata" : "data",
+ dmu_ot_byteswap[bswap].ob_name);
+ } else {
+ (void) strlcpy(type, dmu_ot[BP_GET_TYPE(bp)].ot_name,
+ sizeof (type));
+ }
checksum = zio_checksum_table[BP_GET_CHECKSUM(bp)].ci_name;
compress = zio_compress_table[BP_GET_COMPRESS(bp)].ci_name;
}
return (spa->spa_dsl_pool);
}
+boolean_t
+spa_is_initializing(spa_t *spa)
+{
+ return (spa->spa_is_initializing);
+}
+
blkptr_t *
spa_get_rootblkptr(spa_t *spa)
{
uint64_t
spa_guid(spa_t *spa)
{
+ dsl_pool_t *dp = spa_get_dsl(spa);
+ uint64_t guid;
+
/*
* If we fail to parse the config during spa_load(), we can go through
* the error path (which posts an ereport) and end up here with no root
* vdev. We stash the original pool guid in 'spa_config_guid' to handle
* this case.
*/
- if (spa->spa_root_vdev != NULL)
+ if (spa->spa_root_vdev == NULL)
+ return (spa->spa_config_guid);
+
+ guid = spa->spa_last_synced_guid != 0 ?
+ spa->spa_last_synced_guid : spa->spa_root_vdev->vdev_guid;
+
+ /*
+ * Return the most recently synced out guid unless we're
+ * in syncing context.
+ */
+ if (dp && dsl_pool_sync_context(dp))
return (spa->spa_root_vdev->vdev_guid);
else
- return (spa->spa_config_guid);
+ return (guid);
}
uint64_t
vdev_cache_stat_init();
zfs_prop_init();
zpool_prop_init();
+ zpool_feature_init();
spa_config_load();
l2arc_start();
}