17917SReza.Sabdar@Sun.COM /*
212186SJanice.Chang@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
37917SReza.Sabdar@Sun.COM */
47917SReza.Sabdar@Sun.COM
57917SReza.Sabdar@Sun.COM /*
67917SReza.Sabdar@Sun.COM * BSD 3 Clause License
77917SReza.Sabdar@Sun.COM *
87917SReza.Sabdar@Sun.COM * Copyright (c) 2007, The Storage Networking Industry Association.
97917SReza.Sabdar@Sun.COM *
107917SReza.Sabdar@Sun.COM * Redistribution and use in source and binary forms, with or without
117917SReza.Sabdar@Sun.COM * modification, are permitted provided that the following conditions
127917SReza.Sabdar@Sun.COM * are met:
137917SReza.Sabdar@Sun.COM * - Redistributions of source code must retain the above copyright
147917SReza.Sabdar@Sun.COM * notice, this list of conditions and the following disclaimer.
157917SReza.Sabdar@Sun.COM *
167917SReza.Sabdar@Sun.COM * - Redistributions in binary form must reproduce the above copyright
177917SReza.Sabdar@Sun.COM * notice, this list of conditions and the following disclaimer in
187917SReza.Sabdar@Sun.COM * the documentation and/or other materials provided with the
197917SReza.Sabdar@Sun.COM * distribution.
207917SReza.Sabdar@Sun.COM *
217917SReza.Sabdar@Sun.COM * - Neither the name of The Storage Networking Industry Association (SNIA)
227917SReza.Sabdar@Sun.COM * nor the names of its contributors may be used to endorse or promote
237917SReza.Sabdar@Sun.COM * products derived from this software without specific prior written
247917SReza.Sabdar@Sun.COM * permission.
257917SReza.Sabdar@Sun.COM *
267917SReza.Sabdar@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
277917SReza.Sabdar@Sun.COM * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
287917SReza.Sabdar@Sun.COM * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
297917SReza.Sabdar@Sun.COM * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
307917SReza.Sabdar@Sun.COM * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
317917SReza.Sabdar@Sun.COM * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
327917SReza.Sabdar@Sun.COM * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
337917SReza.Sabdar@Sun.COM * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
347917SReza.Sabdar@Sun.COM * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
357917SReza.Sabdar@Sun.COM * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
367917SReza.Sabdar@Sun.COM * POSSIBILITY OF SUCH DAMAGE.
377917SReza.Sabdar@Sun.COM */
387917SReza.Sabdar@Sun.COM
397917SReza.Sabdar@Sun.COM #include <stdio.h>
407917SReza.Sabdar@Sun.COM #include <string.h>
417917SReza.Sabdar@Sun.COM #include "ndmpd.h"
427917SReza.Sabdar@Sun.COM #include <libzfs.h>
437917SReza.Sabdar@Sun.COM
4412904SReza.Sabdar@Sun.COM typedef struct snap_param {
4512904SReza.Sabdar@Sun.COM char *snp_name;
4612904SReza.Sabdar@Sun.COM boolean_t snp_found;
4712904SReza.Sabdar@Sun.COM } snap_param_t;
487917SReza.Sabdar@Sun.COM
4912904SReza.Sabdar@Sun.COM static int cleanup_fd = -1;
507917SReza.Sabdar@Sun.COM
517917SReza.Sabdar@Sun.COM /*
527917SReza.Sabdar@Sun.COM * ndmp_has_backup
537917SReza.Sabdar@Sun.COM *
547917SReza.Sabdar@Sun.COM * Call backup function which looks for backup snapshot.
557917SReza.Sabdar@Sun.COM * This is a callback function used with zfs_iter_snapshots.
567917SReza.Sabdar@Sun.COM *
577917SReza.Sabdar@Sun.COM * Parameters:
587917SReza.Sabdar@Sun.COM * zhp (input) - ZFS handle pointer
597917SReza.Sabdar@Sun.COM * data (output) - 0 - no backup snapshot
607917SReza.Sabdar@Sun.COM * 1 - has backup snapshot
617917SReza.Sabdar@Sun.COM *
627917SReza.Sabdar@Sun.COM * Returns:
637917SReza.Sabdar@Sun.COM * 0: on success
647917SReza.Sabdar@Sun.COM * -1: otherwise
657917SReza.Sabdar@Sun.COM */
667917SReza.Sabdar@Sun.COM static int
ndmp_has_backup(zfs_handle_t * zhp,void * data)677917SReza.Sabdar@Sun.COM ndmp_has_backup(zfs_handle_t *zhp, void *data)
687917SReza.Sabdar@Sun.COM {
697917SReza.Sabdar@Sun.COM const char *name;
7012904SReza.Sabdar@Sun.COM snap_param_t *chp = (snap_param_t *)data;
717917SReza.Sabdar@Sun.COM
727917SReza.Sabdar@Sun.COM name = zfs_get_name(zhp);
737917SReza.Sabdar@Sun.COM if (name == NULL ||
7412904SReza.Sabdar@Sun.COM strstr(name, chp->snp_name) == NULL) {
757917SReza.Sabdar@Sun.COM zfs_close(zhp);
767917SReza.Sabdar@Sun.COM return (-1);
777917SReza.Sabdar@Sun.COM }
787917SReza.Sabdar@Sun.COM
7912904SReza.Sabdar@Sun.COM chp->snp_found = 1;
807917SReza.Sabdar@Sun.COM zfs_close(zhp);
817917SReza.Sabdar@Sun.COM
827917SReza.Sabdar@Sun.COM return (0);
837917SReza.Sabdar@Sun.COM }
847917SReza.Sabdar@Sun.COM
857917SReza.Sabdar@Sun.COM /*
8612904SReza.Sabdar@Sun.COM * ndmp_has_backup_snapshot
877917SReza.Sabdar@Sun.COM *
887917SReza.Sabdar@Sun.COM * Returns TRUE if the volume has an active backup snapshot, otherwise,
897917SReza.Sabdar@Sun.COM * returns FALSE.
907917SReza.Sabdar@Sun.COM *
917917SReza.Sabdar@Sun.COM * Parameters:
927917SReza.Sabdar@Sun.COM * volname (input) - name of the volume
937917SReza.Sabdar@Sun.COM *
947917SReza.Sabdar@Sun.COM * Returns:
957917SReza.Sabdar@Sun.COM * 0: on success
967917SReza.Sabdar@Sun.COM * -1: otherwise
977917SReza.Sabdar@Sun.COM */
987917SReza.Sabdar@Sun.COM static int
ndmp_has_backup_snapshot(char * volname,char * jobname)9912904SReza.Sabdar@Sun.COM ndmp_has_backup_snapshot(char *volname, char *jobname)
1007917SReza.Sabdar@Sun.COM {
1017917SReza.Sabdar@Sun.COM zfs_handle_t *zhp;
10212904SReza.Sabdar@Sun.COM snap_param_t snp;
1037917SReza.Sabdar@Sun.COM char chname[ZFS_MAXNAMELEN];
1047917SReza.Sabdar@Sun.COM
1057917SReza.Sabdar@Sun.COM (void) mutex_lock(&zlib_mtx);
1067917SReza.Sabdar@Sun.COM if ((zhp = zfs_open(zlibh, volname, ZFS_TYPE_DATASET)) == 0) {
10712904SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Cannot open snapshot %s.", volname);
1087917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
1097917SReza.Sabdar@Sun.COM return (-1);
1107917SReza.Sabdar@Sun.COM }
1117917SReza.Sabdar@Sun.COM
11212904SReza.Sabdar@Sun.COM snp.snp_found = 0;
11312186SJanice.Chang@Sun.COM (void) snprintf(chname, ZFS_MAXNAMELEN, "@%s", jobname);
11412904SReza.Sabdar@Sun.COM snp.snp_name = chname;
1157917SReza.Sabdar@Sun.COM
11612904SReza.Sabdar@Sun.COM (void) zfs_iter_snapshots(zhp, ndmp_has_backup, &snp);
1177917SReza.Sabdar@Sun.COM zfs_close(zhp);
1187917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
1197917SReza.Sabdar@Sun.COM
12012904SReza.Sabdar@Sun.COM return (snp.snp_found);
1217917SReza.Sabdar@Sun.COM }
1227917SReza.Sabdar@Sun.COM
1237917SReza.Sabdar@Sun.COM /*
12412904SReza.Sabdar@Sun.COM * ndmp_create_snapshot
1257917SReza.Sabdar@Sun.COM *
12612904SReza.Sabdar@Sun.COM * This function will parse the path to get the real volume name.
12712904SReza.Sabdar@Sun.COM * It will then create a snapshot based on volume and job name.
1287917SReza.Sabdar@Sun.COM * This function should be called before the NDMP backup is started.
1297917SReza.Sabdar@Sun.COM *
1307917SReza.Sabdar@Sun.COM * Parameters:
1317917SReza.Sabdar@Sun.COM * vol_name (input) - name of the volume
1327917SReza.Sabdar@Sun.COM *
1337917SReza.Sabdar@Sun.COM * Returns:
1347917SReza.Sabdar@Sun.COM * 0: on success
1357917SReza.Sabdar@Sun.COM * -1: otherwise
1367917SReza.Sabdar@Sun.COM */
1377917SReza.Sabdar@Sun.COM int
ndmp_create_snapshot(char * vol_name,char * jname)13812904SReza.Sabdar@Sun.COM ndmp_create_snapshot(char *vol_name, char *jname)
1397917SReza.Sabdar@Sun.COM {
1407917SReza.Sabdar@Sun.COM char vol[ZFS_MAXNAMELEN];
1417917SReza.Sabdar@Sun.COM
1427917SReza.Sabdar@Sun.COM if (vol_name == 0 ||
1437917SReza.Sabdar@Sun.COM get_zfsvolname(vol, sizeof (vol), vol_name) == -1)
1447917SReza.Sabdar@Sun.COM return (0);
1457917SReza.Sabdar@Sun.COM
14612904SReza.Sabdar@Sun.COM /*
14712904SReza.Sabdar@Sun.COM * If there is an old snapshot left from the previous
14812904SReza.Sabdar@Sun.COM * backup it could be stale one and it must be
14912904SReza.Sabdar@Sun.COM * removed before using it.
15012904SReza.Sabdar@Sun.COM */
15112904SReza.Sabdar@Sun.COM if (ndmp_has_backup_snapshot(vol, jname))
15212904SReza.Sabdar@Sun.COM (void) snapshot_destroy(vol, jname, B_FALSE, B_TRUE, NULL);
1537917SReza.Sabdar@Sun.COM
15412904SReza.Sabdar@Sun.COM return (snapshot_create(vol, jname, B_FALSE, B_TRUE));
1557917SReza.Sabdar@Sun.COM }
1567917SReza.Sabdar@Sun.COM
1577917SReza.Sabdar@Sun.COM /*
15812904SReza.Sabdar@Sun.COM * ndmp_remove_snapshot
1597917SReza.Sabdar@Sun.COM *
16012904SReza.Sabdar@Sun.COM * This function will parse the path to get the real volume name.
16112904SReza.Sabdar@Sun.COM * It will then remove the snapshot for that volume and job name.
1627917SReza.Sabdar@Sun.COM * This function should be called after NDMP backup is finished.
1637917SReza.Sabdar@Sun.COM *
1647917SReza.Sabdar@Sun.COM * Parameters:
1657917SReza.Sabdar@Sun.COM * vol_name (input) - name of the volume
1667917SReza.Sabdar@Sun.COM *
1677917SReza.Sabdar@Sun.COM * Returns:
1687917SReza.Sabdar@Sun.COM * 0: on success
1697917SReza.Sabdar@Sun.COM * -1: otherwise
1707917SReza.Sabdar@Sun.COM */
1717917SReza.Sabdar@Sun.COM int
ndmp_remove_snapshot(char * vol_name,char * jname)17212904SReza.Sabdar@Sun.COM ndmp_remove_snapshot(char *vol_name, char *jname)
1737917SReza.Sabdar@Sun.COM {
1747917SReza.Sabdar@Sun.COM char vol[ZFS_MAXNAMELEN];
1757917SReza.Sabdar@Sun.COM
1767917SReza.Sabdar@Sun.COM if (vol_name == 0 ||
17712904SReza.Sabdar@Sun.COM get_zfsvolname(vol, sizeof (vol), vol_name) == -1)
1787917SReza.Sabdar@Sun.COM return (0);
1797917SReza.Sabdar@Sun.COM
18012904SReza.Sabdar@Sun.COM return (snapshot_destroy(vol, jname, B_FALSE, B_TRUE, NULL));
18112904SReza.Sabdar@Sun.COM }
18212904SReza.Sabdar@Sun.COM
18312904SReza.Sabdar@Sun.COM /*
18412904SReza.Sabdar@Sun.COM * Put a hold on snapshot
18512904SReza.Sabdar@Sun.COM */
18612904SReza.Sabdar@Sun.COM int
snapshot_hold(char * volname,char * snapname,char * jname,boolean_t recursive)18712904SReza.Sabdar@Sun.COM snapshot_hold(char *volname, char *snapname, char *jname, boolean_t recursive)
18812904SReza.Sabdar@Sun.COM {
18912904SReza.Sabdar@Sun.COM zfs_handle_t *zhp;
19012904SReza.Sabdar@Sun.COM char *p;
19112904SReza.Sabdar@Sun.COM
19212904SReza.Sabdar@Sun.COM if ((zhp = zfs_open(zlibh, volname, ZFS_TYPE_DATASET)) == 0) {
19312904SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Cannot open volume %s.", volname);
19412904SReza.Sabdar@Sun.COM return (-1);
19512904SReza.Sabdar@Sun.COM }
19612904SReza.Sabdar@Sun.COM
19712904SReza.Sabdar@Sun.COM if (cleanup_fd == -1 && (cleanup_fd = open(ZFS_DEV,
19812904SReza.Sabdar@Sun.COM O_RDWR|O_EXCL)) < 0) {
19912904SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Cannot open dev %d", errno);
20012904SReza.Sabdar@Sun.COM zfs_close(zhp);
20112904SReza.Sabdar@Sun.COM return (-1);
20212904SReza.Sabdar@Sun.COM }
20312904SReza.Sabdar@Sun.COM
20412904SReza.Sabdar@Sun.COM p = strchr(snapname, '@') + 1;
20512904SReza.Sabdar@Sun.COM if (zfs_hold(zhp, p, jname, recursive, B_TRUE, B_FALSE,
20612904SReza.Sabdar@Sun.COM cleanup_fd, 0, 0) != 0) {
20712904SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Cannot hold snapshot %s", p);
20812904SReza.Sabdar@Sun.COM zfs_close(zhp);
20912904SReza.Sabdar@Sun.COM return (-1);
21012904SReza.Sabdar@Sun.COM }
21112904SReza.Sabdar@Sun.COM zfs_close(zhp);
21212904SReza.Sabdar@Sun.COM return (0);
21312904SReza.Sabdar@Sun.COM }
21412904SReza.Sabdar@Sun.COM
21512904SReza.Sabdar@Sun.COM int
snapshot_release(char * volname,char * snapname,char * jname,boolean_t recursive)21612904SReza.Sabdar@Sun.COM snapshot_release(char *volname, char *snapname, char *jname,
21712904SReza.Sabdar@Sun.COM boolean_t recursive)
21812904SReza.Sabdar@Sun.COM {
21912904SReza.Sabdar@Sun.COM zfs_handle_t *zhp;
22012904SReza.Sabdar@Sun.COM char *p;
22112904SReza.Sabdar@Sun.COM int rv = 0;
22212904SReza.Sabdar@Sun.COM
22312904SReza.Sabdar@Sun.COM if ((zhp = zfs_open(zlibh, volname, ZFS_TYPE_DATASET)) == 0) {
22412904SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Cannot open volume %s", volname);
22512904SReza.Sabdar@Sun.COM return (-1);
22612904SReza.Sabdar@Sun.COM }
22712904SReza.Sabdar@Sun.COM
22812904SReza.Sabdar@Sun.COM p = strchr(snapname, '@') + 1;
22912904SReza.Sabdar@Sun.COM if (zfs_release(zhp, p, jname, recursive) != 0) {
23012904SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Cannot release snapshot %s", p);
23112904SReza.Sabdar@Sun.COM rv = -1;
23212904SReza.Sabdar@Sun.COM }
23312904SReza.Sabdar@Sun.COM if (cleanup_fd != -1) {
23412904SReza.Sabdar@Sun.COM (void) close(cleanup_fd);
23512904SReza.Sabdar@Sun.COM cleanup_fd = -1;
23612904SReza.Sabdar@Sun.COM }
23712904SReza.Sabdar@Sun.COM zfs_close(zhp);
23812904SReza.Sabdar@Sun.COM return (rv);
23912904SReza.Sabdar@Sun.COM }
24012904SReza.Sabdar@Sun.COM
24112904SReza.Sabdar@Sun.COM /*
24212904SReza.Sabdar@Sun.COM * Create a snapshot on the volume
24312904SReza.Sabdar@Sun.COM */
24412904SReza.Sabdar@Sun.COM int
snapshot_create(char * volname,char * jname,boolean_t recursive,boolean_t hold)24512904SReza.Sabdar@Sun.COM snapshot_create(char *volname, char *jname, boolean_t recursive,
24612904SReza.Sabdar@Sun.COM boolean_t hold)
24712904SReza.Sabdar@Sun.COM {
24812904SReza.Sabdar@Sun.COM char snapname[ZFS_MAXNAMELEN];
24912904SReza.Sabdar@Sun.COM int rv;
25012904SReza.Sabdar@Sun.COM
25112904SReza.Sabdar@Sun.COM if (!volname || !*volname)
25212904SReza.Sabdar@Sun.COM return (-1);
25312904SReza.Sabdar@Sun.COM
25412904SReza.Sabdar@Sun.COM (void) snprintf(snapname, ZFS_MAXNAMELEN, "%s@%s", volname, jname);
2557917SReza.Sabdar@Sun.COM
25612904SReza.Sabdar@Sun.COM (void) mutex_lock(&zlib_mtx);
25712904SReza.Sabdar@Sun.COM if ((rv = zfs_snapshot(zlibh, snapname, recursive, NULL))
25812904SReza.Sabdar@Sun.COM == -1) {
25912904SReza.Sabdar@Sun.COM if (errno == EEXIST) {
26012904SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
26112904SReza.Sabdar@Sun.COM return (0);
26212904SReza.Sabdar@Sun.COM }
26312904SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
26412904SReza.Sabdar@Sun.COM "snapshot_create: %s failed (err=%d): %s",
26512904SReza.Sabdar@Sun.COM snapname, errno, libzfs_error_description(zlibh));
26612904SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
26712904SReza.Sabdar@Sun.COM return (rv);
26812904SReza.Sabdar@Sun.COM }
26912904SReza.Sabdar@Sun.COM if (hold && snapshot_hold(volname, snapname, jname, recursive) != 0) {
27012904SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
27112904SReza.Sabdar@Sun.COM "snapshot_create: %s hold failed (err=%d): %s",
27212904SReza.Sabdar@Sun.COM snapname, errno, libzfs_error_description(zlibh));
27312904SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
27412904SReza.Sabdar@Sun.COM return (-1);
27512904SReza.Sabdar@Sun.COM }
27612904SReza.Sabdar@Sun.COM
27712904SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
27812904SReza.Sabdar@Sun.COM return (0);
2797917SReza.Sabdar@Sun.COM }
28012904SReza.Sabdar@Sun.COM
28112904SReza.Sabdar@Sun.COM /*
28212904SReza.Sabdar@Sun.COM * Remove and release the backup snapshot
28312904SReza.Sabdar@Sun.COM */
28412904SReza.Sabdar@Sun.COM int
snapshot_destroy(char * volname,char * jname,boolean_t recursive,boolean_t hold,int * zfs_err)28512904SReza.Sabdar@Sun.COM snapshot_destroy(char *volname, char *jname, boolean_t recursive,
28612904SReza.Sabdar@Sun.COM boolean_t hold, int *zfs_err)
28712904SReza.Sabdar@Sun.COM {
28812904SReza.Sabdar@Sun.COM char snapname[ZFS_MAXNAMELEN];
28912904SReza.Sabdar@Sun.COM zfs_handle_t *zhp;
29012904SReza.Sabdar@Sun.COM zfs_type_t ztype;
291*13023SReza.Sabdar@Sun.COM char *namep;
29212904SReza.Sabdar@Sun.COM int err;
29312904SReza.Sabdar@Sun.COM
29412904SReza.Sabdar@Sun.COM if (zfs_err)
29512904SReza.Sabdar@Sun.COM *zfs_err = 0;
29612904SReza.Sabdar@Sun.COM
29712904SReza.Sabdar@Sun.COM if (!volname || !*volname)
29812904SReza.Sabdar@Sun.COM return (-1);
29912904SReza.Sabdar@Sun.COM
30012904SReza.Sabdar@Sun.COM if (recursive) {
30112904SReza.Sabdar@Sun.COM ztype = ZFS_TYPE_VOLUME | ZFS_TYPE_FILESYSTEM;
302*13023SReza.Sabdar@Sun.COM namep = volname;
30312904SReza.Sabdar@Sun.COM } else {
30412904SReza.Sabdar@Sun.COM (void) snprintf(snapname, ZFS_MAXNAMELEN, "%s@%s", volname,
30512904SReza.Sabdar@Sun.COM jname);
306*13023SReza.Sabdar@Sun.COM namep = snapname;
30712904SReza.Sabdar@Sun.COM ztype = ZFS_TYPE_SNAPSHOT;
30812904SReza.Sabdar@Sun.COM }
30912904SReza.Sabdar@Sun.COM
31012904SReza.Sabdar@Sun.COM (void) mutex_lock(&zlib_mtx);
31112904SReza.Sabdar@Sun.COM if (hold &&
312*13023SReza.Sabdar@Sun.COM snapshot_release(volname, namep, jname, recursive) != 0) {
31312904SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
31412904SReza.Sabdar@Sun.COM "snapshot_destroy: %s release failed (err=%d): %s",
315*13023SReza.Sabdar@Sun.COM namep, errno, libzfs_error_description(zlibh));
31612904SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
31712904SReza.Sabdar@Sun.COM return (-1);
31812904SReza.Sabdar@Sun.COM }
31912904SReza.Sabdar@Sun.COM
320*13023SReza.Sabdar@Sun.COM if ((zhp = zfs_open(zlibh, namep, ztype)) == NULL) {
32112904SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "snapshot_destroy: open %s failed",
322*13023SReza.Sabdar@Sun.COM namep);
32312904SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
32412904SReza.Sabdar@Sun.COM return (-1);
32512904SReza.Sabdar@Sun.COM }
32612904SReza.Sabdar@Sun.COM
32712904SReza.Sabdar@Sun.COM if (recursive) {
32812904SReza.Sabdar@Sun.COM err = zfs_destroy_snaps(zhp, jname, B_TRUE);
32912904SReza.Sabdar@Sun.COM } else {
33012904SReza.Sabdar@Sun.COM err = zfs_destroy(zhp, B_TRUE);
33112904SReza.Sabdar@Sun.COM }
33212904SReza.Sabdar@Sun.COM
33312904SReza.Sabdar@Sun.COM if (err) {
33412904SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "%s (recursive destroy: %d): %d; %s; %s",
335*13023SReza.Sabdar@Sun.COM namep,
33612904SReza.Sabdar@Sun.COM recursive,
33712904SReza.Sabdar@Sun.COM libzfs_errno(zlibh),
33812904SReza.Sabdar@Sun.COM libzfs_error_action(zlibh),
33912904SReza.Sabdar@Sun.COM libzfs_error_description(zlibh));
34012904SReza.Sabdar@Sun.COM
34112904SReza.Sabdar@Sun.COM if (zfs_err)
34212904SReza.Sabdar@Sun.COM *zfs_err = err;
34312904SReza.Sabdar@Sun.COM }
34412904SReza.Sabdar@Sun.COM
34512904SReza.Sabdar@Sun.COM zfs_close(zhp);
34612904SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
34712904SReza.Sabdar@Sun.COM
34812904SReza.Sabdar@Sun.COM return (0);
34912904SReza.Sabdar@Sun.COM }
350