xref: /illumos-gate/usr/src/cmd/zoneadm/zfs.c (revision 394707299ee511c373a7a164a534980fb01d39d0)
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 2007 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  * Perform any necessary housekeeping tasks we need to do before we take
159  * a ZFS snapshot of the zone.  What this really entails is that we are
160  * taking a sw inventory of the source zone, like we do when we detach,
161  * so that there is the XML manifest in the snapshot.  We use that to
162  * validate the snapshot if it is the source of a clone at some later time.
163  */
164 static int
165 pre_snapshot(char *source_zone)
166 {
167 	int err;
168 	zone_dochandle_t handle;
169 
170 	if ((handle = zonecfg_init_handle()) == NULL) {
171 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
172 		return (Z_ERR);
173 	}
174 
175 	if ((err = zonecfg_get_handle(source_zone, handle)) != Z_OK) {
176 		errno = err;
177 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
178 		zonecfg_fini_handle(handle);
179 		return (Z_ERR);
180 	}
181 
182 	if ((err = zonecfg_get_detach_info(handle, B_TRUE)) != Z_OK) {
183 		errno = err;
184 		zperror(gettext("getting the software version information "
185 		    "failed"), B_TRUE);
186 		zonecfg_fini_handle(handle);
187 		return (Z_ERR);
188 	}
189 
190 	if ((err = zonecfg_detach_save(handle, 0)) != Z_OK) {
191 		errno = err;
192 		zperror(gettext("saving the software version manifest failed"),
193 		    B_TRUE);
194 		zonecfg_fini_handle(handle);
195 		return (Z_ERR);
196 	}
197 
198 	zonecfg_fini_handle(handle);
199 	return (Z_OK);
200 }
201 
202 /*
203  * Perform any necessary housekeeping tasks we need to do after we take
204  * a ZFS snapshot of the zone.  What this really entails is removing the
205  * sw inventory XML file from the zone.  It is still in the snapshot where
206  * we want it, but we don't want it in the source zone itself.
207  */
208 static int
209 post_snapshot(char *source_zone)
210 {
211 	int err;
212 	zone_dochandle_t handle;
213 
214 	if ((handle = zonecfg_init_handle()) == NULL) {
215 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
216 		return (Z_ERR);
217 	}
218 
219 	if ((err = zonecfg_get_handle(source_zone, handle)) != Z_OK) {
220 		errno = err;
221 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
222 		zonecfg_fini_handle(handle);
223 		return (Z_ERR);
224 	}
225 
226 	zonecfg_rm_detached(handle, B_FALSE);
227 	zonecfg_fini_handle(handle);
228 
229 	return (Z_OK);
230 }
231 
232 /*
233  * This is a ZFS snapshot iterator call-back function which returns the
234  * highest number of SUNWzone snapshots that have been taken.
235  */
236 static int
237 get_snap_max(zfs_handle_t *zhp, void *data)
238 {
239 	int			res;
240 	zfs_snapshot_data_t	*cbp;
241 
242 	if (zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) {
243 		zfs_close(zhp);
244 		return (0);
245 	}
246 
247 	cbp = (zfs_snapshot_data_t *)data;
248 
249 	if (strncmp(zfs_get_name(zhp), cbp->match_name, cbp->len) == 0) {
250 		char	*nump;
251 		int	num;
252 
253 		nump = (char *)(zfs_get_name(zhp) + cbp->len);
254 		num = atoi(nump);
255 		if (num > cbp->max)
256 			cbp->max = num;
257 	}
258 
259 	res = zfs_iter_snapshots(zhp, get_snap_max, data);
260 	zfs_close(zhp);
261 	return (res);
262 }
263 
264 /*
265  * Take a ZFS snapshot to be used for cloning the zone.
266  */
267 static int
268 take_snapshot(char *source_zone, zfs_handle_t *zhp, char *snapshot_name,
269     int snap_size)
270 {
271 	int			res;
272 	char			template[ZFS_MAXNAMELEN];
273 	zfs_snapshot_data_t	cb;
274 
275 	/*
276 	 * First we need to figure out the next available name for the
277 	 * zone snapshot.  Look through the list of zones snapshots for
278 	 * this file system to determine the maximum snapshot name.
279 	 */
280 	if (snprintf(template, sizeof (template), "%s@SUNWzone",
281 	    zfs_get_name(zhp)) >=  sizeof (template))
282 		return (Z_ERR);
283 
284 	cb.match_name = template;
285 	cb.len = strlen(template);
286 	cb.max = 0;
287 
288 	if (zfs_iter_snapshots(zhp, get_snap_max, &cb) != 0)
289 		return (Z_ERR);
290 
291 	cb.max++;
292 
293 	if (snprintf(snapshot_name, snap_size, "%s@SUNWzone%d",
294 	    zfs_get_name(zhp), cb.max) >= snap_size)
295 		return (Z_ERR);
296 
297 	if (pre_snapshot(source_zone) != Z_OK)
298 		return (Z_ERR);
299 	res = zfs_snapshot(g_zfs, snapshot_name, B_FALSE);
300 	if (post_snapshot(source_zone) != Z_OK)
301 		return (Z_ERR);
302 
303 	if (res != 0)
304 		return (Z_ERR);
305 	return (Z_OK);
306 }
307 
308 /*
309  * We are using an explicit snapshot from some earlier point in time so
310  * we need to validate it.  This involves checking the sw inventory that
311  * we took when we made the snapshot to verify that the current sw config
312  * on the host is still valid to run a zone made from this snapshot.
313  */
314 static int
315 validate_snapshot(char *snapshot_name, char *snap_path)
316 {
317 	int err;
318 	zone_dochandle_t handle;
319 	zone_dochandle_t athandle = NULL;
320 
321 	if ((handle = zonecfg_init_handle()) == NULL) {
322 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
323 		return (Z_ERR);
324 	}
325 
326 	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
327 		errno = err;
328 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
329 		zonecfg_fini_handle(handle);
330 		return (Z_ERR);
331 	}
332 
333 	if ((athandle = zonecfg_init_handle()) == NULL) {
334 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
335 		goto done;
336 	}
337 
338 	if ((err = zonecfg_get_attach_handle(snap_path, target_zone, B_TRUE,
339 	    athandle)) != Z_OK) {
340 		if (err == Z_NO_ZONE)
341 			(void) fprintf(stderr, gettext("snapshot %s was not "
342 			    "taken\n\tby a 'zoneadm clone' command.  It can "
343 			    "not be used to clone zones.\n"), snapshot_name);
344 		else
345 			(void) fprintf(stderr, gettext("snapshot %s is "
346 			    "out-dated\n\tIt can no longer be used to clone "
347 			    "zones on this system.\n"), snapshot_name);
348 		goto done;
349 	}
350 
351 	/* Get the detach information for the locally defined zone. */
352 	if ((err = zonecfg_get_detach_info(handle, B_FALSE)) != Z_OK) {
353 		errno = err;
354 		zperror(gettext("getting the attach information failed"),
355 		    B_TRUE);
356 		goto done;
357 	}
358 
359 	if ((err = sw_cmp(handle, athandle, SW_CMP_SILENT)) != Z_OK)
360 		(void) fprintf(stderr, gettext("snapshot %s is out-dated\n\t"
361 		    "It can no longer be used to clone zones on this "
362 		    "system.\n"), snapshot_name);
363 
364 done:
365 	zonecfg_fini_handle(handle);
366 	if (athandle != NULL)
367 		zonecfg_fini_handle(athandle);
368 
369 	return (err);
370 }
371 
372 /*
373  * Remove the sw inventory file from inside this zonepath that we picked up out
374  * of the snapshot.
375  */
376 static int
377 clean_out_clone()
378 {
379 	int err;
380 	zone_dochandle_t handle;
381 
382 	if ((handle = zonecfg_init_handle()) == NULL) {
383 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
384 		return (Z_ERR);
385 	}
386 
387 	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
388 		errno = err;
389 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
390 		zonecfg_fini_handle(handle);
391 		return (Z_ERR);
392 	}
393 
394 	zonecfg_rm_detached(handle, B_FALSE);
395 	zonecfg_fini_handle(handle);
396 
397 	return (Z_OK);
398 }
399 
400 /*
401  * Make a ZFS clone on zonepath from snapshot_name.
402  */
403 static int
404 clone_snap(char *snapshot_name, char *zonepath)
405 {
406 	int		res = Z_OK;
407 	int		err;
408 	zfs_handle_t	*zhp;
409 	zfs_handle_t	*clone;
410 	nvlist_t	*props = NULL;
411 
412 	if ((zhp = zfs_open(g_zfs, snapshot_name, ZFS_TYPE_SNAPSHOT)) == NULL)
413 		return (Z_NO_ENTRY);
414 
415 	(void) printf(gettext("Cloning snapshot %s\n"), snapshot_name);
416 
417 	if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0 ||
418 	    nvlist_add_string(props, zfs_prop_to_name(ZFS_PROP_SHARENFS),
419 	    "off") != 0) {
420 		if (props != NULL)
421 			nvlist_free(props);
422 		(void) fprintf(stderr, gettext("could not create ZFS clone "
423 		    "%s: out of memory\n"), zonepath);
424 		return (Z_ERR);
425 	}
426 
427 	err = zfs_clone(zhp, zonepath, props);
428 	zfs_close(zhp);
429 
430 	nvlist_free(props);
431 
432 	if (err != 0)
433 		return (Z_ERR);
434 
435 	/* create the mountpoint if necessary */
436 	if ((clone = zfs_open(g_zfs, zonepath, ZFS_TYPE_ANY)) == NULL)
437 		return (Z_ERR);
438 
439 	/*
440 	 * The clone has been created so we need to print a diagnostic
441 	 * message if one of the following steps fails for some reason.
442 	 */
443 	if (zfs_mount(clone, NULL, 0) != 0) {
444 		(void) fprintf(stderr, gettext("could not mount ZFS clone "
445 		    "%s\n"), zfs_get_name(clone));
446 		res = Z_ERR;
447 
448 	} else if (clean_out_clone() != Z_OK) {
449 		(void) fprintf(stderr, gettext("could not remove the "
450 		    "software inventory from ZFS clone %s\n"),
451 		    zfs_get_name(clone));
452 		res = Z_ERR;
453 	}
454 
455 	zfs_close(clone);
456 	return (res);
457 }
458 
459 /*
460  * This function takes a zonepath and attempts to determine what the ZFS
461  * file system name (not mountpoint) should be for that path.  We do not
462  * assume that zonepath is an existing directory or ZFS fs since we use
463  * this function as part of the process of creating a new ZFS fs or clone.
464  *
465  * The way this works is that we look at the parent directory of the zonepath
466  * to see if it is a ZFS fs.  If it is, we get the name of that ZFS fs and
467  * append the last component of the zonepath to generate the ZFS name for the
468  * zonepath.  This matches the algorithm that ZFS uses for automatically
469  * mounting a new fs after it is created.
470  *
471  * Although a ZFS fs can be mounted anywhere, we don't worry about handling
472  * all of the complexity that a user could possibly configure with arbitrary
473  * mounts since there is no way to generate a ZFS name from a random path in
474  * the file system.  We only try to handle the automatic mounts that ZFS does
475  * for each file system.  ZFS restricts this so that a new fs must be created
476  * in an existing parent ZFS fs.  It then automatically mounts the new fs
477  * directly under the mountpoint for the parent fs using the last component
478  * of the name as the mountpoint directory.
479  *
480  * For example:
481  *    Name			Mountpoint
482  *    space/eng/dev/test/zone1	/project1/eng/dev/test/zone1
483  *
484  * Return Z_OK if the path mapped to a ZFS file system name, otherwise return
485  * Z_ERR.
486  */
487 static int
488 path2name(char *zonepath, char *zfs_name, int len)
489 {
490 	int		res;
491 	char		*p;
492 	zfs_handle_t	*zhp;
493 
494 	if ((p = strrchr(zonepath, '/')) == NULL)
495 		return (Z_ERR);
496 
497 	/*
498 	 * If the parent directory is not its own ZFS fs, then we can't
499 	 * automatically create a new ZFS fs at the 'zonepath' mountpoint
500 	 * so return an error.
501 	 */
502 	*p = '\0';
503 	zhp = mount2zhandle(zonepath);
504 	*p = '/';
505 	if (zhp == NULL)
506 		return (Z_ERR);
507 
508 	res = snprintf(zfs_name, len, "%s/%s", zfs_get_name(zhp), p + 1);
509 
510 	zfs_close(zhp);
511 	if (res >= len)
512 		return (Z_ERR);
513 
514 	return (Z_OK);
515 }
516 
517 /*
518  * A ZFS file system iterator call-back function used to determine if the
519  * file system has dependents (snapshots & clones).
520  */
521 /* ARGSUSED */
522 static int
523 has_dependent(zfs_handle_t *zhp, void *data)
524 {
525 	zfs_close(zhp);
526 	return (1);
527 }
528 
529 /*
530  * Given a snapshot name, get the file system path where the snapshot lives.
531  * A snapshot name is of the form fs_name@snap_name.  For example, snapshot
532  * pl/zones/z1@SUNWzone1 would have a path of
533  * /pl/zones/z1/.zfs/snapshot/SUNWzone1.
534  */
535 static int
536 snap2path(char *snap_name, char *path, int len)
537 {
538 	char		*p;
539 	zfs_handle_t	*zhp;
540 	char		mp[ZFS_MAXPROPLEN];
541 
542 	if ((p = strrchr(snap_name, '@')) == NULL)
543 		return (Z_ERR);
544 
545 	/* Get the file system name from the snap_name. */
546 	*p = '\0';
547 	zhp = zfs_open(g_zfs, snap_name, ZFS_TYPE_ANY);
548 	*p = '@';
549 	if (zhp == NULL)
550 		return (Z_ERR);
551 
552 	/* Get the file system mount point. */
553 	if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mp, sizeof (mp), NULL, NULL,
554 	    0, B_FALSE) != 0) {
555 		zfs_close(zhp);
556 		return (Z_ERR);
557 	}
558 	zfs_close(zhp);
559 
560 	p++;
561 	if (snprintf(path, len, "%s/.zfs/snapshot/%s", mp, p) >= len)
562 		return (Z_ERR);
563 
564 	return (Z_OK);
565 }
566 
567 /*
568  * Clone a pre-existing ZFS snapshot, either by making a direct ZFS clone, if
569  * possible, or by copying the data from the snapshot to the zonepath.
570  */
571 int
572 clone_snapshot_zfs(char *snap_name, char *zonepath)
573 {
574 	int	err = Z_OK;
575 	char	clone_name[MAXPATHLEN];
576 	char	snap_path[MAXPATHLEN];
577 
578 	if (snap2path(snap_name, snap_path, sizeof (snap_path)) != Z_OK) {
579 		(void) fprintf(stderr, gettext("unable to find path for %s.\n"),
580 		    snap_name);
581 		return (Z_ERR);
582 	}
583 
584 	if (validate_snapshot(snap_name, snap_path) != Z_OK)
585 		return (Z_NO_ENTRY);
586 
587 	/*
588 	 * The zonepath cannot be ZFS cloned, try to copy the data from
589 	 * within the snapshot to the zonepath.
590 	 */
591 	if (path2name(zonepath, clone_name, sizeof (clone_name)) != Z_OK) {
592 		if ((err = clone_copy(snap_path, zonepath)) == Z_OK)
593 			if (clean_out_clone() != Z_OK)
594 				(void) fprintf(stderr,
595 				    gettext("could not remove the "
596 				    "software inventory from %s\n"), zonepath);
597 
598 		return (err);
599 	}
600 
601 	if ((err = clone_snap(snap_name, clone_name)) != Z_OK) {
602 		if (err != Z_NO_ENTRY) {
603 			/*
604 			 * Cloning the snapshot failed.  Fall back to trying
605 			 * to install the zone by copying from the snapshot.
606 			 */
607 			if ((err = clone_copy(snap_path, zonepath)) == Z_OK)
608 				if (clean_out_clone() != Z_OK)
609 					(void) fprintf(stderr,
610 					    gettext("could not remove the "
611 					    "software inventory from %s\n"),
612 					    zonepath);
613 		} else {
614 			/*
615 			 * The snapshot is unusable for some reason so restore
616 			 * the zone state to configured since we were unable to
617 			 * actually do anything about getting the zone
618 			 * installed.
619 			 */
620 			int tmp;
621 
622 			if ((tmp = zone_set_state(target_zone,
623 			    ZONE_STATE_CONFIGURED)) != Z_OK) {
624 				errno = tmp;
625 				zperror2(target_zone,
626 				    gettext("could not set state"));
627 			}
628 		}
629 	}
630 
631 	return (err);
632 }
633 
634 /*
635  * Attempt to clone a source_zone to a target zonepath by using a ZFS clone.
636  */
637 int
638 clone_zfs(char *source_zone, char *source_zonepath, char *zonepath)
639 {
640 	zfs_handle_t	*zhp;
641 	char		clone_name[MAXPATHLEN];
642 	char		snap_name[MAXPATHLEN];
643 
644 	/*
645 	 * Try to get a zfs handle for the source_zonepath.  If this fails
646 	 * the source_zonepath is not ZFS so return an error.
647 	 */
648 	if ((zhp = mount2zhandle(source_zonepath)) == NULL)
649 		return (Z_ERR);
650 
651 	/*
652 	 * Check if there is a file system already mounted on zonepath.  If so,
653 	 * we can't clone to the path so we should fall back to copying.
654 	 */
655 	if (is_mountpnt(zonepath)) {
656 		zfs_close(zhp);
657 		(void) fprintf(stderr,
658 		    gettext("A file system is already mounted on %s,\n"
659 		    "preventing use of a ZFS clone.\n"), zonepath);
660 		return (Z_ERR);
661 	}
662 
663 	/*
664 	 * Instead of using path2name to get the clone name from the zonepath,
665 	 * we could generate a name from the source zone ZFS name.  However,
666 	 * this would mean we would create the clone under the ZFS fs of the
667 	 * source instead of what the zonepath says.  For example,
668 	 *
669 	 * source_zonepath		zonepath
670 	 * /pl/zones/dev/z1		/pl/zones/deploy/z2
671 	 *
672 	 * We don't want the clone to be under "dev", we want it under
673 	 * "deploy", so that we can leverage the normal attribute inheritance
674 	 * that ZFS provides in the fs hierarchy.
675 	 */
676 	if (path2name(zonepath, clone_name, sizeof (clone_name)) != Z_OK) {
677 		zfs_close(zhp);
678 		return (Z_ERR);
679 	}
680 
681 	if (take_snapshot(source_zone, zhp, snap_name, sizeof (snap_name))
682 	    != Z_OK) {
683 		zfs_close(zhp);
684 		return (Z_ERR);
685 	}
686 	zfs_close(zhp);
687 
688 	if (clone_snap(snap_name, clone_name) != Z_OK) {
689 		/* Clean up the snapshot we just took. */
690 		if ((zhp = zfs_open(g_zfs, snap_name, ZFS_TYPE_SNAPSHOT))
691 		    != NULL) {
692 			if (zfs_unmount(zhp, NULL, 0) == 0)
693 				(void) zfs_destroy(zhp);
694 			zfs_close(zhp);
695 		}
696 
697 		return (Z_ERR);
698 	}
699 
700 	(void) printf(gettext("Instead of copying, a ZFS clone has been "
701 	    "created for this zone.\n"));
702 
703 	return (Z_OK);
704 }
705 
706 /*
707  * Attempt to create a ZFS file system for the specified zonepath.
708  * We either will successfully create a ZFS file system and get it mounted
709  * on the zonepath or we don't.  The caller doesn't care since a regular
710  * directory is used for the zonepath if no ZFS file system is mounted there.
711  */
712 void
713 create_zfs_zonepath(char *zonepath)
714 {
715 	zfs_handle_t	*zhp;
716 	char		zfs_name[MAXPATHLEN];
717 	nvlist_t	*props = NULL;
718 
719 	if (path2name(zonepath, zfs_name, sizeof (zfs_name)) != Z_OK)
720 		return;
721 
722 	if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0 ||
723 	    nvlist_add_string(props, zfs_prop_to_name(ZFS_PROP_SHARENFS),
724 	    "off") != 0) {
725 		if (props != NULL)
726 			nvlist_free(props);
727 		(void) fprintf(stderr, gettext("cannot create ZFS dataset %s: "
728 		    "out of memory\n"), zfs_name);
729 	}
730 
731 	if (zfs_create(g_zfs, zfs_name, ZFS_TYPE_FILESYSTEM, props) != 0 ||
732 	    (zhp = zfs_open(g_zfs, zfs_name, ZFS_TYPE_ANY)) == NULL) {
733 		(void) fprintf(stderr, gettext("cannot create ZFS dataset %s: "
734 		    "%s\n"), zfs_name, libzfs_error_description(g_zfs));
735 		nvlist_free(props);
736 		return;
737 	}
738 
739 	nvlist_free(props);
740 
741 	if (zfs_mount(zhp, NULL, 0) != 0) {
742 		(void) fprintf(stderr, gettext("cannot mount ZFS dataset %s: "
743 		    "%s\n"), zfs_name, libzfs_error_description(g_zfs));
744 		(void) zfs_destroy(zhp);
745 	} else {
746 		if (chmod(zonepath, S_IRWXU) != 0) {
747 			(void) fprintf(stderr, gettext("file system %s "
748 			    "successfully created, but chmod %o failed: %s\n"),
749 			    zfs_name, S_IRWXU, strerror(errno));
750 			(void) destroy_zfs(zonepath);
751 		} else {
752 			(void) printf(gettext("A ZFS file system has been "
753 			    "created for this zone.\n"));
754 		}
755 	}
756 
757 	zfs_close(zhp);
758 }
759 
760 /*
761  * If the zonepath is a ZFS file system, attempt to destroy it.  We return Z_OK
762  * if we were able to zfs_destroy the zonepath, otherwise we return Z_ERR
763  * which means the caller should clean up the zonepath in the traditional
764  * way.
765  */
766 int
767 destroy_zfs(char *zonepath)
768 {
769 	zfs_handle_t	*zhp;
770 	boolean_t	is_clone = B_FALSE;
771 	char		origin[ZFS_MAXPROPLEN];
772 
773 	if ((zhp = mount2zhandle(zonepath)) == NULL)
774 		return (Z_ERR);
775 
776 	/*
777 	 * We can't destroy the file system if it has dependents.
778 	 */
779 	if (zfs_iter_dependents(zhp, B_TRUE, has_dependent, NULL) != 0 ||
780 	    zfs_unmount(zhp, NULL, 0) != 0) {
781 		zfs_close(zhp);
782 		return (Z_ERR);
783 	}
784 
785 	/*
786 	 * This might be a clone.  Try to get the snapshot so we can attempt
787 	 * to destroy that as well.
788 	 */
789 	if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof (origin), NULL,
790 	    NULL, 0, B_FALSE) == 0)
791 		is_clone = B_TRUE;
792 
793 	if (zfs_destroy(zhp) != 0) {
794 		/*
795 		 * If the destroy fails for some reason, try to remount
796 		 * the file system so that we can use "rm -rf" to clean up
797 		 * instead.
798 		 */
799 		(void) zfs_mount(zhp, NULL, 0);
800 		zfs_close(zhp);
801 		return (Z_ERR);
802 	}
803 
804 	/*
805 	 * If the zone has ever been moved then the mountpoint dir will not be
806 	 * cleaned up by the zfs_destroy().  To handle this case try to clean
807 	 * it up now but don't worry if it fails, that will be normal.
808 	 */
809 	(void) rmdir(zonepath);
810 
811 	(void) printf(gettext("The ZFS file system for this zone has been "
812 	    "destroyed.\n"));
813 
814 	if (is_clone) {
815 		zfs_handle_t	*ohp;
816 
817 		/*
818 		 * Try to clean up the snapshot that the clone was taken from.
819 		 */
820 		if ((ohp = zfs_open(g_zfs, origin,
821 		    ZFS_TYPE_SNAPSHOT)) != NULL) {
822 			if (zfs_iter_dependents(ohp, B_TRUE, has_dependent,
823 			    NULL) == 0 && zfs_unmount(ohp, NULL, 0) == 0)
824 				(void) zfs_destroy(ohp);
825 			zfs_close(ohp);
826 		}
827 	}
828 
829 	zfs_close(zhp);
830 	return (Z_OK);
831 }
832 
833 /*
834  * Return true if the path is its own zfs file system.  We determine this
835  * by stat-ing the path to see if it is zfs and stat-ing the parent to see
836  * if it is a different fs.
837  */
838 boolean_t
839 is_zonepath_zfs(char *zonepath)
840 {
841 	int res;
842 	char *path;
843 	char *parent;
844 	struct statvfs64 buf1, buf2;
845 
846 	if (statvfs64(zonepath, &buf1) != 0)
847 		return (B_FALSE);
848 
849 	if (strcmp(buf1.f_basetype, "zfs") != 0)
850 		return (B_FALSE);
851 
852 	if ((path = strdup(zonepath)) == NULL)
853 		return (B_FALSE);
854 
855 	parent = dirname(path);
856 	res = statvfs64(parent, &buf2);
857 	free(path);
858 
859 	if (res != 0)
860 		return (B_FALSE);
861 
862 	if (buf1.f_fsid == buf2.f_fsid)
863 		return (B_FALSE);
864 
865 	return (B_TRUE);
866 }
867 
868 /*
869  * Implement the fast move of a ZFS file system by simply updating the
870  * mountpoint.  Since it is file system already, we don't have the
871  * issue of cross-file system copying.
872  */
873 int
874 move_zfs(char *zonepath, char *new_zonepath)
875 {
876 	int		ret = Z_ERR;
877 	zfs_handle_t	*zhp;
878 
879 	if ((zhp = mount2zhandle(zonepath)) == NULL)
880 		return (Z_ERR);
881 
882 	if (zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
883 	    new_zonepath) == 0) {
884 		/*
885 		 * Clean up the old mount point.  We ignore any failure since
886 		 * the zone is already successfully mounted on the new path.
887 		 */
888 		(void) rmdir(zonepath);
889 		ret = Z_OK;
890 	}
891 
892 	zfs_close(zhp);
893 
894 	return (ret);
895 }
896 
897 /*
898  * Validate that the given dataset exists on the system, and that neither it nor
899  * its children are zvols.
900  *
901  * Note that we don't do anything with the 'zoned' property here.  All
902  * management is done in zoneadmd when the zone is actually rebooted.  This
903  * allows us to automatically set the zoned property even when a zone is
904  * rebooted by the administrator.
905  */
906 int
907 verify_datasets(zone_dochandle_t handle)
908 {
909 	int return_code = Z_OK;
910 	struct zone_dstab dstab;
911 	zfs_handle_t *zhp;
912 	char propbuf[ZFS_MAXPROPLEN];
913 	char source[ZFS_MAXNAMELEN];
914 	zfs_source_t srctype;
915 
916 	if (zonecfg_setdsent(handle) != Z_OK) {
917 		/*
918 		 * TRANSLATION_NOTE
919 		 * zfs and dataset are literals that should not be translated.
920 		 */
921 		(void) fprintf(stderr, gettext("could not verify zfs datasets: "
922 		    "unable to enumerate datasets\n"));
923 		return (Z_ERR);
924 	}
925 
926 	while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
927 
928 		if ((zhp = zfs_open(g_zfs, dstab.zone_dataset_name,
929 		    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) == NULL) {
930 			(void) fprintf(stderr, gettext("could not verify zfs "
931 			    "dataset %s: %s\n"), dstab.zone_dataset_name,
932 			    libzfs_error_description(g_zfs));
933 			return_code = Z_ERR;
934 			continue;
935 		}
936 
937 		if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf,
938 		    sizeof (propbuf), &srctype, source,
939 		    sizeof (source), 0) == 0 &&
940 		    (srctype == ZFS_SRC_INHERITED)) {
941 			(void) fprintf(stderr, gettext("could not verify zfs "
942 			    "dataset %s: mountpoint cannot be inherited\n"),
943 			    dstab.zone_dataset_name);
944 			return_code = Z_ERR;
945 			zfs_close(zhp);
946 			continue;
947 		}
948 
949 		if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME) {
950 			(void) fprintf(stderr, gettext("cannot verify zfs "
951 			    "dataset %s: volumes cannot be specified as a "
952 			    "zone dataset resource\n"),
953 			    dstab.zone_dataset_name);
954 			return_code = Z_ERR;
955 		}
956 
957 		if (zfs_iter_children(zhp, check_zvol, NULL) != 0)
958 			return_code = Z_ERR;
959 
960 		zfs_close(zhp);
961 	}
962 	(void) zonecfg_enddsent(handle);
963 
964 	return (return_code);
965 }
966 
967 /*
968  * Verify that the ZFS dataset exists, and its mountpoint
969  * property is set to "legacy".
970  */
971 int
972 verify_fs_zfs(struct zone_fstab *fstab)
973 {
974 	zfs_handle_t *zhp;
975 	char propbuf[ZFS_MAXPROPLEN];
976 
977 	if ((zhp = zfs_open(g_zfs, fstab->zone_fs_special,
978 	    ZFS_TYPE_ANY)) == NULL) {
979 		(void) fprintf(stderr, gettext("could not verify fs %s: "
980 		    "could not access zfs dataset '%s'\n"),
981 		    fstab->zone_fs_dir, fstab->zone_fs_special);
982 		return (Z_ERR);
983 	}
984 
985 	if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
986 		(void) fprintf(stderr, gettext("cannot verify fs %s: "
987 		    "'%s' is not a file system\n"),
988 		    fstab->zone_fs_dir, fstab->zone_fs_special);
989 		zfs_close(zhp);
990 		return (Z_ERR);
991 	}
992 
993 	if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf, sizeof (propbuf),
994 	    NULL, NULL, 0, 0) != 0 || strcmp(propbuf, "legacy") != 0) {
995 		(void) fprintf(stderr, gettext("could not verify fs %s: "
996 		    "zfs '%s' mountpoint is not \"legacy\"\n"),
997 		    fstab->zone_fs_dir, fstab->zone_fs_special);
998 		zfs_close(zhp);
999 		return (Z_ERR);
1000 	}
1001 
1002 	zfs_close(zhp);
1003 	return (Z_OK);
1004 }
1005 
1006 int
1007 init_zfs(void)
1008 {
1009 	if ((g_zfs = libzfs_init()) == NULL) {
1010 		(void) fprintf(stderr, gettext("failed to initialize ZFS "
1011 		    "library\n"));
1012 		return (Z_ERR);
1013 	}
1014 
1015 	return (Z_OK);
1016 }
1017