diff options
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 |