Author: sephe
Date: Thu Mar 24 00:40:41 2016
New Revision: 297219
URL: https://svnweb.freebsd.org/changeset/base/297219

Log:
  hyperv/vmbus: use a better retry method in hv_vmbus_post_message()
  
  Most often, hv_vmbus_post_message() doesn't fail.  However, it fails
  intermittently when GPADLs of large shared memory is to be established
  with the host, e.g. on the hn(4) attach path: a GPADL of 15MB sendbuf
  is created, for which lots of messages will be flooded to the host.
  The host side tries to throttle the message rate by returning
  HV_STATUS_INSUFFICIENT_BUFFERS.
  
  Before this commit, we do several retries for failed messages, but the
  delay between each retry is pretty/too low, which will cause sporadic
  message posting failure.  We now use large delay (>=1ms) between each
  retry to fix the message posting failure.
  
  Submitted by: Dexuan Cui <decui microsoft com>
  Reviewed by:  sephe
  MFC after:    1 week
  Sponsored by: Microsoft OSTC
  Differential Revision:        https://reviews.freebsd.org/D5715

Modified:
  head/sys/dev/hyperv/vmbus/hv_connection.c
  head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h

Modified: head/sys/dev/hyperv/vmbus/hv_connection.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_connection.c   Thu Mar 24 00:24:07 2016        
(r297218)
+++ head/sys/dev/hyperv/vmbus/hv_connection.c   Thu Mar 24 00:40:41 2016        
(r297219)
@@ -364,31 +364,35 @@ hv_vmbus_on_events(int cpu)
 /**
  * Send a msg on the vmbus's message connection
  */
-int hv_vmbus_post_message(void *buffer, size_t bufferLen) {
-       int ret = 0;
+int hv_vmbus_post_message(void *buffer, size_t bufferLen)
+{
        hv_vmbus_connection_id connId;
-       unsigned retries = 0;
-
-       /* NetScaler delays from previous code were consolidated here */
-       static int delayAmount[] = {100, 100, 100, 500, 500, 5000, 5000, 5000};
-
-       /* for(each entry in delayAmount) try to post message,
-        *  delay a little bit before retrying
+       sbintime_t time = SBT_1MS;
+       int retries;
+       int ret;
+
+       connId.as_uint32_t = 0;
+       connId.u.id = HV_VMBUS_MESSAGE_CONNECTION_ID;
+
+       /*
+        * We retry to cope with transient failures caused by host side's
+        * insufficient resources. 20 times should suffice in practice.
         */
-       for (retries = 0;
-           retries < sizeof(delayAmount)/sizeof(delayAmount[0]); retries++) {
-           connId.as_uint32_t = 0;
-           connId.u.id = HV_VMBUS_MESSAGE_CONNECTION_ID;
-           ret = hv_vmbus_post_msg_via_msg_ipc(connId, 1, buffer, bufferLen);
-           if (ret != HV_STATUS_INSUFFICIENT_BUFFERS)
-               break;
-           /* TODO: KYS We should use a blocking wait call */
-           DELAY(delayAmount[retries]);
+       for (retries = 0; retries < 20; retries++) {
+               ret = hv_vmbus_post_msg_via_msg_ipc(connId, 1, buffer,
+                                                   bufferLen);
+               if (ret == HV_STATUS_SUCCESS)
+                       return (0);
+
+               pause_sbt("pstmsg", time, 0, C_HARDCLOCK);
+               if (time < SBT_1S * 2)
+                       time *= 2;
        }
 
-       KASSERT(ret == 0, ("Error VMBUS: Message Post Failed\n"));
+       KASSERT(ret == HV_STATUS_SUCCESS,
+               ("Error VMBUS: Message Post Failed, ret=%d\n", ret));
 
-       return (ret);
+       return (EAGAIN);
 }
 
 /**

Modified: head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h   Thu Mar 24 00:24:07 2016        
(r297218)
+++ head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h   Thu Mar 24 00:40:41 2016        
(r297219)
@@ -70,6 +70,7 @@ typedef uint16_t hv_vmbus_status;
  *    You did not supply enough message buffers to send a message.
  */
 
+#define HV_STATUS_SUCCESS                ((uint16_t)0)
 #define HV_STATUS_INSUFFICIENT_BUFFERS   ((uint16_t)0x0013)
 
 typedef void (*hv_vmbus_channel_callback)(void *context);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to