xref: /illumos-gate/usr/src/cmd/zoneadm/zfs.c (revision e9dbad6f263d5570ed7ff5443ec5b958af8c24d7)
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 2006 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_boolean_value(props,
419 	    zfs_prop_to_name(ZFS_PROP_SHARENFS), B_FALSE) != 0) {
420 		nvlist_free(props);
421 		(void) fprintf(stderr, gettext("could not create ZFS clone "
422 		    "%s: out of memory\n"), zonepath);
423 		return (Z_ERR);
424 	}
425 
426 	err = zfs_clone(zhp, zonepath, props);
427 	zfs_close(zhp);
428 
429 	nvlist_free(props);
430 
431 	if (err != 0)
432 		return (Z_ERR);
433 
434 	/* create the mountpoint if necessary */
435 	if ((clone = zfs_open(g_zfs, zonepath, ZFS_TYPE_ANY)) == NULL)
436 		return (Z_ERR);
437 
438 	/*
439 	 * The clone has been created so we need to print a diagnostic
440 	 * message if one of the following steps fails for some reason.
441 	 */
442 	if (zfs_mount(clone, NULL, 0) != 0) {
443 		(void) fprintf(stderr, gettext("could not mount ZFS clone "
444 		    "%s\n"), zfs_get_name(clone));
445 		res = Z_ERR;
446 
447 	} else if (clean_out_clone() != Z_OK) {
448 		(void) fprintf(stderr, gettext("could not remove the "
449 		    "software inventory from ZFS clone %s\n"),
450 		    zfs_get_name(clone));
451 		res = Z_ERR;
452 	}
453 
454 	zfs_close(clone);
455 	return (res);
456 }
457 
458 /*
459  * This function takes a zonepath and attempts to determine what the ZFS
460  * file system name (not mountpoint) should be for that path.  We do not
461  * assume that zonepath is an existing directory or ZFS fs since we use
462  * this function as part of the process of creating a new ZFS fs or clone.
463  *
464  * The way this works is that we look at the parent directory of the zonepath
465  * to see if it is a ZFS fs.  If it is, we get the name of that ZFS fs and
466  * append the last component of the zonepath to generate the ZFS name for the
467  * zonepath.  This matches the algorithm that ZFS uses for automatically
468  * mounting a new fs after it is created.
469  *
470  * Although a ZFS fs can be mounted anywhere, we don't worry about handling
471  * all of the complexity that a user could possibly configure with arbitrary
472  * mounts since there is no way to generate a ZFS name from a random path in
473  * the file system.  We only try to handle the automatic mounts that ZFS does
474  * for each file system.  ZFS restricts this so that a new fs must be created
475  * in an existing parent ZFS fs.  It then automatically mounts the new fs
476  * directly under the mountpoint for the parent fs using the last component
477  * of the name as the mountpoint directory.
478  *
479  * For example:
480  *    Name			Mountpoint
481  *    space/eng/dev/test/zone1	/project1/eng/dev/test/zone1
482  *
483  * Return Z_OK if the path mapped to a ZFS file system name, otherwise return
484  * Z_ERR.
485  */
486 static int
487 path2name(char *zonepath, char *zfs_name, int len)
488 {
489 	int		res;
490 	char		*p;
491 	zfs_handle_t	*zhp;
492 
493 	if ((p = strrchr(zonepath, '/')) == NULL)
494 		return (Z_ERR);
495 
496 	/*
497 	 * If the parent directory is not its own ZFS fs, then we can't
498 	 * automatically create a new ZFS fs at the 'zonepath' mountpoint
499 	 * so return an error.
500 	 */
501 	*p = '\0';
502 	zhp = mount2zhandle(zonepath);
503 	*p = '/';
504 	if (zhp == NULL)
505 		return (Z_ERR);
506 
507 	res = snprintf(zfs_name, len, "%s/%s", zfs_get_name(zhp), p + 1);
508 
509 	zfs_close(zhp);
510 	if (res >= len)
511 		return (Z_ERR);
512 
513 	return (Z_OK);
514 }
515 
516 /*
517  * A ZFS file system iterator call-back function used to determine if the
518  * file system has dependents (snapshots & clones).
519  */
520 /* ARGSUSED */
521 static int
522 has_dependent(zfs_handle_t *zhp, void *data)
523 {
524 	zfs_close(zhp);
525 	return (1);
526 }
527 
528 /*
529  * Given a snapshot name, get the file system path where the snapshot lives.
530  * A snapshot name is of the form fs_name@snap_name.  For example, snapshot
531  * pl/zones/z1@SUNWzone1 would have a path of
532  * /pl/zones/z1/.zfs/snapshot/SUNWzone1.
533  */
534 static int
535 snap2path(char *snap_name, char *path, int len)
536 {
537 	char		*p;
538 	zfs_handle_t	*zhp;
539 	char		mp[ZFS_MAXPROPLEN];
540 
541 	if ((p = strrchr(snap_name, '@')) == NULL)
542 		return (Z_ERR);
543 
544 	/* Get the file system name from the snap_name. */
545 	*p = '\0';
546 	zhp = zfs_open(g_zfs, snap_name, ZFS_TYPE_ANY);
547 	*p = '@';
548 	if (zhp == NULL)
549 		return (Z_ERR);
550 
551 	/* Get the file system mount point. */
552 	if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mp, sizeof (mp), NULL, NULL,
553 	    0, B_FALSE) != 0) {
554 		zfs_close(zhp);
555 		return (Z_ERR);
556 	}
557 	zfs_close(zhp);
558 
559 	p++;
560 	if (snprintf(path, len, "%s/.zfs/snapshot/%s", mp, p) >= len)
561 		return (Z_ERR);
562 
563 	return (Z_OK);
564 }
565 
566 /*
567  * Clone a pre-existing ZFS snapshot, either by making a direct ZFS clone, if
568  * possible, or by copying the data from the snapshot to the zonepath.
569  */
570 int
571 clone_snapshot_zfs(char *snap_name, char *zonepath)
572 {
573 	int	err = Z_OK;
574 	char	clone_name[MAXPATHLEN];
575 	char	snap_path[MAXPATHLEN];
576 
577 	if (snap2path(snap_name, snap_path, sizeof (snap_path)) != Z_OK) {
578 		(void) fprintf(stderr, gettext("unable to find path for %s.\n"),
579 		    snap_name);
580 		return (Z_ERR);
581 	}
582 
583 	if (validate_snapshot(snap_name, snap_path) != Z_OK)
584 		return (Z_NO_ENTRY);
585 
586 	/*
587 	 * The zonepath cannot be ZFS cloned, try to copy the data from
588 	 * within the snapshot to the zonepath.
589 	 */
590 	if (path2name(zonepath, clone_name, sizeof (clone_name)) != Z_OK) {
591 		if ((err = clone_copy(snap_path, zonepath)) == Z_OK)
592 			if (clean_out_clone() != Z_OK)
593 				(void) fprintf(stderr,
594 				    gettext("could not remove the "
595 				    "software inventory from %s\n"), zonepath);
596 
597 		return (err);
598 	}
599 
600 	if ((err = clone_snap(snap_name, clone_name)) != Z_OK) {
601 		if (err != Z_NO_ENTRY) {
602 			/*
603 			 * Cloning the snapshot failed.  Fall back to trying
604 			 * to install the zone by copying from the snapshot.
605 			 */
606 			if ((err = clone_copy(snap_path, zonepath)) == Z_OK)
607 				if (clean_out_clone() != Z_OK)
608 					(void) fprintf(stderr,
609 					    gettext("could not remove the "
610 					    "software inventory from %s\n"),
611 					    zonepath);
612 		} else {
613 			/*
614 			 * The snapshot is unusable for some reason so restore
615 			 * the zone state to configured since we were unable to
616 			 * actually do anything about getting the zone
617 			 * installed.
618 			 */
619 			int tmp;
620 
621 			if ((tmp = zone_set_state(target_zone,
622 			    ZONE_STATE_CONFIGURED)) != Z_OK) {
623 				errno = tmp;
624 				zperror2(target_zone,
625 				    gettext("could not set state"));
626 			}
627 		}
628 	}
629 
630 	return (err);
631 }
632 
633 /*
634  * Attempt to clone a source_zone to a target zonepath by using a ZFS clone.
635  */
636 int
637 clone_zfs(char *source_zone, char *source_zonepath, char *zonepath)
638 {
639 	zfs_handle_t	*zhp;
640 	char		clone_name[MAXPATHLEN];
641 	char		snap_name[MAXPATHLEN];
642 
643 	/*
644 	 * Try to get a zfs handle for the source_zonepath.  If this fails
645 	 * the source_zonepath is not ZFS so return an error.
646 	 */
647 	if ((zhp = mount2zhandle(source_zonepath)) == NULL)
648 		return (Z_ERR);
649 
650 	/*
651 	 * Check if there is a file system already mounted on zonepath.  If so,
652 	 * we can't clone to the path so we should fall back to copying.
653 	 */
654 	if (is_mountpnt(zonepath)) {
655 		zfs_close(zhp);
656 		(void) fprintf(stderr,
657 		    gettext("A file system is already mounted on %s,\n"
658 		    "preventing use of a ZFS clone.\n"), zonepath);
659 		return (Z_ERR);
660 	}
661 
662 	/*
663 	 * Instead of using path2name to get the clone name from the zonepath,
664 	 * we could generate a name from the source zone ZFS name.  However,
665 	 * this would mean we would create the clone under the ZFS fs of the
666 	 * source instead of what the zonepath says.  For example,
667 	 *
668 	 * source_zonepath		zonepath
669 	 * /pl/zones/dev/z1		/pl/zones/deploy/z2
670 	 *
671 	 * We don't want the clone to be under "dev", we want it under
672 	 * "deploy", so that we can leverage the normal attribute inheritance
673 	 * that ZFS provides in the fs hierarchy.
674 	 */
675 	if (path2name(zonepath, clone_name, sizeof (clone_name)) != Z_OK) {
676 		zfs_close(zhp);
677 		return (Z_ERR);
678 	}
679 
680 	if (take_snapshot(source_zone, zhp, snap_name, sizeof (snap_name))
681 	    != Z_OK) {
682 		zfs_close(zhp);
683 		return (Z_ERR);
684 	}
685 	zfs_close(zhp);
686 
687 	if (clone_snap(snap_name, clone_name) != Z_OK)
688 		return (Z_ERR);
689 
690 	(void) printf(gettext("Instead of copying, a ZFS clone has been "
691 	    "created for this zone.\n"));
692 
693 	return (Z_OK);
694 }
695 
696 /*
697  * Attempt to create a ZFS file system for the specified zonepath.
698  * We either will successfully create a ZFS file system and get it mounted
699  * on the zonepath or we don't.  The caller doesn't care since a regular
700  * directory is used for the zonepath if no ZFS file system is mounted there.
701  */
702 void
703 create_zfs_zonepath(char *zonepath)
704 {
705 	zfs_handle_t	*zhp;
706 	char		zfs_name[MAXPATHLEN];
707 	nvlist_t	*props = NULL;
708 
709 	if (path2name(zonepath, zfs_name, sizeof (zfs_name)) != Z_OK)
710 		return;
711 
712 	if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0 ||
713 	    nvlist_add_boolean_value(props, zfs_prop_to_name(ZFS_PROP_SHARENFS),
714 	    B_FALSE) != 0) {
715 		nvlist_free(props);
716 		(void) fprintf(stderr, gettext("cannot create ZFS dataset %s: "
717 		    "out of memory\n"), zfs_name);
718 	}
719 
720 	if (zfs_create(g_zfs, zfs_name, ZFS_TYPE_FILESYSTEM, props) != 0 ||
721 	    (zhp = zfs_open(g_zfs, zfs_name, ZFS_TYPE_ANY)) == NULL) {
722 		(void) fprintf(stderr, gettext("cannot create ZFS dataset %s: "
723 		    "%s\n"), zfs_name, libzfs_error_description(g_zfs));
724 		nvlist_free(props);
725 		return;
726 	}
727 
728 	nvlist_free(props);
729 
730 	if (zfs_mount(zhp, NULL, 0) != 0) {
731 		(void) fprintf(stderr, gettext("cannot mount ZFS dataset %s: "
732 		    "%s\n"), zfs_name, libzfs_error_description(g_zfs));
733 		(void) zfs_destroy(zhp);
734 	} else {
735 		if (chmod(zonepath, S_IRWXU) != 0) {
736 			(void) fprintf(stderr, gettext("file system %s "
737 			    "successfully created, but chmod %o failed: %s\n"),
738 			    zfs_name, S_IRWXU, strerror(errno));
739 			(void) destroy_zfs(zonepath);
740 		} else {
741 			(void) printf(gettext("A ZFS file system has been "
742 			    "created for this zone.\n"));
743 		}
744 	}
745 
746 	zfs_close(zhp);
747 }
748 
749 /*
750  * If the zonepath is a ZFS file system, attempt to destroy it.  We return Z_OK
751  * if we were able to zfs_destroy the zonepath, otherwise we return Z_ERR
752  * which means the caller should clean up the zonepath in the traditional
753  * way.
754  */
755 int
756 destroy_zfs(char *zonepath)
757 {
758 	zfs_handle_t	*zhp;
759 	boolean_t	is_clone = B_FALSE;
760 	char		origin[ZFS_MAXPROPLEN];
761 
762 	if ((zhp = mount2zhandle(zonepath)) == NULL)
763 		return (Z_ERR);
764 
765 	/*
766 	 * We can't destroy the file system if it has dependents.
767 	 */
768 	if (zfs_iter_dependents(zhp, B_TRUE, has_dependent, NULL) != 0 ||
769 	    zfs_unmount(zhp, NULL, 0) != 0) {
770 		zfs_close(zhp);
771 		return (Z_ERR);
772 	}
773 
774 	/*
775 	 * This might be a clone.  Try to get the snapshot so we can attempt
776 	 * to destroy that as well.
777 	 */
778 	if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof (origin), NULL,
779 	    NULL, 0, B_FALSE) == 0)
780 		is_clone = B_TRUE;
781 
782 	if (zfs_destroy(zhp) != 0) {
783 		/*
784 		 * If the destroy fails for some reason, try to remount
785 		 * the file system so that we can use "rm -rf" to clean up
786 		 * instead.
787 		 */
788 		(void) zfs_mount(zhp, NULL, 0);
789 		zfs_close(zhp);
790 		return (Z_ERR);
791 	}
792 
793 	(void) printf(gettext("The ZFS file system for this zone has been "
794 	    "destroyed.\n"));
795 
796 	if (is_clone) {
797 		zfs_handle_t	*ohp;
798 
799 		/*
800 		 * Try to clean up the snapshot that the clone was taken from.
801 		 */
802 		if ((ohp = zfs_open(g_zfs, origin,
803 		    ZFS_TYPE_SNAPSHOT)) != NULL) {
804 			if (zfs_iter_dependents(ohp, B_TRUE, has_dependent,
805 			    NULL) == 0 && zfs_unmount(ohp, NULL, 0) == 0)
806 				(void) zfs_destroy(ohp);
807 			zfs_close(ohp);
808 		}
809 	}
810 
811 	zfs_close(zhp);
812 	return (Z_OK);
813 }
814 
815 /*
816  * Return true if the path is its own zfs file system.  We determine this
817  * by stat-ing the path to see if it is zfs and stat-ing the parent to see
818  * if it is a different fs.
819  */
820 boolean_t
821 is_zonepath_zfs(char *zonepath)
822 {
823 	int res;
824 	char *path;
825 	char *parent;
826 	struct statvfs64 buf1, buf2;
827 
828 	if (statvfs64(zonepath, &buf1) != 0)
829 		return (B_FALSE);
830 
831 	if (strcmp(buf1.f_basetype, "zfs") != 0)
832 		return (B_FALSE);
833 
834 	if ((path = strdup(zonepath)) == NULL)
835 		return (B_FALSE);
836 
837 	parent = dirname(path);
838 	res = statvfs64(parent, &buf2);
839 	free(path);
840 
841 	if (res != 0)
842 		return (B_FALSE);
843 
844 	if (buf1.f_fsid == buf2.f_fsid)
845 		return (B_FALSE);
846 
847 	return (B_TRUE);
848 }
849 
850 /*
851  * Implement the fast move of a ZFS file system by simply updating the
852  * mountpoint.  Since it is file system already, we don't have the
853  * issue of cross-file system copying.
854  */
855 int
856 move_zfs(char *zonepath, char *new_zonepath)
857 {
858 	int		ret = Z_ERR;
859 	zfs_handle_t	*zhp;
860 
861 	if ((zhp = mount2zhandle(zonepath)) == NULL)
862 		return (Z_ERR);
863 
864 	if (zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
865 	    new_zonepath) == 0) {
866 		/*
867 		 * Clean up the old mount point.  We ignore any failure since
868 		 * the zone is already successfully mounted on the new path.
869 		 */
870 		(void) rmdir(zonepath);
871 		ret = Z_OK;
872 	}
873 
874 	zfs_close(zhp);
875 
876 	return (ret);
877 }
878 
879 /*
880  * Validate that the given dataset exists on the system, and that neither it nor
881  * its children are zvols.
882  *
883  * Note that we don't do anything with the 'zoned' property here.  All
884  * management is done in zoneadmd when the zone is actually rebooted.  This
885  * allows us to automatically set the zoned property even when a zone is
886  * rebooted by the administrator.
887  */
888 int
889 verify_datasets(zone_dochandle_t handle)
890 {
891 	int return_code = Z_OK;
892 	struct zone_dstab dstab;
893 	zfs_handle_t *zhp;
894 	char propbuf[ZFS_MAXPROPLEN];
895 	char source[ZFS_MAXNAMELEN];
896 	zfs_source_t srctype;
897 
898 	if (zonecfg_setdsent(handle) != Z_OK) {
899 		/*
900 		 * TRANSLATION_NOTE
901 		 * zfs and dataset are literals that should not be translated.
902 		 */
903 		(void) fprintf(stderr, gettext("could not verify zfs datasets: "
904 		    "unable to enumerate datasets\n"));
905 		return (Z_ERR);
906 	}
907 
908 	while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
909 
910 		if ((zhp = zfs_open(g_zfs, dstab.zone_dataset_name,
911 		    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) == NULL) {
912 			(void) fprintf(stderr, gettext("could not verify zfs "
913 			    "dataset %s: %s\n"), dstab.zone_dataset_name,
914 			    libzfs_error_description(g_zfs));
915 			return_code = Z_ERR;
916 			continue;
917 		}
918 
919 		if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf,
920 		    sizeof (propbuf), &srctype, source,
921 		    sizeof (source), 0) == 0 &&
922 		    (srctype == ZFS_SRC_INHERITED)) {
923 			(void) fprintf(stderr, gettext("could not verify zfs "
924 			    "dataset %s: mountpoint cannot be inherited\n"),
925 			    dstab.zone_dataset_name);
926 			return_code = Z_ERR;
927 			zfs_close(zhp);
928 			continue;
929 		}
930 
931 		if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME) {
932 			(void) fprintf(stderr, gettext("cannot verify zfs "
933 			    "dataset %s: volumes cannot be specified as a "
934 			    "zone dataset resource\n"),
935 			    dstab.zone_dataset_name);
936 			return_code = Z_ERR;
937 		}
938 
939 		if (zfs_iter_children(zhp, check_zvol, NULL) != 0)
940 			return_code = Z_ERR;
941 
942 		zfs_close(zhp);
943 	}
944 	(void) zonecfg_enddsent(handle);
945 
946 	return (return_code);
947 }
948 
949 /*
950  * Verify that the ZFS dataset exists, and its mountpoint
951  * property is set to "legacy".
952  */
953 int
954 verify_fs_zfs(struct zone_fstab *fstab)
955 {
956 	zfs_handle_t *zhp;
957 	char propbuf[ZFS_MAXPROPLEN];
958 
959 	if ((zhp = zfs_open(g_zfs, fstab->zone_fs_special,
960 	    ZFS_TYPE_ANY)) == NULL) {
961 		(void) fprintf(stderr, gettext("could not verify fs %s: "
962 		    "could not access zfs dataset '%s'\n"),
963 		    fstab->zone_fs_dir, fstab->zone_fs_special);
964 		return (Z_ERR);
965 	}
966 
967 	if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
968 		(void) fprintf(stderr, gettext("cannot verify fs %s: "
969 		    "'%s' is not a file system\n"),
970 		    fstab->zone_fs_dir, fstab->zone_fs_special);
971 		zfs_close(zhp);
972 		return (Z_ERR);
973 	}
974 
975 	if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf, sizeof (propbuf),
976 	    NULL, NULL, 0, 0) != 0 || strcmp(propbuf, "legacy") != 0) {
977 		(void) fprintf(stderr, gettext("could not verify fs %s: "
978 		    "zfs '%s' mountpoint is not \"legacy\"\n"),
979 		    fstab->zone_fs_dir, fstab->zone_fs_special);
980 		zfs_close(zhp);
981 		return (Z_ERR);
982 	}
983 
984 	zfs_close(zhp);
985 	return (Z_OK);
986 }
987 
988 int
989 init_zfs(void)
990 {
991 	if ((g_zfs = libzfs_init()) == NULL) {
992 		(void) fprintf(stderr, gettext("failed to initialize ZFS "
993 		    "library\n"));
994 		return (Z_ERR);
995 	}
996 
997 	return (Z_OK);
998 }
999