1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 5*1544Seschrock * Common Development and Distribution License (the "License"). 6*1544Seschrock * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 21789Sahrens /* 22*1544Seschrock * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27789Sahrens 28789Sahrens /* 29789Sahrens * Iterate over all children of the current object. This includes the normal 30789Sahrens * dataset hierarchy, but also arbitrary hierarchies due to clones. We want to 31789Sahrens * walk all datasets in the pool, and construct a directed graph of the form: 32789Sahrens * 33789Sahrens * home 34789Sahrens * | 35789Sahrens * +----+----+ 36789Sahrens * | | 37789Sahrens * v v ws 38789Sahrens * bar baz | 39789Sahrens * | | 40789Sahrens * v v 41789Sahrens * @yesterday ----> foo 42789Sahrens * 43789Sahrens * In order to construct this graph, we have to walk every dataset in the pool, 44789Sahrens * because the clone parent is stored as a property of the child, not the 45789Sahrens * parent. The parent only keeps track of the number of clones. 46789Sahrens * 47789Sahrens * In the normal case (without clones) this would be rather expensive. To avoid 48789Sahrens * unnecessary computation, we first try a walk of the subtree hierarchy 49789Sahrens * starting from the initial node. At each dataset, we construct a node in the 50789Sahrens * graph and an edge leading from its parent. If we don't see any snapshots 51789Sahrens * with a non-zero clone count, then we are finished. 52789Sahrens * 53789Sahrens * If we do find a cloned snapshot, then we finish the walk of the current 54789Sahrens * subtree, but indicate that we need to do a complete walk. We then perform a 55789Sahrens * global walk of all datasets, avoiding the subtree we already processed. 56789Sahrens * 57789Sahrens * At the end of this, we'll end up with a directed graph of all relevant (and 58789Sahrens * possible some irrelevant) datasets in the system. We need to both find our 59789Sahrens * limiting subgraph and determine a safe ordering in which to destroy the 60789Sahrens * datasets. We do a topological ordering of our graph starting at our target 61789Sahrens * dataset, and then walk the results in reverse. 62789Sahrens * 63789Sahrens * When removing datasets, we want to destroy the snapshots in chronological 64789Sahrens * order (because this is the most efficient method). In order to accomplish 65789Sahrens * this, we store the creation transaction group with each vertex and keep each 66789Sahrens * vertex's edges sorted according to this value. The topological sort will 67789Sahrens * automatically walk the snapshots in the correct order. 68789Sahrens */ 69789Sahrens 70789Sahrens #include <assert.h> 71789Sahrens #include <stdio.h> 72789Sahrens #include <stdlib.h> 73789Sahrens #include <string.h> 74789Sahrens #include <strings.h> 75789Sahrens #include <unistd.h> 76789Sahrens 77789Sahrens #include <libzfs.h> 78789Sahrens 79789Sahrens #include "libzfs_impl.h" 80789Sahrens #include "zfs_namecheck.h" 81789Sahrens 82789Sahrens #define MIN_EDGECOUNT 4 83789Sahrens 84789Sahrens /* 85789Sahrens * Vertex structure. Indexed by dataset name, this structure maintains a list 86789Sahrens * of edges to other vertices. 87789Sahrens */ 88789Sahrens struct zfs_edge; 89789Sahrens typedef struct zfs_vertex { 90789Sahrens char zv_dataset[ZFS_MAXNAMELEN]; 91789Sahrens struct zfs_vertex *zv_next; 92789Sahrens int zv_visited; 93789Sahrens uint64_t zv_txg; 94789Sahrens struct zfs_edge **zv_edges; 95789Sahrens int zv_edgecount; 96789Sahrens int zv_edgealloc; 97789Sahrens } zfs_vertex_t; 98789Sahrens 99789Sahrens /* 100789Sahrens * Edge structure. Simply maintains a pointer to the destination vertex. There 101789Sahrens * is no need to store the source vertex, since we only use edges in the context 102789Sahrens * of the source vertex. 103789Sahrens */ 104789Sahrens typedef struct zfs_edge { 105789Sahrens zfs_vertex_t *ze_dest; 106789Sahrens struct zfs_edge *ze_next; 107789Sahrens } zfs_edge_t; 108789Sahrens 109789Sahrens #define ZFS_GRAPH_SIZE 1027 /* this could be dynamic some day */ 110789Sahrens 111789Sahrens /* 112789Sahrens * Graph structure. Vertices are maintained in a hash indexed by dataset name. 113789Sahrens */ 114789Sahrens typedef struct zfs_graph { 115789Sahrens zfs_vertex_t **zg_hash; 116789Sahrens size_t zg_size; 117789Sahrens size_t zg_nvertex; 118789Sahrens } zfs_graph_t; 119789Sahrens 120789Sahrens /* 121789Sahrens * Allocate a new edge pointing to the target vertex. 122789Sahrens */ 123789Sahrens static zfs_edge_t * 124789Sahrens zfs_edge_create(zfs_vertex_t *dest) 125789Sahrens { 126789Sahrens zfs_edge_t *zep = zfs_malloc(sizeof (zfs_edge_t)); 127789Sahrens 128789Sahrens zep->ze_dest = dest; 129789Sahrens 130789Sahrens return (zep); 131789Sahrens } 132789Sahrens 133789Sahrens /* 134789Sahrens * Destroy an edge. 135789Sahrens */ 136789Sahrens static void 137789Sahrens zfs_edge_destroy(zfs_edge_t *zep) 138789Sahrens { 139789Sahrens free(zep); 140789Sahrens } 141789Sahrens 142789Sahrens /* 143789Sahrens * Allocate a new vertex with the given name. 144789Sahrens */ 145789Sahrens static zfs_vertex_t * 146789Sahrens zfs_vertex_create(const char *dataset) 147789Sahrens { 148789Sahrens zfs_vertex_t *zvp = zfs_malloc(sizeof (zfs_vertex_t)); 149789Sahrens 150789Sahrens assert(strlen(dataset) < ZFS_MAXNAMELEN); 151789Sahrens 152789Sahrens (void) strlcpy(zvp->zv_dataset, dataset, sizeof (zvp->zv_dataset)); 153789Sahrens 154789Sahrens zvp->zv_edges = zfs_malloc(MIN_EDGECOUNT * sizeof (void *)); 155789Sahrens zvp->zv_edgealloc = MIN_EDGECOUNT; 156789Sahrens 157789Sahrens return (zvp); 158789Sahrens } 159789Sahrens 160789Sahrens /* 161789Sahrens * Destroy a vertex. Frees up any associated edges. 162789Sahrens */ 163789Sahrens static void 164789Sahrens zfs_vertex_destroy(zfs_vertex_t *zvp) 165789Sahrens { 166789Sahrens int i; 167789Sahrens 168789Sahrens for (i = 0; i < zvp->zv_edgecount; i++) 169789Sahrens zfs_edge_destroy(zvp->zv_edges[i]); 170789Sahrens 171789Sahrens free(zvp->zv_edges); 172789Sahrens free(zvp); 173789Sahrens } 174789Sahrens 175789Sahrens /* 176789Sahrens * Given a vertex, add an edge to the destination vertex. 177789Sahrens */ 178789Sahrens static void 179789Sahrens zfs_vertex_add_edge(zfs_vertex_t *zvp, zfs_vertex_t *dest) 180789Sahrens { 181789Sahrens zfs_edge_t *zep = zfs_edge_create(dest); 182789Sahrens 183789Sahrens if (zvp->zv_edgecount == zvp->zv_edgealloc) { 184789Sahrens zfs_edge_t **newedges = zfs_malloc(zvp->zv_edgealloc * 2 * 185789Sahrens sizeof (void *)); 186789Sahrens 187789Sahrens bcopy(zvp->zv_edges, newedges, 188789Sahrens zvp->zv_edgealloc * sizeof (void *)); 189789Sahrens 190789Sahrens zvp->zv_edgealloc *= 2; 191789Sahrens free(zvp->zv_edges); 192789Sahrens zvp->zv_edges = newedges; 193789Sahrens } 194789Sahrens 195789Sahrens zvp->zv_edges[zvp->zv_edgecount++] = zep; 196789Sahrens } 197789Sahrens 198789Sahrens static int 199789Sahrens zfs_edge_compare(const void *a, const void *b) 200789Sahrens { 201789Sahrens const zfs_edge_t *ea = *((zfs_edge_t **)a); 202789Sahrens const zfs_edge_t *eb = *((zfs_edge_t **)b); 203789Sahrens 204789Sahrens if (ea->ze_dest->zv_txg < eb->ze_dest->zv_txg) 205789Sahrens return (-1); 206789Sahrens if (ea->ze_dest->zv_txg > eb->ze_dest->zv_txg) 207789Sahrens return (1); 208789Sahrens return (0); 209789Sahrens } 210789Sahrens 211789Sahrens /* 212789Sahrens * Sort the given vertex edges according to the creation txg of each vertex. 213789Sahrens */ 214789Sahrens static void 215789Sahrens zfs_vertex_sort_edges(zfs_vertex_t *zvp) 216789Sahrens { 217789Sahrens if (zvp->zv_edgecount == 0) 218789Sahrens return; 219789Sahrens 220789Sahrens qsort(zvp->zv_edges, zvp->zv_edgecount, sizeof (void *), 221789Sahrens zfs_edge_compare); 222789Sahrens } 223789Sahrens 224789Sahrens /* 225789Sahrens * Construct a new graph object. We allow the size to be specified as a 226789Sahrens * parameter so in the future we can size the hash according to the number of 227789Sahrens * datasets in the pool. 228789Sahrens */ 229789Sahrens static zfs_graph_t * 230789Sahrens zfs_graph_create(size_t size) 231789Sahrens { 232789Sahrens zfs_graph_t *zgp = zfs_malloc(sizeof (zfs_graph_t)); 233789Sahrens 234789Sahrens zgp->zg_size = size; 235789Sahrens zgp->zg_hash = zfs_malloc(size * sizeof (zfs_vertex_t *)); 236789Sahrens 237789Sahrens return (zgp); 238789Sahrens } 239789Sahrens 240789Sahrens /* 241789Sahrens * Destroy a graph object. We have to iterate over all the hash chains, 242789Sahrens * destroying each vertex in the process. 243789Sahrens */ 244789Sahrens static void 245789Sahrens zfs_graph_destroy(zfs_graph_t *zgp) 246789Sahrens { 247789Sahrens int i; 248789Sahrens zfs_vertex_t *current, *next; 249789Sahrens 250789Sahrens for (i = 0; i < zgp->zg_size; i++) { 251789Sahrens current = zgp->zg_hash[i]; 252789Sahrens while (current != NULL) { 253789Sahrens next = current->zv_next; 254789Sahrens zfs_vertex_destroy(current); 255789Sahrens current = next; 256789Sahrens } 257789Sahrens } 258789Sahrens 259789Sahrens free(zgp->zg_hash); 260789Sahrens free(zgp); 261789Sahrens } 262789Sahrens 263789Sahrens /* 264789Sahrens * Graph hash function. Classic bernstein k=33 hash function, taken from 265789Sahrens * usr/src/cmd/sgs/tools/common/strhash.c 266789Sahrens */ 267789Sahrens static size_t 268789Sahrens zfs_graph_hash(zfs_graph_t *zgp, const char *str) 269789Sahrens { 270789Sahrens size_t hash = 5381; 271789Sahrens int c; 272789Sahrens 273789Sahrens while ((c = *str++) != 0) 274789Sahrens hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ 275789Sahrens 276789Sahrens return (hash % zgp->zg_size); 277789Sahrens } 278789Sahrens 279789Sahrens /* 280789Sahrens * Given a dataset name, finds the associated vertex, creating it if necessary. 281789Sahrens */ 282789Sahrens static zfs_vertex_t * 283789Sahrens zfs_graph_lookup(zfs_graph_t *zgp, const char *dataset, uint64_t txg) 284789Sahrens { 285789Sahrens size_t idx = zfs_graph_hash(zgp, dataset); 286789Sahrens zfs_vertex_t *zvp; 287789Sahrens 288789Sahrens for (zvp = zgp->zg_hash[idx]; zvp != NULL; zvp = zvp->zv_next) { 289789Sahrens if (strcmp(zvp->zv_dataset, dataset) == 0) { 290789Sahrens if (zvp->zv_txg == 0) 291789Sahrens zvp->zv_txg = txg; 292789Sahrens return (zvp); 293789Sahrens } 294789Sahrens } 295789Sahrens 296789Sahrens zvp = zfs_vertex_create(dataset); 297789Sahrens zvp->zv_next = zgp->zg_hash[idx]; 298789Sahrens zvp->zv_txg = txg; 299789Sahrens zgp->zg_hash[idx] = zvp; 300789Sahrens zgp->zg_nvertex++; 301789Sahrens 302789Sahrens return (zvp); 303789Sahrens } 304789Sahrens 305789Sahrens /* 306789Sahrens * Given two dataset names, create an edge between them. For the source vertex, 307789Sahrens * mark 'zv_visited' to indicate that we have seen this vertex, and not simply 308789Sahrens * created it as a destination of another edge. If 'dest' is NULL, then this 309789Sahrens * is an individual vertex (i.e. the starting vertex), so don't add an edge. 310789Sahrens */ 311789Sahrens static void 312789Sahrens zfs_graph_add(zfs_graph_t *zgp, const char *source, const char *dest, 313789Sahrens uint64_t txg) 314789Sahrens { 315789Sahrens zfs_vertex_t *svp, *dvp; 316789Sahrens 317789Sahrens svp = zfs_graph_lookup(zgp, source, 0); 318789Sahrens svp->zv_visited = 1; 319789Sahrens if (dest != NULL) { 320789Sahrens dvp = zfs_graph_lookup(zgp, dest, txg); 321789Sahrens zfs_vertex_add_edge(svp, dvp); 322789Sahrens } 323789Sahrens } 324789Sahrens 325789Sahrens /* 326789Sahrens * Iterate over all children of the given dataset, adding any vertices as 327789Sahrens * necessary. Returns 0 if no cloned snapshots were seen, 1 otherwise. This is 328789Sahrens * a simple recursive algorithm - the ZFS namespace typically is very flat. We 329789Sahrens * manually invoke the necessary ioctl() calls to avoid the overhead and 330789Sahrens * additional semantics of zfs_open(). 331789Sahrens */ 332789Sahrens static int 333789Sahrens iterate_children(zfs_graph_t *zgp, const char *dataset) 334789Sahrens { 335789Sahrens zfs_cmd_t zc = { 0 }; 336789Sahrens int ret = 0; 337789Sahrens zfs_vertex_t *zvp; 338789Sahrens 339789Sahrens /* 340789Sahrens * Look up the source vertex, and avoid it if we've seen it before. 341789Sahrens */ 342789Sahrens zvp = zfs_graph_lookup(zgp, dataset, 0); 343789Sahrens if (zvp->zv_visited) 344789Sahrens return (0); 345789Sahrens 346789Sahrens for ((void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 347*1544Seschrock zfs_ioctl(ZFS_IOC_DATASET_LIST_NEXT, &zc) == 0; 348789Sahrens (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name))) { 349789Sahrens 350789Sahrens /* 351789Sahrens * Ignore private dataset names. 352789Sahrens */ 353789Sahrens if (dataset_name_hidden(zc.zc_name)) 354789Sahrens continue; 355789Sahrens 356789Sahrens /* 357789Sahrens * Get statistics for this dataset, to determine the type of the 358789Sahrens * dataset and clone statistics. If this fails, the dataset has 359789Sahrens * since been removed, and we're pretty much screwed anyway. 360789Sahrens */ 361*1544Seschrock if (zfs_ioctl(ZFS_IOC_OBJSET_STATS, &zc) != 0) 362789Sahrens continue; 363789Sahrens 364789Sahrens /* 365789Sahrens * Add an edge between the parent and the child. 366789Sahrens */ 367789Sahrens zfs_graph_add(zgp, dataset, zc.zc_name, 368789Sahrens zc.zc_objset_stats.dds_creation_txg); 369789Sahrens 370789Sahrens /* 371789Sahrens * If this dataset has a clone parent, add an appropriate edge. 372789Sahrens */ 373789Sahrens if (zc.zc_objset_stats.dds_clone_of[0] != '\0') 374789Sahrens zfs_graph_add(zgp, zc.zc_objset_stats.dds_clone_of, 375789Sahrens zc.zc_name, zc.zc_objset_stats.dds_creation_txg); 376789Sahrens 377789Sahrens /* 378789Sahrens * Iterate over all children 379789Sahrens */ 380789Sahrens ret |= iterate_children(zgp, zc.zc_name); 381789Sahrens 382789Sahrens /* 383789Sahrens * Indicate if we found a dataset with a non-zero clone count. 384789Sahrens */ 385789Sahrens if (zc.zc_objset_stats.dds_num_clones != 0) 386789Sahrens ret |= 1; 387789Sahrens } 388789Sahrens 389789Sahrens /* 390789Sahrens * Now iterate over all snapshots. 391789Sahrens */ 392789Sahrens bzero(&zc, sizeof (zc)); 393789Sahrens 394789Sahrens for ((void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 395*1544Seschrock zfs_ioctl(ZFS_IOC_SNAPSHOT_LIST_NEXT, &zc) == 0; 396789Sahrens (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name))) { 397789Sahrens 398789Sahrens /* 399789Sahrens * Get statistics for this dataset, to determine the type of the 400789Sahrens * dataset and clone statistics. If this fails, the dataset has 401789Sahrens * since been removed, and we're pretty much screwed anyway. 402789Sahrens */ 403*1544Seschrock if (zfs_ioctl(ZFS_IOC_OBJSET_STATS, &zc) != 0) 404789Sahrens continue; 405789Sahrens 406789Sahrens /* 407789Sahrens * Add an edge between the parent and the child. 408789Sahrens */ 409789Sahrens zfs_graph_add(zgp, dataset, zc.zc_name, 410789Sahrens zc.zc_objset_stats.dds_creation_txg); 411789Sahrens 412789Sahrens /* 413789Sahrens * Indicate if we found a dataset with a non-zero clone count. 414789Sahrens */ 415789Sahrens if (zc.zc_objset_stats.dds_num_clones != 0) 416789Sahrens ret |= 1; 417789Sahrens } 418789Sahrens 419789Sahrens zvp->zv_visited = 1; 420789Sahrens 421789Sahrens return (ret); 422789Sahrens } 423789Sahrens 424789Sahrens /* 425789Sahrens * Construct a complete graph of all necessary vertices. First, we iterate over 426789Sahrens * only our object's children. If we don't find any cloned snapshots, then we 427789Sahrens * simple return that. Otherwise, we have to start at the pool root and iterate 428789Sahrens * over all datasets. 429789Sahrens */ 430789Sahrens static zfs_graph_t * 431789Sahrens construct_graph(const char *dataset) 432789Sahrens { 433789Sahrens zfs_graph_t *zgp = zfs_graph_create(ZFS_GRAPH_SIZE); 434789Sahrens zfs_cmd_t zc = { 0 }; 435789Sahrens 436789Sahrens /* 437789Sahrens * We need to explicitly check whether this dataset has clones or not, 438789Sahrens * since iterate_children() only checks the children. 439789Sahrens */ 440789Sahrens (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); 441*1544Seschrock (void) zfs_ioctl(ZFS_IOC_OBJSET_STATS, &zc); 442789Sahrens 443789Sahrens if (zc.zc_objset_stats.dds_num_clones != 0 || 444789Sahrens iterate_children(zgp, dataset) != 0) { 445789Sahrens /* 446789Sahrens * Determine pool name and try again. 447789Sahrens */ 448789Sahrens char *pool, *slash; 449789Sahrens 450789Sahrens if ((slash = strchr(dataset, '/')) != NULL || 451789Sahrens (slash = strchr(dataset, '@')) != NULL) { 452789Sahrens pool = zfs_malloc(slash - dataset + 1); 453789Sahrens (void) strncpy(pool, dataset, slash - dataset); 454789Sahrens pool[slash - dataset] = '\0'; 455789Sahrens 456789Sahrens (void) iterate_children(zgp, pool); 457789Sahrens zfs_graph_add(zgp, pool, NULL, 0); 458789Sahrens 459789Sahrens free(pool); 460789Sahrens } 461789Sahrens } 462789Sahrens zfs_graph_add(zgp, dataset, NULL, 0); 463789Sahrens 464789Sahrens return (zgp); 465789Sahrens } 466789Sahrens 467789Sahrens /* 468789Sahrens * Given a graph, do a recursive topological sort into the given array. This is 469789Sahrens * really just a depth first search, so that the deepest nodes appear first. 470789Sahrens * hijack the 'zv_visited' marker to avoid visiting the same vertex twice. 471789Sahrens */ 472789Sahrens static void 473789Sahrens topo_sort(char **result, size_t *idx, zfs_vertex_t *zgv) 474789Sahrens { 475789Sahrens int i; 476789Sahrens 477789Sahrens /* avoid doing a search if we don't have to */ 478789Sahrens if (zgv->zv_visited == 2) 479789Sahrens return; 480789Sahrens 481789Sahrens zfs_vertex_sort_edges(zgv); 482789Sahrens for (i = 0; i < zgv->zv_edgecount; i++) 483789Sahrens topo_sort(result, idx, zgv->zv_edges[i]->ze_dest); 484789Sahrens 485789Sahrens /* we may have visited this in the course of the above */ 486789Sahrens if (zgv->zv_visited == 2) 487789Sahrens return; 488789Sahrens 489789Sahrens result[*idx] = zfs_malloc(strlen(zgv->zv_dataset) + 1); 490789Sahrens (void) strcpy(result[*idx], zgv->zv_dataset); 491789Sahrens *idx += 1; 492789Sahrens zgv->zv_visited = 2; 493789Sahrens } 494789Sahrens 495789Sahrens /* 496789Sahrens * The only public interface for this file. Do the dirty work of constructing a 497789Sahrens * child list for the given object. Construct the graph, do the toplogical 498789Sahrens * sort, and then return the array of strings to the caller. 499789Sahrens */ 500789Sahrens char ** 501789Sahrens get_dependents(const char *dataset, size_t *count) 502789Sahrens { 503789Sahrens char **result; 504789Sahrens zfs_graph_t *zgp; 505789Sahrens zfs_vertex_t *zvp; 506789Sahrens 507789Sahrens zgp = construct_graph(dataset); 508789Sahrens result = zfs_malloc(zgp->zg_nvertex * sizeof (char *)); 509789Sahrens 510789Sahrens zvp = zfs_graph_lookup(zgp, dataset, 0); 511789Sahrens 512789Sahrens *count = 0; 513789Sahrens topo_sort(result, count, zvp); 514789Sahrens 515789Sahrens /* 516789Sahrens * Get rid of the last entry, which is our starting vertex and not 517789Sahrens * strictly a dependent. 518789Sahrens */ 519789Sahrens assert(*count > 0); 520789Sahrens free(result[*count - 1]); 521789Sahrens (*count)--; 522789Sahrens 523789Sahrens zfs_graph_destroy(zgp); 524789Sahrens 525789Sahrens return (result); 526789Sahrens } 527