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