Пример #1
0
static int libzfs_update_stats(zfs_handle_t *p_zfs)
{
        objset_t *p_os;
        nvlist_t *pnv_allprops, *pnv_userprops;
        int i_error;

        if((i_error = dmu_objset_hold(p_zfs->zfs_name, FTAG, &p_os)))
                return i_error;

        dmu_objset_fast_stat(p_os, &p_zfs->zfs_dmustats);

        if((i_error = dsl_prop_get_all(p_os, &pnv_allprops)) == 0)
        {
                dmu_objset_stats(p_os, pnv_allprops);
                if(!p_zfs->zfs_dmustats.dds_inconsistent)
                {
                        if(dmu_objset_type(p_os) == DMU_OST_ZVOL)
                                assert(zvol_get_stats(p_os, pnv_allprops) == 0);
                }
        }

        dmu_objset_rele(p_os, FTAG);

        // Continue processing the stats
        if((pnv_userprops = process_user_props(p_zfs, pnv_allprops)) == NULL)
        {
                nvlist_free(pnv_allprops);
                return 1;
        }

        nvlist_free(p_zfs->zfs_props);
        nvlist_free(p_zfs->zfs_user_props);

        p_zfs->zfs_props = pnv_allprops;
        p_zfs->zfs_user_props = pnv_userprops;

        return 0;
}
Пример #2
0
/*
 * dsl_crypto_key_unload
 *
 * Remove the key from the in memory keystore.
 *
 * First we have to remove the minor node for a ZVOL or unmount
 * the filesystem.  This is so that we flush all pending IO for it to disk
 * so we won't need to encrypt anything with this key.  Anything in flight
 * should already have a lock on the keys it needs.
 * We can't assume that userland has already successfully unmounted the
 * dataset though in many cases it will have.
 *
 * If the key can't be removed return the failure back to our caller.
 */
int
dsl_crypto_key_unload(const char *dsname)
{
    dsl_dataset_t *ds;
    objset_t *os;
    int error;
    spa_t *spa;
    dsl_pool_t *dp;
#ifdef _KERNEL
    dmu_objset_type_t os_type;
    //vfs_t *vfsp;
    struct vfsmount *vfsp;
#endif /* _KERNEL */

    error = dsl_pool_hold(dsname, FTAG, &dp);
    if (error != 0)
        return (error);

    /* XXX - should we use own_exclusive() here? */
    if ((error = dsl_dataset_hold(dp, dsname, FTAG, &ds)) != 0) {
        dsl_pool_rele(dp, FTAG);
        return (error);
    }

    if ((error = dmu_objset_from_ds(ds, &os)) != 0) {
        dsl_dataset_rele(ds, FTAG);
        dsl_pool_rele(dp, FTAG);
        return (error);
    }

#ifdef _KERNEL
    /*
     * Make sure that the device node has gone for ZVOLs
     * and that filesystems are umounted.
     */
#if 0 // FIXME
    os_type = dmu_objset_type(os);
    if (os_type == DMU_OST_ZVOL) {
        error = zvol_remove_minor(dsname);
        if (error == ENXIO)
            error = 0;
    } else if (os_type == DMU_OST_ZFS) {
        vfsp = zfs_get_vfs(dsname);
        if (vfsp != NULL) {
            error = vn_vfswlock(vfsp->vfs_vnodecovered);
            VFS_RELE(vfsp);
            if (error == 0)
                error = dounmount(vfsp, 0, CRED());
        }
    }
    if (error != 0) {
        dsl_dataset_rele(ds, FTAG);
        return (error);
    }
#endif

#endif /* _KERNEL */

    /*
     * Make sure all dbufs are synced.
     *
     * It is essential for encrypted datasets to ensure that
     * there is no further pending IO before removing the key.
     */
    if (dmu_objset_is_dirty(os, 0)) // FIXME, 0?
        txg_wait_synced(dmu_objset_pool(os), 0);
    dmu_objset_evict_dbufs(os);

    spa = dsl_dataset_get_spa(ds);
    error = zcrypt_keystore_remove(spa, ds->ds_object);

    dsl_dataset_rele(ds, FTAG);
    dsl_pool_rele(dp, FTAG);
    return (error);
}
Пример #3
0
int
sa_setup(objset_t *os, uint64_t sa_obj, sa_attr_reg_t *reg_attrs, int count,
    sa_attr_type_t **user_table)
{
	zap_cursor_t zc;
	zap_attribute_t za;
	sa_os_t *sa;
	dmu_objset_type_t ostype = dmu_objset_type(os);
	sa_attr_type_t *tb;
	int error;

	mutex_enter(&os->os_lock);
	if (os->os_sa) {
		mutex_enter(&os->os_sa->sa_lock);
		mutex_exit(&os->os_lock);
		tb = os->os_sa->sa_user_table;
		mutex_exit(&os->os_sa->sa_lock);
		*user_table = tb;
		return (0);
	}

	sa = kmem_zalloc(sizeof (sa_os_t), KM_SLEEP);
	mutex_init(&sa->sa_lock, NULL, MUTEX_DEFAULT, NULL);
	sa->sa_master_obj = sa_obj;

	os->os_sa = sa;
	mutex_enter(&sa->sa_lock);
	mutex_exit(&os->os_lock);
	avl_create(&sa->sa_layout_num_tree, layout_num_compare,
	    sizeof (sa_lot_t), offsetof(sa_lot_t, lot_num_node));
	avl_create(&sa->sa_layout_hash_tree, layout_hash_compare,
	    sizeof (sa_lot_t), offsetof(sa_lot_t, lot_hash_node));

	if (sa_obj) {
		error = zap_lookup(os, sa_obj, SA_LAYOUTS,
		    8, 1, &sa->sa_layout_attr_obj);
		if (error != 0 && error != ENOENT)
			goto fail;
		error = zap_lookup(os, sa_obj, SA_REGISTRY,
		    8, 1, &sa->sa_reg_attr_obj);
		if (error != 0 && error != ENOENT)
			goto fail;
	}

	if ((error = sa_attr_table_setup(os, reg_attrs, count)) != 0)
		goto fail;

	if (sa->sa_layout_attr_obj != 0) {
		uint64_t layout_count;

		error = zap_count(os, sa->sa_layout_attr_obj,
		    &layout_count);

		/*
		 * Layout number count should be > 0
		 */
		if (error || (error == 0 && layout_count == 0)) {
			if (error == 0)
				error = EINVAL;
			goto fail;
		}

		for (zap_cursor_init(&zc, os, sa->sa_layout_attr_obj);
		    (error = zap_cursor_retrieve(&zc, &za)) == 0;
		    zap_cursor_advance(&zc)) {
			sa_attr_type_t *lot_attrs;
			uint64_t lot_num;

			lot_attrs = kmem_zalloc(sizeof (sa_attr_type_t) *
			    za.za_num_integers, KM_SLEEP);

			if ((error = (zap_lookup(os, sa->sa_layout_attr_obj,
			    za.za_name, 2, za.za_num_integers,
			    lot_attrs))) != 0) {
				kmem_free(lot_attrs, sizeof (sa_attr_type_t) *
				    za.za_num_integers);
				break;
			}
			VERIFY(ddi_strtoull(za.za_name, NULL, 10,
			    (unsigned long long *)&lot_num) == 0);

			(void) sa_add_layout_entry(os, lot_attrs,
			    za.za_num_integers, lot_num,
			    sa_layout_info_hash(lot_attrs,
			    za.za_num_integers), B_FALSE, NULL);
			kmem_free(lot_attrs, sizeof (sa_attr_type_t) *
			    za.za_num_integers);
		}
		zap_cursor_fini(&zc);

		/*
		 * Make sure layout count matches number of entries added
		 * to AVL tree
		 */
		if (avl_numnodes(&sa->sa_layout_num_tree) != layout_count) {
			ASSERT(error != 0);
			goto fail;
		}
	}

	/* Add special layout number for old ZNODES */
	if (ostype == DMU_OST_ZFS) {
		(void) sa_add_layout_entry(os, sa_legacy_zpl_layout,
		    sa_legacy_attr_count, 0,
		    sa_layout_info_hash(sa_legacy_zpl_layout,
		    sa_legacy_attr_count), B_FALSE, NULL);

		(void) sa_add_layout_entry(os, sa_dummy_zpl_layout, 0, 1,
		    0, B_FALSE, NULL);
	}
	*user_table = os->os_sa->sa_user_table;
	mutex_exit(&sa->sa_lock);
	return (0);
fail:
	os->os_sa = NULL;
	sa_free_attr_table(sa);
	if (sa->sa_user_table)
		kmem_free(sa->sa_user_table, sa->sa_user_table_sz);
	mutex_exit(&sa->sa_lock);
	kmem_free(sa, sizeof (sa_os_t));
	return ((error == ECKSUM) ? EIO : error);
}
Пример #4
0
static int
sa_attr_table_setup(objset_t *os, sa_attr_reg_t *reg_attrs, int count)
{
	sa_os_t *sa = os->os_sa;
	uint64_t sa_attr_count = 0;
	uint64_t sa_reg_count;
	int error = 0;
	uint64_t attr_value;
	sa_attr_table_t *tb;
	zap_cursor_t zc;
	zap_attribute_t za;
	int registered_count = 0;
	int i;
	dmu_objset_type_t ostype = dmu_objset_type(os);

	sa->sa_user_table =
	    kmem_zalloc(count * sizeof (sa_attr_type_t), KM_SLEEP);
	sa->sa_user_table_sz = count * sizeof (sa_attr_type_t);

	if (sa->sa_reg_attr_obj != 0) {
		error = zap_count(os, sa->sa_reg_attr_obj,
		    &sa_attr_count);

		/*
		 * Make sure we retrieved a count and that it isn't zero
		 */
		if (error || (error == 0 && sa_attr_count == 0)) {
			if (error == 0)
				error = EINVAL;
			goto bail;
		}
		sa_reg_count = sa_attr_count;
	}

	if (ostype == DMU_OST_ZFS && sa_attr_count == 0)
		sa_attr_count += sa_legacy_attr_count;

	/* Allocate attribute numbers for attributes that aren't registered */
	for (i = 0; i != count; i++) {
		boolean_t found = B_FALSE;
		int j;

		if (ostype == DMU_OST_ZFS) {
			for (j = 0; j != sa_legacy_attr_count; j++) {
				if (strcmp(reg_attrs[i].sa_name,
				    sa_legacy_attrs[j].sa_name) == 0) {
					sa->sa_user_table[i] =
					    sa_legacy_attrs[j].sa_attr;
					found = B_TRUE;
				}
			}
		}
		if (found)
			continue;

		if (sa->sa_reg_attr_obj)
			error = zap_lookup(os, sa->sa_reg_attr_obj,
			    reg_attrs[i].sa_name, 8, 1, &attr_value);
		else
			error = ENOENT;
		switch (error) {
		case ENOENT:
			sa->sa_user_table[i] = (sa_attr_type_t)sa_attr_count;
			sa_attr_count++;
			break;
		case 0:
			sa->sa_user_table[i] = ATTR_NUM(attr_value);
			break;
		default:
			goto bail;
		}
	}

	sa->sa_num_attrs = sa_attr_count;
	tb = sa->sa_attr_table =
	    kmem_zalloc(sizeof (sa_attr_table_t) * sa_attr_count, KM_SLEEP);

	/*
	 * Attribute table is constructed from requested attribute list,
	 * previously foreign registered attributes, and also the legacy
	 * ZPL set of attributes.
	 */

	if (sa->sa_reg_attr_obj) {
		for (zap_cursor_init(&zc, os, sa->sa_reg_attr_obj);
		    (error = zap_cursor_retrieve(&zc, &za)) == 0;
		    zap_cursor_advance(&zc)) {
			uint64_t value;
			value  = za.za_first_integer;

			registered_count++;
			tb[ATTR_NUM(value)].sa_attr = ATTR_NUM(value);
			tb[ATTR_NUM(value)].sa_length = ATTR_LENGTH(value);
			tb[ATTR_NUM(value)].sa_byteswap = ATTR_BSWAP(value);
			tb[ATTR_NUM(value)].sa_registered = B_TRUE;

			if (tb[ATTR_NUM(value)].sa_name) {
				continue;
			}
			tb[ATTR_NUM(value)].sa_name =
			    kmem_zalloc(strlen(za.za_name) +1, KM_SLEEP);
			(void) strlcpy(tb[ATTR_NUM(value)].sa_name, za.za_name,
			    strlen(za.za_name) +1);
		}
		zap_cursor_fini(&zc);
		/*
		 * Make sure we processed the correct number of registered
		 * attributes
		 */
		if (registered_count != sa_reg_count) {
			ASSERT(error != 0);
			goto bail;
		}

	}

	if (ostype == DMU_OST_ZFS) {
		for (i = 0; i != sa_legacy_attr_count; i++) {
			if (tb[i].sa_name)
				continue;
			tb[i].sa_attr = sa_legacy_attrs[i].sa_attr;
			tb[i].sa_length = sa_legacy_attrs[i].sa_length;
			tb[i].sa_byteswap = sa_legacy_attrs[i].sa_byteswap;
			tb[i].sa_registered = B_FALSE;
			tb[i].sa_name =
			    kmem_zalloc(strlen(sa_legacy_attrs[i].sa_name) +1,
			    KM_SLEEP);
			(void) strlcpy(tb[i].sa_name,
			    sa_legacy_attrs[i].sa_name,
			    strlen(sa_legacy_attrs[i].sa_name) + 1);
		}
	}

	for (i = 0; i != count; i++) {
		sa_attr_type_t attr_id;

		attr_id = sa->sa_user_table[i];
		if (tb[attr_id].sa_name)
			continue;

		tb[attr_id].sa_length = reg_attrs[i].sa_length;
		tb[attr_id].sa_byteswap = reg_attrs[i].sa_byteswap;
		tb[attr_id].sa_attr = attr_id;
		tb[attr_id].sa_name =
		    kmem_zalloc(strlen(reg_attrs[i].sa_name) + 1, KM_SLEEP);
		(void) strlcpy(tb[attr_id].sa_name, reg_attrs[i].sa_name,
		    strlen(reg_attrs[i].sa_name) + 1);
	}

	sa->sa_need_attr_registration =
	    (sa_attr_count != registered_count);

	return (0);
bail:
	kmem_free(sa->sa_user_table, count * sizeof (sa_attr_type_t));
	sa->sa_user_table = NULL;
	sa_free_attr_table(sa);
	return ((error != 0) ? error : EINVAL);
}