int dsl_dir_is_private(dsl_dir_t *dd) { int rv = FALSE; if (dd->dd_parent && dsl_dir_is_private(dd->dd_parent)) rv = TRUE; if (dataset_name_hidden(dd->dd_myname)) rv = TRUE; return (rv); }
static int zcp_children_iter(lua_State *state) { int err; char childname[ZFS_MAX_DATASET_NAME_LEN]; uint64_t dsobj = lua_tonumber(state, lua_upvalueindex(1)); uint64_t cursor = lua_tonumber(state, lua_upvalueindex(2)); zcp_run_info_t *ri = zcp_run_info(state); dsl_pool_t *dp = ri->zri_pool; dsl_dataset_t *ds; objset_t *os; char *p; err = dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds); if (err != 0) { return (luaL_error(state, "unexpected error %d from dsl_dataset_hold_obj(dsobj)", err)); } dsl_dataset_name(ds, childname); VERIFY3U(sizeof (childname), >, strlcat(childname, "/", sizeof (childname))); p = strchr(childname, '\0'); VERIFY0(dmu_objset_from_ds(ds, &os)); do { err = dmu_dir_list_next(os, sizeof (childname) - (p - childname), p, NULL, &cursor); } while (err == 0 && dataset_name_hidden(childname)); dsl_dataset_rele(ds, FTAG); if (err == ENOENT) { return (0); } else if (err != 0) { return (luaL_error(state, "unexpected error %d from dmu_dir_list_next()", err)); } lua_pushnumber(state, cursor); lua_replace(state, lua_upvalueindex(2)); (void) lua_pushstring(state, childname); return (1); }
/* * Iterate over all children of the given dataset, adding any vertices as * necessary. Returns 0 if no cloned snapshots were seen, -1 if there was an * error, or 1 otherwise. This is a simple recursive algorithm - the ZFS * namespace typically is very flat. We manually invoke the necessary ioctl() * calls to avoid the overhead and additional semantics of zfs_open(). */ static int iterate_children(libzfs_handle_t *hdl, zfs_graph_t *zgp, const char *dataset) { zfs_cmd_t zc = { 0 }; int ret = 0, err; zfs_vertex_t *zvp; /* * Look up the source vertex, and avoid it if we've seen it before. */ zvp = zfs_graph_lookup(hdl, zgp, dataset, 0); if (zvp == NULL) return (-1); if (zvp->zv_visited == VISIT_SEEN) return (0); /* * We check the clone parent here instead of within the loop, so that if * the root dataset has been promoted from a clone, we find its parent * appropriately. */ (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) == 0 && zc.zc_objset_stats.dds_clone_of[0] != '\0') { if (zfs_graph_add(hdl, zgp, zc.zc_objset_stats.dds_clone_of, zc.zc_name, zc.zc_objset_stats.dds_creation_txg) != 0) return (-1); } for ((void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); ioctl(hdl->libzfs_fd, ZFS_IOC_DATASET_LIST_NEXT, &zc) == 0; (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name))) { /* * Ignore private dataset names. */ if (dataset_name_hidden(zc.zc_name)) continue; /* * Get statistics for this dataset, to determine the type of the * dataset and clone statistics. If this fails, the dataset has * since been removed, and we're pretty much screwed anyway. */ if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) continue; /* * Add an edge between the parent and the child. */ if (zfs_graph_add(hdl, zgp, dataset, zc.zc_name, zc.zc_objset_stats.dds_creation_txg) != 0) return (-1); /* * Iterate over all children */ err = iterate_children(hdl, zgp, zc.zc_name); if (err == -1) return (-1); else if (err == 1) ret = 1; /* * Indicate if we found a dataset with a non-zero clone count. */ if (zc.zc_objset_stats.dds_num_clones != 0) ret = 1; } /* * Now iterate over all snapshots. */ bzero(&zc, sizeof (zc)); for ((void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); ioctl(hdl->libzfs_fd, ZFS_IOC_SNAPSHOT_LIST_NEXT, &zc) == 0; (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name))) { /* * Get statistics for this dataset, to determine the type of the * dataset and clone statistics. If this fails, the dataset has * since been removed, and we're pretty much screwed anyway. */ if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) continue; /* * Add an edge between the parent and the child. */ if (zfs_graph_add(hdl, zgp, dataset, zc.zc_name, zc.zc_objset_stats.dds_creation_txg) != 0) return (-1); /* * Indicate if we found a dataset with a non-zero clone count. */ if (zc.zc_objset_stats.dds_num_clones != 0) ret = 1; } zvp->zv_visited = VISIT_SEEN; return (ret); }
/* * Iterate over all children of the given dataset, adding any vertices * as necessary. Returns -1 if there was an error, or 0 otherwise. * This is a simple recursive algorithm - the ZFS namespace typically * is very flat. We manually invoke the necessary ioctl() calls to * avoid the overhead and additional semantics of zfs_open(). */ static int iterate_children(libzfs_handle_t *hdl, zfs_graph_t *zgp, const char *dataset) { zfs_cmd_t zc = { 0 }; zfs_vertex_t *zvp; /* * Look up the source vertex, and avoid it if we've seen it before. */ zvp = zfs_graph_lookup(hdl, zgp, dataset, 0); if (zvp == NULL) return (-1); if (zvp->zv_visited == VISIT_SEEN) return (0); /* * Iterate over all children */ for ((void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); ioctl(hdl->libzfs_fd, ZFS_IOC_DATASET_LIST_NEXT, &zc) == 0; (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name))) { /* * Ignore private dataset names. */ if (dataset_name_hidden(zc.zc_name)) continue; /* * Get statistics for this dataset, to determine the type of the * dataset and clone statistics. If this fails, the dataset has * since been removed, and we're pretty much screwed anyway. */ zc.zc_objset_stats.dds_origin[0] = '\0'; if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) continue; if (zc.zc_objset_stats.dds_origin[0] != '\0') { if (zfs_graph_add(hdl, zgp, zc.zc_objset_stats.dds_origin, zc.zc_name, zc.zc_objset_stats.dds_creation_txg) != 0) return (-1); /* * Count origins only if they are contained in the graph */ if (isa_child_of(zc.zc_objset_stats.dds_origin, zgp->zg_root)) zgp->zg_clone_count--; } /* * Add an edge between the parent and the child. */ if (zfs_graph_add(hdl, zgp, dataset, zc.zc_name, zc.zc_objset_stats.dds_creation_txg) != 0) return (-1); /* * Recursively visit child */ if (iterate_children(hdl, zgp, zc.zc_name)) return (-1); } /* * Now iterate over all snapshots. */ bzero(&zc, sizeof (zc)); for ((void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); ioctl(hdl->libzfs_fd, ZFS_IOC_SNAPSHOT_LIST_NEXT, &zc) == 0; (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name))) { /* * Get statistics for this dataset, to determine the type of the * dataset and clone statistics. If this fails, the dataset has * since been removed, and we're pretty much screwed anyway. */ if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) continue; /* * Add an edge between the parent and the child. */ if (zfs_graph_add(hdl, zgp, dataset, zc.zc_name, zc.zc_objset_stats.dds_creation_txg) != 0) return (-1); zgp->zg_clone_count += zc.zc_objset_stats.dds_num_clones; } zvp->zv_visited = VISIT_SEEN; return (0); }