xref: /illumos-gate/usr/src/cmd/zoneadm/zfs.c (revision ff17c8bf86c3e567734be83f90267edee20f580f)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * This file contains the functions used to support the ZFS integration
31  * with zones.  This includes validation (e.g. zonecfg dataset), cloning,
32  * file system creation and destruction.
33  */
34 
35 #include <stdio.h>
36 #include <errno.h>
37 #include <unistd.h>
38 #include <string.h>
39 #include <locale.h>
40 #include <libintl.h>
41 #include <sys/stat.h>
42 #include <sys/statvfs.h>
43 #include <libgen.h>
44 #include <libzonecfg.h>
45 #include <sys/mnttab.h>
46 #include <libzfs.h>
47 
48 #include "zoneadm.h"
49 
50 libzfs_handle_t *g_zfs;
51 
52 typedef struct zfs_mount_data {
53 	char		*match_name;
54 	zfs_handle_t	*match_handle;
55 } zfs_mount_data_t;
56 
57 typedef struct zfs_snapshot_data {
58 	char	*match_name;
59 	int	len;
60 	int	max;
61 } zfs_snapshot_data_t;
62 
63 /*
64  * A ZFS file system iterator call-back function which is used to validate
65  * datasets imported into the zone.
66  */
67 /* ARGSUSED */
68 static int
69 check_zvol(zfs_handle_t *zhp, void *unused)
70 {
71 	int ret;
72 
73 	if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME) {
74 		/*
75 		 * TRANSLATION_NOTE
76 		 * zfs and dataset are literals that should not be translated.
77 		 */
78 		(void) fprintf(stderr, gettext("cannot verify zfs dataset %s: "
79 		    "volumes cannot be specified as a zone dataset resource\n"),
80 		    zfs_get_name(zhp));
81 		ret = -1;
82 	} else {
83 		ret = zfs_iter_children(zhp, check_zvol, NULL);
84 	}
85 
86 	zfs_close(zhp);
87 
88 	return (ret);
89 }
90 
91 /*
92  * A ZFS file system iterator call-back function which returns the
93  * zfs_handle_t for a ZFS file system on the specified mount point.
94  */
95 static int
96 match_mountpoint(zfs_handle_t *zhp, void *data)
97 {
98 	int			res;
99 	zfs_mount_data_t	*cbp;
100 	char			mp[ZFS_MAXPROPLEN];
101 
102 	if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
103 		zfs_close(zhp);
104 		return (0);
105 	}
106 
107 	cbp = (zfs_mount_data_t *)data;
108 	if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mp, sizeof (mp), NULL, NULL,
109 	    0, B_FALSE) == 0 && strcmp(mp, cbp->match_name) == 0) {
110 		cbp->match_handle = zhp;
111 		return (1);
112 	}
113 
114 	res = zfs_iter_filesystems(zhp, match_mountpoint, data);
115 	zfs_close(zhp);
116 	return (res);
117 }
118 
119 /*
120  * Get ZFS handle for the specified mount point.
121  */
122 static zfs_handle_t *
123 mount2zhandle(char *mountpoint)
124 {
125 	zfs_mount_data_t	cb;
126 
127 	cb.match_name = mountpoint;
128 	cb.match_handle = NULL;
129 	(void) zfs_iter_root(g_zfs, match_mountpoint, &cb);
130 	return (cb.match_handle);
131 }
132 
133 /*
134  * Check if there is already a file system (zfs or any other type) mounted on
135  * path.
136  */
137 static boolean_t
138 is_mountpnt(char *path)
139 {
140 	FILE		*fp;
141 	struct mnttab	entry;
142 
143 	if ((fp = fopen("/etc/mnttab", "r")) == NULL)
144 		return (B_FALSE);
145 
146 	while (getmntent(fp, &entry) == 0) {
147 		if (strcmp(path, entry.mnt_mountp) == 0) {
148 			(void) fclose(fp);
149 			return (B_TRUE);
150 		}
151 	}
152 
153 	(void) fclose(fp);
154 	return (B_FALSE);
155 }
156 
157 /*
158  * Run the brand's pre-snapshot hook before we take a ZFS snapshot of the zone.
159  */
160 static int
161 pre_snapshot(char *presnapbuf)
162 {
163 	int status;
164 
165 	/* No brand-specific handler */
166 	if (presnapbuf[0] == '\0')
167 		return (Z_OK);
168 
169 	/* Run the hook */
170 	status = do_subproc_interactive(presnapbuf);
171 	if ((status = subproc_status(gettext("brand-specific presnapshot"),
172 	    status, B_FALSE)) != ZONE_SUBPROC_OK)
173 		return (Z_ERR);
174 
175 	return (Z_OK);
176 }
177 
178 /*
179  * Run the brand's post-snapshot hook after we take a ZFS snapshot of the zone.
180  */
181 static int
182 post_snapshot(char *postsnapbuf)
183 {
184 	int status;
185 
186 	/* No brand-specific handler */
187 	if (postsnapbuf[0] == '\0')
188 		return (Z_OK);
189 
190 	/* Run the hook */
191 	status = do_subproc_interactive(postsnapbuf);
192 	if ((status = subproc_status(gettext("brand-specific postsnapshot"),
193 	    status, B_FALSE)) != ZONE_SUBPROC_OK)
194 		return (Z_ERR);
195 
196 	return (Z_OK);
197 }
198 
199 /*
200  * This is a ZFS snapshot iterator call-back function which returns the
201  * highest number of SUNWzone snapshots that have been taken.
202  */
203 static int
204 get_snap_max(zfs_handle_t *zhp, void *data)
205 {
206 	int			res;
207 	zfs_snapshot_data_t	*cbp;
208 
209 	if (zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) {
210 		zfs_close(zhp);
211 		return (0);
212 	}
213 
214 	cbp = (zfs_snapshot_data_t *)data;
215 
216 	if (strncmp(zfs_get_name(zhp), cbp->match_name, cbp->len) == 0) {
217 		char	*nump;
218 		int	num;
219 
220 		nump = (char *)(zfs_get_name(zhp) + cbp->len);
221 		num = atoi(nump);
222 		if (num > cbp->max)
223 			cbp->max = num;
224 	}
225 
226 	res = zfs_iter_snapshots(zhp, get_snap_max, data);
227 	zfs_close(zhp);
228 	return (res);
229 }
230 
231 /*
232  * Take a ZFS snapshot to be used for cloning the zone.
233  */
234 static int
235 take_snapshot(zfs_handle_t *zhp, char *snapshot_name, int snap_size,
236     char *presnapbuf, char *postsnapbuf)
237 {
238 	int			res;
239 	char			template[ZFS_MAXNAMELEN];
240 	zfs_snapshot_data_t	cb;
241 
242 	/*
243 	 * First we need to figure out the next available name for the
244 	 * zone snapshot.  Look through the list of zones snapshots for
245 	 * this file system to determine the maximum snapshot name.
246 	 */
247 	if (snprintf(template, sizeof (template), "%s@SUNWzone",
248 	    zfs_get_name(zhp)) >=  sizeof (template))
249 		return (Z_ERR);
250 
251 	cb.match_name = template;
252 	cb.len = strlen(template);
253 	cb.max = 0;
254 
255 	if (zfs_iter_snapshots(zhp, get_snap_max, &cb) != 0)
256 		return (Z_ERR);
257 
258 	cb.max++;
259 
260 	if (snprintf(snapshot_name, snap_size, "%s@SUNWzone%d",
261 	    zfs_get_name(zhp), cb.max) >= snap_size)
262 		return (Z_ERR);
263 
264 	if (pre_snapshot(presnapbuf) != Z_OK)
265 		return (Z_ERR);
266 	res = zfs_snapshot(g_zfs, snapshot_name, B_FALSE);
267 	if (post_snapshot(postsnapbuf) != Z_OK)
268 		return (Z_ERR);
269 
270 	if (res != 0)
271 		return (Z_ERR);
272 	return (Z_OK);
273 }
274 
275 /*
276  * We are using an explicit snapshot from some earlier point in time so
277  * we need to validate it.  Run the brand specific hook.
278  */
279 static int
280 validate_snapshot(char *snapshot_name, char *snap_path, char *validsnapbuf)
281 {
282 	int status;
283 	char cmdbuf[MAXPATHLEN];
284 
285 	/* No brand-specific handler */
286 	if (validsnapbuf[0] == '\0')
287 		return (Z_OK);
288 
289 	/* pass args - snapshot_name & snap_path */
290 	if (snprintf(cmdbuf, sizeof (cmdbuf), "%s %s %s", validsnapbuf,
291 	    snapshot_name, snap_path) >= sizeof (cmdbuf)) {
292 		zerror("Command line too long");
293 		return (Z_ERR);
294 	}
295 
296 	/* Run the hook */
297 	status = do_subproc_interactive(cmdbuf);
298 	if ((status = subproc_status(gettext("brand-specific validatesnapshot"),
299 	    status, B_FALSE)) != ZONE_SUBPROC_OK)
300 		return (Z_ERR);
301 
302 	return (Z_OK);
303 }
304 
305 /*
306  * Remove the sw inventory file from inside this zonepath that we picked up out
307  * of the snapshot.
308  */
309 static int
310 clean_out_clone()
311 {
312 	int err;
313 	zone_dochandle_t handle;
314 
315 	if ((handle = zonecfg_init_handle()) == NULL) {
316 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
317 		return (Z_ERR);
318 	}
319 
320 	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
321 		errno = err;
322 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
323 		zonecfg_fini_handle(handle);
324 		return (Z_ERR);
325 	}
326 
327 	zonecfg_rm_detached(handle, B_FALSE);
328 	zonecfg_fini_handle(handle);
329 
330 	return (Z_OK);
331 }
332 
333 /*
334  * Make a ZFS clone on zonepath from snapshot_name.
335  */
336 static int
337 clone_snap(char *snapshot_name, char *zonepath)
338 {
339 	int		res = Z_OK;
340 	int		err;
341 	zfs_handle_t	*zhp;
342 	zfs_handle_t	*clone;
343 	nvlist_t	*props = NULL;
344 
345 	if ((zhp = zfs_open(g_zfs, snapshot_name, ZFS_TYPE_SNAPSHOT)) == NULL)
346 		return (Z_NO_ENTRY);
347 
348 	(void) printf(gettext("Cloning snapshot %s\n"), snapshot_name);
349 
350 	if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0 ||
351 	    nvlist_add_string(props, zfs_prop_to_name(ZFS_PROP_SHARENFS),
352 	    "off") != 0) {
353 		if (props != NULL)
354 			nvlist_free(props);
355 		(void) fprintf(stderr, gettext("could not create ZFS clone "
356 		    "%s: out of memory\n"), zonepath);
357 		return (Z_ERR);
358 	}
359 
360 	err = zfs_clone(zhp, zonepath, props);
361 	zfs_close(zhp);
362 
363 	nvlist_free(props);
364 
365 	if (err != 0)
366 		return (Z_ERR);
367 
368 	/* create the mountpoint if necessary */
369 	if ((clone = zfs_open(g_zfs, zonepath, ZFS_TYPE_DATASET)) == NULL)
370 		return (Z_ERR);
371 
372 	/*
373 	 * The clone has been created so we need to print a diagnostic
374 	 * message if one of the following steps fails for some reason.
375 	 */
376 	if (zfs_mount(clone, NULL, 0) != 0) {
377 		(void) fprintf(stderr, gettext("could not mount ZFS clone "
378 		    "%s\n"), zfs_get_name(clone));
379 		res = Z_ERR;
380 
381 	} else if (clean_out_clone() != Z_OK) {
382 		(void) fprintf(stderr, gettext("could not remove the "
383 		    "software inventory from ZFS clone %s\n"),
384 		    zfs_get_name(clone));
385 		res = Z_ERR;
386 	}
387 
388 	zfs_close(clone);
389 	return (res);
390 }
391 
392 /*
393  * This function takes a zonepath and attempts to determine what the ZFS
394  * file system name (not mountpoint) should be for that path.  We do not
395  * assume that zonepath is an existing directory or ZFS fs since we use
396  * this function as part of the process of creating a new ZFS fs or clone.
397  *
398  * The way this works is that we look at the parent directory of the zonepath
399  * to see if it is a ZFS fs.  If it is, we get the name of that ZFS fs and
400  * append the last component of the zonepath to generate the ZFS name for the
401  * zonepath.  This matches the algorithm that ZFS uses for automatically
402  * mounting a new fs after it is created.
403  *
404  * Although a ZFS fs can be mounted anywhere, we don't worry about handling
405  * all of the complexity that a user could possibly configure with arbitrary
406  * mounts since there is no way to generate a ZFS name from a random path in
407  * the file system.  We only try to handle the automatic mounts that ZFS does
408  * for each file system.  ZFS restricts this so that a new fs must be created
409  * in an existing parent ZFS fs.  It then automatically mounts the new fs
410  * directly under the mountpoint for the parent fs using the last component
411  * of the name as the mountpoint directory.
412  *
413  * For example:
414  *    Name			Mountpoint
415  *    space/eng/dev/test/zone1	/project1/eng/dev/test/zone1
416  *
417  * Return Z_OK if the path mapped to a ZFS file system name, otherwise return
418  * Z_ERR.
419  */
420 static int
421 path2name(char *zonepath, char *zfs_name, int len)
422 {
423 	int		res;
424 	char		*p;
425 	zfs_handle_t	*zhp;
426 
427 	if ((p = strrchr(zonepath, '/')) == NULL)
428 		return (Z_ERR);
429 
430 	/*
431 	 * If the parent directory is not its own ZFS fs, then we can't
432 	 * automatically create a new ZFS fs at the 'zonepath' mountpoint
433 	 * so return an error.
434 	 */
435 	*p = '\0';
436 	zhp = mount2zhandle(zonepath);
437 	*p = '/';
438 	if (zhp == NULL)
439 		return (Z_ERR);
440 
441 	res = snprintf(zfs_name, len, "%s/%s", zfs_get_name(zhp), p + 1);
442 
443 	zfs_close(zhp);
444 	if (res >= len)
445 		return (Z_ERR);
446 
447 	return (Z_OK);
448 }
449 
450 /*
451  * A ZFS file system iterator call-back function used to determine if the
452  * file system has dependents (snapshots & clones).
453  */
454 /* ARGSUSED */
455 static int
456 has_dependent(zfs_handle_t *zhp, void *data)
457 {
458 	zfs_close(zhp);
459 	return (1);
460 }
461 
462 /*
463  * Given a snapshot name, get the file system path where the snapshot lives.
464  * A snapshot name is of the form fs_name@snap_name.  For example, snapshot
465  * pl/zones/z1@SUNWzone1 would have a path of
466  * /pl/zones/z1/.zfs/snapshot/SUNWzone1.
467  */
468 static int
469 snap2path(char *snap_name, char *path, int len)
470 {
471 	char		*p;
472 	zfs_handle_t	*zhp;
473 	char		mp[ZFS_MAXPROPLEN];
474 
475 	if ((p = strrchr(snap_name, '@')) == NULL)
476 		return (Z_ERR);
477 
478 	/* Get the file system name from the snap_name. */
479 	*p = '\0';
480 	zhp = zfs_open(g_zfs, snap_name, ZFS_TYPE_DATASET);
481 	*p = '@';
482 	if (zhp == NULL)
483 		return (Z_ERR);
484 
485 	/* Get the file system mount point. */
486 	if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mp, sizeof (mp), NULL, NULL,
487 	    0, B_FALSE) != 0) {
488 		zfs_close(zhp);
489 		return (Z_ERR);
490 	}
491 	zfs_close(zhp);
492 
493 	p++;
494 	if (snprintf(path, len, "%s/.zfs/snapshot/%s", mp, p) >= len)
495 		return (Z_ERR);
496 
497 	return (Z_OK);
498 }
499 
500 /*
501  * Clone a pre-existing ZFS snapshot, either by making a direct ZFS clone, if
502  * possible, or by copying the data from the snapshot to the zonepath.
503  */
504 int
505 clone_snapshot_zfs(char *snap_name, char *zonepath, char *validatesnap)
506 {
507 	int	err = Z_OK;
508 	char	clone_name[MAXPATHLEN];
509 	char	snap_path[MAXPATHLEN];
510 
511 	if (snap2path(snap_name, snap_path, sizeof (snap_path)) != Z_OK) {
512 		(void) fprintf(stderr, gettext("unable to find path for %s.\n"),
513 		    snap_name);
514 		return (Z_ERR);
515 	}
516 
517 	if (validate_snapshot(snap_name, snap_path, validatesnap) != Z_OK)
518 		return (Z_NO_ENTRY);
519 
520 	/*
521 	 * The zonepath cannot be ZFS cloned, try to copy the data from
522 	 * within the snapshot to the zonepath.
523 	 */
524 	if (path2name(zonepath, clone_name, sizeof (clone_name)) != Z_OK) {
525 		if ((err = clone_copy(snap_path, zonepath)) == Z_OK)
526 			if (clean_out_clone() != Z_OK)
527 				(void) fprintf(stderr,
528 				    gettext("could not remove the "
529 				    "software inventory from %s\n"), zonepath);
530 
531 		return (err);
532 	}
533 
534 	if ((err = clone_snap(snap_name, clone_name)) != Z_OK) {
535 		if (err != Z_NO_ENTRY) {
536 			/*
537 			 * Cloning the snapshot failed.  Fall back to trying
538 			 * to install the zone by copying from the snapshot.
539 			 */
540 			if ((err = clone_copy(snap_path, zonepath)) == Z_OK)
541 				if (clean_out_clone() != Z_OK)
542 					(void) fprintf(stderr,
543 					    gettext("could not remove the "
544 					    "software inventory from %s\n"),
545 					    zonepath);
546 		} else {
547 			/*
548 			 * The snapshot is unusable for some reason so restore
549 			 * the zone state to configured since we were unable to
550 			 * actually do anything about getting the zone
551 			 * installed.
552 			 */
553 			int tmp;
554 
555 			if ((tmp = zone_set_state(target_zone,
556 			    ZONE_STATE_CONFIGURED)) != Z_OK) {
557 				errno = tmp;
558 				zperror2(target_zone,
559 				    gettext("could not set state"));
560 			}
561 		}
562 	}
563 
564 	return (err);
565 }
566 
567 /*
568  * Attempt to clone a source_zone to a target zonepath by using a ZFS clone.
569  */
570 int
571 clone_zfs(char *source_zonepath, char *zonepath, char *presnapbuf,
572     char *postsnapbuf)
573 {
574 	zfs_handle_t	*zhp;
575 	char		clone_name[MAXPATHLEN];
576 	char		snap_name[MAXPATHLEN];
577 
578 	/*
579 	 * Try to get a zfs handle for the source_zonepath.  If this fails
580 	 * the source_zonepath is not ZFS so return an error.
581 	 */
582 	if ((zhp = mount2zhandle(source_zonepath)) == NULL)
583 		return (Z_ERR);
584 
585 	/*
586 	 * Check if there is a file system already mounted on zonepath.  If so,
587 	 * we can't clone to the path so we should fall back to copying.
588 	 */
589 	if (is_mountpnt(zonepath)) {
590 		zfs_close(zhp);
591 		(void) fprintf(stderr,
592 		    gettext("A file system is already mounted on %s,\n"
593 		    "preventing use of a ZFS clone.\n"), zonepath);
594 		return (Z_ERR);
595 	}
596 
597 	/*
598 	 * Instead of using path2name to get the clone name from the zonepath,
599 	 * we could generate a name from the source zone ZFS name.  However,
600 	 * this would mean we would create the clone under the ZFS fs of the
601 	 * source instead of what the zonepath says.  For example,
602 	 *
603 	 * source_zonepath		zonepath
604 	 * /pl/zones/dev/z1		/pl/zones/deploy/z2
605 	 *
606 	 * We don't want the clone to be under "dev", we want it under
607 	 * "deploy", so that we can leverage the normal attribute inheritance
608 	 * that ZFS provides in the fs hierarchy.
609 	 */
610 	if (path2name(zonepath, clone_name, sizeof (clone_name)) != Z_OK) {
611 		zfs_close(zhp);
612 		return (Z_ERR);
613 	}
614 
615 	if (take_snapshot(zhp, snap_name, sizeof (snap_name), presnapbuf,
616 	    postsnapbuf) != Z_OK) {
617 		zfs_close(zhp);
618 		return (Z_ERR);
619 	}
620 	zfs_close(zhp);
621 
622 	if (clone_snap(snap_name, clone_name) != Z_OK) {
623 		/* Clean up the snapshot we just took. */
624 		if ((zhp = zfs_open(g_zfs, snap_name, ZFS_TYPE_SNAPSHOT))
625 		    != NULL) {
626 			if (zfs_unmount(zhp, NULL, 0) == 0)
627 				(void) zfs_destroy(zhp);
628 			zfs_close(zhp);
629 		}
630 
631 		return (Z_ERR);
632 	}
633 
634 	(void) printf(gettext("Instead of copying, a ZFS clone has been "
635 	    "created for this zone.\n"));
636 
637 	return (Z_OK);
638 }
639 
640 /*
641  * Attempt to create a ZFS file system for the specified zonepath.
642  * We either will successfully create a ZFS file system and get it mounted
643  * on the zonepath or we don't.  The caller doesn't care since a regular
644  * directory is used for the zonepath if no ZFS file system is mounted there.
645  */
646 void
647 create_zfs_zonepath(char *zonepath)
648 {
649 	zfs_handle_t	*zhp;
650 	char		zfs_name[MAXPATHLEN];
651 	nvlist_t	*props = NULL;
652 
653 	if (path2name(zonepath, zfs_name, sizeof (zfs_name)) != Z_OK)
654 		return;
655 
656 	if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0 ||
657 	    nvlist_add_string(props, zfs_prop_to_name(ZFS_PROP_SHARENFS),
658 	    "off") != 0) {
659 		if (props != NULL)
660 			nvlist_free(props);
661 		(void) fprintf(stderr, gettext("cannot create ZFS dataset %s: "
662 		    "out of memory\n"), zfs_name);
663 	}
664 
665 	if (zfs_create(g_zfs, zfs_name, ZFS_TYPE_FILESYSTEM, props) != 0 ||
666 	    (zhp = zfs_open(g_zfs, zfs_name, ZFS_TYPE_DATASET)) == NULL) {
667 		(void) fprintf(stderr, gettext("cannot create ZFS dataset %s: "
668 		    "%s\n"), zfs_name, libzfs_error_description(g_zfs));
669 		nvlist_free(props);
670 		return;
671 	}
672 
673 	nvlist_free(props);
674 
675 	if (zfs_mount(zhp, NULL, 0) != 0) {
676 		(void) fprintf(stderr, gettext("cannot mount ZFS dataset %s: "
677 		    "%s\n"), zfs_name, libzfs_error_description(g_zfs));
678 		(void) zfs_destroy(zhp);
679 	} else {
680 		if (chmod(zonepath, S_IRWXU) != 0) {
681 			(void) fprintf(stderr, gettext("file system %s "
682 			    "successfully created, but chmod %o failed: %s\n"),
683 			    zfs_name, S_IRWXU, strerror(errno));
684 			(void) destroy_zfs(zonepath);
685 		} else {
686 			(void) printf(gettext("A ZFS file system has been "
687 			    "created for this zone.\n"));
688 		}
689 	}
690 
691 	zfs_close(zhp);
692 }
693 
694 /*
695  * If the zonepath is a ZFS file system, attempt to destroy it.  We return Z_OK
696  * if we were able to zfs_destroy the zonepath, otherwise we return Z_ERR
697  * which means the caller should clean up the zonepath in the traditional
698  * way.
699  */
700 int
701 destroy_zfs(char *zonepath)
702 {
703 	zfs_handle_t	*zhp;
704 	boolean_t	is_clone = B_FALSE;
705 	char		origin[ZFS_MAXPROPLEN];
706 
707 	if ((zhp = mount2zhandle(zonepath)) == NULL)
708 		return (Z_ERR);
709 
710 	/*
711 	 * We can't destroy the file system if it has dependents.
712 	 */
713 	if (zfs_iter_dependents(zhp, B_TRUE, has_dependent, NULL) != 0 ||
714 	    zfs_unmount(zhp, NULL, 0) != 0) {
715 		zfs_close(zhp);
716 		return (Z_ERR);
717 	}
718 
719 	/*
720 	 * This might be a clone.  Try to get the snapshot so we can attempt
721 	 * to destroy that as well.
722 	 */
723 	if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof (origin), NULL,
724 	    NULL, 0, B_FALSE) == 0)
725 		is_clone = B_TRUE;
726 
727 	if (zfs_destroy(zhp) != 0) {
728 		/*
729 		 * If the destroy fails for some reason, try to remount
730 		 * the file system so that we can use "rm -rf" to clean up
731 		 * instead.
732 		 */
733 		(void) zfs_mount(zhp, NULL, 0);
734 		zfs_close(zhp);
735 		return (Z_ERR);
736 	}
737 
738 	/*
739 	 * If the zone has ever been moved then the mountpoint dir will not be
740 	 * cleaned up by the zfs_destroy().  To handle this case try to clean
741 	 * it up now but don't worry if it fails, that will be normal.
742 	 */
743 	(void) rmdir(zonepath);
744 
745 	(void) printf(gettext("The ZFS file system for this zone has been "
746 	    "destroyed.\n"));
747 
748 	if (is_clone) {
749 		zfs_handle_t	*ohp;
750 
751 		/*
752 		 * Try to clean up the snapshot that the clone was taken from.
753 		 */
754 		if ((ohp = zfs_open(g_zfs, origin,
755 		    ZFS_TYPE_SNAPSHOT)) != NULL) {
756 			if (zfs_iter_dependents(ohp, B_TRUE, has_dependent,
757 			    NULL) == 0 && zfs_unmount(ohp, NULL, 0) == 0)
758 				(void) zfs_destroy(ohp);
759 			zfs_close(ohp);
760 		}
761 	}
762 
763 	zfs_close(zhp);
764 	return (Z_OK);
765 }
766 
767 /*
768  * Return true if the path is its own zfs file system.  We determine this
769  * by stat-ing the path to see if it is zfs and stat-ing the parent to see
770  * if it is a different fs.
771  */
772 boolean_t
773 is_zonepath_zfs(char *zonepath)
774 {
775 	int res;
776 	char *path;
777 	char *parent;
778 	struct statvfs64 buf1, buf2;
779 
780 	if (statvfs64(zonepath, &buf1) != 0)
781 		return (B_FALSE);
782 
783 	if (strcmp(buf1.f_basetype, "zfs") != 0)
784 		return (B_FALSE);
785 
786 	if ((path = strdup(zonepath)) == NULL)
787 		return (B_FALSE);
788 
789 	parent = dirname(path);
790 	res = statvfs64(parent, &buf2);
791 	free(path);
792 
793 	if (res != 0)
794 		return (B_FALSE);
795 
796 	if (buf1.f_fsid == buf2.f_fsid)
797 		return (B_FALSE);
798 
799 	return (B_TRUE);
800 }
801 
802 /*
803  * Implement the fast move of a ZFS file system by simply updating the
804  * mountpoint.  Since it is file system already, we don't have the
805  * issue of cross-file system copying.
806  */
807 int
808 move_zfs(char *zonepath, char *new_zonepath)
809 {
810 	int		ret = Z_ERR;
811 	zfs_handle_t	*zhp;
812 
813 	if ((zhp = mount2zhandle(zonepath)) == NULL)
814 		return (Z_ERR);
815 
816 	if (zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
817 	    new_zonepath) == 0) {
818 		/*
819 		 * Clean up the old mount point.  We ignore any failure since
820 		 * the zone is already successfully mounted on the new path.
821 		 */
822 		(void) rmdir(zonepath);
823 		ret = Z_OK;
824 	}
825 
826 	zfs_close(zhp);
827 
828 	return (ret);
829 }
830 
831 /*
832  * Validate that the given dataset exists on the system, and that neither it nor
833  * its children are zvols.
834  *
835  * Note that we don't do anything with the 'zoned' property here.  All
836  * management is done in zoneadmd when the zone is actually rebooted.  This
837  * allows us to automatically set the zoned property even when a zone is
838  * rebooted by the administrator.
839  */
840 int
841 verify_datasets(zone_dochandle_t handle)
842 {
843 	int return_code = Z_OK;
844 	struct zone_dstab dstab;
845 	zfs_handle_t *zhp;
846 	char propbuf[ZFS_MAXPROPLEN];
847 	char source[ZFS_MAXNAMELEN];
848 	zprop_source_t srctype;
849 
850 	if (zonecfg_setdsent(handle) != Z_OK) {
851 		/*
852 		 * TRANSLATION_NOTE
853 		 * zfs and dataset are literals that should not be translated.
854 		 */
855 		(void) fprintf(stderr, gettext("could not verify zfs datasets: "
856 		    "unable to enumerate datasets\n"));
857 		return (Z_ERR);
858 	}
859 
860 	while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
861 
862 		if ((zhp = zfs_open(g_zfs, dstab.zone_dataset_name,
863 		    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) == NULL) {
864 			(void) fprintf(stderr, gettext("could not verify zfs "
865 			    "dataset %s: %s\n"), dstab.zone_dataset_name,
866 			    libzfs_error_description(g_zfs));
867 			return_code = Z_ERR;
868 			continue;
869 		}
870 
871 		if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf,
872 		    sizeof (propbuf), &srctype, source,
873 		    sizeof (source), 0) == 0 &&
874 		    (srctype == ZPROP_SRC_INHERITED)) {
875 			(void) fprintf(stderr, gettext("could not verify zfs "
876 			    "dataset %s: mountpoint cannot be inherited\n"),
877 			    dstab.zone_dataset_name);
878 			return_code = Z_ERR;
879 			zfs_close(zhp);
880 			continue;
881 		}
882 
883 		if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME) {
884 			(void) fprintf(stderr, gettext("cannot verify zfs "
885 			    "dataset %s: volumes cannot be specified as a "
886 			    "zone dataset resource\n"),
887 			    dstab.zone_dataset_name);
888 			return_code = Z_ERR;
889 		}
890 
891 		if (zfs_iter_children(zhp, check_zvol, NULL) != 0)
892 			return_code = Z_ERR;
893 
894 		zfs_close(zhp);
895 	}
896 	(void) zonecfg_enddsent(handle);
897 
898 	return (return_code);
899 }
900 
901 /*
902  * Verify that the ZFS dataset exists, and its mountpoint
903  * property is set to "legacy".
904  */
905 int
906 verify_fs_zfs(struct zone_fstab *fstab)
907 {
908 	zfs_handle_t *zhp;
909 	char propbuf[ZFS_MAXPROPLEN];
910 
911 	if ((zhp = zfs_open(g_zfs, fstab->zone_fs_special,
912 	    ZFS_TYPE_DATASET)) == NULL) {
913 		(void) fprintf(stderr, gettext("could not verify fs %s: "
914 		    "could not access zfs dataset '%s'\n"),
915 		    fstab->zone_fs_dir, fstab->zone_fs_special);
916 		return (Z_ERR);
917 	}
918 
919 	if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
920 		(void) fprintf(stderr, gettext("cannot verify fs %s: "
921 		    "'%s' is not a file system\n"),
922 		    fstab->zone_fs_dir, fstab->zone_fs_special);
923 		zfs_close(zhp);
924 		return (Z_ERR);
925 	}
926 
927 	if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf, sizeof (propbuf),
928 	    NULL, NULL, 0, 0) != 0 || strcmp(propbuf, "legacy") != 0) {
929 		(void) fprintf(stderr, gettext("could not verify fs %s: "
930 		    "zfs '%s' mountpoint is not \"legacy\"\n"),
931 		    fstab->zone_fs_dir, fstab->zone_fs_special);
932 		zfs_close(zhp);
933 		return (Z_ERR);
934 	}
935 
936 	zfs_close(zhp);
937 	return (Z_OK);
938 }
939 
940 int
941 init_zfs(void)
942 {
943 	if ((g_zfs = libzfs_init()) == NULL) {
944 		(void) fprintf(stderr, gettext("failed to initialize ZFS "
945 		    "library\n"));
946 		return (Z_ERR);
947 	}
948 
949 	return (Z_OK);
950 }
951