svn commit: r348572 - vendor/illumos/dist/lib/libzfs/common

Alexander Motin mav at FreeBSD.org
Mon Jun 3 19:20:11 UTC 2019


Author: mav
Date: Mon Jun  3 19:20:10 2019
New Revision: 348572
URL: https://svnweb.freebsd.org/changeset/base/348572

Log:
  9880 Race in ZFS parallel mount
  
  illumos/illumos-gate at bc4c0ff1343a311cc24933908ac6c4455af09031
  
  Reviewed by: Jason King <jason.king at joyent.com>
  Reviewed by: Sebastien Roy <sebastien.roy at delphix.com>
  Approved by: Joshua M. Clulow <josh at sysmgr.org>
  Author:     Andy Fiddaman <omnios at citrus-it.co.uk>

Modified:
  vendor/illumos/dist/lib/libzfs/common/libzfs_mount.c

Modified: vendor/illumos/dist/lib/libzfs/common/libzfs_mount.c
==============================================================================
--- vendor/illumos/dist/lib/libzfs/common/libzfs_mount.c	Mon Jun  3 19:19:35 2019	(r348571)
+++ vendor/illumos/dist/lib/libzfs/common/libzfs_mount.c	Mon Jun  3 19:20:10 2019	(r348572)
@@ -26,6 +26,7 @@
  * Copyright 2016 Igor Kozhukhov <ikozhukhov at gmail.com>
  * Copyright 2017 Joyent, Inc.
  * Copyright 2017 RackTop Systems.
+ * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
  */
 
 /*
@@ -1142,19 +1143,28 @@ zfs_iter_cb(zfs_handle_t *zhp, void *data)
 /*
  * Sort comparator that compares two mountpoint paths. We sort these paths so
  * that subdirectories immediately follow their parents. This means that we
- * effectively treat the '/' character as the lowest value non-nul char. An
- * example sorted list using this comparator would look like:
+ * effectively treat the '/' character as the lowest value non-nul char.
+ * Since filesystems from non-global zones can have the same mountpoint
+ * as other filesystems, the comparator sorts global zone filesystems to
+ * the top of the list. This means that the global zone will traverse the
+ * filesystem list in the correct order and can stop when it sees the
+ * first zoned filesystem. In a non-global zone, only the delegated
+ * filesystems are seen.
  *
+ * An example sorted list using this comparator would look like:
+ *
  * /foo
  * /foo/bar
  * /foo/bar/baz
  * /foo/baz
  * /foo.bar
+ * /foo (NGZ1)
+ * /foo (NGZ2)
  *
  * The mounting code depends on this ordering to deterministically iterate
  * over filesystems in order to spawn parallel mount tasks.
  */
-int
+static int
 mountpoint_cmp(const void *arga, const void *argb)
 {
 	zfs_handle_t *const *zap = arga;
@@ -1166,7 +1176,15 @@ mountpoint_cmp(const void *arga, const void *argb)
 	const char *a = mounta;
 	const char *b = mountb;
 	boolean_t gota, gotb;
+	uint64_t zoneda, zonedb;
 
+	zoneda = zfs_prop_get_int(za, ZFS_PROP_ZONED);
+	zonedb = zfs_prop_get_int(zb, ZFS_PROP_ZONED);
+	if (zoneda && !zonedb)
+		return (1);
+	if (!zoneda && zonedb)
+		return (-1);
+
 	gota = (zfs_get_type(za) == ZFS_TYPE_FILESYSTEM);
 	if (gota) {
 		verify(zfs_prop_get(za, ZFS_PROP_MOUNTPOINT, mounta,
@@ -1379,6 +1397,8 @@ void
 zfs_foreach_mountpoint(libzfs_handle_t *hdl, zfs_handle_t **handles,
     size_t num_handles, zfs_iter_f func, void *data, boolean_t parallel)
 {
+	zoneid_t zoneid = getzoneid();
+
 	/*
 	 * The ZFS_SERIAL_MOUNT environment variable is an undocumented
 	 * variable that can be used as a convenience to do a/b comparison
@@ -1414,6 +1434,14 @@ zfs_foreach_mountpoint(libzfs_handle_t *hdl, zfs_handl
 	 */
 	for (int i = 0; i < num_handles;
 	    i = non_descendant_idx(handles, num_handles, i)) {
+		/*
+		 * Since the mountpoints have been sorted so that the zoned
+		 * filesystems are at the end, a zoned filesystem seen from
+		 * the global zone means that we're done.
+		 */
+		if (zoneid == GLOBAL_ZONEID &&
+		    zfs_prop_get_int(handles[i], ZFS_PROP_ZONED))
+			break;
 		zfs_dispatch_mount(hdl, handles, num_handles, i, func, data,
 		    tq);
 	}


More information about the svn-src-all mailing list