Thu Nov 7 20:18:50 2013 UTC ()
Pull up following revision(s) (requested by bouyer in ticket #974):
	sys/arch/xen/xen/xbdback_xenbus.c: revision 1.58
Add more XENPRINTF() to xbdback_connect()
in xbdback_backend_changed(), fix memory leak.
Do not free an uninitialized pointer in xbdback_connect(). Should fix
 hypervisor or dom0 reboot when using windows PV drivers, as reported
 by several users on port-xen.


(snj)
diff -r1.55.2.1 -r1.55.2.1.4.1 src/sys/arch/xen/xen/xbdback_xenbus.c

cvs diff -r1.55.2.1 -r1.55.2.1.4.1 src/sys/arch/xen/xen/xbdback_xenbus.c (expand / switch to unified diff)

--- src/sys/arch/xen/xen/xbdback_xenbus.c 2012/06/05 15:36:00 1.55.2.1
+++ src/sys/arch/xen/xen/xbdback_xenbus.c 2013/11/07 20:18:50 1.55.2.1.4.1
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: xbdback_xenbus.c,v 1.55.2.1 2012/06/05 15:36:00 jdc Exp $ */ 1/* $NetBSD: xbdback_xenbus.c,v 1.55.2.1.4.1 2013/11/07 20:18:50 snj Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006 Manuel Bouyer. 4 * Copyright (c) 2006 Manuel Bouyer.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 14 *
@@ -16,27 +16,27 @@ @@ -16,27 +16,27 @@
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 * 25 *
26 */ 26 */
27 27
28#include <sys/cdefs.h> 28#include <sys/cdefs.h>
29__KERNEL_RCSID(0, "$NetBSD: xbdback_xenbus.c,v 1.55.2.1 2012/06/05 15:36:00 jdc Exp $"); 29__KERNEL_RCSID(0, "$NetBSD: xbdback_xenbus.c,v 1.55.2.1.4.1 2013/11/07 20:18:50 snj Exp $");
30 30
31#include <sys/atomic.h> 31#include <sys/atomic.h>
32#include <sys/buf.h> 32#include <sys/buf.h>
33#include <sys/condvar.h> 33#include <sys/condvar.h>
34#include <sys/conf.h> 34#include <sys/conf.h>
35#include <sys/disk.h> 35#include <sys/disk.h>
36#include <sys/device.h> 36#include <sys/device.h>
37#include <sys/fcntl.h> 37#include <sys/fcntl.h>
38#include <sys/kauth.h> 38#include <sys/kauth.h>
39#include <sys/kernel.h> 39#include <sys/kernel.h>
40#include <sys/kmem.h> 40#include <sys/kmem.h>
41#include <sys/kthread.h> 41#include <sys/kthread.h>
42#include <sys/malloc.h> 42#include <sys/malloc.h>
@@ -521,88 +521,95 @@ xbdback_xenbus_destroy(void *arg) @@ -521,88 +521,95 @@ xbdback_xenbus_destroy(void *arg)
521 521
522static int 522static int
523xbdback_connect(struct xbdback_instance *xbdi) 523xbdback_connect(struct xbdback_instance *xbdi)
524{ 524{
525 int len, err; 525 int len, err;
526 struct gnttab_map_grant_ref grop; 526 struct gnttab_map_grant_ref grop;
527 struct gnttab_unmap_grant_ref ungrop; 527 struct gnttab_unmap_grant_ref ungrop;
528 evtchn_op_t evop; 528 evtchn_op_t evop;
529 u_long ring_ref, revtchn; 529 u_long ring_ref, revtchn;
530 char *xsproto; 530 char *xsproto;
531 const char *proto; 531 const char *proto;
532 struct xenbus_device *xbusd = xbdi->xbdi_xbusd; 532 struct xenbus_device *xbusd = xbdi->xbdi_xbusd;
533 533
 534 XENPRINTF(("xbdback %s: connect\n", xbusd->xbusd_path));
534 /* read comunication informations */ 535 /* read comunication informations */
535 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend, 536 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,
536 "ring-ref", &ring_ref, 10); 537 "ring-ref", &ring_ref, 10);
537 if (err) { 538 if (err) {
538 xenbus_dev_fatal(xbusd, err, "reading %s/ring-ref", 539 xenbus_dev_fatal(xbusd, err, "reading %s/ring-ref",
539 xbusd->xbusd_otherend); 540 xbusd->xbusd_otherend);
540 return -1; 541 return -1;
541 } 542 }
 543 XENPRINTF(("xbdback %s: connect ring-ref %lu\n", xbusd->xbusd_path, ring_ref));
542 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend, 544 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,
543 "event-channel", &revtchn, 10); 545 "event-channel", &revtchn, 10);
544 if (err) { 546 if (err) {
545 xenbus_dev_fatal(xbusd, err, "reading %s/event-channel", 547 xenbus_dev_fatal(xbusd, err, "reading %s/event-channel",
546 xbusd->xbusd_otherend); 548 xbusd->xbusd_otherend);
547 return -1; 549 return -1;
548 } 550 }
 551 XENPRINTF(("xbdback %s: connect revtchn %lu\n", xbusd->xbusd_path, revtchn));
549 err = xenbus_read(NULL, xbusd->xbusd_otherend, "protocol", 552 err = xenbus_read(NULL, xbusd->xbusd_otherend, "protocol",
550 &len, &xsproto); 553 &len, &xsproto);
551 if (err) { 554 if (err) {
552 xbdi->xbdi_proto = XBDIP_NATIVE; 555 xbdi->xbdi_proto = XBDIP_NATIVE;
553 proto = "unspecified"; 556 proto = "unspecified";
 557 XENPRINTF(("xbdback %s: connect no xsproto\n", xbusd->xbusd_path));
554 } else { 558 } else {
 559 XENPRINTF(("xbdback %s: connect xsproto %s\n", xbusd->xbusd_path, xsproto));
555 if (strcmp(xsproto, XEN_IO_PROTO_ABI_NATIVE) == 0) { 560 if (strcmp(xsproto, XEN_IO_PROTO_ABI_NATIVE) == 0) {
556 xbdi->xbdi_proto = XBDIP_NATIVE; 561 xbdi->xbdi_proto = XBDIP_NATIVE;
557 proto = XEN_IO_PROTO_ABI_NATIVE; 562 proto = XEN_IO_PROTO_ABI_NATIVE;
558 } else if (strcmp(xsproto, XEN_IO_PROTO_ABI_X86_32) == 0) { 563 } else if (strcmp(xsproto, XEN_IO_PROTO_ABI_X86_32) == 0) {
559 xbdi->xbdi_proto = XBDIP_32; 564 xbdi->xbdi_proto = XBDIP_32;
560 proto = XEN_IO_PROTO_ABI_X86_32; 565 proto = XEN_IO_PROTO_ABI_X86_32;
561 } else if (strcmp(xsproto, XEN_IO_PROTO_ABI_X86_64) == 0) { 566 } else if (strcmp(xsproto, XEN_IO_PROTO_ABI_X86_64) == 0) {
562 xbdi->xbdi_proto = XBDIP_64; 567 xbdi->xbdi_proto = XBDIP_64;
563 proto = XEN_IO_PROTO_ABI_X86_64; 568 proto = XEN_IO_PROTO_ABI_X86_64;
564 } else { 569 } else {
565 aprint_error("xbd domain %d: unknown proto %s\n", 570 aprint_error("xbd domain %d: unknown proto %s\n",
566 xbdi->xbdi_domid, xsproto); 571 xbdi->xbdi_domid, xsproto);
567 free(xsproto, M_DEVBUF); 572 free(xsproto, M_DEVBUF);
568 return -1; 573 return -1;
569 } 574 }
 575 free(xsproto, M_DEVBUF);
570 } 576 }
571 free(xsproto, M_DEVBUF); 
572 577
573 /* allocate VA space and map rings */ 578 /* allocate VA space and map rings */
574 xbdi->xbdi_ring_va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, 579 xbdi->xbdi_ring_va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
575 UVM_KMF_VAONLY); 580 UVM_KMF_VAONLY);
576 if (xbdi->xbdi_ring_va == 0) { 581 if (xbdi->xbdi_ring_va == 0) {
577 xenbus_dev_fatal(xbusd, ENOMEM, 582 xenbus_dev_fatal(xbusd, ENOMEM,
578 "can't get VA for ring", xbusd->xbusd_otherend); 583 "can't get VA for ring", xbusd->xbusd_otherend);
579 return -1; 584 return -1;
580 } 585 }
 586 XENPRINTF(("xbdback %s: connect va 0x%" PRIxVADDR "\n", xbusd->xbusd_path, xbdi->xbdi_ring_va));
581 587
582 grop.host_addr = xbdi->xbdi_ring_va; 588 grop.host_addr = xbdi->xbdi_ring_va;
583 grop.flags = GNTMAP_host_map; 589 grop.flags = GNTMAP_host_map;
584 grop.ref = ring_ref; 590 grop.ref = ring_ref;
585 grop.dom = xbdi->xbdi_domid; 591 grop.dom = xbdi->xbdi_domid;
586 err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, 592 err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
587 &grop, 1); 593 &grop, 1);
588 if (err || grop.status) { 594 if (err || grop.status) {
589 aprint_error("xbdback %s: can't map grant ref: %d/%d\n", 595 aprint_error("xbdback %s: can't map grant ref: %d/%d\n",
590 xbusd->xbusd_path, err, grop.status); 596 xbusd->xbusd_path, err, grop.status);
591 xenbus_dev_fatal(xbusd, EINVAL, 597 xenbus_dev_fatal(xbusd, EINVAL,
592 "can't map ring", xbusd->xbusd_otherend); 598 "can't map ring", xbusd->xbusd_otherend);
593 goto err; 599 goto err;
594 } 600 }
595 xbdi->xbdi_ring_handle = grop.handle; 601 xbdi->xbdi_ring_handle = grop.handle;
 602 XENPRINTF(("xbdback %s: connect grhandle %d\n", xbusd->xbusd_path, grop.handle));
596 603
597 switch(xbdi->xbdi_proto) { 604 switch(xbdi->xbdi_proto) {
598 case XBDIP_NATIVE: 605 case XBDIP_NATIVE:
599 { 606 {
600 blkif_sring_t *sring = (void *)xbdi->xbdi_ring_va; 607 blkif_sring_t *sring = (void *)xbdi->xbdi_ring_va;
601 BACK_RING_INIT(&xbdi->xbdi_ring.ring_n, sring, PAGE_SIZE); 608 BACK_RING_INIT(&xbdi->xbdi_ring.ring_n, sring, PAGE_SIZE);
602 break; 609 break;
603 } 610 }
604 case XBDIP_32: 611 case XBDIP_32:
605 { 612 {
606 blkif_x86_32_sring_t *sring = (void *)xbdi->xbdi_ring_va; 613 blkif_x86_32_sring_t *sring = (void *)xbdi->xbdi_ring_va;
607 BACK_RING_INIT(&xbdi->xbdi_ring.ring_32, sring, PAGE_SIZE); 614 BACK_RING_INIT(&xbdi->xbdi_ring.ring_32, sring, PAGE_SIZE);
608 break; 615 break;
@@ -617,26 +624,27 @@ xbdback_connect(struct xbdback_instance  @@ -617,26 +624,27 @@ xbdback_connect(struct xbdback_instance
617 624
618 evop.cmd = EVTCHNOP_bind_interdomain; 625 evop.cmd = EVTCHNOP_bind_interdomain;
619 evop.u.bind_interdomain.remote_dom = xbdi->xbdi_domid; 626 evop.u.bind_interdomain.remote_dom = xbdi->xbdi_domid;
620 evop.u.bind_interdomain.remote_port = revtchn; 627 evop.u.bind_interdomain.remote_port = revtchn;
621 err = HYPERVISOR_event_channel_op(&evop); 628 err = HYPERVISOR_event_channel_op(&evop);
622 if (err) { 629 if (err) {
623 aprint_error("blkback %s: " 630 aprint_error("blkback %s: "
624 "can't get event channel: %d\n", 631 "can't get event channel: %d\n",
625 xbusd->xbusd_otherend, err); 632 xbusd->xbusd_otherend, err);
626 xenbus_dev_fatal(xbusd, err, 633 xenbus_dev_fatal(xbusd, err,
627 "can't bind event channel", xbusd->xbusd_otherend); 634 "can't bind event channel", xbusd->xbusd_otherend);
628 goto err2; 635 goto err2;
629 } 636 }
 637 XENPRINTF(("xbdback %s: connect evchannel %d\n", xbusd->xbusd_path, xbdi->xbdi_evtchn));
630 xbdi->xbdi_evtchn = evop.u.bind_interdomain.local_port; 638 xbdi->xbdi_evtchn = evop.u.bind_interdomain.local_port;
631 639
632 event_set_handler(xbdi->xbdi_evtchn, xbdback_evthandler, 640 event_set_handler(xbdi->xbdi_evtchn, xbdback_evthandler,
633 xbdi, IPL_BIO, xbdi->xbdi_name); 641 xbdi, IPL_BIO, xbdi->xbdi_name);
634 aprint_verbose("xbd backend domain %d handle %#x (%d) " 642 aprint_verbose("xbd backend domain %d handle %#x (%d) "
635 "using event channel %d, protocol %s\n", xbdi->xbdi_domid, 643 "using event channel %d, protocol %s\n", xbdi->xbdi_domid,
636 xbdi->xbdi_handle, xbdi->xbdi_handle, xbdi->xbdi_evtchn, proto); 644 xbdi->xbdi_handle, xbdi->xbdi_handle, xbdi->xbdi_evtchn, proto);
637 645
638 /* enable the xbdback event handler machinery */ 646 /* enable the xbdback event handler machinery */
639 xbdi->xbdi_status = WAITING; 647 xbdi->xbdi_status = WAITING;
640 hypervisor_enable_event(xbdi->xbdi_evtchn); 648 hypervisor_enable_event(xbdi->xbdi_evtchn);
641 hypervisor_notify_via_evtchn(xbdi->xbdi_evtchn); 649 hypervisor_notify_via_evtchn(xbdi->xbdi_evtchn);
642 650
@@ -756,26 +764,27 @@ xbdback_backend_changed(struct xenbus_wa @@ -756,26 +764,27 @@ xbdback_backend_changed(struct xenbus_wa
756 return; 764 return;
757 } 765 }
758 xbdi->xbdi_dev = dev; 766 xbdi->xbdi_dev = dev;
759 err = xenbus_read(NULL, xbusd->xbusd_path, "mode", NULL, &mode); 767 err = xenbus_read(NULL, xbusd->xbusd_path, "mode", NULL, &mode);
760 if (err) { 768 if (err) {
761 printf("xbdback: failed to read %s/mode: %d\n", 769 printf("xbdback: failed to read %s/mode: %d\n",
762 xbusd->xbusd_path, err); 770 xbusd->xbusd_path, err);
763 return; 771 return;
764 } 772 }
765 if (mode[0] == 'w') 773 if (mode[0] == 'w')
766 xbdi->xbdi_ro = false; 774 xbdi->xbdi_ro = false;
767 else 775 else
768 xbdi->xbdi_ro = true; 776 xbdi->xbdi_ro = true;
 777 free(mode, M_DEVBUF);
769 major = major(xbdi->xbdi_dev); 778 major = major(xbdi->xbdi_dev);
770 devname = devsw_blk2name(major); 779 devname = devsw_blk2name(major);
771 if (devname == NULL) { 780 if (devname == NULL) {
772 printf("xbdback %s: unknown device 0x%"PRIx64"\n", 781 printf("xbdback %s: unknown device 0x%"PRIx64"\n",
773 xbusd->xbusd_path, xbdi->xbdi_dev); 782 xbusd->xbusd_path, xbdi->xbdi_dev);
774 return; 783 return;
775 } 784 }
776 xbdi->xbdi_bdevsw = bdevsw_lookup(xbdi->xbdi_dev); 785 xbdi->xbdi_bdevsw = bdevsw_lookup(xbdi->xbdi_dev);
777 if (xbdi->xbdi_bdevsw == NULL) { 786 if (xbdi->xbdi_bdevsw == NULL) {
778 printf("xbdback %s: no bdevsw for device 0x%"PRIx64"\n", 787 printf("xbdback %s: no bdevsw for device 0x%"PRIx64"\n",
779 xbusd->xbusd_path, xbdi->xbdi_dev); 788 xbusd->xbusd_path, xbdi->xbdi_dev);
780 return; 789 return;
781 } 790 }