Print this page
Try versioning as a new state

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/varpd/svp/common/libvarpd_svp_conn.c
          +++ new/usr/src/lib/varpd/svp/common/libvarpd_svp_conn.c
↓ open down ↓ 32 lines elided ↑ open up ↑
  33   33  
  34   34  int svp_conn_query_timeout = 30;
  35   35  static int svp_conn_backoff_tbl[] = { 1, 2, 4, 8, 16, 32 };
  36   36  static int svp_conn_nbackoff = sizeof (svp_conn_backoff_tbl) / sizeof (int);
  37   37  
  38   38  typedef enum svp_conn_act {
  39   39          SVP_RA_NONE     = 0x00,
  40   40          SVP_RA_DEGRADE  = 0x01,
  41   41          SVP_RA_RESTORE  = 0x02,
  42   42          SVP_RA_ERROR    = 0x03,
  43      -        SVP_RA_CLEANUP  = 0x04
       43 +        SVP_RA_CLEANUP  = 0x04,
       44 +        SVP_RA_FIND_VERSION = 0x05
  44   45  } svp_conn_act_t;
  45   46  
  46   47  static svp_conn_act_t svp_conn_poll_connect(port_event_t *, svp_conn_t *);
  47   48  
  48   49  static void
  49   50  svp_conn_inject(svp_conn_t *scp)
  50   51  {
  51   52          int ret;
  52   53          assert(MUTEX_HELD(&scp->sc_lock));
  53   54  
↓ open down ↓ 31 lines elided ↑ open up ↑
  85   86  
  86   87          if (!(scp->sc_flags & SVP_CF_DEGRADED))
  87   88                  return;
  88   89  
  89   90          scp->sc_flags &= ~SVP_CF_DEGRADED;
  90   91          if (srp->sr_ndconns == srp->sr_tconns)
  91   92                  svp_remote_restore(srp, SVP_RD_REMOTE_FAIL);
  92   93          srp->sr_ndconns--;
  93   94  }
  94   95  
       96 +static svp_conn_act_t
       97 +svp_conn_pong_handler(svp_conn_t *scp, svp_query_t *sqp)
       98 +{
       99 +        uint16_t remote_version = ntohs(scp->sc_input.sci_req.svp_ver);
      100 +
      101 +        if (scp->sc_cstate == SVP_CS_VERSIONING) {
      102 +                /* Transition VERSIONING -> ACTIVE. */
      103 +                assert(scp->sc_version == 0);
      104 +                if (remote_version == 0 || remote_version > SVP_CURRENT_VERSION)
      105 +                        return (SVP_RA_ERROR);
      106 +                scp->sc_version = remote_version;
      107 +                scp->sc_cstate = SVP_CS_ACTIVE;
      108 +        }
      109 +
      110 +        return (SVP_RA_NONE);
      111 +}
      112 +
  95  113  static void
      114 +svp_conn_ping_cb(svp_query_t *sqp, void *arg)
      115 +{
      116 +        size_t len = (size_t)arg;
      117 +
      118 +        assert(len == sizeof (svp_query_t));
      119 +        umem_free(sqp, len);
      120 +}
      121 +
      122 +static svp_conn_act_t
      123 +svp_conn_ping_version(svp_conn_t *scp)
      124 +{
      125 +        svp_remote_t *srp = scp->sc_remote;
      126 +        svp_query_t *sqp = umem_zalloc(sizeof (svp_query_t), UMEM_DEFAULT);
      127 +        int ret;
      128 +
      129 +        assert(MUTEX_HELD(&srp->sr_lock));
      130 +        assert(MUTEX_HELD(&scp->sc_lock));
      131 +        assert(scp->sc_cstate == SVP_CS_CONNECTING);
      132 +
      133 +        if (sqp == NULL)
      134 +                return (SVP_RA_ERROR);
      135 +
      136 +        /* Only set things that need to be non-0/non-NULL. */
      137 +        sqp->sq_state = SVP_QUERY_INIT;
      138 +        sqp->sq_func = svp_conn_ping_cb;
      139 +        sqp->sq_arg = (void *)sizeof (svp_query_t);
      140 +        sqp->sq_header.svp_op = htons(SVP_R_PING);
      141 +        sqp->sq_header.svp_ver = htons(SVP_CURRENT_VERSION);
      142 +        sqp->sq_header.svp_id = svp_id_alloc();
      143 +        if (sqp->sq_header.svp_id == -1) {
      144 +                umem_free(sqp, sizeof (svp_query_t));
      145 +                return (SVP_RA_ERROR);
      146 +        }
      147 +
      148 +        scp->sc_cstate = SVP_CS_VERSIONING;
      149 +        /* Set the event flags now... */
      150 +        scp->sc_event.se_events = POLLIN | POLLRDNORM | POLLHUP | POLLOUT;
      151 +        /* ...so I can just queue it up directly... */
      152 +        svp_conn_queue(scp, sqp);
      153 +        /* ... and then associate the event port myself. */
      154 +        ret = svp_event_associate(&scp->sc_event, scp->sc_socket);
      155 +        if (ret == 0)
      156 +                return (SVP_RA_RESTORE);
      157 +        scp->sc_error = SVP_CE_ASSOCIATE;
      158 +        scp->sc_errno = ret;
      159 +        scp->sc_cstate = SVP_CS_ERROR;
      160 +        umem_free(sqp, sizeof (svp_query_t));
      161 +        return (SVP_RA_DEGRADE);
      162 +}
      163 +
      164 +static void
  96  165  svp_conn_add(svp_conn_t *scp)
  97  166  {
  98  167          svp_remote_t *srp = scp->sc_remote;
  99  168  
 100  169          assert(MUTEX_HELD(&srp->sr_lock));
 101  170          assert(MUTEX_HELD(&scp->sc_lock));
 102  171  
 103  172          if (scp->sc_flags & SVP_CF_ADDED)
 104  173                  return;
 105  174  
↓ open down ↓ 56 lines elided ↑ open up ↑
 162  231                  scp->sc_btimer.st_value =
 163  232                      svp_conn_backoff_tbl[scp->sc_nbackoff - 1];
 164  233          }
 165  234          svp_timer_add(&scp->sc_btimer);
 166  235  
 167  236          if (scp->sc_nbackoff > svp_conn_nbackoff)
 168  237                  return (SVP_RA_DEGRADE);
 169  238          return (SVP_RA_NONE);
 170  239  }
 171  240  
 172      -/*
 173      - * Think of this as an extension to the connect() call in svp_conn_connect().
 174      - * Send a message, receive it, and set the version here.  If the response is
 175      - * too slow or the socket throws an error, indicate a socket error, which
 176      - * will cause the caller to backoff (i.e. close the socket and try again).
 177      - *
 178      - * Version mismatch (corrupt SVP server or too-advanced SVP server) is its
 179      - * own error type.
 180      - */
 181      -static svp_conn_error_t
 182      -svp_conn_version_set(svp_conn_t *scp)
 183      -{
 184      -        svp_req_t ping;
 185      -        ssize_t ret;
 186      -        uint32_t save_crc;
 187      -        uint16_t peer_version;
 188      -        int ntries = 3; /* One second between tries. 3secs should be enough. */
 189      -
 190      -        ping.svp_ver = htons(SVP_CURRENT_VERSION);
 191      -        ping.svp_op = htons(SVP_R_PING);
 192      -        ping.svp_size = 0;      /* Header-only... */
 193      -        ping.svp_id = 0;
 194      -        /* 0-length data... just use the req buffer for the pointer. */
 195      -        svp_query_crc32(&ping, &ping, 0);
 196      -
 197      -        ret = write(scp->sc_socket, &ping, sizeof (ping));
 198      -        if (ret == -1) {
 199      -                /*
 200      -                 * A failed write() call right after connect probably
 201      -                 * indicates a larger connection failure.  Restart the
 202      -                 * connection from scratch.
 203      -                 */
 204      -                return (SVP_CE_SOCKET);
 205      -        }
 206      -        assert(ret == sizeof (ping));
 207      -        do {
 208      -                /*
 209      -                 * Asynch read.  We may loop here once or twice.
 210      -                 * Wait a bit, but don't loop too many times...
 211      -                 */
 212      -                (void) sleep(1);
 213      -                ret = read(scp->sc_socket, &ping, sizeof (ping));
 214      -        } while (--ntries > 0 &&
 215      -            ret == -1 && (errno == EINTR || errno == EAGAIN));
 216      -        if (ret == -1) {
 217      -                /*
 218      -                 * This is actually a failed read() call.  Restart the
 219      -                 * connection from scratch.
 220      -                 */
 221      -                return (SVP_CE_SOCKET);
 222      -        }
 223      -
 224      -        save_crc = ping.svp_crc32;
 225      -        svp_query_crc32(&ping, &ping, 0);
 226      -        peer_version = htons(ping.svp_ver);
 227      -        if (ping.svp_op != htons(SVP_R_PONG) ||
 228      -            ping.svp_size != 0 || ping.svp_id != 0 ||
 229      -            ping.svp_crc32 != save_crc ||
 230      -            peer_version == 0 || peer_version > SVP_CURRENT_VERSION) {
 231      -                return (SVP_CE_VERSION_PONG);
 232      -        }
 233      -
 234      -        /* This connection now has a version! */
 235      -        scp->sc_version = peer_version;
 236      -        return (SVP_CE_NONE);
 237      -}
 238      -
 239  241  static svp_conn_act_t
 240  242  svp_conn_connect(svp_conn_t *scp)
 241  243  {
 242  244          int ret;
 243  245          struct sockaddr_in6 in6;
 244  246  
 245  247          assert(MUTEX_HELD(&scp->sc_lock));
 246  248          assert(scp->sc_cstate == SVP_CS_BACKOFF ||
 247  249              scp->sc_cstate == SVP_CS_INITIAL);
 248  250          assert(scp->sc_socket == -1);
↓ open down ↓ 68 lines elided ↑ open up ↑
 317  319                           * ENXIO
 318  320                           * ETIMEDOUT
 319  321                           *
 320  322                           * Therefore we need to set ourselves into backoff and
 321  323                           * wait for that to clear up.
 322  324                           */
 323  325                          return (svp_conn_backoff(scp));
 324  326                  }
 325  327          }
 326  328  
      329 +        /* Immediately successful connection, move to SVP_CS_VERSIONING. */
 327  330          return (svp_conn_poll_connect(NULL, scp));
 328  331  }
 329  332  
 330  333  /*
 331  334   * This should be the first call we get after a successful synchronous
 332  335   * connect, or a completed (failed or successful) asynchronous connect.  A
 333  336   * non-NULL port-event indicates asynchronous completion, a NULL port-event
 334  337   * indicates a successful synchronous connect.
 335  338   * 
 336  339   * If we have successfully connected, we should see a writeable event.  In the
↓ open down ↓ 26 lines elided ↑ open up ↑
 363  366  
 364  367                  ret = getsockopt(scp->sc_socket, SOL_SOCKET, SO_ERROR, &err,
 365  368                      &sl);
 366  369                  if (ret != 0)
 367  370                          libvarpd_panic("unanticipated getsockopt error");
 368  371                  if (err != 0) {
 369  372                          return (svp_conn_backoff(scp));
 370  373                  }
 371  374          }
 372  375  
 373      -        /* Use a single SVP_R_PING to determine the version. */
 374      -        version_error = svp_conn_version_set(scp);
 375      -        switch (version_error) {
 376      -        case SVP_CE_SOCKET:
 377      -                /* Use this to signal read/write errors... */
 378      -                return (svp_conn_backoff(scp));
 379      -        case SVP_CE_NONE:
 380      -                assert(scp->sc_version > 0 &&
 381      -                    scp->sc_version <= SVP_CURRENT_VERSION);
 382      -                break;
 383      -        default:
 384      -                scp->sc_error = version_error;
 385      -                scp->sc_cstate = SVP_CS_ERROR;
 386      -                scp->sc_errno = EPROTONOSUPPORT;        /* Protocol error... */
 387      -                return (SVP_RA_DEGRADE);
 388      -        }
 389      -
 390      -        scp->sc_cstate = SVP_CS_ACTIVE;
 391      -        scp->sc_event.se_events = POLLIN | POLLRDNORM | POLLHUP;
 392      -        ret = svp_event_associate(&scp->sc_event, scp->sc_socket);
 393      -        if (ret == 0)
 394      -                return (SVP_RA_RESTORE);
 395      -        scp->sc_error = SVP_CE_ASSOCIATE;
 396      -        scp->sc_errno = ret;
 397      -        scp->sc_cstate = SVP_CS_ERROR;
 398      -        return (SVP_RA_DEGRADE);
      376 +        return (SVP_RA_FIND_VERSION);
 399  377  }
 400  378  
 401  379  static svp_conn_act_t
 402  380  svp_conn_pollout(svp_conn_t *scp)
 403  381  {
 404  382          svp_query_t *sqp;
 405  383          svp_req_t *req;
 406  384          size_t off;
 407  385          struct iovec iov[2];
 408  386          int nvecs = 0;
↓ open down ↓ 64 lines elided ↑ open up ↑
 473  451                  scp->sc_output.sco_offset = 0;
 474  452                  scp->sc_event.se_events |= POLLOUT;
 475  453          }
 476  454          return (SVP_RA_NONE);
 477  455  }
 478  456  
 479  457  static boolean_t
 480  458  svp_conn_pollin_validate(svp_conn_t *scp)
 481  459  {
 482  460          svp_query_t *sqp;
 483      -        uint32_t nsize;
      461 +        uint32_t nsize, expected_size = 0;
 484  462          uint16_t nvers, nop;
 485  463          svp_req_t *resp = &scp->sc_input.sci_req;
 486  464  
 487  465          assert(MUTEX_HELD(&scp->sc_lock));
 488  466  
 489  467          nvers = ntohs(resp->svp_ver);
 490  468          nop = ntohs(resp->svp_op);
 491  469          nsize = ntohl(resp->svp_size);
 492  470  
 493  471          /*
 494  472           * A peer that's messing with post-connection version changes is
 495  473           * likely a broken peer.
 496  474           */
 497      -        if (nvers != scp->sc_version) {
      475 +        if (scp->sc_cstate != SVP_CS_VERSIONING && nvers != scp->sc_version) {
 498  476                  (void) bunyan_warn(svp_bunyan, "version mismatch",
 499  477                      BUNYAN_T_IP, "remote_ip", &scp->sc_addr,
 500  478                      BUNYAN_T_INT32, "remote_port", scp->sc_remote->sr_rport,
 501  479                      BUNYAN_T_INT32, "peer version", nvers,
 502  480                      BUNYAN_T_INT32, "our version", scp->sc_version,
 503  481                      BUNYAN_T_INT32, "operation", nop,
 504  482                      BUNYAN_T_INT32, "response_id", resp->svp_id,
 505  483                      BUNYAN_T_END);
 506  484                  return (B_FALSE);
 507  485          }
 508  486  
 509      -        if (nop != SVP_R_VL2_ACK && nop != SVP_R_VL3_ACK &&
 510      -            nop != SVP_R_LOG_ACK && nop != SVP_R_LOG_RM_ACK) {
      487 +        switch (nop) {
      488 +        case SVP_R_VL2_ACK:
      489 +                expected_size = sizeof (svp_vl2_ack_t);
      490 +                break;
      491 +        case SVP_R_VL3_ACK:
      492 +                expected_size = sizeof (svp_vl3_ack_t);
      493 +                break;
      494 +        case SVP_R_LOG_RM_ACK:
      495 +                expected_size = sizeof (svp_lrm_ack_t);
      496 +                break;
      497 +        case SVP_R_ROUTE_ACK:
      498 +                expected_size = sizeof (svp_route_ack_t);
      499 +                break;
      500 +        case SVP_R_LOG_ACK:
      501 +        case SVP_R_PONG:
      502 +                /* No expected size (LOG_ACK) or size is 0 (PONG). */
      503 +                break;
      504 +        default:
 511  505                  (void) bunyan_warn(svp_bunyan, "unsupported operation",
 512  506                      BUNYAN_T_IP, "remote_ip", &scp->sc_addr,
 513  507                      BUNYAN_T_INT32, "remote_port", scp->sc_remote->sr_rport,
 514  508                      BUNYAN_T_INT32, "version", nvers,
 515  509                      BUNYAN_T_INT32, "operation", nop,
 516  510                      BUNYAN_T_INT32, "response_id", resp->svp_id,
 517  511                      BUNYAN_T_END);
 518  512                  return (B_FALSE);
 519  513          }
 520  514  
↓ open down ↓ 15 lines elided ↑ open up ↑
 536  530                      BUNYAN_T_IP, "remote_ip", &scp->sc_addr,
 537  531                      BUNYAN_T_INT32, "remote_port", scp->sc_remote->sr_rport,
 538  532                      BUNYAN_T_INT32, "version", nvers,
 539  533                      BUNYAN_T_INT32, "operation", nop,
 540  534                      BUNYAN_T_INT32, "response_id", resp->svp_id,
 541  535                      BUNYAN_T_INT32, "query_state", sqp->sq_state,
 542  536                      BUNYAN_T_END);
 543  537                  return (B_FALSE);
 544  538          }
 545  539  
 546      -        if ((nop == SVP_R_VL2_ACK && nsize != sizeof (svp_vl2_ack_t)) ||
 547      -            (nop == SVP_R_VL3_ACK && nsize != sizeof (svp_vl3_ack_t)) ||
 548      -            (nop == SVP_R_LOG_RM_ACK && nsize != sizeof (svp_lrm_ack_t))) {
      540 +        if (nop != SVP_R_LOG_RM_ACK && nsize != expected_size) {
 549  541                  (void) bunyan_warn(svp_bunyan, "response size too large",
 550  542                      BUNYAN_T_IP, "remote_ip", &scp->sc_addr,
 551  543                      BUNYAN_T_INT32, "remote_port", scp->sc_remote->sr_rport,
 552  544                      BUNYAN_T_INT32, "version", nvers,
 553  545                      BUNYAN_T_INT32, "operation", nop,
 554  546                      BUNYAN_T_INT32, "response_id", resp->svp_id,
 555  547                      BUNYAN_T_INT32, "response_size", nsize,
 556  548                      BUNYAN_T_INT32, "expected_size", nop == SVP_R_VL2_ACK ?
 557  549                      sizeof (svp_vl2_ack_t) : sizeof (svp_vl3_ack_t),
 558  550                      BUNYAN_T_INT32, "query_state", sqp->sq_state,
↓ open down ↓ 24 lines elided ↑ open up ↑
 583  575                              ((svp_log_req_t *)sqp->sq_rdata)->svlr_count,
 584  576                              BUNYAN_T_INT32, "query_state", sqp->sq_state,
 585  577                              BUNYAN_T_END);
 586  578                          return (B_FALSE);
 587  579                  }
 588  580          }
 589  581  
 590  582          sqp->sq_size = nsize;
 591  583          scp->sc_input.sci_query = sqp;
 592  584          if (nop == SVP_R_VL2_ACK || nop == SVP_R_VL3_ACK ||
 593      -            nop == SVP_R_LOG_RM_ACK) {
      585 +            nop == SVP_R_LOG_RM_ACK || nop == SVP_R_ROUTE_ACK ||
      586 +            nop == SVP_R_PONG) {
 594  587                  sqp->sq_wdata = &sqp->sq_wdun;
 595  588                  sqp->sq_wsize = sizeof (svp_query_data_t);
 596  589          } else {
 597  590                  VERIFY(nop == SVP_R_LOG_ACK);
 598  591                  assert(sqp->sq_wdata != NULL);
 599  592                  assert(sqp->sq_wsize != 0);
 600  593          }
 601  594  
 602  595          return (B_TRUE);
 603  596  }
↓ open down ↓ 69 lines elided ↑ open up ↑
 673  666                  case EAGAIN:
 674  667                          scp->sc_event.se_events |= POLLIN | POLLRDNORM;
 675  668                          return (SVP_RA_NONE);
 676  669                  case EIO:
 677  670                  case ECONNRESET:
 678  671                          return (SVP_RA_ERROR);
 679  672                          break;
 680  673                  default:
 681  674                          libvarpd_panic("unexpeted read errno: %d", errno);
 682  675                  }
 683      -        } else if (ret == 0) {
      676 +        } else if (ret == 0 && total - off > 0) {
 684  677                  /* Try to reconnect to the remote host */
 685  678                  return (SVP_RA_ERROR);
 686  679          }
 687  680  
 688  681          if (ret + off < total) {
 689  682                  scp->sc_input.sci_offset += ret;
 690  683                  return (SVP_RA_NONE);
 691  684          }
 692  685  
 693  686          nop = ntohs(scp->sc_input.sci_req.svp_op);
↓ open down ↓ 23 lines elided ↑ open up ↑
 717  710                  sqp->sq_status = ntohl(sl2a->sl2a_status);
 718  711          } else if (nop == SVP_R_VL3_ACK) {
 719  712                  svp_vl3_ack_t *sl3a = sqp->sq_wdata;
 720  713                  sqp->sq_status = ntohl(sl3a->sl3a_status);
 721  714          } else if (nop == SVP_R_LOG_ACK) {
 722  715                  svp_log_ack_t *svla = sqp->sq_wdata;
 723  716                  sqp->sq_status = ntohl(svla->svla_status);
 724  717          } else if (nop == SVP_R_LOG_RM_ACK) {
 725  718                  svp_lrm_ack_t *svra = sqp->sq_wdata;
 726  719                  sqp->sq_status = ntohl(svra->svra_status);
      720 +        } else if (nop == SVP_R_ROUTE_ACK) {
      721 +                svp_route_ack_t *sra = sqp->sq_wdata;
      722 +                sqp->sq_status = ntohl(sra->sra_status);
      723 +        } else if (nop == SVP_R_PONG) {
      724 +                /*
      725 +                 * Handle the PONG versioning-capture here, as we need
      726 +                 * the version number, the scp_lock held, and the ability
      727 +                 * to error out.
      728 +                 */
      729 +                svp_conn_act_t cbret;
      730 +
      731 +                cbret = svp_conn_pong_handler(scp, sqp);
      732 +                if (cbret != SVP_RA_NONE)
      733 +                        return (cbret);
 727  734          } else {
 728  735                  libvarpd_panic("unhandled nop: %d", nop);
 729  736          }
 730  737  
 731  738          list_remove(&scp->sc_queries, sqp);
 732  739          mutex_exit(&scp->sc_lock);
 733  740  
 734  741          /*
 735  742           * We have to release all of our resources associated with this entry
 736  743           * before we call the callback. After we call it, the memory will be
↓ open down ↓ 91 lines elided ↑ open up ↑
 828  835          switch (scp->sc_cstate) {
 829  836          case SVP_CS_INITIAL:
 830  837          case SVP_CS_BACKOFF:
 831  838                  assert(pe == NULL);
 832  839                  ret = svp_conn_connect(scp);
 833  840                  break;
 834  841          case SVP_CS_CONNECTING:
 835  842                  assert(pe != NULL);
 836  843                  ret = svp_conn_poll_connect(pe, scp);
 837  844                  break;
      845 +        case SVP_CS_VERSIONING:
 838  846          case SVP_CS_ACTIVE:
 839  847          case SVP_CS_WINDDOWN:
 840  848                  assert(pe != NULL);
 841  849                  oldstate = scp->sc_cstate;
 842  850                  if (pe->portev_events & POLLOUT)
 843  851                          ret = svp_conn_pollout(scp);
 844  852                  if (ret == SVP_RA_NONE && (pe->portev_events & POLLIN))
 845  853                          ret = svp_conn_pollin(scp);
 846  854  
 847  855                  if (oldstate == SVP_CS_WINDDOWN &&
↓ open down ↓ 17 lines elided ↑ open up ↑
 865  873                      "state: %d", scp->sc_cstate);
 866  874          }
 867  875  out:
 868  876          mutex_exit(&scp->sc_lock);
 869  877  
 870  878          if (ret == SVP_RA_NONE)
 871  879                  return;
 872  880  
 873  881          mutex_enter(&srp->sr_lock);
 874  882          mutex_enter(&scp->sc_lock);
      883 +        if (ret == SVP_RA_FIND_VERSION)
      884 +                ret = svp_conn_ping_version(scp);
      885 +
 875  886          if (ret == SVP_RA_ERROR)
 876  887                  ret = svp_conn_reset(scp);
 877  888  
 878  889          if (ret == SVP_RA_DEGRADE)
 879  890                  svp_conn_degrade(scp);
 880  891          if (ret == SVP_RA_RESTORE)
 881  892                  svp_conn_restore(scp);
 882  893  
 883  894          if (ret == SVP_RA_CLEANUP) {
 884  895                  svp_conn_remove(scp);
↓ open down ↓ 221 lines elided ↑ open up ↑
1106 1117                      "%d: %d", scp->sc_socket, errno);
1107 1118  
1108 1119          list_destroy(&scp->sc_queries);
1109 1120          umem_free(scp, sizeof (svp_conn_t));
1110 1121  }
1111 1122  
1112 1123  void
1113 1124  svp_conn_queue(svp_conn_t *scp, svp_query_t *sqp)
1114 1125  {
1115 1126          assert(MUTEX_HELD(&scp->sc_lock));
1116      -        assert(scp->sc_cstate == SVP_CS_ACTIVE);
     1127 +        assert(scp->sc_cstate == SVP_CS_ACTIVE ||
     1128 +            scp->sc_cstate == SVP_CS_VERSIONING);
1117 1129  
1118 1130          sqp->sq_acttime = -1;
1119 1131          list_insert_tail(&scp->sc_queries, sqp);
1120 1132          if (!(scp->sc_event.se_events & POLLOUT)) {
1121 1133                  scp->sc_event.se_events |= POLLOUT;
1122 1134                  /*
1123 1135                   * If this becomes frequent, we should instead give up on this
1124 1136                   * set of connections instead of aborting.
1125 1137                   */
1126 1138                  if (svp_event_associate(&scp->sc_event, scp->sc_socket) != 0)
1127 1139                          libvarpd_panic("svp_event_associate failed somehow");
1128 1140          }
1129 1141  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX