/* * Remove and release the backup snapshot */ int snapshot_destroy(char *volname, char *jname, boolean_t recursive, boolean_t hold, int *zfs_err) { char snapname[ZFS_MAXNAMELEN]; zfs_handle_t *zhp; zfs_type_t ztype; char *namep; int err; if (zfs_err) *zfs_err = 0; if (!volname || !*volname) return (-1); if (recursive) { ztype = ZFS_TYPE_VOLUME | ZFS_TYPE_FILESYSTEM; namep = volname; } else { (void) snprintf(snapname, ZFS_MAXNAMELEN, "%s@%s", volname, jname); namep = snapname; ztype = ZFS_TYPE_SNAPSHOT; } (void) mutex_lock(&zlib_mtx); if (hold && snapshot_release(volname, namep, jname, recursive) != 0) { NDMP_LOG(LOG_DEBUG, "snapshot_destroy: %s release failed (err=%d): %s", namep, errno, libzfs_error_description(zlibh)); (void) mutex_unlock(&zlib_mtx); return (-1); } if ((zhp = zfs_open(zlibh, namep, ztype)) == NULL) { NDMP_LOG(LOG_DEBUG, "snapshot_destroy: open %s failed", namep); (void) mutex_unlock(&zlib_mtx); return (-1); } if (recursive) { err = zfs_destroy_snaps(zhp, jname, B_TRUE); } else { err = zfs_destroy(zhp, B_TRUE); } if (err) { NDMP_LOG(LOG_ERR, "%s (recursive destroy: %d): %d; %s; %s", namep, recursive, libzfs_errno(zlibh), libzfs_error_action(zlibh), libzfs_error_description(zlibh)); if (zfs_err) *zfs_err = err; } zfs_close(zhp); (void) mutex_unlock(&zlib_mtx); return (0); }
/* * Function: be_promote_ds_callback * Description: This function is used to promote the datasets for the BE * being activated as well as the datasets for the zones BE * being activated. * * Parameters: * zhp - the zfs handle for zone BE being activated. * data - not used. * Return: * 0 - Success * be_errno_t - Failure * * Scope: * Private */ static int /* LINTED */ be_promote_ds_callback(zfs_handle_t *zhp, void *data) { char origin[MAXPATHLEN]; char *sub_dataset = NULL; int ret = 0; if (zhp != NULL) { sub_dataset = strdup(zfs_get_name(zhp)); if (sub_dataset == NULL) { ret = BE_ERR_NOMEM; goto done; } } else { be_print_err(gettext("be_promote_ds_callback: " "Invalid zfs handle passed into function\n")); ret = BE_ERR_INVAL; goto done; } /* * This loop makes sure that we promote the dataset to the * top of the tree so that it is no longer a decendent of any * dataset. The ZFS close and then open is used to make sure that * the promotion is updated before we move on. */ while (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof (origin), NULL, NULL, 0, B_FALSE) == 0) { if (zfs_promote(zhp) != 0) { if (libzfs_errno(g_zfs) != EZFS_EXISTS) { be_print_err(gettext("be_promote_ds_callback: " "promote of %s failed: %s\n"), zfs_get_name(zhp), libzfs_error_description(g_zfs)); ret = zfs_err_to_be_err(g_zfs); goto done; } else { /* * If the call to zfs_promote returns the * error EZFS_EXISTS we've hit a snapshot name * collision. This means we're probably * attemping to promote a zone dataset above a * parent dataset that belongs to another zone * which this zone was cloned from. * * TODO: If this is a zone dataset at some * point we should skip this if the zone * paths for the dataset and the snapshot * don't match. */ be_print_err(gettext("be_promote_ds_callback: " "promote of %s failed due to snapshot " "name collision: %s\n"), zfs_get_name(zhp), libzfs_error_description(g_zfs)); ret = zfs_err_to_be_err(g_zfs); goto done; } } ZFS_CLOSE(zhp); if ((zhp = zfs_open(g_zfs, sub_dataset, ZFS_TYPE_FILESYSTEM)) == NULL) { be_print_err(gettext("be_promote_ds_callback: " "Failed to open dataset (%s): %s\n"), sub_dataset, libzfs_error_description(g_zfs)); ret = zfs_err_to_be_err(g_zfs); goto done; } } /* Iterate down this dataset's children and promote them */ ret = zfs_iter_filesystems(zhp, be_promote_ds_callback, NULL); done: free(sub_dataset); ZFS_CLOSE(zhp); return (ret); }