X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=module%2Fzfs%2Fzfs_ioctl.c;h=a9184a1b61bdfb287818284ef4b2e5dca5be447f;hb=refs%2Fheads%2Frertzinger%2Ffeature-zpool-get--p;hp=c609203ea46d9f08c871daf7db07d21cc5a55f55;hpb=d5446cfc528262ae3a41da31a8524c9d2e793f45;p=zfs.git diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index c609203..a9184a1 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -18,6 +18,7 @@ * * CDDL HEADER END */ + /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Portions Copyright 2011 Martin Matuska @@ -26,6 +27,7 @@ * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. */ #include @@ -74,6 +76,8 @@ #include #include +#include + #include #include "zfs_namecheck.h" @@ -127,6 +131,12 @@ static int zfs_fill_zplprops_root(uint64_t, nvlist_t *, nvlist_t *, boolean_t *); int zfs_set_prop_nvlist(const char *, zprop_source_t, nvlist_t *, nvlist_t **); +static int zfs_prop_activate_feature(dsl_pool_t *dp, zfeature_info_t *feature); +static int zfs_prop_activate_feature_check(void *arg1, void *arg2, + dmu_tx_t *tx); +static void zfs_prop_activate_feature_sync(void *arg1, void *arg2, + dmu_tx_t *tx); + static void history_str_free(char *buf) { @@ -1107,6 +1117,8 @@ get_zfs_sb(const char *dsname, zfs_sb_t **zsbp) /* * Find a zfs_sb_t for a mounted filesystem, or create our own, in which * case its z_sb will be NULL, and it will be opened as the owner. + * If 'writer' is set, the z_teardown_lock will be held for RW_WRITER, + * which prevents all inode ops from running. */ static int zfs_sb_hold(const char *name, void *tag, zfs_sb_t **zsbp, boolean_t writer) @@ -1170,7 +1182,7 @@ zfs_ioc_pool_create(zfs_cmd_t *zc) (void) nvlist_lookup_uint64(props, zpool_prop_to_name(ZPOOL_PROP_VERSION), &version); - if (version < SPA_VERSION_INITIAL || version > SPA_VERSION) { + if (!SPA_VERSION_IS_SUPPORTED(version)) { error = EINVAL; goto pool_props_bad; } @@ -1256,9 +1268,6 @@ zfs_ioc_pool_import(zfs_cmd_t *zc) error = err; } - if (error == 0) - zvol_create_minors(zc->zc_name); - nvlist_free(config); if (props) @@ -1297,6 +1306,15 @@ zfs_ioc_pool_configs(zfs_cmd_t *zc) return (error); } +/* + * inputs: + * zc_name name of the pool + * + * outputs: + * zc_cookie real errno + * zc_nvlist_dst config nvlist + * zc_nvlist_dst_size size of config nvlist + */ static int zfs_ioc_pool_stats(zfs_cmd_t *zc) { @@ -1398,7 +1416,8 @@ zfs_ioc_pool_upgrade(zfs_cmd_t *zc) if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) return (error); - if (zc->zc_cookie < spa_version(spa) || zc->zc_cookie > SPA_VERSION) { + if (zc->zc_cookie < spa_version(spa) || + !SPA_VERSION_IS_SUPPORTED(zc->zc_cookie)) { spa_close(spa, FTAG); return (EINVAL); } @@ -1757,7 +1776,7 @@ zfs_ioc_objset_stats_impl(zfs_cmd_t *zc, objset_t *os) error = zvol_get_stats(os, nv); if (error == EIO) return (error); - VERIFY3S(error, ==, 0); + VERIFY0(error); } if (error == 0) error = put_nvlist(zc, nv); @@ -2162,6 +2181,9 @@ zfs_prop_set_special(const char *dsname, zprop_source_t source, case ZFS_PROP_VOLSIZE: err = zvol_set_volsize(dsname, intval); break; + case ZFS_PROP_SNAPDEV: + err = zvol_set_snapdev(dsname, intval); + break; case ZFS_PROP_VERSION: { zfs_sb_t *zsb; @@ -2183,6 +2205,40 @@ zfs_prop_set_special(const char *dsname, zprop_source_t source, } break; } + case ZFS_PROP_COMPRESSION: + { + if (intval == ZIO_COMPRESS_LZ4) { + zfeature_info_t *feature = + &spa_feature_table[SPA_FEATURE_LZ4_COMPRESS]; + spa_t *spa; + dsl_pool_t *dp; + + if ((err = spa_open(dsname, &spa, FTAG)) != 0) + return (err); + + dp = spa->spa_dsl_pool; + + /* + * Setting the LZ4 compression algorithm activates + * the feature. + */ + if (!spa_feature_is_active(spa, feature)) { + if ((err = zfs_prop_activate_feature(dp, + feature)) != 0) { + spa_close(spa, FTAG); + return (err); + } + } + + spa_close(spa, FTAG); + } + /* + * We still want the default set action to be performed in the + * caller, we only performed zfeature settings here. + */ + err = -1; + break; + } default: err = -1; @@ -3403,6 +3459,22 @@ zfs_check_settable(const char *dsname, nvpair_t *pair, cred_t *cr) SPA_VERSION_ZLE_COMPRESSION)) return (ENOTSUP); + if (intval == ZIO_COMPRESS_LZ4) { + zfeature_info_t *feature = + &spa_feature_table[ + SPA_FEATURE_LZ4_COMPRESS]; + spa_t *spa; + + if ((err = spa_open(dsname, &spa, FTAG)) != 0) + return (err); + + if (!spa_feature_is_enabled(spa, feature)) { + spa_close(spa, FTAG); + return (ENOTSUP); + } + spa_close(spa, FTAG); + } + /* * If this is a bootable dataset then * verify that the compression algorithm @@ -3449,6 +3521,56 @@ zfs_check_settable(const char *dsname, nvpair_t *pair, cred_t *cr) } /* + * Activates a feature on a pool in response to a property setting. This + * creates a new sync task which modifies the pool to reflect the feature + * as being active. + */ +static int +zfs_prop_activate_feature(dsl_pool_t *dp, zfeature_info_t *feature) +{ + int err; + + /* EBUSY here indicates that the feature is already active */ + err = dsl_sync_task_do(dp, zfs_prop_activate_feature_check, + zfs_prop_activate_feature_sync, dp->dp_spa, feature, 2); + + if (err != 0 && err != EBUSY) + return (err); + else + return (0); +} + +/* + * Checks for a race condition to make sure we don't increment a feature flag + * multiple times. + */ +/*ARGSUSED*/ +static int +zfs_prop_activate_feature_check(void *arg1, void *arg2, dmu_tx_t *tx) +{ + spa_t *spa = arg1; + zfeature_info_t *feature = arg2; + + if (!spa_feature_is_active(spa, feature)) + return (0); + else + return (EBUSY); +} + +/* + * The callback invoked on feature activation in the sync task caused by + * zfs_prop_activate_feature. + */ +static void +zfs_prop_activate_feature_sync(void *arg1, void *arg2, dmu_tx_t *tx) +{ + spa_t *spa = arg1; + zfeature_info_t *feature = arg2; + + spa_feature_incr(spa, feature, tx); +} + +/* * Removes properties from the given props list that fail permission checks * needed to clear them and to restore them in case of a receive error. For each * property, make sure we have both set and inherit permissions. @@ -5011,8 +5133,6 @@ zfsdev_state_init(struct file *filp) return (ENXIO); zs = kmem_zalloc( sizeof(zfsdev_state_t), KM_SLEEP); - if (zs == NULL) - return (ENOMEM); zs->zs_file = filp; zs->zs_minor = minor;