コード例 #1
0
ファイル: libzfs_graph.c プロジェクト: BjoKaSH/mac-zfs
/*
 * Construct a complete graph of all necessary vertices.  First, we iterate over
 * only our object's children.  If we don't find any cloned snapshots, then we
 * simple return that.  Otherwise, we have to start at the pool root and iterate
 * over all datasets.
 */
static zfs_graph_t *
construct_graph(libzfs_handle_t *hdl, const char *dataset)
{
	zfs_graph_t *zgp = zfs_graph_create(hdl, ZFS_GRAPH_SIZE);
	zfs_cmd_t zc = { 0 };
	int ret = 0;

	if (zgp == NULL)
		return (zgp);

	/*
	 * We need to explicitly check whether this dataset has clones or not,
	 * since iterate_children() only checks the children.
	 */
	(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
	(void) ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc);

	if (zc.zc_objset_stats.dds_num_clones != 0 ||
	    (ret = iterate_children(hdl, zgp, dataset)) != 0) {
		/*
		 * Determine pool name and try again.
		 */
		char *pool, *slash;

		if ((slash = strchr(dataset, '/')) != NULL ||
		    (slash = strchr(dataset, '@')) != NULL) {
			pool = zfs_alloc(hdl, slash - dataset + 1);
			if (pool == NULL) {
				zfs_graph_destroy(zgp);
				return (NULL);
			}
			(void) strncpy(pool, dataset, slash - dataset);
			pool[slash - dataset] = '\0';

			if (iterate_children(hdl, zgp, pool) == -1 ||
			    zfs_graph_add(hdl, zgp, pool, NULL, 0) != 0) {
				free(pool);
				zfs_graph_destroy(zgp);
				return (NULL);
			}

			free(pool);
		}
	}

	if (ret == -1 || zfs_graph_add(hdl, zgp, dataset, NULL, 0) != 0) {
		zfs_graph_destroy(zgp);
		return (NULL);
	}

	return (zgp);
}
コード例 #2
0
ファイル: libzfs_graph.c プロジェクト: BjoKaSH/mac-zfs
/*
 * The only public interface for this file.  Do the dirty work of constructing a
 * child list for the given object.  Construct the graph, do the toplogical
 * sort, and then return the array of strings to the caller.
 *
 * The 'allowrecursion' parameter controls behavior when cycles are found.  If
 * it is set, the the cycle is ignored and the results returned as if the cycle
 * did not exist.  If it is not set, then the routine will generate an error if
 * a cycle is found.
 */
int
get_dependents(libzfs_handle_t *hdl, boolean_t allowrecursion,
    const char *dataset, char ***result, size_t *count)
{
	zfs_graph_t *zgp;
	zfs_vertex_t *zvp;

	if ((zgp = construct_graph(hdl, dataset)) == NULL)
		return (-1);

	if ((*result = zfs_alloc(hdl,
	    zgp->zg_nvertex * sizeof (char *))) == NULL) {
		zfs_graph_destroy(zgp);
		return (-1);
	}

	if ((zvp = zfs_graph_lookup(hdl, zgp, dataset, 0)) == NULL) {
		free(*result);
		zfs_graph_destroy(zgp);
		return (-1);
	}

	*count = 0;
	if (topo_sort(hdl, allowrecursion, *result, count, zvp) != 0) {
		free(*result);
		zfs_graph_destroy(zgp);
		return (-1);
	}

	/*
	 * Get rid of the last entry, which is our starting vertex and not
	 * strictly a dependent.
	 */
	assert(*count > 0);
	free((*result)[*count - 1]);
	(*count)--;

	zfs_graph_destroy(zgp);

	return (0);
}
コード例 #3
0
/*
 * Construct a complete graph of all necessary vertices.  First, iterate over
 * only our object's children.  If no cloned snapshots are found, or all of
 * the cloned snapshots are in this subtree then return a graph of the subtree.
 * Otherwise, start at the root of the pool and iterate over all datasets.
 */
static zfs_graph_t *
construct_graph(libzfs_handle_t *hdl, const char *dataset)
{
	zfs_graph_t *zgp = zfs_graph_create(hdl, dataset, ZFS_GRAPH_SIZE);
	int ret = 0;

	if (zgp == NULL)
		return (zgp);

	if ((strchr(dataset, '/') == NULL) ||
	    (external_dependents(hdl, zgp, dataset))) {
		/*
		 * Determine pool name and try again.
		 */
		int len = strcspn(dataset, "/@") + 1;
		char *pool = zfs_alloc(hdl, len);

		if (pool == NULL) {
			zfs_graph_destroy(zgp);
			return (NULL);
		}
		(void) strlcpy(pool, dataset, len);

		if (iterate_children(hdl, zgp, pool) == -1 ||
		    zfs_graph_add(hdl, zgp, pool, NULL, 0) != 0) {
			free(pool);
			zfs_graph_destroy(zgp);
			return (NULL);
		}
		free(pool);
	}

	if (ret == -1 || zfs_graph_add(hdl, zgp, dataset, NULL, 0) != 0) {
		zfs_graph_destroy(zgp);
		return (NULL);
	}

	return (zgp);
}