Example #1
0
File: zvol.c Project: Oliverlyn/zfs
static int
zvol_first_open(zvol_state_t *zv)
{
	objset_t *os;
	uint64_t volsize;
	int error;
	uint64_t ro;

	/* lie and say we're read-only */
	error = dmu_objset_own(zv->zv_name, DMU_OST_ZVOL, 1, zvol_tag, &os);
	if (error)
		return (SET_ERROR(-error));

	zv->zv_objset = os;

	error = dsl_prop_get_integer(zv->zv_name, "readonly", &ro, NULL);
	if (error)
		goto out_owned;

	error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize);
	if (error)
		goto out_owned;

	error = dmu_bonus_hold(os, ZVOL_OBJ, zvol_tag, &zv->zv_dbuf);
	if (error)
		goto out_owned;

	set_capacity(zv->zv_disk, volsize >> 9);
	zv->zv_volsize = volsize;
	zv->zv_zilog = zil_open(os, zvol_get_data);

	if (ro || dmu_objset_is_snapshot(os) ||
	    !spa_writeable(dmu_objset_spa(os))) {
		set_disk_ro(zv->zv_disk, 1);
		zv->zv_flags |= ZVOL_RDONLY;
	} else {
		set_disk_ro(zv->zv_disk, 0);
		zv->zv_flags &= ~ZVOL_RDONLY;
	}

out_owned:
	if (error) {
		dmu_objset_disown(os, zvol_tag);
		zv->zv_objset = NULL;
	}

	return (SET_ERROR(-error));
}
Example #2
0
static int osd_zap_it_rec(const struct lu_env *env, const struct dt_it *di,
			  struct dt_rec *dtrec, __u32 attr)
{
	struct luz_direntry *zde = &osd_oti_get(env)->oti_zde;
	zap_attribute_t     *za = &osd_oti_get(env)->oti_za;
	struct osd_zap_it   *it = (struct osd_zap_it *)di;
	struct lu_dirent    *lde = (struct lu_dirent *)dtrec;
	int                  rc, namelen;
	ENTRY;

	it->ozi_reset = 0;
	LASSERT(lde);

	lde->lde_hash = cpu_to_le64(udmu_zap_cursor_serialize(it->ozi_zc));

	if ((rc = -zap_cursor_retrieve(it->ozi_zc, za)))
		GOTO(out, rc);

	namelen = strlen(za->za_name);
	if (namelen > NAME_MAX)
		GOTO(out, rc = -EOVERFLOW);
	strcpy(lde->lde_name, za->za_name);
	lde->lde_namelen = cpu_to_le16(namelen);

	if (za->za_integer_length != 8 || za->za_num_integers < 3) {
		CERROR("%s: unsupported direntry format: %d %d\n",
		       osd_obj2dev(it->ozi_obj)->od_svname,
		       za->za_integer_length, (int)za->za_num_integers);

		GOTO(out, rc = -EIO);
	}

	rc = -zap_lookup(it->ozi_zc->zc_objset, it->ozi_zc->zc_zapobj,
			 za->za_name, za->za_integer_length, 3, zde);
	if (rc)
		GOTO(out, rc);

	lde->lde_fid = zde->lzd_fid;
	lde->lde_attrs = LUDA_FID;

	/* append lustre attributes */
	osd_it_append_attrs(lde, attr, namelen, zde->lzd_reg.zde_type);

	lde->lde_reclen = cpu_to_le16(lu_dirent_calc_size(namelen, attr));

out:
	RETURN(rc);
}
Example #3
0
/*
 * zfs_match_find() is used by zfs_dirent_lock() to peform zap lookups
 * of names after deciding which is the appropriate lookup interface.
 */
static int
zfs_match_find(zfsvfs_t *zfsvfs, znode_t *dzp, char *name, matchtype_t mt,
    boolean_t update, int *deflags, pathname_t *rpnp, uint64_t *zoid)
{
	boolean_t conflict = B_FALSE;
	int error;

	if (zfsvfs->z_norm) {
		size_t bufsz = 0;
		char *buf = NULL;

		if (rpnp) {
			buf = rpnp->pn_buf;
			bufsz = rpnp->pn_bufsize;
		}

		/*
		 * In the non-mixed case we only expect there would ever
		 * be one match, but we need to use the normalizing lookup.
		 */
		error = zap_lookup_norm(zfsvfs->z_os, dzp->z_id, name, 8, 1,
		    zoid, mt, buf, bufsz, &conflict);
	} else {
		error = zap_lookup(zfsvfs->z_os, dzp->z_id, name, 8, 1, zoid);
	}

	/*
	 * Allow multiple entries provided the first entry is
	 * the object id.  Non-zpl consumers may safely make
	 * use of the additional space.
	 *
	 * XXX: This should be a feature flag for compatibility
	 */
	if (error == EOVERFLOW)
		error = 0;

	if (zfsvfs->z_norm && !error && deflags)
		*deflags = conflict ? ED_CASE_CONFLICT : 0;

	*zoid = ZFS_DIRENT_OBJ(*zoid);

#ifdef HAVE_DNLC
	if (error == ENOENT && update)
		dnlc_update(ZTOI(dzp), name, DNLC_NO_VNODE);
#endif /* HAVE_DNLC */

	return (error);
}
Example #4
0
int osd_xattrs_destroy(const struct lu_env *env,
		       struct osd_object *obj, struct osd_thandle *oh)
{
	struct osd_device *osd = osd_obj2dev(obj);
	dmu_tx_t	  *tx = oh->ot_tx;
	zap_attribute_t	  *za = &osd_oti_get(env)->oti_za;
	zap_cursor_t	  *zc;
	uint64_t	   xid;
	int		   rc;

	/* The transaction must have been assigned to a transaction group. */
	LASSERT(tx->tx_txg != 0);

	if (obj->oo_xattr == ZFS_NO_OBJECT)
		return 0; /* Nothing to do for SA xattrs */

	/* Free the ZAP holding the xattrs */
	rc = osd_zap_cursor_init(&zc, osd->od_os, obj->oo_xattr, 0);
	if (rc)
		return rc;

	while (zap_cursor_retrieve(zc, za) == 0) {
		LASSERT(za->za_num_integers == 1);
		LASSERT(za->za_integer_length == sizeof(uint64_t));

		rc = -zap_lookup(osd->od_os, obj->oo_xattr, za->za_name,
				 sizeof(uint64_t), 1, &xid);
		if (rc) {
			CERROR("%s: lookup xattr %s failed: rc = %d\n",
			       osd->od_svname, za->za_name, rc);
		} else {
			rc = -dmu_object_free(osd->od_os, xid, tx);
			if (rc)
				CERROR("%s: free xattr %s failed: rc = %d\n",
				       osd->od_svname, za->za_name, rc);
		}
		zap_cursor_advance(zc);
	}
	osd_zap_cursor_fini(zc);

	rc = -dmu_object_free(osd->od_os, obj->oo_xattr, tx);
	if (rc)
		CERROR("%s: free xattr "LPU64" failed: rc = %d\n",
		       osd->od_svname, obj->oo_xattr, rc);

	return rc;
}
Example #5
0
/*
 * Delete a DMU object
 *
 * The transaction passed to this routine must have
 * dmu_tx_hold_free(tx, oid, 0, DMU_OBJECT_END) called
 * and then assigned to a transaction group.
 *
 * This will release db and set it to NULL to prevent further dbuf releases.
 */
static int __osd_object_destroy(const struct lu_env *env,
				struct osd_object *obj,
				dmu_tx_t *tx, void *tag)
{
	struct osd_device	*osd = osd_obj2dev(obj);
	udmu_objset_t		*uos = &osd->od_objset;
	uint64_t		 xid;
	zap_attribute_t		*za = &osd_oti_get(env)->oti_za;
	zap_cursor_t		*zc;
	int			 rc;

	/* Assert that the transaction has been assigned to a
	   transaction group. */
	LASSERT(tx->tx_txg != 0);

	/* zap holding xattrs */
	if (obj->oo_xattr != ZFS_NO_OBJECT) {
		rc = -udmu_zap_cursor_init(&zc, uos, obj->oo_xattr, 0);
		if (rc)
			return rc;
		while ((rc = -zap_cursor_retrieve(zc, za)) == 0) {
			BUG_ON(za->za_integer_length != sizeof(uint64_t));
			BUG_ON(za->za_num_integers != 1);

			rc = -zap_lookup(uos->os, obj->oo_xattr, za->za_name,
					 sizeof(uint64_t), 1, &xid);
			if (rc) {
				CERROR("%s: lookup xattr %s failed: rc = %d\n",
				       osd->od_svname, za->za_name, rc);
				continue;
			}
			rc = __osd_object_free(uos, xid, tx);
			if (rc)
				CERROR("%s: fetch xattr %s failed: rc = %d\n",
				       osd->od_svname, za->za_name, rc);
			zap_cursor_advance(zc);
		}
		udmu_zap_cursor_fini(zc);

		rc = __osd_object_free(uos, obj->oo_xattr, tx);
		if (rc)
			CERROR("%s: freeing xattr failed: rc = %d\n",
			       osd->od_svname, rc);
	}

	return __osd_object_free(uos, obj->oo_db->db_object, tx);
}
static void
vdev_initialize_load(vdev_t *vd)
{
	ASSERT(spa_config_held(vd->vdev_spa, SCL_CONFIG, RW_READER) ||
	    spa_config_held(vd->vdev_spa, SCL_CONFIG, RW_WRITER));
	ASSERT(vd->vdev_leaf_zap != 0);

	if (vd->vdev_initialize_state == VDEV_INITIALIZE_ACTIVE ||
	    vd->vdev_initialize_state == VDEV_INITIALIZE_SUSPENDED) {
		int err = zap_lookup(vd->vdev_spa->spa_meta_objset,
		    vd->vdev_leaf_zap, VDEV_LEAF_ZAP_INITIALIZE_LAST_OFFSET,
		    sizeof (vd->vdev_initialize_last_offset), 1,
		    &vd->vdev_initialize_last_offset);
		ASSERT(err == 0 || err == ENOENT);
	}

	vdev_initialize_calculate_progress(vd);
}
Example #7
0
int
zvol_get_stats(zfs_cmd_t *zc, objset_t *os)
{
	int error;
	dmu_object_info_t doi;

	error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &zc->zc_volsize);

	if (error)
		return (error);

	error = dmu_object_info(os, ZVOL_OBJ, &doi);

	if (error == 0)
		zc->zc_volblocksize = doi.doi_data_block_size;

	return (error);
}
Example #8
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);
}
Example #9
0
static void
dsl_deleg_set_sync(void *arg, dmu_tx_t *tx)
{
    dsl_deleg_arg_t *dda = arg;
    dsl_dir_t *dd;
    dsl_pool_t *dp = dmu_tx_pool(tx);
    objset_t *mos = dp->dp_meta_objset;
    nvpair_t *whopair = NULL;
    uint64_t zapobj;

    VERIFY0(dsl_dir_hold(dp, dda->dda_name, FTAG, &dd, NULL));

    zapobj = dd->dd_phys->dd_deleg_zapobj;
    if (zapobj == 0) {
        dmu_buf_will_dirty(dd->dd_dbuf, tx);
        zapobj = dd->dd_phys->dd_deleg_zapobj = zap_create(mos,
                                                DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx);
    }

    while ((whopair = nvlist_next_nvpair(dda->dda_nvlist, whopair))) {
        const char *whokey = nvpair_name(whopair);
        nvlist_t *perms;
        nvpair_t *permpair = NULL;
        uint64_t jumpobj;

        perms = fnvpair_value_nvlist(whopair);

        if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0) {
            jumpobj = zap_create_link(mos, DMU_OT_DSL_PERMS,
                                      zapobj, whokey, tx);
        }

        while ((permpair = nvlist_next_nvpair(perms, permpair))) {
            const char *perm = nvpair_name(permpair);
            uint64_t n = 0;

            VERIFY(zap_update(mos, jumpobj,
                              perm, 8, 1, &n, tx) == 0);
            spa_history_log_internal_dd(dd, "permission update", tx,
                                        "%s %s", whokey, perm);
        }
    }
    dsl_dir_rele(dd, FTAG);
}
int
dsl_prop_get_ds(dsl_dataset_t *ds, const char *propname,
    int intsz, int numint, void *buf, char *setpoint)
{
	ASSERT(RW_LOCK_HELD(&ds->ds_dir->dd_pool->dp_config_rwlock));

	if (ds->ds_phys->ds_props_obj) {
		int err = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset,
		    ds->ds_phys->ds_props_obj, propname, intsz, numint, buf);
		if (err != ENOENT) {
			if (setpoint)
				dsl_dataset_name(ds, setpoint);
			return (err);
		}
	}

	return (dsl_prop_get_dd(ds->ds_dir, propname,
	    intsz, numint, buf, setpoint));
}
Example #11
0
static void
dsl_deleg_set_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx)
{
	dsl_dir_t *dd = arg1;
	nvlist_t *nvp = arg2;
	objset_t *mos = dd->dd_pool->dp_meta_objset;
	nvpair_t *whopair = NULL;
	uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj;

	if (zapobj == 0) {
		dmu_buf_will_dirty(dd->dd_dbuf, tx);
		zapobj = dd->dd_phys->dd_deleg_zapobj = zap_create(mos,
		    DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx);
	}

	while (whopair = nvlist_next_nvpair(nvp, whopair)) {
		const char *whokey = nvpair_name(whopair);
		nvlist_t *perms;
		nvpair_t *permpair = NULL;
		uint64_t jumpobj;

		VERIFY(nvpair_value_nvlist(whopair, &perms) == 0);

		if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0) {
			jumpobj = zap_create(mos, DMU_OT_DSL_PERMS,
			    DMU_OT_NONE, 0, tx);
			VERIFY(zap_update(mos, zapobj,
			    whokey, 8, 1, &jumpobj, tx) == 0);
		}

		while (permpair = nvlist_next_nvpair(perms, permpair)) {
			const char *perm = nvpair_name(permpair);
			uint64_t n = 0;

			VERIFY(zap_update(mos, jumpobj,
			    perm, 8, 1, &n, tx) == 0);
			spa_history_internal_log(LOG_DS_PERM_UPDATE,
			    dd->dd_pool->dp_spa, tx, cr,
			    "%s %s dataset = %llu", whokey, perm,
			    dd->dd_phys->dd_head_dataset_obj);
		}
	}
}
Example #12
0
static int osd_dir_lookup(const struct lu_env *env, struct dt_object *dt,
			  struct dt_rec *rec, const struct dt_key *key,
			  struct lustre_capa *capa)
{
	struct osd_thread_info *oti = osd_oti_get(env);
	struct osd_object  *obj = osd_dt_obj(dt);
	struct osd_device  *osd = osd_obj2dev(obj);
	int                 rc;
	ENTRY;

	LASSERT(udmu_object_is_zap(obj->oo_db));

	rc = -zap_lookup(osd->od_objset.os, obj->oo_db->db_object,
			 (char *)key, 8, sizeof(oti->oti_zde) / 8,
			 (void *)&oti->oti_zde);
	memcpy(rec, &oti->oti_zde.lzd_fid, sizeof(struct lu_fid));

	RETURN(rc == 0 ? 1 : rc);
}
Example #13
0
static int
dsl_dataset_user_release_check_one(dsl_dataset_t *ds,
    nvlist_t *holds, boolean_t *todelete)
{
	uint64_t zapobj;
	nvpair_t *pair;
	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
	int error;
	int numholds = 0;

	*todelete = B_FALSE;

	if (!dsl_dataset_is_snapshot(ds))
		return (EINVAL);

	zapobj = ds->ds_phys->ds_userrefs_obj;
	if (zapobj == 0)
		return (ESRCH);

	for (pair = nvlist_next_nvpair(holds, NULL); pair != NULL;
	    pair = nvlist_next_nvpair(holds, pair)) {
		/* Make sure the hold exists */
		uint64_t tmp;
		error = zap_lookup(mos, zapobj, nvpair_name(pair), 8, 1, &tmp);
		if (error == ENOENT)
			error = ESRCH;
		if (error != 0)
			return (error);
		numholds++;
	}

	if (DS_IS_DEFER_DESTROY(ds) && ds->ds_phys->ds_num_children == 1 &&
	    ds->ds_userrefs == numholds) {
		/* we need to destroy the snapshot as well */

		if (dsl_dataset_long_held(ds))
			return (EBUSY);
		*todelete = B_TRUE;
	}
	return (0);
}
Example #14
0
void osd_declare_xattrs_destroy(const struct lu_env *env,
				struct osd_object *obj, struct osd_thandle *oh)
{
	struct osd_device *osd = osd_obj2dev(obj);
	zap_attribute_t	  *za = &osd_oti_get(env)->oti_za;
	uint64_t	   oid = obj->oo_xattr, xid;
	dmu_tx_t	  *tx = oh->ot_tx;
	zap_cursor_t	  *zc;
	int		   rc;

	if (oid == ZFS_NO_OBJECT)
		return; /* Nothing to do for SA xattrs */

	/* Declare to free the ZAP holding xattrs */
	dmu_tx_hold_free(tx, oid, 0, DMU_OBJECT_END);

	rc = osd_zap_cursor_init(&zc, osd->od_os, oid, 0);
	if (rc)
		goto out;

	while (zap_cursor_retrieve(zc, za) == 0) {
		LASSERT(za->za_num_integers == 1);
		LASSERT(za->za_integer_length == sizeof(uint64_t));

		rc = -zap_lookup(osd->od_os, oid, za->za_name,
				 sizeof(uint64_t), 1, &xid);
		if (rc) {
			CERROR("%s: xattr %s lookup failed: rc = %d\n",
			       osd->od_svname, za->za_name, rc);
			break;
		}
		dmu_tx_hold_free(tx, xid, 0, DMU_OBJECT_END);

		zap_cursor_advance(zc);
	}

	osd_zap_cursor_fini(zc);
out:
	if (rc && tx->tx_err == 0)
		tx->tx_err = -rc;
}
Example #15
0
/*
 * Checks that the features active in the specified object are supported by
 * this software.  Adds each unsupported feature (name -> description) to
 * the supplied nvlist.
 */
boolean_t
feature_is_supported(objset_t *os, uint64_t obj, uint64_t desc_obj,
                     nvlist_t *unsup_feat, nvlist_t *enabled_feat)
{
    boolean_t supported;
    zap_cursor_t zc;
    zap_attribute_t za;

    supported = B_TRUE;
    for (zap_cursor_init(&zc, os, obj);
            zap_cursor_retrieve(&zc, &za) == 0;
            zap_cursor_advance(&zc)) {
        ASSERT(za.za_integer_length == sizeof (uint64_t) &&
               za.za_num_integers == 1);

        if (NULL != enabled_feat) {
            fnvlist_add_uint64(enabled_feat, za.za_name,
                               za.za_first_integer);
        }

        if (za.za_first_integer != 0 &&
                !zfeature_is_supported(za.za_name)) {
            supported = B_FALSE;

            if (NULL != unsup_feat) {
                char *desc = "";
                char buf[MAXPATHLEN];

                if (zap_lookup(os, desc_obj, za.za_name,
                               1, sizeof (buf), buf) == 0)
                    desc = buf;

                VERIFY(nvlist_add_string(unsup_feat, za.za_name,
                                         desc) == 0);
            }
        }
    }
    zap_cursor_fini(&zc);

    return (supported);
}
int
dsl_prop_get_dd(dsl_dir_t *dd, const char *propname,
    int intsz, int numint, void *buf, char *setpoint)
{
	int err = ENOENT;
	objset_t *mos = dd->dd_pool->dp_meta_objset;
	zfs_prop_t prop;

	ASSERT(RW_LOCK_HELD(&dd->dd_pool->dp_config_rwlock));

	if (setpoint)
		setpoint[0] = '\0';

	prop = zfs_name_to_prop(propname);

	/*
	 * Note: dd may be NULL, therefore we shouldn't dereference it
	 * ouside this loop.
	 */
	for (; dd != NULL; dd = dd->dd_parent) {
		ASSERT(RW_LOCK_HELD(&dd->dd_pool->dp_config_rwlock));
		err = zap_lookup(mos, dd->dd_phys->dd_props_zapobj,
		    propname, intsz, numint, buf);
		if (err != ENOENT) {
			if (setpoint)
				dsl_dir_name(dd, setpoint);
			break;
		}

		/*
		 * Break out of this loop for non-inheritable properties.
		 */
		if (prop != ZPROP_INVAL && !zfs_prop_inheritable(prop))
			break;
	}
	if (err == ENOENT)
		err = dodefault(propname, intsz, numint, buf);

	return (err);
}
Example #17
0
/*ARGSUSED*/
static int
dmu_objset_create_check(void *arg1, void *arg2, dmu_tx_t *tx)
{
	dsl_dir_t *dd = arg1;
	struct oscarg *oa = arg2;
	objset_t *mos = dd->dd_pool->dp_meta_objset;
	int err;
	uint64_t ddobj;
    static boolean_t dp_config_rwlock_held = B_TRUE;

	err = zap_lookup(mos, dd->dd_phys->dd_child_dir_zapobj,
	    oa->lastname, sizeof (uint64_t), 1, &ddobj);
	if (err != ENOENT)
		return (err ? err : EEXIST);

	if (oa->clone_origin != NULL) {
		/* You can't clone across pools. */
		if (oa->clone_origin->ds_dir->dd_pool != dd->dd_pool)
			return (EXDEV);

		/* You can only clone snapshots, not the head datasets. */
		if (!dsl_dataset_is_snapshot(oa->clone_origin))
			return (EINVAL);

        if (dsl_dataset_keystatus(oa->clone_origin,
            dp_config_rwlock_held) == ZFS_CRYPT_KEY_UNAVAILABLE)
            return (ENOKEY);
	}

    /*
     * Check we have the required crypto algorithms available
     * via kcf since this is our last chance to fail the dataset creation.
     */
    if (oa->crypto_ctx != NULL &&
        !zcrypt_mech_available(oa->crypto_ctx->dcc_crypt)) {
        return (ENOTSUP);
    }

	return (0);
}
Example #18
0
/*
 * zfs_match_find() is used by zfs_dirent_lookup() to peform zap lookups
 * of names after deciding which is the appropriate lookup interface.
 */
static int
zfs_match_find(zfsvfs_t *zfsvfs, znode_t *dzp, const char *name,
               boolean_t exact, uint64_t *zoid)
{
    int error;

    if (zfsvfs->z_norm) {
        matchtype_t mt = exact? MT_EXACT : MT_FIRST;

        /*
         * In the non-mixed case we only expect there would ever
         * be one match, but we need to use the normalizing lookup.
         */
        error = zap_lookup_norm(zfsvfs->z_os, dzp->z_id, name, 8, 1,
                                zoid, mt, NULL, 0, NULL);
    } else {
        error = zap_lookup(zfsvfs->z_os, dzp->z_id, name, 8, 1, zoid);
    }
    *zoid = ZFS_DIRENT_OBJ(*zoid);

    return (error);
}
Example #19
0
int
zvol_get_stats(objset_t *os, nvlist_t *nv)
{
	int error;
	dmu_object_info_t doi;
	uint64_t val;

	error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &val);
	if (error)
		return (error);

	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_VOLSIZE, val);

	error = dmu_object_info(os, ZVOL_OBJ, &doi);

	if (error == 0) {
		dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_VOLBLOCKSIZE,
		    doi.doi_data_block_size);
	}

	return (error);
}
Example #20
0
int
dsl_pool_open_special_dir(dsl_pool_t *dp, const char *name, dsl_dir_t **ddp)
{
	uint64_t obj;
	int err;
#if 0
    printf("  +dsl_pool_open_special_dir: '%s'\n", name ? name : "(null)");
    printf("   dp %p\n", dp);
    printf("   dp->meta %p\n", dp->dp_meta_objset);
    printf("   dp->root %p\n", dp->dp_root_dir);
    printf("   dp->root->phys %p\n", dp->dp_root_dir->dd_phys);
    printf("   dp->root->phys->zap %p\n", dp->dp_root_dir->dd_phys->dd_child_dir_zapobj);
#endif

	err = zap_lookup(dp->dp_meta_objset,
	    dsl_dir_phys(dp->dp_root_dir)->dd_child_dir_zapobj,
	    name, sizeof (obj), 1, &obj);
	if (err)
		return (err);

	return (dsl_dir_hold_obj(dp, obj, name, dp, ddp));
}
Example #21
0
/*
 * zfs_match_find() is used by zfs_dirent_lock() to peform zap lookups
 * of names after deciding which is the appropriate lookup interface.
 */
static int
zfs_match_find(zfs_sb_t *zsb, znode_t *dzp, char *name, boolean_t exact,
               boolean_t update, int *deflags, pathname_t *rpnp, uint64_t *zoid)
{
    int error;

    if (zsb->z_norm) {
        matchtype_t mt = MT_FIRST;
        boolean_t conflict = B_FALSE;
        size_t bufsz = 0;
        char *buf = NULL;

        if (rpnp) {
            buf = rpnp->pn_buf;
            bufsz = rpnp->pn_bufsize;
        }
        if (exact)
            mt = MT_EXACT;
        /*
         * In the non-mixed case we only expect there would ever
         * be one match, but we need to use the normalizing lookup.
         */
        error = zap_lookup_norm(zsb->z_os, dzp->z_id, name, 8, 1,
                                zoid, mt, buf, bufsz, &conflict);
        if (!error && deflags)
            *deflags = conflict ? ED_CASE_CONFLICT : 0;
    } else {
        error = zap_lookup(zsb->z_os, dzp->z_id, name, 8, 1, zoid);
    }
    *zoid = ZFS_DIRENT_OBJ(*zoid);

#ifdef HAVE_DNLC
    if (error == ENOENT && update)
        dnlc_update(ZTOI(dzp), name, DNLC_NO_VNODE);
#endif /* HAVE_DNLC */

    return (error);
}
/*
 * Read a property stored within the master node.
 */
int
zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
{
	const char *pname;
	int error = ENOENT;

	/*
	 * Look up the file system's value for the property.  For the
	 * version property, we look up a slightly different string.
	 */
	if (prop == ZFS_PROP_VERSION)
		pname = ZPL_VERSION_STR;
	else
		pname = zfs_prop_to_name(prop);

	if (os != NULL)
		error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value);

	if (error == ENOENT) {
		/* No value set, use the default value */
		switch (prop) {
		case ZFS_PROP_VERSION:
			*value = ZPL_VERSION;
			break;
		case ZFS_PROP_NORMALIZE:
		case ZFS_PROP_UTF8ONLY:
			*value = 0;
			break;
		case ZFS_PROP_CASE:
			*value = ZFS_CASE_SENSITIVE;
			break;
		default:
			return (error);
		}
		error = 0;
	}
	return (error);
}
Example #23
0
/*
 * Load the fuid table(s) into memory.
 */
static void
zfs_fuid_init(zfsvfs_t *zfsvfs)
{
	rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER);

	if (zfsvfs->z_fuid_loaded) {
		rw_exit(&zfsvfs->z_fuid_lock);
		return;
	}

	zfs_fuid_avl_tree_create(&zfsvfs->z_fuid_idx, &zfsvfs->z_fuid_domain);

	(void) zap_lookup(zfsvfs->z_os, MASTER_NODE_OBJ,
	    ZFS_FUID_TABLES, 8, 1, &zfsvfs->z_fuid_obj);
	if (zfsvfs->z_fuid_obj != 0) {
		zfsvfs->z_fuid_size = zfs_fuid_table_load(zfsvfs->z_os,
		    zfsvfs->z_fuid_obj, &zfsvfs->z_fuid_idx,
		    &zfsvfs->z_fuid_domain);
	}

	zfsvfs->z_fuid_loaded = B_TRUE;
	rw_exit(&zfsvfs->z_fuid_lock);
}
/*
 * Load the fuid table(s) into memory.
 */
static void
zfs_fuid_init(zfsvfs_t *zfsvfs, dmu_tx_t *tx)
{
    int error = 0;

    rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER);

    if (zfsvfs->z_fuid_loaded) {
        rw_exit(&zfsvfs->z_fuid_lock);
        return;
    }

    if (zfsvfs->z_fuid_obj == 0) {

        /* first make sure we need to allocate object */

        error = zap_lookup(zfsvfs->z_os, MASTER_NODE_OBJ,
                           ZFS_FUID_TABLES, 8, 1, &zfsvfs->z_fuid_obj);
        if (error == ENOENT && tx != NULL) {
            zfsvfs->z_fuid_obj = dmu_object_alloc(zfsvfs->z_os,
                                                  DMU_OT_FUID, 1 << 14, DMU_OT_FUID_SIZE,
                                                  sizeof (uint64_t), tx);
            VERIFY(zap_add(zfsvfs->z_os, MASTER_NODE_OBJ,
                           ZFS_FUID_TABLES, sizeof (uint64_t), 1,
                           &zfsvfs->z_fuid_obj, tx) == 0);
        }
    }

    if (zfsvfs->z_fuid_obj != 0) {
        zfsvfs->z_fuid_size = zfs_fuid_table_load(zfsvfs->z_os,
                              zfsvfs->z_fuid_obj, &zfsvfs->z_fuid_idx,
                              &zfsvfs->z_fuid_domain);
        zfsvfs->z_fuid_loaded = B_TRUE;
    }

    rw_exit(&zfsvfs->z_fuid_lock);
}
Example #25
0
int
zfs_userspace_one(zfs_sb_t *zsb, zfs_userquota_prop_t type,
    const char *domain, uint64_t rid, uint64_t *valp)
{
	char buf[20 + DMU_OBJACCT_PREFIX_LEN];
	int offset = 0;
	int err;
	uint64_t obj;

	*valp = 0;

	if (!dmu_objset_userspace_present(zsb->z_os))
		return (SET_ERROR(ENOTSUP));

	if ((type == ZFS_PROP_USEROBJUSED || type == ZFS_PROP_GROUPOBJUSED ||
	    type == ZFS_PROP_USEROBJQUOTA || type == ZFS_PROP_GROUPOBJQUOTA) &&
	    !dmu_objset_userobjspace_present(zsb->z_os))
		return (SET_ERROR(ENOTSUP));

	obj = zfs_userquota_prop_to_obj(zsb, type);
	if (obj == ZFS_NO_OBJECT)
		return (0);

	if (type == ZFS_PROP_USEROBJUSED || type == ZFS_PROP_GROUPOBJUSED) {
		strlcpy(buf, DMU_OBJACCT_PREFIX, DMU_OBJACCT_PREFIX_LEN);
		offset = DMU_OBJACCT_PREFIX_LEN;
	}

	err = id_to_fuidstr(zsb, domain, rid, buf + offset, B_FALSE);
	if (err)
		return (err);

	err = zap_lookup(zsb->z_os, obj, buf, 8, 1, valp);
	if (err == ENOENT)
		err = 0;
	return (err);
}
Example #26
0
static void
__osd_xattr_declare_del(const struct lu_env *env, struct osd_object *obj,
			const char *name, struct osd_thandle *oh)
{
	struct osd_device *osd = osd_obj2dev(obj);
	udmu_objset_t     *uos = &osd->od_objset;
	dmu_tx_t          *tx = oh->ot_tx;
	uint64_t           xa_data_obj;
	int                rc;

	/* update SA_ZPL_DXATTR if xattr was in SA */
	dmu_tx_hold_sa(tx, obj->oo_sa_hdl, 0);

	if (obj->oo_xattr == ZFS_NO_OBJECT)
		return;

	rc = -zap_lookup(uos->os, obj->oo_xattr, name, 8, 1, &xa_data_obj);
	if (rc == 0) {
		/*
		 * Entry exists.
		 * We'll delete the existing object and ZAP entry.
		 */
		dmu_tx_hold_bonus(tx, xa_data_obj);
		dmu_tx_hold_free(tx, xa_data_obj, 0, DMU_OBJECT_END);
		dmu_tx_hold_zap(tx, obj->oo_xattr, FALSE, (char *) name);
		return;
	} else if (rc == -ENOENT) {
		/*
		 * Entry doesn't exist, nothing to be changed.
		 */
		return;
	}

	/* An error happened */
	tx->tx_err = -rc;
}
Example #27
0
File: zvol.c Project: alek-p/zfs
/*
 * ZFS_IOC_OBJSET_STATS entry point.
 */
int
zvol_get_stats(objset_t *os, nvlist_t *nv)
{
	int error;
	dmu_object_info_t *doi;
	uint64_t val;

	error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &val);
	if (error)
		return (SET_ERROR(error));

	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_VOLSIZE, val);
	doi = kmem_alloc(sizeof (dmu_object_info_t), KM_SLEEP);
	error = dmu_object_info(os, ZVOL_OBJ, doi);

	if (error == 0) {
		dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_VOLBLOCKSIZE,
		    doi->doi_data_block_size);
	}

	kmem_free(doi, sizeof (dmu_object_info_t));

	return (SET_ERROR(error));
}
Example #28
0
static int __osd_xattr_del(const struct lu_env *env, struct osd_object *obj,
			   const char *name, struct osd_thandle *oh)
{
	struct osd_device *osd = osd_obj2dev(obj);
	uint64_t           xa_data_obj;
	int                rc;

	if (unlikely(!dt_object_exists(&obj->oo_dt) || obj->oo_destroyed))
		return -ENOENT;

	/* try remove xattr from SA at first */
	rc = __osd_sa_xattr_del(env, obj, name, oh);
	if (rc != -ENOENT)
		return rc;

	if (obj->oo_xattr == ZFS_NO_OBJECT)
		return 0;

	rc = -zap_lookup(osd->od_os, obj->oo_xattr, name, sizeof(uint64_t), 1,
			&xa_data_obj);
	if (rc == -ENOENT) {
		rc = 0;
	} else if (rc == 0) {
		/*
		 * Entry exists.
		 * We'll delete the existing object and ZAP entry.
		 */
		rc = -dmu_object_free(osd->od_os, xa_data_obj, oh->ot_tx);
		if (rc)
			return rc;

		rc = -zap_remove(osd->od_os, obj->oo_xattr, name, oh->ot_tx);
	}

	return rc;
}
Example #29
0
int
dsl_dir_hold_obj(dsl_pool_t *dp, uint64_t ddobj,
    const char *tail, void *tag, dsl_dir_t **ddp)
{
	dmu_buf_t *dbuf;
	dsl_dir_t *dd;
	int err;

	ASSERT(dsl_pool_config_held(dp));

	err = dmu_bonus_hold(dp->dp_meta_objset, ddobj, tag, &dbuf);
	if (err != 0)
		return (err);
	dd = dmu_buf_get_user(dbuf);
#ifdef ZFS_DEBUG
	{
		dmu_object_info_t doi;
		dmu_object_info_from_db(dbuf, &doi);
		ASSERT3U(doi.doi_bonus_type, ==, DMU_OT_DSL_DIR);
		ASSERT3U(doi.doi_bonus_size, >=, sizeof (dsl_dir_phys_t));
	}
#endif
	if (dd == NULL) {
		dsl_dir_t *winner;

		dd = kmem_zalloc(sizeof (dsl_dir_t), KM_SLEEP);
		dd->dd_object = ddobj;
		dd->dd_dbuf = dbuf;
		dd->dd_pool = dp;
		dd->dd_phys = dbuf->db_data;
		mutex_init(&dd->dd_lock, NULL, MUTEX_DEFAULT, NULL);

		list_create(&dd->dd_prop_cbs, sizeof (dsl_prop_cb_record_t),
		    offsetof(dsl_prop_cb_record_t, cbr_node));

		dsl_dir_snap_cmtime_update(dd);

		if (dd->dd_phys->dd_parent_obj) {
			err = dsl_dir_hold_obj(dp, dd->dd_phys->dd_parent_obj,
			    NULL, dd, &dd->dd_parent);
			if (err != 0)
				goto errout;
			if (tail) {
#ifdef ZFS_DEBUG
				uint64_t foundobj;

				err = zap_lookup(dp->dp_meta_objset,
				    dd->dd_parent->dd_phys->dd_child_dir_zapobj,
				    tail, sizeof (foundobj), 1, &foundobj);
				ASSERT(err || foundobj == ddobj);
#endif
				(void) strcpy(dd->dd_myname, tail);
			} else {
				err = zap_value_search(dp->dp_meta_objset,
				    dd->dd_parent->dd_phys->dd_child_dir_zapobj,
				    ddobj, 0, dd->dd_myname);
			}
			if (err != 0)
				goto errout;
		} else {
			(void) strcpy(dd->dd_myname, spa_name(dp->dp_spa));
		}

		if (dsl_dir_is_clone(dd)) {
			dmu_buf_t *origin_bonus;
			dsl_dataset_phys_t *origin_phys;

			/*
			 * We can't open the origin dataset, because
			 * that would require opening this dsl_dir.
			 * Just look at its phys directly instead.
			 */
			err = dmu_bonus_hold(dp->dp_meta_objset,
			    dd->dd_phys->dd_origin_obj, FTAG, &origin_bonus);
			if (err != 0)
				goto errout;
			origin_phys = origin_bonus->db_data;
			dd->dd_origin_txg =
			    origin_phys->ds_creation_txg;
			dmu_buf_rele(origin_bonus, FTAG);
		}

		winner = dmu_buf_set_user_ie(dbuf, dd, &dd->dd_phys,
		    dsl_dir_evict);
		if (winner) {
			if (dd->dd_parent)
				dsl_dir_rele(dd->dd_parent, dd);
			mutex_destroy(&dd->dd_lock);
			kmem_free(dd, sizeof (dsl_dir_t));
			dd = winner;
		} else {
			spa_open_ref(dp->dp_spa, dd);
		}
	}

	/*
	 * The dsl_dir_t has both open-to-close and instantiate-to-evict
	 * holds on the spa.  We need the open-to-close holds because
	 * otherwise the spa_refcnt wouldn't change when we open a
	 * dir which the spa also has open, so we could incorrectly
	 * think it was OK to unload/export/destroy the pool.  We need
	 * the instantiate-to-evict hold because the dsl_dir_t has a
	 * pointer to the dd_pool, which has a pointer to the spa_t.
	 */
	spa_open_ref(dp->dp_spa, tag);
	ASSERT3P(dd->dd_pool, ==, dp);
	ASSERT3U(dd->dd_object, ==, ddobj);
	ASSERT3P(dd->dd_dbuf, ==, dbuf);
	*ddp = dd;
	return (0);

errout:
	if (dd->dd_parent)
		dsl_dir_rele(dd->dd_parent, dd);
	mutex_destroy(&dd->dd_lock);
	kmem_free(dd, sizeof (dsl_dir_t));
	dmu_buf_rele(dbuf, tag);
	return (err);
}
Example #30
0
/*
 * Return the dsl_dir_t, and possibly the last component which couldn't
 * be found in *tail.  The name must be in the specified dsl_pool_t.  This
 * thread must hold the dp_config_rwlock for the pool.  Returns NULL if the
 * path is bogus, or if tail==NULL and we couldn't parse the whole name.
 * (*tail)[0] == '@' means that the last component is a snapshot.
 */
int
dsl_dir_hold(dsl_pool_t *dp, const char *name, void *tag,
    dsl_dir_t **ddp, const char **tailp)
{
	char buf[MAXNAMELEN];
	const char *spaname, *next, *nextnext = NULL;
	int err;
	dsl_dir_t *dd;
	uint64_t ddobj;

	err = getcomponent(name, buf, &next);
	if (err != 0)
		return (err);

	/* Make sure the name is in the specified pool. */
	spaname = spa_name(dp->dp_spa);
	if (strcmp(buf, spaname) != 0)
		return (SET_ERROR(EINVAL));

	ASSERT(dsl_pool_config_held(dp));

	err = dsl_dir_hold_obj(dp, dp->dp_root_dir_obj, NULL, tag, &dd);
	if (err != 0) {
		return (err);
	}

	while (next != NULL) {
		dsl_dir_t *child_ds;
		err = getcomponent(next, buf, &nextnext);
		if (err != 0)
			break;
		ASSERT(next[0] != '\0');
		if (next[0] == '@')
			break;
		dprintf("looking up %s in obj%lld\n",
		    buf, dd->dd_phys->dd_child_dir_zapobj);

		err = zap_lookup(dp->dp_meta_objset,
		    dd->dd_phys->dd_child_dir_zapobj,
		    buf, sizeof (ddobj), 1, &ddobj);
		if (err != 0) {
			if (err == ENOENT)
				err = 0;
			break;
		}

		err = dsl_dir_hold_obj(dp, ddobj, buf, tag, &child_ds);
		if (err != 0)
			break;
		dsl_dir_rele(dd, tag);
		dd = child_ds;
		next = nextnext;
	}

	if (err != 0) {
		dsl_dir_rele(dd, tag);
		return (err);
	}

	/*
	 * It's an error if there's more than one component left, or
	 * tailp==NULL and there's any component left.
	 */
	if (next != NULL &&
	    (tailp == NULL || (nextnext && nextnext[0] != '\0'))) {
		/* bad path name */
		dsl_dir_rele(dd, tag);
		dprintf("next=%p (%s) tail=%p\n", next, next?next:"", tailp);
		err = SET_ERROR(ENOENT);
	}
	if (tailp != NULL)
		*tailp = next;
	*ddp = dd;
	return (err);
}