summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c1
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_gettimeofday.c2
-rw-r--r--lib/libc/db/hash/hash.c3
-rw-r--r--lib/libc/sys/ktrace.24
-rw-r--r--sbin/devd/tests/client_test.c66
-rw-r--r--share/man/man4/amdsbwd.46
-rw-r--r--share/man/man4/usb_quirk.48
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c10
-rw-r--r--sys/dev/amdsbwd/amdsbwd.c20
-rw-r--r--sys/dev/sound/pci/hda/hdac.c2
-rw-r--r--sys/dev/sound/pci/hda/hdac.h4
-rw-r--r--sys/dev/usb/controller/ehci_pci.c2
-rw-r--r--sys/dev/usb/controller/ohci_pci.c3
-rw-r--r--sys/dev/usb/controller/xhci_pci.c3
-rw-r--r--sys/fs/ext2fs/ext2_alloc.c4
-rw-r--r--sys/fs/ext2fs/ext2_vfsops.c6
-rw-r--r--sys/kern/kern_event.c61
-rw-r--r--sys/net/if.c7
-rw-r--r--sys/sys/event.h1
-rw-r--r--tests/sys/kqueue/common.h1
-rw-r--r--tests/sys/kqueue/main.c69
-rw-r--r--tests/sys/kqueue/proc.c168
-rw-r--r--usr.bin/ktrace/ktrace.15
-rw-r--r--usr.bin/uuencode/uuencode.14
-rw-r--r--usr.bin/uuencode/uuencode.c18
25 files changed, 382 insertions, 96 deletions
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
index dcfff2f..b787bcd 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
@@ -694,6 +694,7 @@ dt_module_load_proc(dtrace_hdl_t *dtp, dt_module_t *dmp)
arg.dpa_count = 0;
if (Pobject_iter_resolved(p, dt_module_load_proc_count, &arg) != 0) {
dt_dprintf("failed to iterate objects\n");
+ dt_proc_unlock(dtp, p);
dt_proc_release(dtp, p);
return (dt_set_errno(dtp, EDT_CANTLOAD));
}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_gettimeofday.c b/contrib/netbsd-tests/lib/libc/sys/t_gettimeofday.c
index 1cf303b..4d82a26 100644
--- a/contrib/netbsd-tests/lib/libc/sys/t_gettimeofday.c
+++ b/contrib/netbsd-tests/lib/libc/sys/t_gettimeofday.c
@@ -46,9 +46,11 @@ ATF_TC_HEAD(gettimeofday_err, tc)
ATF_TC_BODY(gettimeofday_err, tc)
{
+#ifdef __NetBSD__
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, gettimeofday((void *)-1, NULL) != 0);
+#endif
}
ATF_TC(gettimeofday_mono);
diff --git a/lib/libc/db/hash/hash.c b/lib/libc/db/hash/hash.c
index 333b1a1..12220a9 100644
--- a/lib/libc/db/hash/hash.c
+++ b/lib/libc/db/hash/hash.c
@@ -423,7 +423,8 @@ hdestroy(HTAB *hashp)
free(hashp->tmp_buf);
if (hashp->fp != -1) {
- (void)_fsync(hashp->fp);
+ if (hashp->save_file)
+ (void)_fsync(hashp->fp);
(void)_close(hashp->fp);
}
diff --git a/lib/libc/sys/ktrace.2 b/lib/libc/sys/ktrace.2
index 4e5d92a..b02a672 100644
--- a/lib/libc/sys/ktrace.2
+++ b/lib/libc/sys/ktrace.2
@@ -28,7 +28,7 @@
.\" @(#)ktrace.2 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd October 10, 2011
+.Dd March 31, 2016
.Dt KTRACE 2
.Os
.Sh NAME
@@ -94,6 +94,8 @@ generate much output).
.It KTRFAC_PROCCTOR Ta "Trace process construction."
.It KTRFAC_PROCDTOR Ta "Trace process destruction."
.It KTRFAC_CAPFAIL Ta "Trace capability failures."
+.It KTRFAC_FAULT Ta "Trace page faults."
+.It KTRFAC_FAULTEND Ta "Trace the end of page faults."
.It KTRFAC_INHERIT Ta "Inherit tracing to future children."
.El
.Pp
diff --git a/sbin/devd/tests/client_test.c b/sbin/devd/tests/client_test.c
index 77f8a9c..79ebca7 100644
--- a/sbin/devd/tests/client_test.c
+++ b/sbin/devd/tests/client_test.c
@@ -34,6 +34,10 @@ __FBSDID("$FreeBSD$");
#include <sys/un.h>
#include <atf-c.h>
+
+const char create_pat[] = "!system=DEVFS subsystem=CDEV type=CREATE cdev=md";
+const char destroy_pat[] = "!system=DEVFS subsystem=CDEV type=DESTROY cdev=md";
+
/* Helper functions*/
/*
@@ -63,6 +67,24 @@ create_two_events(void)
ATF_REQUIRE_EQ(0, pclose(destroy_stdout));
}
+/* Setup and return an open client socket */
+static int
+common_setup(int socktype, const char* sockpath) {
+ struct sockaddr_un devd_addr;
+ int s, error;
+
+ memset(&devd_addr, 0, sizeof(devd_addr));
+ devd_addr.sun_family = PF_LOCAL;
+ strlcpy(devd_addr.sun_path, sockpath, sizeof(devd_addr.sun_path));
+ s = socket(PF_LOCAL, socktype, 0);
+ ATF_REQUIRE(s >= 0);
+ error = connect(s, (struct sockaddr*)&devd_addr, SUN_LEN(&devd_addr));
+ ATF_REQUIRE_EQ(0, error);
+
+ create_two_events();
+ return (s);
+}
+
/*
* Test Cases
*/
@@ -75,27 +97,10 @@ ATF_TC_WITHOUT_HEAD(seqpacket);
ATF_TC_BODY(seqpacket, tc)
{
int s;
- int error;
- struct sockaddr_un devd_addr;
bool got_create_event = false;
bool got_destroy_event = false;
- const char create_pat[] =
- "!system=DEVFS subsystem=CDEV type=CREATE cdev=md";
- const char destroy_pat[] =
- "!system=DEVFS subsystem=CDEV type=DESTROY cdev=md";
-
- memset(&devd_addr, 0, sizeof(devd_addr));
- devd_addr.sun_family = PF_LOCAL;
- strlcpy(devd_addr.sun_path, "/var/run/devd.seqpacket.pipe",
- sizeof(devd_addr.sun_path));
-
- s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
- ATF_REQUIRE(s >= 0);
- error = connect(s, (struct sockaddr*)&devd_addr, SUN_LEN(&devd_addr));
- ATF_REQUIRE_EQ(0, error);
-
- create_two_events();
+ s = common_setup(SOCK_SEQPACKET, "/var/run/devd.seqpacket.pipe");
/*
* Loop until both events are detected on _different_ reads
* There may be extra events due to unrelated system activity
@@ -132,31 +137,14 @@ ATF_TC_WITHOUT_HEAD(stream);
ATF_TC_BODY(stream, tc)
{
int s;
- int error;
- struct sockaddr_un devd_addr;
bool got_create_event = false;
bool got_destroy_event = false;
- const char create_pat[] =
- "!system=DEVFS subsystem=CDEV type=CREATE cdev=md";
- const char destroy_pat[] =
- "!system=DEVFS subsystem=CDEV type=DESTROY cdev=md";
ssize_t len = 0;
- memset(&devd_addr, 0, sizeof(devd_addr));
- devd_addr.sun_family = PF_LOCAL;
- strlcpy(devd_addr.sun_path, "/var/run/devd.pipe",
- sizeof(devd_addr.sun_path));
-
- s = socket(PF_LOCAL, SOCK_STREAM, 0);
- ATF_REQUIRE(s >= 0);
- error = connect(s, (struct sockaddr*)&devd_addr, SUN_LEN(&devd_addr));
- ATF_REQUIRE_EQ(0, error);
-
- create_two_events();
-
+ s = common_setup(SOCK_STREAM, "/var/run/devd.pipe");
/*
- * Loop until both events are detected on _different_ reads
- * There may be extra events due to unrelated system activity
+ * Loop until both events are detected on the same or different reads.
+ * There may be extra events due to unrelated system activity.
* If we never get both events, then the test will timeout.
*/
while (!(got_create_event && got_destroy_event)) {
@@ -169,7 +157,7 @@ ATF_TC_BODY(stream, tc)
ATF_REQUIRE(newlen != -1);
len += newlen;
/* NULL terminate the result */
- event[newlen] = '\0';
+ event[len] = '\0';
printf("%s", event);
create_pos = strstr(event, create_pat);
diff --git a/share/man/man4/amdsbwd.4 b/share/man/man4/amdsbwd.4
index cfb2f79..dd85bf7 100644
--- a/share/man/man4/amdsbwd.4
+++ b/share/man/man4/amdsbwd.4
@@ -25,12 +25,12 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 7, 2011
+.Dd March 29, 2016
.Dt AMDSBWD 4
.Os
.Sh NAME
.Nm amdsbwd
-.Nd device driver for the AMD SB600/SB7xx/SB8xx watchdog timers
+.Nd device driver for the AMD southbridge watchdog timers
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following line in your
@@ -51,7 +51,7 @@ The
driver provides
.Xr watchdog 4
support for the watchdog timers present on
-AMD SB600, SB7xx and SB8xx southbridges.
+AMD SB600, SB7xx, SB8xx and SB9xx southbridges and Axx FCHs.
.Sh SEE ALSO
.Xr watchdog 4 ,
.Xr watchdog 8 ,
diff --git a/share/man/man4/usb_quirk.4 b/share/man/man4/usb_quirk.4
index 89ace34..f207466 100644
--- a/share/man/man4/usb_quirk.4
+++ b/share/man/man4/usb_quirk.4
@@ -16,7 +16,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 26, 2015
+.Dd April 4, 2016
.Dt USB_QUIRK 4
.Os
.Sh NAME
@@ -234,6 +234,12 @@ device which appears as a USB device on
usbconfig -d ugen0.3 add_quirk UQ_MSC_EJECT_WAIT
.Ed
.Pp
+Enable a Holtec/Keep Out F85 gaming keyboard on
+.Pa ugen1.4 :
+.Bd -literal -offset indent
+usbconfig -d ugen1.4 add_quirk UQ_KBD_BOOTPROTO
+.Ed
+.Pp
To install a quirk at boot time, place one or several lines like the
following in
.Xr loader.conf 5 :
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 d64001e..30eb903 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
@@ -676,7 +676,15 @@ vdev_geom_open_by_path(vdev_t *vd, int check_guid)
g_topology_unlock();
vdev_geom_read_guids(cp, &pguid, &vguid);
g_topology_lock();
- if (pguid != spa_guid(vd->vdev_spa) ||
+ /*
+ * Check that the label's vdev guid matches the
+ * desired guid. If the label has a pool guid,
+ * check that it matches too. (Inactive spares
+ * and L2ARCs do not have any pool guid in the
+ * label.)
+ */
+ if ((pguid != 0 &&
+ pguid != spa_guid(vd->vdev_spa)) ||
vguid != vd->vdev_guid) {
vdev_geom_close_locked(vd);
cp = NULL;
diff --git a/sys/dev/amdsbwd/amdsbwd.c b/sys/dev/amdsbwd/amdsbwd.c
index 4726416..4603c90 100644
--- a/sys/dev/amdsbwd/amdsbwd.c
+++ b/sys/dev/amdsbwd/amdsbwd.c
@@ -106,6 +106,8 @@ __FBSDID("$FreeBSD$");
/* SB7xx RRG 2.3.1.1, SB600 RRG 2.3.1.1, SB8xx RRG 2.3.1. */
#define AMDSB_SMBUS_DEVID 0x43851002
#define AMDSB8_SMBUS_REVID 0x40
+#define AMDHUDSON_SMBUS_DEVID 0x780b1022
+#define AMDKERNCZ_SMBUS_DEVID 0x790b1022
#define amdsbwd_verbose_printf(dev, ...) \
do { \
@@ -279,7 +281,9 @@ amdsbwd_identify(driver_t *driver, device_t parent)
smb_dev = pci_find_bsf(0, 20, 0);
if (smb_dev == NULL)
return;
- if (pci_get_devid(smb_dev) != AMDSB_SMBUS_DEVID)
+ if (pci_get_devid(smb_dev) != AMDSB_SMBUS_DEVID &&
+ pci_get_devid(smb_dev) != AMDHUDSON_SMBUS_DEVID &&
+ pci_get_devid(smb_dev) != AMDKERNCZ_SMBUS_DEVID)
return;
child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "amdsbwd", -1);
@@ -309,10 +313,12 @@ amdsbwd_probe_sb7xx(device_t dev, struct resource *pmres, uint32_t *addr)
*addr <<= 8;
*addr |= pmio_read(pmres, AMDSB_PM_WDT_BASE_MSB - i);
}
+ *addr &= ~0x07u;
+
/* Set watchdog timer tick to 1s. */
val = pmio_read(pmres, AMDSB_PM_WDT_CTRL);
val &= ~AMDSB_WDT_RES_MASK;
- val |= AMDSB_WDT_RES_10MS;
+ val |= AMDSB_WDT_RES_1S;
pmio_write(pmres, AMDSB_PM_WDT_CTRL, val);
/* Enable watchdog device (in stopped state). */
@@ -372,7 +378,7 @@ amdsbwd_probe_sb8xx(device_t dev, struct resource *pmres, uint32_t *addr)
val = pmio_read(pmres, AMDSB8_PM_WDT_EN);
device_printf(dev, "AMDSB8_PM_WDT_EN value = %#02x\n", val);
#endif
- device_set_desc(dev, "AMD SB8xx Watchdog Timer");
+ device_set_desc(dev, "AMD SB8xx/SB9xx/Axx Watchdog Timer");
}
static int
@@ -404,7 +410,8 @@ amdsbwd_probe(device_t dev)
smb_dev = pci_find_bsf(0, 20, 0);
KASSERT(smb_dev != NULL, ("can't find SMBus PCI device\n"));
- if (pci_get_revid(smb_dev) < AMDSB8_SMBUS_REVID)
+ if (pci_get_devid(smb_dev) == AMDSB_SMBUS_DEVID &&
+ pci_get_revid(smb_dev) < AMDSB8_SMBUS_REVID)
amdsbwd_probe_sb7xx(dev, res, &addr);
else
amdsbwd_probe_sb8xx(dev, res, &addr);
@@ -440,10 +447,7 @@ amdsbwd_attach_sb(device_t dev, struct amdsbwd_softc *sc)
smb_dev = pci_find_bsf(0, 20, 0);
KASSERT(smb_dev != NULL, ("can't find SMBus PCI device\n"));
- if (pci_get_revid(smb_dev) < AMDSB8_SMBUS_REVID)
- sc->ms_per_tick = 10;
- else
- sc->ms_per_tick = 1000;
+ sc->ms_per_tick = 1000;
sc->res_ctrl = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&sc->rid_ctrl, RF_ACTIVE);
diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c
index f20443b..9768dd2 100644
--- a/sys/dev/sound/pci/hda/hdac.c
+++ b/sys/dev/sound/pci/hda/hdac.c
@@ -159,6 +159,7 @@ static const struct {
{ HDA_ATI_RV940, "ATI RV940", 0, 0 },
{ HDA_ATI_RV970, "ATI RV970", 0, 0 },
{ HDA_ATI_R1000, "ATI R1000", 0, 0 },
+ { HDA_AMD_HUDSON2, "AMD Hudson-2", 0, 0 },
{ HDA_RDC_M3010, "RDC M3010", 0, 0 },
{ HDA_VIA_VT82XX, "VIA VT8251/8237A",0, 0 },
{ HDA_SIS_966, "SiS 966", 0, 0 },
@@ -167,6 +168,7 @@ static const struct {
{ HDA_INTEL_ALL, "Intel", 0, 0 },
{ HDA_NVIDIA_ALL, "NVIDIA", 0, 0 },
{ HDA_ATI_ALL, "ATI", 0, 0 },
+ { HDA_AMD_ALL, "AMD", 0, 0 },
{ HDA_VIA_ALL, "VIA", 0, 0 },
{ HDA_SIS_ALL, "SiS", 0, 0 },
{ HDA_ULI_ALL, "ULI", 0, 0 },
diff --git a/sys/dev/sound/pci/hda/hdac.h b/sys/dev/sound/pci/hda/hdac.h
index d9d8ad6..c6b4b6a 100644
--- a/sys/dev/sound/pci/hda/hdac.h
+++ b/sys/dev/sound/pci/hda/hdac.h
@@ -136,6 +136,10 @@
#define HDA_ATI_R1000 HDA_MODEL_CONSTRUCT(ATI, 0xaaa0)
#define HDA_ATI_ALL HDA_MODEL_CONSTRUCT(ATI, 0xffff)
+#define AMD_VENDORID 0x1022
+#define HDA_AMD_HUDSON2 HDA_MODEL_CONSTRUCT(AMD, 0x780d)
+#define HDA_AMD_ALL HDA_MODEL_CONSTRUCT(AMD, 0xffff)
+
/* RDC */
#define RDC_VENDORID 0x17f3
#define HDA_RDC_M3010 HDA_MODEL_CONSTRUCT(RDC, 0x3010)
diff --git a/sys/dev/usb/controller/ehci_pci.c b/sys/dev/usb/controller/ehci_pci.c
index 1fab1d3..47048df 100644
--- a/sys/dev/usb/controller/ehci_pci.c
+++ b/sys/dev/usb/controller/ehci_pci.c
@@ -112,6 +112,8 @@ ehci_pci_match(device_t self)
case 0x20951022:
return ("AMD CS5536 (Geode) USB 2.0 controller");
+ case 0x78081022:
+ return ("AMD FCH USB 2.0 controller");
case 0x43451002:
return "ATI SB200 USB 2.0 controller";
diff --git a/sys/dev/usb/controller/ohci_pci.c b/sys/dev/usb/controller/ohci_pci.c
index 257f20d..af03392 100644
--- a/sys/dev/usb/controller/ohci_pci.c
+++ b/sys/dev/usb/controller/ohci_pci.c
@@ -124,9 +124,10 @@ ohci_pci_match(device_t self)
case 0x740c1022:
return ("AMD-756 USB Controller");
-
case 0x74141022:
return ("AMD-766 USB Controller");
+ case 0x78071022:
+ return ("AMD FCH USB Controller");
case 0x43741002:
return "ATI SB400 USB Controller";
diff --git a/sys/dev/usb/controller/xhci_pci.c b/sys/dev/usb/controller/xhci_pci.c
index 48dee2c..ef1a7d6 100644
--- a/sys/dev/usb/controller/xhci_pci.c
+++ b/sys/dev/usb/controller/xhci_pci.c
@@ -95,6 +95,9 @@ xhci_pci_match(device_t self)
uint32_t device_id = pci_get_devid(self);
switch (device_id) {
+ case 0x78141022:
+ return ("AMD FCH USB 3.0 controller");
+
case 0x01941033:
return ("NEC uPD720200 USB 3.0 controller");
diff --git a/sys/fs/ext2fs/ext2_alloc.c b/sys/fs/ext2fs/ext2_alloc.c
index 2bf7772..448b051 100644
--- a/sys/fs/ext2fs/ext2_alloc.c
+++ b/sys/fs/ext2fs/ext2_alloc.c
@@ -406,10 +406,8 @@ ext2_valloc(struct vnode *pvp, int mode, struct ucred *cred, struct vnode **vpp)
/*
* Set up a new generation number for this inode.
- * XXX check if this makes sense in ext2
*/
- if (ip->i_gen == 0 || ++ip->i_gen == 0)
- ip->i_gen = random() / 2 + 1;
+ ip->i_gen = arc4random();
vfs_timestamp(&ts);
ip->i_birthtime = ts.tv_sec;
diff --git a/sys/fs/ext2fs/ext2_vfsops.c b/sys/fs/ext2fs/ext2_vfsops.c
index fab98a5..a1f3c51 100644
--- a/sys/fs/ext2fs/ext2_vfsops.c
+++ b/sys/fs/ext2fs/ext2_vfsops.c
@@ -308,8 +308,8 @@ ext2_check_sb_compat(struct ext2fs *es, struct cdev *dev, int ronly)
}
/*
- * This computes the fields of the ext2_sb_info structure from the
- * data in the ext2_super_block structure read in.
+ * This computes the fields of the m_ext2fs structure from the
+ * data in the ext2fs structure read in.
*/
static int
compute_sb_data(struct vnode *devvp, struct ext2fs *es,
@@ -600,7 +600,7 @@ ext2_mountfs(struct vnode *devvp, struct mount *mp)
/*
* I don't know whether this is the right strategy. Note that
- * we dynamically allocate both an ext2_sb_info and an ext2_super_block
+ * we dynamically allocate both an m_ext2fs and an ext2fs
* while Linux keeps the super block in a locked buffer.
*/
ump->um_e2fs = malloc(sizeof(struct m_ext2fs),
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index e665a8e..a0c4fa4 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -364,11 +364,21 @@ filt_procattach(struct knote *kn)
kn->kn_flags |= EV_CLEAR; /* automatically set */
/*
- * internal flag indicating registration done by kernel
+ * Internal flag indicating registration done by kernel for the
+ * purposes of getting a NOTE_CHILD notification.
*/
- if (kn->kn_flags & EV_FLAG1) {
+ if (kn->kn_flags & EV_FLAG2) {
+ kn->kn_flags &= ~EV_FLAG2;
kn->kn_data = kn->kn_sdata; /* ppid */
kn->kn_fflags = NOTE_CHILD;
+ kn->kn_sfflags &= ~NOTE_EXIT;
+ immediate = 1; /* Force immediate activation of child note. */
+ }
+ /*
+ * Internal flag indicating registration done by kernel (for other than
+ * NOTE_CHILD).
+ */
+ if (kn->kn_flags & EV_FLAG1) {
kn->kn_flags &= ~EV_FLAG1;
}
@@ -376,9 +386,10 @@ filt_procattach(struct knote *kn)
knlist_add(&p->p_klist, kn, 1);
/*
- * Immediately activate any exit notes if the target process is a
- * zombie. This is necessary to handle the case where the target
- * process, e.g. a child, dies before the kevent is registered.
+ * Immediately activate any child notes or, in the case of a zombie
+ * target process, exit notes. The latter is necessary to handle the
+ * case where the target process, e.g. a child, dies before the kevent
+ * is registered.
*/
if (immediate && filt_proc(kn, NOTE_EXIT))
KNOTE_ACTIVATE(kn, 0);
@@ -487,7 +498,7 @@ knote_fork(struct knlist *list, int pid)
/*
* The NOTE_TRACK case. In addition to the activation
- * of the event, we need to register new event to
+ * of the event, we need to register new events to
* track the child. Drop the locks in preparation for
* the call to kqueue_register().
*/
@@ -496,8 +507,27 @@ knote_fork(struct knlist *list, int pid)
list->kl_unlock(list->kl_lockarg);
/*
- * Activate existing knote and register a knote with
+ * Activate existing knote and register tracking knotes with
* new process.
+ *
+ * First register a knote to get just the child notice. This
+ * must be a separate note from a potential NOTE_EXIT
+ * notification since both NOTE_CHILD and NOTE_EXIT are defined
+ * to use the data field (in conflicting ways).
+ */
+ kev.ident = pid;
+ kev.filter = kn->kn_filter;
+ kev.flags = kn->kn_flags | EV_ADD | EV_ENABLE | EV_ONESHOT | EV_FLAG2;
+ kev.fflags = kn->kn_sfflags;
+ kev.data = kn->kn_id; /* parent */
+ kev.udata = kn->kn_kevent.udata;/* preserve udata */
+ error = kqueue_register(kq, &kev, NULL, 0);
+ if (error)
+ kn->kn_fflags |= NOTE_TRACKERR;
+
+ /*
+ * Then register another knote to track other potential events
+ * from the new process.
*/
kev.ident = pid;
kev.filter = kn->kn_filter;
@@ -1071,7 +1101,7 @@ findkn:
if (fp->f_type == DTYPE_KQUEUE) {
/*
- * if we add some inteligence about what we are doing,
+ * If we add some intelligence about what we are doing,
* we should be able to support events on ourselves.
* We need to know when we are doing this to prevent
* getting both the knlist lock and the kq lock since
@@ -1103,7 +1133,18 @@ findkn:
kqueue_expand(kq, fops, kev->ident, waitok);
KQ_LOCK(kq);
- if (kq->kq_knhashmask != 0) {
+
+ /*
+ * If possible, find an existing knote to use for this kevent.
+ */
+ if (kev->filter == EVFILT_PROC &&
+ (kev->flags & (EV_FLAG1 | EV_FLAG2)) != 0) {
+ /* This is an internal creation of a process tracking
+ * note. Don't attempt to coalesce this with an
+ * existing note.
+ */
+ ;
+ } else if (kq->kq_knhashmask != 0) {
struct klist *list;
list = &kq->kq_knhash[
@@ -1115,7 +1156,7 @@ findkn:
}
}
- /* knote is in the process of changing, wait for it to stablize. */
+ /* knote is in the process of changing, wait for it to stabilize. */
if (kn != NULL && (kn->kn_status & KN_INFLUX) == KN_INFLUX) {
KQ_GLOBAL_UNLOCK(&kq_global, haskqglobal);
if (filedesc_unlock) {
diff --git a/sys/net/if.c b/sys/net/if.c
index 288d944..af8182b 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -339,11 +339,12 @@ ifnet_setbyindex(u_short idx, struct ifnet *ifp)
struct ifaddr *
ifaddr_byindex(u_short idx)
{
- struct ifaddr *ifa;
+ struct ifnet *ifp;
+ struct ifaddr *ifa = NULL;
IFNET_RLOCK_NOSLEEP();
- ifa = ifnet_byindex_locked(idx)->if_addr;
- if (ifa != NULL)
+ ifp = ifnet_byindex_locked(idx);
+ if (ifp != NULL && (ifa = ifp->if_addr) != NULL)
ifa_ref(ifa);
IFNET_RUNLOCK_NOSLEEP();
return (ifa);
diff --git a/sys/sys/event.h b/sys/sys/event.h
index d8ea6f5..dfa9138 100644
--- a/sys/sys/event.h
+++ b/sys/sys/event.h
@@ -78,6 +78,7 @@ struct kevent {
#define EV_SYSFLAGS 0xF000 /* reserved by system */
#define EV_DROP 0x1000 /* note should be dropped */
#define EV_FLAG1 0x2000 /* filter-specific flag */
+#define EV_FLAG2 0x4000 /* filter-specific flag */
/* returned values */
#define EV_EOF 0x8000 /* EOF detected */
diff --git a/tests/sys/kqueue/common.h b/tests/sys/kqueue/common.h
index aada778..89a4029 100644
--- a/tests/sys/kqueue/common.h
+++ b/tests/sys/kqueue/common.h
@@ -46,6 +46,7 @@ int vnode_fd;
extern const char * kevent_to_str(struct kevent *);
struct kevent * kevent_get(int);
+struct kevent * kevent_get_timeout(int, int);
void kevent_cmp(struct kevent *, struct kevent *);
diff --git a/tests/sys/kqueue/main.c b/tests/sys/kqueue/main.c
index f76c4e2..26e8f91 100644
--- a/tests/sys/kqueue/main.c
+++ b/tests/sys/kqueue/main.c
@@ -69,6 +69,28 @@ kevent_get(int kqfd)
return (kev);
}
+/* Retrieve a single kevent, specifying a maximum time to wait for it. */
+struct kevent *
+kevent_get_timeout(int kqfd, int seconds)
+{
+ int nfds;
+ struct kevent *kev;
+ struct timespec timeout = {seconds, 0};
+
+ if ((kev = calloc(1, sizeof(*kev))) == NULL)
+ err(1, "out of memory");
+
+ nfds = kevent(kqfd, NULL, 0, kev, 1, &timeout);
+ if (nfds < 0) {
+ err(1, "kevent(2)");
+ } else if (nfds == 0) {
+ free(kev);
+ kev = NULL;
+ }
+
+ return (kev);
+}
+
char *
kevent_fflags_dump(struct kevent *kev)
{
@@ -82,25 +104,33 @@ kevent_fflags_dump(struct kevent *kev)
abort();
/* Not every filter has meaningful fflags */
- if (kev->filter != EVFILT_VNODE) {
- snprintf(buf, 1024, "fflags = %d", kev->fflags);
- return (buf);
- }
-
- snprintf(buf, 1024, "fflags = %d (", kev->fflags);
- KEVFFL_DUMP(NOTE_DELETE);
- KEVFFL_DUMP(NOTE_WRITE);
- KEVFFL_DUMP(NOTE_EXTEND);
+ if (kev->filter == EVFILT_PROC) {
+ snprintf(buf, 1024, "fflags = %x (", kev->fflags);
+ KEVFFL_DUMP(NOTE_EXIT);
+ KEVFFL_DUMP(NOTE_FORK);
+ KEVFFL_DUMP(NOTE_EXEC);
+ KEVFFL_DUMP(NOTE_CHILD);
+ KEVFFL_DUMP(NOTE_TRACKERR);
+ KEVFFL_DUMP(NOTE_TRACK);
+ buf[strlen(buf) - 1] = ')';
+ } else if (kev->filter == EVFILT_VNODE) {
+ snprintf(buf, 1024, "fflags = %x (", kev->fflags);
+ KEVFFL_DUMP(NOTE_DELETE);
+ KEVFFL_DUMP(NOTE_WRITE);
+ KEVFFL_DUMP(NOTE_EXTEND);
#if HAVE_NOTE_TRUNCATE
- KEVFFL_DUMP(NOTE_TRUNCATE);
+ KEVFFL_DUMP(NOTE_TRUNCATE);
#endif
- KEVFFL_DUMP(NOTE_ATTRIB);
- KEVFFL_DUMP(NOTE_LINK);
- KEVFFL_DUMP(NOTE_RENAME);
+ KEVFFL_DUMP(NOTE_ATTRIB);
+ KEVFFL_DUMP(NOTE_LINK);
+ KEVFFL_DUMP(NOTE_RENAME);
#if HAVE_NOTE_REVOKE
- KEVFFL_DUMP(NOTE_REVOKE);
+ KEVFFL_DUMP(NOTE_REVOKE);
#endif
- buf[strlen(buf) - 1] = ')';
+ buf[strlen(buf) - 1] = ')';
+ } else {
+ snprintf(buf, 1024, "fflags = %x", kev->fflags);
+ }
return (buf);
}
@@ -260,6 +290,15 @@ main(int argc, char **argv)
argc--;
}
+ /*
+ * Some tests fork. If output is fully buffered,
+ * the children inherit some buffered data and flush
+ * it when they exit, causing some data to be printed twice.
+ * Use line buffering to avoid this problem.
+ */
+ setlinebuf(stdout);
+ setlinebuf(stderr);
+
test_kqueue();
test_kqueue_close();
diff --git a/tests/sys/kqueue/proc.c b/tests/sys/kqueue/proc.c
index 6288ee6..79b8d35 100644
--- a/tests/sys/kqueue/proc.c
+++ b/tests/sys/kqueue/proc.c
@@ -74,6 +74,172 @@ add_and_delete(void)
}
+static void
+proc_track(int sleep_time)
+{
+ char test_id[64];
+ struct kevent kev;
+ pid_t pid;
+ int pipe_fd[2];
+ ssize_t result;
+
+ snprintf(test_id, sizeof(test_id),
+ "kevent(EVFILT_PROC, NOTE_TRACK); sleep %d", sleep_time);
+ test_begin(test_id);
+ test_no_kevents();
+
+ if (pipe(pipe_fd)) {
+ err(1, "pipe (parent) failed! (%s() at %s:%d)",
+ __func__, __FILE__, __LINE__);
+ }
+
+ /* Create a child to track. */
+ pid = fork();
+ if (pid == 0) { /* Child */
+ pid_t grandchild = -1;
+
+ /*
+ * Give the parent a chance to start tracking us.
+ */
+ result = read(pipe_fd[1], test_id, 1);
+ if (result != 1) {
+ err(1, "read from pipe in child failed! (ret %zd) (%s() at %s:%d)",
+ result, __func__, __FILE__, __LINE__);
+ }
+
+ /*
+ * Spawn a grandchild that will immediately exit. If the kernel has bug
+ * 180385, the parent will see a kevent with both NOTE_CHILD and
+ * NOTE_EXIT. If that bug is fixed, it will see two separate kevents
+ * for those notes. Note that this triggers the conditions for
+ * detecting the bug quite reliably on a 1 CPU system (or if the test
+ * process is restricted to a single CPU), but may not trigger it on a
+ * multi-CPU system.
+ */
+ grandchild = fork();
+ if (grandchild == 0) { /* Grandchild */
+ if (sleep_time) sleep(sleep_time);
+ exit(1);
+ } else if (grandchild == -1) { /* Error */
+ err(1, "fork (grandchild) failed! (%s() at %s:%d)",
+ __func__, __FILE__, __LINE__);
+ } else { /* Child (Grandchild Parent) */
+ printf(" -- grandchild created (pid %d)\n", (int) grandchild);
+ }
+ if (sleep_time) sleep(sleep_time);
+ exit(0);
+ } else if (pid == -1) { /* Error */
+ err(1, "fork (child) failed! (%s() at %s:%d)",
+ __func__, __FILE__, __LINE__);
+ }
+
+ printf(" -- child created (pid %d)\n", (int) pid);
+
+ kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD | EV_ENABLE,
+ NOTE_TRACK | NOTE_EXEC | NOTE_EXIT | NOTE_FORK,
+ 0, NULL);
+
+ printf(" -- tracking child (pid %d)\n", (int) pid);
+
+ /* Now that we're tracking the child, tell it to proceed. */
+ result = write(pipe_fd[0], test_id, 1);
+ if (result != 1) {
+ err(1, "write to pipe in parent failed! (ret %zd) (%s() at %s:%d)",
+ result, __func__, __FILE__, __LINE__);
+ }
+
+ /*
+ * Several events should be received:
+ * - NOTE_FORK (from child)
+ * - NOTE_CHILD (from grandchild)
+ * - NOTE_EXIT (from grandchild)
+ * - NOTE_EXIT (from child)
+ *
+ * The NOTE_FORK and NOTE_EXIT from the child could be combined into a
+ * single event, but the NOTE_CHILD and NOTE_EXIT from the grandchild must
+ * not be combined.
+ *
+ * The loop continues until no events are received within a 5 second
+ * period, at which point it is assumed that no more will be coming. The
+ * loop is deliberately designed to attempt to get events even after all
+ * the expected ones are received in case some spurious events are
+ * generated as well as the expected ones.
+ */
+ {
+ int child_exit = 0;
+ int child_fork = 0;
+ int gchild_exit = 0;
+ int gchild_note = 0;
+ pid_t gchild_pid = -1;
+ int done = 0;
+
+ while (!done)
+ {
+ int handled = 0;
+ struct kevent *kevp;
+
+ kevp = kevent_get_timeout(kqfd, 5);
+ if (kevp == NULL) {
+ done = 1;
+ } else {
+ printf(" -- Received kevent: %s\n", kevent_to_str(kevp));
+
+ if ((kevp->fflags & NOTE_CHILD) && (kevp->fflags & NOTE_EXIT)) {
+ errx(1, "NOTE_CHILD and NOTE_EXIT in same kevent: %s", kevent_to_str(kevp));
+ }
+
+ if (kevp->fflags & NOTE_CHILD) {
+ if (kevp->data == pid) {
+ if (!gchild_note) {
+ ++gchild_note;
+ gchild_pid = kevp->ident;
+ ++handled;
+ } else {
+ errx(1, "Spurious NOTE_CHILD: %s", kevent_to_str(kevp));
+ }
+ }
+ }
+
+ if (kevp->fflags & NOTE_EXIT) {
+ if ((kevp->ident == pid) && (!child_exit)) {
+ ++child_exit;
+ ++handled;
+ } else if ((kevp->ident == gchild_pid) && (!gchild_exit)) {
+ ++gchild_exit;
+ ++handled;
+ } else {
+ errx(1, "Spurious NOTE_EXIT: %s", kevent_to_str(kevp));
+ }
+ }
+
+ if (kevp->fflags & NOTE_FORK) {
+ if ((kevp->ident == pid) && (!child_fork)) {
+ ++child_fork;
+ ++handled;
+ } else {
+ errx(1, "Spurious NOTE_FORK: %s", kevent_to_str(kevp));
+ }
+ }
+
+ if (!handled) {
+ errx(1, "Spurious kevent: %s", kevent_to_str(kevp));
+ }
+
+ free(kevp);
+ }
+ }
+
+ /* Make sure all expected events were received. */
+ if (child_exit && child_fork && gchild_exit && gchild_note) {
+ printf(" -- Received all expected events.\n");
+ } else {
+ errx(1, "Did not receive all expected events.");
+ }
+ }
+
+ success();
+}
+
#ifdef TODO
static void
event_trigger(void)
@@ -236,6 +402,8 @@ test_evfilt_proc()
signal(SIGUSR1, sig_handler);
add_and_delete();
+ proc_track(0); /* Run without sleeping before children exit. */
+ proc_track(1); /* Sleep a bit in the children before exiting. */
#if TODO
event_trigger();
diff --git a/usr.bin/ktrace/ktrace.1 b/usr.bin/ktrace/ktrace.1
index a5e930a..4a46052 100644
--- a/usr.bin/ktrace/ktrace.1
+++ b/usr.bin/ktrace/ktrace.1
@@ -28,7 +28,7 @@
.\" @(#)ktrace.1 8.1 (Berkeley) 6/6/93
.\" $FreeBSD$
.\"
-.Dd August 26, 2014
+.Dd March 31, 2016
.Dt KTRACE 1
.Os
.Sh NAME
@@ -175,7 +175,8 @@ on process 67
# disable tracing of all user-owned processes
.Dl $ ktrace -C
.Sh SEE ALSO
-.Xr kdump 1
+.Xr kdump 1 ,
+.Xr ktrace 2
.Sh HISTORY
The
.Nm
diff --git a/usr.bin/uuencode/uuencode.1 b/usr.bin/uuencode/uuencode.1
index 2c31bdc..9ce7e05 100644
--- a/usr.bin/uuencode/uuencode.1
+++ b/usr.bin/uuencode/uuencode.1
@@ -40,6 +40,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl m
+.Op Fl r
.Op Fl o Ar output_file
.Op Ar file
.Ar name
@@ -50,6 +51,7 @@
.Op Fl i
.Fl o Ar output_file
.Nm b64encode
+.Op Fl r
.Op Fl o Ar output_file
.Op Ar file
.Ar name
@@ -123,6 +125,8 @@ The following options are available for
Use the Base64 method of encoding, rather than the traditional
.Nm
algorithm.
+.It Fl r
+Produce raw output by excluding the initial and final framing lines.
.It Fl o Ar output_file
Output to
.Ar output_file
diff --git a/usr.bin/uuencode/uuencode.c b/usr.bin/uuencode/uuencode.c
index def8bcc..500dcd3 100644
--- a/usr.bin/uuencode/uuencode.c
+++ b/usr.bin/uuencode/uuencode.c
@@ -66,6 +66,7 @@ static void usage(void);
static FILE *output;
static int mode;
+static char raw = 0;
static char **av;
int
@@ -82,7 +83,7 @@ main(int argc, char *argv[])
if (strcmp(basename(argv[0]), "b64encode") == 0)
base64 = 1;
- while ((ch = getopt(argc, argv, "mo:")) != -1) {
+ while ((ch = getopt(argc, argv, "mo:r")) != -1) {
switch (ch) {
case 'm':
base64 = 1;
@@ -90,6 +91,9 @@ main(int argc, char *argv[])
case 'o':
outfile = optarg;
break;
+ case 'r':
+ raw = 1;
+ break;
case '?':
default:
usage();
@@ -152,7 +156,8 @@ base64_encode(void)
sequence = 0;
- fprintf(output, "begin-base64 %o %s\n", mode, *av);
+ if (!raw)
+ fprintf(output, "begin-base64 %o %s\n", mode, *av);
while ((n = fread(buf, 1, sizeof(buf), stdin))) {
++sequence;
rv = b64_ntop(buf, n, buf2, (sizeof(buf2) / sizeof(buf2[0])));
@@ -162,7 +167,8 @@ base64_encode(void)
}
if (sequence % GROUPS)
fprintf(output, "\n");
- fprintf(output, "====\n");
+ if (!raw)
+ fprintf(output, "====\n");
}
/*
@@ -175,7 +181,8 @@ encode(void)
register char *p;
char buf[80];
- (void)fprintf(output, "begin %o %s\n", mode, *av);
+ if (!raw)
+ (void)fprintf(output, "begin %o %s\n", mode, *av);
while ((n = fread(buf, 1, 45, stdin))) {
ch = ENC(n);
if (fputc(ch, output) == EOF)
@@ -209,7 +216,8 @@ encode(void)
}
if (ferror(stdin))
errx(1, "read error");
- (void)fprintf(output, "%c\nend\n", ENC('\0'));
+ if (!raw)
+ (void)fprintf(output, "%c\nend\n", ENC('\0'));
}
static void
OpenPOWER on IntegriCloud