diff --git a/release/doc/en_US.ISO8859-1/relnotes/article.xml b/release/doc/en_US.ISO8859-1/relnotes/article.xml
index 4f85f8124053..d2cef567d025 100644
--- a/release/doc/en_US.ISO8859-1/relnotes/article.xml
+++ b/release/doc/en_US.ISO8859-1/relnotes/article.xml
@@ -174,6 +174,11 @@
WITH_LLD_AS_LD build knob has been added,
which installs LLD as
/usr/bin/ld if set.
+
+
+ LLD has been enabled by default and
+ installed as /usr/bin/ld on
+ &os;/&arch.arm64;.
@@ -225,6 +230,10 @@
The &man.daemon.8; utility has been
updated to allow redirecting &man.stdout.4; and &man.stderr.4;
output to &man.syslog.3; or to a file.
+
+ The
+ &man.efivar.8; utility has been added, providing an interface
+ to manage UEFI variables.
@@ -384,8 +393,8 @@
clock and choose between absolute and relative mode.
The clang
- nullability qualifier has been added to the
- C library headers.
+ nullability qualifiers have been added to
+ the C library headers.
Uses of the GNU
__nonnull__ attribute have been replaced
@@ -597,6 +606,12 @@
sponsor="&netgate;">The &man.etherswitch.4; driver has been
updated to support RTL8366RB and RTL8366SR cards.
+ The
+ &man.if.ipsec.4; virtual tunneling interface has been added,
+ implementing route-based VPNs protected
+ with Encapsulating Security Payload
+ (ESP).
+
The &man.qlnxe.4; driver has been added,
providing support for Cavium® Qlogic™ 45000 Series
adapters.
@@ -641,6 +656,25 @@
sponsor="&chelsio;">PCI passthrough with
&man.bhyve.4; resets functions via FLR when
a virtual machine is started and stopped.
+
+ PCI passthrough support has
+ been enabled on &os; virtual machines running on
+ Microsoft® Hyper-V™.
+
+ The
+ &man.hv.netvsc.4; driver SR-IOV
+ implementation has been updated to support Virtual Function
+ (VF) devices, such as the Mellanox®
+ Connect-X3™ network card.
+
+ Support
+ for Microsoft® Hyper-V™ Generation 2 virtual
+ machines has been added.
+
+ Support
+ for synthetic keyboards has been added for virtual machines
+ running on Microsoft® Hyper-V™.
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index 2a4308298c60..b68f63660bf6 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -107,7 +107,11 @@ struct pidfh *pidfile;
*/
#define ASSERT_STATE(state_is, state_shouldbe) {}
-#define TIME_MAX 2147483647
+/*
+ * We need to check that the expiry, renewal and rebind times are not beyond
+ * the end of time (~2038 when a 32-bit time_t is being used).
+ */
+#define TIME_MAX ((((time_t) 1 << (sizeof(time_t) * CHAR_BIT - 2)) - 1) * 2 + 1)
int log_priority;
int no_daemon;
@@ -762,15 +766,17 @@ dhcpack(struct packet *packet)
else
ip->client->new->expiry = default_lease_time;
/* A number that looks negative here is really just very large,
- because the lease expiry offset is unsigned. */
- if (ip->client->new->expiry < 0)
- ip->client->new->expiry = TIME_MAX;
+ because the lease expiry offset is unsigned. Also make sure that
+ the addition of cur_time below does not overflow (a 32 bit) time_t. */
+ if (ip->client->new->expiry < 0 ||
+ ip->client->new->expiry > TIME_MAX - cur_time)
+ ip->client->new->expiry = TIME_MAX - cur_time;
/* XXX should be fixed by resetting the client state */
if (ip->client->new->expiry < 60)
ip->client->new->expiry = 60;
/* Unless overridden in the config, take the server-provided renewal
- * time if there is one; otherwise figure it out according to the spec.
+ * time if there is one. Otherwise figure it out according to the spec.
* Also make sure the renewal time does not exceed the expiry time.
*/
if (ip->client->config->default_actions[DHO_DHCP_RENEWAL_TIME] ==
@@ -782,7 +788,8 @@ dhcpack(struct packet *packet)
ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
else
ip->client->new->renewal = ip->client->new->expiry / 2;
- if (ip->client->new->renewal > ip->client->new->expiry / 2)
+ if (ip->client->new->renewal < 0 ||
+ ip->client->new->renewal > ip->client->new->expiry / 2)
ip->client->new->renewal = ip->client->new->expiry / 2;
/* Same deal with the rebind time. */
@@ -794,20 +801,15 @@ dhcpack(struct packet *packet)
ip->client->new->rebind = getULong(
ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
else
- ip->client->new->rebind = ip->client->new->renewal * 7 / 4;
- if (ip->client->new->rebind > ip->client->new->renewal * 7 / 4)
- ip->client->new->rebind = ip->client->new->renewal * 7 / 4;
-
- ip->client->new->expiry += cur_time;
- /* Lease lengths can never be negative. */
- if (ip->client->new->expiry < cur_time)
- ip->client->new->expiry = TIME_MAX;
- ip->client->new->renewal += cur_time;
- if (ip->client->new->renewal < cur_time)
- ip->client->new->renewal = TIME_MAX;
- ip->client->new->rebind += cur_time;
- if (ip->client->new->rebind < cur_time)
- ip->client->new->rebind = TIME_MAX;
+ ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
+ if (ip->client->new->rebind < 0 ||
+ ip->client->new->rebind > ip->client->new->renewal / 4 * 7)
+ ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
+
+ /* Convert the time offsets into seconds-since-the-epoch */
+ ip->client->new->expiry += cur_time;
+ ip->client->new->renewal += cur_time;
+ ip->client->new->rebind += cur_time;
bind_lease(ip);
}
diff --git a/sbin/dhclient/options.c b/sbin/dhclient/options.c
index be073dae39cd..fe025e6d6a40 100644
--- a/sbin/dhclient/options.c
+++ b/sbin/dhclient/options.c
@@ -783,7 +783,7 @@ pretty_print_option(unsigned int code, unsigned char *data, int len,
dp += 4;
break;
case 'L':
- opcount = snprintf(op, opleft, "%ld",
+ opcount = snprintf(op, opleft, "%lu",
(unsigned long)getULong(dp));
if (opcount >= opleft || opcount == -1)
goto toobig;
@@ -799,7 +799,7 @@ pretty_print_option(unsigned int code, unsigned char *data, int len,
dp += 2;
break;
case 'S':
- opcount = snprintf(op, opleft, "%d",
+ opcount = snprintf(op, opleft, "%u",
getUShort(dp));
if (opcount >= opleft || opcount == -1)
goto toobig;
diff --git a/sys/arm/include/vmparam.h b/sys/arm/include/vmparam.h
index c28b28ebfd73..061ccabe9d2c 100644
--- a/sys/arm/include/vmparam.h
+++ b/sys/arm/include/vmparam.h
@@ -42,7 +42,7 @@
* Virtual memory related constants, all in bytes
*/
#ifndef MAXTSIZ
-#define MAXTSIZ (64UL*1024*1024) /* max text size */
+#define MAXTSIZ (256UL*1024*1024) /* max text size */
#endif
#ifndef DFLDSIZ
#define DFLDSIZ (128UL*1024*1024) /* initial data size limit */
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
index 22b48e823060..c6e30301c623 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
@@ -49,6 +49,16 @@ struct g_class zfs_vdev_class = {
.attrchanged = vdev_geom_attrchanged,
};
+struct consumer_vdev_elem {
+ SLIST_ENTRY(consumer_vdev_elem) elems;
+ vdev_t *vd;
+};
+
+SLIST_HEAD(consumer_priv_t, consumer_vdev_elem);
+_Static_assert(sizeof(((struct g_consumer*)NULL)->private)
+ == sizeof(struct consumer_priv_t*),
+ "consumer_priv_t* can't be stored in g_consumer.private");
+
DECLARE_GEOM_CLASS(zfs_vdev_class, zfs_vdev);
SYSCTL_DECL(_vfs_zfs_vdev);
@@ -85,21 +95,16 @@ vdev_geom_set_rotation_rate(vdev_t *vd, struct g_consumer *cp)
}
static void
-vdev_geom_set_physpath(struct g_consumer *cp, boolean_t do_null_update)
+vdev_geom_set_physpath(vdev_t *vd, struct g_consumer *cp,
+ boolean_t do_null_update)
{
boolean_t needs_update = B_FALSE;
- vdev_t *vd;
char *physpath;
int error, physpath_len;
- if (g_access(cp, 1, 0, 0) != 0)
- return;
-
- vd = cp->private;
physpath_len = MAXPATHLEN;
physpath = g_malloc(physpath_len, M_WAITOK|M_ZERO);
error = g_io_getattr("GEOM::physpath", cp, &physpath_len, physpath);
- g_access(cp, -1, 0, 0);
if (error == 0) {
char *old_physpath;
@@ -130,37 +135,40 @@ vdev_geom_set_physpath(struct g_consumer *cp, boolean_t do_null_update)
static void
vdev_geom_attrchanged(struct g_consumer *cp, const char *attr)
{
- vdev_t *vd;
char *old_physpath;
+ struct consumer_priv_t *priv;
+ struct consumer_vdev_elem *elem;
int error;
- vd = cp->private;
- if (vd == NULL)
+ priv = (struct consumer_priv_t*)&cp->private;
+ if (SLIST_EMPTY(priv))
return;
- if (strcmp(attr, "GEOM::rotation_rate") == 0) {
- vdev_geom_set_rotation_rate(vd, cp);
- return;
- }
-
- if (strcmp(attr, "GEOM::physpath") == 0) {
- vdev_geom_set_physpath(cp, /*do_null_update*/B_TRUE);
- return;
+ SLIST_FOREACH(elem, priv, elems) {
+ vdev_t *vd = elem->vd;
+ if (strcmp(attr, "GEOM::rotation_rate") == 0) {
+ vdev_geom_set_rotation_rate(vd, cp);
+ return;
+ }
+ if (strcmp(attr, "GEOM::physpath") == 0) {
+ vdev_geom_set_physpath(vd, cp, /*null_update*/B_TRUE);
+ return;
+ }
}
}
static void
vdev_geom_orphan(struct g_consumer *cp)
{
- vdev_t *vd;
+ struct consumer_priv_t *priv;
+ struct consumer_vdev_elem *elem;
g_topology_assert();
- vd = cp->private;
- if (vd == NULL) {
+ priv = (struct consumer_priv_t*)&cp->private;
+ if (SLIST_EMPTY(priv))
/* Vdev close in progress. Ignore the event. */
return;
- }
/*
* Orphan callbacks occur from the GEOM event thread.
@@ -176,8 +184,12 @@ vdev_geom_orphan(struct g_consumer *cp)
* async removal support to invoke a close on this
* vdev once it is safe to do so.
*/
- vd->vdev_remove_wanted = B_TRUE;
- spa_async_request(vd->vdev_spa, SPA_ASYNC_REMOVE);
+ SLIST_FOREACH(elem, priv, elems) {
+ vdev_t *vd = elem->vd;
+
+ vd->vdev_remove_wanted = B_TRUE;
+ spa_async_request(vd->vdev_spa, SPA_ASYNC_REMOVE);
+ }
}
static struct g_consumer *
@@ -265,21 +277,8 @@ vdev_geom_attach(struct g_provider *pp, vdev_t *vd)
}
}
- /*
- * BUG: cp may already belong to a vdev. This could happen if:
- * 1) That vdev is a shared spare, or
- * 2) We are trying to reopen a missing vdev and we are scanning by
- * guid. In that case, we'll ultimately fail to open this consumer,
- * but not until after setting the private field.
- * The solution is to:
- * 1) Don't set the private field until after the open succeeds, and
- * 2) Set it to a linked list of vdevs, not just a single vdev
- */
- cp->private = vd;
- if (vd != NULL) {
+ if (vd != NULL)
vd->vdev_tsd = cp;
- vdev_geom_set_physpath(cp, /*do_null_update*/B_FALSE);
- }
cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE;
return (cp);
@@ -289,16 +288,12 @@ static void
vdev_geom_detach(struct g_consumer *cp, boolean_t open_for_read)
{
struct g_geom *gp;
- vdev_t *vd;
g_topology_assert();
ZFS_LOG(1, "Detaching from %s.",
cp->provider && cp->provider->name ? cp->provider->name : "NULL");
- vd = cp->private;
- cp->private = NULL;
-
gp = cp->geom;
if (open_for_read)
g_access(cp, -1, 0, -1);
@@ -324,16 +319,26 @@ static void
vdev_geom_close_locked(vdev_t *vd)
{
struct g_consumer *cp;
+ struct consumer_priv_t *priv;
+ struct consumer_vdev_elem *elem, *elem_temp;
g_topology_assert();
cp = vd->vdev_tsd;
- vd->vdev_tsd = NULL;
vd->vdev_delayed_close = B_FALSE;
if (cp == NULL)
return;
ZFS_LOG(1, "Closing access to %s.", cp->provider->name);
+ KASSERT(cp->private != NULL, ("%s: cp->private is NULL", __func__));
+ priv = (struct consumer_priv_t*)&cp->private;
+ vd->vdev_tsd = NULL;
+ SLIST_FOREACH_SAFE(elem, priv, elems, elem_temp) {
+ if (elem->vd == vd) {
+ SLIST_REMOVE(priv, elem, consumer_vdev_elem, elems);
+ g_free(elem);
+ }
+ }
vdev_geom_detach(cp, B_TRUE);
}
@@ -870,11 +875,27 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
cp = NULL;
}
}
+ if (cp != NULL) {
+ struct consumer_priv_t *priv;
+ struct consumer_vdev_elem *elem;
+
+ priv = (struct consumer_priv_t*)&cp->private;
+ if (cp->private == NULL)
+ SLIST_INIT(priv);
+ elem = g_malloc(sizeof(*elem), M_WAITOK|M_ZERO);
+ elem->vd = vd;
+ SLIST_INSERT_HEAD(priv, elem, elems);
+ }
/* Fetch initial physical path information for this device. */
- if (cp != NULL)
+ if (cp != NULL) {
vdev_geom_attrchanged(cp, "GEOM::physpath");
+ /* Set other GEOM characteristics */
+ vdev_geom_set_physpath(vd, cp, /*do_null_update*/B_FALSE);
+ vdev_geom_set_rotation_rate(vd, cp);
+ }
+
g_topology_unlock();
PICKUP_GIANT();
if (cp == NULL) {
@@ -905,11 +926,6 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
*/
vd->vdev_nowritecache = B_FALSE;
- /*
- * Determine the device's rotation rate.
- */
- vdev_geom_set_rotation_rate(vd, cp);
-
return (0);
}