xref: /onnv-gate/usr/src/cmd/ndmpd/ndmp/ndmpd_chkpnt.c (revision 12904:aab2c5dd2abc)
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 
44*12904SReza.Sabdar@Sun.COM typedef struct snap_param {
45*12904SReza.Sabdar@Sun.COM 	char *snp_name;
46*12904SReza.Sabdar@Sun.COM 	boolean_t snp_found;
47*12904SReza.Sabdar@Sun.COM } snap_param_t;
487917SReza.Sabdar@Sun.COM 
49*12904SReza.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
677917SReza.Sabdar@Sun.COM ndmp_has_backup(zfs_handle_t *zhp, void *data)
687917SReza.Sabdar@Sun.COM {
697917SReza.Sabdar@Sun.COM 	const char *name;
70*12904SReza.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 ||
74*12904SReza.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 
79*12904SReza.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 /*
86*12904SReza.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
99*12904SReza.Sabdar@Sun.COM ndmp_has_backup_snapshot(char *volname, char *jobname)
1007917SReza.Sabdar@Sun.COM {
1017917SReza.Sabdar@Sun.COM 	zfs_handle_t *zhp;
102*12904SReza.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) {
107*12904SReza.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 
112*12904SReza.Sabdar@Sun.COM 	snp.snp_found = 0;
11312186SJanice.Chang@Sun.COM 	(void) snprintf(chname, ZFS_MAXNAMELEN, "@%s", jobname);
114*12904SReza.Sabdar@Sun.COM 	snp.snp_name = chname;
1157917SReza.Sabdar@Sun.COM 
116*12904SReza.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 
120*12904SReza.Sabdar@Sun.COM 	return (snp.snp_found);
1217917SReza.Sabdar@Sun.COM }
1227917SReza.Sabdar@Sun.COM 
1237917SReza.Sabdar@Sun.COM /*
124*12904SReza.Sabdar@Sun.COM  * ndmp_create_snapshot
1257917SReza.Sabdar@Sun.COM  *
126*12904SReza.Sabdar@Sun.COM  * This function will parse the path to get the real volume name.
127*12904SReza.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
138*12904SReza.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 
146*12904SReza.Sabdar@Sun.COM 	/*
147*12904SReza.Sabdar@Sun.COM 	 * If there is an old snapshot left from the previous
148*12904SReza.Sabdar@Sun.COM 	 * backup it could be stale one and it must be
149*12904SReza.Sabdar@Sun.COM 	 * removed before using it.
150*12904SReza.Sabdar@Sun.COM 	 */
151*12904SReza.Sabdar@Sun.COM 	if (ndmp_has_backup_snapshot(vol, jname))
152*12904SReza.Sabdar@Sun.COM 		(void) snapshot_destroy(vol, jname, B_FALSE, B_TRUE, NULL);
1537917SReza.Sabdar@Sun.COM 
154*12904SReza.Sabdar@Sun.COM 	return (snapshot_create(vol, jname, B_FALSE, B_TRUE));
1557917SReza.Sabdar@Sun.COM }
1567917SReza.Sabdar@Sun.COM 
1577917SReza.Sabdar@Sun.COM /*
158*12904SReza.Sabdar@Sun.COM  * ndmp_remove_snapshot
1597917SReza.Sabdar@Sun.COM  *
160*12904SReza.Sabdar@Sun.COM  * This function will parse the path to get the real volume name.
161*12904SReza.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
172*12904SReza.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 ||
177*12904SReza.Sabdar@Sun.COM 	    get_zfsvolname(vol, sizeof (vol), vol_name) == -1)
1787917SReza.Sabdar@Sun.COM 		return (0);
1797917SReza.Sabdar@Sun.COM 
180*12904SReza.Sabdar@Sun.COM 	return (snapshot_destroy(vol, jname, B_FALSE, B_TRUE, NULL));
181*12904SReza.Sabdar@Sun.COM }
182*12904SReza.Sabdar@Sun.COM 
183*12904SReza.Sabdar@Sun.COM /*
184*12904SReza.Sabdar@Sun.COM  * Put a hold on snapshot
185*12904SReza.Sabdar@Sun.COM  */
186*12904SReza.Sabdar@Sun.COM int
187*12904SReza.Sabdar@Sun.COM snapshot_hold(char *volname, char *snapname, char *jname, boolean_t recursive)
188*12904SReza.Sabdar@Sun.COM {
189*12904SReza.Sabdar@Sun.COM 	zfs_handle_t *zhp;
190*12904SReza.Sabdar@Sun.COM 	char *p;
191*12904SReza.Sabdar@Sun.COM 
192*12904SReza.Sabdar@Sun.COM 	if ((zhp = zfs_open(zlibh, volname, ZFS_TYPE_DATASET)) == 0) {
193*12904SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Cannot open volume %s.", volname);
194*12904SReza.Sabdar@Sun.COM 		return (-1);
195*12904SReza.Sabdar@Sun.COM 	}
196*12904SReza.Sabdar@Sun.COM 
197*12904SReza.Sabdar@Sun.COM 	if (cleanup_fd == -1 && (cleanup_fd = open(ZFS_DEV,
198*12904SReza.Sabdar@Sun.COM 	    O_RDWR|O_EXCL)) < 0) {
199*12904SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Cannot open dev %d", errno);
200*12904SReza.Sabdar@Sun.COM 		zfs_close(zhp);
201*12904SReza.Sabdar@Sun.COM 		return (-1);
202*12904SReza.Sabdar@Sun.COM 	}
203*12904SReza.Sabdar@Sun.COM 
204*12904SReza.Sabdar@Sun.COM 	p = strchr(snapname, '@') + 1;
205*12904SReza.Sabdar@Sun.COM 	if (zfs_hold(zhp, p, jname, recursive, B_TRUE, B_FALSE,
206*12904SReza.Sabdar@Sun.COM 	    cleanup_fd, 0, 0) != 0) {
207*12904SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Cannot hold snapshot %s", p);
208*12904SReza.Sabdar@Sun.COM 		zfs_close(zhp);
209*12904SReza.Sabdar@Sun.COM 		return (-1);
210*12904SReza.Sabdar@Sun.COM 	}
211*12904SReza.Sabdar@Sun.COM 	zfs_close(zhp);
212*12904SReza.Sabdar@Sun.COM 	return (0);
213*12904SReza.Sabdar@Sun.COM }
214*12904SReza.Sabdar@Sun.COM 
215*12904SReza.Sabdar@Sun.COM int
216*12904SReza.Sabdar@Sun.COM snapshot_release(char *volname, char *snapname, char *jname,
217*12904SReza.Sabdar@Sun.COM     boolean_t recursive)
218*12904SReza.Sabdar@Sun.COM {
219*12904SReza.Sabdar@Sun.COM 	zfs_handle_t *zhp;
220*12904SReza.Sabdar@Sun.COM 	char *p;
221*12904SReza.Sabdar@Sun.COM 	int rv = 0;
222*12904SReza.Sabdar@Sun.COM 
223*12904SReza.Sabdar@Sun.COM 	if ((zhp = zfs_open(zlibh, volname, ZFS_TYPE_DATASET)) == 0) {
224*12904SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Cannot open volume %s", volname);
225*12904SReza.Sabdar@Sun.COM 		return (-1);
226*12904SReza.Sabdar@Sun.COM 	}
227*12904SReza.Sabdar@Sun.COM 
228*12904SReza.Sabdar@Sun.COM 	p = strchr(snapname, '@') + 1;
229*12904SReza.Sabdar@Sun.COM 	if (zfs_release(zhp, p, jname, recursive) != 0) {
230*12904SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Cannot release snapshot %s", p);
231*12904SReza.Sabdar@Sun.COM 		rv = -1;
232*12904SReza.Sabdar@Sun.COM 	}
233*12904SReza.Sabdar@Sun.COM 	if (cleanup_fd != -1) {
234*12904SReza.Sabdar@Sun.COM 		(void) close(cleanup_fd);
235*12904SReza.Sabdar@Sun.COM 		cleanup_fd = -1;
236*12904SReza.Sabdar@Sun.COM 	}
237*12904SReza.Sabdar@Sun.COM 	zfs_close(zhp);
238*12904SReza.Sabdar@Sun.COM 	return (rv);
239*12904SReza.Sabdar@Sun.COM }
240*12904SReza.Sabdar@Sun.COM 
241*12904SReza.Sabdar@Sun.COM /*
242*12904SReza.Sabdar@Sun.COM  * Create a snapshot on the volume
243*12904SReza.Sabdar@Sun.COM  */
244*12904SReza.Sabdar@Sun.COM int
245*12904SReza.Sabdar@Sun.COM snapshot_create(char *volname, char *jname, boolean_t recursive,
246*12904SReza.Sabdar@Sun.COM     boolean_t hold)
247*12904SReza.Sabdar@Sun.COM {
248*12904SReza.Sabdar@Sun.COM 	char snapname[ZFS_MAXNAMELEN];
249*12904SReza.Sabdar@Sun.COM 	int rv;
250*12904SReza.Sabdar@Sun.COM 
251*12904SReza.Sabdar@Sun.COM 	if (!volname || !*volname)
252*12904SReza.Sabdar@Sun.COM 		return (-1);
253*12904SReza.Sabdar@Sun.COM 
254*12904SReza.Sabdar@Sun.COM 	(void) snprintf(snapname, ZFS_MAXNAMELEN, "%s@%s", volname, jname);
2557917SReza.Sabdar@Sun.COM 
256*12904SReza.Sabdar@Sun.COM 	(void) mutex_lock(&zlib_mtx);
257*12904SReza.Sabdar@Sun.COM 	if ((rv = zfs_snapshot(zlibh, snapname, recursive, NULL))
258*12904SReza.Sabdar@Sun.COM 	    == -1) {
259*12904SReza.Sabdar@Sun.COM 		if (errno == EEXIST) {
260*12904SReza.Sabdar@Sun.COM 			(void) mutex_unlock(&zlib_mtx);
261*12904SReza.Sabdar@Sun.COM 			return (0);
262*12904SReza.Sabdar@Sun.COM 		}
263*12904SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
264*12904SReza.Sabdar@Sun.COM 		    "snapshot_create: %s failed (err=%d): %s",
265*12904SReza.Sabdar@Sun.COM 		    snapname, errno, libzfs_error_description(zlibh));
266*12904SReza.Sabdar@Sun.COM 		(void) mutex_unlock(&zlib_mtx);
267*12904SReza.Sabdar@Sun.COM 		return (rv);
268*12904SReza.Sabdar@Sun.COM 	}
269*12904SReza.Sabdar@Sun.COM 	if (hold && snapshot_hold(volname, snapname, jname, recursive) != 0) {
270*12904SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
271*12904SReza.Sabdar@Sun.COM 		    "snapshot_create: %s hold failed (err=%d): %s",
272*12904SReza.Sabdar@Sun.COM 		    snapname, errno, libzfs_error_description(zlibh));
273*12904SReza.Sabdar@Sun.COM 		(void) mutex_unlock(&zlib_mtx);
274*12904SReza.Sabdar@Sun.COM 		return (-1);
275*12904SReza.Sabdar@Sun.COM 	}
276*12904SReza.Sabdar@Sun.COM 
277*12904SReza.Sabdar@Sun.COM 	(void) mutex_unlock(&zlib_mtx);
278*12904SReza.Sabdar@Sun.COM 	return (0);
2797917SReza.Sabdar@Sun.COM }
280*12904SReza.Sabdar@Sun.COM 
281*12904SReza.Sabdar@Sun.COM /*
282*12904SReza.Sabdar@Sun.COM  * Remove and release the backup snapshot
283*12904SReza.Sabdar@Sun.COM  */
284*12904SReza.Sabdar@Sun.COM int
285*12904SReza.Sabdar@Sun.COM snapshot_destroy(char *volname, char *jname, boolean_t recursive,
286*12904SReza.Sabdar@Sun.COM     boolean_t hold, int *zfs_err)
287*12904SReza.Sabdar@Sun.COM {
288*12904SReza.Sabdar@Sun.COM 	char snapname[ZFS_MAXNAMELEN];
289*12904SReza.Sabdar@Sun.COM 	zfs_handle_t *zhp;
290*12904SReza.Sabdar@Sun.COM 	zfs_type_t ztype;
291*12904SReza.Sabdar@Sun.COM 	int err;
292*12904SReza.Sabdar@Sun.COM 
293*12904SReza.Sabdar@Sun.COM 	if (zfs_err)
294*12904SReza.Sabdar@Sun.COM 		*zfs_err = 0;
295*12904SReza.Sabdar@Sun.COM 
296*12904SReza.Sabdar@Sun.COM 	if (!volname || !*volname)
297*12904SReza.Sabdar@Sun.COM 		return (-1);
298*12904SReza.Sabdar@Sun.COM 
299*12904SReza.Sabdar@Sun.COM 	if (recursive) {
300*12904SReza.Sabdar@Sun.COM 		ztype = ZFS_TYPE_VOLUME | ZFS_TYPE_FILESYSTEM;
301*12904SReza.Sabdar@Sun.COM 	} else {
302*12904SReza.Sabdar@Sun.COM 		(void) snprintf(snapname, ZFS_MAXNAMELEN, "%s@%s", volname,
303*12904SReza.Sabdar@Sun.COM 		    jname);
304*12904SReza.Sabdar@Sun.COM 		ztype = ZFS_TYPE_SNAPSHOT;
305*12904SReza.Sabdar@Sun.COM 	}
306*12904SReza.Sabdar@Sun.COM 
307*12904SReza.Sabdar@Sun.COM 	(void) mutex_lock(&zlib_mtx);
308*12904SReza.Sabdar@Sun.COM 	if (hold &&
309*12904SReza.Sabdar@Sun.COM 	    snapshot_release(volname, snapname, jname, recursive) != 0) {
310*12904SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
311*12904SReza.Sabdar@Sun.COM 		    "snapshot_destroy: %s release failed (err=%d): %s",
312*12904SReza.Sabdar@Sun.COM 		    snapname, errno, libzfs_error_description(zlibh));
313*12904SReza.Sabdar@Sun.COM 		(void) mutex_unlock(&zlib_mtx);
314*12904SReza.Sabdar@Sun.COM 		return (-1);
315*12904SReza.Sabdar@Sun.COM 	}
316*12904SReza.Sabdar@Sun.COM 
317*12904SReza.Sabdar@Sun.COM 	if ((zhp = zfs_open(zlibh, snapname, ztype)) == NULL) {
318*12904SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "snapshot_destroy: open %s failed",
319*12904SReza.Sabdar@Sun.COM 		    snapname);
320*12904SReza.Sabdar@Sun.COM 		(void) mutex_unlock(&zlib_mtx);
321*12904SReza.Sabdar@Sun.COM 		return (-1);
322*12904SReza.Sabdar@Sun.COM 	}
323*12904SReza.Sabdar@Sun.COM 
324*12904SReza.Sabdar@Sun.COM 	if (recursive) {
325*12904SReza.Sabdar@Sun.COM 		err = zfs_destroy_snaps(zhp, jname, B_TRUE);
326*12904SReza.Sabdar@Sun.COM 	} else {
327*12904SReza.Sabdar@Sun.COM 		err = zfs_destroy(zhp, B_TRUE);
328*12904SReza.Sabdar@Sun.COM 	}
329*12904SReza.Sabdar@Sun.COM 
330*12904SReza.Sabdar@Sun.COM 	if (err) {
331*12904SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "%s (recursive destroy: %d): %d; %s; %s",
332*12904SReza.Sabdar@Sun.COM 		    snapname,
333*12904SReza.Sabdar@Sun.COM 		    recursive,
334*12904SReza.Sabdar@Sun.COM 		    libzfs_errno(zlibh),
335*12904SReza.Sabdar@Sun.COM 		    libzfs_error_action(zlibh),
336*12904SReza.Sabdar@Sun.COM 		    libzfs_error_description(zlibh));
337*12904SReza.Sabdar@Sun.COM 
338*12904SReza.Sabdar@Sun.COM 		if (zfs_err)
339*12904SReza.Sabdar@Sun.COM 			*zfs_err = err;
340*12904SReza.Sabdar@Sun.COM 	}
341*12904SReza.Sabdar@Sun.COM 
342*12904SReza.Sabdar@Sun.COM 	zfs_close(zhp);
343*12904SReza.Sabdar@Sun.COM 	(void) mutex_unlock(&zlib_mtx);
344*12904SReza.Sabdar@Sun.COM 
345*12904SReza.Sabdar@Sun.COM 	return (0);
346*12904SReza.Sabdar@Sun.COM }
347