Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 5 May 2014 07:40:56 +0000 (UTC)
From:      Mark Murray <markm@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r265347 - in projects/random_number_generator: . release/doc/en_US.ISO8859-1/relnotes share/man/man9 sys/amd64/conf sys/cam/ctl sys/cddl/contrib/opensolaris/uts/common/fs/zfs sys/cddl/c...
Message-ID:  <201405050740.s457eudB039364@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: markm
Date: Mon May  5 07:40:55 2014
New Revision: 265347
URL: http://svnweb.freebsd.org/changeset/base/265347

Log:
  MFC - tracking commit.
  Merging r265316 through r265346.

Modified:
  projects/random_number_generator/ObsoleteFiles.inc
  projects/random_number_generator/release/doc/en_US.ISO8859-1/relnotes/article.xml
  projects/random_number_generator/share/man/man9/pget.9
  projects/random_number_generator/sys/amd64/conf/GENERIC.hints
  projects/random_number_generator/sys/cam/ctl/ctl_io.h
  projects/random_number_generator/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
  projects/random_number_generator/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c
  projects/random_number_generator/sys/geom/part/g_part.c
  projects/random_number_generator/sys/geom/part/g_part_ebr.c
  projects/random_number_generator/sys/geom/part/g_part_mbr.c
  projects/random_number_generator/sys/geom/part/g_part_pc98.c
  projects/random_number_generator/sys/geom/part/g_part_vtoc8.c
  projects/random_number_generator/sys/i386/conf/GENERIC.hints
  projects/random_number_generator/sys/netinet/tcp_input.c
  projects/random_number_generator/sys/netinet/tcp_reass.c
  projects/random_number_generator/sys/netinet/tcp_subr.c
  projects/random_number_generator/sys/netinet/tcp_usrreq.c
  projects/random_number_generator/sys/netinet/tcp_var.h
  projects/random_number_generator/sys/sys/mbuf.h
  projects/random_number_generator/usr.bin/nl/nl.1
  projects/random_number_generator/usr.bin/nl/nl.c
Directory Properties:
  projects/random_number_generator/   (props changed)
  projects/random_number_generator/sys/   (props changed)
  projects/random_number_generator/sys/cddl/contrib/opensolaris/   (props changed)

Modified: projects/random_number_generator/ObsoleteFiles.inc
==============================================================================
--- projects/random_number_generator/ObsoleteFiles.inc	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/ObsoleteFiles.inc	Mon May  5 07:40:55 2014	(r265347)
@@ -38,6 +38,8 @@
 #   xargs -n1 | sort | uniq -d;
 # done
 
+# 20140502: Removal of lindev(4)
+OLD_FILES+=usr/share/man/man4/lindev.4.gz
 # 20140314: AppleTalk
 OLD_DIRS+=usr/include/netatalk
 OLD_FILES+=usr/include/netatalk/aarp.h
@@ -49,7 +51,6 @@ OLD_FILES+=usr/include/netatalk/ddp_pcb.
 OLD_FILES+=usr/include/netatalk/ddp_var.h
 OLD_FILES+=usr/include/netatalk/endian.h
 OLD_FILES+=usr/include/netatalk/phase2.h
-
 # 20140314: Remove IPX/SPX
 OLD_LIBS+=lib/libipx.so.5
 OLD_FILES+=usr/include/netipx/ipx.h

Modified: projects/random_number_generator/release/doc/en_US.ISO8859-1/relnotes/article.xml
==============================================================================
--- projects/random_number_generator/release/doc/en_US.ISO8859-1/relnotes/article.xml	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/release/doc/en_US.ISO8859-1/relnotes/article.xml	Mon May  5 07:40:55 2014	(r265347)
@@ -107,7 +107,7 @@
     <para revision="265132">The &man.full.4; device has been added,
       and the <literal>lindev(4)</literal> device has been removed.
       Prior to this change, <literal>lindev(4)</literal> provided only
-      the <filename>/dev/null</filename> character device, returning
+      the <filename>/dev/full</filename> character device, returning
       <literal>ENOSPC</literal> on write attempts.  As this device is
       not specific to &linux;, a native &os; version has been
       added.</para>

Modified: projects/random_number_generator/share/man/man9/pget.9
==============================================================================
--- projects/random_number_generator/share/man/man9/pget.9	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/share/man/man9/pget.9	Mon May  5 07:40:55 2014	(r265347)
@@ -46,13 +46,13 @@ and fills a pointer to the
 structure in
 .Fa *pp .
 In the latter case, a process owning the specified thread is looked for.
-The actual operation is performed by invoking the
+The operation is performed by invoking the
 .Xr pfind 9
 function.
 The found process is returned locked.
-Only for
+For the
 .Dv PGET_HOLD
-case it is returned unlocked (but held).
+case, it is returned unlocked (but held).
 The
 .Fn pget
 function can
@@ -65,7 +65,7 @@ The
 argument is the logical OR of some subset of:
 .Bl -tag -width ".Dv PGET_NOTINEXEC"
 .It Dv PGET_HOLD
-If set, the found process will be referenced and unlocked.
+If set, the found process will be held and unlocked.
 .It Dv PGET_CANSEE
 If set, the found process will be checked for its visibility.
 See
@@ -93,6 +93,8 @@ If set,
 is not assumed as a thread id for values larger than
 .Dv PID_MAX .
 .It Dv PGET_WANTREAD
+If set, the found process will be checked that the caller may get
+a read access to its structure.
 A shorthand for
 .Pq Dv PGET_HOLD | PGET_CANDEBUG | PGET_NOTWEXIT .
 .El

Modified: projects/random_number_generator/sys/amd64/conf/GENERIC.hints
==============================================================================
--- projects/random_number_generator/sys/amd64/conf/GENERIC.hints	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/sys/amd64/conf/GENERIC.hints	Mon May  5 07:40:55 2014	(r265347)
@@ -31,3 +31,5 @@ hint.attimer.0.at="isa"
 hint.attimer.0.port="0x40"
 hint.attimer.0.irq="0"
 hint.wbwd.0.at="isa"
+hint.acpi_throttle.0.disabled="1"
+hint.p4tcc.0.disabled="1"

Modified: projects/random_number_generator/sys/cam/ctl/ctl_io.h
==============================================================================
--- projects/random_number_generator/sys/cam/ctl/ctl_io.h	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/sys/cam/ctl/ctl_io.h	Mon May  5 07:40:55 2014	(r265347)
@@ -293,21 +293,60 @@ union ctl_io;
  */
 struct ctl_scsiio {
 	struct ctl_io_hdr io_hdr;	/* common to all I/O types */
+
+	/*
+	 * The ext_* fields are generally intended for frontend use; CTL itself
+	 * doesn't modify or use them.
+	 */
 	uint32_t   ext_sg_entries;	/* 0 = no S/G list, > 0 = num entries */
 	uint8_t	   *ext_data_ptr;	/* data buffer or S/G list */
 	uint32_t   ext_data_len;	/* Data transfer length */
 	uint32_t   ext_data_filled;	/* Amount of data filled so far */
-	uint32_t   kern_sg_entries;	/* 0 = no S/G list, > 0 = num entries */
-	uint32_t   rem_sg_entries;	/* 0 = no S/G list, > 0 = num entries */
-	uint8_t    *kern_data_ptr;	/* data buffer or S/G list */
-	uint32_t   kern_data_len;	/* Length of this S/G list/buffer */
-	uint32_t   kern_total_len;	/* Total length of this transaction */
-	uint32_t   kern_data_resid;	/* Length left to transfer after this*/
-	uint32_t   kern_rel_offset;	/* Byte Offset of this transfer */
+
+	/*
+	 * The number of scatter/gather entries in the list pointed to
+	 * by kern_data_ptr.  0 means there is no list, just a data pointer.
+	 */
+	uint32_t   kern_sg_entries;
+
+	uint32_t   rem_sg_entries;	/* Unused. */
+
+	/*
+	 * The data pointer or a pointer to the scatter/gather list.
+	 */
+	uint8_t    *kern_data_ptr;
+
+	/*
+	 * Length of the data buffer or scatter/gather list.  It's also
+	 * the length of this particular piece of the data transfer,
+	 * ie. number of bytes expected to be transferred by the current
+	 * invocation of frontend's datamove() callback.  It's always
+	 * less than or equal to kern_total_len.
+	 */
+	uint32_t   kern_data_len;
+
+	/*
+	 * Total length of data to be transferred during this particular
+	 * SCSI command, as decoded from SCSI CDB.
+	 */
+	uint32_t   kern_total_len;
+
+	/*
+	 * Amount of data left after the current data transfer.
+	 */
+	uint32_t   kern_data_resid;
+
+	/*
+	 * Byte offset of this transfer, equal to the amount of data
+	 * already transferred for this SCSI command during previous
+	 * datamove() invocations.
+	 */
+	uint32_t   kern_rel_offset;
+
 	struct     scsi_sense_data sense_data;	/* sense data */
 	uint8_t	   sense_len;		/* Returned sense length */
 	uint8_t	   scsi_status;		/* SCSI status byte */
-	uint8_t	   sense_residual;	/* sense residual length */
+	uint8_t	   sense_residual;	/* Unused. */
 	uint32_t   residual;		/* data residual length */
 	uint32_t   tag_num;		/* tag number */
 	ctl_tag_type tag_type;		/* simple, ordered, head of queue,etc.*/

Modified: projects/random_number_generator/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
==============================================================================
--- projects/random_number_generator/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h	Mon May  5 07:40:55 2014	(r265347)
@@ -196,6 +196,7 @@ enum zio_flag {
 	ZIO_FLAG_NOPWRITE	= 1 << 25,
 	ZIO_FLAG_REEXECUTED	= 1 << 26,
 	ZIO_FLAG_DELEGATED	= 1 << 27,
+	ZIO_FLAG_QUEUE_IO_DONE	= 1 << 28,
 };
 
 #define	ZIO_FLAG_MUSTSUCCEED		0

Modified: projects/random_number_generator/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c
==============================================================================
--- projects/random_number_generator/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c	Mon May  5 07:40:55 2014	(r265347)
@@ -796,14 +796,25 @@ vdev_queue_io_done(zio_t *zio)
 
 	vq->vq_io_complete_ts = gethrtime();
 
+	if (zio->io_flags & ZIO_FLAG_QUEUE_IO_DONE) {
+		/*
+		 * Executing from a previous vdev_queue_io_done so
+		 * to avoid recursion we just unlock and return.
+		 */
+		mutex_exit(&vq->vq_lock);
+		return;
+	}
+
 	while ((nio = vdev_queue_io_to_issue(vq)) != NULL) {
 		mutex_exit(&vq->vq_lock);
+		nio->io_flags |= ZIO_FLAG_QUEUE_IO_DONE;
 		if (nio->io_done == vdev_queue_agg_io_done) {
 			zio_nowait(nio);
 		} else {
 			zio_vdev_io_reissue(nio);
 			zio_execute(nio);
 		}
+		nio->io_flags &= ~ZIO_FLAG_QUEUE_IO_DONE;
 		mutex_enter(&vq->vq_lock);
 	}
 

Modified: projects/random_number_generator/sys/geom/part/g_part.c
==============================================================================
--- projects/random_number_generator/sys/geom/part/g_part.c	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/sys/geom/part/g_part.c	Mon May  5 07:40:55 2014	(r265347)
@@ -1316,7 +1316,9 @@ g_part_ctl_resize(struct gctl_req *req, 
 
 	error = G_PART_RESIZE(table, entry, gpp);
 	if (error) {
-		gctl_error(req, "%d", error);
+		gctl_error(req, "%d%s", error, error != EBUSY ? "":
+		    " resizing will lead to unexpected shrinking"
+		    " due to alignment");
 		return (error);
 	}
 
@@ -2063,8 +2065,10 @@ g_part_resize(struct g_consumer *cp)
 		table->gpt_opened = 1;
 	}
 	if (G_PART_RESIZE(table, NULL, NULL) == 0)
-		printf("GEOM_PART: %s was automatically resized\n",
-		    cp->geom->name);
+		printf("GEOM_PART: %s was automatically resized.\n"
+		    "  Use `gpart commit %s` to save changes or "
+		    "`gpart undo %s` to revert them.\n", cp->geom->name,
+		    cp->geom->name, cp->geom->name);
 	if (g_part_check_integrity(table, cp) != 0) {
 		g_access(cp, -1, -1, -1);
 		table->gpt_opened = 0;

Modified: projects/random_number_generator/sys/geom/part/g_part_ebr.c
==============================================================================
--- projects/random_number_generator/sys/geom/part/g_part_ebr.c	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/sys/geom/part/g_part_ebr.c	Mon May  5 07:40:55 2014	(r265347)
@@ -220,47 +220,54 @@ ebr_set_chs(struct g_part_table *table, 
 }
 
 static int
+ebr_align(struct g_part_table *basetable, uint32_t *start, uint32_t *size)
+{
+	uint32_t sectors;
+
+	sectors = basetable->gpt_sectors;
+	if (*size < 2 * sectors)
+		return (EINVAL);
+	if (*start % sectors) {
+		*size += (*start % sectors) - sectors;
+		*start -= (*start % sectors) - sectors;
+	}
+	if (*size % sectors)
+		*size -= (*size % sectors);
+	if (*size < 2 * sectors)
+		return (EINVAL);
+	return (0);
+}
+
+
+static int
 g_part_ebr_add(struct g_part_table *basetable, struct g_part_entry *baseentry,
     struct g_part_parms *gpp)
 {
-	struct g_geom *gp;
 	struct g_provider *pp;
 	struct g_part_ebr_entry *entry;
-	uint32_t start, size, sectors;
+	uint32_t start, size;
 
 	if (gpp->gpp_parms & G_PART_PARM_LABEL)
 		return (EINVAL);
 
-	gp = basetable->gpt_gp;
-	pp = LIST_FIRST(&gp->consumer)->provider;
-	sectors = basetable->gpt_sectors;
-
+	pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
 	entry = (struct g_part_ebr_entry *)baseentry;
-
 	start = gpp->gpp_start;
 	size = gpp->gpp_size;
-	if (size < 2 * sectors)
-		return (EINVAL);
-	if (start % sectors) {
-		size = size - sectors + (start % sectors);
-		start = start - (start % sectors) + sectors;
-	}
-	if (size % sectors)
-		size = size - (size % sectors);
-	if (size < 2 * sectors)
+	if (ebr_align(basetable, &start, &size) != 0)
 		return (EINVAL);
-
 	if (baseentry->gpe_deleted)
 		bzero(&entry->ent, sizeof(entry->ent));
 
 	KASSERT(baseentry->gpe_start <= start, ("%s", __func__));
 	KASSERT(baseentry->gpe_end >= start + size - 1, ("%s", __func__));
-	baseentry->gpe_index = (start / sectors) + 1;
-	baseentry->gpe_offset = (off_t)(start + sectors) * pp->sectorsize;
+	baseentry->gpe_index = (start / basetable->gpt_sectors) + 1;
+	baseentry->gpe_offset =
+	    (off_t)(start + basetable->gpt_sectors) * pp->sectorsize;
 	baseentry->gpe_start = start;
 	baseentry->gpe_end = start + size - 1;
-	entry->ent.dp_start = sectors;
-	entry->ent.dp_size = size - sectors;
+	entry->ent.dp_start = basetable->gpt_sectors;
+	entry->ent.dp_size = size - basetable->gpt_sectors;
 	ebr_set_chs(basetable, entry->ent.dp_start, &entry->ent.dp_scyl,
 	    &entry->ent.dp_shd, &entry->ent.dp_ssect);
 	ebr_set_chs(basetable, baseentry->gpe_end, &entry->ent.dp_ecyl,

Modified: projects/random_number_generator/sys/geom/part/g_part_mbr.c
==============================================================================
--- projects/random_number_generator/sys/geom/part/g_part_mbr.c	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/sys/geom/part/g_part_mbr.c	Mon May  5 07:40:55 2014	(r265347)
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/sysctl.h>
 #include <geom/geom.h>
+#include <geom/geom_int.h>
 #include <geom/part/g_part.h>
 
 #include "g_part_if.h"
@@ -195,34 +196,39 @@ mbr_set_chs(struct g_part_table *table, 
 }
 
 static int
+mbr_align(struct g_part_table *basetable, uint32_t *start, uint32_t *size)
+{
+	uint32_t sectors;
+
+	sectors = basetable->gpt_sectors;
+	if (*size < sectors)
+		return (EINVAL);
+	if (start != NULL && (*start % sectors)) {
+		*size += (*start % sectors) - sectors;
+		*start -= (*start % sectors) - sectors;
+	}
+	if (*size % sectors)
+		*size -= (*size % sectors);
+	if (*size < sectors)
+		return (EINVAL);
+	return (0);
+}
+
+static int
 g_part_mbr_add(struct g_part_table *basetable, struct g_part_entry *baseentry,
     struct g_part_parms *gpp)
 {
 	struct g_part_mbr_entry *entry;
-	struct g_part_mbr_table *table;
-	uint32_t start, size, sectors;
+	uint32_t start, size;
 
 	if (gpp->gpp_parms & G_PART_PARM_LABEL)
 		return (EINVAL);
 
-	sectors = basetable->gpt_sectors;
-
 	entry = (struct g_part_mbr_entry *)baseentry;
-	table = (struct g_part_mbr_table *)basetable;
-
 	start = gpp->gpp_start;
 	size = gpp->gpp_size;
-	if (size < sectors)
-		return (EINVAL);
-	if (start % sectors) {
-		size = size - sectors + (start % sectors);
-		start = start - (start % sectors) + sectors;
-	}
-	if (size % sectors)
-		size = size - (size % sectors);
-	if (size < sectors)
+	if (mbr_align(basetable, &start, &size) != 0)
 		return (EINVAL);
-
 	if (baseentry->gpe_deleted)
 		bzero(&entry->ent, sizeof(entry->ent));
 
@@ -337,7 +343,7 @@ g_part_mbr_resize(struct g_part_table *b
 {
 	struct g_part_mbr_entry *entry;
 	struct g_provider *pp;
-	uint32_t size, sectors;
+	uint32_t size;
 
 	if (baseentry == NULL) {
 		pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
@@ -345,16 +351,14 @@ g_part_mbr_resize(struct g_part_table *b
 		    UINT32_MAX) - 1;
 		return (0);
 	}
-	sectors = basetable->gpt_sectors;
 	size = gpp->gpp_size;
-
-	if (size < sectors)
+	if (mbr_align(basetable, NULL, &size) != 0)
 		return (EINVAL);
-	if (size % sectors)
-		size = size - (size % sectors);
-	if (size < sectors)
-		return (EINVAL);
-
+	/* XXX: prevent unexpected shrinking. */
+	pp = baseentry->gpe_pp;
+	if ((g_debugflags & 16) == 0 && size < gpp->gpp_size &&
+	    (pp->acr > 0 || pp->acw > 0 || pp->ace > 0))
+		return (EBUSY);
 	entry = (struct g_part_mbr_entry *)baseentry;
 	baseentry->gpe_end = baseentry->gpe_start + size - 1;
 	entry->ent.dp_size = size;

Modified: projects/random_number_generator/sys/geom/part/g_part_pc98.c
==============================================================================
--- projects/random_number_generator/sys/geom/part/g_part_pc98.c	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/sys/geom/part/g_part_pc98.c	Mon May  5 07:40:55 2014	(r265347)
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/sysctl.h>
 #include <geom/geom.h>
+#include <geom/geom_int.h>
 #include <geom/part/g_part.h>
 
 #include "g_part_if.h"
@@ -175,32 +176,37 @@ pc98_set_chs(struct g_part_table *table,
 }
 
 static int
+pc98_align(struct g_part_table *basetable, uint32_t *start, uint32_t *size)
+{
+	uint32_t cyl;
+
+	cyl = basetable->gpt_heads * basetable->gpt_sectors;
+	if (*size < cyl)
+		return (EINVAL);
+	if (start != NULL && (*start % cyl)) {
+		*size += (*start % cyl) - cyl;
+		*start -= (*start % cyl) - cyl;
+	}
+	if (*size % cyl)
+		*size -= (*size % cyl);
+	if (*size < cyl)
+		return (EINVAL);
+	return (0);
+}
+
+static int
 g_part_pc98_add(struct g_part_table *basetable, struct g_part_entry *baseentry,
     struct g_part_parms *gpp)
 {
 	struct g_part_pc98_entry *entry;
-	struct g_part_pc98_table *table;
-	uint32_t cyl, start, size;
+	uint32_t start, size;
 	int error;
 
-	cyl = basetable->gpt_heads * basetable->gpt_sectors;
-
 	entry = (struct g_part_pc98_entry *)baseentry;
-	table = (struct g_part_pc98_table *)basetable;
-
 	start = gpp->gpp_start;
 	size = gpp->gpp_size;
-	if (size < cyl)
-		return (EINVAL);
-	if (start % cyl) {
-		size = size - cyl + (start % cyl);
-		start = start - (start % cyl) + cyl;
-	}
-	if (size % cyl)
-		size = size - (size % cyl);
-	if (size < cyl)
+	if (pc98_align(basetable, &start, &size) != 0)
 		return (EINVAL);
-
 	if (baseentry->gpe_deleted)
 		bzero(&entry->ent, sizeof(entry->ent));
 	else
@@ -344,7 +350,7 @@ g_part_pc98_resize(struct g_part_table *
 {
 	struct g_part_pc98_entry *entry;
 	struct g_provider *pp;
-	uint32_t size, cyl;
+	uint32_t size;
 
 	if (baseentry == NULL) {
 		pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
@@ -352,16 +358,14 @@ g_part_pc98_resize(struct g_part_table *
 		    UINT32_MAX) - 1;
 		return (0);
 	}
-	cyl = basetable->gpt_heads * basetable->gpt_sectors;
 	size = gpp->gpp_size;
-
-	if (size < cyl)
+	if (pc98_align(basetable, NULL, &size) != 0)
 		return (EINVAL);
-	if (size % cyl)
-		size = size - (size % cyl);
-	if (size < cyl)
-		return (EINVAL);
-
+	/* XXX: prevent unexpected shrinking. */
+	pp = baseentry->gpe_pp;
+	if ((g_debugflags & 0x10) == 0 && size < gpp->gpp_size &&
+	    (pp->acr > 0 || pp->acw > 0 || pp->ace > 0))
+		return (EBUSY);
 	entry = (struct g_part_pc98_entry *)baseentry;
 	baseentry->gpe_end = baseentry->gpe_start + size - 1;
 	pc98_set_chs(basetable, baseentry->gpe_end, &entry->ent.dp_ecyl,

Modified: projects/random_number_generator/sys/geom/part/g_part_vtoc8.c
==============================================================================
--- projects/random_number_generator/sys/geom/part/g_part_vtoc8.c	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/sys/geom/part/g_part_vtoc8.c	Mon May  5 07:40:55 2014	(r265347)
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/sysctl.h>
 #include <sys/vtoc.h>
 #include <geom/geom.h>
+#include <geom/geom_int.h>
 #include <geom/part/g_part.h>
 
 #include "g_part_if.h"
@@ -143,6 +144,23 @@ vtoc8_parse_type(const char *type, uint1
 }
 
 static int
+vtoc8_align(struct g_part_vtoc8_table *table, uint64_t *start, uint64_t *size)
+{
+
+	if (*size < table->secpercyl)
+		return (EINVAL);
+	if (start != NULL && (*start % table->secpercyl)) {
+		*size += (*start % table->secpercyl) - table->secpercyl;
+		*start -= (*start % table->secpercyl) - table->secpercyl;
+	}
+	if (*size % table->secpercyl)
+		*size -= (*size % table->secpercyl);
+	if (*size < table->secpercyl)
+		return (EINVAL);
+	return (0);
+}
+
+static int
 g_part_vtoc8_add(struct g_part_table *basetable, struct g_part_entry *entry,
     struct g_part_parms *gpp)
 {
@@ -160,16 +178,9 @@ g_part_vtoc8_add(struct g_part_table *ba
 
 	table = (struct g_part_vtoc8_table *)basetable;
 	index = entry->gpe_index - 1;
-
 	start = gpp->gpp_start;
 	size = gpp->gpp_size;
-	if (start % table->secpercyl) {
-		size = size - table->secpercyl + (start % table->secpercyl);
-		start = start - (start % table->secpercyl) + table->secpercyl;
-	}
-	if (size % table->secpercyl)
-		size = size - (size % table->secpercyl);
-	if (size < table->secpercyl)
+	if (vtoc8_align(table, &start, &size) != 0)
 		return (EINVAL);
 
 	KASSERT(entry->gpe_start <= start, (__func__));
@@ -355,11 +366,13 @@ g_part_vtoc8_resize(struct g_part_table 
 	}
 	table = (struct g_part_vtoc8_table *)basetable;
 	size = gpp->gpp_size;
-	if (size % table->secpercyl)
-		size = size - (size % table->secpercyl);
-	if (size < table->secpercyl)
+	if (vtoc8_align(table, NULL, &size) != 0)
 		return (EINVAL);
-
+	/* XXX: prevent unexpected shrinking. */
+	pp = entry->gpe_pp;
+	if ((g_debugflags & 0x10) == 0 && size < gpp->gpp_size &&
+	    (pp->acr > 0 || pp->acw > 0 || pp->ace > 0))
+		return (EBUSY);
 	entry->gpe_end = entry->gpe_start + size - 1;
 	be32enc(&table->vtoc.map[entry->gpe_index - 1].nblks, size);
 

Modified: projects/random_number_generator/sys/i386/conf/GENERIC.hints
==============================================================================
--- projects/random_number_generator/sys/i386/conf/GENERIC.hints	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/sys/i386/conf/GENERIC.hints	Mon May  5 07:40:55 2014	(r265347)
@@ -39,3 +39,5 @@ hint.attimer.0.at="isa"
 hint.attimer.0.port="0x40"
 hint.attimer.0.irq="0"
 hint.wbwd.0.at="isa"
+hint.acpi_throttle.0.disabled="1"
+hint.p4tcc.0.disabled="1"

Modified: projects/random_number_generator/sys/netinet/tcp_input.c
==============================================================================
--- projects/random_number_generator/sys/netinet/tcp_input.c	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/sys/netinet/tcp_input.c	Mon May  5 07:40:55 2014	(r265347)
@@ -1639,8 +1639,7 @@ tcp_do_segment(struct mbuf *m, struct tc
 	    tp->snd_nxt == tp->snd_max &&
 	    tiwin && tiwin == tp->snd_wnd && 
 	    ((tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) == 0) &&
-	    LIST_EMPTY(&tp->t_segq) &&
-	    ((to.to_flags & TOF_TS) == 0 ||
+	    tp->t_segq == NULL && ((to.to_flags & TOF_TS) == 0 ||
 	     TSTMP_GEQ(to.to_tsval, tp->ts_recent)) ) {
 
 		/*
@@ -2908,8 +2907,7 @@ dodata:							/* XXX */
 		 * immediately when segments are out of order (so
 		 * fast retransmit can work).
 		 */
-		if (th->th_seq == tp->rcv_nxt &&
-		    LIST_EMPTY(&tp->t_segq) &&
+		if (th->th_seq == tp->rcv_nxt && tp->t_segq == NULL &&
 		    TCPS_HAVEESTABLISHED(tp->t_state)) {
 			if (DELAY_ACK(tp, tlen))
 				tp->t_flags |= TF_DELACK;

Modified: projects/random_number_generator/sys/netinet/tcp_reass.c
==============================================================================
--- projects/random_number_generator/sys/netinet/tcp_reass.c	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/sys/netinet/tcp_reass.c	Mon May  5 07:40:55 2014	(r265347)
@@ -71,19 +71,10 @@ __FBSDID("$FreeBSD$");
 #include <netinet/tcp_var.h>
 #include <netinet6/tcp6_var.h>
 #include <netinet/tcpip.h>
-#ifdef TCPDEBUG
-#include <netinet/tcp_debug.h>
-#endif /* TCPDEBUG */
 
 static SYSCTL_NODE(_net_inet_tcp, OID_AUTO, reass, CTLFLAG_RW, 0,
     "TCP Segment Reassembly Queue");
 
-static VNET_DEFINE(int, tcp_reass_maxseg) = 0;
-#define	V_tcp_reass_maxseg		VNET(tcp_reass_maxseg)
-SYSCTL_VNET_INT(_net_inet_tcp_reass, OID_AUTO, maxsegments, CTLFLAG_RDTUN,
-    &VNET_NAME(tcp_reass_maxseg), 0,
-    "Global maximum number of TCP Segments in Reassembly Queue");
-
 static VNET_DEFINE(int, tcp_reass_overflows) = 0;
 #define	V_tcp_reass_overflows		VNET(tcp_reass_overflows)
 SYSCTL_VNET_INT(_net_inet_tcp_reass, OID_AUTO, overflows,
@@ -91,78 +82,32 @@ SYSCTL_VNET_INT(_net_inet_tcp_reass, OID
     &VNET_NAME(tcp_reass_overflows), 0,
     "Global number of TCP Segment Reassembly Queue Overflows");
 
-static VNET_DEFINE(uma_zone_t, tcp_reass_zone);
-#define	V_tcp_reass_zone		VNET(tcp_reass_zone)
-SYSCTL_UMA_CUR(_net_inet_tcp_reass, OID_AUTO, cursegments, CTLFLAG_VNET,
-    &VNET_NAME(tcp_reass_zone),
-    "Global number of TCP Segments currently in Reassembly Queue");
-
-/* Initialize TCP reassembly queue */
-static void
-tcp_reass_zone_change(void *tag)
-{
-
-	/* Set the zone limit and read back the effective value. */
-	V_tcp_reass_maxseg = nmbclusters / 16;
-	V_tcp_reass_maxseg = uma_zone_set_max(V_tcp_reass_zone,
-	    V_tcp_reass_maxseg);
-}
-
-void
-tcp_reass_init(void)
-{
-
-	V_tcp_reass_maxseg = nmbclusters / 16;
-	TUNABLE_INT_FETCH("net.inet.tcp.reass.maxsegments",
-	    &V_tcp_reass_maxseg);
-	V_tcp_reass_zone = uma_zcreate("tcpreass", sizeof (struct tseg_qent),
-	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
-	/* Set the zone limit and read back the effective value. */
-	V_tcp_reass_maxseg = uma_zone_set_max(V_tcp_reass_zone,
-	    V_tcp_reass_maxseg);
-	EVENTHANDLER_REGISTER(nmbclusters_change,
-	    tcp_reass_zone_change, NULL, EVENTHANDLER_PRI_ANY);
-}
-
-#ifdef VIMAGE
-void
-tcp_reass_destroy(void)
-{
-
-	uma_zdestroy(V_tcp_reass_zone);
-}
-#endif
-
 void
 tcp_reass_flush(struct tcpcb *tp)
 {
-	struct tseg_qent *qe;
+	struct mbuf *m;
 
 	INP_WLOCK_ASSERT(tp->t_inpcb);
 
-	while ((qe = LIST_FIRST(&tp->t_segq)) != NULL) {
-		LIST_REMOVE(qe, tqe_q);
-		m_freem(qe->tqe_m);
-		uma_zfree(V_tcp_reass_zone, qe);
-		tp->t_segqlen--;
+	while ((m = tp->t_segq) != NULL) {
+		tp->t_segq = m->m_nextpkt;
+		tp->t_segqlen -= m->m_pkthdr.len;
+		m_freem(m);
 	}
 
 	KASSERT((tp->t_segqlen == 0),
-	    ("TCP reass queue %p segment count is %d instead of 0 after flush.",
+	    ("TCP reass queue %p length is %d instead of 0 after flush.",
 	    tp, tp->t_segqlen));
 }
 
+#define	M_TCPHDR(m)	((struct tcphdr *)((m)->m_pkthdr.pkt_tcphdr))
+
 int
 tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
 {
-	struct tseg_qent *q;
-	struct tseg_qent *p = NULL;
-	struct tseg_qent *nq;
-	struct tseg_qent *te = NULL;
 	struct socket *so = tp->t_inpcb->inp_socket;
-	char *s = NULL;
-	int flags;
-	struct tseg_qent tqs;
+	struct mbuf *mq, *mp;
+	int flags, wakeup;
 
 	INP_WLOCK_ASSERT(tp->t_inpcb);
 
@@ -178,6 +123,10 @@ tcp_reass(struct tcpcb *tp, struct tcphd
 	if (th == NULL)
 		goto present;
 
+	M_ASSERTPKTHDR(m);
+	KASSERT(*tlenp == m->m_pkthdr.len, ("%s: tlenp %u len %u", __func__,
+	    *tlenp, m->m_pkthdr.len));
+
 	/*
 	 * Limit the number of segments that can be queued to reduce the
 	 * potential for mbuf exhaustion. For best performance, we want to be
@@ -188,19 +137,17 @@ tcp_reass(struct tcpcb *tp, struct tcphd
 	 * Always let the missing segment through which caused this queue.
 	 * NB: Access to the socket buffer is left intentionally unlocked as we
 	 * can tolerate stale information here.
-	 *
-	 * XXXLAS: Using sbspace(so->so_rcv) instead of so->so_rcv.sb_hiwat
-	 * should work but causes packets to be dropped when they shouldn't.
-	 * Investigate why and re-evaluate the below limit after the behaviour
-	 * is understood.
 	 */
 	if ((th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) &&
-	    tp->t_segqlen >= (so->so_rcv.sb_hiwat / tp->t_maxseg) + 1) {
+	    tp->t_segqlen + m->m_pkthdr.len >= sbspace(&so->so_rcv)) {
+		char *s;
+
 		V_tcp_reass_overflows++;
 		TCPSTAT_INC(tcps_rcvmemdrop);
 		m_freem(m);
 		*tlenp = 0;
-		if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) {
+		if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL,
+		    NULL))) {
 			log(LOG_DEBUG, "%s; %s: queue limit reached, "
 			    "segment dropped\n", s, __func__);
 			free(s, M_TCPLOG);
@@ -209,46 +156,13 @@ tcp_reass(struct tcpcb *tp, struct tcphd
 	}
 
 	/*
-	 * Allocate a new queue entry. If we can't, or hit the zone limit
-	 * just drop the pkt.
-	 *
-	 * Use a temporary structure on the stack for the missing segment
-	 * when the zone is exhausted. Otherwise we may get stuck.
-	 */
-	te = uma_zalloc(V_tcp_reass_zone, M_NOWAIT);
-	if (te == NULL) {
-		if (th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) {
-			TCPSTAT_INC(tcps_rcvmemdrop);
-			m_freem(m);
-			*tlenp = 0;
-			if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL,
-			    NULL))) {
-				log(LOG_DEBUG, "%s; %s: global zone limit "
-				    "reached, segment dropped\n", s, __func__);
-				free(s, M_TCPLOG);
-			}
-			return (0);
-		} else {
-			bzero(&tqs, sizeof(struct tseg_qent));
-			te = &tqs;
-			if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL,
-			    NULL))) {
-				log(LOG_DEBUG,
-				    "%s; %s: global zone limit reached, using "
-				    "stack for missing segment\n", s, __func__);
-				free(s, M_TCPLOG);
-			}
-		}
-	}
-	tp->t_segqlen++;
-
-	/*
 	 * Find a segment which begins after this one does.
 	 */
-	LIST_FOREACH(q, &tp->t_segq, tqe_q) {
-		if (SEQ_GT(q->tqe_th->th_seq, th->th_seq))
+	mp = NULL;
+	for (mq = tp->t_segq; mq != NULL; mq = mq->m_nextpkt) {
+		if (SEQ_GT(M_TCPHDR(mq)->th_seq, th->th_seq))
 			break;
-		p = q;
+		mp = mq;
 	}
 
 	/*
@@ -256,18 +170,16 @@ tcp_reass(struct tcpcb *tp, struct tcphd
 	 * our data already.  If so, drop the data from the incoming
 	 * segment.  If it provides all of our data, drop us.
 	 */
-	if (p != NULL) {
+	if (mp != NULL) {
 		int i;
+
 		/* conversion to int (in i) handles seq wraparound */
-		i = p->tqe_th->th_seq + p->tqe_len - th->th_seq;
+		i = M_TCPHDR(mp)->th_seq + mp->m_pkthdr.len - th->th_seq;
 		if (i > 0) {
 			if (i >= *tlenp) {
 				TCPSTAT_INC(tcps_rcvduppack);
 				TCPSTAT_ADD(tcps_rcvdupbyte, *tlenp);
 				m_freem(m);
-				if (te != &tqs)
-					uma_zfree(V_tcp_reass_zone, te);
-				tp->t_segqlen--;
 				/*
 				 * Try to present any queued data
 				 * at the left window edge to the user.
@@ -289,37 +201,40 @@ tcp_reass(struct tcpcb *tp, struct tcphd
 	 * While we overlap succeeding segments trim them or,
 	 * if they are completely covered, dequeue them.
 	 */
-	while (q) {
-		int i = (th->th_seq + *tlenp) - q->tqe_th->th_seq;
+	while (mq) {
+		struct mbuf *nq;
+		int i;
+
+		i = (th->th_seq + *tlenp) - M_TCPHDR(mq)->th_seq;
 		if (i <= 0)
 			break;
-		if (i < q->tqe_len) {
-			q->tqe_th->th_seq += i;
-			q->tqe_len -= i;
-			m_adj(q->tqe_m, i);
+		if (i < mq->m_pkthdr.len) {
+			M_TCPHDR(mq)->th_seq += i;
+			m_adj(mq, i);
+			tp->t_segqlen -= i;
 			break;
 		}
 
-		nq = LIST_NEXT(q, tqe_q);
-		LIST_REMOVE(q, tqe_q);
-		m_freem(q->tqe_m);
-		uma_zfree(V_tcp_reass_zone, q);
-		tp->t_segqlen--;
-		q = nq;
+		nq = mq->m_nextpkt;
+		tp->t_segqlen -= mq->m_pkthdr.len;
+		m_freem(mq);
+		if (mp)
+			mp->m_nextpkt = nq;
+		else
+			tp->t_segq = nq;
+		mq = nq;
 	}
 
 	/* Insert the new segment queue entry into place. */
-	te->tqe_m = m;
-	te->tqe_th = th;
-	te->tqe_len = *tlenp;
-
-	if (p == NULL) {
-		LIST_INSERT_HEAD(&tp->t_segq, te, tqe_q);
+	if (mp) {
+		m->m_nextpkt = mp->m_nextpkt;
+		mp->m_nextpkt = m;
 	} else {
-		KASSERT(te != &tqs, ("%s: temporary stack based entry not "
-		    "first element in queue", __func__));
-		LIST_INSERT_AFTER(p, te, tqe_q);
+		m->m_nextpkt = tp->t_segq;
+		tp->t_segq = m ;
 	}
+	m->m_pkthdr.pkt_tcphdr = th;
+	tp->t_segqlen += m->m_pkthdr.len;
 
 present:
 	/*
@@ -328,25 +243,30 @@ present:
 	 */
 	if (!TCPS_HAVEESTABLISHED(tp->t_state))
 		return (0);
-	q = LIST_FIRST(&tp->t_segq);
-	if (!q || q->tqe_th->th_seq != tp->rcv_nxt)
-		return (0);
+
+	flags = 0;
+	wakeup = 0;
 	SOCKBUF_LOCK(&so->so_rcv);
-	do {
-		tp->rcv_nxt += q->tqe_len;
-		flags = q->tqe_th->th_flags & TH_FIN;
-		nq = LIST_NEXT(q, tqe_q);
-		LIST_REMOVE(q, tqe_q);
+	while ((mq = tp->t_segq) != NULL &&
+	    M_TCPHDR(mq)->th_seq == tp->rcv_nxt) {
+		tp->t_segq = mq->m_nextpkt;
+
+		tp->rcv_nxt += mq->m_pkthdr.len;
+		tp->t_segqlen -= mq->m_pkthdr.len;
+		flags = M_TCPHDR(mq)->th_flags & TH_FIN;
+
 		if (so->so_rcv.sb_state & SBS_CANTRCVMORE)
-			m_freem(q->tqe_m);
-		else
-			sbappendstream_locked(&so->so_rcv, q->tqe_m);
-		if (q != &tqs)
-			uma_zfree(V_tcp_reass_zone, q);
-		tp->t_segqlen--;
-		q = nq;
-	} while (q && q->tqe_th->th_seq == tp->rcv_nxt);
+			m_freem(mq);
+		else {
+			mq->m_nextpkt = NULL;
+			sbappendstream_locked(&so->so_rcv, mq);
+			wakeup = 1;
+		}
+	}
 	ND6_HINT(tp);
-	sorwakeup_locked(so);
+	if (wakeup)
+		sorwakeup_locked(so);
+	else
+		SOCKBUF_UNLOCK(&so->so_rcv);
 	return (flags);
 }

Modified: projects/random_number_generator/sys/netinet/tcp_subr.c
==============================================================================
--- projects/random_number_generator/sys/netinet/tcp_subr.c	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/sys/netinet/tcp_subr.c	Mon May  5 07:40:55 2014	(r265347)
@@ -375,7 +375,6 @@ tcp_init(void)
 	tcp_tw_init();
 	syncache_init();
 	tcp_hc_init();
-	tcp_reass_init();
 
 	TUNABLE_INT_FETCH("net.inet.tcp.sack.enable", &V_tcp_do_sack);
 	V_sack_hole_zone = uma_zcreate("sackhole", sizeof(struct sackhole),
@@ -433,7 +432,6 @@ tcp_destroy(void)
 {
 	int error;
 
-	tcp_reass_destroy();
 	tcp_hc_destroy();
 	syncache_destroy();
 	tcp_tw_destroy();

Modified: projects/random_number_generator/sys/netinet/tcp_usrreq.c
==============================================================================
--- projects/random_number_generator/sys/netinet/tcp_usrreq.c	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/sys/netinet/tcp_usrreq.c	Mon May  5 07:40:55 2014	(r265347)
@@ -1949,7 +1949,7 @@ db_print_tcpcb(struct tcpcb *tp, const c
 
 	db_print_indent(indent);
 	db_printf("t_segq first: %p   t_segqlen: %d   t_dupacks: %d\n",
-	   LIST_FIRST(&tp->t_segq), tp->t_segqlen, tp->t_dupacks);
+	   tp->t_segq, tp->t_segqlen, tp->t_dupacks);
 
 	db_print_indent(indent);
 	db_printf("tt_rexmt: %p   tt_persist: %p   tt_keep: %p\n",

Modified: projects/random_number_generator/sys/netinet/tcp_var.h
==============================================================================
--- projects/random_number_generator/sys/netinet/tcp_var.h	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/sys/netinet/tcp_var.h	Mon May  5 07:40:55 2014	(r265347)
@@ -46,15 +46,6 @@ VNET_DECLARE(int, tcp_do_rfc1323);
 
 #endif /* _KERNEL */
 
-/* TCP segment queue entry */
-struct tseg_qent {
-	LIST_ENTRY(tseg_qent) tqe_q;
-	int	tqe_len;		/* TCP segment data length */
-	struct	tcphdr *tqe_th;		/* a pointer to tcp header */
-	struct	mbuf	*tqe_m;		/* mbuf contains packet */
-};
-LIST_HEAD(tsegqe_head, tseg_qent);
-
 struct sackblk {
 	tcp_seq start;		/* start seq no. of sack block */
 	tcp_seq end;		/* end seq no. */
@@ -100,7 +91,7 @@ do {								\
  * Organized for 16 byte cacheline efficiency.
  */
 struct tcpcb {
-	struct	tsegqe_head t_segq;	/* segment reassembly queue */
+	struct	mbuf *t_segq;		/* segment reassembly queue */
 	void	*t_pspare[2];		/* new reassembly queue */
 	int	t_segqlen;		/* segment reassembly queue length */
 	int	t_dupacks;		/* consecutive dup acks recd */
@@ -663,11 +654,7 @@ char	*tcp_log_addrs(struct in_conninfo *
 char	*tcp_log_vain(struct in_conninfo *, struct tcphdr *, void *,
 	    const void *);
 int	 tcp_reass(struct tcpcb *, struct tcphdr *, int *, struct mbuf *);
-void	 tcp_reass_init(void);
 void	 tcp_reass_flush(struct tcpcb *);
-#ifdef VIMAGE
-void	 tcp_reass_destroy(void);
-#endif
 void	 tcp_input(struct mbuf *, int);
 u_long	 tcp_maxmtu(struct in_conninfo *, struct tcp_ifcap *);
 u_long	 tcp_maxmtu6(struct in_conninfo *, struct tcp_ifcap *);

Modified: projects/random_number_generator/sys/sys/mbuf.h
==============================================================================
--- projects/random_number_generator/sys/sys/mbuf.h	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/sys/sys/mbuf.h	Mon May  5 07:40:55 2014	(r265347)
@@ -159,6 +159,7 @@ struct pkthdr {
 #define	tso_segsz	PH_per.sixteen[1]
 #define	csum_phsum	PH_per.sixteen[2]
 #define	csum_data	PH_per.thirtytwo[1]
+#define	pkt_tcphdr	PH_loc.ptr
 
 /*
  * Description of external storage mapped into mbuf; valid only if M_EXT is

Modified: projects/random_number_generator/usr.bin/nl/nl.1
==============================================================================
--- projects/random_number_generator/usr.bin/nl/nl.1	Mon May  5 03:15:53 2014	(r265346)
+++ projects/random_number_generator/usr.bin/nl/nl.1	Mon May  5 07:40:55 2014	(r265347)
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd January 26, 2005
+.Dd May 4, 2014
 .Dt NL 1
 .Os

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201405050740.s457eudB039364>