ndmpd_chkpnt.c revision a7a845e4bf22fd1b2a284729ccd95c7370a0438c
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
8c4f9701439555b41fbfe7848508f53b52166007Janice Chang * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens * Copyright (c) 2013 by Delphix. All rights reserved.
a7a845e4bf22fd1b2a284729ccd95c7370a0438cSteven Hartland * Copyright (c) 2013 Steven Hartland. All rights reserved.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * BSD 3 Clause License
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Copyright (c) 2007, The Storage Networking Industry Association.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Redistribution and use in source and binary forms, with or without
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * modification, are permitted provided that the following conditions
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * are met:
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * - Redistributions of source code must retain the above copyright
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * notice, this list of conditions and the following disclaimer.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * - Redistributions in binary form must reproduce the above copyright
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * notice, this list of conditions and the following disclaimer in
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * the documentation and/or other materials provided with the
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * distribution.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * - Neither the name of The Storage Networking Industry Association (SNIA)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * nor the names of its contributors may be used to endorse or promote
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * products derived from this software without specific prior written
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * permission.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * POSSIBILITY OF SUCH DAMAGE.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <stdio.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <string.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include "ndmpd.h"
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <libzfs.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdartypedef struct snap_param {
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar char *snp_name;
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar boolean_t snp_found;
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar} snap_param_t;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdarstatic int cleanup_fd = -1;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * ndmp_has_backup
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Call backup function which looks for backup snapshot.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * This is a callback function used with zfs_iter_snapshots.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Parameters:
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * zhp (input) - ZFS handle pointer
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * data (output) - 0 - no backup snapshot
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * 1 - has backup snapshot
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Returns:
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * 0: on success
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * -1: otherwise
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarstatic int
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarndmp_has_backup(zfs_handle_t *zhp, void *data)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar const char *name;
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar snap_param_t *chp = (snap_param_t *)data;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar name = zfs_get_name(zhp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (name == NULL ||
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar strstr(name, chp->snp_name) == NULL) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar zfs_close(zhp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar chp->snp_found = 1;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar zfs_close(zhp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (0);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * ndmp_has_backup_snapshot
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Returns TRUE if the volume has an active backup snapshot, otherwise,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * returns FALSE.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Parameters:
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * volname (input) - name of the volume
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Returns:
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * 0: on success
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * -1: otherwise
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarstatic int
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdarndmp_has_backup_snapshot(char *volname, char *jobname)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar zfs_handle_t *zhp;
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar snap_param_t snp;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char chname[ZFS_MAXNAMELEN];
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) mutex_lock(&zlib_mtx);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if ((zhp = zfs_open(zlibh, volname, ZFS_TYPE_DATASET)) == 0) {
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar NDMP_LOG(LOG_ERR, "Cannot open snapshot %s.", volname);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) mutex_unlock(&zlib_mtx);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar snp.snp_found = 0;
8c4f9701439555b41fbfe7848508f53b52166007Janice Chang (void) snprintf(chname, ZFS_MAXNAMELEN, "@%s", jobname);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar snp.snp_name = chname;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar (void) zfs_iter_snapshots(zhp, ndmp_has_backup, &snp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar zfs_close(zhp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) mutex_unlock(&zlib_mtx);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar return (snp.snp_found);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * ndmp_create_snapshot
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * This function will parse the path to get the real volume name.
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * It will then create a snapshot based on volume and job name.
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * This function should be called before the NDMP backup is started.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Parameters:
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * vol_name (input) - name of the volume
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Returns:
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * 0: on success
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * -1: otherwise
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdarint
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdarndmp_create_snapshot(char *vol_name, char *jname)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar char vol[ZFS_MAXNAMELEN];
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if (vol_name == 0 ||
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar get_zfsvolname(vol, sizeof (vol), vol_name) == -1)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (0);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar /*
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * If there is an old snapshot left from the previous
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * backup it could be stale one and it must be
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * removed before using it.
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar */
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if (ndmp_has_backup_snapshot(vol, jname))
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar (void) snapshot_destroy(vol, jname, B_FALSE, B_TRUE, NULL);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar return (snapshot_create(vol, jname, B_FALSE, B_TRUE));
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * ndmp_remove_snapshot
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * This function will parse the path to get the real volume name.
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * It will then remove the snapshot for that volume and job name.
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * This function should be called after NDMP backup is finished.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Parameters:
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * vol_name (input) - name of the volume
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Returns:
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * 0: on success
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * -1: otherwise
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdarint
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdarndmp_remove_snapshot(char *vol_name, char *jname)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar char vol[ZFS_MAXNAMELEN];
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if (vol_name == 0 ||
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar get_zfsvolname(vol, sizeof (vol), vol_name) == -1)
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar return (0);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar return (snapshot_destroy(vol, jname, B_FALSE, B_TRUE, NULL));
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar}
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar/*
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * Put a hold on snapshot
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar */
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdarint
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdarsnapshot_hold(char *volname, char *snapname, char *jname, boolean_t recursive)
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar{
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar zfs_handle_t *zhp;
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar char *p;
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if ((zhp = zfs_open(zlibh, volname, ZFS_TYPE_DATASET)) == 0) {
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar NDMP_LOG(LOG_ERR, "Cannot open volume %s.", volname);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar return (-1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if (cleanup_fd == -1 && (cleanup_fd = open(ZFS_DEV,
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar O_RDWR|O_EXCL)) < 0) {
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar NDMP_LOG(LOG_ERR, "Cannot open dev %d", errno);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar zfs_close(zhp);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar return (-1);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar }
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar p = strchr(snapname, '@') + 1;
a7a845e4bf22fd1b2a284729ccd95c7370a0438cSteven Hartland if (zfs_hold(zhp, p, jname, recursive, cleanup_fd) != 0) {
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar NDMP_LOG(LOG_ERR, "Cannot hold snapshot %s", p);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar zfs_close(zhp);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar return (-1);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar }
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar zfs_close(zhp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (0);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdarint
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdarsnapshot_release(char *volname, char *snapname, char *jname,
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar boolean_t recursive)
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar{
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar zfs_handle_t *zhp;
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar char *p;
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar int rv = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if ((zhp = zfs_open(zlibh, volname, ZFS_TYPE_DATASET)) == 0) {
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar NDMP_LOG(LOG_ERR, "Cannot open volume %s", volname);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar return (-1);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar p = strchr(snapname, '@') + 1;
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if (zfs_release(zhp, p, jname, recursive) != 0) {
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar NDMP_LOG(LOG_DEBUG, "Cannot release snapshot %s", p);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar rv = -1;
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar }
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if (cleanup_fd != -1) {
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar (void) close(cleanup_fd);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar cleanup_fd = -1;
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar }
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar zfs_close(zhp);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar return (rv);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * Create a snapshot on the volume
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarint
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdarsnapshot_create(char *volname, char *jname, boolean_t recursive,
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar boolean_t hold)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar char snapname[ZFS_MAXNAMELEN];
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar int rv;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if (!volname || !*volname)
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar return (-1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar (void) snprintf(snapname, ZFS_MAXNAMELEN, "%s@%s", volname, jname);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar (void) mutex_lock(&zlib_mtx);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if ((rv = zfs_snapshot(zlibh, snapname, recursive, NULL))
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar == -1) {
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if (errno == EEXIST) {
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar (void) mutex_unlock(&zlib_mtx);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar return (0);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar }
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar NDMP_LOG(LOG_DEBUG,
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar "snapshot_create: %s failed (err=%d): %s",
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar snapname, errno, libzfs_error_description(zlibh));
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar (void) mutex_unlock(&zlib_mtx);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar return (rv);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar }
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if (hold && snapshot_hold(volname, snapname, jname, recursive) != 0) {
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar NDMP_LOG(LOG_DEBUG,
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar "snapshot_create: %s hold failed (err=%d): %s",
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar snapname, errno, libzfs_error_description(zlibh));
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar (void) mutex_unlock(&zlib_mtx);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar return (-1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar (void) mutex_unlock(&zlib_mtx);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar return (0);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar * Remove and release the backup snapshot
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarint
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdarsnapshot_destroy(char *volname, char *jname, boolean_t recursive,
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar boolean_t hold, int *zfs_err)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar char snapname[ZFS_MAXNAMELEN];
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar zfs_handle_t *zhp;
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar zfs_type_t ztype;
588541fbf64fffe619698198cef04af1900f1f86Reza Sabdar char *namep;
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar int err;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if (zfs_err)
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar *zfs_err = 0;
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if (!volname || !*volname)
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar return (-1);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if (recursive) {
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar ztype = ZFS_TYPE_VOLUME | ZFS_TYPE_FILESYSTEM;
588541fbf64fffe619698198cef04af1900f1f86Reza Sabdar namep = volname;
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar } else {
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar (void) snprintf(snapname, ZFS_MAXNAMELEN, "%s@%s", volname,
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar jname);
588541fbf64fffe619698198cef04af1900f1f86Reza Sabdar namep = snapname;
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar ztype = ZFS_TYPE_SNAPSHOT;
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar }
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar (void) mutex_lock(&zlib_mtx);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if (hold &&
588541fbf64fffe619698198cef04af1900f1f86Reza Sabdar snapshot_release(volname, namep, jname, recursive) != 0) {
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar NDMP_LOG(LOG_DEBUG,
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar "snapshot_destroy: %s release failed (err=%d): %s",
588541fbf64fffe619698198cef04af1900f1f86Reza Sabdar namep, errno, libzfs_error_description(zlibh));
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar (void) mutex_unlock(&zlib_mtx);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar return (-1);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar }
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar
588541fbf64fffe619698198cef04af1900f1f86Reza Sabdar if ((zhp = zfs_open(zlibh, namep, ztype)) == NULL) {
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar NDMP_LOG(LOG_DEBUG, "snapshot_destroy: open %s failed",
588541fbf64fffe619698198cef04af1900f1f86Reza Sabdar namep);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar (void) mutex_unlock(&zlib_mtx);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar return (-1);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar }
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if (recursive) {
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar err = zfs_destroy_snaps(zhp, jname, B_TRUE);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar } else {
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar err = zfs_destroy(zhp, B_TRUE);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar }
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if (err) {
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar NDMP_LOG(LOG_ERR, "%s (recursive destroy: %d): %d; %s; %s",
588541fbf64fffe619698198cef04af1900f1f86Reza Sabdar namep,
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar recursive,
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar libzfs_errno(zlibh),
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar libzfs_error_action(zlibh),
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar libzfs_error_description(zlibh));
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar if (zfs_err)
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar *zfs_err = err;
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar zfs_close(zhp);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar (void) mutex_unlock(&zlib_mtx);
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar
876b86efac620aaabc70ad2ed4bfb715ce714875Reza Sabdar return (0);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}