예제 #1
0
파일: zvol.c 프로젝트: lycovian/zfs
int
zvol_set_snapdev(const char *dsname, uint64_t snapdev) {
	(void) dmu_objset_find((char *) dsname, snapdev_snapshot_changed_cb,
		&snapdev, DS_FIND_SNAPSHOTS | DS_FIND_CHILDREN);
	/* caller should continue to modify snapdev property */
	return (-1);
}
예제 #2
0
파일: zvol.c 프로젝트: alek-p/zfs
/*
 * Create minors for the specified dataset, including children and snapshots.
 * Pay attention to the 'snapdev' property and iterate over the snapshots
 * only if they are 'visible'. This approach allows one to assure that the
 * snapshot metadata is read from disk only if it is needed.
 *
 * The name can represent a dataset to be recursively scanned for zvols and
 * their snapshots, or a single zvol snapshot. If the name represents a
 * dataset, the scan is performed in two nested stages:
 * - scan the dataset for zvols, and
 * - for each zvol, create a minor node, then check if the zvol's snapshots
 *   are 'visible', and only then iterate over the snapshots if needed
 *
 * If the name represents a snapshot, a check is perfromed if the snapshot is
 * 'visible' (which also verifies that the parent is a zvol), and if so,
 * a minor node for that snapshot is created.
 */
static int
zvol_create_minors_impl(const char *name)
{
	int error = 0;
	fstrans_cookie_t cookie;
	char *atp, *parent;

	if (zvol_inhibit_dev)
		return (0);

	parent = kmem_alloc(MAXPATHLEN, KM_SLEEP);
	(void) strlcpy(parent, name, MAXPATHLEN);

	if ((atp = strrchr(parent, '@')) != NULL) {
		uint64_t snapdev;

		*atp = '\0';
		error = dsl_prop_get_integer(parent, "snapdev",
		    &snapdev, NULL);

		if (error == 0 && snapdev == ZFS_SNAPDEV_VISIBLE)
			error = zvol_create_minor_impl(name);
	} else {
		cookie = spl_fstrans_mark();
		error = dmu_objset_find(parent, zvol_create_minors_cb,
		    NULL, DS_FIND_CHILDREN);
		spl_fstrans_unmark(cookie);
	}

	kmem_free(parent, MAXPATHLEN);

	return (SET_ERROR(error));
}
예제 #3
0
int
dmu_objset_snapshot(char *fsname, char *snapname, boolean_t recursive)
{
	dsl_sync_task_t *dst;
	struct osnode *osn;
	struct snaparg sn = { 0 };
	spa_t *spa;
	int err;

	(void) strcpy(sn.failed, fsname);

	err = spa_open(fsname, &spa, FTAG);
	if (err)
		return (err);

	sn.dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
	sn.snapname = snapname;
	list_create(&sn.objsets, sizeof (struct osnode),
	    offsetof(struct osnode, node));

	if (recursive) {
		sn.checkperms = B_TRUE;
		err = dmu_objset_find(fsname,
		    dmu_objset_snapshot_one, &sn, DS_FIND_CHILDREN);
	} else {
		sn.checkperms = B_FALSE;
		err = dmu_objset_snapshot_one(fsname, &sn);
	}

	if (err)
		goto out;

	err = dsl_sync_task_group_wait(sn.dstg);

	for (dst = list_head(&sn.dstg->dstg_tasks); dst;
	    dst = list_next(&sn.dstg->dstg_tasks, dst)) {
		dsl_dataset_t *ds = dst->dst_arg1;
		if (dst->dst_err)
			dsl_dataset_name(ds, sn.failed);
	}

out:
	while (osn = list_head(&sn.objsets)) {
		list_remove(&sn.objsets, osn);
		zil_resume(dmu_objset_zil(osn->os));
		dmu_objset_close(osn->os);
		kmem_free(osn, sizeof (struct osnode));
	}
	list_destroy(&sn.objsets);

	if (err)
		(void) strcpy(fsname, sn.failed);
	dsl_sync_task_group_destroy(sn.dstg);
	spa_close(spa, FTAG);
	return (err);
}
예제 #4
0
파일: zvol.c 프로젝트: Acidburn0zzz/zfs
/*
 * Create minors for specified dataset including children and snapshots.
 */
int
zvol_create_minors(const char *name)
{
	int error = 0;

	if (!zvol_inhibit_dev)
		error = dmu_objset_find((char *)name, zvol_create_minors_cb,
		    NULL, DS_FIND_CHILDREN | DS_FIND_SNAPSHOTS);

	return (SET_ERROR(error));
}
예제 #5
0
파일: zvol.c 프로젝트: alek-p/zfs
static void
zvol_set_snapdev_impl(char *name, uint64_t snapdev)
{
	zvol_snapdev_cb_arg_t arg = {snapdev};
	fstrans_cookie_t cookie = spl_fstrans_mark();
	/*
	 * The zvol_set_snapdev_sync() sets snapdev appropriately
	 * in the dataset hierarchy. Here, we only scan snapshots.
	 */
	dmu_objset_find(name, zvol_set_snapdev_cb, &arg, DS_FIND_SNAPSHOTS);
	spl_fstrans_unmark(cookie);
}
예제 #6
0
파일: dmu_objset.c 프로젝트: harshada/zfs
int
dmu_objset_snapshot(char *fsname, char *snapname,
    nvlist_t *props, boolean_t recursive)
{
	dsl_sync_task_t *dst;
	struct snaparg *sn;
	spa_t *spa;
	int err;

	sn = kmem_alloc(sizeof (struct snaparg), KM_SLEEP);
	(void) strcpy(sn->failed, fsname);

	err = spa_open(fsname, &spa, FTAG);
	if (err) {
		kmem_free(sn, sizeof (struct snaparg));
		return (err);
	}

	sn->dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
	sn->snapname = snapname;
	sn->props = props;

	if (recursive) {
		sn->checkperms = B_TRUE;
		err = dmu_objset_find(fsname,
		    dmu_objset_snapshot_one, sn, DS_FIND_CHILDREN);
	} else {
		sn->checkperms = B_FALSE;
		err = dmu_objset_snapshot_one(fsname, sn);
	}

	if (err == 0)
		err = dsl_sync_task_group_wait(sn->dstg);

	for (dst = list_head(&sn->dstg->dstg_tasks); dst;
	    dst = list_next(&sn->dstg->dstg_tasks, dst)) {
		objset_t *os = dst->dst_arg1;
		dsl_dataset_t *ds = os->os->os_dsl_dataset;
		if (dst->dst_err)
			dsl_dataset_name(ds, sn->failed);
		zil_resume(dmu_objset_zil(os));
		dmu_objset_close(os);
	}

	if (err)
		(void) strcpy(fsname, sn->failed);
	dsl_sync_task_group_destroy(sn->dstg);
	spa_close(spa, FTAG);
	kmem_free(sn, sizeof (struct snaparg));
	return (err);
}
예제 #7
0
static zfs_handle_t *libzfs_zfs_snapshot_next(libzfs_handle_t *p_libzfshd, const char *psz_zfs, char *psz_buffer, size_t i_buffer, uint64_t *p_cookie, const char **ppsz_error)
{
        objset_t *p_os;
        size_t i_zfs_len = strlen(psz_zfs);
        int i_error;

        /* Check the size of the zfs name */
        if(i_zfs_len >= i_buffer)
        {
                *ppsz_error = "ZFS name too long to handle snapshots";
                return NULL;
        }

        if(*p_cookie == 0)
                dmu_objset_find(psz_zfs, dmu_objset_prefetch, NULL, DS_FIND_SNAPSHOTS);

top:
        if((i_error = dmu_objset_hold(psz_zfs, FTAG, &p_os)))
        {
                *ppsz_error = "Unable to hold the zfs filesystem";
                return NULL;
        }

        snprintf(psz_buffer, i_buffer, "%s@", psz_zfs);

        if((i_error = dmu_snapshot_list_next(p_os, i_buffer - i_zfs_len - 1,
                                             psz_buffer + i_zfs_len + 1, NULL, p_cookie, NULL)))
                *ppsz_error = "Unable to get the next snapshot";

        dmu_objset_rele(p_os, FTAG);

        zfs_handle_t *p_zfs_snap = NULL;
        if(i_error == 0)
        {
                i_error = dmu_objset_hold(psz_buffer, FTAG, &p_os);
                if(i_error == ENOENT)
                        goto top;

                if(!(p_zfs_snap = libzfs_make_dataset_handle(p_libzfshd, psz_buffer)))
                        *ppsz_error = "Unable to create a zfs handle for the snapshot";
                dmu_objset_rele(p_os, FTAG);
        }
        return p_zfs_snap;
}
예제 #8
0
파일: zvol.c 프로젝트: alek-p/zfs
/*
 * Mask errors to continue dmu_objset_find() traversal
 */
static int
zvol_create_minors_cb(const char *dsname, void *arg)
{
	uint64_t snapdev;
	int error;

	ASSERT0(MUTEX_HELD(&spa_namespace_lock));

	error = dsl_prop_get_integer(dsname, "snapdev", &snapdev, NULL);
	if (error)
		return (0);

	/*
	 * Given the name and the 'snapdev' property, create device minor nodes
	 * with the linkages to zvols/snapshots as needed.
	 * If the name represents a zvol, create a minor node for the zvol, then
	 * check if its snapshots are 'visible', and if so, iterate over the
	 * snapshots and create device minor nodes for those.
	 */
	if (strchr(dsname, '@') == 0) {
		/* create minor for the 'dsname' explicitly */
		error = zvol_create_minor_impl(dsname);
		if ((error == 0 || error == EEXIST) &&
		    (snapdev == ZFS_SNAPDEV_VISIBLE)) {
			fstrans_cookie_t cookie = spl_fstrans_mark();
			/*
			 * traverse snapshots only, do not traverse children,
			 * and skip the 'dsname'
			 */
			error = dmu_objset_find((char *)dsname,
			    zvol_create_snap_minor_cb, (void *)dsname,
			    DS_FIND_SNAPSHOTS);
			spl_fstrans_unmark(cookie);
		}
	} else {
		dprintf("zvol_create_minors_cb(): %s is not a zvol name\n",
			dsname);
	}

	return (0);
}
예제 #9
0
int
dsl_crypto_key_change(char *dsname, zcrypt_key_t *newkey, nvlist_t *props)
{
    struct wkey_change_arg *ca;
    struct kcnode *kcn;
    dsl_dataset_t *ds;
    dsl_props_arg_t pa;
    spa_t *spa;
    int err;
    //dsl_sync_task_group_t *dstg;
    zcrypt_key_t *oldkey;
    dsl_pool_t *dp;

    ASSERT(newkey != NULL);
    ASSERT(dsname != NULL);

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

    if ((err = dsl_dataset_hold(dp, dsname, FTAG, &ds)) != 0) {
        dsl_pool_rele(dp, FTAG);
        return (err);
    }

    /*
     * Take the spa lock here so that new datasets can't get
     * created below us while we are doing a wrapping key change.
     * This is to avoid them being created with the wrong inherited
     * wrapping key.
     */
    err = spa_open(dsname, &spa, FTAG);
    if (err)
        return (err);

    oldkey = zcrypt_key_copy(zcrypt_keystore_find_wrappingkey(spa,
                             ds->ds_object));
    if (oldkey == NULL) {
        dsl_dataset_rele(ds, FTAG);
        dsl_pool_rele(dp, FTAG);
        spa_close(spa, FTAG);
        return (ENOENT);
    }
    ca = kmem_alloc(sizeof (struct wkey_change_arg), KM_SLEEP);
    ca->ca_new_key = newkey;
    ca->ca_old_key = oldkey;
    ca->ca_parent = dsname;
    ca->ca_props = props;

    list_create(&ca->ca_nodes, sizeof (struct kcnode),
                offsetof(struct kcnode, kc_node));

    zcrypt_key_hold(ca->ca_old_key, FTAG);
    zcrypt_key_hold(ca->ca_new_key, FTAG);

    //ca->ca_ds = dsl_sync_task_group_create(spa_get_dsl(spa));

    err = dmu_objset_find(dsname, dsl_crypto_key_change_find,
                          ca, DS_FIND_CHILDREN);

    /*
     * If this is the "top" dataset in this keychange it gets
     * the keysource and salt properties updated.
     */
    pa.pa_props = props;
    pa.pa_source = ZPROP_SRC_LOCAL;
    //pa.pa_flags = 0;
    //pa.pa_zone = curzone;
    //dsl_sync_task_create(ca->ca_dstg, NULL, dsl_props_set_sync, ds, &pa, 2);

    dsl_props_set(dsname, ZPROP_SRC_LOCAL, props);

    //if (err == 0)
    //err = dsl_sync_task_group_wait(dstg);

    while ((kcn = list_head(&ca->ca_nodes))) {
        list_remove(&ca->ca_nodes, kcn);
        dsl_dataset_rele(kcn->kc_ds, kcn);
        kmem_free(kcn, sizeof (struct kcnode));
    }

    //dsl_sync_task_group_destroy(ca->ca_dstg);

    /*
     * We are finished so release and free both the old and new keys.
     * We can free even the new key because everyone got a copy of it
     * not a reference to this one.
     */
    zcrypt_key_release(ca->ca_old_key, FTAG);
    zcrypt_key_free(ca->ca_old_key);
    zcrypt_key_release(ca->ca_new_key, FTAG);
    zcrypt_key_free(ca->ca_new_key);

    kmem_free(ca, sizeof (struct wkey_change_arg));
    dsl_dataset_rele(ds, FTAG);
    dsl_pool_rele(dp, FTAG);

    spa_close(spa, FTAG);

    return (err);
}