Mercurial > illumos > illumos-gate
diff usr/src/uts/common/fs/zfs/spa.c @ 3912:f6891a60bd72
PSARC 2007/083 ZFS bootable datasets
4929890 ZFS Boot support for the x86 platform
6479807 pools need properties
6531774 reserve bits in directory entry for file type
author | lling |
---|---|
date | Wed, 28 Mar 2007 12:48:13 -0700 |
parents | 5340a4d98e0b |
children | 6674f5d79069 |
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/spa.c Wed Mar 28 12:00:22 2007 -0700 +++ b/usr/src/uts/common/fs/zfs/spa.c Wed Mar 28 12:48:13 2007 -0700 @@ -48,10 +48,13 @@ #include <sys/txg.h> #include <sys/avl.h> #include <sys/dmu_traverse.h> +#include <sys/dmu_objset.h> #include <sys/unique.h> #include <sys/dsl_pool.h> +#include <sys/dsl_dataset.h> #include <sys/dsl_dir.h> #include <sys/dsl_prop.h> +#include <sys/dsl_synctask.h> #include <sys/fs/zfs.h> #include <sys/callb.h> @@ -134,6 +137,7 @@ mutex_init(&spa->spa_config_lock.scl_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&spa->spa_sync_bplist.bpl_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&spa->spa_history_lock, NULL, MUTEX_DEFAULT, NULL); + mutex_init(&spa->spa_props_lock, NULL, MUTEX_DEFAULT, NULL); list_create(&spa->spa_dirty_list, sizeof (vdev_t), offsetof(vdev_t, vdev_dirty_node)); @@ -672,6 +676,23 @@ spa_config_exit(spa, FTAG); } + error = zap_lookup(spa->spa_meta_objset, DMU_POOL_DIRECTORY_OBJECT, + DMU_POOL_PROPS, sizeof (uint64_t), 1, &spa->spa_pool_props_object); + + if (error && error != ENOENT) { + vdev_set_state(rvd, B_TRUE, VDEV_STATE_CANT_OPEN, + VDEV_AUX_CORRUPT_DATA); + error = EIO; + goto out; + } + + if (error == 0) { + (void) zap_lookup(spa->spa_meta_objset, + spa->spa_pool_props_object, + zpool_prop_to_name(ZFS_PROP_BOOTFS), + sizeof (uint64_t), 1, &spa->spa_bootfs); + } + /* * Load the vdev state for all toplevel vdevs. */ @@ -1176,6 +1197,7 @@ dmu_tx_commit(tx); + spa->spa_bootfs = zfs_prop_default_numeric(ZFS_PROP_BOOTFS); spa->spa_sync_on = B_TRUE; txg_sync_start(spa->spa_dsl_pool); @@ -2815,6 +2837,43 @@ spa_sync_nvlist(spa, spa->spa_config_object, config, tx); } +static void +spa_sync_props(void *arg1, void *arg2, dmu_tx_t *tx) +{ + spa_t *spa = arg1; + nvlist_t *nvp = arg2; + nvpair_t *nvpair; + objset_t *mos = spa->spa_meta_objset; + uint64_t zapobj; + + mutex_enter(&spa->spa_props_lock); + if (spa->spa_pool_props_object == 0) { + zapobj = zap_create(mos, DMU_OT_POOL_PROPS, DMU_OT_NONE, 0, tx); + VERIFY(zapobj > 0); + + spa->spa_pool_props_object = zapobj; + + VERIFY(zap_update(mos, DMU_POOL_DIRECTORY_OBJECT, + DMU_POOL_PROPS, 8, 1, + &spa->spa_pool_props_object, tx) == 0); + } + mutex_exit(&spa->spa_props_lock); + + nvpair = NULL; + while ((nvpair = nvlist_next_nvpair(nvp, nvpair))) { + switch (zpool_name_to_prop(nvpair_name(nvpair))) { + case ZFS_PROP_BOOTFS: + VERIFY(nvlist_lookup_uint64(nvp, + nvpair_name(nvpair), &spa->spa_bootfs) == 0); + VERIFY(zap_update(mos, + spa->spa_pool_props_object, + zpool_prop_to_name(ZFS_PROP_BOOTFS), 8, 1, + &spa->spa_bootfs, tx) == 0); + break; + } + } +} + /* * Sync the specified transaction group. New blocks may be dirtied as * part of the process, so we iterate until it converges. @@ -3093,3 +3152,105 @@ return (B_FALSE); } + +int +spa_set_props(spa_t *spa, nvlist_t *nvp) +{ + return (dsl_sync_task_do(spa_get_dsl(spa), NULL, spa_sync_props, + spa, nvp, 3)); +} + +int +spa_get_props(spa_t *spa, nvlist_t **nvp) +{ + zap_cursor_t zc; + zap_attribute_t za; + objset_t *mos = spa->spa_meta_objset; + zfs_source_t src; + zfs_prop_t prop; + nvlist_t *propval; + uint64_t value; + int err; + + VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0); + + mutex_enter(&spa->spa_props_lock); + /* If no props object, then just return empty nvlist */ + if (spa->spa_pool_props_object == 0) { + mutex_exit(&spa->spa_props_lock); + return (0); + } + + for (zap_cursor_init(&zc, mos, spa->spa_pool_props_object); + (err = zap_cursor_retrieve(&zc, &za)) == 0; + zap_cursor_advance(&zc)) { + + if ((prop = zpool_name_to_prop(za.za_name)) == ZFS_PROP_INVAL) + continue; + + VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0); + switch (za.za_integer_length) { + case 8: + if (zfs_prop_default_numeric(prop) == + za.za_first_integer) + src = ZFS_SRC_DEFAULT; + else + src = ZFS_SRC_LOCAL; + value = za.za_first_integer; + + if (prop == ZFS_PROP_BOOTFS) { + dsl_pool_t *dp; + dsl_dataset_t *ds = NULL; + char strval[MAXPATHLEN]; + + dp = spa_get_dsl(spa); + rw_enter(&dp->dp_config_rwlock, RW_READER); + if ((err = dsl_dataset_open_obj(dp, + za.za_first_integer, NULL, DS_MODE_NONE, + FTAG, &ds)) != 0) { + rw_exit(&dp->dp_config_rwlock); + break; + } + dsl_dataset_name(ds, strval); + dsl_dataset_close(ds, DS_MODE_NONE, FTAG); + rw_exit(&dp->dp_config_rwlock); + + VERIFY(nvlist_add_uint64(propval, + ZFS_PROP_SOURCE, src) == 0); + VERIFY(nvlist_add_string(propval, + ZFS_PROP_VALUE, strval) == 0); + } else { + VERIFY(nvlist_add_uint64(propval, + ZFS_PROP_SOURCE, src) == 0); + VERIFY(nvlist_add_uint64(propval, + ZFS_PROP_VALUE, value) == 0); + } + VERIFY(nvlist_add_nvlist(*nvp, za.za_name, + propval) == 0); + break; + } + nvlist_free(propval); + } + zap_cursor_fini(&zc); + mutex_exit(&spa->spa_props_lock); + if (err && err != ENOENT) { + nvlist_free(*nvp); + return (err); + } + + return (0); +} + +/* + * If the bootfs property value is dsobj, clear it. + */ +void +spa_clear_bootfs(spa_t *spa, uint64_t dsobj, dmu_tx_t *tx) +{ + if (spa->spa_bootfs == dsobj && spa->spa_pool_props_object != 0) { + VERIFY(zap_remove(spa->spa_meta_objset, + spa->spa_pool_props_object, + zpool_prop_to_name(ZFS_PROP_BOOTFS), tx) == 0); + spa->spa_bootfs = 0; + } +}