win-pvdrivers

changeset 683:4baaaaa23235 0.10.0.129

Fix a hang in xenbus when a flurry of activity fills the xenstore ring
author James Harper <james.harper@bendigoit.com.au>
date Sun Oct 11 00:21:41 2009 +1100 (2009-10-11)
parents 38fd04771db8
children ff8518224fff
files xenpci/xenbus.c xenpci/xenpci.h xenpci/xenpci_fdo.c
line diff
     1.1 --- a/xenpci/xenbus.c	Sun Oct 11 00:20:16 2009 +1100
     1.2 +++ b/xenpci/xenbus.c	Sun Oct 11 00:21:41 2009 +1100
     1.3 @@ -260,6 +260,7 @@ XenBus_Dpc(PVOID ServiceContext)
     1.4    NTSTATUS status;
     1.5    PXENPCI_DEVICE_DATA xpdd = ServiceContext;
     1.6    xsd_sockmsg_t msg;
     1.7 +  ULONG msg_len;
     1.8    WDF_WORKITEM_CONFIG workitem_config;
     1.9    WDF_OBJECT_ATTRIBUTES workitem_attributes;
    1.10    WDFWORKITEM workitem;
    1.11 @@ -268,32 +269,47 @@ XenBus_Dpc(PVOID ServiceContext)
    1.12    
    1.13    KeAcquireSpinLockAtDpcLevel(&xpdd->xb_ring_spinlock);
    1.14  
    1.15 -  //KdPrint((__DRIVER_NAME "     rsp_prod = %d, rsp_cons = %d\n", xpdd->xen_store_interface->rsp_prod, xpdd->xen_store_interface->rsp_cons));
    1.16    while (xpdd->xen_store_interface->rsp_prod != xpdd->xen_store_interface->rsp_cons)
    1.17    {
    1.18 -    if (xpdd->xen_store_interface->rsp_prod - xpdd->xen_store_interface->rsp_cons < sizeof(msg))
    1.19 +    if (!xpdd->xb_msg)
    1.20      {
    1.21 -      KdPrint((__DRIVER_NAME " +++ Message incomplete (not even a full header)\n"));
    1.22 -      break;
    1.23 +      if (xpdd->xen_store_interface->rsp_prod - xpdd->xen_store_interface->rsp_cons < sizeof(xsd_sockmsg_t))
    1.24 +      {
    1.25 +        KdPrint((__DRIVER_NAME " +++ Message incomplete (not even a full header)\n"));
    1.26 +        break;
    1.27 +      }
    1.28 +      KeMemoryBarrier();
    1.29 +      memcpy_from_ring(xpdd->xen_store_interface->rsp, &msg,
    1.30 +        MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons), sizeof(xsd_sockmsg_t));
    1.31 +      xpdd->xb_msg = ExAllocatePoolWithTag(NonPagedPool, sizeof(xsd_sockmsg_t) + msg.len, XENPCI_POOL_TAG);
    1.32 +      memcpy(xpdd->xb_msg, &msg, sizeof(xsd_sockmsg_t));
    1.33 +      xpdd->xb_msg_offset = sizeof(xsd_sockmsg_t);
    1.34 +      xpdd->xen_store_interface->rsp_cons += sizeof(xsd_sockmsg_t);
    1.35      }
    1.36 -    KeMemoryBarrier();
    1.37 -    memcpy_from_ring(xpdd->xen_store_interface->rsp, &msg,
    1.38 -      MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons), sizeof(msg));
    1.39 -    if (xpdd->xen_store_interface->rsp_prod - xpdd->xen_store_interface->rsp_cons < sizeof(msg) + msg.len)
    1.40 +
    1.41 +    msg_len = min(xpdd->xen_store_interface->rsp_prod - xpdd->xen_store_interface->rsp_cons, sizeof(xsd_sockmsg_t) + xpdd->xb_msg->len - xpdd->xb_msg_offset);
    1.42 +    KeMemoryBarrier(); /* make sure the data in the ring is valid */
    1.43 +    ASSERT(xpdd->xb_msg_offset + msg_len <= sizeof(xsd_sockmsg_t) + xpdd->xb_msg->len);
    1.44 +    memcpy_from_ring(xpdd->xen_store_interface->rsp,
    1.45 +      (PUCHAR)xpdd->xb_msg + xpdd->xb_msg_offset,
    1.46 +      MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons),
    1.47 +      msg_len);
    1.48 +    xpdd->xen_store_interface->rsp_cons += msg_len;
    1.49 +    xpdd->xb_msg_offset += msg_len;
    1.50 +
    1.51 +    if (xpdd->xb_msg_offset < sizeof(xsd_sockmsg_t) + xpdd->xb_msg->len)
    1.52      {
    1.53 -      //KdPrint((__DRIVER_NAME " +++ Message incomplete (header but not full body)\n"));
    1.54 +      KdPrint((__DRIVER_NAME " +++ Message incomplete (header but not full body)\n"));
    1.55 +      EvtChn_Notify(xpdd, xpdd->xen_store_evtchn); /* there is room on the ring now */
    1.56        break;
    1.57      }
    1.58  
    1.59 -    if (msg.type != XS_WATCH_EVENT)
    1.60 +    if (xpdd->xb_msg->type != XS_WATCH_EVENT)
    1.61      {
    1.62        /* process reply - only ever one outstanding */
    1.63 -      xpdd->xb_reply = ExAllocatePoolWithTag(NonPagedPool, sizeof(msg) + msg.len, XENPCI_POOL_TAG);
    1.64 -      memcpy_from_ring(xpdd->xen_store_interface->rsp,
    1.65 -        xpdd->xb_reply,
    1.66 -        MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons),
    1.67 -        msg.len + sizeof(msg));
    1.68 -      xpdd->xen_store_interface->rsp_cons += msg.len + sizeof(msg);
    1.69 +      ASSERT(xpdd->xb_reply == NULL);
    1.70 +      xpdd->xb_reply = xpdd->xb_msg;
    1.71 +      xpdd->xb_msg = NULL;
    1.72        KeSetEvent(&xpdd->xb_request_complete_event, IO_NO_INCREMENT, FALSE);
    1.73      }
    1.74      else
    1.75 @@ -302,20 +318,18 @@ XenBus_Dpc(PVOID ServiceContext)
    1.76        WDF_WORKITEM_CONFIG_INIT(&workitem_config, XenBus_WatchWorkItemProc);
    1.77        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&workitem_attributes, xsd_sockmsg_t);
    1.78        workitem_attributes.ParentObject = xpdd->wdf_device;
    1.79 -      workitem_attributes.ContextSizeOverride = sizeof(msg) + msg.len;
    1.80 +      workitem_attributes.ContextSizeOverride = xpdd->xb_msg_offset;
    1.81        status = WdfWorkItemCreate(&workitem_config, &workitem_attributes, &workitem);
    1.82        if (!NT_SUCCESS(status))
    1.83        {
    1.84          KdPrint((__DRIVER_NAME "     Failed to create work item for watch\n"));
    1.85 -        xpdd->xen_store_interface->rsp_cons += msg.len + sizeof(msg);
    1.86          continue;
    1.87        }
    1.88 -      memcpy_from_ring(xpdd->xen_store_interface->rsp,
    1.89 -        WdfObjectGetTypedContext(workitem, xsd_sockmsg_t),
    1.90 -        MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons), msg.len + sizeof(msg));
    1.91 -      xpdd->xen_store_interface->rsp_cons += msg.len + sizeof(msg);
    1.92 +      memcpy(WdfObjectGetTypedContext(workitem, xsd_sockmsg_t), xpdd->xb_msg, xpdd->xb_msg_offset);
    1.93 +      xpdd->xb_msg = NULL;
    1.94        WdfWorkItemEnqueue(workitem);
    1.95      }
    1.96 +    EvtChn_Notify(xpdd, xpdd->xen_store_evtchn); /* there is room on the ring now */
    1.97    }
    1.98    KeReleaseSpinLockFromDpcLevel(&xpdd->xb_ring_spinlock);
    1.99    
     2.1 --- a/xenpci/xenpci.h	Sun Oct 11 00:20:16 2009 +1100
     2.2 +++ b/xenpci/xenpci.h	Sun Oct 11 00:21:41 2009 +1100
     2.3 @@ -177,6 +177,8 @@ typedef struct {
     2.4    FAST_MUTEX xb_request_mutex;
     2.5    KEVENT xb_request_complete_event;
     2.6    struct xsd_sockmsg *xb_reply;
     2.7 +  struct xsd_sockmsg *xb_msg;
     2.8 +  ULONG xb_msg_offset;
     2.9    
    2.10    WDFCHILDLIST child_list;
    2.11  
     3.1 --- a/xenpci/xenpci_fdo.c	Sun Oct 11 00:20:16 2009 +1100
     3.2 +++ b/xenpci/xenpci_fdo.c	Sun Oct 11 00:21:41 2009 +1100
     3.3 @@ -923,6 +923,7 @@ XenPci_EvtChildListScanForChildren(WDFCH
     3.4            RtlZeroMemory(&child_description, sizeof(child_description));
     3.5            WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&child_description.header, sizeof(child_description));
     3.6            RtlStringCbPrintfA(path, ARRAY_SIZE(path), "device/%s/%s", devices[i], instances[j]);
     3.7 +          KdPrint((__DRIVER_NAME "     Found path = %s\n", path));
     3.8            RtlStringCbCopyA(child_description.path, ARRAY_SIZE(child_description.path), path);
     3.9            RtlStringCbCopyA(child_description.device, ARRAY_SIZE(child_description.device), devices[i]);
    3.10            child_description.index = atoi(instances[j]);