xref: /titanic_51/usr/src/cmd/zoneadm/zfs.c (revision 40e7ce05bde825a43b0db32ded62db8cc5b6ec9c)
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 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * This file contains the functions used to support the ZFS integration
29  * with zones.  This includes validation (e.g. zonecfg dataset), cloning,
30  * file system creation and destruction.
31  */
32 
33 #include <stdio.h>
34 #include <errno.h>
35 #include <unistd.h>
36 #include <string.h>
37 #include <locale.h>
38 #include <libintl.h>
39 #include <sys/stat.h>
40 #include <sys/statvfs.h>
41 #include <libgen.h>
42 #include <libzonecfg.h>
43 #include <sys/mnttab.h>
44 #include <libzfs.h>
45 #include <sys/mntent.h>
46 
47 #include "zoneadm.h"
48 
49 libzfs_handle_t *g_zfs;
50 
51 typedef struct zfs_mount_data {
52 	char		*match_name;
53 	zfs_handle_t	*match_handle;
54 } zfs_mount_data_t;
55 
56 typedef struct zfs_snapshot_data {
57 	char	*match_name;
58 	int	len;
59 	int	max;
60 } zfs_snapshot_data_t;
61 
62 /*
63  * A ZFS file system iterator call-back function which is used to validate
64  * datasets imported into the zone.
65  */
66 /* ARGSUSED */
67 static int
68 check_zvol(zfs_handle_t *zhp, void *unused)
69 {
70 	int ret;
71 
72 	if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME) {
73 		/*
74 		 * TRANSLATION_NOTE
75 		 * zfs and dataset are literals that should not be translated.
76 		 */
77 		(void) fprintf(stderr, gettext("cannot verify zfs dataset %s: "
78 		    "volumes cannot be specified as a zone dataset resource\n"),
79 		    zfs_get_name(zhp));
80 		ret = -1;
81 	} else {
82 		ret = zfs_iter_children(zhp, check_zvol, NULL);
83 	}
84 
85 	zfs_close(zhp);
86 
87 	return (ret);
88 }
89 
90 /*
91  * A ZFS file system iterator call-back function which returns the
92  * zfs_handle_t for a ZFS file system on the specified mount point.
93  */
94 static int
95 match_mountpoint(zfs_handle_t *zhp, void *data)
96 {
97 	int			res;
98 	zfs_mount_data_t	*cbp;
99 	char			mp[ZFS_MAXPROPLEN];
100 
101 	if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
102 		zfs_close(zhp);
103 		return (0);
104 	}
105 
106 	/* First check if the dataset is mounted. */
107 	if (zfs_prop_get(zhp, ZFS_PROP_MOUNTED, mp, sizeof (mp), NULL, NULL,
108 	    0, B_FALSE) != 0 || strcmp(mp, "no") == 0) {
109 		zfs_close(zhp);
110 		return (0);
111 	}
112 
113 	/* Now check mount point. */
114 	if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mp, sizeof (mp), NULL, NULL,
115 	    0, B_FALSE) != 0) {
116 		zfs_close(zhp);
117 		return (0);
118 	}
119 
120 	cbp = (zfs_mount_data_t *)data;
121 
122 	if (strcmp(mp, "legacy") == 0) {
123 		/* If legacy, must look in mnttab for mountpoint. */
124 		FILE		*fp;
125 		struct mnttab	entry;
126 		const char	*nm;
127 
128 		nm = zfs_get_name(zhp);
129 		if ((fp = fopen(MNTTAB, "r")) == NULL) {
130 			zfs_close(zhp);
131 			return (0);
132 		}
133 
134 		while (getmntent(fp, &entry) == 0) {
135 			if (strcmp(nm, entry.mnt_special) == 0) {
136 				if (strcmp(entry.mnt_mountp, cbp->match_name)
137 				    == 0) {
138 					(void) fclose(fp);
139 					cbp->match_handle = zhp;
140 					return (1);
141 				}
142 				break;
143 			}
144 		}
145 		(void) fclose(fp);
146 
147 	} else if (strcmp(mp, cbp->match_name) == 0) {
148 		cbp->match_handle = zhp;
149 		return (1);
150 	}
151 
152 	/* Iterate over any nested datasets. */
153 	res = zfs_iter_filesystems(zhp, match_mountpoint, data);
154 	zfs_close(zhp);
155 	return (res);
156 }
157 
158 /*
159  * Get ZFS handle for the specified mount point.
160  */
161 static zfs_handle_t *
162 mount2zhandle(char *mountpoint)
163 {
164 	zfs_mount_data_t	cb;
165 
166 	cb.match_name = mountpoint;
167 	cb.match_handle = NULL;
168 	(void) zfs_iter_root(g_zfs, match_mountpoint, &cb);
169 	return (cb.match_handle);
170 }
171 
172 /*
173  * Check if there is already a file system (zfs or any other type) mounted on
174  * path.
175  */
176 static boolean_t
177 is_mountpnt(char *path)
178 {
179 	FILE		*fp;
180 	struct mnttab	entry;
181 
182 	if ((fp = fopen(MNTTAB, "r")) == NULL)
183 		return (B_FALSE);
184 
185 	while (getmntent(fp, &entry) == 0) {
186 		if (strcmp(path, entry.mnt_mountp) == 0) {
187 			(void) fclose(fp);
188 			return (B_TRUE);
189 		}
190 	}
191 
192 	(void) fclose(fp);
193 	return (B_FALSE);
194 }
195 
196 /*
197  * Run the brand's pre-snapshot hook before we take a ZFS snapshot of the zone.
198  */
199 static int
200 pre_snapshot(char *presnapbuf)
201 {
202 	int status;
203 
204 	/* No brand-specific handler */
205 	if (presnapbuf[0] == '\0')
206 		return (Z_OK);
207 
208 	/* Run the hook */
209 	status = do_subproc(presnapbuf);
210 	if ((status = subproc_status(gettext("brand-specific presnapshot"),
211 	    status, B_FALSE)) != ZONE_SUBPROC_OK)
212 		return (Z_ERR);
213 
214 	return (Z_OK);
215 }
216 
217 /*
218  * Run the brand's post-snapshot hook after we take a ZFS snapshot of the zone.
219  */
220 static int
221 post_snapshot(char *postsnapbuf)
222 {
223 	int status;
224 
225 	/* No brand-specific handler */
226 	if (postsnapbuf[0] == '\0')
227 		return (Z_OK);
228 
229 	/* Run the hook */
230 	status = do_subproc(postsnapbuf);
231 	if ((status = subproc_status(gettext("brand-specific postsnapshot"),
232 	    status, B_FALSE)) != ZONE_SUBPROC_OK)
233 		return (Z_ERR);
234 
235 	return (Z_OK);
236 }
237 
238 /*
239  * This is a ZFS snapshot iterator call-back function which returns the
240  * highest number of SUNWzone snapshots that have been taken.
241  */
242 static int
243 get_snap_max(zfs_handle_t *zhp, void *data)
244 {
245 	int			res;
246 	zfs_snapshot_data_t	*cbp;
247 
248 	if (zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) {
249 		zfs_close(zhp);
250 		return (0);
251 	}
252 
253 	cbp = (zfs_snapshot_data_t *)data;
254 
255 	if (strncmp(zfs_get_name(zhp), cbp->match_name, cbp->len) == 0) {
256 		char	*nump;
257 		int	num;
258 
259 		nump = (char *)(zfs_get_name(zhp) + cbp->len);
260 		num = atoi(nump);
261 		if (num > cbp->max)
262 			cbp->max = num;
263 	}
264 
265 	res = zfs_iter_snapshots(zhp, get_snap_max, data);
266 	zfs_close(zhp);
267 	return (res);
268 }
269 
270 /*
271  * Take a ZFS snapshot to be used for cloning the zone.
272  */
273 static int
274 take_snapshot(zfs_handle_t *zhp, char *snapshot_name, int snap_size,
275     char *presnapbuf, char *postsnapbuf)
276 {
277 	int			res;
278 	char			template[ZFS_MAXNAMELEN];
279 	zfs_snapshot_data_t	cb;
280 
281 	/*
282 	 * First we need to figure out the next available name for the
283 	 * zone snapshot.  Look through the list of zones snapshots for
284 	 * this file system to determine the maximum snapshot name.
285 	 */
286 	if (snprintf(template, sizeof (template), "%s@SUNWzone",
287 	    zfs_get_name(zhp)) >=  sizeof (template))
288 		return (Z_ERR);
289 
290 	cb.match_name = template;
291 	cb.len = strlen(template);
292 	cb.max = 0;
293 
294 	if (zfs_iter_snapshots(zhp, get_snap_max, &cb) != 0)
295 		return (Z_ERR);
296 
297 	cb.max++;
298 
299 	if (snprintf(snapshot_name, snap_size, "%s@SUNWzone%d",
300 	    zfs_get_name(zhp), cb.max) >= snap_size)
301 		return (Z_ERR);
302 
303 	if (pre_snapshot(presnapbuf) != Z_OK)
304 		return (Z_ERR);
305 	res = zfs_snapshot(g_zfs, snapshot_name, B_FALSE, NULL);
306 	if (post_snapshot(postsnapbuf) != Z_OK)
307 		return (Z_ERR);
308 
309 	if (res != 0)
310 		return (Z_ERR);
311 	return (Z_OK);
312 }
313 
314 /*
315  * We are using an explicit snapshot from some earlier point in time so
316  * we need to validate it.  Run the brand specific hook.
317  */
318 static int
319 validate_snapshot(char *snapshot_name, char *snap_path, char *validsnapbuf)
320 {
321 	int status;
322 	char cmdbuf[MAXPATHLEN];
323 
324 	/* No brand-specific handler */
325 	if (validsnapbuf[0] == '\0')
326 		return (Z_OK);
327 
328 	/* pass args - snapshot_name & snap_path */
329 	if (snprintf(cmdbuf, sizeof (cmdbuf), "%s %s %s", validsnapbuf,
330 	    snapshot_name, snap_path) >= sizeof (cmdbuf)) {
331 		zerror("Command line too long");
332 		return (Z_ERR);
333 	}
334 
335 	/* Run the hook */
336 	status = do_subproc(cmdbuf);
337 	if ((status = subproc_status(gettext("brand-specific validatesnapshot"),
338 	    status, B_FALSE)) != ZONE_SUBPROC_OK)
339 		return (Z_ERR);
340 
341 	return (Z_OK);
342 }
343 
344 /*
345  * Remove the sw inventory file from inside this zonepath that we picked up out
346  * of the snapshot.
347  */
348 static int
349 clean_out_clone()
350 {
351 	int err;
352 	zone_dochandle_t handle;
353 
354 	if ((handle = zonecfg_init_handle()) == NULL) {
355 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
356 		return (Z_ERR);
357 	}
358 
359 	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
360 		errno = err;
361 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
362 		zonecfg_fini_handle(handle);
363 		return (Z_ERR);
364 	}
365 
366 	zonecfg_rm_detached(handle, B_FALSE);
367 	zonecfg_fini_handle(handle);
368 
369 	return (Z_OK);
370 }
371 
372 /*
373  * Make a ZFS clone on zonepath from snapshot_name.
374  */
375 static int
376 clone_snap(char *snapshot_name, char *zonepath)
377 {
378 	int		res = Z_OK;
379 	int		err;
380 	zfs_handle_t	*zhp;
381 	zfs_handle_t	*clone;
382 	nvlist_t	*props = NULL;
383 
384 	if ((zhp = zfs_open(g_zfs, snapshot_name, ZFS_TYPE_SNAPSHOT)) == NULL)
385 		return (Z_NO_ENTRY);
386 
387 	(void) printf(gettext("Cloning snapshot %s\n"), snapshot_name);
388 
389 	if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0 ||
390 	    nvlist_add_string(props, zfs_prop_to_name(ZFS_PROP_SHARENFS),
391 	    "off") != 0) {
392 		if (props != NULL)
393 			nvlist_free(props);
394 		(void) fprintf(stderr, gettext("could not create ZFS clone "
395 		    "%s: out of memory\n"), zonepath);
396 		return (Z_ERR);
397 	}
398 
399 	err = zfs_clone(zhp, zonepath, props);
400 	zfs_close(zhp);
401 
402 	nvlist_free(props);
403 
404 	if (err != 0)
405 		return (Z_ERR);
406 
407 	/* create the mountpoint if necessary */
408 	if ((clone = zfs_open(g_zfs, zonepath, ZFS_TYPE_DATASET)) == NULL)
409 		return (Z_ERR);
410 
411 	/*
412 	 * The clone has been created so we need to print a diagnostic
413 	 * message if one of the following steps fails for some reason.
414 	 */
415 	if (zfs_mount(clone, NULL, 0) != 0) {
416 		(void) fprintf(stderr, gettext("could not mount ZFS clone "
417 		    "%s\n"), zfs_get_name(clone));
418 		res = Z_ERR;
419 
420 	} else if (clean_out_clone() != Z_OK) {
421 		(void) fprintf(stderr, gettext("could not remove the "
422 		    "software inventory from ZFS clone %s\n"),
423 		    zfs_get_name(clone));
424 		res = Z_ERR;
425 	}
426 
427 	zfs_close(clone);
428 	return (res);
429 }
430 
431 /*
432  * This function takes a zonepath and attempts to determine what the ZFS
433  * file system name (not mountpoint) should be for that path.  We do not
434  * assume that zonepath is an existing directory or ZFS fs since we use
435  * this function as part of the process of creating a new ZFS fs or clone.
436  *
437  * The way this works is that we look at the parent directory of the zonepath
438  * to see if it is a ZFS fs.  If it is, we get the name of that ZFS fs and
439  * append the last component of the zonepath to generate the ZFS name for the
440  * zonepath.  This matches the algorithm that ZFS uses for automatically
441  * mounting a new fs after it is created.
442  *
443  * Although a ZFS fs can be mounted anywhere, we don't worry about handling
444  * all of the complexity that a user could possibly configure with arbitrary
445  * mounts since there is no way to generate a ZFS name from a random path in
446  * the file system.  We only try to handle the automatic mounts that ZFS does
447  * for each file system.  ZFS restricts this so that a new fs must be created
448  * in an existing parent ZFS fs.  It then automatically mounts the new fs
449  * directly under the mountpoint for the parent fs using the last component
450  * of the name as the mountpoint directory.
451  *
452  * For example:
453  *    Name			Mountpoint
454  *    space/eng/dev/test/zone1	/project1/eng/dev/test/zone1
455  *
456  * Return Z_OK if the path mapped to a ZFS file system name, otherwise return
457  * Z_ERR.
458  */
459 static int
460 path2name(char *zonepath, char *zfs_name, int len)
461 {
462 	int		res;
463 	char		*bnm, *dnm, *dname, *bname;
464 	zfs_handle_t	*zhp;
465 	struct stat	stbuf;
466 
467 	/*
468 	 * We need two tmp strings to handle paths directly in / (e.g. /foo)
469 	 * since dirname will overwrite the first char after "/" in this case.
470 	 */
471 	if ((bnm = strdup(zonepath)) == NULL)
472 		return (Z_ERR);
473 
474 	if ((dnm = strdup(zonepath)) == NULL) {
475 		free(bnm);
476 		return (Z_ERR);
477 	}
478 
479 	bname = basename(bnm);
480 	dname = dirname(dnm);
481 
482 	/*
483 	 * This is a quick test to save iterating over all of the zfs datasets
484 	 * on the system (which can be a lot).  If the parent dir is not in a
485 	 * ZFS fs, then we're done.
486 	 */
487 	if (stat(dname, &stbuf) != 0 || !S_ISDIR(stbuf.st_mode) ||
488 	    strcmp(stbuf.st_fstype, MNTTYPE_ZFS) != 0) {
489 		free(bnm);
490 		free(dnm);
491 		return (Z_ERR);
492 	}
493 
494 	/* See if the parent directory is its own ZFS dataset. */
495 	if ((zhp = mount2zhandle(dname)) == NULL) {
496 		/*
497 		 * The parent is not a ZFS dataset so we can't automatically
498 		 * create a dataset on the given path.
499 		 */
500 		free(bnm);
501 		free(dnm);
502 		return (Z_ERR);
503 	}
504 
505 	res = snprintf(zfs_name, len, "%s/%s", zfs_get_name(zhp), bname);
506 
507 	free(bnm);
508 	free(dnm);
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_DATASET);
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, char *validatesnap)
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, validatesnap) != 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_zonepath, char *zonepath, char *presnapbuf,
638     char *postsnapbuf)
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(zhp, snap_name, sizeof (snap_name), presnapbuf,
682 	    postsnapbuf) != 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 	/* Check if the dataset already exists. */
723 	if ((zhp = zfs_open(g_zfs, zfs_name, ZFS_TYPE_DATASET)) != NULL) {
724 		zfs_close(zhp);
725 		return;
726 	}
727 
728 	if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0 ||
729 	    nvlist_add_string(props, zfs_prop_to_name(ZFS_PROP_SHARENFS),
730 	    "off") != 0) {
731 		if (props != NULL)
732 			nvlist_free(props);
733 		(void) fprintf(stderr, gettext("cannot create ZFS dataset %s: "
734 		    "out of memory\n"), zfs_name);
735 	}
736 
737 	if (zfs_create(g_zfs, zfs_name, ZFS_TYPE_FILESYSTEM, props) != 0 ||
738 	    (zhp = zfs_open(g_zfs, zfs_name, ZFS_TYPE_DATASET)) == NULL) {
739 		(void) fprintf(stderr, gettext("cannot create ZFS dataset %s: "
740 		    "%s\n"), zfs_name, libzfs_error_description(g_zfs));
741 		nvlist_free(props);
742 		return;
743 	}
744 
745 	nvlist_free(props);
746 
747 	if (zfs_mount(zhp, NULL, 0) != 0) {
748 		(void) fprintf(stderr, gettext("cannot mount ZFS dataset %s: "
749 		    "%s\n"), zfs_name, libzfs_error_description(g_zfs));
750 		(void) zfs_destroy(zhp);
751 	} else {
752 		if (chmod(zonepath, S_IRWXU) != 0) {
753 			(void) fprintf(stderr, gettext("file system %s "
754 			    "successfully created, but chmod %o failed: %s\n"),
755 			    zfs_name, S_IRWXU, strerror(errno));
756 			(void) destroy_zfs(zonepath);
757 		} else {
758 			(void) printf(gettext("A ZFS file system has been "
759 			    "created for this zone.\n"));
760 		}
761 	}
762 
763 	zfs_close(zhp);
764 }
765 
766 /*
767  * If the zonepath is a ZFS file system, attempt to destroy it.  We return Z_OK
768  * if we were able to zfs_destroy the zonepath, otherwise we return Z_ERR
769  * which means the caller should clean up the zonepath in the traditional
770  * way.
771  */
772 int
773 destroy_zfs(char *zonepath)
774 {
775 	zfs_handle_t	*zhp;
776 	boolean_t	is_clone = B_FALSE;
777 	char		origin[ZFS_MAXPROPLEN];
778 
779 	if ((zhp = mount2zhandle(zonepath)) == NULL)
780 		return (Z_ERR);
781 
782 	/*
783 	 * We can't destroy the file system if it has dependents.
784 	 */
785 	if (zfs_iter_dependents(zhp, B_TRUE, has_dependent, NULL) != 0 ||
786 	    zfs_unmount(zhp, NULL, 0) != 0) {
787 		zfs_close(zhp);
788 		return (Z_ERR);
789 	}
790 
791 	/*
792 	 * This might be a clone.  Try to get the snapshot so we can attempt
793 	 * to destroy that as well.
794 	 */
795 	if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof (origin), NULL,
796 	    NULL, 0, B_FALSE) == 0)
797 		is_clone = B_TRUE;
798 
799 	if (zfs_destroy(zhp) != 0) {
800 		/*
801 		 * If the destroy fails for some reason, try to remount
802 		 * the file system so that we can use "rm -rf" to clean up
803 		 * instead.
804 		 */
805 		(void) zfs_mount(zhp, NULL, 0);
806 		zfs_close(zhp);
807 		return (Z_ERR);
808 	}
809 
810 	/*
811 	 * If the zone has ever been moved then the mountpoint dir will not be
812 	 * cleaned up by the zfs_destroy().  To handle this case try to clean
813 	 * it up now but don't worry if it fails, that will be normal.
814 	 */
815 	(void) rmdir(zonepath);
816 
817 	(void) printf(gettext("The ZFS file system for this zone has been "
818 	    "destroyed.\n"));
819 
820 	if (is_clone) {
821 		zfs_handle_t	*ohp;
822 
823 		/*
824 		 * Try to clean up the snapshot that the clone was taken from.
825 		 */
826 		if ((ohp = zfs_open(g_zfs, origin,
827 		    ZFS_TYPE_SNAPSHOT)) != NULL) {
828 			if (zfs_iter_dependents(ohp, B_TRUE, has_dependent,
829 			    NULL) == 0 && zfs_unmount(ohp, NULL, 0) == 0)
830 				(void) zfs_destroy(ohp);
831 			zfs_close(ohp);
832 		}
833 	}
834 
835 	zfs_close(zhp);
836 	return (Z_OK);
837 }
838 
839 /*
840  * Return true if the path is its own zfs file system.  We determine this
841  * by stat-ing the path to see if it is zfs and stat-ing the parent to see
842  * if it is a different fs.
843  */
844 boolean_t
845 is_zonepath_zfs(char *zonepath)
846 {
847 	int res;
848 	char *path;
849 	char *parent;
850 	struct statvfs64 buf1, buf2;
851 
852 	if (statvfs64(zonepath, &buf1) != 0)
853 		return (B_FALSE);
854 
855 	if (strcmp(buf1.f_basetype, "zfs") != 0)
856 		return (B_FALSE);
857 
858 	if ((path = strdup(zonepath)) == NULL)
859 		return (B_FALSE);
860 
861 	parent = dirname(path);
862 	res = statvfs64(parent, &buf2);
863 	free(path);
864 
865 	if (res != 0)
866 		return (B_FALSE);
867 
868 	if (buf1.f_fsid == buf2.f_fsid)
869 		return (B_FALSE);
870 
871 	return (B_TRUE);
872 }
873 
874 /*
875  * Implement the fast move of a ZFS file system by simply updating the
876  * mountpoint.  Since it is file system already, we don't have the
877  * issue of cross-file system copying.
878  */
879 int
880 move_zfs(char *zonepath, char *new_zonepath)
881 {
882 	int		ret = Z_ERR;
883 	zfs_handle_t	*zhp;
884 
885 	if ((zhp = mount2zhandle(zonepath)) == NULL)
886 		return (Z_ERR);
887 
888 	if (zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
889 	    new_zonepath) == 0) {
890 		/*
891 		 * Clean up the old mount point.  We ignore any failure since
892 		 * the zone is already successfully mounted on the new path.
893 		 */
894 		(void) rmdir(zonepath);
895 		ret = Z_OK;
896 	}
897 
898 	zfs_close(zhp);
899 
900 	return (ret);
901 }
902 
903 /*
904  * Validate that the given dataset exists on the system, and that neither it nor
905  * its children are zvols.
906  *
907  * Note that we don't do anything with the 'zoned' property here.  All
908  * management is done in zoneadmd when the zone is actually rebooted.  This
909  * allows us to automatically set the zoned property even when a zone is
910  * rebooted by the administrator.
911  */
912 int
913 verify_datasets(zone_dochandle_t handle)
914 {
915 	int return_code = Z_OK;
916 	struct zone_dstab dstab;
917 	zfs_handle_t *zhp;
918 	char propbuf[ZFS_MAXPROPLEN];
919 	char source[ZFS_MAXNAMELEN];
920 	zprop_source_t srctype;
921 
922 	if (zonecfg_setdsent(handle) != Z_OK) {
923 		/*
924 		 * TRANSLATION_NOTE
925 		 * zfs and dataset are literals that should not be translated.
926 		 */
927 		(void) fprintf(stderr, gettext("could not verify zfs datasets: "
928 		    "unable to enumerate datasets\n"));
929 		return (Z_ERR);
930 	}
931 
932 	while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
933 
934 		if ((zhp = zfs_open(g_zfs, dstab.zone_dataset_name,
935 		    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) == NULL) {
936 			(void) fprintf(stderr, gettext("could not verify zfs "
937 			    "dataset %s: %s\n"), dstab.zone_dataset_name,
938 			    libzfs_error_description(g_zfs));
939 			return_code = Z_ERR;
940 			continue;
941 		}
942 
943 		if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf,
944 		    sizeof (propbuf), &srctype, source,
945 		    sizeof (source), 0) == 0 &&
946 		    (srctype == ZPROP_SRC_INHERITED)) {
947 			(void) fprintf(stderr, gettext("could not verify zfs "
948 			    "dataset %s: mountpoint cannot be inherited\n"),
949 			    dstab.zone_dataset_name);
950 			return_code = Z_ERR;
951 			zfs_close(zhp);
952 			continue;
953 		}
954 
955 		if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME) {
956 			(void) fprintf(stderr, gettext("cannot verify zfs "
957 			    "dataset %s: volumes cannot be specified as a "
958 			    "zone dataset resource\n"),
959 			    dstab.zone_dataset_name);
960 			return_code = Z_ERR;
961 		}
962 
963 		if (zfs_iter_children(zhp, check_zvol, NULL) != 0)
964 			return_code = Z_ERR;
965 
966 		zfs_close(zhp);
967 	}
968 	(void) zonecfg_enddsent(handle);
969 
970 	return (return_code);
971 }
972 
973 /*
974  * Verify that the ZFS dataset exists, and its mountpoint
975  * property is set to "legacy".
976  */
977 int
978 verify_fs_zfs(struct zone_fstab *fstab)
979 {
980 	zfs_handle_t *zhp;
981 	char propbuf[ZFS_MAXPROPLEN];
982 
983 	if ((zhp = zfs_open(g_zfs, fstab->zone_fs_special,
984 	    ZFS_TYPE_DATASET)) == NULL) {
985 		(void) fprintf(stderr, gettext("could not verify fs %s: "
986 		    "could not access zfs dataset '%s'\n"),
987 		    fstab->zone_fs_dir, fstab->zone_fs_special);
988 		return (Z_ERR);
989 	}
990 
991 	if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
992 		(void) fprintf(stderr, gettext("cannot verify fs %s: "
993 		    "'%s' is not a file system\n"),
994 		    fstab->zone_fs_dir, fstab->zone_fs_special);
995 		zfs_close(zhp);
996 		return (Z_ERR);
997 	}
998 
999 	if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf, sizeof (propbuf),
1000 	    NULL, NULL, 0, 0) != 0 || strcmp(propbuf, "legacy") != 0) {
1001 		(void) fprintf(stderr, gettext("could not verify fs %s: "
1002 		    "zfs '%s' mountpoint is not \"legacy\"\n"),
1003 		    fstab->zone_fs_dir, fstab->zone_fs_special);
1004 		zfs_close(zhp);
1005 		return (Z_ERR);
1006 	}
1007 
1008 	zfs_close(zhp);
1009 	return (Z_OK);
1010 }
1011 
1012 int
1013 init_zfs(void)
1014 {
1015 	if ((g_zfs = libzfs_init()) == NULL) {
1016 		(void) fprintf(stderr, gettext("failed to initialize ZFS "
1017 		    "library\n"));
1018 		return (Z_ERR);
1019 	}
1020 
1021 	return (Z_OK);
1022 }
1023