From aae6b2073aeb7ba1118183bb52286e44dd04df28 Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Tue, 27 Jan 2015 01:39:42 +0000 Subject: [PATCH 01/14] Merge some cherry-picked fixes originating in OpenBSD Check whether the version field is available before looking at it. While we're at it, use ND_TCHECK(), rather than a hand-rolled check, to check whether we have the full fixed-length portion of the IPv4 header. commit c67afe913011138a2504ec4d3d423b48e73b12f3 Do more length checking. From OpenBSD. commit d7516761f9c4877bcb05bb6543be3543e165249 --- print-ip.c | 11 +++++++---- print-sl.c | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/print-ip.c b/print-ip.c index 362465e698de..830cfb324aa4 100644 --- a/print-ip.c +++ b/print-ip.c @@ -529,6 +529,7 @@ ip_print(netdissect_options *ndo, struct protoent *proto; ipds->ip = (const struct ip *)bp; + ND_TCHECK(ipds->ip->ip_vhl); if (IP_V(ipds->ip) != 4) { /* print version if != 4 */ ND_PRINT((ndo, "IP%u ", IP_V(ipds->ip))); if (IP_V(ipds->ip) == 6) @@ -537,10 +538,7 @@ ip_print(netdissect_options *ndo, else if (!ndo->ndo_eflag) ND_PRINT((ndo, "IP ")); - if ((u_char *)(ipds->ip + 1) > ndo->ndo_snapend) { - ND_PRINT((ndo, "%s", tstr)); - return; - } + ND_TCHECK(*ipds->ip); if (length < sizeof (struct ip)) { ND_PRINT((ndo, "truncated-ip %u", length)); return; @@ -669,6 +667,11 @@ ip_print(netdissect_options *ndo, ND_PRINT((ndo, " ip-proto-%d", ipds->ip->ip_p)); } } + return; + +trunc: + ND_PRINT((ndo, "%s", tstr)); + return; } void diff --git a/print-sl.c b/print-sl.c index a12a2bd6f35f..d08cd2459579 100644 --- a/print-sl.c +++ b/print-sl.c @@ -62,7 +62,7 @@ sl_if_print(netdissect_options *ndo, register u_int length = h->len; register const struct ip *ip; - if (caplen < SLIP_HDRLEN) { + if (caplen < SLIP_HDRLEN || length < SLIP_HDRLEN) { ND_PRINT((ndo, "%s", tstr)); return (caplen); } From e18480699e55169fe2161fe4e4455945eb1a0511 Mon Sep 17 00:00:00 2001 From: Gregory Neil Shapiro Date: Tue, 27 Jan 2015 04:06:47 +0000 Subject: [PATCH 02/14] Remove build specific details from sendmail.cf/submit.cf in support of https://wiki.freebsd.org/ReproducibleBuilds The contrib/sendmail change will be made in the upstream source for a future sendmail release. Reviewed by: des MFC after: 3 days --- contrib/sendmail/cf/m4/cfhead.m4 | 2 +- etc/sendmail/Makefile | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/contrib/sendmail/cf/m4/cfhead.m4 b/contrib/sendmail/cf/m4/cfhead.m4 index a244b9ab3c0c..51f676cb855f 100644 --- a/contrib/sendmail/cf/m4/cfhead.m4 +++ b/contrib/sendmail/cf/m4/cfhead.m4 @@ -20,7 +20,7 @@ ifdef(`__win32__', `dnl', `dnl ifdef(`TEMPFILE', `dnl', `define(`TEMPFILE', maketemp(/tmp/cfXXXXXX))dnl syscmd(sh _CF_DIR_`'sh/makeinfo.sh _CF_DIR_ > TEMPFILE)dnl -include(TEMPFILE)dnl +ifdef(`_NO_MAKEINFO_',, `include(TEMPFILE)')dnl syscmd(rm -f TEMPFILE)dnl')') ##### ###################################################################### diff --git a/etc/sendmail/Makefile b/etc/sendmail/Makefile index b79e722a4bf4..719f351d1f97 100644 --- a/etc/sendmail/Makefile +++ b/etc/sendmail/Makefile @@ -17,7 +17,8 @@ M4FILES!= find ${SENDMAIL_CF_DIR} -type f -name '*.m4' -print .mc.cf: ${M4FILES} ${RM} ${.TARGET} - ${M4} -D_CF_DIR_=${SENDMAIL_CF_DIR}/ ${SENDMAIL_M4_FLAGS} \ + ${M4} -D_CF_DIR_=${SENDMAIL_CF_DIR}/ -D_NO_MAKEINFO_ \ + ${SENDMAIL_M4_FLAGS} \ ${SENDMAIL_CF_DIR}/m4/cf.m4 ${.IMPSRC} > ${.TARGET} ${CHMOD} ${ROMODE} ${.TARGET} From 6b0e9233e41f43f8a366193ec76c90bc734ee41f Mon Sep 17 00:00:00 2001 From: Bryan Venteicher Date: Tue, 27 Jan 2015 05:34:46 +0000 Subject: [PATCH 03/14] Rework vtblk dump handling of in flight requests Previously, the driver resets the device and abandon the requests that are caught in flight when the dump was initiated. This was problematic if the system is resumed after the dump is completed. While that is probably not the typical action, it is simple to rework the driver to very likely have the device usable after the dump without making it more likely for the dump to fail. The in flight requests are simply queued for completion once the dump is finished. Requested by: markj MFC after: 1 month --- sys/dev/virtio/block/virtio_blk.c | 72 +++++++++++++------------------ 1 file changed, 31 insertions(+), 41 deletions(-) diff --git a/sys/dev/virtio/block/virtio_blk.c b/sys/dev/virtio/block/virtio_blk.c index a65e23d37b4c..cfd1148ba667 100644 --- a/sys/dev/virtio/block/virtio_blk.c +++ b/sys/dev/virtio/block/virtio_blk.c @@ -76,9 +76,8 @@ struct vtblk_softc { #define VTBLK_FLAG_READONLY 0x0002 #define VTBLK_FLAG_DETACH 0x0004 #define VTBLK_FLAG_SUSPEND 0x0008 -#define VTBLK_FLAG_DUMPING 0x0010 -#define VTBLK_FLAG_BARRIER 0x0020 -#define VTBLK_FLAG_WC_CONFIG 0x0040 +#define VTBLK_FLAG_BARRIER 0x0010 +#define VTBLK_FLAG_WC_CONFIG 0x0020 struct virtqueue *vtblk_vq; struct sglist *vtblk_sglist; @@ -95,6 +94,7 @@ struct vtblk_softc { int vtblk_request_count; enum vtblk_cache_mode vtblk_write_cache; + struct bio_queue vtblk_dump_queue; struct vtblk_request vtblk_dump_request; }; @@ -162,7 +162,7 @@ static void vtblk_queue_completed(struct vtblk_softc *, struct bio_queue *); static void vtblk_done_completed(struct vtblk_softc *, struct bio_queue *); -static void vtblk_drain_vq(struct vtblk_softc *, int); +static void vtblk_drain_vq(struct vtblk_softc *); static void vtblk_drain(struct vtblk_softc *); static void vtblk_startio(struct vtblk_softc *); @@ -177,9 +177,10 @@ static int vtblk_quiesce(struct vtblk_softc *); static void vtblk_vq_intr(void *); static void vtblk_stop(struct vtblk_softc *); -static void vtblk_dump_prepare(struct vtblk_softc *); +static void vtblk_dump_quiesce(struct vtblk_softc *); static int vtblk_dump_write(struct vtblk_softc *, void *, off_t, size_t); static int vtblk_dump_flush(struct vtblk_softc *); +static void vtblk_dump_complete(struct vtblk_softc *); static void vtblk_set_write_cache(struct vtblk_softc *, int); static int vtblk_write_cache_enabled(struct vtblk_softc *sc, @@ -302,6 +303,7 @@ vtblk_attach(device_t dev) sc->vtblk_dev = dev; VTBLK_LOCK_INIT(sc, device_get_nameunit(dev)); bioq_init(&sc->vtblk_bioq); + TAILQ_INIT(&sc->vtblk_dump_queue); TAILQ_INIT(&sc->vtblk_req_free); TAILQ_INIT(&sc->vtblk_req_ready); @@ -506,25 +508,19 @@ vtblk_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset, int error; dp = arg; + error = 0; if ((sc = dp->d_drv1) == NULL) return (ENXIO); VTBLK_LOCK(sc); - if ((sc->vtblk_flags & VTBLK_FLAG_DUMPING) == 0) { - vtblk_dump_prepare(sc); - sc->vtblk_flags |= VTBLK_FLAG_DUMPING; - } + vtblk_dump_quiesce(sc); if (length > 0) error = vtblk_dump_write(sc, virtual, offset, length); - else if (virtual == NULL && offset == 0) - error = vtblk_dump_flush(sc); - else { - error = EINVAL; - sc->vtblk_flags &= ~VTBLK_FLAG_DUMPING; - } + if (error || (virtual == NULL && offset == 0)) + vtblk_dump_complete(sc); VTBLK_UNLOCK(sc); @@ -996,7 +992,7 @@ vtblk_done_completed(struct vtblk_softc *sc, struct bio_queue *queue) } static void -vtblk_drain_vq(struct vtblk_softc *sc, int skip_done) +vtblk_drain_vq(struct vtblk_softc *sc) { struct virtqueue *vq; struct vtblk_request *req; @@ -1006,9 +1002,7 @@ vtblk_drain_vq(struct vtblk_softc *sc, int skip_done) last = 0; while ((req = virtqueue_drain(vq, &last)) != NULL) { - if (!skip_done) - vtblk_bio_done(sc, req->vbr_bp, ENXIO); - + vtblk_bio_done(sc, req->vbr_bp, ENXIO); vtblk_request_enqueue(sc, req); } @@ -1031,7 +1025,7 @@ vtblk_drain(struct vtblk_softc *sc) vtblk_queue_completed(sc, &queue); vtblk_done_completed(sc, &queue); - vtblk_drain_vq(sc, 0); + vtblk_drain_vq(sc); } while ((req = vtblk_request_next_ready(sc)) != NULL) { @@ -1256,31 +1250,16 @@ vtblk_stop(struct vtblk_softc *sc) } static void -vtblk_dump_prepare(struct vtblk_softc *sc) +vtblk_dump_quiesce(struct vtblk_softc *sc) { - device_t dev; - struct virtqueue *vq; - - dev = sc->vtblk_dev; - vq = sc->vtblk_vq; - - vtblk_stop(sc); /* - * Drain all requests caught in-flight in the virtqueue, - * skipping biodone(). When dumping, only one request is - * outstanding at a time, and we just poll the virtqueue - * for the response. + * Spin here until all the requests in-flight at the time of the + * dump are completed and queued. The queued requests will be + * biodone'd once the dump is finished. */ - vtblk_drain_vq(sc, 1); - - if (virtio_reinit(dev, sc->vtblk_features) != 0) { - panic("%s: cannot reinit VirtIO block device during dump", - device_get_nameunit(dev)); - } - - virtqueue_disable_intr(vq); - virtio_reinit_complete(dev); + while (!virtqueue_empty(sc->vtblk_vq)) + vtblk_queue_completed(sc, &sc->vtblk_dump_queue); } static int @@ -1326,6 +1305,17 @@ vtblk_dump_flush(struct vtblk_softc *sc) return (vtblk_poll_request(sc, req)); } +static void +vtblk_dump_complete(struct vtblk_softc *sc) +{ + + vtblk_dump_flush(sc); + + VTBLK_UNLOCK(sc); + vtblk_done_completed(sc, &sc->vtblk_dump_queue); + VTBLK_LOCK(sc); +} + static void vtblk_set_write_cache(struct vtblk_softc *sc, int wc) { From c7be335e3ec5f6d3be03960223e312ec5171a097 Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Tue, 27 Jan 2015 07:20:00 +0000 Subject: [PATCH 04/14] Fix bug in mapppings of multiple pages exposed by updates to the VSCSI support in QEMU. Each page of a many page mapping was getting mapped to the same physical address, which is not the desired behavior. MFC after: 1 week --- sys/powerpc/pseries/plpar_iommu.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sys/powerpc/pseries/plpar_iommu.c b/sys/powerpc/pseries/plpar_iommu.c index 8db374c7bd6c..5edbf6d50474 100644 --- a/sys/powerpc/pseries/plpar_iommu.c +++ b/sys/powerpc/pseries/plpar_iommu.c @@ -191,13 +191,13 @@ phyp_iommu_map(device_t dev, bus_dma_segment_t *segs, int *nsegs, tce = trunc_page(segs[i].ds_addr); tce |= 0x3; /* read/write */ - if (papr_supports_stuff_tce) { - error = phyp_hcall(H_STUFF_TCE, window->map->iobn, - alloced, tce, allocsize/PAGE_SIZE); - } else { - for (j = 0; j < allocsize; j += PAGE_SIZE) - error = phyp_hcall(H_PUT_TCE, window->map->iobn, - alloced + j, tce + j); + for (j = 0; j < allocsize; j += PAGE_SIZE) { + error = phyp_hcall(H_PUT_TCE, window->map->iobn, + alloced + j, tce + j); + if (error < 0) { + panic("IOMMU mapping error: %d\n", error); + return (ENOMEM); + } } segs[i].ds_addr = alloced + (segs[i].ds_addr & PAGE_MASK); From 3834f9235958b9cfdc886ddd5076db4d1256eb2e Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 27 Jan 2015 09:48:02 +0000 Subject: [PATCH 05/14] Rewrite pmap_enter(9) man page. In collaboration with: alc Differential Revision: https://reviews.freebsd.org/D1531 Sponsored by: The FreeBSD Foundation and EMC / Isilon Storage Division MFC after: 1 week --- share/man/man9/pmap_enter.9 | 140 ++++++++++++++++++++++++++++++------ 1 file changed, 118 insertions(+), 22 deletions(-) diff --git a/share/man/man9/pmap_enter.9 b/share/man/man9/pmap_enter.9 index 69e0650c6ef6..85ab4e8499bc 100644 --- a/share/man/man9/pmap_enter.9 +++ b/share/man/man9/pmap_enter.9 @@ -1,5 +1,6 @@ .\" .\" Copyright (c) 2003 Bruce M Simpson +.\" Copyright (c) 2014 The FreeBSD Foundation .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -25,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 21, 2003 +.Dd January 27, 2015 .Dt PMAP_ENTER 9 .Os .Sh NAME @@ -35,34 +36,129 @@ .In sys/param.h .In vm/vm.h .In vm/pmap.h -.Ft void +.Ft int .Fo pmap_enter -.Fa "pmap_t pmap" "vm_offset_t va" "vm_page_t p" "vm_prot_t prot" -.Fa "boolean_t wired" +.Fa "pmap_t pmap" "vm_offset_t va" "vm_page_t m" "vm_prot_t prot" +.Fa "u_int flags" "int8_t psind" .Fc .Sh DESCRIPTION The .Fn pmap_enter -function inserts the given physical page -.Fa p , -into the physical map -.Fa pmap , -at the virtual address -.Fa va , +function creates a mapping in the physical map +.Fa pmap +from the virtual address +.Fa va +to the physical page +.Fa m with the protection .Fa prot . -If -.Fa wired -is -.Dv TRUE , -then increment the wired count for the page as soon as the mapping -is inserted into -.Fa pmap . -.Sh IMPLEMENTATION NOTES -This routine MAY NOT lazy-evaluate the entry; it is required by -specification to make the requested entry at the time it is called. +Any previous mapping at the virtual address +.Fa va +is destroyed. +.Pp +The +.Fa flags +argument may have the following values: +.Bl -tag -width ".Dv PMAP_ENTER_NOSLEEP" +.It Dv VM_PROT_READ +A read access to the given virtual address triggered the call. +.It Dv VM_PROT_WRITE +A write access to the given virtual address triggered the call. +.It Dv VM_PROT_EXECUTE +An execute access to the given virtual address triggered the call. +.It Dv PMAP_ENTER_WIRED +The mapping should be marked as wired. +.It Dv PMAP_ENTER_NOSLEEP +This function may not sleep during creation of the mapping. +If the mapping cannot be created without sleeping, an appropriate +Mach VM error is returned. +.El +If the +.Dv PMAP_ENTER_NOSLEEP +flag is not specified, this function must create the requested mapping +before returning. +It may not fail. +In order to create the requested mapping, this function may destroy +any non-wired mapping in any pmap. +.Pp +The +.Fa psind +parameter specifies the page size that should be used by the mapping. +The supported page sizes are described by the global array +.Dv pagesizes[] . +The desired page size is specified by passing the index of the array +element that equals the desired page size. +.Pp +When the +.Fn pmap_enter +function destroys or updates a managed mapping, including an existing +mapping at virtual address +.Fa va , +it updates the +.Ft vm_page +structure corresponding to the previously mapped physical page. +If the physical page was accessed through the managed mapping, +then the +.Ft vm_page +structure's +.Dv PGA_REFERENCED +aflag is set. +If the physical page was modified through the managed mapping, then the +.Fn vm_page_dirty +function is called on the +.Ft vm_page +structure. +.Pp +The +.Dv PGA_WRITEABLE +aflag must be set for the page +.Fa m +if the new mapping is managed and writeable. +It is advised to clear +.Dv PGA_WRITEABLE +for destroyed mappings if the implementation can ensure +that no other writeable managed mappings for the previously +mapped pages exist. +.Pp +If the page +.Fa m +is managed, the page must be busied by the caller +or the owning object must be locked. +In the later case, the +.Dv PMAP_ENTER_NOSLEEP +must be specified by the caller. +.Pp +The +.Fn pmap_enter +function must handle the multiprocessor TLB consistency for the +given address. +.Sh NOTES +On amd64, arm and i386 architectures the existing implementation +of the +.Nm +function is incomplete, only value 0 for +.Fa psind +is supported. +Other supported architectures have +.Dv pagesizes[] +array of size 1. +.Sh RETURN VALUES +If successful, the +.Fn pmap_enter +function returns +.Er KERN_SUCCESS . +If the +.Dv PMAP_ENTER_NOSLEEP +flag was specified and the resources required for the mapping cannot +be acquired without sleeping, +.Dv KERN_RESOURCE_SHORTAGE +is returned. .Sh SEE ALSO .Xr pmap 9 .Sh AUTHORS -This manual page was written by -.An Bruce M Simpson Aq Mt bms@spc.org . +This manual page was first written by +.An Bruce M Simpson Aq Mt bms@spc.org +and then rewritten by +.An Alan Cox Aq Mt alc@FreeBSD.org +and +.An Konstantin Belousov Aq Mt kib@FreeBSD.org . From cda374fe00a687b28ce979ad4aa8c59ae8c06c10 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 27 Jan 2015 10:32:49 +0000 Subject: [PATCH 06/14] The sys_quotactl() contract demands that the mount point is vfs_unbusy()ed when the cmd is Q_QUOTAON, regardless of other input parameters or error return. Submitted by: Conrad Meyer Sponsored by: EMC / Isilon Storage Division Differential Revision: https://reviews.freebsd.org/D1684 Tested by: pho MFC after: 1 week --- sys/ufs/ufs/ufs_quota.c | 8 ++++++-- sys/ufs/ufs/ufs_vfsops.c | 10 +++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c index 132fab2eb591..4fbb8a18032f 100644 --- a/sys/ufs/ufs/ufs_quota.c +++ b/sys/ufs/ufs/ufs_quota.c @@ -495,11 +495,15 @@ quotaon(struct thread *td, struct mount *mp, int type, void *fname) struct nameidata nd; error = priv_check(td, PRIV_UFS_QUOTAON); - if (error) + if (error != 0) { + vfs_unbusy(mp); return (error); + } - if (mp->mnt_flag & MNT_RDONLY) + if ((mp->mnt_flag & MNT_RDONLY) != 0) { + vfs_unbusy(mp); return (EROFS); + } ump = VFSTOUFS(mp); dq = NODQUOT; diff --git a/sys/ufs/ufs/ufs_vfsops.c b/sys/ufs/ufs/ufs_vfsops.c index 74a863a0bc8f..5bb73ea0c81d 100644 --- a/sys/ufs/ufs/ufs_vfsops.c +++ b/sys/ufs/ufs/ufs_vfsops.c @@ -92,6 +92,9 @@ ufs_quotactl(mp, cmds, id, arg) void *arg; { #ifndef QUOTA + if ((cmds >> SUBCMDSHIFT) == Q_QUOTAON) + vfs_unbusy(mp); + return (EOPNOTSUPP); #else struct thread *td; @@ -112,11 +115,16 @@ ufs_quotactl(mp, cmds, id, arg) break; default: + if (cmd == Q_QUOTAON) + vfs_unbusy(mp); return (EINVAL); } } - if ((u_int)type >= MAXQUOTAS) + if ((u_int)type >= MAXQUOTAS) { + if (cmd == Q_QUOTAON) + vfs_unbusy(mp); return (EINVAL); + } switch (cmd) { case Q_QUOTAON: From 6dfa4578d6458c9531a1b1d9a17563f78751ec38 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Tue, 27 Jan 2015 15:28:46 +0000 Subject: [PATCH 07/14] vt(4): Use power_{suspend,resume} event handlers to implement suspend/resume The goal is to avoid that the vt(4) resume happens before the video display is resumed. The original patch was provided by Andriy Gapon. This new patch registers the handlers in vt_upgrade(). This is done once, thanks to the VDF_ASYNC flag. I abused this flag because it was already abused by the keyboard allocation. The event handlers then call the backend if it provides callbacks for suspend/resume. Differential Revision: https://reviews.freebsd.org/D1004 On behalf of: dumbbell MFC after: 2 weeks --- sys/dev/fb/fbd.c | 18 -------------- sys/dev/vt/hw/fb/vt_fb.c | 10 ++++---- sys/dev/vt/hw/fb/vt_fb.h | 4 ++-- sys/dev/vt/vt.h | 11 +++++++-- sys/dev/vt/vt_core.c | 52 +++++++++++++++++++++++++++++++++------- 5 files changed, 61 insertions(+), 34 deletions(-) diff --git a/sys/dev/fb/fbd.c b/sys/dev/fb/fbd.c index ff2488d537c6..6bd5766543b5 100644 --- a/sys/dev/fb/fbd.c +++ b/sys/dev/fb/fbd.c @@ -332,22 +332,6 @@ fbd_detach(device_t dev) return (err); } -static int -fbd_suspend(device_t dev) -{ - - vt_fb_suspend(); - return (bus_generic_suspend(dev)); -} - -static int -fbd_resume(device_t dev) -{ - - vt_fb_resume(); - return (bus_generic_resume(dev)); -} - static device_method_t fbd_methods[] = { /* Device interface */ DEVMETHOD(device_probe, fbd_probe), @@ -355,8 +339,6 @@ static device_method_t fbd_methods[] = { DEVMETHOD(device_detach, fbd_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, fbd_suspend), - DEVMETHOD(device_resume, fbd_resume), { 0, 0 } }; diff --git a/sys/dev/vt/hw/fb/vt_fb.c b/sys/dev/vt/hw/fb/vt_fb.c index 044b64161099..5a0fe4f24854 100644 --- a/sys/dev/vt/hw/fb/vt_fb.c +++ b/sys/dev/vt/hw/fb/vt_fb.c @@ -53,6 +53,8 @@ static struct vt_driver vt_fb_driver = { .vd_priority = VD_PRIORITY_GENERIC+10, .vd_fb_ioctl = vt_fb_ioctl, .vd_fb_mmap = vt_fb_mmap, + .vd_suspend = vt_fb_suspend, + .vd_resume = vt_fb_resume, }; VT_DRIVER_DECLARE(vt_fb, vt_fb_driver); @@ -450,15 +452,15 @@ vt_fb_attach(struct fb_info *info) } void -vt_fb_resume(void) +vt_fb_suspend(struct vt_device *vd) { - vt_resume(); + vt_suspend(vd); } void -vt_fb_suspend(void) +vt_fb_resume(struct vt_device *vd) { - vt_suspend(); + vt_resume(vd); } diff --git a/sys/dev/vt/hw/fb/vt_fb.h b/sys/dev/vt/hw/fb/vt_fb.h index 43ce2b7b4c64..ac18cff49e36 100644 --- a/sys/dev/vt/hw/fb/vt_fb.h +++ b/sys/dev/vt/hw/fb/vt_fb.h @@ -33,8 +33,8 @@ #define _DEV_VT_HW_FB_VT_FB_H_ /* Generic framebuffer interface call vt_fb_attach to init VT(9) */ int vt_fb_attach(struct fb_info *info); -void vt_fb_resume(void); -void vt_fb_suspend(void); +void vt_fb_resume(struct vt_device *vd); +void vt_fb_suspend(struct vt_device *vd); vd_init_t vt_fb_init; vd_blank_t vt_fb_blank; diff --git a/sys/dev/vt/vt.h b/sys/dev/vt/vt.h index 67fcf1e06491..0ad8ab5dffda 100644 --- a/sys/dev/vt/vt.h +++ b/sys/dev/vt/vt.h @@ -90,8 +90,6 @@ SYSCTL_INT(_kern_vt, OID_AUTO, _name, CTLFLAG_RWTUN, &vt_##_name, _default,\ struct vt_driver; void vt_allocate(struct vt_driver *, void *); -void vt_resume(void); -void vt_suspend(void); typedef unsigned int vt_axis_t; @@ -162,6 +160,9 @@ struct vt_device { #define VD_PASTEBUFSZ(vd) ((vd)->vd_pastebuf.vpb_bufsz) #define VD_PASTEBUFLEN(vd) ((vd)->vd_pastebuf.vpb_len) +void vt_resume(struct vt_device *vd); +void vt_suspend(struct vt_device *vd); + /* * Per-window terminal screen buffer. * @@ -314,6 +315,8 @@ typedef int vd_fb_mmap_t(struct vt_device *, vm_ooffset_t, vm_paddr_t *, int, typedef void vd_drawrect_t(struct vt_device *, int, int, int, int, int, term_color_t); typedef void vd_setpixel_t(struct vt_device *, int, int, term_color_t); +typedef void vd_suspend_t(struct vt_device *); +typedef void vd_resume_t(struct vt_device *); struct vt_driver { char vd_name[16]; @@ -337,6 +340,10 @@ struct vt_driver { /* Update display setting on vt switch. */ vd_postswitch_t *vd_postswitch; + /* Suspend/resume handlers. */ + vd_suspend_t *vd_suspend; + vd_resume_t *vd_resume; + /* Priority to know which one can override */ int vd_priority; #define VD_PRIORITY_DUMB 10 diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c index bf0ae1a8f355..d70073090a93 100644 --- a/sys/dev/vt/vt_core.c +++ b/sys/dev/vt/vt_core.c @@ -167,6 +167,8 @@ static void vt_update_static(void *); #ifndef SC_NO_CUTPASTE static void vt_mouse_paste(void); #endif +static void vt_suspend_handler(void *priv); +static void vt_resume_handler(void *priv); SET_DECLARE(vt_drv_set, struct vt_driver); @@ -2552,6 +2554,12 @@ vt_upgrade(struct vt_device *vd) vd->vd_flags |= VDF_ASYNC; callout_reset(&vd->vd_timer, hz / VT_TIMERFREQ, vt_timer, vd); vd->vd_timer_armed = 1; + + /* Register suspend/resume handlers. */ + EVENTHANDLER_REGISTER(power_suspend, vt_suspend_handler, vd, + EVENTHANDLER_PRI_ANY); + EVENTHANDLER_REGISTER(power_resume, vt_resume_handler, vd, + EVENTHANDLER_PRI_ANY); } VT_UNLOCK(vd); @@ -2655,26 +2663,54 @@ vt_allocate(struct vt_driver *drv, void *softc) termcn_cnregister(vd->vd_windows[VT_CONSWINDOW]->vw_terminal); } -void -vt_suspend() +static void +vt_suspend_handler(void *priv) { + struct vt_device *vd; + + vd = priv; + if (vd->vd_driver != NULL && vd->vd_driver->vd_suspend != NULL) + vd->vd_driver->vd_suspend(vd); +} + +static void +vt_resume_handler(void *priv) +{ + struct vt_device *vd; + + vd = priv; + if (vd->vd_driver != NULL && vd->vd_driver->vd_resume != NULL) + vd->vd_driver->vd_resume(vd); +} + +void +vt_suspend(struct vt_device *vd) +{ + int error; if (vt_suspendswitch == 0) return; /* Save current window. */ - main_vd->vd_savedwindow = main_vd->vd_curwindow; + vd->vd_savedwindow = vd->vd_curwindow; /* Ask holding process to free window and switch to console window */ - vt_proc_window_switch(main_vd->vd_windows[VT_CONSWINDOW]); + vt_proc_window_switch(vd->vd_windows[VT_CONSWINDOW]); + + /* Wait for the window switch to complete. */ + error = 0; + VT_LOCK(vd); + while (vd->vd_curwindow != vd->vd_windows[VT_CONSWINDOW] && error == 0) + error = cv_wait_sig(&vd->vd_winswitch, &vd->vd_lock); + VT_UNLOCK(vd); } void -vt_resume() +vt_resume(struct vt_device *vd) { if (vt_suspendswitch == 0) return; /* Switch back to saved window */ - if (main_vd->vd_savedwindow != NULL) - vt_proc_window_switch(main_vd->vd_savedwindow); - main_vd->vd_savedwindow = NULL; + if (vd->vd_savedwindow != NULL) + vt_proc_window_switch(vd->vd_savedwindow); + vd->vd_savedwindow = NULL; } From 85f95fffd78f81cbbb8a948a3789e94f275bd1e2 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Tue, 27 Jan 2015 17:33:18 +0000 Subject: [PATCH 08/14] hook userland threads suspend + resume into acpi suspend code Also, split power_suspend into power_suspend and power_suspend_early. power_suspend_early is called before the userland is frozen. power_suspend is called after the userland is frozen. Currently only VT switching is hooked to power_suspend_early. This is needed because switching away from X server requires its cooperation, so obviously X server must not be frozen when that happens. Freezing userland during ACPI suspend is useful because not all drivers correctly handle suspension concurrent with other activity. This is especially applicable to drivers ported from other operating systems that suspend all software activity between placing drivers and hardware into suspended state. In particular drm2/radeon (radeonkms) depends on the described procedure. The driver does not have any internal synchronization between suspension activities and processing of userland requests. Many thanks to kib for the code that allows to freeze and thaw all userland threads. Note that ideally we also need to park / inhibit (non-special) kernel threads as well to ensure that they do not call into drivers. MFC after: 17 days --- sys/dev/acpica/acpi.c | 4 ++++ sys/dev/syscons/syscons.c | 2 +- sys/dev/vt/vt_core.c | 4 ++-- sys/sys/eventhandler.h | 1 + 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index 0e8998b09496..a4732c47a647 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -2749,6 +2749,8 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state) return_ACPI_STATUS (AE_OK); } + EVENTHANDLER_INVOKE(power_suspend_early); + stop_all_proc(); EVENTHANDLER_INVOKE(power_suspend); if (smp_started) { @@ -2892,6 +2894,8 @@ backout: thread_unlock(curthread); } + resume_all_proc(); + EVENTHANDLER_INVOKE(power_resume); /* Allow another sleep request after a while. */ diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index 6a19523ee2ea..2ab28895a1f4 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -549,7 +549,7 @@ sc_attach_unit(int unit, int flags) /* Register suspend/resume/shutdown callbacks for the kernel console. */ if (sc_console_unit == unit) { - EVENTHANDLER_REGISTER(power_suspend, scsuspend, NULL, + EVENTHANDLER_REGISTER(power_suspend_early, scsuspend, NULL, EVENTHANDLER_PRI_ANY); EVENTHANDLER_REGISTER(power_resume, scresume, NULL, EVENTHANDLER_PRI_ANY); diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c index d70073090a93..47b3c8a67d93 100644 --- a/sys/dev/vt/vt_core.c +++ b/sys/dev/vt/vt_core.c @@ -2556,8 +2556,8 @@ vt_upgrade(struct vt_device *vd) vd->vd_timer_armed = 1; /* Register suspend/resume handlers. */ - EVENTHANDLER_REGISTER(power_suspend, vt_suspend_handler, vd, - EVENTHANDLER_PRI_ANY); + EVENTHANDLER_REGISTER(power_suspend_early, vt_suspend_handler, + vd, EVENTHANDLER_PRI_ANY); EVENTHANDLER_REGISTER(power_resume, vt_resume_handler, vd, EVENTHANDLER_PRI_ANY); } diff --git a/sys/sys/eventhandler.h b/sys/sys/eventhandler.h index 4e77d5b63b93..d82ece71eda9 100644 --- a/sys/sys/eventhandler.h +++ b/sys/sys/eventhandler.h @@ -182,6 +182,7 @@ EVENTHANDLER_DECLARE(shutdown_final, shutdown_fn); typedef void (*power_change_fn)(void *); EVENTHANDLER_DECLARE(power_resume, power_change_fn); EVENTHANDLER_DECLARE(power_suspend, power_change_fn); +EVENTHANDLER_DECLARE(power_suspend_early, power_change_fn); /* Low memory event */ typedef void (*vm_lowmem_handler_t)(void *, int); From b489a49fc0b64eab08d5af8f6f173bf47fe8e1fc Mon Sep 17 00:00:00 2001 From: "Andrey V. Elsukov" Date: Tue, 27 Jan 2015 17:46:55 +0000 Subject: [PATCH 09/14] key_spdget uses key_setdumpsp() without SPTREE_RLOCK held (it uses referenced pointer to sp). Remove SPTREE_RLOCK_ASSERT from key_setdumpsp() to fix wrong assertion. Reported by: Emeric POUPON Obtained from: Yandex LLC Sponsored by: Yandex LLC --- sys/netipsec/key.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c index a4e8a25a5a8a..c38dae8ff84f 100644 --- a/sys/netipsec/key.c +++ b/sys/netipsec/key.c @@ -2421,8 +2421,6 @@ key_setdumpsp(struct secpolicy *sp, u_int8_t type, u_int32_t seq, struct mbuf *result = NULL, *m; struct seclifetime lt; - SPTREE_RLOCK_ASSERT(); - m = key_setsadbmsg(type, 0, SADB_SATYPE_UNSPEC, seq, pid, sp->refcnt); if (!m) goto fail; From 8da97f00573902efb70b1732b550edacf673fef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20E=C3=9Fer?= Date: Tue, 27 Jan 2015 18:04:41 +0000 Subject: [PATCH 10/14] Fix overflow check for multiplication: - Add special test to detect the case of -1 * INTMAX_MIN - Protect against elimination of the test division by the optimizer Garrett Cooper noticed that the overflow checks were incomplete, and Bruce Evans suggested the use of the "volatile" qualifier to counter the effect of the undefined behaviour, when the prior multiplication caused overflow, and he also suggested improvements to the comments. Reviewed by: bde MFC after: 1 week --- bin/expr/expr.y | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/bin/expr/expr.y b/bin/expr/expr.y index 1856ec84d0f7..0ddf3990d2a8 100644 --- a/bin/expr/expr.y +++ b/bin/expr/expr.y @@ -444,14 +444,26 @@ op_minus(struct val *a, struct val *b) return (r); } +/* + * We depend on undefined behaviour giving a result (in r). + * To test this result, pass it as volatile. This prevents + * optimizing away of the test based on the undefined behaviour. + */ void -assert_times(intmax_t a, intmax_t b, intmax_t r) +assert_times(intmax_t a, intmax_t b, volatile intmax_t r) { /* - * if first operand is 0, no overflow is possible, - * else result of division test must match second operand + * If the first operand is 0, no overflow is possible, + * else the result of the division test must match the + * second operand. + * + * Be careful to avoid overflow in the overflow test, as + * in assert_div(). Overflow in division would kill us + * with a SIGFPE before getting the test wrong. In old + * buggy versions, optimization used to give a null test + * instead of a SIGFPE. */ - if (a != 0 && r / a != b) + if ((a == -1 && b == INTMAX_MIN) || (a != 0 && r / a != b)) errx(ERR_EXIT, "overflow"); } From da8e209f333c58c144c6593d50d71de0b025364a Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Tue, 27 Jan 2015 18:27:07 +0000 Subject: [PATCH 11/14] Fix sysctl name. MFC after: 1 month Sponsored by: The FreeBSD Foundation --- sbin/geom/class/mountver/gmountver.8 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbin/geom/class/mountver/gmountver.8 b/sbin/geom/class/mountver/gmountver.8 index c9a9c0ac8313..44736d5d90e4 100644 --- a/sbin/geom/class/mountver/gmountver.8 +++ b/sbin/geom/class/mountver/gmountver.8 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 14, 2010 +.Dd January 27, 2015 .Dt GMOUNTVER 8 .Os .Sh NAME @@ -110,7 +110,7 @@ GEOM class. This can be set to a number between 0 and 3 inclusive. If set to 0 minimal debug information is printed, and if set to 3 the maximum amount of debug information is printed. -.It Va kern.geom.mountver.check.check_ident : No 1 +.It Va kern.geom.mountver.check_ident : No 1 This can be set to 0 or 1. If set to 0, .Nm From cb8266e79741e2e73ddb968761e192f8c9e02508 Mon Sep 17 00:00:00 2001 From: Randall Stewart Date: Tue, 27 Jan 2015 18:56:22 +0000 Subject: [PATCH 12/14] Fix yet another coverty warning (missing io is NULL check) and in examining that warning I see yet another issue where we should be pclosing the io in the event of the error and its a command (not fclose only). --- usr.sbin/pmcstudy/pmcstudy.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/usr.sbin/pmcstudy/pmcstudy.c b/usr.sbin/pmcstudy/pmcstudy.c index a99d59a8cb33..a7ec3719a0b4 100644 --- a/usr.sbin/pmcstudy/pmcstudy.c +++ b/usr.sbin/pmcstudy/pmcstudy.c @@ -1796,6 +1796,10 @@ process_file(char *filename) if (filename == NULL) { io = my_popen(command, "r", &pid_of_command); + if (io == NULL) { + printf("Can't popen the command %s\n", command); + return; + } } else { io = fopen(filename, "r"); if (io == NULL) { @@ -1808,8 +1812,10 @@ process_file(char *filename) if (cnts == NULL) { /* Nothing we can do */ printf("Nothing to do -- no counters built\n"); - if (io) { - fclose(io); + if (filename) { + fclose(io); + } else { + my_pclose(io, pid_of_command); } return; } From c7d7e597b410b3802ed7480d0db628e8449f29cc Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Tue, 27 Jan 2015 18:56:46 +0000 Subject: [PATCH 13/14] Constify a struct savexmm pointer in pt_ucontext_to_fpreg(), to silence a -Wcast-qual warning from clang 3.6.0. --- lib/libthread_db/arch/i386/libpthread_md.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libthread_db/arch/i386/libpthread_md.c b/lib/libthread_db/arch/i386/libpthread_md.c index d41865f521e3..784c245d93eb 100644 --- a/lib/libthread_db/arch/i386/libpthread_md.c +++ b/lib/libthread_db/arch/i386/libpthread_md.c @@ -72,7 +72,7 @@ pt_ucontext_to_fpreg(const ucontext_t *uc, struct fpreg *r) memcpy(r, &uc->uc_mcontext.mc_fpstate, sizeof(struct save87)); else { int i; - struct savexmm *sx = (struct savexmm *)&uc->uc_mcontext.mc_fpstate; + const struct savexmm *sx = (const struct savexmm *)&uc->uc_mcontext.mc_fpstate; memcpy(&r->fpr_env, &sx->sv_env, sizeof(r->fpr_env)); for (i = 0; i < 8; ++i) memcpy(&r->fpr_acc[i], &sx->sv_fp[i].fp_acc, 10); From fc04dce05911dc5a6ababdcbc1ce0eeb726705a1 Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Tue, 27 Jan 2015 18:58:24 +0000 Subject: [PATCH 14/14] Fix resource leak and dereference after NULL. process.c: Protect access against NULL. main.c: Prevent outfile overwrite resource leak. CID: 271181 CID: 1006930 Obtained from: NetBSD MFC after: 3 days --- usr.bin/sed/main.c | 2 ++ usr.bin/sed/process.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/usr.bin/sed/main.c b/usr.bin/sed/main.c index 029a79fdeec6..dafb0bd845ef 100644 --- a/usr.bin/sed/main.c +++ b/usr.bin/sed/main.c @@ -411,6 +411,8 @@ mf_fgets(SPACE *sp, enum e_spflag spflag) unlink(tmpfname); if ((outfile = fopen(tmpfname, "w")) == NULL) err(1, "%s", fname); + if (outfile != NULL && outfile != stdout) + fclose(outfile); fchown(fileno(outfile), sb.st_uid, sb.st_gid); fchmod(fileno(outfile), sb.st_mode & ALLPERMS); outfname = tmpfname; diff --git a/usr.bin/sed/process.c b/usr.bin/sed/process.c index cdfba811ce18..daabfd8bc7f6 100644 --- a/usr.bin/sed/process.c +++ b/usr.bin/sed/process.c @@ -324,7 +324,7 @@ applies(struct s_command *cp) } else r = 1; } - } else if (MATCH(cp->a1)) { + } else if (cp->a1 && MATCH(cp->a1)) { /* * If the second address is a number less than or * equal to the line number first selected, only